{
  "address": "0xC16B94F118DD7181655bbb34e555Db82514A6E38",
  "abi": [
    {
      "inputs": [
        {
          "internalType": "bytes",
          "name": "_anchors",
          "type": "bytes"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "constructor"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "addr",
          "type": "address"
        }
      ],
      "name": "AlgorithmUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "addr",
          "type": "address"
        }
      ],
      "name": "DigestUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [],
      "name": "Marker",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "indexed": false,
          "internalType": "address",
          "name": "addr",
          "type": "address"
        }
      ],
      "name": "NSEC3DigestUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "bytes",
          "name": "name",
          "type": "bytes"
        },
        {
          "indexed": false,
          "internalType": "bytes",
          "name": "rrset",
          "type": "bytes"
        }
      ],
      "name": "RRSetUpdated",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": false,
          "internalType": "uint256",
          "name": "t",
          "type": "uint256"
        }
      ],
      "name": "Test",
      "type": "event"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "name": "algorithms",
      "outputs": [
        {
          "internalType": "contract Algorithm",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "anchors",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint16",
          "name": "deleteType",
          "type": "uint16"
        },
        {
          "internalType": "bytes",
          "name": "deleteName",
          "type": "bytes"
        },
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature",
          "name": "nsec",
          "type": "tuple"
        },
        {
          "internalType": "bytes",
          "name": "proof",
          "type": "bytes"
        }
      ],
      "name": "deleteRRSet",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint16",
          "name": "deleteType",
          "type": "uint16"
        },
        {
          "internalType": "bytes",
          "name": "deleteName",
          "type": "bytes"
        },
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature",
          "name": "closestEncloser",
          "type": "tuple"
        },
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature",
          "name": "nextClosest",
          "type": "tuple"
        },
        {
          "internalType": "bytes",
          "name": "dnskey",
          "type": "bytes"
        }
      ],
      "name": "deleteRRSetNSEC3",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "name": "digests",
      "outputs": [
        {
          "internalType": "contract Digest",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "",
          "type": "uint8"
        }
      ],
      "name": "nsec3Digests",
      "outputs": [
        {
          "internalType": "contract NSEC3Digest",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [],
      "name": "owner",
      "outputs": [
        {
          "internalType": "address",
          "name": "",
          "type": "address"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint16",
          "name": "dnstype",
          "type": "uint16"
        },
        {
          "internalType": "bytes",
          "name": "name",
          "type": "bytes"
        }
      ],
      "name": "rrdata",
      "outputs": [
        {
          "internalType": "uint32",
          "name": "",
          "type": "uint32"
        },
        {
          "internalType": "uint32",
          "name": "",
          "type": "uint32"
        },
        {
          "internalType": "bytes20",
          "name": "",
          "type": "bytes20"
        }
      ],
      "stateMutability": "view",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "internalType": "contract Algorithm",
          "name": "algo",
          "type": "address"
        }
      ],
      "name": "setAlgorithm",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "internalType": "contract Digest",
          "name": "digest",
          "type": "address"
        }
      ],
      "name": "setDigest",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "uint8",
          "name": "id",
          "type": "uint8"
        },
        {
          "internalType": "contract NSEC3Digest",
          "name": "digest",
          "type": "address"
        }
      ],
      "name": "setNSEC3Digest",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "internalType": "address",
          "name": "newOwner",
          "type": "address"
        }
      ],
      "name": "setOwner",
      "outputs": [],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature",
          "name": "input",
          "type": "tuple"
        },
        {
          "internalType": "bytes",
          "name": "proof",
          "type": "bytes"
        }
      ],
      "name": "submitRRSet",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "inputs": [
        {
          "components": [
            {
              "internalType": "bytes",
              "name": "rrset",
              "type": "bytes"
            },
            {
              "internalType": "bytes",
              "name": "sig",
              "type": "bytes"
            }
          ],
          "internalType": "struct DNSSEC.RRSetWithSignature[]",
          "name": "input",
          "type": "tuple[]"
        },
        {
          "internalType": "bytes",
          "name": "_proof",
          "type": "bytes"
        }
      ],
      "name": "submitRRSets",
      "outputs": [
        {
          "internalType": "bytes",
          "name": "",
          "type": "bytes"
        }
      ],
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ],
  "transactionHash": "0x6bf46695f16f724493d4103824f8b51b03bf9dcc759c185399cf908d1c96efe3",
  "receipt": {
    "to": null,
    "from": "0xa303ddC620aa7d1390BACcc8A495508B183fab59",
    "contractAddress": "0xC16B94F118DD7181655bbb34e555Db82514A6E38",
    "transactionIndex": 0,
    "gasUsed": "4221613",
    "logsBloom": "0x00000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000",
    "blockHash": "0x785b16051b9ebddd6dfb6319d716cf21b5aef4b720c64276ac599243070e846f",
    "transactionHash": "0x6bf46695f16f724493d4103824f8b51b03bf9dcc759c185399cf908d1c96efe3",
    "logs": [
      {
        "transactionIndex": 0,
        "blockNumber": 10909322,
        "transactionHash": "0x6bf46695f16f724493d4103824f8b51b03bf9dcc759c185399cf908d1c96efe3",
        "address": "0xC16B94F118DD7181655bbb34e555Db82514A6E38",
        "topics": [
          "0x55ced933cdd5a34dd03eb5d4bef19ec6ebb251dcd7a988eee0c1b9a13baaa88b"
        ],
        "data": "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d00002b000100000e1000244a5c080249aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb500002b000100000e1000244f660802e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d00002b000100000e10000404fefdfd00000000000000000000000000000000000000",
        "logIndex": 0,
        "blockHash": "0x785b16051b9ebddd6dfb6319d716cf21b5aef4b720c64276ac599243070e846f"
      }
    ],
    "blockNumber": 10909322,
    "cumulativeGasUsed": "4221613",
    "status": 1,
    "byzantium": true
  },
  "args": [
    "0x00002b000100000e1000244a5c080249aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb500002b000100000e1000244f660802e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d00002b000100000e10000404fefdfd"
  ],
  "solcInputHash": "08371ea78d6ca0259dbc9b2f768cf73e",
  "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_anchors\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"AlgorithmUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"DigestUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Marker\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"NSEC3DigestUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"}],\"name\":\"RRSetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"}],\"name\":\"Test\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"algorithms\",\"outputs\":[{\"internalType\":\"contract Algorithm\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"anchors\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"deleteType\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"deleteName\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature\",\"name\":\"nsec\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"deleteRRSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"deleteType\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"deleteName\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature\",\"name\":\"closestEncloser\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature\",\"name\":\"nextClosest\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"dnskey\",\"type\":\"bytes\"}],\"name\":\"deleteRRSetNSEC3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"digests\",\"outputs\":[{\"internalType\":\"contract Digest\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"name\":\"nsec3Digests\",\"outputs\":[{\"internalType\":\"contract NSEC3Digest\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"dnstype\",\"type\":\"uint16\"},{\"internalType\":\"bytes\",\"name\":\"name\",\"type\":\"bytes\"}],\"name\":\"rrdata\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"bytes20\",\"name\":\"\",\"type\":\"bytes20\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"internalType\":\"contract Algorithm\",\"name\":\"algo\",\"type\":\"address\"}],\"name\":\"setAlgorithm\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"internalType\":\"contract Digest\",\"name\":\"digest\",\"type\":\"address\"}],\"name\":\"setDigest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"id\",\"type\":\"uint8\"},{\"internalType\":\"contract NSEC3Digest\",\"name\":\"digest\",\"type\":\"address\"}],\"name\":\"setNSEC3Digest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature\",\"name\":\"input\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"}],\"name\":\"submitRRSet\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"rrset\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sig\",\"type\":\"bytes\"}],\"internalType\":\"struct DNSSEC.RRSetWithSignature[]\",\"name\":\"input\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"_proof\",\"type\":\"bytes\"}],\"name\":\"submitRRSets\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Constructor.\",\"params\":{\"_anchors\":\"The binary format RR entries for the root DS records.\"}},\"deleteRRSet(uint16,bytes,(bytes,bytes),bytes)\":{\"details\":\"Deletes an RR from the oracle.\",\"params\":{\"deleteName\":\"which you want to delete\",\"deleteType\":\"The DNS record type to delete.\",\"nsec\":\"The signed NSEC RRset. This is in the format described in section        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature        data, followed by a series of canonicalised RR records that the signature        applies to.\"}},\"deleteRRSetNSEC3(uint16,bytes,(bytes,bytes),(bytes,bytes),bytes)\":{\"details\":\"Deletes an RR from the oracle using an NSEC3 proof.      Deleting a record using NSEC3 requires using up to two NSEC3 records. There are two cases:       1. The name exists, but the record type doesn't. Eg, example.com has A records but no TXT records.       2. The name does not exist, but a parent name does.      In the first case, we submit one NSEC3 proof in `closestEncloser` that matches the target name      but does not have the bit for `deleteType` set in its type bitmap. In the second case, we submit      two proofs: closestEncloser and nextClosest, that together prove that the name does not exist.      NSEC3 records are in the format described in section 5.3.2 of RFC4035: The RRDATA section      from the RRSIG without the signature data, followed by a series of canonicalised RR records      that the signature applies to.\",\"params\":{\"closestEncloser\":\"An NSEC3 proof matching the closest enclosing name - that is,        the nearest ancestor of the target name that *does* exist.\",\"deleteName\":\"The name to delete.\",\"deleteType\":\"The DNS record type to delete.\",\"dnskey\":\"An encoded DNSKEY record that has already been submitted to the oracle and can be used        to verify the signatures closestEncloserSig and nextClosestSig\",\"nextClosest\":\"An NSEC3 proof covering the next closest name. This proves that the immediate        subdomain of the closestEncloser does not exist.\"}},\"rrdata(uint16,bytes)\":{\"details\":\"Returns data about the RRs (if any) known to this oracle with the provided type and name.\",\"params\":{\"dnstype\":\"The DNS record type to query.\",\"name\":\"The name to query, in DNS label-sequence format.\"},\"returns\":{\"_0\":\"inception The unix timestamp (wrapped) at which the signature for this RRSET was created.\",\"_1\":\"expiration The unix timestamp (wrapped) at which the signature for this RRSET expires.\",\"_2\":\"hash The hash of the RRset.\"}},\"setAlgorithm(uint8,address)\":{\"details\":\"Sets the contract address for a signature verification algorithm.      Callable only by the owner.\",\"params\":{\"algo\":\"The address of the algorithm contract.\",\"id\":\"The algorithm ID\"}},\"setDigest(uint8,address)\":{\"details\":\"Sets the contract address for a digest verification algorithm.      Callable only by the owner.\",\"params\":{\"digest\":\"The address of the digest contract.\",\"id\":\"The digest ID\"}},\"setNSEC3Digest(uint8,address)\":{\"details\":\"Sets the contract address for an NSEC3 digest algorithm.      Callable only by the owner.\",\"params\":{\"digest\":\"The address of the digest contract.\",\"id\":\"The digest ID\"}},\"submitRRSet((bytes,bytes),bytes)\":{\"details\":\"Submits a signed set of RRs to the oracle. RRSETs are only accepted if they are signed with a key that is already trusted, or if they are self-signed, and the signing key is identified by a DS record that is already trusted.\",\"params\":{\"input\":\"The signed RR set. This is in the format described in section        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature        data, followed by a series of canonicalised RR records that the signature        applies to.\",\"proof\":\"The DNSKEY or DS to validate the signature against. Must Already        have been submitted and proved previously.\"}},\"submitRRSets((bytes,bytes)[],bytes)\":{\"details\":\"Submits multiple RRSets\",\"params\":{\"_proof\":\"The DNSKEY or DS to validate the first signature against.\",\"input\":\"A list of RRSets and signatures forming a chain of trust from an existing known-good record.\"},\"returns\":{\"_0\":\"The last RRSET submitted.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/dnssec-oracle/DNSSECImpl.sol\":\"DNSSECImpl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@ensdomains/buffer/contracts/Buffer.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n* @dev A library for working with mutable byte buffers in Solidity.\\n*\\n* Byte buffers are mutable and expandable, and provide a variety of primitives\\n* for writing to them. At any time you can fetch a bytes object containing the\\n* current contents of the buffer. The bytes object should not be stored between\\n* operations, as it may change due to resizing of the buffer.\\n*/\\nlibrary Buffer {\\n    /**\\n    * @dev Represents a mutable buffer. Buffers have a current value (buf) and\\n    *      a capacity. The capacity may be longer than the current value, in\\n    *      which case it can be extended without the need to allocate more memory.\\n    */\\n    struct buffer {\\n        bytes buf;\\n        uint capacity;\\n    }\\n\\n    /**\\n    * @dev Initializes a buffer with an initial capacity.\\n    * @param buf The buffer to initialize.\\n    * @param capacity The number of bytes of space to allocate the buffer.\\n    * @return The buffer, for chaining.\\n    */\\n    function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {\\n        if (capacity % 32 != 0) {\\n            capacity += 32 - (capacity % 32);\\n        }\\n        // Allocate space for the buffer data\\n        buf.capacity = capacity;\\n        assembly {\\n            let ptr := mload(0x40)\\n            mstore(buf, ptr)\\n            mstore(ptr, 0)\\n            mstore(0x40, add(32, add(ptr, capacity)))\\n        }\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Initializes a new buffer from an existing bytes object.\\n    *      Changes to the buffer may mutate the original value.\\n    * @param b The bytes object to initialize the buffer with.\\n    * @return A new buffer.\\n    */\\n    function fromBytes(bytes memory b) internal pure returns(buffer memory) {\\n        buffer memory buf;\\n        buf.buf = b;\\n        buf.capacity = b.length;\\n        return buf;\\n    }\\n\\n    function resize(buffer memory buf, uint capacity) private pure {\\n        bytes memory oldbuf = buf.buf;\\n        init(buf, capacity);\\n        append(buf, oldbuf);\\n    }\\n\\n    function max(uint a, uint b) private pure returns(uint) {\\n        if (a > b) {\\n            return a;\\n        }\\n        return b;\\n    }\\n\\n    /**\\n    * @dev Sets buffer length to 0.\\n    * @param buf The buffer to truncate.\\n    * @return The original buffer, for chaining..\\n    */\\n    function truncate(buffer memory buf) internal pure returns (buffer memory) {\\n        assembly {\\n            let bufptr := mload(buf)\\n            mstore(bufptr, 0)\\n        }\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Writes a byte string to a buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param off The start offset to write to.\\n    * @param data The data to append.\\n    * @param len The number of bytes to copy.\\n    * @return The original buffer, for chaining.\\n    */\\n    function write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns(buffer memory) {\\n        require(len <= data.length);\\n\\n        if (off + len > buf.capacity) {\\n            resize(buf, max(buf.capacity, len + off) * 2);\\n        }\\n\\n        uint dest;\\n        uint src;\\n        assembly {\\n            // Memory address of the buffer data\\n            let bufptr := mload(buf)\\n            // Length of existing buffer data\\n            let buflen := mload(bufptr)\\n            // Start address = buffer address + offset + sizeof(buffer length)\\n            dest := add(add(bufptr, 32), off)\\n            // Update buffer length if we're extending it\\n            if gt(add(len, off), buflen) {\\n                mstore(bufptr, add(len, off))\\n            }\\n            src := add(data, 32)\\n        }\\n\\n        // Copy word-length chunks while possible\\n        for (; len >= 32; len -= 32) {\\n            assembly {\\n                mstore(dest, mload(src))\\n            }\\n            dest += 32;\\n            src += 32;\\n        }\\n\\n        // Copy remaining bytes\\n        unchecked {\\n            uint mask = (256 ** (32 - len)) - 1;\\n            assembly {\\n                let srcpart := and(mload(src), not(mask))\\n                let destpart := and(mload(dest), mask)\\n                mstore(dest, or(destpart, srcpart))\\n            }\\n        }\\n\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @param len The number of bytes to copy.\\n    * @return The original buffer, for chaining.\\n    */\\n    function append(buffer memory buf, bytes memory data, uint len) internal pure returns (buffer memory) {\\n        return write(buf, buf.buf.length, data, len);\\n    }\\n\\n    /**\\n    * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @return The original buffer, for chaining.\\n    */\\n    function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\\n        return write(buf, buf.buf.length, data, data.length);\\n    }\\n\\n    /**\\n    * @dev Writes a byte to the buffer. Resizes if doing so would exceed the\\n    *      capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param off The offset to write the byte at.\\n    * @param data The data to append.\\n    * @return The original buffer, for chaining.\\n    */\\n    function writeUint8(buffer memory buf, uint off, uint8 data) internal pure returns(buffer memory) {\\n        if (off >= buf.capacity) {\\n            resize(buf, buf.capacity * 2);\\n        }\\n\\n        assembly {\\n            // Memory address of the buffer data\\n            let bufptr := mload(buf)\\n            // Length of existing buffer data\\n            let buflen := mload(bufptr)\\n            // Address = buffer address + sizeof(buffer length) + off\\n            let dest := add(add(bufptr, off), 32)\\n            mstore8(dest, data)\\n            // Update buffer length if we extended it\\n            if eq(off, buflen) {\\n                mstore(bufptr, add(buflen, 1))\\n            }\\n        }\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\\n    *      capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @return The original buffer, for chaining.\\n    */\\n    function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {\\n        return writeUint8(buf, buf.buf.length, data);\\n    }\\n\\n    /**\\n    * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would\\n    *      exceed the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param off The offset to write at.\\n    * @param data The data to append.\\n    * @param len The number of bytes to write (left-aligned).\\n    * @return The original buffer, for chaining.\\n    */\\n    function write(buffer memory buf, uint off, bytes32 data, uint len) private pure returns(buffer memory) {\\n        if (len + off > buf.capacity) {\\n            resize(buf, (len + off) * 2);\\n        }\\n\\n        unchecked {\\n            uint mask = (256 ** len) - 1;\\n            // Right-align data\\n            data = data >> (8 * (32 - len));\\n            assembly {\\n                // Memory address of the buffer data\\n                let bufptr := mload(buf)\\n                // Address = buffer address + sizeof(buffer length) + off + len\\n                let dest := add(add(bufptr, off), len)\\n                mstore(dest, or(and(mload(dest), not(mask)), data))\\n                // Update buffer length if we extended it\\n                if gt(add(off, len), mload(bufptr)) {\\n                    mstore(bufptr, add(off, len))\\n                }\\n            }\\n        }\\n        return buf;\\n    }\\n\\n    /**\\n    * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the\\n    *      capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param off The offset to write at.\\n    * @param data The data to append.\\n    * @return The original buffer, for chaining.\\n    */\\n    function writeBytes20(buffer memory buf, uint off, bytes20 data) internal pure returns (buffer memory) {\\n        return write(buf, off, bytes32(data), 20);\\n    }\\n\\n    /**\\n    * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @return The original buffer, for chhaining.\\n    */\\n    function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\\n        return write(buf, buf.buf.length, bytes32(data), 20);\\n    }\\n\\n    /**\\n    * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param data The data to append.\\n    * @return The original buffer, for chaining.\\n    */\\n    function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\\n        return write(buf, buf.buf.length, data, 32);\\n    }\\n\\n    /**\\n    * @dev Writes an integer to the buffer. Resizes if doing so would exceed\\n    *      the capacity of the buffer.\\n    * @param buf The buffer to append to.\\n    * @param off The offset to write at.\\n    * @param data The data to append.\\n    * @param len The number of bytes to write (right-aligned).\\n    * @return The original buffer, for chaining.\\n    */\\n    function writeInt(buffer memory buf, uint off, uint data, uint len) private pure returns(buffer memory) {\\n        if (len + off > buf.capacity) {\\n            resize(buf, (len + off) * 2);\\n        }\\n\\n        uint mask = (256 ** len) - 1;\\n        assembly {\\n            // Memory address of the buffer data\\n            let bufptr := mload(buf)\\n            // Address = buffer address + off + sizeof(buffer length) + len\\n            let dest := add(add(bufptr, off), len)\\n            mstore(dest, or(and(mload(dest), not(mask)), data))\\n            // Update buffer length if we extended it\\n            if gt(add(off, len), mload(bufptr)) {\\n                mstore(bufptr, add(off, len))\\n            }\\n        }\\n        return buf;\\n    }\\n\\n    /**\\n     * @dev Appends a byte to the end of the buffer. Resizes if doing so would\\n     * exceed the capacity of the buffer.\\n     * @param buf The buffer to append to.\\n     * @param data The data to append.\\n     * @return The original buffer.\\n     */\\n    function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {\\n        return writeInt(buf, buf.buf.length, data, len);\\n    }\\n}\\n\",\"keccak256\":\"0x18e42be1a3e4f7b4442d7ab0b524af5e09163503439954faf0ab3792cce91caa\"},\"contracts/dnssec-oracle/BytesUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nlibrary BytesUtils {\\n    /*\\n    * @dev Returns the keccak-256 hash of a byte range.\\n    * @param self The byte string to hash.\\n    * @param offset The position to start hashing at.\\n    * @param len The number of bytes to hash.\\n    * @return The hash of the byte range.\\n    */\\n    function keccak(bytes memory self, uint offset, uint len) internal pure returns (bytes32 ret) {\\n        require(offset + len <= self.length);\\n        assembly {\\n            ret := keccak256(add(add(self, 32), offset), len)\\n        }\\n    }\\n\\n\\n    /*\\n    * @dev Returns a positive number if `other` comes lexicographically after\\n    *      `self`, a negative number if it comes before, or zero if the\\n    *      contents of the two bytes are equal.\\n    * @param self The first bytes to compare.\\n    * @param other The second bytes to compare.\\n    * @return The result of the comparison.\\n    */\\n    function compare(bytes memory self, bytes memory other) internal pure returns (int) {\\n        return compare(self, 0, self.length, other, 0, other.length);\\n    }\\n\\n    /*\\n    * @dev Returns a positive number if `other` comes lexicographically after\\n    *      `self`, a negative number if it comes before, or zero if the\\n    *      contents of the two bytes are equal. Comparison is done per-rune,\\n    *      on unicode codepoints.\\n    * @param self The first bytes to compare.\\n    * @param offset The offset of self.\\n    * @param len    The length of self.\\n    * @param other The second bytes to compare.\\n    * @param otheroffset The offset of the other string.\\n    * @param otherlen    The length of the other string.\\n    * @return The result of the comparison.\\n    */\\n    function compare(bytes memory self, uint offset, uint len, bytes memory other, uint otheroffset, uint otherlen) internal pure returns (int) {\\n        uint shortest = len;\\n        if (otherlen < len)\\n        shortest = otherlen;\\n\\n        uint selfptr;\\n        uint otherptr;\\n\\n        assembly {\\n            selfptr := add(self, add(offset, 32))\\n            otherptr := add(other, add(otheroffset, 32))\\n        }\\n        for (uint idx = 0; idx < shortest; idx += 32) {\\n            uint a;\\n            uint b;\\n            assembly {\\n                a := mload(selfptr)\\n                b := mload(otherptr)\\n            }\\n            if (a != b) {\\n                // Mask out irrelevant bytes and check again\\n                uint mask;\\n                if (shortest > 32) {\\n                    mask = type(uint256).max;\\n                } else {\\n                    mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);\\n                }\\n                int diff = int(a & mask) - int(b & mask);\\n                if (diff != 0)\\n                return diff;\\n            }\\n            selfptr += 32;\\n            otherptr += 32;\\n        }\\n\\n        return int(len) - int(otherlen);\\n    }\\n\\n    /*\\n    * @dev Returns true if the two byte ranges are equal.\\n    * @param self The first byte range to compare.\\n    * @param offset The offset into the first byte range.\\n    * @param other The second byte range to compare.\\n    * @param otherOffset The offset into the second byte range.\\n    * @param len The number of bytes to compare\\n    * @return True if the byte ranges are equal, false otherwise.\\n    */\\n    function equals(bytes memory self, uint offset, bytes memory other, uint otherOffset, uint len) internal pure returns (bool) {\\n        return keccak(self, offset, len) == keccak(other, otherOffset, len);\\n    }\\n\\n    /*\\n    * @dev Returns true if the two byte ranges are equal with offsets.\\n    * @param self The first byte range to compare.\\n    * @param offset The offset into the first byte range.\\n    * @param other The second byte range to compare.\\n    * @param otherOffset The offset into the second byte range.\\n    * @return True if the byte ranges are equal, false otherwise.\\n    */\\n    function equals(bytes memory self, uint offset, bytes memory other, uint otherOffset) internal pure returns (bool) {\\n        return keccak(self, offset, self.length - offset) == keccak(other, otherOffset, other.length - otherOffset);\\n    }\\n\\n    /*\\n    * @dev Compares a range of 'self' to all of 'other' and returns True iff\\n    *      they are equal.\\n    * @param self The first byte range to compare.\\n    * @param offset The offset into the first byte range.\\n    * @param other The second byte range to compare.\\n    * @return True if the byte ranges are equal, false otherwise.\\n    */\\n    function equals(bytes memory self, uint offset, bytes memory other) internal pure returns (bool) {\\n        return self.length >= offset + other.length && equals(self, offset, other, 0, other.length);\\n    }\\n\\n    /*\\n    * @dev Returns true if the two byte ranges are equal.\\n    * @param self The first byte range to compare.\\n    * @param other The second byte range to compare.\\n    * @return True if the byte ranges are equal, false otherwise.\\n    */\\n    function equals(bytes memory self, bytes memory other) internal pure returns(bool) {\\n        return self.length == other.length && equals(self, 0, other, 0, self.length);\\n    }\\n\\n    /*\\n    * @dev Returns the 8-bit number at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 8 bits of the string, interpreted as an integer.\\n    */\\n    function readUint8(bytes memory self, uint idx) internal pure returns (uint8 ret) {\\n        return uint8(self[idx]);\\n    }\\n\\n    /*\\n    * @dev Returns the 16-bit number at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 16 bits of the string, interpreted as an integer.\\n    */\\n    function readUint16(bytes memory self, uint idx) internal pure returns (uint16 ret) {\\n        require(idx + 2 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 2), idx)), 0xFFFF)\\n        }\\n    }\\n\\n    /*\\n    * @dev Returns the 32-bit number at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 32 bits of the string, interpreted as an integer.\\n    */\\n    function readUint32(bytes memory self, uint idx) internal pure returns (uint32 ret) {\\n        require(idx + 4 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)\\n        }\\n    }\\n\\n    /*\\n    * @dev Returns the 32 byte value at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 32 bytes of the string.\\n    */\\n    function readBytes32(bytes memory self, uint idx) internal pure returns (bytes32 ret) {\\n        require(idx + 32 <= self.length);\\n        assembly {\\n            ret := mload(add(add(self, 32), idx))\\n        }\\n    }\\n\\n    /*\\n    * @dev Returns the 32 byte value at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes\\n    * @return The specified 32 bytes of the string.\\n    */\\n    function readBytes20(bytes memory self, uint idx) internal pure returns (bytes20 ret) {\\n        require(idx + 20 <= self.length);\\n        assembly {\\n            ret := and(mload(add(add(self, 32), idx)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000)\\n        }\\n    }\\n\\n    /*\\n    * @dev Returns the n byte value at the specified index of self.\\n    * @param self The byte string.\\n    * @param idx The index into the bytes.\\n    * @param len The number of bytes.\\n    * @return The specified 32 bytes of the string.\\n    */\\n    function readBytesN(bytes memory self, uint idx, uint len) internal pure returns (bytes32 ret) {\\n        require(len <= 32);\\n        require(idx + len <= self.length);\\n        assembly {\\n            let mask := not(sub(exp(256, sub(32, len)), 1))\\n            ret := and(mload(add(add(self, 32), idx)),  mask)\\n        }\\n    }\\n\\n    function memcpy(uint dest, uint src, uint len) private pure {\\n        // Copy word-length chunks while possible\\n        for (; len >= 32; len -= 32) {\\n            assembly {\\n                mstore(dest, mload(src))\\n            }\\n            dest += 32;\\n            src += 32;\\n        }\\n\\n        // Copy remaining bytes\\n        unchecked {\\n            uint mask = (256 ** (32 - len)) - 1;\\n            assembly {\\n                let srcpart := and(mload(src), not(mask))\\n                let destpart := and(mload(dest), mask)\\n                mstore(dest, or(destpart, srcpart))\\n            }\\n        }\\n    }\\n\\n    /*\\n    * @dev Copies a substring into a new byte string.\\n    * @param self The byte string to copy from.\\n    * @param offset The offset to start copying at.\\n    * @param len The number of bytes to copy.\\n    */\\n    function substring(bytes memory self, uint offset, uint len) internal pure returns(bytes memory) {\\n        require(offset + len <= self.length);\\n\\n        bytes memory ret = new bytes(len);\\n        uint dest;\\n        uint src;\\n\\n        assembly {\\n            dest := add(ret, 32)\\n            src := add(add(self, 32), offset)\\n        }\\n        memcpy(dest, src, len);\\n\\n        return ret;\\n    }\\n\\n    // Maps characters from 0x30 to 0x7A to their base32 values.\\n    // 0xFF represents invalid characters in that range.\\n    bytes constant base32HexTable = hex'00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F';\\n\\n    /**\\n     * @dev Decodes unpadded base32 data of up to one word in length.\\n     * @param self The data to decode.\\n     * @param off Offset into the string to start at.\\n     * @param len Number of characters to decode.\\n     * @return The decoded data, left aligned.\\n     */\\n    function base32HexDecodeWord(bytes memory self, uint off, uint len) internal pure returns(bytes32) {\\n        require(len <= 52);\\n\\n        uint ret = 0;\\n        uint8 decoded;\\n        for(uint i = 0; i < len; i++) {\\n            bytes1 char = self[off + i];\\n            require(char >= 0x30 && char <= 0x7A);\\n            decoded = uint8(base32HexTable[uint(uint8(char)) - 0x30]);\\n            require(decoded <= 0x20);\\n            if(i == len - 1) {\\n                break;\\n            }\\n            ret = (ret << 5) | decoded;\\n        }\\n\\n        uint bitlen = len * 5;\\n        if(len % 8 == 0) {\\n            // Multiple of 8 characters, no padding\\n            ret = (ret << 5) | decoded;\\n        } else if(len % 8 == 2) {\\n            // Two extra characters - 1 byte\\n            ret = (ret << 3) | (decoded >> 2);\\n            bitlen -= 2;\\n        } else if(len % 8 == 4) {\\n            // Four extra characters - 2 bytes\\n            ret = (ret << 1) | (decoded >> 4);\\n            bitlen -= 4;\\n        } else if(len % 8 == 5) {\\n            // Five extra characters - 3 bytes\\n            ret = (ret << 4) | (decoded >> 1);\\n            bitlen -= 1;\\n        } else if(len % 8 == 7) {\\n            // Seven extra characters - 4 bytes\\n            ret = (ret << 2) | (decoded >> 3);\\n            bitlen -= 3;\\n        } else {\\n            revert();\\n        }\\n\\n        return bytes32(ret << (256 - bitlen));\\n    }\\n}\",\"keccak256\":\"0x83315df2e54c74451577c70da2c267c3459802b08b9aeec6516302eee70f796e\"},\"contracts/dnssec-oracle/DNSSEC.sol\":{\"content\":\"pragma solidity ^0.8.4;\\npragma experimental ABIEncoderV2;\\n\\nabstract contract DNSSEC {\\n\\n    bytes public anchors;\\n\\n    struct RRSetWithSignature {\\n        bytes rrset;\\n        bytes sig;\\n    }\\n\\n    event AlgorithmUpdated(uint8 id, address addr);\\n    event DigestUpdated(uint8 id, address addr);\\n    event NSEC3DigestUpdated(uint8 id, address addr);\\n    event RRSetUpdated(bytes name, bytes rrset);\\n\\n    function submitRRSets(RRSetWithSignature[] memory input, bytes calldata proof) public virtual returns (bytes memory);\\n    function submitRRSet(RRSetWithSignature calldata input, bytes calldata proof) public virtual returns (bytes memory);\\n    function deleteRRSet(uint16 deleteType, bytes calldata deleteName, RRSetWithSignature calldata nsec, bytes calldata proof) public virtual;\\n    function deleteRRSetNSEC3(uint16 deleteType, bytes memory deleteName, RRSetWithSignature memory closestEncloser, RRSetWithSignature memory nextClosest, bytes memory dnskey) public virtual;\\n    function rrdata(uint16 dnstype, bytes calldata name) external virtual view returns (uint32, uint32, bytes20);\\n}\\n\",\"keccak256\":\"0x5b8d2391f66e878e09aa88a97fe8ea5b26604a0c0ad9247feb6124db9817f6c1\"},\"contracts/dnssec-oracle/DNSSECImpl.sol\":{\"content\":\"pragma solidity ^0.8.4;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"./Owned.sol\\\";\\nimport \\\"./BytesUtils.sol\\\";\\nimport \\\"./RRUtils.sol\\\";\\nimport \\\"./DNSSEC.sol\\\";\\nimport \\\"./algorithms/Algorithm.sol\\\";\\nimport \\\"./digests/Digest.sol\\\";\\nimport \\\"./nsec3digests/NSEC3Digest.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/*\\n * @dev An oracle contract that verifies and stores DNSSEC-validated DNS records.\\n *\\n * TODO: Support for NSEC3 records\\n */\\ncontract DNSSECImpl is DNSSEC, Owned {\\n    using Buffer for Buffer.buffer;\\n    using BytesUtils for bytes;\\n    using RRUtils for *;\\n\\n    uint16 constant DNSCLASS_IN = 1;\\n\\n    uint16 constant DNSTYPE_NS = 2;\\n    uint16 constant DNSTYPE_SOA = 6;\\n    uint16 constant DNSTYPE_DNAME = 39;\\n    uint16 constant DNSTYPE_DS = 43;\\n    uint16 constant DNSTYPE_RRSIG = 46;\\n    uint16 constant DNSTYPE_NSEC = 47;\\n    uint16 constant DNSTYPE_DNSKEY = 48;\\n    uint16 constant DNSTYPE_NSEC3 = 50;\\n\\n    uint constant DNSKEY_FLAG_ZONEKEY = 0x100;\\n\\n    uint8 constant ALGORITHM_RSASHA256 = 8;\\n\\n    uint8 constant DIGEST_ALGORITHM_SHA256 = 2;\\n\\n    struct RRSet {\\n        uint32 inception;\\n        uint32 expiration;\\n        bytes20 hash;\\n    }\\n\\n    // (name, type) => RRSet\\n    mapping (bytes32 => mapping(uint16 => RRSet)) rrsets;\\n\\n    mapping (uint8 => Algorithm) public algorithms;\\n    mapping (uint8 => Digest) public digests;\\n    mapping (uint8 => NSEC3Digest) public nsec3Digests;\\n\\n    event Test(uint t);\\n    event Marker();\\n\\n    /**\\n     * @dev Constructor.\\n     * @param _anchors The binary format RR entries for the root DS records.\\n     */\\n    constructor(bytes memory _anchors) {\\n        // Insert the 'trust anchors' - the key hashes that start the chain\\n        // of trust for all other records.\\n        anchors = _anchors;\\n        rrsets[keccak256(hex\\\"00\\\")][DNSTYPE_DS] = RRSet({\\n            inception: uint32(0),\\n            expiration: uint32(3767581600), // May 22 2089 - the latest date we can encode as of writing this\\n            hash: bytes20(keccak256(anchors))\\n        });\\n        emit RRSetUpdated(hex\\\"00\\\", anchors);\\n    }\\n\\n    /**\\n     * @dev Sets the contract address for a signature verification algorithm.\\n     *      Callable only by the owner.\\n     * @param id The algorithm ID\\n     * @param algo The address of the algorithm contract.\\n     */\\n    function setAlgorithm(uint8 id, Algorithm algo) public owner_only {\\n        algorithms[id] = algo;\\n        emit AlgorithmUpdated(id, address(algo));\\n    }\\n\\n    /**\\n     * @dev Sets the contract address for a digest verification algorithm.\\n     *      Callable only by the owner.\\n     * @param id The digest ID\\n     * @param digest The address of the digest contract.\\n     */\\n    function setDigest(uint8 id, Digest digest) public owner_only {\\n        digests[id] = digest;\\n        emit DigestUpdated(id, address(digest));\\n    }\\n\\n    /**\\n     * @dev Sets the contract address for an NSEC3 digest algorithm.\\n     *      Callable only by the owner.\\n     * @param id The digest ID\\n     * @param digest The address of the digest contract.\\n     */\\n    function setNSEC3Digest(uint8 id, NSEC3Digest digest) public owner_only {\\n        nsec3Digests[id] = digest;\\n        emit NSEC3DigestUpdated(id, address(digest));\\n    }\\n\\n    /**\\n     * @dev Submits multiple RRSets\\n     * @param input A list of RRSets and signatures forming a chain of trust from an existing known-good record.\\n     * @param _proof The DNSKEY or DS to validate the first signature against.\\n     * @return The last RRSET submitted.\\n     */\\n    function submitRRSets(RRSetWithSignature[] memory input, bytes calldata _proof) public override returns (bytes memory) {\\n        bytes memory proof = _proof;\\n        for(uint i = 0; i < input.length; i++) {\\n            proof = _submitRRSet(input[i], proof);\\n        }\\n        return proof;\\n    }\\n\\n    /**\\n     * @dev Submits a signed set of RRs to the oracle.\\n     *\\n     * RRSETs are only accepted if they are signed with a key that is already\\n     * trusted, or if they are self-signed, and the signing key is identified by\\n     * a DS record that is already trusted.\\n     *\\n     * @param input The signed RR set. This is in the format described in section\\n     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature\\n     *        data, followed by a series of canonicalised RR records that the signature\\n     *        applies to.\\n     * @param proof The DNSKEY or DS to validate the signature against. Must Already\\n     *        have been submitted and proved previously.\\n     */\\n    function submitRRSet(RRSetWithSignature memory input, bytes memory proof)\\n        public override\\n        returns (bytes memory)\\n    {\\n        return _submitRRSet(input, proof);\\n    }\\n\\n    /**\\n     * @dev Deletes an RR from the oracle.\\n     *\\n     * @param deleteType The DNS record type to delete.\\n     * @param deleteName which you want to delete\\n     * @param nsec The signed NSEC RRset. This is in the format described in section\\n     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature\\n     *        data, followed by a series of canonicalised RR records that the signature\\n     *        applies to.\\n     */\\n    function deleteRRSet(uint16 deleteType, bytes memory deleteName, RRSetWithSignature memory nsec, bytes memory proof)\\n        public override\\n    {\\n        RRUtils.SignedSet memory rrset;\\n        rrset = validateSignedSet(nsec, proof);\\n        require(rrset.typeCovered == DNSTYPE_NSEC);\\n\\n        // Don't let someone use an old proof to delete a new name\\n        require(RRUtils.serialNumberGte(rrset.inception, rrsets[keccak256(deleteName)][deleteType].inception));\\n\\n        for (RRUtils.RRIterator memory iter = rrset.rrs(); !iter.done(); iter.next()) {\\n            // We're dealing with three names here:\\n            //   - deleteName is the name the user wants us to delete\\n            //   - nsecName is the owner name of the NSEC record\\n            //   - nextName is the next name specified in the NSEC record\\n            //\\n            // And three cases:\\n            //   - deleteName equals nsecName, in which case we can delete the\\n            //     record if it's not in the type bitmap.\\n            //   - nextName comes after nsecName, in which case we can delete\\n            //     the record if deleteName comes between nextName and nsecName.\\n            //   - nextName comes before nsecName, in which case nextName is the\\n            //     zone apex, and deleteName must come after nsecName.\\n            checkNsecName(iter, rrset.name, deleteName, deleteType);\\n            delete rrsets[keccak256(deleteName)][deleteType];\\n            return;\\n        }\\n        // We should never reach this point\\n        revert();\\n    }\\n\\n    function checkNsecName(RRUtils.RRIterator memory iter, bytes memory nsecName, bytes memory deleteName, uint16 deleteType) private pure {\\n        uint rdataOffset = iter.rdataOffset;\\n        uint nextNameLength = iter.data.nameLength(rdataOffset);\\n        uint rDataLength = iter.nextOffset - iter.rdataOffset;\\n\\n        // We assume that there is always typed bitmap after the next domain name\\n        require(rDataLength > nextNameLength);\\n\\n        int compareResult = deleteName.compareNames(nsecName);\\n        if(compareResult == 0) {\\n            // Name to delete is on the same label as the NSEC record\\n            require(!iter.data.checkTypeBitmap(rdataOffset + nextNameLength, deleteType));\\n        } else {\\n            // First check if the NSEC next name comes after the NSEC name.\\n            bytes memory nextName = iter.data.substring(rdataOffset,nextNameLength);\\n            // deleteName must come after nsecName\\n            require(compareResult > 0);\\n            if(nsecName.compareNames(nextName) < 0) {\\n                // deleteName must also come before nextName\\n                require(deleteName.compareNames(nextName) < 0);\\n            }\\n        }\\n    }\\n\\n    /**\\n     * @dev Deletes an RR from the oracle using an NSEC3 proof.\\n     *      Deleting a record using NSEC3 requires using up to two NSEC3 records. There are two cases:\\n     *       1. The name exists, but the record type doesn't. Eg, example.com has A records but no TXT records.\\n     *       2. The name does not exist, but a parent name does.\\n     *      In the first case, we submit one NSEC3 proof in `closestEncloser` that matches the target name\\n     *      but does not have the bit for `deleteType` set in its type bitmap. In the second case, we submit\\n     *      two proofs: closestEncloser and nextClosest, that together prove that the name does not exist.\\n     *      NSEC3 records are in the format described in section 5.3.2 of RFC4035: The RRDATA section\\n     *      from the RRSIG without the signature data, followed by a series of canonicalised RR records\\n     *      that the signature applies to.\\n     *\\n     * @param deleteType The DNS record type to delete.\\n     * @param deleteName The name to delete.\\n     * @param closestEncloser An NSEC3 proof matching the closest enclosing name - that is,\\n     *        the nearest ancestor of the target name that *does* exist.\\n     * @param nextClosest An NSEC3 proof covering the next closest name. This proves that the immediate\\n     *        subdomain of the closestEncloser does not exist.\\n     * @param dnskey An encoded DNSKEY record that has already been submitted to the oracle and can be used\\n     *        to verify the signatures closestEncloserSig and nextClosestSig\\n     */\\n    function deleteRRSetNSEC3(uint16 deleteType, bytes memory deleteName, RRSetWithSignature memory closestEncloser, RRSetWithSignature memory nextClosest, bytes memory dnskey)\\n        public override\\n    {\\n        uint32 originalInception = rrsets[keccak256(deleteName)][deleteType].inception;\\n\\n        RRUtils.SignedSet memory ce = validateSignedSet(closestEncloser, dnskey);\\n        checkNSEC3Validity(ce, deleteName, originalInception);\\n\\n        RRUtils.SignedSet memory nc;\\n        if(nextClosest.rrset.length > 0) {\\n            nc = validateSignedSet(nextClosest, dnskey);\\n            checkNSEC3Validity(nc, deleteName, originalInception);\\n        }\\n\\n        RRUtils.NSEC3 memory ceNSEC3 = readNSEC3(ce);\\n        // The flags field must be 0 or 1 (RFC5155 section 8.2).\\n        require(ceNSEC3.flags & 0xfe == 0);\\n        // Check that the closest encloser is from the correct zone (RFC5155 section 8.3)\\n        // \\\"The DNAME type bit must not be set and the NS type bit may only be set if the SOA type bit is set.\\\"\\n        require(!ceNSEC3.checkTypeBitmap(DNSTYPE_DNAME) && (!ceNSEC3.checkTypeBitmap(DNSTYPE_NS) || ceNSEC3.checkTypeBitmap(DNSTYPE_SOA)));\\n\\n        // Case 1: deleteName does exist, but no records of RRTYPE deleteType do.\\n        if(isMatchingNSEC3Record(deleteType, deleteName, ce.name, ceNSEC3)) {\\n            delete rrsets[keccak256(deleteName)][deleteType];\\n        // Case 2: deleteName does not exist.\\n        } else if(isCoveringNSEC3Record(deleteName, ce.name, ceNSEC3, nc.name, readNSEC3(nc))) {\\n            delete rrsets[keccak256(deleteName)][deleteType];\\n        } else {\\n            revert();\\n        }\\n    }\\n\\n    function checkNSEC3Validity(RRUtils.SignedSet memory nsec, bytes memory deleteName, uint32 originalInception) private pure {\\n        // The records must have been signed after the record we're trying to delete\\n        require(RRUtils.serialNumberGte(nsec.inception, originalInception));\\n\\n        // The record must be an NSEC3\\n        require(nsec.typeCovered == DNSTYPE_NSEC3);\\n\\n        // nsecName is of the form <hash>.zone.xyz. <hash> is the NSEC3 hash of the entire name the NSEC3 record matches, while\\n        // zone.xyz can be any ancestor of that name. We'll check that, so someone can't use a record on foo.com\\n        // as proof of the nonexistence of bar.org.\\n        require(checkNSEC3OwnerName(nsec.name, deleteName));\\n    }\\n\\n    function isMatchingNSEC3Record(uint16 deleteType, bytes memory deleteName, bytes memory closestEncloserName, RRUtils.NSEC3 memory closestEncloser) private view returns(bool) {\\n        // Check the record matches the hashed name, but the type bitmap does not include the type\\n        if(checkNSEC3Name(closestEncloser, closestEncloserName, deleteName)) {\\n            return !closestEncloser.checkTypeBitmap(deleteType);\\n        }\\n\\n        return false;\\n    }\\n\\n    function isCoveringNSEC3Record(bytes memory deleteName, bytes memory ceName, RRUtils.NSEC3 memory ce, bytes memory ncName, RRUtils.NSEC3 memory nc) private view returns(bool) {\\n        // The flags field must be 0 or 1 (RFC5155 section 8.2).\\n        require(nc.flags & 0xfe == 0);\\n\\n        bytes32 ceNameHash = decodeOwnerNameHash(ceName);\\n        bytes32 ncNameHash = decodeOwnerNameHash(ncName);\\n\\n        uint lastOffset = 0;\\n        // Iterate over suffixes of the name to delete until one matches the closest encloser\\n        for(uint offset = deleteName.readUint8(0) + 1; offset < deleteName.length; offset += deleteName.readUint8(offset) + 1) {\\n            if(hashName(ce, deleteName.substring(offset, deleteName.length - offset)) == ceNameHash) {\\n                // Check that the next closest record encloses the name one label longer\\n                bytes32 checkHash = hashName(nc, deleteName.substring(lastOffset, deleteName.length - lastOffset));\\n                if(ncNameHash < nc.nextHashedOwnerName) {\\n                    return checkHash > ncNameHash && checkHash < nc.nextHashedOwnerName;\\n                } else {\\n                    return checkHash > ncNameHash || checkHash < nc.nextHashedOwnerName;\\n                }\\n            }\\n            lastOffset = offset;\\n        }\\n        // If we reached the root without finding a match, return false.\\n        return false;\\n    }\\n\\n    function readNSEC3(RRUtils.SignedSet memory ss) private pure returns(RRUtils.NSEC3 memory) {\\n        RRUtils.RRIterator memory iter = ss.rrs();\\n        return iter.data.readNSEC3(iter.rdataOffset, iter.nextOffset - iter.rdataOffset);\\n    }\\n\\n    function checkNSEC3Name(RRUtils.NSEC3 memory nsec, bytes memory ownerName, bytes memory deleteName) private view returns(bool) {\\n        // Compute the NSEC3 name hash of the name to delete.\\n        bytes32 deleteNameHash = hashName(nsec, deleteName);\\n\\n        // Decode the NSEC3 name hash from the first label of the NSEC3 owner name.\\n        bytes32 nsecNameHash = decodeOwnerNameHash(ownerName);\\n\\n        return deleteNameHash == nsecNameHash;\\n    }\\n\\n    function hashName(RRUtils.NSEC3 memory nsec, bytes memory name) private view returns(bytes32) {\\n        return nsec3Digests[nsec.hashAlgorithm].hash(nsec.salt, name, nsec.iterations);\\n    }\\n\\n    function decodeOwnerNameHash(bytes memory name) private pure returns(bytes32) {\\n        return name.base32HexDecodeWord(1, uint(name.readUint8(0)));\\n    }\\n\\n    function checkNSEC3OwnerName(bytes memory nsecName, bytes memory deleteName) private pure returns(bool) {\\n        uint nsecNameOffset = nsecName.readUint8(0) + 1;\\n        uint deleteNameOffset = 0;\\n        while(deleteNameOffset < deleteName.length) {\\n            if(deleteName.equals(deleteNameOffset, nsecName, nsecNameOffset)) {\\n                return true;\\n            }\\n            deleteNameOffset += deleteName.readUint8(deleteNameOffset) + 1;\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Returns data about the RRs (if any) known to this oracle with the provided type and name.\\n     * @param dnstype The DNS record type to query.\\n     * @param name The name to query, in DNS label-sequence format.\\n     * @return inception The unix timestamp (wrapped) at which the signature for this RRSET was created.\\n     * @return expiration The unix timestamp (wrapped) at which the signature for this RRSET expires.\\n     * @return hash The hash of the RRset.\\n     */\\n    function rrdata(uint16 dnstype, bytes calldata name) external override view returns (uint32, uint32, bytes20) {\\n        RRSet storage result = rrsets[keccak256(name)][dnstype];\\n        return (result.inception, result.expiration, result.hash);\\n    }\\n\\n    function _submitRRSet(RRSetWithSignature memory input, bytes memory proof) internal returns (bytes memory) {\\n        RRUtils.SignedSet memory rrset;\\n        rrset = validateSignedSet(input, proof);\\n\\n        RRSet storage storedSet = rrsets[keccak256(rrset.name)][rrset.typeCovered];\\n        if (storedSet.hash != bytes20(0)) {\\n            // To replace an existing rrset, the signature must be at least as new\\n            require(RRUtils.serialNumberGte(rrset.inception, storedSet.inception));\\n        }\\n        rrsets[keccak256(rrset.name)][rrset.typeCovered] = RRSet({\\n            inception: rrset.inception,\\n            expiration: rrset.expiration,\\n            hash: bytes20(keccak256(rrset.data))\\n        });\\n\\n        emit RRSetUpdated(rrset.name, rrset.data);\\n\\n        return rrset.data;\\n    }\\n\\n    /**\\n     * @dev Submits a signed set of RRs to the oracle.\\n     *\\n     * RRSETs are only accepted if they are signed with a key that is already\\n     * trusted, or if they are self-signed, and the signing key is identified by\\n     * a DS record that is already trusted.\\n     *\\n     * @param input The signed RR set. This is in the format described in section\\n     *        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature\\n     *        data, followed by a series of canonicalised RR records that the signature\\n     *        applies to.\\n     * @param proof The DNSKEY or DS to validate the signature against. Must Already\\n     *        have been submitted and proved previously.\\n     */\\n    function validateSignedSet(RRSetWithSignature memory input, bytes memory proof) internal view returns(RRUtils.SignedSet memory rrset) {\\n        rrset = input.rrset.readSignedSet();\\n        require(validProof(rrset.signerName, proof));\\n\\n        // Do some basic checks on the RRs and extract the name\\n        bytes memory name = validateRRs(rrset, rrset.typeCovered);\\n        require(name.labelCount(0) == rrset.labels);\\n        rrset.name = name;\\n\\n        // All comparisons involving the Signature Expiration and\\n        // Inception fields MUST use \\\"serial number arithmetic\\\", as\\n        // defined in RFC 1982\\n\\n        // o  The validator's notion of the current time MUST be less than or\\n        //    equal to the time listed in the RRSIG RR's Expiration field.\\n        require(RRUtils.serialNumberGte(rrset.expiration, uint32(block.timestamp)));\\n\\n        // o  The validator's notion of the current time MUST be greater than or\\n        //    equal to the time listed in the RRSIG RR's Inception field.\\n        require(RRUtils.serialNumberGte(uint32(block.timestamp), rrset.inception));\\n\\n        // Validate the signature\\n        verifySignature(name, rrset, input, proof);\\n\\n        return rrset;\\n    }\\n\\n    function validProof(bytes memory name, bytes memory proof) internal view returns(bool) {\\n        uint16 dnstype = proof.readUint16(proof.nameLength(0));\\n        return rrsets[keccak256(name)][dnstype].hash == bytes20(keccak256(proof));\\n    }\\n\\n    /**\\n     * @dev Validates a set of RRs.\\n     * @param rrset The RR set.\\n     * @param typecovered The type covered by the RRSIG record.\\n     */\\n    function validateRRs(RRUtils.SignedSet memory rrset, uint16 typecovered) internal pure returns (bytes memory name) {\\n        // Iterate over all the RRs\\n        for (RRUtils.RRIterator memory iter = rrset.rrs(); !iter.done(); iter.next()) {\\n            // We only support class IN (Internet)\\n            require(iter.class == DNSCLASS_IN);\\n\\n            if(name.length == 0) {\\n                name = iter.name();\\n            } else {\\n                // Name must be the same on all RRs. We do things this way to avoid copying the name\\n                // repeatedly.\\n                require(name.length == iter.data.nameLength(iter.offset));\\n                require(name.equals(0, iter.data, iter.offset, name.length));\\n            }\\n\\n            // o  The RRSIG RR's Type Covered field MUST equal the RRset's type.\\n            require(iter.dnstype == typecovered);\\n        }\\n    }\\n\\n    /**\\n     * @dev Performs signature verification.\\n     *\\n     * Throws or reverts if unable to verify the record.\\n     *\\n     * @param name The name of the RRSIG record, in DNS label-sequence format.\\n     * @param data The original data to verify.\\n     * @param proof A DS or DNSKEY record that's already verified by the oracle.\\n     */\\n    function verifySignature(bytes memory name, RRUtils.SignedSet memory rrset, RRSetWithSignature memory data, bytes memory proof) internal view {\\n        // o  The RRSIG RR's Signer's Name field MUST be the name of the zone\\n        //    that contains the RRset.\\n        require(rrset.signerName.length <= name.length);\\n        require(rrset.signerName.equals(0, name, name.length - rrset.signerName.length));\\n\\n        RRUtils.RRIterator memory proofRR = proof.iterateRRs(0);\\n        // Check the proof\\n        if (proofRR.dnstype == DNSTYPE_DS) {\\n            require(verifyWithDS(rrset, data, proofRR));\\n        } else if (proofRR.dnstype == DNSTYPE_DNSKEY) {\\n            require(verifyWithKnownKey(rrset, data, proofRR));\\n        } else {\\n            revert(\\\"No valid proof found\\\");\\n        }\\n    }\\n\\n    /**\\n     * @dev Attempts to verify a signed RRSET against an already known public key.\\n     * @param rrset The signed set to verify.\\n     * @param data The original data the signed set was read from.\\n     * @param proof The serialized DS or DNSKEY record to use as proof.\\n     * @return True if the RRSET could be verified, false otherwise.\\n     */\\n    function verifyWithKnownKey(RRUtils.SignedSet memory rrset, RRSetWithSignature memory data, RRUtils.RRIterator memory proof) internal view returns(bool) {\\n        // Check the DNSKEY's owner name matches the signer name on the RRSIG\\n        require(proof.name().equals(rrset.signerName));\\n        for(; !proof.done(); proof.next()) {\\n            require(proof.name().equals(rrset.signerName));\\n            bytes memory keyrdata = proof.rdata();\\n            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(0, keyrdata.length);\\n            if(verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {\\n                return true;\\n            }\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Attempts to verify some data using a provided key and a signature.\\n     * @param dnskey The dns key record to verify the signature with.\\n     * @param rrset The signed RRSET being verified.\\n     * @param data The original data `rrset` was decoded from.\\n     * @return True iff the key verifies the signature.\\n     */\\n    function verifySignatureWithKey(RRUtils.DNSKEY memory dnskey, bytes memory keyrdata, RRUtils.SignedSet memory rrset, RRSetWithSignature memory data)\\n        internal\\n        view\\n        returns (bool)\\n    {\\n        // TODO: Check key isn't expired, unless updating key itself\\n\\n        // The Protocol Field MUST have value 3 (RFC4034 2.1.2)\\n        if(dnskey.protocol != 3) {\\n            return false;\\n        }\\n\\n        // o The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST\\n        //   match the owner name, algorithm, and key tag for some DNSKEY RR in\\n        //   the zone's apex DNSKEY RRset.\\n        if(dnskey.algorithm != rrset.algorithm) {\\n            return false;\\n        }\\n        uint16 computedkeytag = keyrdata.computeKeytag();\\n        if (computedkeytag != rrset.keytag) {\\n            return false;\\n        }\\n\\n        // o The matching DNSKEY RR MUST be present in the zone's apex DNSKEY\\n        //   RRset, and MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7)\\n        //   set.\\n        if (dnskey.flags & DNSKEY_FLAG_ZONEKEY == 0) {\\n            return false;\\n        }\\n\\n        return algorithms[dnskey.algorithm].verify(keyrdata, data.rrset, data.sig);\\n    }\\n\\n    /**\\n     * @dev Attempts to verify a signed RRSET against an already known hash. This function assumes\\n     *      that the record \\n     * @param rrset The signed set to verify.\\n     * @param data The original data the signed set was read from.\\n     * @param proof The serialized DS or DNSKEY record to use as proof.\\n     * @return True if the RRSET could be verified, false otherwise.\\n     */\\n    function verifyWithDS(RRUtils.SignedSet memory rrset, RRSetWithSignature memory data, RRUtils.RRIterator memory proof) internal view returns(bool) {\\n        for(RRUtils.RRIterator memory iter = rrset.rrs(); !iter.done(); iter.next()) {\\n            require(iter.dnstype == DNSTYPE_DNSKEY);\\n            bytes memory keyrdata = iter.rdata();\\n            RRUtils.DNSKEY memory dnskey = keyrdata.readDNSKEY(0, keyrdata.length);\\n            if (verifySignatureWithKey(dnskey, keyrdata, rrset, data)) {\\n                // It's self-signed - look for a DS record to verify it.\\n                return verifyKeyWithDS(iter.name(), proof, dnskey, keyrdata);\\n            }\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Attempts to verify a key using DS records.\\n     * @param keyname The DNS name of the key, in DNS label-sequence format.\\n     * @param dsrrs The DS records to use in verification.\\n     * @param dnskey The dnskey to verify.\\n     * @param keyrdata The RDATA section of the key.\\n     * @return True if a DS record verifies this key.\\n     */\\n    function verifyKeyWithDS(bytes memory keyname, RRUtils.RRIterator memory dsrrs, RRUtils.DNSKEY memory dnskey, bytes memory keyrdata)\\n        internal view returns (bool)\\n    {\\n        uint16 keytag = keyrdata.computeKeytag();\\n        for (; !dsrrs.done(); dsrrs.next()) {\\n            RRUtils.DS memory ds = dsrrs.data.readDS(dsrrs.rdataOffset, dsrrs.nextOffset - dsrrs.rdataOffset);\\n            if(ds.keytag != keytag) {\\n                continue;\\n            }\\n            if (ds.algorithm != dnskey.algorithm) {\\n                continue;\\n            }\\n\\n            Buffer.buffer memory buf;\\n            buf.init(keyname.length + keyrdata.length);\\n            buf.append(keyname);\\n            buf.append(keyrdata);\\n            if (verifyDSHash(ds.digestType, buf.buf, ds.digest)) {\\n                return true;\\n            }\\n        }\\n        return false;\\n    }\\n\\n    /**\\n     * @dev Attempts to verify a DS record's hash value against some data.\\n     * @param digesttype The digest ID from the DS record.\\n     * @param data The data to digest.\\n     * @param digest The digest data to check against.\\n     * @return True iff the digest matches.\\n     */\\n    function verifyDSHash(uint8 digesttype, bytes memory data, bytes memory digest) internal view returns (bool) {\\n        if (address(digests[digesttype]) == address(0)) {\\n            return false;\\n        }\\n        return digests[digesttype].verify(data, digest);\\n    }\\n}\\n\",\"keccak256\":\"0x347fdc38971b863831f00f0e5a8e791ace9dda1196da57fbf726a125c9d99a04\"},\"contracts/dnssec-oracle/Owned.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n* @dev Contract mixin for 'owned' contracts.\\n*/\\ncontract Owned {\\n    address public owner;\\n    \\n    modifier owner_only() {\\n        require(msg.sender == owner);\\n        _;\\n    }\\n\\n    constructor() public {\\n        owner = msg.sender;\\n    }\\n\\n    function setOwner(address newOwner) public owner_only {\\n        owner = newOwner;\\n    }\\n}\\n\",\"keccak256\":\"0x14ca1cbae3a361b9d868147498af8bdea7e7d5b0829e207fb7719f607cce5ab3\"},\"contracts/dnssec-oracle/RRUtils.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\nimport \\\"./BytesUtils.sol\\\";\\nimport \\\"@ensdomains/buffer/contracts/Buffer.sol\\\";\\n\\n/**\\n* @dev RRUtils is a library that provides utilities for parsing DNS resource records.\\n*/\\nlibrary RRUtils {\\n    using BytesUtils for *;\\n    using Buffer for *;\\n\\n    /**\\n    * @dev Returns the number of bytes in the DNS name at 'offset' in 'self'.\\n    * @param self The byte array to read a name from.\\n    * @param offset The offset to start reading at.\\n    * @return The length of the DNS name at 'offset', in bytes.\\n    */\\n    function nameLength(bytes memory self, uint offset) internal pure returns(uint) {\\n        uint idx = offset;\\n        while (true) {\\n            assert(idx < self.length);\\n            uint labelLen = self.readUint8(idx);\\n            idx += labelLen + 1;\\n            if (labelLen == 0) {\\n                break;\\n            }\\n        }\\n        return idx - offset;\\n    }\\n\\n    /**\\n    * @dev Returns a DNS format name at the specified offset of self.\\n    * @param self The byte array to read a name from.\\n    * @param offset The offset to start reading at.\\n    * @return ret The name.\\n    */\\n    function readName(bytes memory self, uint offset) internal pure returns(bytes memory ret) {\\n        uint len = nameLength(self, offset);\\n        return self.substring(offset, len);\\n    }\\n\\n    /**\\n    * @dev Returns the number of labels in the DNS name at 'offset' in 'self'.\\n    * @param self The byte array to read a name from.\\n    * @param offset The offset to start reading at.\\n    * @return The number of labels in the DNS name at 'offset', in bytes.\\n    */\\n    function labelCount(bytes memory self, uint offset) internal pure returns(uint) {\\n        uint count = 0;\\n        while (true) {\\n            assert(offset < self.length);\\n            uint labelLen = self.readUint8(offset);\\n            offset += labelLen + 1;\\n            if (labelLen == 0) {\\n                break;\\n            }\\n            count += 1;\\n        }\\n        return count;\\n    }\\n\\n    uint constant RRSIG_TYPE = 0;\\n    uint constant RRSIG_ALGORITHM = 2;\\n    uint constant RRSIG_LABELS = 3;\\n    uint constant RRSIG_TTL = 4;\\n    uint constant RRSIG_EXPIRATION = 8;\\n    uint constant RRSIG_INCEPTION = 12;\\n    uint constant RRSIG_KEY_TAG = 16;\\n    uint constant RRSIG_SIGNER_NAME = 18;\\n\\n    struct SignedSet {\\n        uint16 typeCovered;\\n        uint8 algorithm;\\n        uint8 labels;\\n        uint32 ttl;\\n        uint32 expiration;\\n        uint32 inception;\\n        uint16 keytag;\\n        bytes signerName;\\n        bytes data;\\n        bytes name;\\n    }\\n\\n    function readSignedSet(bytes memory data) internal pure returns(SignedSet memory self) {\\n        self.typeCovered = data.readUint16(RRSIG_TYPE);\\n        self.algorithm = data.readUint8(RRSIG_ALGORITHM);\\n        self.labels = data.readUint8(RRSIG_LABELS);\\n        self.ttl = data.readUint32(RRSIG_TTL);\\n        self.expiration = data.readUint32(RRSIG_EXPIRATION);\\n        self.inception = data.readUint32(RRSIG_INCEPTION);\\n        self.keytag = data.readUint16(RRSIG_KEY_TAG);\\n        self.signerName = readName(data, RRSIG_SIGNER_NAME);\\n        self.data = data.substring(RRSIG_SIGNER_NAME + self.signerName.length, data.length - RRSIG_SIGNER_NAME - self.signerName.length);\\n    }\\n\\n    function rrs(SignedSet memory rrset) internal pure returns(RRIterator memory) {\\n        return iterateRRs(rrset.data, 0);\\n    }\\n\\n    /**\\n    * @dev An iterator over resource records.\\n    */\\n    struct RRIterator {\\n        bytes data;\\n        uint offset;\\n        uint16 dnstype;\\n        uint16 class;\\n        uint32 ttl;\\n        uint rdataOffset;\\n        uint nextOffset;\\n    }\\n\\n    /**\\n    * @dev Begins iterating over resource records.\\n    * @param self The byte string to read from.\\n    * @param offset The offset to start reading at.\\n    * @return ret An iterator object.\\n    */\\n    function iterateRRs(bytes memory self, uint offset) internal pure returns (RRIterator memory ret) {\\n        ret.data = self;\\n        ret.nextOffset = offset;\\n        next(ret);\\n    }\\n\\n    /**\\n    * @dev Returns true iff there are more RRs to iterate.\\n    * @param iter The iterator to check.\\n    * @return True iff the iterator has finished.\\n    */\\n    function done(RRIterator memory iter) internal pure returns(bool) {\\n        return iter.offset >= iter.data.length;\\n    }\\n\\n    /**\\n    * @dev Moves the iterator to the next resource record.\\n    * @param iter The iterator to advance.\\n    */\\n    function next(RRIterator memory iter) internal pure {\\n        iter.offset = iter.nextOffset;\\n        if (iter.offset >= iter.data.length) {\\n            return;\\n        }\\n\\n        // Skip the name\\n        uint off = iter.offset + nameLength(iter.data, iter.offset);\\n\\n        // Read type, class, and ttl\\n        iter.dnstype = iter.data.readUint16(off);\\n        off += 2;\\n        iter.class = iter.data.readUint16(off);\\n        off += 2;\\n        iter.ttl = iter.data.readUint32(off);\\n        off += 4;\\n\\n        // Read the rdata\\n        uint rdataLength = iter.data.readUint16(off);\\n        off += 2;\\n        iter.rdataOffset = off;\\n        iter.nextOffset = off + rdataLength;\\n    }\\n\\n    /**\\n    * @dev Returns the name of the current record.\\n    * @param iter The iterator.\\n    * @return A new bytes object containing the owner name from the RR.\\n    */\\n    function name(RRIterator memory iter) internal pure returns(bytes memory) {\\n        return iter.data.substring(iter.offset, nameLength(iter.data, iter.offset));\\n    }\\n\\n    /**\\n    * @dev Returns the rdata portion of the current record.\\n    * @param iter The iterator.\\n    * @return A new bytes object containing the RR's RDATA.\\n    */\\n    function rdata(RRIterator memory iter) internal pure returns(bytes memory) {\\n        return iter.data.substring(iter.rdataOffset, iter.nextOffset - iter.rdataOffset);\\n    }\\n\\n    uint constant DNSKEY_FLAGS = 0;\\n    uint constant DNSKEY_PROTOCOL = 2;\\n    uint constant DNSKEY_ALGORITHM = 3;\\n    uint constant DNSKEY_PUBKEY = 4;\\n\\n    struct DNSKEY {\\n        uint16 flags;\\n        uint8 protocol;\\n        uint8 algorithm;\\n        bytes publicKey;\\n    }\\n\\n    function readDNSKEY(bytes memory data, uint offset, uint length) internal pure returns(DNSKEY memory self) {\\n        self.flags = data.readUint16(offset + DNSKEY_FLAGS);\\n        self.protocol = data.readUint8(offset + DNSKEY_PROTOCOL);\\n        self.algorithm = data.readUint8(offset + DNSKEY_ALGORITHM);\\n        self.publicKey = data.substring(offset + DNSKEY_PUBKEY, length - DNSKEY_PUBKEY);\\n    } \\n\\n    uint constant DS_KEY_TAG = 0;\\n    uint constant DS_ALGORITHM = 2;\\n    uint constant DS_DIGEST_TYPE = 3;\\n    uint constant DS_DIGEST = 4;\\n\\n    struct DS {\\n        uint16 keytag;\\n        uint8 algorithm;\\n        uint8 digestType;\\n        bytes digest;\\n    }\\n\\n    function readDS(bytes memory data, uint offset, uint length) internal pure returns(DS memory self) {\\n        self.keytag = data.readUint16(offset + DS_KEY_TAG);\\n        self.algorithm = data.readUint8(offset + DS_ALGORITHM);\\n        self.digestType = data.readUint8(offset + DS_DIGEST_TYPE);\\n        self.digest = data.substring(offset + DS_DIGEST, length - DS_DIGEST);\\n    }\\n\\n    struct NSEC3 {\\n        uint8 hashAlgorithm;\\n        uint8 flags;\\n        uint16 iterations;\\n        bytes salt;\\n        bytes32 nextHashedOwnerName;\\n        bytes typeBitmap;\\n    }\\n\\n    uint constant NSEC3_HASH_ALGORITHM = 0;\\n    uint constant NSEC3_FLAGS = 1;\\n    uint constant NSEC3_ITERATIONS = 2;\\n    uint constant NSEC3_SALT_LENGTH = 4;\\n    uint constant NSEC3_SALT = 5;\\n\\n    function readNSEC3(bytes memory data, uint offset, uint length) internal pure returns(NSEC3 memory self) {\\n        uint end = offset + length;\\n        self.hashAlgorithm = data.readUint8(offset + NSEC3_HASH_ALGORITHM);\\n        self.flags = data.readUint8(offset + NSEC3_FLAGS);\\n        self.iterations = data.readUint16(offset + NSEC3_ITERATIONS);\\n        uint8 saltLength = data.readUint8(offset + NSEC3_SALT_LENGTH);\\n        offset = offset + NSEC3_SALT;\\n        self.salt = data.substring(offset, saltLength);\\n        offset += saltLength;\\n        uint8 nextLength = data.readUint8(offset);\\n        require(nextLength <= 32);\\n        offset += 1;\\n        self.nextHashedOwnerName = data.readBytesN(offset, nextLength);\\n        offset += nextLength;\\n        self.typeBitmap = data.substring(offset, end - offset);\\n    }\\n\\n    function checkTypeBitmap(NSEC3 memory self, uint16 rrtype) internal pure returns(bool) {\\n        return checkTypeBitmap(self.typeBitmap, 0, rrtype);\\n    }\\n\\n    /**\\n    * @dev Checks if a given RR type exists in a type bitmap.\\n    * @param bitmap The byte string to read the type bitmap from.\\n    * @param offset The offset to start reading at.\\n    * @param rrtype The RR type to check for.\\n    * @return True if the type is found in the bitmap, false otherwise.\\n    */\\n    function checkTypeBitmap(bytes memory bitmap, uint offset, uint16 rrtype) internal pure returns (bool) {\\n        uint8 typeWindow = uint8(rrtype >> 8);\\n        uint8 windowByte = uint8((rrtype & 0xff) / 8);\\n        uint8 windowBitmask = uint8(uint8(1) << (uint8(7) - uint8(rrtype & 0x7)));\\n        for (uint off = offset; off < bitmap.length;) {\\n            uint8 window = bitmap.readUint8(off);\\n            uint8 len = bitmap.readUint8(off + 1);\\n            if (typeWindow < window) {\\n                // We've gone past our window; it's not here.\\n                return false;\\n            } else if (typeWindow == window) {\\n                // Check this type bitmap\\n                if (len <= windowByte) {\\n                    // Our type is past the end of the bitmap\\n                    return false;\\n                }\\n                return (bitmap.readUint8(off + windowByte + 2) & windowBitmask) != 0;\\n            } else {\\n                // Skip this type bitmap\\n                off += len + 2;\\n            }\\n        }\\n\\n        return false;\\n    }\\n\\n    function compareNames(bytes memory self, bytes memory other) internal pure returns (int) {\\n        if (self.equals(other)) {\\n            return 0;\\n        }\\n\\n        uint off;\\n        uint otheroff;\\n        uint prevoff;\\n        uint otherprevoff;\\n        uint counts = labelCount(self, 0);\\n        uint othercounts = labelCount(other, 0);\\n\\n        // Keep removing labels from the front of the name until both names are equal length\\n        while (counts > othercounts) {\\n            prevoff = off;\\n            off = progress(self, off);\\n            counts--;\\n        }\\n\\n        while (othercounts > counts) {\\n            otherprevoff = otheroff;\\n            otheroff = progress(other, otheroff);\\n            othercounts--;\\n        }\\n\\n        // Compare the last nonequal labels to each other\\n        while (counts > 0 && !self.equals(off, other, otheroff)) {\\n            prevoff = off;\\n            off = progress(self, off);\\n            otherprevoff = otheroff;\\n            otheroff = progress(other, otheroff);\\n            counts -= 1;\\n        }\\n\\n        if (off == 0) {\\n            return -1;\\n        }\\n        if(otheroff == 0) {\\n            return 1;\\n        }\\n\\n        return self.compare(prevoff + 1, self.readUint8(prevoff), other, otherprevoff + 1, other.readUint8(otherprevoff));\\n    }\\n\\n    /**\\n     * @dev Compares two serial numbers using RFC1982 serial number math.\\n     */\\n    function serialNumberGte(uint32 i1, uint32 i2) internal pure returns(bool) {\\n        return int32(i1) - int32(i2) >= 0;\\n    }\\n\\n    function progress(bytes memory body, uint off) internal pure returns(uint) {\\n        return off + 1 + body.readUint8(off);\\n    }\\n\\n    /**\\n     * @dev Computes the keytag for a chunk of data.\\n     * @param data The data to compute a keytag for.\\n     * @return The computed key tag.\\n     */\\n    function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n        /* This function probably deserves some explanation.\\n         * The DNSSEC keytag function is a checksum that relies on summing up individual bytes\\n         * from the input string, with some mild bitshifting. Here's a Naive solidity implementation:\\n         *\\n         *     function computeKeytag(bytes memory data) internal pure returns (uint16) {\\n         *         uint ac;\\n         *         for (uint i = 0; i < data.length; i++) {\\n         *             ac += i & 1 == 0 ? uint16(data.readUint8(i)) << 8 : data.readUint8(i);\\n         *         }\\n         *         return uint16(ac + (ac >> 16));\\n         *     }\\n         *\\n         * The EVM, with its 256 bit words, is exceedingly inefficient at doing byte-by-byte operations;\\n         * the code above, on reasonable length inputs, consumes over 100k gas. But we can make the EVM's\\n         * large words work in our favour.\\n         *\\n         * The code below works by treating the input as a series of 256 bit words. It first masks out\\n         * even and odd bytes from each input word, adding them to two separate accumulators `ac1` and `ac2`.\\n         * The bytes are separated by empty bytes, so as long as no individual sum exceeds 2^16-1, we're\\n         * effectively summing 16 different numbers with each EVM ADD opcode.\\n         *\\n         * Once it's added up all the inputs, it has to add all the 16 bit values in `ac1` and `ac2` together.\\n         * It does this using the same trick - mask out every other value, shift to align them, add them together.\\n         * After the first addition on both accumulators, there's enough room to add the two accumulators together,\\n         * and the remaining sums can be done just on ac1.\\n         */\\n        unchecked {\\n            require(data.length <= 8192, \\\"Long keys not permitted\\\");\\n            uint ac1;\\n            uint ac2;\\n            for(uint i = 0; i < data.length + 31; i += 32) {\\n                uint word;\\n                assembly {\\n                    word := mload(add(add(data, 32), i))\\n                }\\n                if(i + 32 > data.length) {\\n                    uint unused = 256 - (data.length - i) * 8;\\n                    word = (word >> unused) << unused;\\n                }\\n                ac1 += (word & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8;\\n                ac2 += (word & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF);\\n            }\\n            ac1 = (ac1 & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF)\\n                + ((ac1 & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16);\\n            ac2 = (ac2 & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF)\\n                + ((ac2 & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16);\\n            ac1 = (ac1 << 8) + ac2;\\n            ac1 = (ac1 & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF)\\n                + ((ac1 & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32);\\n            ac1 = (ac1 & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF)\\n                + ((ac1 & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64);\\n            ac1 = (ac1 & 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)\\n                + (ac1 >> 128);\\n            ac1 += (ac1 >> 16) & 0xFFFF;\\n            return uint16(ac1);\\n        }\\n    }\\n}\",\"keccak256\":\"0x811642c86c539d645ef99a15fa1bf0eb4ce963cf1a618ef2a6f34d27a5e34030\"},\"contracts/dnssec-oracle/algorithms/Algorithm.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n* @dev An interface for contracts implementing a DNSSEC (signing) algorithm.\\n*/\\ninterface Algorithm {\\n    /**\\n    * @dev Verifies a signature.\\n    * @param key The public key to verify with.\\n    * @param data The signed data to verify.\\n    * @param signature The signature to verify.\\n    * @return True iff the signature is valid.\\n    */\\n    function verify(bytes calldata key, bytes calldata data, bytes calldata signature) external virtual view returns (bool);\\n}\\n\",\"keccak256\":\"0x51d6251568844e435f58952354abe8c8c8e978ab40ecb0bbb2f5bd767838b3a7\"},\"contracts/dnssec-oracle/digests/Digest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n* @dev An interface for contracts implementing a DNSSEC digest.\\n*/\\ninterface Digest {\\n    /**\\n    * @dev Verifies a cryptographic hash.\\n    * @param data The data to hash.\\n    * @param hash The hash to compare to.\\n    * @return True iff the hashed data matches the provided hash value.\\n    */\\n    function verify(bytes calldata data, bytes calldata hash) external virtual pure returns (bool);\\n}\\n\",\"keccak256\":\"0x259720cef78c019d38b908bc7dd524f087c58d8c40792cebcdd4e982c628bc9a\"},\"contracts/dnssec-oracle/nsec3digests/NSEC3Digest.sol\":{\"content\":\"pragma solidity ^0.8.4;\\n\\n/**\\n * @dev Interface for contracts that implement NSEC3 digest algorithms.\\n */\\ninterface NSEC3Digest {\\n    /**\\n     * @dev Performs an NSEC3 iterated hash.\\n     * @param salt The salt value to use on each iteration.\\n     * @param data The data to hash.\\n     * @param iterations The number of iterations to perform.\\n     * @return The result of the iterated hash operation.\\n     */\\n     function hash(bytes calldata salt, bytes calldata data, uint iterations) external virtual pure returns (bytes32);\\n}\\n\",\"keccak256\":\"0xb3b61aee6bb472158b7ace6b5644dcb668271296b98a6dcde24dc72e3cdf4950\"}},\"version\":1}",
  "bytecode": "0x60806040523480156200001157600080fd5b5060405162004ecb38038062004ecb833981810160405281019062000037919062000319565b33600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806000908051906020019062000090929190620001f7565b506040518060600160405280600063ffffffff16815260200163e090bba063ffffffff1681526020016000604051620000ca91906200049c565b60405180910390206bffffffffffffffffffffffff1916815250600260007fbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a81526020019081526020016000206000602b61ffff1661ffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908360601c02179055509050507f55ced933cdd5a34dd03eb5d4bef19ec6ebb251dcd7a988eee0c1b9a13baaa88b6000604051620001e89190620004b5565b60405180910390a15062000698565b8280546200020590620005b4565b90600052602060002090601f01602090048101928262000229576000855562000275565b82601f106200024457805160ff191683800117855562000275565b8280016001018555821562000275579182015b828111156200027457825182559160200191906001019062000257565b5b50905062000284919062000288565b5090565b5b80821115620002a357600081600090555060010162000289565b5090565b6000620002be620002b88462000517565b620004ee565b905082815260208101848484011115620002d757600080fd5b620002e48482856200057e565b509392505050565b600082601f830112620002fe57600080fd5b815162000310848260208601620002a7565b91505092915050565b6000602082840312156200032c57600080fd5b600082015167ffffffffffffffff8111156200034757600080fd5b6200035584828501620002ec565b91505092915050565b600081546200036d81620005b4565b62000379818662000562565b94506001821660008114620003975760018114620003aa57620003e1565b60ff1983168652602086019350620003e1565b620003b5856200054d565b60005b83811015620003d957815481890152600182019150602081019050620003b8565b808801955050505b50505092915050565b60008154620003f981620005b4565b62000405818662000573565b9450600182166000811462000423576001811462000435576200046c565b60ff198316865281860193506200046c565b62000440856200054d565b60005b83811015620004645781548189015260018201915060208101905062000443565b838801955050505b50505092915050565b60006200048460018362000562565b915062000491826200068f565b602082019050919050565b6000620004aa8284620003ea565b915081905092915050565b60006040820190508181036000830152620004d08162000475565b90508181036020830152620004e681846200035e565b905092915050565b6000620004fa6200050d565b9050620005088282620005ea565b919050565b6000604051905090565b600067ffffffffffffffff8211156200053557620005346200064f565b5b62000540826200067e565b9050602081019050919050565b60008190508160005260206000209050919050565b600082825260208201905092915050565b600081905092915050565b60005b838110156200059e57808201518184015260208101905062000581565b83811115620005ae576000848401525b50505050565b60006002820490506001821680620005cd57607f821691505b60208210811415620005e457620005e362000620565b5b50919050565b620005f5826200067e565b810181811067ffffffffffffffff821117156200061757620006166200064f565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008082015250565b61482380620006a86000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806373cc48a61161008c57806398d35f201161006657806398d35f2014610247578063bd7ed31a14610265578063c327deef14610295578063d7b82ebe146102c5576100ea565b806373cc48a6146101dd5780638438dc041461020d5780638da5cb5b14610229576100ea565b806313af4035116100c857806313af40351461015957806328e7677d146101755780632c095cbb14610191578063435cc162146101ad576100ea565b8063020ed8d3146100ef578063087991bc1461010b5780630b1a24951461013d575b600080fd5b61010960048036038101906101049190613a6f565b6102f5565b005b6101256004803603810190610120919061386c565b6103e4565b60405161013493929190613dee565b60405180910390f35b6101576004803603810190610152919061396f565b61047b565b005b610173600480360381019061016e9190613715565b6106f2565b005b61018f600480360381019061018a9190613aab565b610790565b005b6101ab60048036038101906101a691906138c4565b61087f565b005b6101c760048036038101906101c2919061373e565b6109d2565b6040516101d49190613c73565b60405180910390f35b6101f760048036038101906101f29190613a46565b610a94565b6040516102049190613d78565b60405180910390f35b61022760048036038101906102229190613ae7565b610ac7565b005b610231610bb6565b60405161023e9190613c58565b60405180910390f35b61024f610bdc565b60405161025c9190613c73565b60405180910390f35b61027f600480360381019061027a9190613a46565b610c6a565b60405161028c9190613d93565b60405180910390f35b6102af60048036038101906102aa9190613a46565b610c9d565b6040516102bc9190613d5d565b60405180910390f35b6102df60048036038101906102da9190613800565b610cd0565b6040516102ec9190613c73565b60405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461034f57600080fd5b80600360008460ff1660ff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff73c3c226af96b7f1ba666a21b3ceaf2be3ee6a365e3178fd9cd1eaae0075aa882826040516103d8929190613e25565b60405180910390a15050565b6000806000806002600087876040516103fe929190613c3f565b6040518091039020815260200190815260200160002060008861ffff1661ffff16815260200190815260200160002090508060000160009054906101000a900463ffffffff168160000160049054906101000a900463ffffffff168260000160089054906101000a900460601b9350935093505093509350939050565b6000600260008680519060200120815260200190815260200160002060008761ffff1661ffff16815260200190815260200160002060000160009054906101000a900463ffffffff16905060006104d28584610ce4565b90506104df818784610d95565b6104e7613310565b6000856000015151111561050d576104ff8585610ce4565b905061050c818885610d95565b5b600061051883610de2565b9050600060fe82602001511660ff161461053157600080fd5b610545602782610e2f90919063ffffffff16565b15801561057e5750610561600282610e2f90919063ffffffff16565b158061057d575061057c600682610e2f90919063ffffffff16565b5b5b61058757600080fd5b610598898985610120015184610e49565b1561062d57600260008980519060200120815260200190815260200160002060008a61ffff1661ffff168152602001908152602001600020600080820160006101000a81549063ffffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550506106e7565b61064c888461012001518385610120015161064787610de2565b610e83565b156106e157600260008980519060200120815260200190815260200160002060008a61ffff1661ffff168152602001908152602001600020600080820160006101000a81549063ffffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550506106e6565b600080fd5b5b505050505050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074c57600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107ea57600080fd5b80600460008460ff1660ff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f2fcc274c3b72dd483ab201bfa87295e3817e8b9b10693219873b722ca1af00c78282604051610873929190613e25565b60405180910390a15050565b610887613310565b6108918383610ce4565b9050602f61ffff16816000015161ffff16146108ac57600080fd5b6109008160a00151600260008780519060200120815260200190815260200160002060008861ffff1661ffff16815260200190815260200160002060000160009054906101000a900463ffffffff16610fd6565b61090957600080fd5b600061091482610ff2565b905061091f81611011565b6109c657610934818361012001518789611027565b600260008680519060200120815260200190815260200160002060008761ffff1661ffff168152602001908152602001600020600080820160006101000a81549063ffffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055505050506109cc565b50600080fd5b50505050565b6060600083838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060005b8551811015610a8857610a73868281518110610a65577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101518361127d565b91508080610a8090614548565b915050610a20565b50809150509392505050565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b2157600080fd5b80600560008460ff1660ff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc7eec866a7a1386188cc3ca20ffea75b71bd3e90a60b6791b1d3f0971145118d8282604051610baa929190613e25565b60405180910390a15050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054610be9906144e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610c15906144e5565b8015610c625780601f10610c3757610100808354040283529160200191610c62565b820191906000526020600020905b815481529060010190602001808311610c4557829003601f168201915b505050505081565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60036020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060610cdc838361127d565b905092915050565b610cec613310565b610cf98360000151611497565b9050610d098160e001518361161c565b610d1257600080fd5b6000610d228283600001516116bb565b9050816040015160ff16610d4060008361178c90919063ffffffff16565b14610d4a57600080fd5b80826101200181905250610d62826080015142610fd6565b610d6b57600080fd5b610d79428360a00151610fd6565b610d8257600080fd5b610d8e81838686611834565b5092915050565b610da38360a0015182610fd6565b610dac57600080fd5b603261ffff16836000015161ffff1614610dc557600080fd5b610dd483610120015183611934565b610ddd57600080fd5b505050565b610dea613383565b6000610df583610ff2565b9050610e278160a001518260a001518360c00151610e13919061429d565b83600001516119d09092919063ffffffff16565b915050919050565b6000610e418360a00151600084611b78565b905092915050565b6000610e56828486611cbf565b15610e7657610e6e8583610e2f90919063ffffffff16565b159050610e7b565b600090505b949350505050565b60008060fe83602001511660ff1614610e9b57600080fd5b6000610ea686611ce9565b90506000610eb385611ce9565b90506000806001610ece60008c611d1e90919063ffffffff16565b610ed89190613f5e565b60ff1690505b8951811015610fc45783610f1289610f0d84858f51610efd919061429d565b8f611d6f9092919063ffffffff16565b611e2a565b1415610f8d576000610f4487610f3f85868f51610f2f919061429d565b8f611d6f9092919063ffffffff16565b611e2a565b90508660800151841015610f70578381118015610f645750866080015181105b95505050505050610fcd565b83811180610f815750866080015181105b95505050505050610fcd565b8091506001610fa5828c611d1e90919063ffffffff16565b610faf9190613f5e565b60ff1681610fbd9190613f08565b9050610ede565b50600093505050505b95945050505050565b6000808284610fe59190614225565b60030b1215905092915050565b610ffa6133c6565b61100a8261010001516000611f06565b9050919050565b6000816000015151826020015110159050919050565b60008460a0015190506000611049828760000151611f3090919063ffffffff16565b905060008660a001518760c00151611061919061429d565b905081811161106f57600080fd5b60006110848787611fd390919063ffffffff16565b905060008114156110c2576110b3838561109e9190613f08565b868a60000151611b789092919063ffffffff16565b156110bd57600080fd5b611129565b60006110dd85858b60000151611d6f9092919063ffffffff16565b9050600082136110ec57600080fd5b6000611101828a611fd390919063ffffffff16565b121561112757600061111c8289611fd390919063ffffffff16565b1261112657600080fd5b5b505b5050505050505050565b8060c001518160200181815250508060000151518160200151106111565761127a565b600061116a82600001518360200151611f30565b82602001516111799190613f08565b905061119281836000015161218790919063ffffffff16565b826040019061ffff16908161ffff16815250506002816111b29190613f08565b90506111cb81836000015161218790919063ffffffff16565b826060019061ffff16908161ffff16815250506002816111eb9190613f08565b90506112048183600001516121b690919063ffffffff16565b826080019063ffffffff16908163ffffffff16815250506004816112289190613f08565b9050600061124382846000015161218790919063ffffffff16565b61ffff1690506002826112569190613f08565b9150818360a0018181525050808261126e9190613f08565b8360c001818152505050505b50565b6060611287613310565b6112918484610ce4565b90506000600260008361012001518051906020012081526020019081526020016000206000836000015161ffff1661ffff1681526020019081526020016000209050600060601b6bffffffffffffffffffffffff19168160000160089054906101000a900460601b6bffffffffffffffffffffffff1916146113395761132f8260a001518260000160009054906101000a900463ffffffff16610fd6565b61133857600080fd5b5b60405180606001604052808360a0015163ffffffff168152602001836080015163ffffffff168152602001836101000151805190602001206bffffffffffffffffffffffff1916815250600260008461012001518051906020012081526020019081526020016000206000846000015161ffff1661ffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908360601c02179055509050507f55ced933cdd5a34dd03eb5d4bef19ec6ebb251dcd7a988eee0c1b9a13baaa88b82610120015183610100015160405161147f929190613c95565b60405180910390a18161010001519250505092915050565b61149f613310565b6114b360008361218790919063ffffffff16565b816000019061ffff16908161ffff16815250506114da600283611d1e90919063ffffffff16565b816020019060ff16908160ff16815250506114ff600383611d1e90919063ffffffff16565b816040019060ff16908160ff16815250506115246004836121b690919063ffffffff16565b816060019063ffffffff16908163ffffffff168152505061154f6008836121b690919063ffffffff16565b816080019063ffffffff16908163ffffffff168152505061157a600c836121b690919063ffffffff16565b8160a0019063ffffffff16908163ffffffff16815250506115a560108361218790919063ffffffff16565b8160c0019061ffff16908161ffff16815250506115c38260126121e7565b8160e0018190525061160e8160e001515160126115e09190613f08565b8260e0015151601285516115f4919061429d565b6115fe919061429d565b84611d6f9092919063ffffffff16565b816101000181905250919050565b600080611645611636600085611f3090919063ffffffff16565b8461218790919063ffffffff16565b905082805190602001206bffffffffffffffffffffffff1916600260008680519060200120815260200190815260200160002060008361ffff1661ffff16815260200190815260200160002060000160089054906101000a900460601b6bffffffffffffffffffffffff19161491505092915050565b606060006116c884610ff2565b90505b6116d481611011565b61178557600161ffff16816060015161ffff16146116f157600080fd5b60008251141561170b5761170481612215565b915061175f565b61172681602001518260000151611f3090919063ffffffff16565b82511461173257600080fd5b61175560008260000151836020015185518661224c90949392919063ffffffff16565b61175e57600080fd5b5b8261ffff16816040015161ffff161461177757600080fd5b61178081611133565b6116cb565b5092915050565b600080600090505b60011561182a57835183106117d2577f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60006117e78486611d1e90919063ffffffff16565b60ff1690506001816117f99190613f08565b846118049190613f08565b93506000811415611815575061182a565b6001826118229190613f08565b915050611794565b8091505092915050565b83518360e0015151111561184757600080fd5b6118746000858560e0015151875161185f919061429d565b8660e00151612270909392919063ffffffff16565b61187d57600080fd5b6000611893600083611f0690919063ffffffff16565b9050602b61ffff16816040015161ffff1614156118c3576118b58484836122ab565b6118be57600080fd5b61192d565b603061ffff16816040015161ffff1614156118f1576118e3848483612354565b6118ec57600080fd5b61192c565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192390613dce565b60405180910390fd5b5b5050505050565b600080600161194d600086611d1e90919063ffffffff16565b6119579190613f5e565b60ff16905060005b83518110156119c35761197f81868487612270909392919063ffffffff16565b1561198f576001925050506119ca565b60016119a48286611d1e90919063ffffffff16565b6119ae9190613f5e565b60ff16816119bc9190613f08565b905061195f565b6000925050505b92915050565b6119d8613383565b600082846119e69190613f08565b9050611a076000856119f89190613f08565b86611d1e90919063ffffffff16565b826000019060ff16908160ff1681525050611a37600185611a289190613f08565b86611d1e90919063ffffffff16565b826020019060ff16908160ff1681525050611a67600285611a589190613f08565b8661218790919063ffffffff16565b826040019061ffff16908161ffff16815250506000611a9b600486611a8c9190613f08565b87611d1e90919063ffffffff16565b9050600585611aaa9190613f08565b9450611ac4858260ff1688611d6f9092919063ffffffff16565b83606001819052508060ff1685611adb9190613f08565b94506000611af28688611d1e90919063ffffffff16565b905060208160ff161115611b0557600080fd5b600186611b129190613f08565b9550611b2c868260ff16896124149092919063ffffffff16565b8460800181815250508060ff1686611b449190613f08565b9550611b66868785611b56919061429d565b89611d6f9092919063ffffffff16565b8460a001819052505050509392505050565b60008060088361ffff16901c90506000600860ff8516611b989190613f95565b90506000600785166007611bac91906142d1565b60ff16600160ff16901b905060008690505b8751811015611caf576000611bdc828a611d1e90919063ffffffff16565b90506000611bff600184611bf09190613f08565b8b611d1e90919063ffffffff16565b90508160ff168660ff161015611c1e5760009650505050505050611cb8565b8160ff168660ff161415611c8b578460ff168160ff1611611c485760009650505050505050611cb8565b600084611c7860028860ff1687611c5f9190613f08565b611c699190613f08565b8d611d1e90919063ffffffff16565b1660ff1614159650505050505050611cb8565b600281611c989190613f5e565b60ff1683611ca69190613f08565b92505050611bbe565b50600093505050505b9392505050565b600080611ccc8584611e2a565b90506000611cd985611ce9565b9050808214925050509392505050565b6000611d176001611d04600085611d1e90919063ffffffff16565b60ff168461245c9092919063ffffffff16565b9050919050565b6000828281518110611d59577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b60f81c905092915050565b606083518284611d7f9190613f08565b1115611d8a57600080fd5b60008267ffffffffffffffff811115611dcc577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611dfe5781602001600182028036833780820191505090505b5090506000806020830191508560208801019050611e1d828287612744565b8293505050509392505050565b600060056000846000015160ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166368f9dab284606001518486604001516040518463ffffffff1660e01b8152600401611eae93929190613d18565b60206040518083038186803b158015611ec657600080fd5b505afa158015611eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efe91906137d7565b905092915050565b611f0e6133c6565b828160000181905250818160c0018181525050611f2a81611133565b92915050565b6000808290505b600115611fbe5783518110611f75577f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000611f8a8286611d1e90919063ffffffff16565b60ff169050600181611f9c9190613f08565b82611fa79190613f08565b91506000811415611fb85750611fbe565b50611f37565b8281611fca919061429d565b91505092915050565b6000611fe882846127a890919063ffffffff16565b15611ff65760009050612181565b600080600080600061200988600061178c565b9050600061201888600061178c565b90505b808211156120455785935061203089876127cf565b9550818061203d906144bb565b92505061201b565b5b818111156120705784925061205b88866127cf565b94508080612068906144bb565b915050612046565b5b60008211801561209557506120938689878c612270909392919063ffffffff16565b155b156120cc578593506120a789876127cf565b95508492506120b688866127cf565b94506001826120c5919061429d565b9150612071565b6000861415612103577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9650505050505050612181565b600085141561211b5760019650505050505050612181565b61217860018561212b9190613f08565b61213e868c611d1e90919063ffffffff16565b60ff168a60018761214f9190613f08565b612162888e611d1e90919063ffffffff16565b60ff168e6128069095949392919063ffffffff16565b96505050505050505b92915050565b600082516002836121989190613f08565b11156121a357600080fd5b61ffff8260028501015116905092915050565b600082516004836121c79190613f08565b11156121d257600080fd5b63ffffffff8260048501015116905092915050565b606060006121f58484611f30565b905061220c838286611d6f9092919063ffffffff16565b91505092915050565b6060612245826020015161223184600001518560200151611f30565b8460000151611d6f9092919063ffffffff16565b9050919050565b600061225984848461293b565b61226487878561293b565b14905095945050505050565b60006122898383848651612284919061429d565b61293b565b6122a0868687895161229b919061429d565b61293b565b149050949350505050565b6000806122b785610ff2565b90505b6122c381611011565b61234757603061ffff16816040015161ffff16146122e057600080fd5b60006122eb82612967565b9050600061230660008351846129a09092919063ffffffff16565b905061231481838989612a76565b156123375761232d61232584612215565b868385612bd5565b935050505061234d565b505061234281611133565b6122ba565b50600090505b9392505050565b60006123758460e0015161236784612215565b6127a890919063ffffffff16565b61237e57600080fd5b5b61238882611011565b612408576123ab8460e0015161239d84612215565b6127a890919063ffffffff16565b6123b457600080fd5b60006123bf83612967565b905060006123da60008351846129a09092919063ffffffff16565b90506123e881838888612a76565b156123f85760019250505061240d565b505061240382611133565b61237f565b600090505b9392505050565b6000602082111561242457600080fd5b835182846124329190613f08565b111561243d57600080fd5b6001826020036101000a03198084602087010151169150509392505050565b6000603482111561246c57600080fd5b60008080600090505b848110156125f357600087828861248c9190613f08565b815181106124c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b9050603060f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161015801561252c5750607a60f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191611155b61253557600080fd5b6040518060800160405280604781526020016147a76047913960308260f81c60ff16612561919061429d565b81518110612598577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b60f81c925060208360ff1611156125b957600080fd5b6001866125c6919061429d565b8214156125d357506125f3565b8260ff16600585901b1793505080806125eb90614548565b915050612475565b5060006005856126039190614137565b905060006008866126149190614591565b141561262b578160ff16600584901b179250612724565b600260088661263a9190614591565b14156126675760028260ff16901c60ff16600384901b179250600281612660919061429d565b9050612723565b60046008866126769190614591565b14156126a35760048260ff16901c60ff16600184901b17925060048161269c919061429d565b9050612722565b60056008866126b29190614591565b14156126df5760018260ff16901c60ff16600484901b1792506001816126d8919061429d565b9050612721565b60076008866126ee9190614591565b141561271b5760038260ff16901c60ff16600284901b179250600381612714919061429d565b9050612720565b600080fd5b5b5b5b5b80610100612732919061429d565b83901b60001b93505050509392505050565b5b60208110612783578151835260208361275e9190613f08565b925060208261276d9190613f08565b915060208161277c919061429d565b9050612745565b60006001826020036101000a0390508019835116818551168181178652505050505050565b6000815183511480156127c757506127c6836000846000875161224c565b5b905092915050565b60006127e48284611d1e90919063ffffffff16565b60ff166001836127f49190613f08565b6127fe9190613f08565b905092915050565b60008085905085831015612818578290505b600080602089018a019150602086018701905060005b8381101561291e5760008084519150835190508082146128ea576000602087111561287b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90506128bb565b60018488602061288b919061429d565b6128959190613f08565b60086128a19190614137565b60026128ad9190614019565b6128b7919061429d565b1990505b60008183168285166128cd9190614191565b9050600081146128e7578098505050505050505050612931565b50505b6020856128f79190613f08565b94506020846129069190613f08565b935050506020816129179190613f08565b905061282e565b50848861292b9190614191565b93505050505b9695505050505050565b60008351828461294b9190613f08565b111561295657600080fd5b818360208601012090509392505050565b60606129998260a001518360a001518460c00151612985919061429d565b8460000151611d6f9092919063ffffffff16565b9050919050565b6129a8613411565b6129c76000846129b89190613f08565b8561218790919063ffffffff16565b816000019061ffff16908161ffff16815250506129f96002846129ea9190613f08565b85611d1e90919063ffffffff16565b816020019060ff16908160ff1681525050612a29600384612a1a9190613f08565b85611d1e90919063ffffffff16565b816040019060ff16908160ff1681525050612a67600484612a4a9190613f08565b600484612a57919061429d565b86611d6f9092919063ffffffff16565b81606001819052509392505050565b60006003856020015160ff1614612a905760009050612bcd565b826020015160ff16856040015160ff1614612aae5760009050612bcd565b6000612ab985612cf1565b90508360c0015161ffff168161ffff1614612ad8576000915050612bcd565b6000610100876000015161ffff16161415612af7576000915050612bcd565b60036000876040015160ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663de8f50a186856000015186602001516040518463ffffffff1660e01b8152600401612b7993929190613ccc565b60206040518083038186803b158015612b9157600080fd5b505afa158015612ba5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc991906137ae565b9150505b949350505050565b600080612be183612cf1565b90505b612bed85611011565b612ce3576000612c238660a001518760a001518860c00151612c0f919061429d565b8860000151612f399092919063ffffffff16565b90508161ffff16816000015161ffff1614612c3e5750612cd5565b846040015160ff16816020015160ff1614612c595750612cd5565b612c61613443565b612c8185518951612c729190613f08565b8261300f90919063ffffffff16565b50612c95888261307990919063ffffffff16565b50612ca9858261307990919063ffffffff16565b50612cc182604001518260000151846060015161309b565b15612cd25760019350505050612ce9565b50505b612cde85611133565b612be4565b60009150505b949350505050565b600061200082511115612d39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d3090613dae565b60405180910390fd5b60008060005b601f855101811015612dd95760008160208701015190508551602083011115612d7c57600060088388510302610100039050808183901c901b9150505b60087fff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff008216901c840193507eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff81168301925050602081019050612d3f565b5060107fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00008316901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff831601915060107fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00008216901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff821601905080600883901b01915060207fffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000008316901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff831601915060407fffffffffffffffff0000000000000000ffffffffffffffff00000000000000008316901c77ffffffffffffffff0000000000000000ffffffffffffffff8316019150608082901c6fffffffffffffffffffffffffffffffff831601915061ffff601083901c16820191508192505050919050565b612f4161345d565b612f60600084612f519190613f08565b8561218790919063ffffffff16565b816000019061ffff16908161ffff1681525050612f92600284612f839190613f08565b85611d1e90919063ffffffff16565b816020019060ff16908160ff1681525050612fc2600384612fb39190613f08565b85611d1e90919063ffffffff16565b816040019060ff16908160ff1681525050613000600484612fe39190613f08565b600484612ff0919061429d565b86611d6f9092919063ffffffff16565b81606001819052509392505050565b613017613443565b60006020836130269190614591565b14613052576020826130389190614591565b6020613044919061429d565b8261304f9190613f08565b91505b81836020018181525050604051808452600081528281016020016040525082905092915050565b613081613443565b613093838460000151518485516131e1565b905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008660ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561311357600090506131da565b600460008560ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f7e83aee84846040518363ffffffff1660e01b8152600401613187929190613c95565b60206040518083038186803b15801561319f57600080fd5b505afa1580156131b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d791906137ae565b90505b9392505050565b6131e9613443565b82518211156131f757600080fd5b846020015182856132089190613f08565b111561323d5761323c85600261322d886020015188876132289190613f08565b6132d0565b6132379190614137565b6132ec565b5b60008086518051876020830101935080888701111561325c5787860182525b60208701925050505b602084106132a3578051825260208261327e9190613f08565b915060208161328d9190613f08565b905060208461329c919061429d565b9350613265565b60006001856020036101000a03905080198251168184511681811785525050508692505050949350505050565b6000818311156132e2578290506132e6565b8190505b92915050565b6000826000015190506132ff838361300f565b5061330a8382613079565b50505050565b604051806101400160405280600061ffff168152602001600060ff168152602001600060ff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600061ffff1681526020016060815260200160608152602001606081525090565b6040518060c00160405280600060ff168152602001600060ff168152602001600061ffff1681526020016060815260200160008019168152602001606081525090565b6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b6040518060800160405280600061ffff168152602001600060ff168152602001600060ff168152602001606081525090565b604051806040016040528060608152602001600081525090565b6040518060800160405280600061ffff168152602001600060ff168152602001600060ff168152602001606081525090565b60006134a261349d84613e73565b613e4e565b905080838252602082019050828560208602820111156134c157600080fd5b60005b8581101561350b57813567ffffffffffffffff8111156134e357600080fd5b8086016134f0898261366f565b855260208501945060208401935050506001810190506134c4565b5050509392505050565b600061352861352384613e9f565b613e4e565b90508281526020810184848401111561354057600080fd5b61354b848285614479565b509392505050565b600081359050613562816146ee565b92915050565b600082601f83011261357957600080fd5b813561358984826020860161348f565b91505092915050565b6000815190506135a181614705565b92915050565b6000815190506135b68161471c565b92915050565b60008083601f8401126135ce57600080fd5b8235905067ffffffffffffffff8111156135e757600080fd5b6020830191508360018202830111156135ff57600080fd5b9250929050565b600082601f83011261361757600080fd5b8135613627848260208601613515565b91505092915050565b60008135905061363f81614733565b92915050565b6000813590506136548161474a565b92915050565b60008135905061366981614761565b92915050565b60006040828403121561368157600080fd5b61368b6040613e4e565b9050600082013567ffffffffffffffff8111156136a757600080fd5b6136b384828501613606565b600083015250602082013567ffffffffffffffff8111156136d357600080fd5b6136df84828501613606565b60208301525092915050565b6000813590506136fa81614778565b92915050565b60008135905061370f8161478f565b92915050565b60006020828403121561372757600080fd5b600061373584828501613553565b91505092915050565b60008060006040848603121561375357600080fd5b600084013567ffffffffffffffff81111561376d57600080fd5b61377986828701613568565b935050602084013567ffffffffffffffff81111561379657600080fd5b6137a2868287016135bc565b92509250509250925092565b6000602082840312156137c057600080fd5b60006137ce84828501613592565b91505092915050565b6000602082840312156137e957600080fd5b60006137f7848285016135a7565b91505092915050565b6000806040838503121561381357600080fd5b600083013567ffffffffffffffff81111561382d57600080fd5b6138398582860161366f565b925050602083013567ffffffffffffffff81111561385657600080fd5b61386285828601613606565b9150509250929050565b60008060006040848603121561388157600080fd5b600061388f868287016136eb565b935050602084013567ffffffffffffffff8111156138ac57600080fd5b6138b8868287016135bc565b92509250509250925092565b600080600080608085870312156138da57600080fd5b60006138e8878288016136eb565b945050602085013567ffffffffffffffff81111561390557600080fd5b61391187828801613606565b935050604085013567ffffffffffffffff81111561392e57600080fd5b61393a8782880161366f565b925050606085013567ffffffffffffffff81111561395757600080fd5b61396387828801613606565b91505092959194509250565b600080600080600060a0868803121561398757600080fd5b6000613995888289016136eb565b955050602086013567ffffffffffffffff8111156139b257600080fd5b6139be88828901613606565b945050604086013567ffffffffffffffff8111156139db57600080fd5b6139e78882890161366f565b935050606086013567ffffffffffffffff811115613a0457600080fd5b613a108882890161366f565b925050608086013567ffffffffffffffff811115613a2d57600080fd5b613a3988828901613606565b9150509295509295909350565b600060208284031215613a5857600080fd5b6000613a6684828501613700565b91505092915050565b60008060408385031215613a8257600080fd5b6000613a9085828601613700565b9250506020613aa185828601613630565b9150509250929050565b60008060408385031215613abe57600080fd5b6000613acc85828601613700565b9250506020613add85828601613645565b9150509250929050565b60008060408385031215613afa57600080fd5b6000613b0885828601613700565b9250506020613b198582860161365a565b9150509250929050565b613b2c81614305565b82525050565b613b3b81614323565b82525050565b6000613b4d8385613eec565b9350613b5a838584614479565b82840190509392505050565b6000613b7182613ed0565b613b7b8185613edb565b9350613b8b818560208601614488565b613b948161467e565b840191505092915050565b613ba8816143fb565b82525050565b613bb78161441f565b82525050565b613bc681614443565b82525050565b6000613bd9601783613ef7565b9150613be48261469c565b602082019050919050565b6000613bfc601483613ef7565b9150613c07826146c5565b602082019050919050565b613c1b81614467565b82525050565b613c2a816143de565b82525050565b613c39816143ee565b82525050565b6000613c4c828486613b41565b91508190509392505050565b6000602082019050613c6d6000830184613b23565b92915050565b60006020820190508181036000830152613c8d8184613b66565b905092915050565b60006040820190508181036000830152613caf8185613b66565b90508181036020830152613cc38184613b66565b90509392505050565b60006060820190508181036000830152613ce68186613b66565b90508181036020830152613cfa8185613b66565b90508181036040830152613d0e8184613b66565b9050949350505050565b60006060820190508181036000830152613d328186613b66565b90508181036020830152613d468185613b66565b9050613d556040830184613c12565b949350505050565b6000602082019050613d726000830184613b9f565b92915050565b6000602082019050613d8d6000830184613bae565b92915050565b6000602082019050613da86000830184613bbd565b92915050565b60006020820190508181036000830152613dc781613bcc565b9050919050565b60006020820190508181036000830152613de781613bef565b9050919050565b6000606082019050613e036000830186613c21565b613e106020830185613c21565b613e1d6040830184613b32565b949350505050565b6000604082019050613e3a6000830185613c30565b613e476020830184613b23565b9392505050565b6000613e58613e69565b9050613e648282614517565b919050565b6000604051905090565b600067ffffffffffffffff821115613e8e57613e8d61464f565b5b602082029050602081019050919050565b600067ffffffffffffffff821115613eba57613eb961464f565b5b613ec38261467e565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000613f13826143d4565b9150613f1e836143d4565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613f5357613f526145c2565b5b828201905092915050565b6000613f69826143ee565b9150613f74836143ee565b92508260ff03821115613f8a57613f896145c2565b5b828201905092915050565b6000613fa0826143a6565b9150613fab836143a6565b925082613fbb57613fba6145f1565b5b828204905092915050565b6000808291508390505b600185111561401057808604811115613fec57613feb6145c2565b5b6001851615613ffb5780820291505b80810290506140098561468f565b9450613fd0565b94509492505050565b6000614024826143d4565b915061402f836143d4565b925061405c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614064565b905092915050565b6000826140745760019050614130565b816140825760009050614130565b816001811461409857600281146140a2576140d1565b6001915050614130565b60ff8411156140b4576140b36145c2565b5b8360020a9150848211156140cb576140ca6145c2565b5b50614130565b5060208310610133831016604e8410600b84101617156141065782820a905083811115614101576141006145c2565b5b614130565b6141138484846001613fc6565b9250905081840481111561412a576141296145c2565b5b81810290505b9392505050565b6000614142826143d4565b915061414d836143d4565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614186576141856145c2565b5b828202905092915050565b600061419c8261438f565b91506141a78361438f565b9250827f8000000000000000000000000000000000000000000000000000000000000000018212600084121516156141e2576141e16145c2565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01821360008412161561421a576142196145c2565b5b828203905092915050565b600061423082614399565b915061423b83614399565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000001821260008412151615614276576142756145c2565b5b82637fffffff018213600084121615614292576142916145c2565b5b828203905092915050565b60006142a8826143d4565b91506142b3836143d4565b9250828210156142c6576142c56145c2565b5b828203905092915050565b60006142dc826143ee565b91506142e7836143ee565b9250828210156142fa576142f96145c2565b5b828203905092915050565b6000614310826143b4565b9050919050565b60008115159050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b600061436482614305565b9050919050565b600061437682614305565b9050919050565b600061438882614305565b9050919050565b6000819050919050565b60008160030b9050919050565b600061ffff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600063ffffffff82169050919050565b600060ff82169050919050565b60006144068261440d565b9050919050565b6000614418826143b4565b9050919050565b600061442a82614431565b9050919050565b600061443c826143b4565b9050919050565b600061444e82614455565b9050919050565b6000614460826143b4565b9050919050565b6000614472826143a6565b9050919050565b82818337600083830152505050565b60005b838110156144a657808201518184015260208101905061448b565b838111156144b5576000848401525b50505050565b60006144c6826143d4565b915060008214156144da576144d96145c2565b5b600182039050919050565b600060028204905060018216806144fd57607f821691505b6020821081141561451157614510614620565b5b50919050565b6145208261467e565b810181811067ffffffffffffffff8211171561453f5761453e61464f565b5b80604052505050565b6000614553826143d4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614586576145856145c2565b5b600182019050919050565b600061459c826143d4565b91506145a7836143d4565b9250826145b7576145b66145f1565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160011c9050919050565b7f4c6f6e67206b657973206e6f74207065726d6974746564000000000000000000600082015250565b7f4e6f2076616c69642070726f6f6620666f756e64000000000000000000000000600082015250565b6146f781614305565b811461470257600080fd5b50565b61470e81614317565b811461471957600080fd5b50565b6147258161434f565b811461473057600080fd5b50565b61473c81614359565b811461474757600080fd5b50565b6147538161436b565b811461475e57600080fd5b50565b61476a8161437d565b811461477557600080fd5b50565b614781816143a6565b811461478c57600080fd5b50565b614798816143ee565b81146147a357600080fd5b5056fe00010203040506070809ffffffffffffff0a0b0c0d0e0f101112131415161718191a1b1c1d1e1fffffffffffffffffffff0a0b0c0d0e0f101112131415161718191a1b1c1d1e1fa26469706673582212200863ca5c6fb425baca4f13e2cb90134252c9ba773757e3a584f08f724650c50164736f6c63430008040033",
  "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c806373cc48a61161008c57806398d35f201161006657806398d35f2014610247578063bd7ed31a14610265578063c327deef14610295578063d7b82ebe146102c5576100ea565b806373cc48a6146101dd5780638438dc041461020d5780638da5cb5b14610229576100ea565b806313af4035116100c857806313af40351461015957806328e7677d146101755780632c095cbb14610191578063435cc162146101ad576100ea565b8063020ed8d3146100ef578063087991bc1461010b5780630b1a24951461013d575b600080fd5b61010960048036038101906101049190613a6f565b6102f5565b005b6101256004803603810190610120919061386c565b6103e4565b60405161013493929190613dee565b60405180910390f35b6101576004803603810190610152919061396f565b61047b565b005b610173600480360381019061016e9190613715565b6106f2565b005b61018f600480360381019061018a9190613aab565b610790565b005b6101ab60048036038101906101a691906138c4565b61087f565b005b6101c760048036038101906101c2919061373e565b6109d2565b6040516101d49190613c73565b60405180910390f35b6101f760048036038101906101f29190613a46565b610a94565b6040516102049190613d78565b60405180910390f35b61022760048036038101906102229190613ae7565b610ac7565b005b610231610bb6565b60405161023e9190613c58565b60405180910390f35b61024f610bdc565b60405161025c9190613c73565b60405180910390f35b61027f600480360381019061027a9190613a46565b610c6a565b60405161028c9190613d93565b60405180910390f35b6102af60048036038101906102aa9190613a46565b610c9d565b6040516102bc9190613d5d565b60405180910390f35b6102df60048036038101906102da9190613800565b610cd0565b6040516102ec9190613c73565b60405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461034f57600080fd5b80600360008460ff1660ff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff73c3c226af96b7f1ba666a21b3ceaf2be3ee6a365e3178fd9cd1eaae0075aa882826040516103d8929190613e25565b60405180910390a15050565b6000806000806002600087876040516103fe929190613c3f565b6040518091039020815260200190815260200160002060008861ffff1661ffff16815260200190815260200160002090508060000160009054906101000a900463ffffffff168160000160049054906101000a900463ffffffff168260000160089054906101000a900460601b9350935093505093509350939050565b6000600260008680519060200120815260200190815260200160002060008761ffff1661ffff16815260200190815260200160002060000160009054906101000a900463ffffffff16905060006104d28584610ce4565b90506104df818784610d95565b6104e7613310565b6000856000015151111561050d576104ff8585610ce4565b905061050c818885610d95565b5b600061051883610de2565b9050600060fe82602001511660ff161461053157600080fd5b610545602782610e2f90919063ffffffff16565b15801561057e5750610561600282610e2f90919063ffffffff16565b158061057d575061057c600682610e2f90919063ffffffff16565b5b5b61058757600080fd5b610598898985610120015184610e49565b1561062d57600260008980519060200120815260200190815260200160002060008a61ffff1661ffff168152602001908152602001600020600080820160006101000a81549063ffffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550506106e7565b61064c888461012001518385610120015161064787610de2565b610e83565b156106e157600260008980519060200120815260200190815260200160002060008a61ffff1661ffff168152602001908152602001600020600080820160006101000a81549063ffffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550506106e6565b600080fd5b5b505050505050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461074c57600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146107ea57600080fd5b80600460008460ff1660ff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f2fcc274c3b72dd483ab201bfa87295e3817e8b9b10693219873b722ca1af00c78282604051610873929190613e25565b60405180910390a15050565b610887613310565b6108918383610ce4565b9050602f61ffff16816000015161ffff16146108ac57600080fd5b6109008160a00151600260008780519060200120815260200190815260200160002060008861ffff1661ffff16815260200190815260200160002060000160009054906101000a900463ffffffff16610fd6565b61090957600080fd5b600061091482610ff2565b905061091f81611011565b6109c657610934818361012001518789611027565b600260008680519060200120815260200190815260200160002060008761ffff1661ffff168152602001908152602001600020600080820160006101000a81549063ffffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055505050506109cc565b50600080fd5b50505050565b6060600083838080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060005b8551811015610a8857610a73868281518110610a65577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101518361127d565b91508080610a8090614548565b915050610a20565b50809150509392505050565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b2157600080fd5b80600560008460ff1660ff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fc7eec866a7a1386188cc3ca20ffea75b71bd3e90a60b6791b1d3f0971145118d8282604051610baa929190613e25565b60405180910390a15050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054610be9906144e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610c15906144e5565b8015610c625780601f10610c3757610100808354040283529160200191610c62565b820191906000526020600020905b815481529060010190602001808311610c4557829003601f168201915b505050505081565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60036020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060610cdc838361127d565b905092915050565b610cec613310565b610cf98360000151611497565b9050610d098160e001518361161c565b610d1257600080fd5b6000610d228283600001516116bb565b9050816040015160ff16610d4060008361178c90919063ffffffff16565b14610d4a57600080fd5b80826101200181905250610d62826080015142610fd6565b610d6b57600080fd5b610d79428360a00151610fd6565b610d8257600080fd5b610d8e81838686611834565b5092915050565b610da38360a0015182610fd6565b610dac57600080fd5b603261ffff16836000015161ffff1614610dc557600080fd5b610dd483610120015183611934565b610ddd57600080fd5b505050565b610dea613383565b6000610df583610ff2565b9050610e278160a001518260a001518360c00151610e13919061429d565b83600001516119d09092919063ffffffff16565b915050919050565b6000610e418360a00151600084611b78565b905092915050565b6000610e56828486611cbf565b15610e7657610e6e8583610e2f90919063ffffffff16565b159050610e7b565b600090505b949350505050565b60008060fe83602001511660ff1614610e9b57600080fd5b6000610ea686611ce9565b90506000610eb385611ce9565b90506000806001610ece60008c611d1e90919063ffffffff16565b610ed89190613f5e565b60ff1690505b8951811015610fc45783610f1289610f0d84858f51610efd919061429d565b8f611d6f9092919063ffffffff16565b611e2a565b1415610f8d576000610f4487610f3f85868f51610f2f919061429d565b8f611d6f9092919063ffffffff16565b611e2a565b90508660800151841015610f70578381118015610f645750866080015181105b95505050505050610fcd565b83811180610f815750866080015181105b95505050505050610fcd565b8091506001610fa5828c611d1e90919063ffffffff16565b610faf9190613f5e565b60ff1681610fbd9190613f08565b9050610ede565b50600093505050505b95945050505050565b6000808284610fe59190614225565b60030b1215905092915050565b610ffa6133c6565b61100a8261010001516000611f06565b9050919050565b6000816000015151826020015110159050919050565b60008460a0015190506000611049828760000151611f3090919063ffffffff16565b905060008660a001518760c00151611061919061429d565b905081811161106f57600080fd5b60006110848787611fd390919063ffffffff16565b905060008114156110c2576110b3838561109e9190613f08565b868a60000151611b789092919063ffffffff16565b156110bd57600080fd5b611129565b60006110dd85858b60000151611d6f9092919063ffffffff16565b9050600082136110ec57600080fd5b6000611101828a611fd390919063ffffffff16565b121561112757600061111c8289611fd390919063ffffffff16565b1261112657600080fd5b5b505b5050505050505050565b8060c001518160200181815250508060000151518160200151106111565761127a565b600061116a82600001518360200151611f30565b82602001516111799190613f08565b905061119281836000015161218790919063ffffffff16565b826040019061ffff16908161ffff16815250506002816111b29190613f08565b90506111cb81836000015161218790919063ffffffff16565b826060019061ffff16908161ffff16815250506002816111eb9190613f08565b90506112048183600001516121b690919063ffffffff16565b826080019063ffffffff16908163ffffffff16815250506004816112289190613f08565b9050600061124382846000015161218790919063ffffffff16565b61ffff1690506002826112569190613f08565b9150818360a0018181525050808261126e9190613f08565b8360c001818152505050505b50565b6060611287613310565b6112918484610ce4565b90506000600260008361012001518051906020012081526020019081526020016000206000836000015161ffff1661ffff1681526020019081526020016000209050600060601b6bffffffffffffffffffffffff19168160000160089054906101000a900460601b6bffffffffffffffffffffffff1916146113395761132f8260a001518260000160009054906101000a900463ffffffff16610fd6565b61133857600080fd5b5b60405180606001604052808360a0015163ffffffff168152602001836080015163ffffffff168152602001836101000151805190602001206bffffffffffffffffffffffff1916815250600260008461012001518051906020012081526020019081526020016000206000846000015161ffff1661ffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908360601c02179055509050507f55ced933cdd5a34dd03eb5d4bef19ec6ebb251dcd7a988eee0c1b9a13baaa88b82610120015183610100015160405161147f929190613c95565b60405180910390a18161010001519250505092915050565b61149f613310565b6114b360008361218790919063ffffffff16565b816000019061ffff16908161ffff16815250506114da600283611d1e90919063ffffffff16565b816020019060ff16908160ff16815250506114ff600383611d1e90919063ffffffff16565b816040019060ff16908160ff16815250506115246004836121b690919063ffffffff16565b816060019063ffffffff16908163ffffffff168152505061154f6008836121b690919063ffffffff16565b816080019063ffffffff16908163ffffffff168152505061157a600c836121b690919063ffffffff16565b8160a0019063ffffffff16908163ffffffff16815250506115a560108361218790919063ffffffff16565b8160c0019061ffff16908161ffff16815250506115c38260126121e7565b8160e0018190525061160e8160e001515160126115e09190613f08565b8260e0015151601285516115f4919061429d565b6115fe919061429d565b84611d6f9092919063ffffffff16565b816101000181905250919050565b600080611645611636600085611f3090919063ffffffff16565b8461218790919063ffffffff16565b905082805190602001206bffffffffffffffffffffffff1916600260008680519060200120815260200190815260200160002060008361ffff1661ffff16815260200190815260200160002060000160089054906101000a900460601b6bffffffffffffffffffffffff19161491505092915050565b606060006116c884610ff2565b90505b6116d481611011565b61178557600161ffff16816060015161ffff16146116f157600080fd5b60008251141561170b5761170481612215565b915061175f565b61172681602001518260000151611f3090919063ffffffff16565b82511461173257600080fd5b61175560008260000151836020015185518661224c90949392919063ffffffff16565b61175e57600080fd5b5b8261ffff16816040015161ffff161461177757600080fd5b61178081611133565b6116cb565b5092915050565b600080600090505b60011561182a57835183106117d2577f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60006117e78486611d1e90919063ffffffff16565b60ff1690506001816117f99190613f08565b846118049190613f08565b93506000811415611815575061182a565b6001826118229190613f08565b915050611794565b8091505092915050565b83518360e0015151111561184757600080fd5b6118746000858560e0015151875161185f919061429d565b8660e00151612270909392919063ffffffff16565b61187d57600080fd5b6000611893600083611f0690919063ffffffff16565b9050602b61ffff16816040015161ffff1614156118c3576118b58484836122ab565b6118be57600080fd5b61192d565b603061ffff16816040015161ffff1614156118f1576118e3848483612354565b6118ec57600080fd5b61192c565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192390613dce565b60405180910390fd5b5b5050505050565b600080600161194d600086611d1e90919063ffffffff16565b6119579190613f5e565b60ff16905060005b83518110156119c35761197f81868487612270909392919063ffffffff16565b1561198f576001925050506119ca565b60016119a48286611d1e90919063ffffffff16565b6119ae9190613f5e565b60ff16816119bc9190613f08565b905061195f565b6000925050505b92915050565b6119d8613383565b600082846119e69190613f08565b9050611a076000856119f89190613f08565b86611d1e90919063ffffffff16565b826000019060ff16908160ff1681525050611a37600185611a289190613f08565b86611d1e90919063ffffffff16565b826020019060ff16908160ff1681525050611a67600285611a589190613f08565b8661218790919063ffffffff16565b826040019061ffff16908161ffff16815250506000611a9b600486611a8c9190613f08565b87611d1e90919063ffffffff16565b9050600585611aaa9190613f08565b9450611ac4858260ff1688611d6f9092919063ffffffff16565b83606001819052508060ff1685611adb9190613f08565b94506000611af28688611d1e90919063ffffffff16565b905060208160ff161115611b0557600080fd5b600186611b129190613f08565b9550611b2c868260ff16896124149092919063ffffffff16565b8460800181815250508060ff1686611b449190613f08565b9550611b66868785611b56919061429d565b89611d6f9092919063ffffffff16565b8460a001819052505050509392505050565b60008060088361ffff16901c90506000600860ff8516611b989190613f95565b90506000600785166007611bac91906142d1565b60ff16600160ff16901b905060008690505b8751811015611caf576000611bdc828a611d1e90919063ffffffff16565b90506000611bff600184611bf09190613f08565b8b611d1e90919063ffffffff16565b90508160ff168660ff161015611c1e5760009650505050505050611cb8565b8160ff168660ff161415611c8b578460ff168160ff1611611c485760009650505050505050611cb8565b600084611c7860028860ff1687611c5f9190613f08565b611c699190613f08565b8d611d1e90919063ffffffff16565b1660ff1614159650505050505050611cb8565b600281611c989190613f5e565b60ff1683611ca69190613f08565b92505050611bbe565b50600093505050505b9392505050565b600080611ccc8584611e2a565b90506000611cd985611ce9565b9050808214925050509392505050565b6000611d176001611d04600085611d1e90919063ffffffff16565b60ff168461245c9092919063ffffffff16565b9050919050565b6000828281518110611d59577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b60f81c905092915050565b606083518284611d7f9190613f08565b1115611d8a57600080fd5b60008267ffffffffffffffff811115611dcc577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611dfe5781602001600182028036833780820191505090505b5090506000806020830191508560208801019050611e1d828287612744565b8293505050509392505050565b600060056000846000015160ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166368f9dab284606001518486604001516040518463ffffffff1660e01b8152600401611eae93929190613d18565b60206040518083038186803b158015611ec657600080fd5b505afa158015611eda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efe91906137d7565b905092915050565b611f0e6133c6565b828160000181905250818160c0018181525050611f2a81611133565b92915050565b6000808290505b600115611fbe5783518110611f75577f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000611f8a8286611d1e90919063ffffffff16565b60ff169050600181611f9c9190613f08565b82611fa79190613f08565b91506000811415611fb85750611fbe565b50611f37565b8281611fca919061429d565b91505092915050565b6000611fe882846127a890919063ffffffff16565b15611ff65760009050612181565b600080600080600061200988600061178c565b9050600061201888600061178c565b90505b808211156120455785935061203089876127cf565b9550818061203d906144bb565b92505061201b565b5b818111156120705784925061205b88866127cf565b94508080612068906144bb565b915050612046565b5b60008211801561209557506120938689878c612270909392919063ffffffff16565b155b156120cc578593506120a789876127cf565b95508492506120b688866127cf565b94506001826120c5919061429d565b9150612071565b6000861415612103577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9650505050505050612181565b600085141561211b5760019650505050505050612181565b61217860018561212b9190613f08565b61213e868c611d1e90919063ffffffff16565b60ff168a60018761214f9190613f08565b612162888e611d1e90919063ffffffff16565b60ff168e6128069095949392919063ffffffff16565b96505050505050505b92915050565b600082516002836121989190613f08565b11156121a357600080fd5b61ffff8260028501015116905092915050565b600082516004836121c79190613f08565b11156121d257600080fd5b63ffffffff8260048501015116905092915050565b606060006121f58484611f30565b905061220c838286611d6f9092919063ffffffff16565b91505092915050565b6060612245826020015161223184600001518560200151611f30565b8460000151611d6f9092919063ffffffff16565b9050919050565b600061225984848461293b565b61226487878561293b565b14905095945050505050565b60006122898383848651612284919061429d565b61293b565b6122a0868687895161229b919061429d565b61293b565b149050949350505050565b6000806122b785610ff2565b90505b6122c381611011565b61234757603061ffff16816040015161ffff16146122e057600080fd5b60006122eb82612967565b9050600061230660008351846129a09092919063ffffffff16565b905061231481838989612a76565b156123375761232d61232584612215565b868385612bd5565b935050505061234d565b505061234281611133565b6122ba565b50600090505b9392505050565b60006123758460e0015161236784612215565b6127a890919063ffffffff16565b61237e57600080fd5b5b61238882611011565b612408576123ab8460e0015161239d84612215565b6127a890919063ffffffff16565b6123b457600080fd5b60006123bf83612967565b905060006123da60008351846129a09092919063ffffffff16565b90506123e881838888612a76565b156123f85760019250505061240d565b505061240382611133565b61237f565b600090505b9392505050565b6000602082111561242457600080fd5b835182846124329190613f08565b111561243d57600080fd5b6001826020036101000a03198084602087010151169150509392505050565b6000603482111561246c57600080fd5b60008080600090505b848110156125f357600087828861248c9190613f08565b815181106124c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b9050603060f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161015801561252c5750607a60f81b817effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191611155b61253557600080fd5b6040518060800160405280604781526020016147a76047913960308260f81c60ff16612561919061429d565b81518110612598577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b60f81c925060208360ff1611156125b957600080fd5b6001866125c6919061429d565b8214156125d357506125f3565b8260ff16600585901b1793505080806125eb90614548565b915050612475565b5060006005856126039190614137565b905060006008866126149190614591565b141561262b578160ff16600584901b179250612724565b600260088661263a9190614591565b14156126675760028260ff16901c60ff16600384901b179250600281612660919061429d565b9050612723565b60046008866126769190614591565b14156126a35760048260ff16901c60ff16600184901b17925060048161269c919061429d565b9050612722565b60056008866126b29190614591565b14156126df5760018260ff16901c60ff16600484901b1792506001816126d8919061429d565b9050612721565b60076008866126ee9190614591565b141561271b5760038260ff16901c60ff16600284901b179250600381612714919061429d565b9050612720565b600080fd5b5b5b5b5b80610100612732919061429d565b83901b60001b93505050509392505050565b5b60208110612783578151835260208361275e9190613f08565b925060208261276d9190613f08565b915060208161277c919061429d565b9050612745565b60006001826020036101000a0390508019835116818551168181178652505050505050565b6000815183511480156127c757506127c6836000846000875161224c565b5b905092915050565b60006127e48284611d1e90919063ffffffff16565b60ff166001836127f49190613f08565b6127fe9190613f08565b905092915050565b60008085905085831015612818578290505b600080602089018a019150602086018701905060005b8381101561291e5760008084519150835190508082146128ea576000602087111561287b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90506128bb565b60018488602061288b919061429d565b6128959190613f08565b60086128a19190614137565b60026128ad9190614019565b6128b7919061429d565b1990505b60008183168285166128cd9190614191565b9050600081146128e7578098505050505050505050612931565b50505b6020856128f79190613f08565b94506020846129069190613f08565b935050506020816129179190613f08565b905061282e565b50848861292b9190614191565b93505050505b9695505050505050565b60008351828461294b9190613f08565b111561295657600080fd5b818360208601012090509392505050565b60606129998260a001518360a001518460c00151612985919061429d565b8460000151611d6f9092919063ffffffff16565b9050919050565b6129a8613411565b6129c76000846129b89190613f08565b8561218790919063ffffffff16565b816000019061ffff16908161ffff16815250506129f96002846129ea9190613f08565b85611d1e90919063ffffffff16565b816020019060ff16908160ff1681525050612a29600384612a1a9190613f08565b85611d1e90919063ffffffff16565b816040019060ff16908160ff1681525050612a67600484612a4a9190613f08565b600484612a57919061429d565b86611d6f9092919063ffffffff16565b81606001819052509392505050565b60006003856020015160ff1614612a905760009050612bcd565b826020015160ff16856040015160ff1614612aae5760009050612bcd565b6000612ab985612cf1565b90508360c0015161ffff168161ffff1614612ad8576000915050612bcd565b6000610100876000015161ffff16161415612af7576000915050612bcd565b60036000876040015160ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663de8f50a186856000015186602001516040518463ffffffff1660e01b8152600401612b7993929190613ccc565b60206040518083038186803b158015612b9157600080fd5b505afa158015612ba5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc991906137ae565b9150505b949350505050565b600080612be183612cf1565b90505b612bed85611011565b612ce3576000612c238660a001518760a001518860c00151612c0f919061429d565b8860000151612f399092919063ffffffff16565b90508161ffff16816000015161ffff1614612c3e5750612cd5565b846040015160ff16816020015160ff1614612c595750612cd5565b612c61613443565b612c8185518951612c729190613f08565b8261300f90919063ffffffff16565b50612c95888261307990919063ffffffff16565b50612ca9858261307990919063ffffffff16565b50612cc182604001518260000151846060015161309b565b15612cd25760019350505050612ce9565b50505b612cde85611133565b612be4565b60009150505b949350505050565b600061200082511115612d39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d3090613dae565b60405180910390fd5b60008060005b601f855101811015612dd95760008160208701015190508551602083011115612d7c57600060088388510302610100039050808183901c901b9150505b60087fff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff008216901c840193507eff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff81168301925050602081019050612d3f565b5060107fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00008316901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff831601915060107fffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff00008216901c7dffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff821601905080600883901b01915060207fffffffff00000000ffffffff00000000ffffffff00000000ffffffff000000008316901c7bffffffff00000000ffffffff00000000ffffffff00000000ffffffff831601915060407fffffffffffffffff0000000000000000ffffffffffffffff00000000000000008316901c77ffffffffffffffff0000000000000000ffffffffffffffff8316019150608082901c6fffffffffffffffffffffffffffffffff831601915061ffff601083901c16820191508192505050919050565b612f4161345d565b612f60600084612f519190613f08565b8561218790919063ffffffff16565b816000019061ffff16908161ffff1681525050612f92600284612f839190613f08565b85611d1e90919063ffffffff16565b816020019060ff16908160ff1681525050612fc2600384612fb39190613f08565b85611d1e90919063ffffffff16565b816040019060ff16908160ff1681525050613000600484612fe39190613f08565b600484612ff0919061429d565b86611d6f9092919063ffffffff16565b81606001819052509392505050565b613017613443565b60006020836130269190614591565b14613052576020826130389190614591565b6020613044919061429d565b8261304f9190613f08565b91505b81836020018181525050604051808452600081528281016020016040525082905092915050565b613081613443565b613093838460000151518485516131e1565b905092915050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008660ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561311357600090506131da565b600460008560ff1660ff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f7e83aee84846040518363ffffffff1660e01b8152600401613187929190613c95565b60206040518083038186803b15801561319f57600080fd5b505afa1580156131b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131d791906137ae565b90505b9392505050565b6131e9613443565b82518211156131f757600080fd5b846020015182856132089190613f08565b111561323d5761323c85600261322d886020015188876132289190613f08565b6132d0565b6132379190614137565b6132ec565b5b60008086518051876020830101935080888701111561325c5787860182525b60208701925050505b602084106132a3578051825260208261327e9190613f08565b915060208161328d9190613f08565b905060208461329c919061429d565b9350613265565b60006001856020036101000a03905080198251168184511681811785525050508692505050949350505050565b6000818311156132e2578290506132e6565b8190505b92915050565b6000826000015190506132ff838361300f565b5061330a8382613079565b50505050565b604051806101400160405280600061ffff168152602001600060ff168152602001600060ff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600061ffff1681526020016060815260200160608152602001606081525090565b6040518060c00160405280600060ff168152602001600060ff168152602001600061ffff1681526020016060815260200160008019168152602001606081525090565b6040518060e001604052806060815260200160008152602001600061ffff168152602001600061ffff168152602001600063ffffffff16815260200160008152602001600081525090565b6040518060800160405280600061ffff168152602001600060ff168152602001600060ff168152602001606081525090565b604051806040016040528060608152602001600081525090565b6040518060800160405280600061ffff168152602001600060ff168152602001600060ff168152602001606081525090565b60006134a261349d84613e73565b613e4e565b905080838252602082019050828560208602820111156134c157600080fd5b60005b8581101561350b57813567ffffffffffffffff8111156134e357600080fd5b8086016134f0898261366f565b855260208501945060208401935050506001810190506134c4565b5050509392505050565b600061352861352384613e9f565b613e4e565b90508281526020810184848401111561354057600080fd5b61354b848285614479565b509392505050565b600081359050613562816146ee565b92915050565b600082601f83011261357957600080fd5b813561358984826020860161348f565b91505092915050565b6000815190506135a181614705565b92915050565b6000815190506135b68161471c565b92915050565b60008083601f8401126135ce57600080fd5b8235905067ffffffffffffffff8111156135e757600080fd5b6020830191508360018202830111156135ff57600080fd5b9250929050565b600082601f83011261361757600080fd5b8135613627848260208601613515565b91505092915050565b60008135905061363f81614733565b92915050565b6000813590506136548161474a565b92915050565b60008135905061366981614761565b92915050565b60006040828403121561368157600080fd5b61368b6040613e4e565b9050600082013567ffffffffffffffff8111156136a757600080fd5b6136b384828501613606565b600083015250602082013567ffffffffffffffff8111156136d357600080fd5b6136df84828501613606565b60208301525092915050565b6000813590506136fa81614778565b92915050565b60008135905061370f8161478f565b92915050565b60006020828403121561372757600080fd5b600061373584828501613553565b91505092915050565b60008060006040848603121561375357600080fd5b600084013567ffffffffffffffff81111561376d57600080fd5b61377986828701613568565b935050602084013567ffffffffffffffff81111561379657600080fd5b6137a2868287016135bc565b92509250509250925092565b6000602082840312156137c057600080fd5b60006137ce84828501613592565b91505092915050565b6000602082840312156137e957600080fd5b60006137f7848285016135a7565b91505092915050565b6000806040838503121561381357600080fd5b600083013567ffffffffffffffff81111561382d57600080fd5b6138398582860161366f565b925050602083013567ffffffffffffffff81111561385657600080fd5b61386285828601613606565b9150509250929050565b60008060006040848603121561388157600080fd5b600061388f868287016136eb565b935050602084013567ffffffffffffffff8111156138ac57600080fd5b6138b8868287016135bc565b92509250509250925092565b600080600080608085870312156138da57600080fd5b60006138e8878288016136eb565b945050602085013567ffffffffffffffff81111561390557600080fd5b61391187828801613606565b935050604085013567ffffffffffffffff81111561392e57600080fd5b61393a8782880161366f565b925050606085013567ffffffffffffffff81111561395757600080fd5b61396387828801613606565b91505092959194509250565b600080600080600060a0868803121561398757600080fd5b6000613995888289016136eb565b955050602086013567ffffffffffffffff8111156139b257600080fd5b6139be88828901613606565b945050604086013567ffffffffffffffff8111156139db57600080fd5b6139e78882890161366f565b935050606086013567ffffffffffffffff811115613a0457600080fd5b613a108882890161366f565b925050608086013567ffffffffffffffff811115613a2d57600080fd5b613a3988828901613606565b9150509295509295909350565b600060208284031215613a5857600080fd5b6000613a6684828501613700565b91505092915050565b60008060408385031215613a8257600080fd5b6000613a9085828601613700565b9250506020613aa185828601613630565b9150509250929050565b60008060408385031215613abe57600080fd5b6000613acc85828601613700565b9250506020613add85828601613645565b9150509250929050565b60008060408385031215613afa57600080fd5b6000613b0885828601613700565b9250506020613b198582860161365a565b9150509250929050565b613b2c81614305565b82525050565b613b3b81614323565b82525050565b6000613b4d8385613eec565b9350613b5a838584614479565b82840190509392505050565b6000613b7182613ed0565b613b7b8185613edb565b9350613b8b818560208601614488565b613b948161467e565b840191505092915050565b613ba8816143fb565b82525050565b613bb78161441f565b82525050565b613bc681614443565b82525050565b6000613bd9601783613ef7565b9150613be48261469c565b602082019050919050565b6000613bfc601483613ef7565b9150613c07826146c5565b602082019050919050565b613c1b81614467565b82525050565b613c2a816143de565b82525050565b613c39816143ee565b82525050565b6000613c4c828486613b41565b91508190509392505050565b6000602082019050613c6d6000830184613b23565b92915050565b60006020820190508181036000830152613c8d8184613b66565b905092915050565b60006040820190508181036000830152613caf8185613b66565b90508181036020830152613cc38184613b66565b90509392505050565b60006060820190508181036000830152613ce68186613b66565b90508181036020830152613cfa8185613b66565b90508181036040830152613d0e8184613b66565b9050949350505050565b60006060820190508181036000830152613d328186613b66565b90508181036020830152613d468185613b66565b9050613d556040830184613c12565b949350505050565b6000602082019050613d726000830184613b9f565b92915050565b6000602082019050613d8d6000830184613bae565b92915050565b6000602082019050613da86000830184613bbd565b92915050565b60006020820190508181036000830152613dc781613bcc565b9050919050565b60006020820190508181036000830152613de781613bef565b9050919050565b6000606082019050613e036000830186613c21565b613e106020830185613c21565b613e1d6040830184613b32565b949350505050565b6000604082019050613e3a6000830185613c30565b613e476020830184613b23565b9392505050565b6000613e58613e69565b9050613e648282614517565b919050565b6000604051905090565b600067ffffffffffffffff821115613e8e57613e8d61464f565b5b602082029050602081019050919050565b600067ffffffffffffffff821115613eba57613eb961464f565b5b613ec38261467e565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000613f13826143d4565b9150613f1e836143d4565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613f5357613f526145c2565b5b828201905092915050565b6000613f69826143ee565b9150613f74836143ee565b92508260ff03821115613f8a57613f896145c2565b5b828201905092915050565b6000613fa0826143a6565b9150613fab836143a6565b925082613fbb57613fba6145f1565b5b828204905092915050565b6000808291508390505b600185111561401057808604811115613fec57613feb6145c2565b5b6001851615613ffb5780820291505b80810290506140098561468f565b9450613fd0565b94509492505050565b6000614024826143d4565b915061402f836143d4565b925061405c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484614064565b905092915050565b6000826140745760019050614130565b816140825760009050614130565b816001811461409857600281146140a2576140d1565b6001915050614130565b60ff8411156140b4576140b36145c2565b5b8360020a9150848211156140cb576140ca6145c2565b5b50614130565b5060208310610133831016604e8410600b84101617156141065782820a905083811115614101576141006145c2565b5b614130565b6141138484846001613fc6565b9250905081840481111561412a576141296145c2565b5b81810290505b9392505050565b6000614142826143d4565b915061414d836143d4565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614186576141856145c2565b5b828202905092915050565b600061419c8261438f565b91506141a78361438f565b9250827f8000000000000000000000000000000000000000000000000000000000000000018212600084121516156141e2576141e16145c2565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01821360008412161561421a576142196145c2565b5b828203905092915050565b600061423082614399565b915061423b83614399565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000001821260008412151615614276576142756145c2565b5b82637fffffff018213600084121615614292576142916145c2565b5b828203905092915050565b60006142a8826143d4565b91506142b3836143d4565b9250828210156142c6576142c56145c2565b5b828203905092915050565b60006142dc826143ee565b91506142e7836143ee565b9250828210156142fa576142f96145c2565b5b828203905092915050565b6000614310826143b4565b9050919050565b60008115159050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b600061436482614305565b9050919050565b600061437682614305565b9050919050565b600061438882614305565b9050919050565b6000819050919050565b60008160030b9050919050565b600061ffff82169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600063ffffffff82169050919050565b600060ff82169050919050565b60006144068261440d565b9050919050565b6000614418826143b4565b9050919050565b600061442a82614431565b9050919050565b600061443c826143b4565b9050919050565b600061444e82614455565b9050919050565b6000614460826143b4565b9050919050565b6000614472826143a6565b9050919050565b82818337600083830152505050565b60005b838110156144a657808201518184015260208101905061448b565b838111156144b5576000848401525b50505050565b60006144c6826143d4565b915060008214156144da576144d96145c2565b5b600182039050919050565b600060028204905060018216806144fd57607f821691505b6020821081141561451157614510614620565b5b50919050565b6145208261467e565b810181811067ffffffffffffffff8211171561453f5761453e61464f565b5b80604052505050565b6000614553826143d4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614586576145856145c2565b5b600182019050919050565b600061459c826143d4565b91506145a7836143d4565b9250826145b7576145b66145f1565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160011c9050919050565b7f4c6f6e67206b657973206e6f74207065726d6974746564000000000000000000600082015250565b7f4e6f2076616c69642070726f6f6620666f756e64000000000000000000000000600082015250565b6146f781614305565b811461470257600080fd5b50565b61470e81614317565b811461471957600080fd5b50565b6147258161434f565b811461473057600080fd5b50565b61473c81614359565b811461474757600080fd5b50565b6147538161436b565b811461475e57600080fd5b50565b61476a8161437d565b811461477557600080fd5b50565b614781816143a6565b811461478c57600080fd5b50565b614798816143ee565b81146147a357600080fd5b5056fe00010203040506070809ffffffffffffff0a0b0c0d0e0f101112131415161718191a1b1c1d1e1fffffffffffffffffffff0a0b0c0d0e0f101112131415161718191a1b1c1d1e1fa26469706673582212200863ca5c6fb425baca4f13e2cb90134252c9ba773757e3a584f08f724650c50164736f6c63430008040033",
  "devdoc": {
    "kind": "dev",
    "methods": {
      "constructor": {
        "details": "Constructor.",
        "params": {
          "_anchors": "The binary format RR entries for the root DS records."
        }
      },
      "deleteRRSet(uint16,bytes,(bytes,bytes),bytes)": {
        "details": "Deletes an RR from the oracle.",
        "params": {
          "deleteName": "which you want to delete",
          "deleteType": "The DNS record type to delete.",
          "nsec": "The signed NSEC RRset. This is in the format described in section        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature        data, followed by a series of canonicalised RR records that the signature        applies to."
        }
      },
      "deleteRRSetNSEC3(uint16,bytes,(bytes,bytes),(bytes,bytes),bytes)": {
        "details": "Deletes an RR from the oracle using an NSEC3 proof.      Deleting a record using NSEC3 requires using up to two NSEC3 records. There are two cases:       1. The name exists, but the record type doesn't. Eg, example.com has A records but no TXT records.       2. The name does not exist, but a parent name does.      In the first case, we submit one NSEC3 proof in `closestEncloser` that matches the target name      but does not have the bit for `deleteType` set in its type bitmap. In the second case, we submit      two proofs: closestEncloser and nextClosest, that together prove that the name does not exist.      NSEC3 records are in the format described in section 5.3.2 of RFC4035: The RRDATA section      from the RRSIG without the signature data, followed by a series of canonicalised RR records      that the signature applies to.",
        "params": {
          "closestEncloser": "An NSEC3 proof matching the closest enclosing name - that is,        the nearest ancestor of the target name that *does* exist.",
          "deleteName": "The name to delete.",
          "deleteType": "The DNS record type to delete.",
          "dnskey": "An encoded DNSKEY record that has already been submitted to the oracle and can be used        to verify the signatures closestEncloserSig and nextClosestSig",
          "nextClosest": "An NSEC3 proof covering the next closest name. This proves that the immediate        subdomain of the closestEncloser does not exist."
        }
      },
      "rrdata(uint16,bytes)": {
        "details": "Returns data about the RRs (if any) known to this oracle with the provided type and name.",
        "params": {
          "dnstype": "The DNS record type to query.",
          "name": "The name to query, in DNS label-sequence format."
        },
        "returns": {
          "_0": "inception The unix timestamp (wrapped) at which the signature for this RRSET was created.",
          "_1": "expiration The unix timestamp (wrapped) at which the signature for this RRSET expires.",
          "_2": "hash The hash of the RRset."
        }
      },
      "setAlgorithm(uint8,address)": {
        "details": "Sets the contract address for a signature verification algorithm.      Callable only by the owner.",
        "params": {
          "algo": "The address of the algorithm contract.",
          "id": "The algorithm ID"
        }
      },
      "setDigest(uint8,address)": {
        "details": "Sets the contract address for a digest verification algorithm.      Callable only by the owner.",
        "params": {
          "digest": "The address of the digest contract.",
          "id": "The digest ID"
        }
      },
      "setNSEC3Digest(uint8,address)": {
        "details": "Sets the contract address for an NSEC3 digest algorithm.      Callable only by the owner.",
        "params": {
          "digest": "The address of the digest contract.",
          "id": "The digest ID"
        }
      },
      "submitRRSet((bytes,bytes),bytes)": {
        "details": "Submits a signed set of RRs to the oracle. RRSETs are only accepted if they are signed with a key that is already trusted, or if they are self-signed, and the signing key is identified by a DS record that is already trusted.",
        "params": {
          "input": "The signed RR set. This is in the format described in section        5.3.2 of RFC4035: The RRDATA section from the RRSIG without the signature        data, followed by a series of canonicalised RR records that the signature        applies to.",
          "proof": "The DNSKEY or DS to validate the signature against. Must Already        have been submitted and proved previously."
        }
      },
      "submitRRSets((bytes,bytes)[],bytes)": {
        "details": "Submits multiple RRSets",
        "params": {
          "_proof": "The DNSKEY or DS to validate the first signature against.",
          "input": "A list of RRSets and signatures forming a chain of trust from an existing known-good record."
        },
        "returns": {
          "_0": "The last RRSET submitted."
        }
      }
    },
    "version": 1
  },
  "userdoc": {
    "kind": "user",
    "methods": {},
    "version": 1
  },
  "storageLayout": {
    "storage": [
      {
        "astId": 2402,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "anchors",
        "offset": 0,
        "slot": "0",
        "type": "t_bytes_storage"
      },
      {
        "astId": 4242,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "owner",
        "offset": 0,
        "slot": "1",
        "type": "t_address"
      },
      {
        "astId": 2567,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "rrsets",
        "offset": 0,
        "slot": "2",
        "type": "t_mapping(t_bytes32,t_mapping(t_uint16,t_struct(RRSet)2560_storage))"
      },
      {
        "astId": 2572,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "algorithms",
        "offset": 0,
        "slot": "3",
        "type": "t_mapping(t_uint8,t_contract(Algorithm)5633)"
      },
      {
        "astId": 2577,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "digests",
        "offset": 0,
        "slot": "4",
        "type": "t_mapping(t_uint8,t_contract(Digest)5647)"
      },
      {
        "astId": 2582,
        "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
        "label": "nsec3Digests",
        "offset": 0,
        "slot": "5",
        "type": "t_mapping(t_uint8,t_contract(NSEC3Digest)5663)"
      }
    ],
    "types": {
      "t_address": {
        "encoding": "inplace",
        "label": "address",
        "numberOfBytes": "20"
      },
      "t_bytes20": {
        "encoding": "inplace",
        "label": "bytes20",
        "numberOfBytes": "20"
      },
      "t_bytes32": {
        "encoding": "inplace",
        "label": "bytes32",
        "numberOfBytes": "32"
      },
      "t_bytes_storage": {
        "encoding": "bytes",
        "label": "bytes",
        "numberOfBytes": "32"
      },
      "t_contract(Algorithm)5633": {
        "encoding": "inplace",
        "label": "contract Algorithm",
        "numberOfBytes": "20"
      },
      "t_contract(Digest)5647": {
        "encoding": "inplace",
        "label": "contract Digest",
        "numberOfBytes": "20"
      },
      "t_contract(NSEC3Digest)5663": {
        "encoding": "inplace",
        "label": "contract NSEC3Digest",
        "numberOfBytes": "20"
      },
      "t_mapping(t_bytes32,t_mapping(t_uint16,t_struct(RRSet)2560_storage))": {
        "encoding": "mapping",
        "key": "t_bytes32",
        "label": "mapping(bytes32 => mapping(uint16 => struct DNSSECImpl.RRSet))",
        "numberOfBytes": "32",
        "value": "t_mapping(t_uint16,t_struct(RRSet)2560_storage)"
      },
      "t_mapping(t_uint16,t_struct(RRSet)2560_storage)": {
        "encoding": "mapping",
        "key": "t_uint16",
        "label": "mapping(uint16 => struct DNSSECImpl.RRSet)",
        "numberOfBytes": "32",
        "value": "t_struct(RRSet)2560_storage"
      },
      "t_mapping(t_uint8,t_contract(Algorithm)5633)": {
        "encoding": "mapping",
        "key": "t_uint8",
        "label": "mapping(uint8 => contract Algorithm)",
        "numberOfBytes": "32",
        "value": "t_contract(Algorithm)5633"
      },
      "t_mapping(t_uint8,t_contract(Digest)5647)": {
        "encoding": "mapping",
        "key": "t_uint8",
        "label": "mapping(uint8 => contract Digest)",
        "numberOfBytes": "32",
        "value": "t_contract(Digest)5647"
      },
      "t_mapping(t_uint8,t_contract(NSEC3Digest)5663)": {
        "encoding": "mapping",
        "key": "t_uint8",
        "label": "mapping(uint8 => contract NSEC3Digest)",
        "numberOfBytes": "32",
        "value": "t_contract(NSEC3Digest)5663"
      },
      "t_struct(RRSet)2560_storage": {
        "encoding": "inplace",
        "label": "struct DNSSECImpl.RRSet",
        "members": [
          {
            "astId": 2555,
            "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
            "label": "inception",
            "offset": 0,
            "slot": "0",
            "type": "t_uint32"
          },
          {
            "astId": 2557,
            "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
            "label": "expiration",
            "offset": 4,
            "slot": "0",
            "type": "t_uint32"
          },
          {
            "astId": 2559,
            "contract": "contracts/dnssec-oracle/DNSSECImpl.sol:DNSSECImpl",
            "label": "hash",
            "offset": 8,
            "slot": "0",
            "type": "t_bytes20"
          }
        ],
        "numberOfBytes": "32"
      },
      "t_uint16": {
        "encoding": "inplace",
        "label": "uint16",
        "numberOfBytes": "2"
      },
      "t_uint32": {
        "encoding": "inplace",
        "label": "uint32",
        "numberOfBytes": "4"
      },
      "t_uint8": {
        "encoding": "inplace",
        "label": "uint8",
        "numberOfBytes": "1"
      }
    }
  }
}