<?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.19 (Ruby 3.0.2) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-bryce-cose-merkle-mountain-range-proofs-00" category="exp" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.23.2 -->
  <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-00"/>
    <author fullname="Robin Bryce">
      <organization>DataTrails</organization>
      <address>
        <email>robinbryce@gmail.com</email>
      </address>
    </author>
    <date year="2024" month="October" day="21"/>
    <area>Security</area>
    <workgroup>COSE</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 25?>

<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 31?>

<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="verifiable-data-structure">
      <name>Verifiable Data Structure</name>
      <t>The integer identifier for this Verifiable Data Structure is 2.</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 exceedes 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) => 2
  * 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.
If this process fails, the inclusion proof may have been tampered with.
If this process succeeds, the result is a merkle root, which in the attached as the COSE Sign1 payload.
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) => 2
  * 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="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 619?>

<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>
        <t>The count of nodes above and to the left of <tt>pos</tt></t>
        <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/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. (./test-vectors.md)</t>
          </section>
        </section>
      </section>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
    </section>
  </back>
  <!-- ##markdown-source:
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
6M9YAAA=

-->

</rfc>
