<?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-bryce-cose-receipts-mmr-profile-01" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.31.0 -->
  <front>
    <title abbrev="COSE Receipts for MMRs">COSE Receipts for MMRs</title>
    <seriesInfo name="Internet-Draft" value="draft-bryce-cose-receipts-mmr-profile-01"/>
    <author fullname="Robin Bryce">
      <organization>Datatrails</organization>
      <address>
        <email>robinbryce@gmail.com</email>
      </address>
    </author>
    <date year="2025" month="December" day="15"/>
    <area>Security</area>
    <workgroup>TBD</workgroup>
    <keyword>Internet-Draft</keyword>
    <abstract>
      <?line 33?>

<t>This document defines a new verifiable data structure type for COSE Receipts <xref target="I-D.ietf-cose-merkle-tree-proofs"/> specifically for use with ledgers based on post-order traversal binary Merkle trees and which are designed for high throughput, ease of replication and compatibility with commodity cloud storage.</t>
      <t>Post-order traversal binary Merkle trees, also known as history trees, are more commonly known as Merkle Mountain Ranges.</t>
    </abstract>
  </front>
  <middle>
    <?line 39?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>The COSE Receipts document <xref target="I-D.ietf-cose-merkle-tree-proofs"/> defines a common framework for defining different types of proofs, such as proof of inclusion, about verifiable data structures (VDS). For instance, inclusion proofs guarantee to a verifier that a given serializable element is recorded at a given state of the VDS, while consistency proofs are used to establish that an inclusion proof is still consistent with the new state of the VDS at a later time.</t>
      <t>In this document, we define a new type of VDS: 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>
      <t>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>
    </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-verifiable-data-structure">
      <name>Description of the Verifiable Data Structure</name>
      <t>This documents extends the verifiable data structure registry of <xref target="I-D.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">MMR_SHA256</td>
            <td align="left">TBD_1 (requested assignment 3)</td>
            <td align="left">Linearly addressed, position committing, MMR implementations, such as the MMR ledger</td>
            <td align="left">This document</td>
          </tr>
        </tbody>
      </table>
    </section>
    <section anchor="inclusion-proofs">
      <name>Inclusion Proofs</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="cose-receipt-of-inclusion">
      <name>COSE 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 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="cose-receipt-of-consistency">
      <name>COSE Receipt of Consistency</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[
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.</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 <tt>append(entry) -&gt; index</tt> and <tt>get(index) -&gt; entry</tt> 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="node-values">
        <name>Node values</name>
        <t>Interior nodes in the tree <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 anchor="detection-of-improper-inclusion">
        <name>Detection of improper inclusion</name>
        <t>A receipt of inclusion shows only that the element is included in the ledger.
Defining whether that inclusion was legitimate, or in some way valid,  is out of scope for this document.</t>
      </section>
      <section anchor="misbehaving-ledgers">
        <name>Misbehaving Ledgers</name>
        <t>A ledger can misbehave in several ways. Examples include the following: failing to incorporate a leaf entry in the MMR; presenting different, conflicting views of the MMR at different times and/or to different parties.</t>
        <t>Detection of a failure to include items in the first place is out of scope for
this document.</t>
        <t>Having included an element, ledger implementations using this draft <bcp14>MUST</bcp14> use consistency proofs as the basis for proving entries are not moved, modified or excluded in future states of the MMR.
Similarly, consistency proofs <bcp14>MUST</bcp14> be the basis for proving the unequivocal history of additions.</t>
      </section>
    </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.ietf-cose-merkle-tree-proofs">
        <front>
          <title>COSE (CBOR Object Signing and Encryption) Receipts</title>
          <author fullname="Orie Steele" initials="O." surname="Steele">
            <organization>Tradeverifyd</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="2" month="December" year="2025"/>
          <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 Merkle inclusion and
   consistency proofs.

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

<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="acknowledgments">
      <name>Acknowledgments</name>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+1c63LbRpb+j6fokatmyZikRPmWcK3MyJYcq+LbSkpSKZdX
BIEm2SsQYNAAKcb2PMs+yz7ZnkvfAFKyd2pmdqdqXZWIAPpy+ly/c7qBfr8f
VarK5EjsPX97cSrOZSLVstJiWpTi9etzvRfFk0kpV3c0SOJKzopyMxK6SqMo
LZI8XsCIaRlPq/6k3CSynxRa9kvTt79YlP1lWUxVJvsHw0jXk4XSWhV5tVlC
x7PTyxdRXi8mshxFKYw+ipIi1zLXtR6JqqxlBPQ8iOJSxkDXhUzqUlWbvWhd
lNezsqiXI3H57CS6lhu4k46iqC/O8kqWuaz6J0hVFMV1NS9geNGPIgH/pnWW
MdnnxUTl4hmSTU+Kchbn6ve4AvpG4iSu4qqMVabpoVzAz5EosQ+t9M8zvDNI
ikUU5UW5gG4roF+I8xfPvzt49GAkkI1wfdY/GShZTZk1C1leAzOqUkrkTDGF
hTZ4FkUqn/rxosFgAMvq90U80UBPAku6nCstgPv1QuaVSOVU5VKLWORyLVay
VFMVTzIpgKExSKqsk6oupUCWkzCb4v34sSmzz5+FXsoEBkniLNtQj1pLsVbV
XGQynclSi0msZSqKXCwLXfWB9bIEccUwuY4zASyKy414TUsVuFSgLk/Feq6S
uQBhAs1azXIYAkefq9lcVHMQ52y+rKuekDC6KKailMsMqEB5UH/g9RKuJioD
JWCC4NaiSPEyyYo6heUWZTyTwLJ3X0lZT8SZLsR1XqxhFg3U4Bgb9xCoXRTw
P5opB4a4lmaU10WdVzFo0nmcz6Q20lqoNM1kFN1DhSyLFIQAy0DZyZYAnCB3
SMLLlqcX0xJUF7WfOEePVT4TqZpOZYmDoJQ1Mo+Vqyd0jTzXfI0PVJ5kNdog
LG5S1NXtKqNF5+eTi+5AvIC5VK6rOE9kzw9g5hCzOi5jMDvgaAGk8njI93lc
wfUMFDkXGu7GGZgXziMzSUsGPYbVopRSEbYF0yMNqIBbQEIPVSdDGeQaxCPz
ZGPnRvnUqIwwtYR+k0zpuZk5b5OK8+lKZZkfqWI9wonQfNozM1UZ3ITlqAUq
1lkODwMDBOKkEZSxQbI0GAP6j+AW2oggTQQyjQYuvAYCUT2RFTO2tx7NXOfq
t1oSz4w0ZTmVSbWjO3Lwt1qVzAJUEwV8Bb3KJGg9quPpTbxYZrLH/g/+PeYf
h/DfI/p5IIbigXgonhjfAhyq0dlUMPoYfH/n2+64Z8wXHqMdloo8ADBqXTjq
DD1FUbE8H5PZPhlET7AbLgyfYa+Yl94YCTQPdNlrx4CtZSnja21F0pwJ/STd
jhOQRQ1iKkrTyziCYC5w12SnMJkyIlzHGyQsTlNQdqQiRlPLoE1cgmaVMYgD
VwANFJqvRhbjfDQgql6cwRjQabmUeYrMflcWK7RI7EaGsKGr0qoITy7LhVtS
Um6WVTEr4yXwFyjY5An4wryodbgsdJlJqSaoQhvx/lxuflf5r/F1UU+K1YcB
rbmSyTxHNQKCV2CQsH5Wnq920kim0klNzABC3z8vCz3Z/AKaGSfzC+bpB1rc
e3Swb3HQS1BeoABc3fMiB/NlTmGbE/JPdM1SgUAtMFJrsff6p4vLvR7/FW/e
0u/z03/76ez89AR/X7w8fvXK/YhMi4uXb396deJ/+Z7P375+ffrmhDvDXdG4
Fe29Pv51j6W59/bd5dnbN8ev9pwiOB+MHAAZT8AqEUcsS0mqrCPPfsQMz9/9
138OH4LH/gNE+8Ph8Dvw1Xzx7fDJQ7hYz2XOs1HM4EuQ9iZCVYnRnYLugB+K
l6qCANRD1dNzjCxz8BPAzW/eI2c+jMTTSbIcPvze3MAFN25anjVuEs+272x1
ZibuuLVjGsfNxv0Wp5v0Hv/auLZ8D24+/RNam+gPv/3T9xHCt2PyCRmwHUFn
J+/6GJgLgJPsrnORFyAR5CsILAfX/1sNOj2XACUqcCMQBcDqWKnlDTj6AQw9
VmNgMXIdxIuWp/JU3pCHyDc0oIltKXYG9znlWXqsJkQQDDNrDvK7LAuDh8z0
5HKwp+2HdBABLzs33RYNIJf+4aPHYHZgrJUlZhVn4P5vsM+nT7bHQgILIHAh
DM8ZFSFIitfgEYBdgJbAi4ESx2yAxr2UkpBBAvTRqDoIYQ7oVQwHYBJG4yau
5galPX4I7qIik0D4x95mEd+oRb1orNo4cBPWsF+Ho8Yag+4cfI8Yz44ePxgT
fMEohd69S87jhCxsaddFAdgjE4Tj4sIikxYGRiFX6ICp1+0QuJQz0AXwejD+
DrTlkMC0yLJijVpALAMU/km8AeAlPomfSTKfGtR+AjBnmBx9AvAXfQJNuQLJ
omA/YYZyNRQdDNMgYnInyFfyNw+60OAVBRxwEy4Q9dBnk+M0Eb0CYnqogEKh
dSycmD3AMxpqMDrOG7Io+jgS9zxn+siZvuNMn1UDNAAIO9rL5LTaE5QvHu3d
KgRxnEE2CDxb6L3PjHQt2npH4Myg3Wdvz1vKyWq+A51F0V/gn0gAO0fuKedJ
4khgAiQGyQRU5z2CmX8Njc8bM6sfGiC0odsjUYPuchfIIOY4H0Vpgn3Q8F+0
J4Y6uamh9Ui8F/d58g/RB6Iwit4AxmGYyZ7ErQSHR+X2DgY8SaoZGhv7ABSz
iHOU/7abIKnRbbIZip+UiE0QXqK52PYBOuhZBaClQ2a8hgVVPILEkFzbIfYm
kELLdA9RBKNVHBIN8J5fxRVx/ArXEkXjXbc7qicS8GVAq0XfS8pyZGCCJnXD
9lxG2MocOKtrg3qg5gfMAyifHyfjprPGiyzWnnfoMGnd7GpgPIR5Gv29dftb
A2AkYSbPwQls08uZCeNqIOcY6KRuspoXqSbC3tOAV+z+PnTu0SVfdQ0pxYQp
2R0nxrNxGHyCaZAlWHsAz8Y8UOLpkUjGUfSLSzV2imWMUIVtaLkBUlGZof1O
ybIIR5wV0JqPxPsPfDmD3+HyOqrLDzgPuyzJKXI2cU8Q3jYxF82YMDWEC3F/
vy8O/70zuz/smsamWTGdalnBJJ1D8fSpmHX9YGfTQFrxFBMvGhCrBBIUXVU2
l0AvBYRj2ttz3VGjlMs2Qjhgmqhpa2VAnPhezNx67IogGgDscJC/MRZOYNYw
kXOFc7reyrYBFop+a8X3xbA9D6+APdfWJJjGoHNbLGSqIO5nm6A3ccfPK+4f
weh8ITMt71pRzNzbXk48B29FUty9oPutBfXvXlB7lu31tFZxj1DBLsGZFTam
92rzCyBsYzuLZY1R1s4qbxIpDTQosUSDlCG2fA6S94oDSTzhEws/2RLJBXrF
sWN+L5KRI0uAp4B4yI7DUoS/B5wWdmy3QMsvgHUzq1oeQXEZ4gYTeLmwfp6G
Mj1nLGSOQfcalSTs7yIwh14KlV8Zekdh7IWbkEwCE/qoDrLsL+IliP8jUPHH
TpzNRgKM5uh7RIR0awU+UTz47hHdfAC3vuGiZhZPZIb36IpARvTZUN8HtDET
HWqC442ETWUG4gJgSEwYI7YYQ6gUU0ssLA0MCuMissoJ3QMJbjCkJBzudkT4
lcMTN+vcsUUwWyio7eCmduS3+NoGNRp9LthUG+uAGw6wmmvK/G81HkH2ZITR
HBs4HQU07xLlKl0itx5T/60Zv06ObPKbrGC/8QV2eJRCUMajW2sMnNgFRUqD
pTjaV1pmU5P2kW3QBDZiy8Wy2nB24gX7nnM6mV5h8YkCNV/jZTeI0TAArWzQ
XBNl3ROMu1WczBEOnNAvix9tO9CFBCi31U9ys1jcJHfki1/Tsli0MSMuohcR
BUZcEEBnSFbVwvtClmVR6oADDeaayVMxqasGcaZgSBSkhUSEWUEGVyXzXbQw
HPzZla+wSeBlVNPLtMWNIdhThYmkIws8GtWhBtELVeoqwIqUcy6XGdY7d1DE
MQuSInSlUgA7IIvrYABaSExYu5QDm8wU3F2dOZgQLh2ZqbiEtmuSBnhPYB0K
N6WsVrjSPXqn4ZZ+IDGkw16PLkD8BtK5ojioUHKtW6Izrt+PPojObPqOa0Eh
+NZmLN1rCGbORf4VsdmuywzM/DLx5FZveOekTmu4qtlrrWARbzh+TiQG4nix
pHI3ptRYcHClfgj8eUrBNW7rtrZx1OVJk6LIsOhhBIqSsattIPYCJrPpMFmd
S0SSOe5ZkF9KErmkNcUoHhXqKDDN+HF+sm0OxzpwN4taI+7Dq4TrxstSodYU
W0IyBJKyNQ3Z1NlIHQyczWeYKNlKt9NILsaAcZQFzIMKaVWU0ljiJjpUrX6n
6o7N5KzLi1oOcdx4OgZFzxJMI43lhUVn8tFbs3kzJ6dsnWaQs6mxtT7G8fhr
jI1fxnrOz6jIyhXPuMI++HhOj0lJKQRzdubF0eyIvYgWNxsZMEUcxmmmrBFE
GfUPy+ZgTFzOFTitZazKxw9hVLzhru241u2NX45dEIS8nHjrykCU10BYgLiT
pYCvB9u5oJfoHUmgbYTZn+V4jyVqc0HylEfu6RcyQtQOB/CNwYz+Eencbfkc
5li7M7r/YaZlMpMg/eAEqJHwIJAfM9dBduOXmE+KT5/cyPCTcMbY9THsbeoG
k92z3Xrc6a5k7m+dZQ22F9pOzu9aL63Kr/tr14sP3ar/JvnREeZIVkZO/8gx
sIcVawiUaL8cwsApzlQeZ07fOVJhIJJpFGR35Epd4hUUrajYCV5lu5JFbkr7
MmGjYhfsB7a383oR+Vw8I4JOvT+kigqMCV1cCSv0083mh3YPNISGFONsgkz7
K3cMYHwdUFdrh3Od14crLDuT2+JSNQpww/C7JzLFGxlj0q8+7d+OXXHOTP51
Kyg96AyZi3Vtwz1d2GMGEOoVAR4zqFrtPDAAsA4DiIOkVTGDMCDtvvFtKfMO
4bZzu6BF39bTIIEyhePmY1PR3lHShplXCjd/XUyH24EqhLVsCtrVLS0Pw5a7
itSYiMgYA1A74qucOwUKCKaILsMWjMn2QnEJ0V6+5rr5Flc+eIrsvjpYH+/y
oyjp6dfqSY9a4/aq2YPnWnRFuMFUpB3cb4gQKYTOgY4ivd+0yvyApYJejbr4
Ox493HO6o+Dtzi/YwwwBb+s8Nba54zGaQkAkYUFnnRME9aviGm10TM87oRX3
IRKOeRsat/Xj0uxsohvssD10fUKKUaQF4/CZA1dUdPdVdL8AaloVX2x4eCv0
2q5O2zwdb9NdvNnF1rRMeEx/u3cVzWllTyGWAW0NuLRbpPo24HRL8w5NgBCm
cGV0Y9e2jk46QLCIZEMdurZyyLmFrRHeUqHHwU1ctFVGCje3VQCDwPT/NcD/
kzXArThgi4DbAeLOMuBW85HoH3aZ0a0n/wuVwL9t1Ux7L7Vru/Dy71g5U1z1
mMkcoiki6XZUsWnVV5XOktA8fw6DBgQ5OstKefiq0d+UPxiGeHDjTwfu3EJ9
J0t3Ps4faEBtpaC/rW0GTiN867Uo8KxyZySKugIRhRuyMOdwIM54wxr8PdBa
Uo5ikCMHhykV/rZmH7T6BjGfRV/cHj8N4Y3p2uMpN0rQEeJjoFh3dTe2Z6jY
gjp3jXIMOJk1JahJ+/OnlI1jPPO36E632dcEfzcCUMIo4EsICYd5YanjUUwL
bTGUBQdNKMDJFh0HonNGZIY2MULlb6+BVvu8lLEx3OCMbUgfHjygmOfVG49m
4pUBgUW7ux+e0zlTVs6LsK8574xn1e+Y3WihdUvOzP15zS+XZv/Zyplb7uGf
rqB5b0vZomjcvjU2DLcS1olRMls/MEewbX5qjhkHxrtlRk09mtbECDojjlrQ
EjeFPHNoxOf83oJYu0MLamHZsQGIYz7OqFv90TMo2hsT45Z7HO/E7S0srvwG
uT1fyUt352aclqztXkJOJ2jas/kNOVdgBa+nl4Ux6ravvtNDDV0ZV9uDOq1T
Qi5m2RM/2wS1nd4dicZtO4G7cotdOYPTti8kC6adzRJaJJuaq7aZA95jhh01
kgVbx1JTm7e5ll3xh6N2Mtf/Xpyen78995VczelIIxuhYxAd6NppUdV1yYmp
2jVrxsGRB0fFe/Vha3F0j0mCn92gVMsUobOlX+/7ww/i6IguwgMVeIZL5bUM
iNE2U2JhtStz2mVExy64xHSIF3UhCJwE1338KXa/HuDf2QAL2uBbMowwyTsx
xovT9ArHv+IiOR1AiX3lXmlXkehRkRrWbRwR7buawoGvbWIDV7HFMlAq0Rlj
qbCyh1vwZYtdR521w9sLWc6Qwtfw11SDbanMhD6mypxSttSyC6jia7sJlP5H
nBCOYdyhzSsl04qFR5P7vQgLwJFgJoUusH4IgsyaMdu+ToVeiPIxXU/4rDYw
dtxga2cKzhDu2B2CeEp1ZLM7NA1fx2h6wOnY9+DGfk+TfJ45i+03e7NMlo5V
Qb/xzRgHTCdjDqkVwGpgDdU/i5IGHBvNpF1WskFyuGNi1Xgmqw5d0xNqM7Zu
6a/YjLL7SrdvKzXcVoOdt/msJs/TSU9AMkkb6tY9BRX5g96OojwxjIryU7dd
dBB2Ve4cnUtmXOWKLRZkHdndh3RirX3aDSr5rQ0oVO4Z4U161yyHWTv3sqJY
VjEYgdk+4ROL7Z7h9pAhkDFvEWxXubVNja4T1cGRMftCFJ7zs+ccra+jXnwE
cPuQI03IRrRrRr/Z9cVp3WaUGe6oeZenWuEsL3nPBTdpfkCVRAK77op6d7tN
Cr8ss5VfcENszpe3t33uD3vYbOYo8JeGhK/dBVoDTzwveNPHbgLRIbkwRChf
z33jcQu+CQHKg1DXHjty/sS6Mdpy8TvSHqEW1odQSjyGNY5Nkcg4jtXY1IY2
7DbsNM5XQ3/oZUXw6vTF5dXzl2evTpxUzs9+eGnvdcftfXwcnOzOltHDGNWS
myE1BWiaVNnGgOqmcKLo3OBnT1iM/5s03v7zvLDOk+OdrZ2ZqjSqMzIFtRFI
PwUSsfySF5UciZfFWvCLV/iSdrP2QQ4ey4LxjF/0xTknadO/I7dNova7y9EQ
0PKJgfB8OEFfHdCCgHYc1CJ4MbjBwWDHagETQlvWNB92nJhZ+WDPV/e8vUiN
VD0F5/H4oSWMggbMY7UEB5N6q+wUpk+WZc1DAU3p3ub7WwYKvwDO9UDmzvO/
YZGZOYzyNYXTY2lKftMUc3Bt32yiQeZmAzhTk4Gex3C74/z6JYAOWtFEzQTC
MsqQ2/VqoItHGtRL1BMkdFAVVxSlOt/2KFwRYDvag4H2eoLfXTp6AYmUNI7N
dY5b15Nu6CzmA34bC2i0oPJUIzUKgFcQ9x03tDl042MMvTbRCDnN7PTW8yPe
ntiC1Lh9sKYRLdC52HcZ2kdC/PS3nwhpRkVCLgaIo2La8w4+jmIpFKDSVZED
16GJ38yg5mxjCwDPV8D+q4mqqJHfkDcchgdXNnPB531/pvkeQ05goEmDWpwz
u4+pSvgFYH5BGU/xh06K3ulHyNp8M/hY63oB/WwX+zYz5sO9rfoNbhVzOYM9
HTXOja+dbCLcfLVFrADH3x/+lSLjnfJdgrKsMKJBFiC+shdBjkdCux+KTGOa
eDByQXWqjC+iIziaIT770VYhFbmkLSQwra+o4ZHoDBHTZMXscAqIq+xo4CbL
0egD00h/7jc6Bw1cTocXff+SiOgfNbs09r9IPaxh2m+C8MZXagtnUXQhpXXV
3CBpNMD7xreQmD5+7GOJ7/NnUsETWbnHqBYlluTCc6/H4dEEX7Dg8x70yq8r
AAXfOnBbBbbUTq/q4daI+Y7Dek5nEUw50Q2L5ZhMzkDxIHWUdCQaRtDFQtIr
7FTl6wk65cEleZ0US+m11r4EyInra6Unch7TC3Cv+IMeuCDz3iAq/cK0II3Q
cgVMy3AmPRDmYwJuLc3thZGYxioziTW0KErwlRihOBVvnkMF9aLjDuRZw49Y
9FBW00wldHul5FqHIR5YE3zvQi346yL7XK/0T5YxeGnKKRvSjInEumzGbchc
HPpjVLDMMMvbwdKozdKXzEonXGCgkXnPMrXtWeypGoeAKNhj6XrXJy7Y8UG0
UOzx7NuLtiDIeXUFfneFxQb8IArhMCyb3XiNC8uXIUMH0YVaqAzfQO3tmt8C
kd1EVLQrilXPVYGfHrDfTyk8LqUarjg7fnO8ZaUtWEgYwyML/EwMvYD3Cx3H
RtJL88EOgy4G0eW62PGq8zbDpXj26vjH08MJduvhiOuizrAafM3fLUlTG9tp
fTDBA2rKvx4ND/kghTvt9KNMEnBueO+dhCVpOpQJ9nUcfi3iFN8+Rz6d87vH
Sm6tuirSwr+abF4TZkjxBrKcsCN+WWYSJ9fIT/fOMTc9818Najzqb50uG4l5
VS31aH8fUBZubas4KQdFOds/PBg+2n8y/HawTDGNb3fEsRofhAiGQq1SyQD4
nKsbGozeO90HN3vw3T5+mWIfv7x0tYzBk+r9hIax8zQH3ZrGfnfi7zGb+6bF
g8EDgRdWpyG04QeOGOnjlzLMF0WQuuanLzxZ6MviMpkP9LqC/wOy2K+gxT1T
b7y5inH+Zm8aDxxUeVmkaTAW7lLoAfjS+mZa1EACqhQtdano/WGV7QOMSgqV
91O5Qtk97r+ON/sHw8Mnw0eDebXIaDY3Ns70Y15X88tnl8FE6/W6n+j+NE4g
V9wM8Cs/oEnpQKb1/l+usf1+FRfJ0o3oxhCHgweDobjkb4og457xR0UusZiH
0z17c3mnuh0O9w8eOHXD1lTBJZSW0jcHoMtCoVKzljvA4ZNVctl4C90ASg1h
tTgUN7uAlAcsNwZMGVRxMwgwaQuQhni2Oe8i1v58PN3AujFmHrRVllfmuwmU
vuwgZxsphxDckEZIi/KdNond4OCF3+L3LON9NsNNJBO/HEU4A13ohPAxLWTj
P29FYR/ytBIFiV/nist0jeMY58g+zlPCsy8Av+DHIPxuFY1Ou5cmxCMPBmJy
MBwazwshBXwq3Dho3ECHOjk4CFrhlus271o5RINlbWZ5WdrkBchGL4uVefoa
B1Db8xuBW2JkQIaoseJvgg2J8nAt+Lk6Xk5wc4rZ507yG1kUih13h3kRCz0B
6LylG/wMNc7C7w62xOPuHnl7BuC+Crb2a8fprhL8XFkUPcc/hGskKSnE6BeE
FziDH/u2nQmsiF/1P6Rh6Kt4oEVXmMRuqXVnJf4o+qvurfYkjhP8hBoiI9p+
jaKPI1YbyNb3iGF7n6P/BpBeZ5WxUAAA

-->

</rfc>
