<?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.21 (Ruby 3.0.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-bryce-cose-merkle-mountain-range-proofs-02" category="exp" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.25.0 -->
  <front>
    <title abbrev="MMRIVER">Merkle Mountain Range for Immediately Verifiable and Replicable Commitments</title>
    <seriesInfo name="Internet-Draft" value="draft-bryce-cose-merkle-mountain-range-proofs-02"/>
    <author fullname="Robin Bryce">
      <organization>DataTrails</organization>
      <address>
        <email>robinbryce@gmail.com</email>
      </address>
    </author>
    <date year="2024" month="November" day="26"/>
    <area>Security</area>
    <workgroup>COSE</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 26?>

<t>This specification describes the COSE encoding of proofs for post-order traversal binary Merkle trees, also known as history trees and Merkle mountain ranges.
Proving and verifying are defined in terms of the cryptographic asynchronous accumulator described by <eref target="https://eprint.iacr.org/2015/718.pdf">ReyzinYakoubov</eref>.
The technical advantages of post-order traversal binary Merkle trees are discussed in <eref target="https://static.usenix.org/event/sec09/tech/full_papers/crosby.pdf">CrosbyWallachStorage</eref> and <eref target="https://research.swtch.com/tlog#appendix_a">PostOrderTlog</eref>.</t>
    </abstract>
  </front>
  <middle>
    <?line 32?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>A post ordered binary merkle tree is, logically, the unique series of perfect binary merkle trees required to commit its leaves.</t>
      <t>Example,</t>
      <artwork><![CDATA[
   6
 2   5
0 1 3 4 7
]]></artwork>
      <t>This illustrates <tt>MMR(8)</tt>, which is comprised of two perfect trees rooted at 6 and 7.
7 is the root of a tree comprised of a single element.</t>
      <t>The peaks of the perfect trees form the accumulator.</t>
      <t>The storage of a tree maintained in this way is addressed as a linear array, and additions to the tree are always appends.</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?>

<ul spacing="normal">
        <li>
          <t>A complete MMR(n) defines an mmr with n nodes where no equal height sibling trees exist.</t>
        </li>
        <li>
          <t><tt>i</tt> shall be the index of any node, including leaf nodes, in the MMR</t>
        </li>
        <li>
          <t>g shall be the zero based height of a node in the tree.</t>
        </li>
        <li>
          <t><tt>H(x)</tt> shall be the SHA-256 digest of any value x</t>
        </li>
        <li>
          <t><tt>||</tt> shall mean concatenation of raw byte representations of the referenced values.</t>
        </li>
      </ul>
      <t>In this specification, all numbers are unsigned 64 bit integers.
The maximum height of a single tree is 64 (which will have <tt>g=63</tt> for its peak).</t>
    </section>
    <section anchor="description-of-the-mmriver-verifiable-data-structure">
      <name>Description of the MMRIVER Verifiable Data Structure</name>
      <t>This documents extends the verifiable data structure registry of <xref target="I-D.draft-ietf-cose-merkle-tree-proofs"/> with the following value:</t>
      <table align="left" anchor="verifiable-data-structure-values">
        <name>Verifiable Data Structure Algorithms</name>
        <thead>
          <tr>
            <th align="left">Name</th>
            <th align="left">Value</th>
            <th align="left">Description</th>
            <th align="left">Reference</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td align="left">MMRIVER_SHA256</td>
            <td align="left">TBD_1 (requested assignment 3)</td>
            <td align="left">Linearly addressed, position committing, MMR implementations, such as the MMRIVER ledger</td>
            <td align="left">This document</td>
          </tr>
        </tbody>
      </table>
      <t>This document defines inclusion proofs for Merkle Mountain Range, Immediately Verifiable and Efficiently Replicable (MMRIVER) ledgers.
Verifiers <bcp14>MUST</bcp14> reject all other proof types</t>
    </section>
    <section anchor="inclusion-proof">
      <name>Inclusion Proof</name>
      <t>The CBOR representation of an inclusion proof is</t>
      <sourcecode type="cddl"><![CDATA[
inclusion-proof = bstr .cbor [

  ; zero based index of a tree node
  index: uint

  ; path proving the node's inclusion
  inclusion-path: [ + bstr ]
]
]]></sourcecode>
      <t>Note that the inclusion path for the index leads to a single permanent node in the tree.
This node will initially be a peak in the accumulator, as the tree grows it will eventually be "buried" by a new peak.</t>
      <section anchor="inclusionproofpath">
        <name>inclusion_proof_path</name>
        <t><tt>inclusion_proof_path(i, c)</tt> is used to produce the verification paths for inclusion proofs and consistency proofs.</t>
        <t>Given:</t>
        <ul spacing="normal">
          <li>
            <t><tt>c</tt> the index of the last node in any tree which contains <tt>i</tt>.</t>
          </li>
          <li>
            <t><tt>i</tt> the index of the mmr node whose verification path is required.</t>
          </li>
        </ul>
        <t>And the methods:</t>
        <ul spacing="normal">
          <li>
            <t><xref target="indexheight">index_height</xref> which obtains the zero based height <tt>g</tt> of any node.</t>
          </li>
        </ul>
        <t>And the constraints:</t>
        <ul spacing="normal">
          <li>
            <t><tt>i &lt;= c</tt></t>
          </li>
        </ul>
        <t>We define <tt>inclusion_proof_path</tt> as</t>
        <sourcecode type="python"><![CDATA[
  def inclusion_proof_path(i, c):

    path = []

    g = index_height(i)

    while True:

      # The sibling of i is at i +/- 2^(g+1)
      siblingoffset = (2 << g)

      # If the index after i is higher, it is the left parent,
      # and i is the right sibling
      if index_height(i+1) > g:

        # The witness to the right sibling is offset behind i
        isibling = i - siblingoffset + 1

        # The parent of a right sibling is stored immediately
        # after
        i += 1
      else:

        # The witness to a left sibling is offset ahead of i
        isibling = i + siblingoffset - 1

        # The parent of a left sibling is stored immediately after
        # its right sibling
        i += siblingoffset

      # When the computed sibling exceeds the range of MMR(C+1),
      # we have completed the path
      if isibling > c:
          return path

      path.append(isibling)

      # Set g to the height of the next item in the path.
      g += 1
]]></sourcecode>
      </section>
    </section>
    <section anchor="receipt-of-inclusion">
      <name>Receipt of Inclusion</name>
      <t>The cbor representation of an inclusion proof is:</t>
      <sourcecode type="cddl"><![CDATA[
protected-header-map = {
  &(alg: 1) => int
  &(vds: 395) => 3
  * cose-label => cose-value
}
]]></sourcecode>
      <ul spacing="normal">
        <li>
          <t>alg (label: 1): <bcp14>REQUIRED</bcp14>. Signature algorithm identifier. Value type: int.</t>
        </li>
        <li>
          <t>vds (label: 395): <bcp14>REQUIRED</bcp14>. verifiable data structure algorithm identifier. Value type: int.</t>
        </li>
      </ul>
      <t>The unprotected header for an inclusion proof signature is:</t>
      <sourcecode type="cddl"><![CDATA[
inclusion-proofs = [ + inclusion-proof ]

verifiable-proofs = {
  &(inclusion-proof: -1) => inclusion-proofs
}

unprotected-header-map = {
  &(vdp: 396) => verifiable-proofs
  * cose-label => cose-value
}
]]></sourcecode>
      <t>The payload of an MMRIVER inclusion proof signature is the tree peak committing to the nodes inclusion, or the node itself where the proof path is empty.
The algorithm <xref target="includedroot">included_root</xref> obtains this value.</t>
      <t>The payload <bcp14>MUST</bcp14> be detached.
Detaching the payload forces verifiers to recompute the root from the inclusion proof,
this protects against implementation errors where the signature is verified but the payload merkle root does not match the inclusion proof.</t>
      <section anchor="verifying-the-receipt-of-inclusion">
        <name>Verifying the Receipt of inclusion</name>
        <t>The inclusion proof and signature are verified in order.
First the verifiers applies the inclusion proof to a possible entry (set member) bytes.
The result is the merkle root implied by the inclusion proof path for the candidate value.
The COSE Sign1 payload <bcp14>MUST</bcp14> be set to this value.
Second the verifier checks the signature of the COSE Sign1.
If the resulting signature verifies, the Receipt has proved inclusion of the entry in the verifiable data structure.
If the resulting signature does not verify, the signature may have been tampered with.</t>
        <t>It is recommended that implementations return a single boolean result for Receipt verification operations, to reduce the chance of accepting a valid signature over an invalid inclusion proof.</t>
        <t>As the proof must be processed prior to signature verification the implementation <bcp14>SHOULD</bcp14> check the lengths of the proof paths are appropriate for the provided tree sizes.</t>
      </section>
      <section anchor="includedroot">
        <name>included_root</name>
        <t>The algorithm <tt>included_root</tt> calculates the accumulator peak for the provided proof and node value.</t>
        <t>Given:</t>
        <ul spacing="normal">
          <li>
            <t><tt>i</tt> is the index the <tt>nodeHash</tt> is to be shown at</t>
          </li>
          <li>
            <t><tt>nodehash</tt> the value whose inclusion is to be shown</t>
          </li>
          <li>
            <t><tt>proof</tt> is the path of sibling values committing i.</t>
          </li>
        </ul>
        <t>And the methods:</t>
        <ul spacing="normal">
          <li>
            <t><xref target="indexheight">index_height</xref> which obtains the zero based height <tt>g</tt> of any node.</t>
          </li>
          <li>
            <t><xref target="hashpospair64">hash_pospair64</xref> which applies <tt>H</tt> to the new node position and its children.</t>
          </li>
        </ul>
        <t>We define <tt>included_root</tt> as</t>
        <sourcecode type="python"><![CDATA[
  def included_root(i, nodehash, proof):

    root = nodehash

    g = index_height(i)

    for sibling in proof:

      # If the index after i is higher, it is the left parent,
      # and i is the right sibling

      if index_height(i + 1) > g:

        # The parent of a right sibling is stored immediately after

        i = i + 1

        # Set `root` to `H(i+1 || sibling || root)`
        root = hash_pospair64(i + 1, sibling, root)
      else:

        # The parent of a left sibling is stored immediately after
        # its right sibling.

        i = i + (2 << g)

        # Set `root` to `H(i+1 || root || sibling)`
        root = hash_pospair64(i + 1, root, sibling)

      # Set g to the height of the next item in the path.
      g = g + 1

    # If the path length was zero, the original nodehash is returned
    return root
]]></sourcecode>
      </section>
    </section>
    <section anchor="consistency-proof">
      <name>Consistency Proof</name>
      <t>A consistency proof shows that the accumulator, defined in <eref target="https://eprint.iacr.org/2015/718.pdf">ReyzinYakoubov</eref>,
for tree-size-1 is a prefix of the accumulator for tree-size-2.</t>
      <t>The signature is over the complete accumulator for tree-size-2 obtained using the proof and the, supplied, possibly empty, list of <tt>right-peaks</tt> which complete the accumulator for tree-size-2.</t>
      <t>The receipt of consistency is defined so that a chain of cumulative consistency proofs can be verified together.</t>
      <t>The cbor representation of a consistency proof is:</t>
      <sourcecode type="cddl"><![CDATA[
consistency-path = [ * bstr ]

consistency-proof =  bstr .cbor [

  ; previous tree size
  tree-size-1: uint

  ; latest tree size
  tree-size-2: uint

  ; the inclusion path from each accumulator peak in
  ; tree-size-1 to its new peak in tree-size-2.
  consistency-paths: [ + consistency-path ]

  ; the additional peaks that
  ; complete the accumulator for tree-size-2,
  ; when appended to those produced by the consistency paths
  right-peaks: [ *bstr ]
]
]]></sourcecode>
      <section anchor="consistencyproofpath">
        <name>consistency_proof_path</name>
        <t>Produces the verification paths for inclusion of the peaks of tree-size-1 under the peaks of tree-size-2.</t>
        <t>right-peaks are obtained by invoking <tt>peaks(tree-size-2 - 1)</tt>, and discarding length(proofs) from the left.</t>
        <t>Given:</t>
        <ul spacing="normal">
          <li>
            <t><tt>ifrom</tt> is the last index of tree-size-1</t>
          </li>
          <li>
            <t><tt>ito</tt> is the last index of tree-size-2</t>
          </li>
        </ul>
        <t>And the methods:</t>
        <ul spacing="normal">
          <li>
            <t><xref target="inclusionproofpath">inclusion_proof_path</xref></t>
          </li>
          <li>
            <t><xref target="peaks"/></t>
          </li>
        </ul>
        <t>And the constraints:</t>
        <ul spacing="normal">
          <li>
            <t><tt>ifrom &lt;= ito</tt></t>
          </li>
        </ul>
        <t>We define <tt>consistency_proof_paths</tt> as</t>
        <sourcecode type="python"><![CDATA[
  def consistency_proof_paths(ifrom, ito):

    proof = []

    for i in peaks(ifrom):
      proof.append(inclusion_proof_path(i, ito))

    return proof
]]></sourcecode>
      </section>
    </section>
    <section anchor="receipt-of-consistency">
      <name>Receipt of Consistency</name>
      <t>The cbor representation of an inclusion proof for MMRIVER is:</t>
      <sourcecode type="cddl"><![CDATA[
protected-header-map = {
  &(alg: 1) => int
  &(vds: 395) => 3
  * cose-label => cose-value
}
]]></sourcecode>
      <ul spacing="normal">
        <li>
          <t>alg (label: 1): <bcp14>REQUIRED</bcp14>. Signature algorithm identifier. Value type: int.</t>
        </li>
        <li>
          <t>vds (label: 395): <bcp14>REQUIRED</bcp14>. verifiable data structure algorithm identifier. Value type: int.</t>
        </li>
      </ul>
      <t>The unprotected header for an inclusion proof signature is:</t>
      <sourcecode type="cddl"><![CDATA[
consistency-proofs = [ + consistency-proof ]

verifiable-proofs = {
  &(consistency-proof: -2) => consistency-proof
}

unprotected-header-map = {
  &(vdp: 396) => verifiable-proofs
  * cose-label => cose-value
}
]]></sourcecode>
      <t>The payload <bcp14>MUST</bcp14> be detached.
Detaching the payload forces verifiers to recompute the roots from the consistency proofs.
This protects against implementation errors where the signature is verified but the payload is not genuinely produced by the included proof.</t>
      <section anchor="verifying-the-receipt-of-consistency">
        <name>Verifying the Receipt of consistency</name>
        <t>Verification accommodates verifying the result of a cumulative series of consistency proofs.</t>
        <t>Perform the following for each consistency-proof in the list, verifying the signature with the output of the last.</t>
        <ol spacing="normal" type="1"><li>
            <t>Initialize current proof as the first consistency-proof.</t>
          </li>
          <li>
            <t>Initialize accumulatorfrom to the peaks of tree-size-1 in the current proof.</t>
          </li>
          <li>
            <t>Initialize ifrom to tree-size-1 - 1 from the current proof.</t>
          </li>
          <li>
            <t>Initialize proofs to the consistency-paths from the current proof.</t>
          </li>
          <li>
            <t>Apply the algorithm <xref target="consistentroots">consistent_roots</xref></t>
          </li>
          <li>
            <t>Apply the peaks algorithm to obtain the accumulator for tree-size-2</t>
          </li>
          <li>
            <t>From the peaks for tres-size-2, discard from the left the number of roots returned by consistent_roots.</t>
          </li>
          <li>
            <t>Create the consistent accumulator by appending the remaining peaks to the consistent roots.</t>
          </li>
          <li>
            <t>If there are no remaining proofs, use the consistent accumulator as the detached payload and verify the signature of the COSE Sign1.</t>
          </li>
        </ol>
        <t>It is recommended that implementations return a single boolean result for Receipt verification operations, to reduce the chance of accepting a valid signature over an invalid consistency proof.</t>
        <t>As the proof must be processed prior to signature verification the implementation <bcp14>SHOULD</bcp14> check the lengths of the proof paths are appropriate for the provided tree sizes.</t>
        <section anchor="consistentroots">
          <name>consistent_roots</name>
          <t><tt>consistent_roots</tt> returns the descending height ordered list of elements from the accumulator for the consistent future state.</t>
          <t>Implementations <bcp14>MUST</bcp14> require that the number of peaks returned by <xref target="peaks"/><tt>(ifrom)</tt> equals the number of entries in <tt>accumulatorfrom</tt>.</t>
          <t>Given:</t>
          <ul spacing="normal">
            <li>
              <t><tt>ifrom</tt> the last index in the complete MMR from which consistency was proven.</t>
            </li>
            <li>
              <t><tt>accumulatorfrom</tt> the node values corresponding to the peaks of the accumulator for tree-size-1</t>
            </li>
            <li>
              <t><tt>proofs</tt> the inclusion proofs for each node in <tt>accumulatorfrom</tt> for tree-size-2</t>
            </li>
          </ul>
          <t>And the methods:</t>
          <ul spacing="normal">
            <li>
              <t><xref target="includedroot">included_root</xref></t>
            </li>
            <li>
              <t><xref target="peaks"/></t>
            </li>
          </ul>
          <t>We define <tt>consistent_roots</tt> as</t>
          <sourcecode type="python"><![CDATA[
  def consistent_roots(ifrom, accumulatorfrom, proofs):

    frompeaks = peaks(ifrom)

    # if length(frompeaks) != length(proofs) -> ERROR

    roots = []
    for i in range(len(accumulatorfrom)):
      root = included_root(
          frompeaks[i], accumulatorfrom[i], proofs[i])

      if roots and roots[-1] == root:
          continue
      roots.append(root)

    return roots
]]></sourcecode>
        </section>
      </section>
    </section>
    <section anchor="appending-a-leaf">
      <name>Appending a leaf</name>
      <t>An algorithm for appending to a tree maintained in post order layout is provided.
Implementation defined methods for interacting with storage are specified.</t>
      <section anchor="addleafhash">
        <name>add_leaf_hash</name>
        <t>When a new node is appended, if its height matches the height of its immediate predecessor, then the two equal height siblings <bcp14>MUST</bcp14> be merged.
Merging is defined as the append of a new node which takes the adjacent peaks as its left and right children.
This process <bcp14>MUST</bcp14> proceed until there are no more completable sub trees.</t>
        <t><tt>add_leaf_hash(f)</tt> adds the leaf hash value f to the tree.</t>
        <t>Given:</t>
        <ul spacing="normal">
          <li>
            <t><tt>f</tt> the leaf value resulting from <tt>H(x)</tt> for the caller defined leaf value <tt>x</tt></t>
          </li>
          <li>
            <t><tt>db</tt> an interface supporting the <xref target="append"/> and <xref target="get"/> implementation defined storage methods.</t>
          </li>
        </ul>
        <t>And the methods:</t>
        <ul spacing="normal">
          <li>
            <t><xref target="indexheight">index_height</xref></t>
          </li>
          <li>
            <t><xref target="hashpospair64"/></t>
          </li>
        </ul>
        <t>We define <tt>add_leaf_hash</tt> as</t>
        <sourcecode type="python"><![CDATA[
  def add_leaf_hash(db, f: bytes):

    # Set g to 0, the height of the leaf item f
    g = 0

    # Set i to the result of invoking Append(f)
    i = db.append(f)

    # If index_height(i) is greater than g (#looptarget)
    while index_height(i) > g:

      # Set ileft to the index of the left child of i,
      # which is i - 2^(g+1)

      ileft = i - (2 << g)

      # Set iright to the index of the the right child of i,
      # which is i - 1

      iright = i - 1

      # Set v to H(i + 1 || Get(ileft) || Get(iright))
      # Set i to the result of invoking Append(v)

      i = db.append(
        hash_pospair64(i+1, db.get(ileft), db.get(iright)))

      # Set g to the height of the new i, which is g + 1
      g += 1

    return i
]]></sourcecode>
      </section>
      <section anchor="implementation-defined-storage-methods">
        <name>Implementation defined storage methods</name>
        <t>The following methods are assumed to be available to the implementation.
Very minimal requirements are specified.</t>
        <t>Informally, the storage must be array like and have no gaps.</t>
        <section anchor="get">
          <name>Get</name>
          <t>Reads the value from the tree at the supplied index.</t>
          <t>The read <bcp14>MUST</bcp14> be consistent with any other calls to Append or Get within the same algorithm invocation.</t>
          <t>Get <bcp14>MAY</bcp14> fail for transient reasons.</t>
        </section>
        <section anchor="append">
          <name>Append</name>
          <t>Appends new node to storage and returns the index that will be occupied by the node provided to the next call to append.</t>
          <t>The implementation <bcp14>MUST</bcp14> guarantee that the results of Append are immediately available to Get calls in the same invocation of the algorithm.</t>
          <t>Append <bcp14>MUST</bcp14> return the node <tt>i</tt> identifying the node location which comes next.</t>
          <t>The implementation <bcp14>MAY</bcp14> defer commitment to underlying persistent storage.</t>
          <t>Append <bcp14>MAY</bcp14> fail for transient reasons.</t>
        </section>
      </section>
      <section anchor="node-values">
        <name>Node values</name>
        <t>Interior nodes in the <bcp14>MUST</bcp14> prefix the value provided to <tt>H(x)</tt> with <tt>pos</tt>.</t>
        <t>The value <tt>v</tt> for any interior node <bcp14>MUST</bcp14> be <tt>H(pos || Get(LEFT_CHILD) || Get(RIGHT_CHILD))</tt></t>
        <t>The algorithm for leaf addition is provided the result of <tt>H(x)</tt> directly.</t>
        <section anchor="hashpospair64">
          <name>hash_pospair64</name>
          <t>Returns <tt>H(pos || a || b)</tt>, which is the value for the node identified by index <tt>pos - 1</tt></t>
          <t>Editors note: How this draft accommodates hash alg agility is tbd.</t>
          <t>Given:</t>
          <ul spacing="normal">
            <li>
              <t><tt>pos</tt> the size of the MMR whose last node index is <tt>pos - 1</tt></t>
            </li>
            <li>
              <t><tt>a</tt> the first value to include in the hash after <tt>pos</tt></t>
            </li>
            <li>
              <t><tt>b</tt> the second value to include in the hash after <tt>pos</tt></t>
            </li>
          </ul>
          <t>And the constraints:</t>
          <ul spacing="normal">
            <li>
              <t><tt>pos &lt; 2^64</tt></t>
            </li>
            <li>
              <t><tt>a</tt> and <tt>b</tt> <bcp14>MUST</bcp14> be hashes produced by the appropriate hash alg.</t>
            </li>
          </ul>
          <t>We define <tt>hash_pospair64</tt> as</t>
          <sourcecode type="python"><![CDATA[
  def hash_pospair64(pos, a, b):

    # Note: Hash algorithm agility is tbd, this example uses SHA-256
    h = hashlib.sha256()

    # Take the big endian representation of pos
    h.update(pos.to_bytes(8, byteorder="big", signed=False))
    h.update(a)
    h.update(b)
    return h.digest()
]]></sourcecode>
        </section>
      </section>
    </section>
    <section anchor="essential-supporting-algorithms">
      <name>Essential supporting algorithms</name>
      <section anchor="indexheight">
        <name>index_height</name>
        <t><tt>index_height(i)</tt> returns the zero based height <tt>g</tt> of the node index <tt>i</tt></t>
        <t>Given:</t>
        <ul spacing="normal">
          <li>
            <t><tt>i</tt> the index of any mmr node.</t>
          </li>
        </ul>
        <t>We define <tt>index_height</tt> as</t>
        <sourcecode type="python"><![CDATA[
  def index_height(i) -> int:
    pos = i + 1
    while not all_ones(pos):
      pos = pos - most_sig_bit(pos) + 1

    return bit_length(pos) - 1
]]></sourcecode>
      </section>
      <section anchor="peaks">
        <name>peaks</name>
        <t><tt>peaks(i)</tt> returns the peak indices for <tt>MMR(i+1)</tt>, which is also its accumulator.</t>
        <t>Assumes MMR(i+1) is complete, implementations can check for this condition by
testing the height of i+1</t>
        <t>Given:</t>
        <ul spacing="normal">
          <li>
            <t><tt>i</tt> the index of any mmr node.</t>
          </li>
        </ul>
        <t>We define <tt>peaks</tt></t>
        <sourcecode type="python"><![CDATA[
  def peaks(i):
    peak = 0
    peaks = []
    s = i+1
    while s != 0:
      # find the highest peak size in the current MMR(s)
      highest_size = (1 << log2floor(s+1)) - 1
      peak = peak + highest_size
      peaks.append(peak-1)
      s -= highest_size

    return peaks
]]></sourcecode>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>See the security considerations section of:</t>
      <ul spacing="normal">
        <li>
          <t><xref target="RFC9053"/></t>
        </li>
      </ul>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>Editors note: Hash agility is desired.
We can start with SHA-256.
Two of the referenced implementations use BLAKE2b-256,
We would like to add support for SHA3-256, SHA3-512, and possibly Keccak and Pedersen.</t>
      <section anchor="additions-to-existing-registries">
        <name>Additions to Existing Registries</name>
        <t>Editors note: todo registry requests</t>
      </section>
      <section anchor="new-registries">
        <name>New Registries</name>
      </section>
    </section>
  </middle>
  <back>
    <references anchor="sec-normative-references">
      <name>Normative References</name>
      <reference anchor="RFC9053">
        <front>
          <title>CBOR Object Signing and Encryption (COSE): Initial Algorithms</title>
          <author fullname="J. Schaad" initials="J." surname="Schaad"/>
          <date month="August" year="2022"/>
          <abstract>
            <t>Concise Binary Object Representation (CBOR) is a data format designed for small code size and small message size. There is a need to be able to define basic security services for this data format. This document defines a set of algorithms that can be used with the CBOR Object Signing and Encryption (COSE) protocol (RFC 9052).</t>
            <t>This document, along with RFC 9052, obsoletes RFC 8152.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="9053"/>
        <seriesInfo name="DOI" value="10.17487/RFC9053"/>
      </reference>
      <reference anchor="I-D.draft-ietf-cose-merkle-tree-proofs">
        <front>
          <title>COSE Receipts</title>
          <author fullname="Orie Steele" initials="O." surname="Steele">
            <organization>Transmute</organization>
          </author>
          <author fullname="Henk Birkholz" initials="H." surname="Birkholz">
            <organization>Fraunhofer SIT</organization>
          </author>
          <author fullname="Antoine Delignat-Lavaud" initials="A." surname="Delignat-Lavaud">
            <organization>Microsoft</organization>
          </author>
          <author fullname="Cedric Fournet" initials="C." surname="Fournet">
            <organization>Microsoft</organization>
          </author>
          <date day="17" month="October" year="2024"/>
          <abstract>
            <t>   COSE (CBOR Object Signing and Encryption) Receipts prove properties
   of a verifiable data structure to a verifier.  Verifiable data
   structures and associated proof types enable security properties,
   such as minimal disclosure, transparency and non-equivocation.
   Transparency helps maintain trust over time, and has been applied to
   certificates, end to end encrypted messaging systems, and supply
   chain security.  This specification enables concise transparency
   oriented systems, by building on CBOR (Concise Binary Object
   Representation) and COSE.  The extensibility of the approach is
   demonstrated by providing CBOR encodings for RFC9162.

            </t>
          </abstract>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-ietf-cose-merkle-tree-proofs-07"/>
      </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>
    </references>
    <?line 632?>

<section anchor="references">
      <name>References</name>
      <section anchor="informative-references">
        <name>Informative References</name>
        <ul spacing="normal">
          <li>
            <t><eref target="https://eprint.iacr.org/2015/718.pdf">ReyzinYakoubov</eref></t>
          </li>
          <li>
            <t><eref target="https://static.usenix.org/event/sec09/tech/full_papers/crosby.pdf">CrosbyWallach</eref></t>
          </li>
          <li>
            <t><eref target="https://static.usenix.org/event/sec09/tech/full_papers/crosby.pdf">CrosbyWallachStorage</eref> 3.3 Storing the log on secondary storage</t>
          </li>
          <li>
            <t><eref target="https://research.swtch.com/tlog#appendix_a">PostOrderTlog</eref></t>
          </li>
          <li>
            <t><eref target="https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2016-May/012715.html">PeterTodd</eref></t>
          </li>
          <li>
            <t><eref target="https://www-cs-faculty.stanford.edu/~knuth/taocp.html">KnuthTBT</eref> 2.3.1 Traversing Binary Trees</t>
          </li>
          <li>
            <t><eref target="https://eprint.iacr.org/2021/038.pdf">BNT</eref></t>
          </li>
        </ul>
      </section>
    </section>
    <section anchor="assumed-bit-primitives">
      <name>Assumed bit primitives</name>
      <section anchor="log2floor">
        <name>log2floor</name>
        <t>Returns the floor of log base 2 x</t>
        <sourcecode type="python"><![CDATA[
  def log2floor(x):
    return x.bit_length() - 1
]]></sourcecode>
      </section>
      <section anchor="mostsigbit">
        <name>most_sig_bit</name>
        <t>Returns the mask for the the most significant bit in pos</t>
        <sourcecode type="python"><![CDATA[
  def most_sig_bit(pos) -> int:
    return 1 << (pos.bit_length() - 1)
]]></sourcecode>
        <t>The following primitives are assumed for working with bits as they commonly have library or hardware support.</t>
      </section>
      <section anchor="bitlength">
        <name>bit_length</name>
        <t>The minimum number of bits to represent pos. b011 would be 2, b010 would be 2, and b001 would be 1.</t>
        <sourcecode type="python"><![CDATA[
  def bit_length(pos):
    return pos.bit_length()
]]></sourcecode>
      </section>
      <section anchor="allones">
        <name>all_ones</name>
        <t>Tests if all bits, from the most significant that is set, are 1, b0111 would be true, b0101 would be false.</t>
        <sourcecode type="python"><![CDATA[
  def all_ones(pos) -> bool:
    msb = most_sig_bit(pos)
    mask = (1 << (msb + 1)) - 1
    return pos == mask
]]></sourcecode>
      </section>
      <section anchor="onescount">
        <name>ones_count</name>
        <t>Count of set bits.
For example <tt>ones_count(b101)</tt> is 2</t>
      </section>
      <section anchor="trailingzeros">
        <name>trailing_zeros</name>
        <sourcecode type="python"><![CDATA[
  (v & -v).bit_length() - 1
]]></sourcecode>
      </section>
    </section>
    <section anchor="implementation-status">
      <name>Implementation Status</name>
      <t>Note to RFC Editor: Please remove this section as well as references to BCP205 before AUTH48.</t>
      <t>This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in BCP205.
The description of implementations in this section is intended to assist the IETF in its decision processes in progressing drafts to RFCs.
Please note that the listing of any individual implementation here does not imply endorsement by the IETF.
Furthermore, no effort has been spent to verify the information presented here that was supplied by IETF contributors.
This is not intended as, and must not be construed to be, a catalog of available implementations or their features.
Readers are advised to note that other implementations may exist.</t>
      <t>According to BCP205,
"this will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature.
It is up to the individual working groups to use this information as they see fit".</t>
      <section anchor="implementers">
        <name>Implementers</name>
        <section anchor="datatrails">
          <name>DataTrails</name>
          <t>An open-source implementation was initiated and is maintained by Data Trails Inc. - DataTrails.</t>
          <t>Uses SHA-256 as the hash alg</t>
          <section anchor="implementation-name">
            <name>Implementation Name</name>
            <t>An application demonstrating the concepts is available at <eref target="https://app.datatrails.ai/">https://app.datatrails.ai/</eref>.</t>
          </section>
          <section anchor="implementation-url">
            <name>Implementation URL</name>
            <t>An open-source implementation is available at:</t>
            <ul spacing="normal">
              <li>
                <t>https://github.com/datatrails/go-datatrails-merklelog</t>
              </li>
            </ul>
          </section>
          <section anchor="maturity">
            <name>Maturity</name>
            <t>Used in production.
SEMVER unstable (no backwards compat declared yet)</t>
          </section>
        </section>
        <section anchor="robin-bryce-1">
          <name>Robin Bryce (1)</name>
          <section anchor="implementation-url-1">
            <name>Implementation URL</name>
            <t>A minimal reference implementation of this draft.
Used to generate the test vectors in this draft, is available at:</t>
            <ul spacing="normal">
              <li>
                <t>https://github.com/robinbryce/draft-bryce-cose-merkle-mountain-range-proofs/blob/main/algorithms.py</t>
              </li>
            </ul>
          </section>
          <section anchor="maturity-1">
            <name>Maturity</name>
            <t>Reference only</t>
          </section>
        </section>
        <section anchor="robin-bryce-2">
          <name>Robin Bryce (2)</name>
          <section anchor="implementation-url-2">
            <name>Implementation URL</name>
            <t>A minimal tiled log implementation</t>
            <ul spacing="normal">
              <li>
                <t>https://github.com/robinbryce/mmriver-tiles-ts</t>
              </li>
            </ul>
          </section>
          <section anchor="maturity-2">
            <name>Maturity</name>
            <t>Prototype</t>
          </section>
        </section>
        <section anchor="mimblewimble">
          <name>Mimblewimble</name>
          <t>Is specifically committing to positions as we describe, but is committing zero based indices,
and uses BLAKE2B as the HASH-ALG.
Accounting for those differences, their commitment trees would be compatible with this draft.</t>
          <section anchor="implementation-url-3">
            <name>Implementation URL</name>
            <t>An implementation is available here:</t>
            <ul spacing="normal">
              <li>
                <t>https://github.com/mimblewimble/grin/blob/master/doc/mmr.md (Grin is a rust implementation of the mimblewimble protocol)</t>
              </li>
              <li>
                <t>https://github.com/BeamMW/beam/blob/master/core/merkle.cpp (Beam is a C++ implementation of the mimblewimble protocol)</t>
              </li>
            </ul>
          </section>
        </section>
        <section anchor="herodotus">
          <name> Herodotus</name>
          <section anchor="implementation-url-4">
            <name>Implementation URL</name>
            <t>https://github.com/HerodotusDev/rust-accumulators</t>
            <t>Production, supports keccak, posiedon &amp; pedersen hash algs</t>
            <t>Editors note: test vectors, based on a SHA256 instantiation, are currently provided in a separate document.
These should inlined if the draft is accepted: https://github.com/robinbryce/draft-bryce-cose-merkle-mountain-range-proofs/blob/main/test-vectors.md</t>
          </section>
        </section>
      </section>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
    </section>
  </back>
  <!-- ##markdown-source:
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

-->

</rfc>
