From 0958e8ffb2f84beeba694ae1480c981fdc909336 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Wed, 17 Apr 2024 22:21:53 +0000 Subject: [PATCH] Initial commit --- .github/funding.yml | 1 + .github/workflows/nodejs.yml | 23 ++ .github/workflows/publish-npm.yml | 23 ++ .gitignore | 5 + LICENSE | 21 ++ README.md | 186 +++++++++++ lib/esm/package.json | 10 + package-lock.json | 188 +++++++++++ package.json | 39 +++ src/cbor.ts | 287 +++++++++++++++++ src/cli.ts | 383 ++++++++++++++++++++++ src/index.ts | 280 +++++++++++++++++ src/package.json | 3 + test/cbor.test.js | 435 +++++++++++++++++++++++++ test/cli.test.js | 34 ++ test/fixtures/ordinals.json | 57 ++++ test/index.test.js | 7 + test/ordinals.test.js | 505 ++++++++++++++++++++++++++++++ test/package.json | 1 + tsconfig.esm.json | 8 + tsconfig.json | 8 + 21 files changed, 2504 insertions(+) create mode 100644 .github/funding.yml create mode 100644 .github/workflows/nodejs.yml create mode 100644 .github/workflows/publish-npm.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 lib/esm/package.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/cbor.ts create mode 100644 src/cli.ts create mode 100644 src/index.ts create mode 100644 src/package.json create mode 100644 test/cbor.test.js create mode 100644 test/cli.test.js create mode 100644 test/fixtures/ordinals.json create mode 100644 test/index.test.js create mode 100644 test/ordinals.test.js create mode 100644 test/package.json create mode 100644 tsconfig.esm.json create mode 100644 tsconfig.json diff --git a/.github/funding.yml b/.github/funding.yml new file mode 100644 index 0000000..09d9be7 --- /dev/null +++ b/.github/funding.yml @@ -0,0 +1 @@ +github: paulmillr diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 0000000..81bf353 --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,23 @@ +name: Run node.js tests +on: + - push + - pull_request +jobs: + test: + name: v${{ matrix.node }} @ ubuntu-latest + runs-on: ubuntu-latest + strategy: + matrix: + node: + - 18 + - 20 + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: ${{ matrix.node }} + - run: npm install + - run: npm run build --if-present + - run: npm test + - run: npm run lint --if-present diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml new file mode 100644 index 0000000..cd57db8 --- /dev/null +++ b/.github/workflows/publish-npm.yml @@ -0,0 +1,23 @@ +name: Publish package to npm +on: + release: + types: [created] +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: 20 + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm install -g npm + - run: npm ci + - run: npm run build + - run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5985948 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules +/build/micro-eth-signer.js +/lib +/index.js +/index.d.ts \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3433c63 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 Paul Miller (https://paulmillr.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3220830 --- /dev/null +++ b/README.md @@ -0,0 +1,186 @@ +# micro-ordinals + +Minimal JS library for [ordinals](https://ordinals.com) and inscriptions on top of +[scure-btc-signer](https://github.com/paulmillr/scure-btc-signer). + +Use it as a library in your JS code, or run an included CLI tool. +Inscriptions allow uploading random files on BTC blockchain. + +**Experimental:** can lead to loss of funds until tested thoroughly. + +## Usage + +> npm install micro-ordinals + +- [Creating inscription](#creating-inscription) +- [TypeScript API](#typescript-api) +- [CLI](#cli) + +### Creating inscription + +```js +// npm install micro-ordinals @scure/btc-signer @scure/base +import * as btc from '@scure/btc-signer'; +import * as ordinals from 'micro-ordinals'; +import { hex, utf8 } from '@scure/base'; + +const TESTNET = btc.utils.TEST_NETWORK; +const privKey = hex.decode('0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a'); +const pubKey = btc.utils.pubSchnorr(privKey); +const customScripts = [ordinals.OutOrdinalReveal]; // Enable custom scripts outside + +// This inscribes on first satoshi of first input (default) +const inscription = { + tags: { + contentType: 'application/json', // can be any format (MIME type) + // ContentEncoding: 'br', // compression: only brotli supported + }, + body: utf8.decode(JSON.stringify({ some: 1, test: 2, inscription: true, in: 'json' })), + // One can use previously inscribed js scripts in html + // utf8.decode(`test`) +}; + +const revealPayment = btc.p2tr( + undefined, // internalPubKey + ordinals.p2tr_ord_reveal(pubKey, [inscription]), // TaprootScriptTree + TESTNET, // mainnet or testnet + false, // allowUnknownOutputs, safety feature + customScripts // how to handle custom scripts +); + +// We need to send some bitcoins to this address before reveal. +// Also, there should be enough to cover reveal tx fee. +console.log('Address', revealPayment.address); // 'tb1p5mykwcq5ly7y2ctph9r2wfgldq94eccm2t83dd58k785p0zqzwkspyjkp5' + +// Be extra careful: it's possible to accidentally send an inscription as a fee. +// Also, rarity is only available with ordinal wallet. +// But you can parse other inscriptions and create a common one using this. +const changeAddr = revealPayment.address; // can be different +const revealAmount = 2000n; +const fee = 500n; + +const tx = new btc.Transaction({ customScripts }); +tx.addInput({ + ...revealPayment, + // This is txid of tx with bitcoins we sent (replace) + txid: '75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858', + index: 0, + witnessUtxo: { script: revealPayment.script, amount: revealAmount }, +}); +tx.addOutputAddress(changeAddr, revealAmount - fee, TESTNET); +tx.sign(privKey, undefined, new Uint8Array(32)); +tx.finalize(); + +const txHex = hex.encode(tx.extract()); +console.log(txHex); // Hex of reveal tx to broadcast +const tx2 = btc.Transaction.fromRaw(hex.decode(txHex)); // Parsing inscriptions +console.log('parsed', ordinals.parseWitness(tx2.inputs[0].finalScriptWitness)); +console.log('vsize', tx2.vsize); // Reveal tx should pay at least this much fee +``` + +### TypeScript API + +```ts +import { Coder } from '@scure/base'; +import * as P from 'micro-packed'; +import { ScriptType, OptScript, CustomScript } from '@scure/btc-signer'; +type Bytes = Uint8Array; +export declare const InscriptionId: P.Coder; +type TagRaw = { + tag: Bytes; + data: Bytes; +}; +declare const TagCoders: { + pointer: P.CoderType; + contentType: P.CoderType; + parent: P.Coder; + metadata: P.CoderType; + metaprotocol: P.CoderType; + contentEncoding: P.CoderType; + delegate: P.Coder; + rune: P.CoderType; + note: P.CoderType; +}; +export type Tags = Partial<{ + [K in keyof typeof TagCoders]: P.UnwrapCoder<(typeof TagCoders)[K]>; +}> & { + unknown?: [Bytes, Bytes][]; +}; +export type Inscription = { tags: Tags; body: Bytes; cursed?: boolean; }; +type OutOrdinalRevealType = { type: 'tr_ord_reveal'; pubkey: Bytes; inscriptions: Inscription[]; }; +export declare const OutOrdinalReveal: Coder & CustomScript; +export declare function parseInscriptions(script: ScriptType, strict?: boolean): Inscription[] | undefined; +/** + * Parse inscriptions from reveal tx input witness (tx.inputs[0].finalScriptWitness) + */ +export declare function parseWitness(witness: Bytes[]): Inscription[] | undefined; +/** + * Create reveal transaction. Inscription created on spending output from this address by + * revealing taproot script. + */ +export declare function p2tr_ord_reveal(pubkey: Bytes, inscriptions: Inscription[]): { + type: string; + script: Uint8Array; +}; +``` + +### CLI + +> npm install -g micro-ordinals +> ord file.jpg + +Usage: ord [--net mainnet|testnet] [--priv key] [--recovery key] [--compress=on|off] [--fee 10.1] [--addr address] + +- net: bitcoin network +- priv: taproot private key in WIF format, will be used for reveal transaction + Don't use your wallet, priv should be a new one. + We generate a temporary key, if none is provided +- recovery: taproot private key in WIF format, can be used to recover any bitcoins + sent to inscription address by accident without paying full inscription fee. +- compress: inscriptions compressed with brotli. + Compatible with explorers. default=on +- fee: bitcoin network fee in satoshis +- addr: address where inscription will be sent after reveal +Important: first sat is always inscribed. Batch inscriptions are not supported. + +## Design + +There is no network code. It makes package safer, but decreases developer experience. + +We can probably fetch fees automatically, but utxo selection would become more complex. +For example if user previously inscribed something or has rare ordinals, +we need access to ordinal node to know that. Also, we don't know anything +about frozen outputs in wallet: it is inside of a wallet only. + +Edge cases to keep in mind: + +1. user added wrong txid/index or quit application after sending + - we print temporary private key, user can restart by providing it with '--priv' + - as long fee/network/path is same, you can restart process +2. user sent less than amount or multiple UTXO. + - this is actually harder, because any spend will require full inscription fee + - for this we add `recovery` + +## Testing + +### Exporers + +Use [mempool](https://mempool.space/testnet) and +[ordinalsbot](https://testnet-explorer.ordinalsbot.com). + +### Getting testnet coins + +There are several faucets: +[uo1](https://bitcoinfaucet.uo1.net/send.php), +[eu](https://coinfaucet.eu/en/btc-testnet/), +[pump](https://cryptopump.info/send.php) + +### 3rd-party wallets + +To use [sparrow](https://sparrowwallet.com) on mac: + + open /Applications/Sparrow.app --args -n testnet + +## License + +MIT (c) Paul Miller [(https://paulmillr.com)](https://paulmillr.com), see LICENSE file. diff --git a/lib/esm/package.json b/lib/esm/package.json new file mode 100644 index 0000000..f42e46b --- /dev/null +++ b/lib/esm/package.json @@ -0,0 +1,10 @@ +{ + "type": "module", + "sideEffects": false, + "browser": { + "node:crypto": false + }, + "node": { + "./crypto": "./esm/cryptoNode.js" + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..48c89fa --- /dev/null +++ b/package-lock.json @@ -0,0 +1,188 @@ +{ + "name": "micro-ordinals", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "micro-ordinals", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@scure/base": "1.1.6", + "@scure/btc-signer": "1.3.0", + "enquirer": "2.4.1", + "micro-packed": "0.5.3" + }, + "bin": { + "ord": "lib/esm/cli.js" + }, + "devDependencies": { + "@paulmillr/jsbt": "0.1.0", + "@types/node": "20.12.7", + "micro-bmark": "0.3.1", + "micro-should": "0.4.0", + "prettier": "3.1.1", + "typescript": "5.3.2" + } + }, + "node_modules/@noble/curves": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", + "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@paulmillr/jsbt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@paulmillr/jsbt/-/jsbt-0.1.0.tgz", + "integrity": "sha512-TdowoHD36hkZARv6LW4jenkVTdK2vP0sy4ZM8E9MxaqAAIRdwmn3RlB+zWkEHi4hKTgLqMGkURfNkFtt0STX2Q==", + "dev": true, + "bin": { + "jsbt": "jsbt.js" + } + }, + "node_modules/@scure/base": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", + "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/btc-signer": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/btc-signer/-/btc-signer-1.3.0.tgz", + "integrity": "sha512-/0cxVHDy+gsiEbZGa5wcZMK/oZ0YxSVUqnqUF9dGZFC/rhjE5Q3V94Yg0TusP3dxG4YLKZ7m9LYnqccLzMapDA==", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6", + "micro-packed": "~0.5.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@types/node": { + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micro-bmark": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/micro-bmark/-/micro-bmark-0.3.1.tgz", + "integrity": "sha512-bNaKObD4yPAAPrpEqp5jO6LJ2sEFgLoFSmRjEY809mJ62+2AehI/K3+RlVpN3Oo92RHpgC2RQhj6b1Tb4dmo+w==", + "dev": true + }, + "node_modules/micro-packed": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.5.3.tgz", + "integrity": "sha512-zWRoH+qUb/ZMp9gVZhexvRGCENDM5HEQF4sflqpdilUHWK2/zKR7/MT8GBctnTwbhNJwy1iuk5q6+TYP7/twYA==", + "dependencies": { + "@scure/base": "~1.1.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/micro-should": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/micro-should/-/micro-should-0.4.0.tgz", + "integrity": "sha512-Vclj8yrngSYc9Y3dL2C+AdUlTkyx/syWc4R7LYfk4h7+icfF0DoUBGjjUIaEDzZA19RzoI+Hg8rW9IRoNGP0tQ==", + "dev": true + }, + "node_modules/prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/typescript": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..986b43b --- /dev/null +++ b/package.json @@ -0,0 +1,39 @@ +{ + "name": "micro-ordinals", + "version": "0.1.0", + "description": "Manage ordinals, inscriptions and runes using scure-btc-signer", + "bin": { + "ord": "lib/esm/cli.js" + }, + "main": "lib/index.js", + "module": "lib/esm/index.js", + "types": "lib/index.d.ts", + "dependencies": { + "@scure/base": "1.1.6", + "@scure/btc-signer": "1.3.0", + "enquirer": "2.4.1", + "micro-packed": "0.5.3" + }, + "devDependencies": { + "@paulmillr/jsbt": "0.1.0", + "@types/node": "20.12.7", + "micro-bmark": "0.3.1", + "micro-should": "0.4.0", + "prettier": "3.1.1", + "typescript": "5.3.2" + }, + "scripts": { + "build": "tsc && tsc -p tsconfig.esm.json", + "build:release": "cd build; npm run build:release", + "lint": "prettier --print-width 100 --single-quote --check src", + "format": "prettier --print-width 100 --single-quote --write src", + "test": "node test/index.test.js" + }, + "keywords": [], + "author": "Paul Miller (https://paulmillr.com)", + "repository": { + "type": "git", + "url": "git+https://github.com/paulmillr/micro-ordinals.git" + }, + "license": "MIT" +} diff --git a/src/cbor.ts b/src/cbor.ts new file mode 100644 index 0000000..b35ed33 --- /dev/null +++ b/src/cbor.ts @@ -0,0 +1,287 @@ +import * as P from 'micro-packed'; +import { utils } from '@scure/btc-signer'; + +type Bytes = Uint8Array; + +// Binary JSON-like encoding: [RFC 7049](https://www.rfc-editor.org/rfc/rfc7049) +// And partially [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html): without tagged values. +// Used for metadata encoding in ordinals and passkeys. Complex, but efficient encoding. + +const isNegZero = (x: number) => x === 0 && 1 / x < 0; + +// Float16Array is not available in JS as per Apr 2024. +// For now, we implement it using RFC 8949 like technique, +// while preserving Infinity and NaN. f32 rounding would be too slow. +// https://github.com/tc39/proposal-float16array +const F16BE = P.wrap({ + encodeStream(w, value: number) { + // We simple encode popular values as bytes + if (value === Infinity) return w.bytes(new Uint8Array([0x7c, 0x00])); + if (value === -Infinity) return w.bytes(new Uint8Array([0xfc, 0x00])); + if (Number.isNaN(value)) return w.bytes(new Uint8Array([0x7e, 0x00])); + if (isNegZero(value)) return w.bytes(new Uint8Array([0x80, 0x00])); + throw w.err('f16: not implemented'); + }, + decodeStream: (r) => { + // decode_half from RFC 8949 + const half = P.U16BE.decodeStream(r); + const exp = (half & 0x7c00) >> 10; + const mant = half & 0x03ff; + let val: number; + if (exp === 0) val = 6.103515625e-5 * (mant / 1024); + else if (exp !== 31) val = Math.pow(2, exp - 15) * (1 + mant / 1024); + else val = mant ? NaN : Infinity; + return half & 0x8000 ? -val : val; + }, +}); + +const createView = (arr: Uint8Array) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength); + +const f32 = (le?: boolean) => + P.wrap({ + encodeStream(w, value: number) { + if (Math.fround(value) !== value) throw w.err(`f32: wrong value=${value}`); + const buf = new Uint8Array(4); + createView(buf).setFloat32(0, value, le); + w.bytes(buf); + }, + decodeStream: (r) => createView(r.bytes(4)).getFloat32(0, le), + }); + +const f64 = (le?: boolean) => + P.wrap({ + encodeStream(w, value: number) { + // no validation, any JS number can be encoded as float64 + const buf = new Uint8Array(8); + createView(buf).setFloat64(0, value, le); + w.bytes(buf); + }, + decodeStream: (r) => createView(r.bytes(8)).getFloat64(0, le), + }); + +const F32BE = /* @__PURE__ */ f32(false); // const F32LE = /* @__PURE__ */ f32(true); +const F64BE = /* @__PURE__ */ f64(false); // const F64LE = /* @__PURE__ */ f64(true); + +const INFO = P.bits(5); // additional info +const U64LEN = P.apply(P.U64BE, P.coders.number); + +// Number/lengths limits +const CBOR_LIMITS: Record< + number, + [number | bigint, P.CoderType | P.CoderType, P.CoderType] +> = { + 24: [2 ** 8 - 1, P.U8, P.U8], + 25: [2 ** 16 - 1, P.U16BE, P.U16BE], + 26: [2 ** 32 - 1, P.U32BE, P.U32BE], + 27: [2n ** 64n - 1n, P.U64BE, U64LEN], +}; + +const cborUint = P.wrap({ + encodeStream(w, value: number | bigint) { + if (value < 24) return INFO.encodeStream(w, typeof value === 'bigint' ? Number(value) : value); + for (const ai in CBOR_LIMITS) { + const [limit, intCoder, _] = CBOR_LIMITS[ai]; + if (value > limit) continue; + INFO.encodeStream(w, Number(ai)); + return (intCoder.encodeStream as any)(w, value); + } + throw w.err(`cbor/uint: wrong value=${value}`); + }, + decodeStream(r) { + const ai = INFO.decodeStream(r); + if (ai < 24) return ai; + const intCoder = CBOR_LIMITS[ai][1]; + if (!intCoder) throw r.err(`cbor/uint wrong additional information=${ai}`); + return intCoder.decodeStream(r); + }, +}); + +const cborNegint = P.wrap({ + encodeStream: (w, v: number | bigint) => + cborUint.encodeStream(w, typeof v === 'bigint' ? -(v + 1n) : -(v + 1)), + decodeStream(r) { + const v = cborUint.decodeStream(r); + return typeof v === 'bigint' ? -1n - v : -1 - v; + }, +}); + +const cborArrLength = (inner: P.CoderType): P.CoderType => + P.wrap({ + encodeStream(w, value: T[]) { + if (value.length < 24) { + INFO.encodeStream(w, value.length); + P.array(value.length, inner).encodeStream(w, value); + return; + } + for (const ai in CBOR_LIMITS) { + const [limit, _, lenCoder] = CBOR_LIMITS[ai]; + if (value.length < limit) { + INFO.encodeStream(w, Number(ai)); + P.array(lenCoder, inner).encodeStream(w, value); + return; + } + } + throw w.err(`cbor/lengthArray: wrong value=${value}`); + }, + decodeStream(r): T[] { + const ai = INFO.decodeStream(r); + if (ai < 24) return P.array(ai, inner).decodeStream(r); + // array can have indefinite-length + if (ai === 31) return P.array(new Uint8Array([0xff]), inner).decodeStream(r); + const lenCoder = CBOR_LIMITS[ai][2]; + if (!lenCoder) throw r.err(`cbor/lengthArray wrong length=${ai}`); + return P.array(lenCoder, inner).decodeStream(r); + }, + }); + +// for strings/bytestrings +const cborLength = ( + fn: (len: P.Length) => P.CoderType, + // Indefinity-length strings accept other elements with different types, we validate that later + def: P.CoderType, +): P.CoderType => + P.wrap({ + encodeStream(w, value: T | T[]) { + if (Array.isArray(value)) + throw new Error('cbor/length: encoding indefinite-length strings not supported'); + const bytes = fn(null).encode(value); + if (bytes.length < 24) { + INFO.encodeStream(w, bytes.length); + w.bytes(bytes); + return; + } + for (const ai in CBOR_LIMITS) { + const [limit, _, lenCoder] = CBOR_LIMITS[ai]; + if (bytes.length < limit) { + INFO.encodeStream(w, Number(ai)); + lenCoder.encodeStream(w, bytes.length); + w.bytes(bytes); + return; + } + } + throw w.err(`cbor/lengthArray: wrong value=${value}`); + }, + decodeStream(r): T | T[] { + const ai = INFO.decodeStream(r); + if (ai < 24) return fn(ai).decodeStream(r); + if (ai === 31) return P.array(new Uint8Array([0xff]), def).decodeStream(r); + const lenCoder = CBOR_LIMITS[ai][2]; + if (!lenCoder) throw r.err(`cbor/length wrong length=${ai}`); + return fn(lenCoder).decodeStream(r); + }, + }); + +const cborSimple: P.CoderType = P.wrap({ + encodeStream(w, value) { + if (value === false) return INFO.encodeStream(w, 20); + if (value === true) return INFO.encodeStream(w, 21); + if (value === null) return INFO.encodeStream(w, 22); + if (value === undefined) return INFO.encodeStream(w, 23); + if (typeof value !== 'number') throw w.err(`cbor/simple: wrong value type=${typeof value}`); + // Basic values encoded as f16 + if (isNegZero(value) || Number.isNaN(value) || value === Infinity || value === -Infinity) { + INFO.encodeStream(w, 25); + return F16BE.encodeStream(w, value); + } + // If can be encoded as F32 without rounding + if (Math.fround(value) === value) { + INFO.encodeStream(w, 26); + return F32BE.encodeStream(w, value); + } + INFO.encodeStream(w, 27); + return F64BE.encodeStream(w, value); + }, + decodeStream(r) { + const ai = INFO.decodeStream(r); + if (ai === 20) return false; + if (ai === 21) return true; + if (ai === 22) return null; + if (ai === 23) return undefined; + // ai === 24 is P.U8 with simple, reserved + if (ai === 25) return F16BE.decodeStream(r); + if (ai === 26) return F32BE.decodeStream(r); + if (ai === 27) return F64BE.decodeStream(r); + throw r.err('cbor/simple: unassigned'); + }, +}); + +export type CborValue = + | { TAG: 'uint'; data: number | bigint } + | { TAG: 'negint'; data: number | bigint } + | { TAG: 'simple'; data: boolean | null | undefined | number } + | { TAG: 'string'; data: string } + | { TAG: 'bytes'; data: Bytes } + | { TAG: 'array'; data: CborValue[] } + | { TAG: 'map'; data: [CborValue][] } + | { TAG: 'tag'; data: [CborValue, CborValue] }; + +const cborValue: P.CoderType = P.mappedTag(P.bits(3), { + uint: [0, cborUint], // An unsigned integer in the range 0..264-1 inclusive. + negint: [1, cborNegint], // A negative integer in the range -264..-1 inclusive + bytes: [2, P.lazy(() => cborLength(P.bytes, cborValue))], // A byte string. + string: [3, P.lazy(() => cborLength(P.string, cborValue))], // A text string (utf8) + array: [4, cborArrLength(P.lazy(() => cborValue))], // An array of data items + map: [5, P.lazy(() => cborArrLength(P.tuple([cborValue, cborValue])))], // A map of pairs of data items + tag: [6, P.tuple([cborUint, P.lazy(() => cborValue)] as const)], // A tagged data item ("tag") whose tag number + simple: [7, cborSimple], // Floating-point numbers and simple values, as well as the "break" stop code +}); + +export const CBOR = P.apply(cborValue, { + encode(from: CborValue): any { + let value = from.data; + if (from.TAG === 'bytes') { + if (utils.isBytes(value)) return value; + const chunks = []; + if (!Array.isArray(value)) + throw new Error(`CBOR: wrong indefinite-length bytestring=${value}`); + for (const c of value as any) { + if (c.TAG !== 'bytes' || !utils.isBytes(c.data)) + throw new Error(`CBOR: wrong indefinite-length bytestring=${c}`); + chunks.push(c.data); + } + return utils.concatBytes(...chunks); + } + if (from.TAG === 'string') { + if (typeof value === 'string') return value; + if (!Array.isArray(value)) throw new Error(`CBOR: wrong indefinite-length string=${value}`); + let res = ''; + for (const c of value as any) { + if (c.TAG !== 'string' || typeof c.data !== 'string') + throw new Error(`CBOR: wrong indefinite-length string=${c}`); + res += c.data; + } + return res; + } + if (from.TAG === 'array' && Array.isArray(value)) value = value.map((i: any) => this.encode(i)); + if (from.TAG === 'map' && typeof value === 'object' && value !== null) { + return Object.fromEntries( + (from.data as any).map(([k, v]: [any, any]) => [this.encode(k), this.encode(v)]), + ); + } + if (from.TAG === 'tag') throw new Error('not implemented'); + return value; + }, + decode(data: any): any { + if (typeof data === 'bigint') { + return data < 0n ? { TAG: 'negint', data } : { TAG: 'uint', data }; + } + if (typeof data === 'string') return { TAG: 'string', data }; + if (utils.isBytes(data)) return { TAG: 'bytes', data }; + if (Array.isArray(data)) return { TAG: 'array', data: data.map((i) => this.decode(i)) }; + if (typeof data === 'number' && Number.isSafeInteger(data) && !isNegZero(data)) { + return data < 0 ? { TAG: 'negint', data } : { TAG: 'uint', data }; + } + if ( + typeof data === 'boolean' || + typeof data === 'number' || + data === null || + data === undefined + ) { + return { TAG: 'simple', data: data }; + } + if (typeof data === 'object') { + return { TAG: 'map', data: Object.entries(data).map((kv) => kv.map((i) => this.decode(i))) }; + } + throw new Error('unknown type'); + }, +}); diff --git a/src/cli.ts b/src/cli.ts new file mode 100644 index 0000000..424d9a2 --- /dev/null +++ b/src/cli.ts @@ -0,0 +1,383 @@ +#!/usr/bin/env node +import { constants as zlibc, brotliCompressSync } from 'node:zlib'; +import { extname } from 'node:path'; +import { lstatSync, realpathSync, readFileSync } from 'node:fs'; + +// @ts-ignore +import Input from 'enquirer/lib/prompts/input.js'; +// @ts-ignore +import Select from 'enquirer/lib/prompts/select.js'; +import { hex } from '@scure/base'; +import { + Address, + Decimal, + Transaction, + WIF, + p2tr, + NETWORK, + TEST_NETWORK, + utils, +} from '@scure/btc-signer'; +import { Inscription, OutOrdinalReveal, p2tr_ord_reveal } from './index.js'; +/* + +*/ + +const { BROTLI_MODE_GENERIC: B_GENR, BROTLI_MODE_TEXT: B_TEXT, BROTLI_MODE_FONT } = zlibc; +// Max script limit. +// Bitcoin core node won't relay transaction with bigger limit, even if they possible. +// https://github.com/bitcoin/bitcoin/blob/d908877c4774c2456eed09167a5f382758e4a8a6/src/policy/policy.h#L26-L27 +const MAX_STANDARD_TX_WEIGHT = 400000; // 4 * 100kvb +const DUST_RELAY_TX_FEE = 3000n; // won't relay if less than this in fees? +const customScripts = [OutOrdinalReveal]; +const ZERO_32B = '00'.repeat(32); + +// Utils +type Opts = Record; +export function splitArgs(args: string[]): { args: string[]; opts: Opts } { + const _args: string[] = []; + const opts: Opts = {}; + for (let i = 0; i < args.length; i++) { + const cur = args[i]; + if (cur.startsWith('--')) { + if (i + 1 >= args.length) throw new Error(`arguments: no value for ${cur}`); + const next = args[++i]; + if (next.startsWith('--')) throw new Error(`arguments: no value for ${cur}, got ${next}`); + opts[cur.slice(2)] = next; + continue; + } + _args.push(cur); + } + return { args: _args, opts }; +} + +const validateFloat = (s: string) => { + const n = Number.parseFloat(s); + const matches = n.toString() === s && Number.isFinite(n) && n > 0; + return matches || `Number must be greater than zero`; +}; + +const validateTxid = (s: string) => { + try { + const txid = hex.decode(s); + if (txid.length !== 32) return `wrong length ${txid.length}, expected 32 bytes`; + return true; + } catch (e) { + return `${e}`; + } +}; + +const validateIndex = (s: string) => { + const n = Number.parseInt(s); + // Index is U32LE + const matches = s === `${n}` && Number.isInteger(n) && 0 <= n && n < 2 ** 32; + return matches || `Number must be between 0 and ${2 ** 32}`; +}; + +const validateAmount = (s: string) => { + try { + const n = Decimal.decode(s); + if (n <= 0) return `amount should be bigger than zero`; + return true; + } catch (e) { + return `${e}`; + } +}; + +// /Utils + +// UI +// const underline = '\x1b[4m'; +const bold = '\x1b[1m'; +// const gray = '\x1b[90m'; +const reset = '\x1b[0m'; +const red = '\x1b[31m'; +const green = '\x1b[32m'; +// const yellow = '\x1b[33m'; +const magenta = '\x1b[35m'; + +const HELP_TEXT = ` +- ${bold}net:${reset} bitcoin network +- ${bold}priv:${reset} taproot private key in WIF format, will be used for reveal transaction + Don't use your wallet, priv should be a new one. + We generate a temporary key, if none is provided +- ${bold}recovery:${reset} taproot private key in WIF format, can be used to recover any bitcoins + sent to inscription address by accident without paying full inscription fee. +- ${bold}compress:${reset} inscriptions compressed with brotli. + Compatible with explorers. default=on +- ${bold}fee:${reset} bitcoin network fee in satoshis +- ${bold}addr:${reset} address where inscription will be sent after reveal +${bold}Important:${reset} first sat is always inscribed. Batch inscriptions are not supported. +`; + +type InputValidate = (input: string) => boolean | string | Promise; + +export const select = async (message: string, choices: string[]) => { + try { + return await new Select({ message, choices }).run(); + } catch (e) { + process.exit(); // ctrl+c + } +}; + +export async function input(message: string, validate?: InputValidate) { + let opts: { message: string; validate?: InputValidate } = { message }; + if (validate) opts.validate = validate; + try { + return await new Input(opts).run(); + } catch (e) { + process.exit(); // ctrl+c + } +} + +declare const navigator: any; +const defaultLang = typeof navigator === 'object' ? navigator.language : undefined; +const bfmt = new Intl.NumberFormat(defaultLang, { style: 'unit', unit: 'byte' }); + +const formatBytes = (n: number) => `${magenta}${bfmt.format(n)}${reset}`; +const formatSatoshi = (n: bigint) => + `${magenta}${n}${reset} satoshi (${magenta}${Decimal.encode(n)}${reset} BTC)`; +const formatAddress = (s: string) => `${green}${s}${reset}`; +// /UI + +// We support MIME types, supported by ordinals explorer. +// Other MIME types can be allowed, but won't be displayed there. +// Important: .txt file can actually be .jpg, etc. +// prettier-ignore +const contentTypeTable: [string, number, string[]][] = [ + ["application/cbor", B_GENR, [".cbor"]], + ["application/json", B_TEXT, [".json"]], + ["application/octet-stream", B_GENR, [".bin"]], + ["application/pdf", B_GENR, [".pdf"]], + ["application/pgp-signature", B_TEXT, [".asc"]], + ["application/protobuf", B_GENR, [".binpb"]], + ["application/yaml", B_TEXT, [".yaml", ".yml"]], + ["audio/flac", B_GENR, [".flac"]], + ["audio/mpeg", B_GENR, [".mp3"]], + ["audio/wav", B_GENR, [".wav"]], + ["font/otf", B_GENR, [".otf"]], + ["font/ttf", B_GENR, [".ttf"]], + ["font/woff", B_GENR, [".woff"]], + ["font/woff2", BROTLI_MODE_FONT, [".woff2"]], + ["image/apng", B_GENR, [".apng"]], + ["image/avif", B_GENR, [".avif"]], + ["image/gif", B_GENR, [".gif"]], + ["image/jpeg", B_GENR, [".jpg", ".jpeg"]], + ["image/png", B_GENR, [".png"]], + ["image/svg+xml", B_TEXT, [".svg"]], + ["image/webp", B_GENR, [".webp"]], + ["model/gltf+json", B_TEXT, [".gltf"]], + ["model/gltf-binary", B_GENR, [".glb"]], + ["model/stl", B_GENR, [".stl"]], + ["text/css", B_TEXT, [".css"]], + ["text/html;charset=utf-8", B_TEXT, [".html"]], + ["text/javascript", B_TEXT, [".js"]], + ["text/markdown;charset=utf-8", B_TEXT, [".md"]], + ["text/plain;charset=utf-8", B_TEXT, [".txt"]], + ["text/x-python", B_TEXT, [".py"]], + ["video/mp4", B_GENR, [".mp4"]], + ["video/webm", B_GENR, [".webm"]], +]; + +// Some formats have multiple extensions +const contentType: Map = new Map(); +for (const [type, brotliMode, exts] of contentTypeTable) { + for (const ext of exts) contentType.set(ext, [type, brotliMode]); +} + +const NETWORKS: Record = { + mainnet: { ...NETWORK, name: `${red}mainnet${reset}` }, + testnet: { ...TEST_NETWORK, name: `testnet` }, +}; +type NET = (typeof NETWORKS)[keyof typeof NETWORKS]; + +const usage = (err?: Error | string) => { + if (err) console.error(`${red}ERROR${reset}: ${err}`); + console.log( + `Usage: ${green}ord-cli${reset} [--net ${Object.keys(NETWORKS).join( + '|', + )}] [--priv key] [--recovery key] [--compress=on|off] [--fee 10.1] [--addr address] `, + ); + console.log(HELP_TEXT); + process.exit(); +}; + +async function getNetwork(opts: Opts) { + if (!opts.net) opts.net = await select('Network', ['testnet', 'mainnet']); + const NET = NETWORKS[opts.net]; + if (typeof opts.net !== 'string' || !NET) + return usage(`wrong network ${opts.net}. Expected: ${Object.keys(NETWORKS).join(', ')}`); + console.log(`${bold}Network:${reset} ${NET.name}`); + return NET; +} + +function getKeys(net: NET, opts: Opts) { + const KEYS: Record = { priv: 'Temporary', recovery: 'Recovery' }; + const res: Record = {}; + for (const name in KEYS) { + // We can probably can do taproot tweak, + // but if user provided non-taproot key there would be an error? + // For example user can accidentally provide key for + if (opts[name]) res[name] = WIF(net).decode(opts.priv); + else { + res[name] = utils.randomPrivateKeyBytes(); + console.log(`${KEYS[name]} private key: ${red}${WIF(net).encode(res[name])}${reset}`); + } + if (res[name].length !== 32) { + return usage( + `wrong ${KEYS[name].toLowerCase()} private key, expected 32-bytes, got ${res[name].length}`, + ); + } + } + console.log( + `${bold}Important:${reset} if there is an issue with reveal transaction, you will need these keys to refund sent coins`, + ); + return res as { priv: Uint8Array; recovery: Uint8Array }; +} + +function getInscription(filePath: string, opts: Opts) { + const stat = lstatSync(filePath); + if (!stat.isFile()) return usage(`path is not file "${filePath}"`); + const ext = extname(filePath).toLowerCase(); + const type = contentType.get(ext); + if (!type) throw new Error(`unknown extension "${ext}"`); + const [mime, brotliMode] = type; + const info: string[] = []; + info.push(`mime=${mime}`); + let data = Uint8Array.from(readFileSync(filePath, null)); + let inscription: Inscription = { tags: { contentType: mime }, body: data }; + info.push(`size=${formatBytes(data.length)}`); + if (!opts.compress || opts.compress !== 'off') { + const compressed = brotliCompressSync(data, { + params: { + [zlibc.BROTLI_PARAM_MODE]: brotliMode, + [zlibc.BROTLI_PARAM_QUALITY]: zlibc.BROTLI_MAX_QUALITY, + [zlibc.BROTLI_PARAM_SIZE_HINT]: data.length, + }, + }); + // Very small files can take more space after compression + if (data.length > compressed.length) { + data = compressed; + info.push(`compressed_size=${formatBytes(data.length)}`); + inscription = { tags: { contentType: mime, contentEncoding: 'br' }, body: data }; + } + } else info.push(`${red}uncompressed${reset}`); // notify user that compression disabled + if (data.length > MAX_STANDARD_TX_WEIGHT) + return usage(`File is too big ${data.length}. Limit ${MAX_STANDARD_TX_WEIGHT}`); + console.log(`${bold}File:${reset} ${filePath} (${info.join(', ')})`); + return inscription; +} + +async function getFee(opts: Opts) { + let fee = opts.fee; + if (!fee) fee = await input(`Network fee (in satoshi)`, validateFloat); + if (validateFloat(fee) !== true) return usage(`wrong fee=${fee}`); + return parseFloat(fee); +} + +async function getAddr(net: NET, opts: Opts) { + let address = opts.addr; + const validate = (s: string) => { + try { + Address(net).decode(s); + return true; + } catch (e) { + return `${e}`; + } + }; + if (!address) + address = await input('Change address (where inscription will be sent on reveal)', validate); + if (validate(address) !== true) return usage(`wrong address=${address}`); + return address; +} + +function getPayment(privKey: Uint8Array, recovery: Uint8Array, inscription: Inscription, net: NET) { + const pubKey = utils.pubSchnorr(privKey); + const recoveryPub = utils.pubSchnorr(recovery); + return p2tr(recoveryPub, p2tr_ord_reveal(pubKey, [inscription]), net, false, customScripts); +} + +function getTransaction( + privKey: Uint8Array, + addr: string, + payment: ReturnType, + net: NET, + txid: string, + index: number, + amount: bigint, + fee: bigint, +) { + const tx = new Transaction({ customScripts }); + tx.addInput({ + ...payment, + txid, + index, + witnessUtxo: { script: payment.script, amount }, + }); + tx.addOutputAddress(addr, amount - fee, net); + tx.sign(privKey, undefined, new Uint8Array(32)); + tx.finalize(); + return tx; +} + +async function main() { + try { + const argv = process.argv; + // @ts-ignore + if (import.meta.url !== `file://${realpathSync(argv[1])}`) return; // ESM is broken. + if (argv.length < 3) return usage('Wrong argument count'); // node script file + const { args, opts } = splitArgs(argv.slice(2)); + if (args.length !== 1) return usage(`only single file supported, got ${args.length}`); + const net = await getNetwork(opts); + const inscription = getInscription(args[0], opts); + const { priv, recovery } = getKeys(net, opts); + const fee = await getFee(opts); + const addr = await getAddr(net, opts); + // Actual logic + const payment = getPayment(priv, recovery, inscription, net); + // dummy tx to estimate fees and tx size + const dummyTx = getTransaction(priv, addr, payment, net, ZERO_32B, 0, DUST_RELAY_TX_FEE, 1n); + if (dummyTx.weight >= MAX_STANDARD_TX_WEIGHT) { + return usage( + `File is too big: reveal transaction weight (${dummyTx.weight}) is higher than limit (${MAX_STANDARD_TX_WEIGHT})`, + ); + } + const txFee = BigInt(Math.floor(dummyTx.vsize * fee)); + console.log(`${bold}Fee:${reset} ${formatSatoshi(txFee)}`); + // If output of reveal tx considered dust, it would be hard to spend later, + // real limit is probably lower, but we take bigger value to be sure. + // Making UTXO inscription dust can probably prevent spending as fees, + // but also will prevent moving to different address. + const minAmount = DUST_RELAY_TX_FEE + txFee; + console.log( + `Created. Please send at least ${formatSatoshi(minAmount)} to ${formatAddress( + payment.address!, + )}`, + ); + // Ask for UTXO + console.log('Please enter UTXO information for transaction you sent:'); + // These fields cannot be known before we send tx, + // and to send tx user needs an address of inscription + const txid = await input('Txid', validateTxid); + const index = Number.parseInt(await input('Index', validateIndex)); + const amount = Decimal.decode(await input('Amount', validateAmount)); + // Real reveal transaction + const tx = getTransaction(priv, addr, payment, net, txid, index, amount, txFee); + console.log('Reveal transaction created.'); + console.log(`${bold}Txid:${reset} ${tx.id}`); + console.log(`${bold}Tx:${reset}`); + console.log(hex.encode(tx.extract())); + console.log( + `Please broadcast this transaction to reveal inscription and transfer to your address (${formatAddress( + addr, + )})`, + ); + console.log( + `${bold}Important:${reset} please freeze this UTXO in your wallet when received to avoid sending inscription as fees for other transactions.`, + ); + } catch (e) { + return usage(e as Error); + } +} + +main(); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..bcb063f --- /dev/null +++ b/src/index.ts @@ -0,0 +1,280 @@ +import { Coder, hex, utf8 } from '@scure/base'; +import * as P from 'micro-packed'; +import { + Script, + ScriptType, + OptScript, + CustomScript, + MAX_SCRIPT_BYTE_LENGTH, + utils, +} from '@scure/btc-signer'; +import { CBOR } from './cbor.js'; + +type Bytes = Uint8Array; +const PROTOCOL_ID = /* @__PURE__ */ utf8.decode('ord'); + +function splitChunks(buf: Bytes): Bytes[] { + const res = []; + for (let i = 0; i < buf.length; i += MAX_SCRIPT_BYTE_LENGTH) + res.push(buf.subarray(i, i + MAX_SCRIPT_BYTE_LENGTH)); + return res; +} + +const RawInscriptionId = /* @__PURE__ */ P.tuple([ + P.bytes(32, true), + P.apply(P.bigint(4, true, false, false), P.coders.number), +] as const); + +export const InscriptionId: P.Coder = { + encode(data: string) { + const [txId, index] = data.split('i', 2); + if (`${+index}` !== index) throw new Error(`InscriptionId wrong index: ${index}`); + return RawInscriptionId.encode([hex.decode(txId), +index]); + }, + decode(data: Bytes) { + const [txId, index] = RawInscriptionId.decode(data); + return `${hex.encode(txId)}i${index}`; + }, +}; + +const TagEnum = { + // Would be simpler to have body tag here, + // but body chunks don't have body tag near them + contentType: 1, + pointer: 2, + parent: 3, + metadata: 5, + metaprotocol: 7, + contentEncoding: 9, + delegate: 11, + rune: 13, + note: 15, + // Unrecognized even tag makes inscription unbound + // unbound: 66, + // Odd fields are ignored + // nop: 255, +}; + +const TagCoderInternal = /* @__PURE__ */ P.map(P.U8, TagEnum); +type TagName = keyof typeof TagEnum; +type TagRaw = { tag: Bytes; data: Bytes }; + +const TagCoders = /* @__PURE__ */ { + pointer: P.bigint(8, true, false, false), // U64 + contentType: P.string(null), + parent: InscriptionId, + metadata: CBOR, + metaprotocol: P.string(null), + contentEncoding: P.string(null), + delegate: InscriptionId, + rune: P.bigint(16, true, false, false), // U128 + note: P.string(null), + // unbound: P.bytes(null), + // nop: P.bytes(null), +}; + +export type Tags = Partial<{ + [K in keyof typeof TagCoders]: P.UnwrapCoder<(typeof TagCoders)[K]>; +}> & { + unknown?: [Bytes, Bytes][]; +}; +// We can't use mappedTag here, because tags can be split in chunks +const TagCoder: P.Coder = { + encode(from: TagRaw[]): Tags { + const tmp: Record = {}; + const unknown: [Bytes, Bytes][] = []; + // collect tag parts + for (const { tag, data } of from) { + try { + const tagName = TagCoderInternal.decode(tag); + if (!tmp[tagName]) tmp[tagName] = []; + tmp[tagName].push(data); + } catch (e) { + unknown.push([tag, data]); + } + } + const res: Partial = {}; + if (unknown.length) res.unknown = unknown; + for (const field in tmp) { + if (field === 'parent' && tmp[field].length > 1) { + res[field as TagName] = tmp[field].map((i) => TagCoders.parent.decode(i)); + continue; + } + res[field as TagName] = TagCoders[field as TagName].decode(utils.concatBytes(...tmp[field])); + } + return res as Tags; + }, + decode(to: Tags): TagRaw[] { + const res: TagRaw[] = []; + for (const field in to) { + if (field === 'unknown') continue; + const tagName = TagCoderInternal.encode(field); + if (field === 'parent' && Array.isArray(to.parent)) { + for (const p of to.parent) res.push({ tag: tagName, data: TagCoders.parent.encode(p) }); + continue; + } + const bytes = TagCoders[field as TagName].encode(to[field as TagName]); + for (const data of splitChunks(bytes)) res.push({ tag: tagName, data }); + } + if (to.unknown) { + if (!Array.isArray(to.unknown)) throw new Error('ordinals/TagCoder: unknown should be array'); + for (const [tag, data] of to.unknown) res.push({ tag, data }); + } + return res; + }, +}; + +export type Inscription = { tags: Tags; body: Bytes; cursed?: boolean }; +type OutOrdinalRevealType = { + type: 'tr_ord_reveal'; + pubkey: Bytes; + inscriptions: Inscription[]; +}; + +const parseEnvelopes = (script: ScriptType, pos = 0) => { + if (!Number.isSafeInteger(pos)) throw new Error(`parseInscription: wrong pos=${typeof pos}`); + const envelopes = []; + // Inscriptions with broken parsing are called 'cursed' (stutter or pushnum) + let stutter = false; + main: for (; pos < script.length; pos++) { + const instr = script[pos]; + if (instr !== 0) continue; + if (script[pos + 1] !== 'IF') { + if (script[pos + 1] === 0) stutter = true; + continue main; + } + if (!utils.isBytes(script[pos + 2]) || !P.equalBytes(script[pos + 2] as any, PROTOCOL_ID)) { + if (script[pos + 2] === 0) stutter = true; + continue main; + } + let pushnum = false; + const payload: ScriptType = []; // bytes or 0 + for (let j = pos + 3; j < script.length; j++) { + const op = script[j]; + // done + if (op === 'ENDIF') { + envelopes.push({ start: pos + 3, end: j, pushnum, payload, stutter }); + pos = j; + break; + } + if (op === '1NEGATE') { + pushnum = true; + payload.push(new Uint8Array([0x81])); + continue; + } + if (typeof op === 'number' && 1 <= op && op <= 16) { + pushnum = true; + payload.push(new Uint8Array([op])); + continue; + } + if (utils.isBytes(op) || op === 0) { + payload.push(op); + continue; + } + stutter = false; + break; + } + } + return envelopes; +}; + +// Additional API for parsing inscriptions +export function parseInscriptions(script: ScriptType, strict = false): Inscription[] | undefined { + if (strict && (!utils.isBytes(script[0]) || script[0].length !== 32)) return; + if (strict && script[1] !== 'CHECKSIG') return; + + const envelopes = parseEnvelopes(script); + const inscriptions: Inscription[] = []; + // Check that all inscriptions are sequential inside script + let pos = 5; + for (const envelope of envelopes) { + if (strict && (envelope.stutter || envelope.pushnum)) return; + if (strict && envelope.start !== pos) return; + const { payload } = envelope; + let i = 0; + const tags: TagRaw[] = []; + for (; i < payload.length && payload[i] !== 0; i += 2) { + const tag = payload[i]; + const data = payload[i + 1]; + if (!utils.isBytes(tag)) throw new Error('parseInscription: non-bytes tag'); + if (!utils.isBytes(data)) throw new Error('parseInscription: non-bytes tag data'); + tags.push({ tag, data }); + } + while (payload[i] === 0 && i < payload.length) i++; + + const chunks = []; + for (; i < payload.length; i++) { + if (!utils.isBytes(payload[i])) break; + chunks.push(payload[i] as Bytes); + } + inscriptions.push({ + tags: TagCoder.encode(tags), + body: utils.concatBytes(...chunks), + cursed: envelope.pushnum || envelope.stutter, + }); + pos = envelope.end + 4; + } + if (pos - 3 !== script.length) return; + return inscriptions; +} + +/** + * Parse inscriptions from reveal tx input witness (tx.inputs[0].finalScriptWitness) + */ +export function parseWitness(witness: Bytes[]): Inscription[] | undefined { + if (witness.length !== 3) throw new Error('Wrong witness'); + // We don't validate other parts of witness here since we want to parse + // as much stuff as possible. When creating inscription, it is done more strictly + return parseInscriptions(Script.decode(witness[1])); +} + +export const OutOrdinalReveal: Coder & CustomScript = { + encode(from: ScriptType): OutOrdinalRevealType | undefined { + const res: Partial = { type: 'tr_ord_reveal' }; + try { + res.inscriptions = parseInscriptions(from, true); + res.pubkey = from[0] as Bytes; + } catch (e) { + return; + } + return res as OutOrdinalRevealType; + }, + decode: (to: OutOrdinalRevealType): OptScript => { + if (to.type !== 'tr_ord_reveal') return; + const out: ScriptType = [to.pubkey, 'CHECKSIG']; + for (const { tags, body } of to.inscriptions) { + out.push(0, 'IF', PROTOCOL_ID); + const rawTags = TagCoder.decode(tags); + for (const tag of rawTags) out.push(tag.tag, tag.data); + // Body + out.push(0); + for (const c of splitChunks(body)) out.push(c); + out.push('ENDIF'); + } + return out as any; + }, + finalizeTaproot: (script: any, parsed: any, signatures: any) => { + if (signatures.length !== 1) throw new Error('tr_ord_reveal/finalize: wrong signatures array'); + const [{ pubKey }, sig] = signatures[0]; + if (!P.equalBytes(pubKey, parsed.pubkey)) return; + return [sig, script]; + }, +}; + +/** + * Create reveal transaction. Inscription created on spending output from this address by + * revealing taproot script. + */ +export function p2tr_ord_reveal(pubkey: Bytes, inscriptions: Inscription[]) { + return { + type: 'tr_ord_reveal', + script: P.apply(Script, P.coders.match([OutOrdinalReveal])).encode({ + type: 'tr_ord_reveal', + pubkey, + inscriptions, + }), + }; +} + +// Internal methods for tests +export const __test__ = { TagCoders, TagCoder, parseEnvelopes }; diff --git a/src/package.json b/src/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/src/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/test/cbor.test.js b/test/cbor.test.js new file mode 100644 index 0000000..6e5ce16 --- /dev/null +++ b/test/cbor.test.js @@ -0,0 +1,435 @@ +import { deepStrictEqual, throws } from 'node:assert'; +import { describe, should } from 'micro-should'; +import { hex } from '@scure/base'; +import { CBOR } from '../lib/esm/cbor.js'; + +describe('CBOR', () => { + should('Decode', () => { + const VECTORS = [ + // infinity arrays + [[], '9fff'], + [[[0]], '9f9f00ffff'], + [ + [ + [0, 1], + [2, 3], + ], + '9f9f0001ff9f0203ffff', + ], + [ + [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + ], + '9f9f000102ff9f030405ff9f060708ffff', + ], + // infinity bytes + [ + new Uint8Array([101, 120, 97, 109, 112, 108, 101, 206, 177, 226, 137, 164, 206, 178]), + '5f476578616d706c6547ceb1e289a4ceb2ff', + ], + [new Uint8Array([101, 120, 97, 109, 112, 108, 101]), '5f476578616d706c65ff'], + [new Uint8Array([]), '5fff'], + [new Uint8Array([]), '5f40ff'], + // infinity strings + ['exampleα≤β', '7f676578616d706c6567ceb1e289a4ceb2ff'], + ['example', '7f676578616d706c65ff'], + ['', '7fff'], + ['', '7f60ff'], + // RFC 8949 + [0, '00'], + [1, '01'], + [10, '0a'], + [23, '17'], + [24, '1818'], + [25, '1819'], + [100, '1864'], + [1000, '1903e8'], + [1000000, '1a000f4240'], + [1000000000000n, '1b000000e8d4a51000'], + [18446744073709551615n, '1bffffffffffffffff'], + [-18446744073709551616n, '3bffffffffffffffff'], + [-1, '20'], + [-10, '29'], + [-100, '3863'], + [-1000, '3903e7'], + [0.0, 'f90000'], + [-0.0, 'f98000'], + [1.0, 'f93c00'], + [1.1, 'fb3ff199999999999a'], + [1.5, 'f93e00'], + [65504.0, 'f97bff'], + [100000.0, 'fa47c35000'], + [3.4028234663852886e38, 'fa7f7fffff'], + [1.0e300, 'fb7e37e43c8800759c'], + [5.960464477539063e-8, 'f90001'], + [0.00006103515625, 'f90400'], + [-4.0, 'f9c400'], + [-4.1, 'fbc010666666666666'], + [Infinity, 'f97c00'], + [NaN, 'f97e00'], + [-Infinity, 'f9fc00'], + [Infinity, 'fa7f800000'], + [NaN, 'fa7fc00000'], + [-Infinity, 'faff800000'], + [Infinity, 'fb7ff0000000000000'], + [NaN, 'fb7ff8000000000000'], + [-Infinity, 'fbfff0000000000000'], + [false, 'f4'], + [true, 'f5'], + [null, 'f6'], + [undefined, 'f7'], + [new Uint8Array([]), '40'], + [new Uint8Array([1, 2, 3, 4]), '4401020304'], + ['', '60'], + ['a', '6161'], + ['IETF', '6449455446'], + ['"\\', '62225c'], + ['\u00fc', '62c3bc'], + ['\u6c34', '63e6b0b4'], + ['\ud800\udd51', '64f0908591'], + [[], '80'], + [[1, 2, 3], '83010203'], + [[1, [2, 3], [4, 5]], '8301820203820405'], + [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], + '98190102030405060708090a0b0c0d0e0f101112131415161718181819', + ], + [{}, 'a0'], + [{ 1: 2, 3: 4 }, 'a201020304'], + [{ a: 1, b: [2, 3] }, 'a26161016162820203'], + [['a', { b: 'c' }], '826161a161626163'], + [{ a: 'A', b: 'B', c: 'C', d: 'D', e: 'E' }, 'a56161614161626142616361436164614461656145'], + [new Uint8Array([1, 2, 3, 4, 5]), '5f42010243030405ff'], + ['streaming', '7f657374726561646d696e67ff'], + [[], '9fff'], + [[1, [2, 3], [4, 5]], '9f018202039f0405ffff'], + [[1, [2, 3], [4, 5]], '9f01820203820405ff'], + [[1, [2, 3], [4, 5]], '83018202039f0405ff'], + [[1, [2, 3], [4, 5]], '83019f0203ff820405'], + [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], + '9f0102030405060708090a0b0c0d0e0f101112131415161718181819ff', + ], + [{ a: 1, b: [2, 3] }, 'bf61610161629f0203ffff'], + [['a', { b: 'c' }], '826161bf61626163ff'], + [{ Fun: true, Amt: -2 }, 'bf6346756ef563416d7421ff'], + [0, '00'], + [1, '01'], + [10, '0a'], + [23, '17'], + [24, '1818'], + [25, '1819'], + [100, '1864'], + [1000, '1903e8'], + [1000000, '1a000f4240'], + [1000000000000n, '1b000000e8d4a51000'], + [18446744073709551615n, '1bffffffffffffffff'], + [-18446744073709551616n, '3bffffffffffffffff'], + [-1, '20'], + [-10, '29'], + [-100, '3863'], + [-1000, '3903e7'], + + ['', '60'], + ['a', '6161'], + ['IETF', '6449455446'], + ['"\\', '62225c'], + ['\u00fc', '62c3bc'], + ['\u6c34', '63e6b0b4'], + ['\ud800\udd51', '64f0908591'], + [[], '80'], + [[1, 2, 3], '83010203'], + [[1, [2, 3], [4, 5]], '8301820203820405'], + [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], + '98190102030405060708090a0b0c0d0e0f101112131415161718181819', + ], + [{}, 'a0'], + [{ 1: 2, 3: 4 }, 'a201020304'], + [{ a: 1, b: [2, 3] }, 'a26161016162820203'], + [['a', { b: 'c' }], '826161a161626163'], + [{ a: 'A', b: 'B', c: 'C', d: 'D', e: 'E' }, 'a56161614161626142616361436164614461656145'], + [0.0, 'f90000'], + [-0.0, 'f98000'], + [1.0, 'f93c00'], + [1.1, 'fb3ff199999999999a'], + [1.5, 'f93e00'], + [65504.0, 'f97bff'], + [100000.0, 'fa47c35000'], + [3.4028234663852886e38, 'fa7f7fffff'], + [1.0e300, 'fb7e37e43c8800759c'], + [5.960464477539063e-8, 'f90001'], + [0.00006103515625, 'f90400'], + [-4.0, 'f9c400'], + [-4.1, 'fbc010666666666666'], + [Infinity, 'f97c00'], + [NaN, 'f97e00'], + [-Infinity, 'f9fc00'], + [false, 'f4'], + [true, 'f5'], + [null, 'f6'], + [undefined, 'f7'], + [new Uint8Array(0), '40'], + [new Uint8Array([1, 2, 3, 4]), '4401020304'], + // TAGS + // bigint + //[18446744073709551616, 'c249010000000000000000'], + //[-18446744073709551617, 'c349010000000000000000'], + + // ['', 'f0'], simple(16) + //[simple(16), 'f0'], + //[simple(255), "f8ff"], + //[0("2013-03-21T20:04:00Z"), "c074323031332d30332d32315432303a 30343a30305a"], + //[1(1363896240), "c11a514b67b0"], + //[1(1363896240.5), "c1fb41d452d9ec200000"], + //[23(h'01020304'), "d74401020304"], + //[24(h'6449455446'), "d818456449455446"], + //[32("http://www.example.com"), "d82076687474703a2f2f7777772e6578 616d706c652e636f6d"], + ]; + + for (const [exp, testHex] of VECTORS) { + const decoded = CBOR.decode(hex.decode(testHex)); + deepStrictEqual(exp, decoded); + } + }); + should('Encode', () => { + const VECTORS = [ + // RFC 8949 + [0, '00'], + [1, '01'], + [10, '0a'], + [23, '17'], + [24, '1818'], + [25, '1819'], + [100, '1864'], + [1000, '1903e8'], + [1000000, '1a000f4240'], + [1000000000000n, '1b000000e8d4a51000'], + [18446744073709551615n, '1bffffffffffffffff'], + [-18446744073709551616n, '3bffffffffffffffff'], + [-1, '20'], + [-10, '29'], + [-100, '3863'], + [-1000, '3903e7'], + [-0.0, 'f98000'], + [1.1, 'fb3ff199999999999a'], + // [1.5, 'f93e00'], <- we encode this as f32 instead of f16 + [3.4028234663852886e38, 'fa7f7fffff'], + [1.0e300, 'fb7e37e43c8800759c'], + // [5.960464477539063e-8, 'f90001'], // f16 :( + // [0.00006103515625, 'f90400'], f16 :( + [-4.1, 'fbc010666666666666'], + [Infinity, 'f97c00'], + [NaN, 'f97e00'], + [-Infinity, 'f9fc00'], + [false, 'f4'], + [true, 'f5'], + [null, 'f6'], + [undefined, 'f7'], + [new Uint8Array([]), '40'], + [new Uint8Array([1, 2, 3, 4]), '4401020304'], + ['', '60'], + ['a', '6161'], + ['IETF', '6449455446'], + ['"\\', '62225c'], + ['\u00fc', '62c3bc'], + ['\u6c34', '63e6b0b4'], + ['\ud800\udd51', '64f0908591'], + [[], '80'], + [[1, 2, 3], '83010203'], + [[1, [2, 3], [4, 5]], '8301820203820405'], + [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], + '98190102030405060708090a0b0c0d0e0f101112131415161718181819', + ], + [{}, 'a0'], + [{ a: 1, b: [2, 3] }, 'a26161016162820203'], + [['a', { b: 'c' }], '826161a161626163'], + [{ a: 'A', b: 'B', c: 'C', d: 'D', e: 'E' }, 'a56161614161626142616361436164614461656145'], + [0, '00'], + [1, '01'], + [10, '0a'], + [23, '17'], + [24, '1818'], + [25, '1819'], + [100, '1864'], + [1000, '1903e8'], + [1000000, '1a000f4240'], + [1000000000000n, '1b000000e8d4a51000'], + [18446744073709551615n, '1bffffffffffffffff'], + [-18446744073709551616n, '3bffffffffffffffff'], + [-1, '20'], + [-10, '29'], + [-100, '3863'], + [-1000, '3903e7'], + + ['', '60'], + ['a', '6161'], + ['IETF', '6449455446'], + ['"\\', '62225c'], + ['\u00fc', '62c3bc'], + ['\u6c34', '63e6b0b4'], + ['\ud800\udd51', '64f0908591'], + [[], '80'], + [[1, 2, 3], '83010203'], + [[1, [2, 3], [4, 5]], '8301820203820405'], + [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25], + '98190102030405060708090a0b0c0d0e0f101112131415161718181819', + ], + [{}, 'a0'], + [{ a: 1, b: [2, 3] }, 'a26161016162820203'], + [['a', { b: 'c' }], '826161a161626163'], + [{ a: 'A', b: 'B', c: 'C', d: 'D', e: 'E' }, 'a56161614161626142616361436164614461656145'], + [1.1, 'fb3ff199999999999a'], + [3.4028234663852886e38, 'fa7f7fffff'], + [1.0e300, 'fb7e37e43c8800759c'], + [-4.1, 'fbc010666666666666'], + [Infinity, 'f97c00'], + [NaN, 'f97e00'], + [-Infinity, 'f9fc00'], + [false, 'f4'], + [true, 'f5'], + [null, 'f6'], + [undefined, 'f7'], + [new Uint8Array(0), '40'], + [new Uint8Array([1, 2, 3, 4]), '4401020304'], + // TAGS + //[simple(16), "f0"], + //[simple(255), "f8ff"], + //[0("2013-03-21T20:04:00Z"), "c074323031332d30332d32315432303a 30343a30305a"], + //[1(1363896240), "c11a514b67b0"], + //[1(1363896240.5), "c1fb41d452d9ec200000"], + //[23(h'01020304'), "d74401020304"], + //[24(h'6449455446'), "d818456449455446"], + //[32("http://www.example.com"), "d82076687474703a2f2f7777772e6578 616d706c652e636f6d"], + ]; + + for (const [value, exp] of VECTORS) { + const encoded = hex.encode(CBOR.encode(value)); + deepStrictEqual(encoded, exp); + } + }); + + should('malformed', () => { + const VECTORS = [ + // End of input in a head + '18', + '19', + '1a', + '1b', + '1901', + '1a0102', + '1b01020304050607', + '38', + '58', + '78', + '98', + '9a01ff00', + 'b8', + 'd8', + 'f8', + 'f900', + 'fa0000', + 'fb000000', + // Definite-length strings with short data + '41', + '61', + '5affffffff00', + '5bffffffffffffffff010203', + '7affffffff00', + '7b7fffffffffffffff010203', + // Definite-length maps and arrays not closed with enough items + '81', + '818181818181818181', + '8200', + 'a1', + 'a20102', + 'a100', + 'a2000000', + // Tag number not followed by tag content + 'c0', + // Indefinite-length strings not closed by a "break" stop code + '5f4100', + '7f6100', + // Indefinite-length maps and arrays not closed by a "break" stop code + '9f', + '9f0102', + 'bf', + 'bf01020102', + '819f', + '9f8000', + '9f9f9f9f9fffffffff', + '9f819f819f9fffffff', + // Reserved additional information values + '1c', + '1d', + '1e', + '3c', + '3d', + '3e', + '5c', + '5d', + '5e', + '7c', + '7d', + '7e', + '9c', + '9d', + '9e', + 'bc', + 'bd', + 'be', + 'dc', + 'dd', + 'de', + 'fc', + 'fd', + 'fe', + // Reserved two-byte encodings of simple values + 'f800', + 'f801', + 'f818', + 'f81f', + // Indefinite-length string chunks not of the correct type: + '5f00ff', + '5f21ff', + '5f6100ff', + '5f80ff', + '5fa0ff', + '5fc000ff', + '5fe0ff', + '7f4100ff', + // Indefinite-length string chunks not definite length + '5f5f4100ffff', + '7f7f6100ffff', + // Break occurring on its own outside of an indefinite-length item + 'ff', + // Break occurring in a definite-length array or map or a tag + '81ff', + '8200ff', + 'a1ff', + 'a1ff00', + 'a100ff', + 'a20000ff', + '9f81ff', + '9f829f819f9fffffffff', + // Break in an indefinite-length map that would lead to an odd number of items (break in a value position): + 'bf00ff', + 'bf000000ff', + // Major type 0, 1, 6 with additional information 31 + '1f', + '3f', + 'df', + ]; + for (const v of VECTORS) throws(() => CBOR.decode(hex.decode(v)), v); + }); +}); + +// ESM is broken. +import url from 'url'; +if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { + should.run(); +} diff --git a/test/cli.test.js b/test/cli.test.js new file mode 100644 index 0000000..213a600 --- /dev/null +++ b/test/cli.test.js @@ -0,0 +1,34 @@ +import { describe, should } from 'micro-should'; +import { deepStrictEqual, throws } from 'node:assert'; +import * as cli from '../lib/esm/cli.js'; + +describe('micro-ord-cli', () => { + should('splitArgs', () => { + deepStrictEqual(cli.splitArgs([]), { args: [], opts: {} }); + deepStrictEqual(cli.splitArgs(['file.js']), { args: ['file.js'], opts: {} }); + deepStrictEqual(cli.splitArgs(['--net', 'testnet', 'file.js']), { + args: ['file.js'], + opts: { net: 'testnet' }, + }); + deepStrictEqual(cli.splitArgs(['file.js', '--net', 'testnet']), { + args: ['file.js'], + opts: { net: 'testnet' }, + }); + deepStrictEqual(cli.splitArgs(['--priv', 'test', '--net', 'testnet', 'file.js']), { + args: ['file.js'], + opts: { priv: 'test', net: 'testnet' }, + }); + throws(() => cli.splitArgs(['--priv', '--net', 'testnet', 'file.js'])); + throws(() => cli.splitArgs(['file.js', '--net'])); + }); +}); + +should('Basic', () => { + console.log('TEST?'); +}); + +// ESM is broken. +import url from 'url'; +if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { + should.run(); +} diff --git a/test/fixtures/ordinals.json b/test/fixtures/ordinals.json new file mode 100644 index 0000000..1ae0989 --- /dev/null +++ b/test/fixtures/ordinals.json @@ -0,0 +1,57 @@ +[{ + "title": "inscription/11820782", + "raw_tx": "02000000000101ae57dbfc2e85b8f6a779a964b0ec4d7b456b9f5f31f7a3994bd16ce64da629f30200000000fdffffff012202000000000000225120396c3b320fc349556b70f151ae9919efb1bb90fdd3c19ec3dfafbfb3460bd06c0340d226c8247238d01ef6b71262cdcd9a044b8eaaf5d38cc473d3720b6db4e180aceeeba36b0af4e67977ed7f1d9ebb912d610ef26a05a6123ae8cf0fd13a30191bfd850420117f692257b2331233b5705ce9c682be8719ff1b2b64cbca290bd6faeb54423eac06b18dffb78801750063036f726401010d696d6167652f7376672b786d6c004d08020a3c7376672069643d224f7264694d616e646f526563757273697665222077696474683d223130302522206865696768743d2231303025222076657273696f6e3d22312e31222076696577426f783d223020302036342036342220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737667223e0a202020203c696d61676520687265663d222f636f6e74656e742f3463306262343164663366313939343163333030666562393364383437346639623733313134343232386666336365616533633537356332376537666262336569302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a202020203c696d61676520687265663d222f636f6e74656e742f6431656430316336626462366235643433366365663261633533333038313861663732303964363337613937633830373464643034633535666538626333366169302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a202020203c696d6167652068724d080265663d222f636f6e74656e742f6433396137326164383063643031333164626562366231393062663365336330336463346634306634306266666162373361313663663437623331336238643469302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a202020203c696d61676520687265663d222f636f6e74656e742f3361366465343939326535393965336266663036376135613632396635346662613836386561373433623035636432303137633132373237656432616630666669302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a202020203c696d61676520687265663d222f636f6e74656e742f6432376635633762653162346162346632343462303466353764363966366162393130383563393235353465316437333435393261303135646332663136656269302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c61742c656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a3c2f7376673e0a6821c0117f692257b2331233b5705ce9c682be8719ff1b2b64cbca290bd6faeb54423e00000000", + "body": "0a3c7376672069643d224f7264694d616e646f526563757273697665222077696474683d223130302522206865696768743d2231303025222076657273696f6e3d22312e31222076696577426f783d223020302036342036342220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737667223e0a202020203c696d61676520687265663d222f636f6e74656e742f3463306262343164663366313939343163333030666562393364383437346639623733313134343232386666336365616533633537356332376537666262336569302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a202020203c696d61676520687265663d222f636f6e74656e742f6431656430316336626462366235643433366365663261633533333038313861663732303964363337613937633830373464643034633535666538626333366169302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a202020203c696d61676520687265663d222f636f6e74656e742f6433396137326164383063643031333164626562366231393062663365336330336463346634306634306266666162373361313663663437623331336238643469302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a202020203c696d61676520687265663d222f636f6e74656e742f3361366465343939326535393965336266663036376135613632396635346662613836386561373433623035636432303137633132373237656432616630666669302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a202020203c696d61676520687265663d222f636f6e74656e742f6432376635633762653162346162346632343462303466353764363966366162393130383563393235353465316437333435393261303135646332663136656269302220783d22302220793d2230222077696474683d22363422206865696768743d2236342220696d6167652d72656e646572696e673d22706978656c6174656422207072657365727665417370656374526174696f3d22784d6964594d6964222f3e0a3c2f7376673e0a" + }, + { + "title": "inscription/62115659", + "raw_tx": "020000000001018b751eefd13c87f90c0e01f9a8b88a7caca46be2fabe365aa733b373356eae8b0000000000fdffffff011027000000000000225120a2caee05a7bbadca9e1c13d09f7cbe36a4e0bf412917804a6bc94383c39a0fec03406f719c20dba7c0152f88d73bb58010a589b7add342e73f526a0872b4276bc856908ed20611c0975890056e16675baf921a43c444f1e116af42df76d8c0d3c0a7fddac1205465af30cb735feed149f55056fd9477354d5181567cf2861e387d5fedf70026ac0063036f7264010109696d6167652f676966004d080247494638396190019001f5000017171717171817181917191c161b20161d24151f2815202a15202c15223014233114243413273b14263813283c35393f132a40343a404c4f534c5054606365606367606467606468727374727477727578075aac0080ff929394929496a0a1a2a0a1a3a0a2a3adaeaeadafb0babbbd97cbffd3d3d3d3d3d4d3d4d4dedfdfeaeaeaf4f5f5ffffffaacaffd1e2ff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021ff0b4e45545343415045322e30030100000021f904001e00ff0021fe28474946206372656174656420776974682068747470733a2f2f657a6769662e636f6d2f6d616b6572002c00000000900190010006ff408070482c1a8fc8a4f218683a9fd0a8744aad5205d8ac76cbed7abfe0b0784c2e9bbfd6b47abd5ebadff0b87c4e57b2ef78f579cfeffbff80637983844f758788898a75858d778190919293948e96698b999a9b87979e5094a1a2a3a4629fa7019caaabac42a897a5b1b2b3a2af96adb8b98cb684b4bebfc07ebc84bac5c648c378c1cbcccd61c977c7d2c6d07aced7d8d9d598d3ddabdb55d9e2e3cde054dee899e651e4c003efef5af1edcbeb50e9f8bbf601f4a5f0030200061488059ebc7ff3fa8ddad7249fc337fb144e327890e0c08a5910269c975062a07d0f432233e71190c5811dff154d0802cc685025978d294bfe5927b2e6109232cfb44c49716547ff9f007b6ea12894e3c99ca6c0d914090e699978165dae7c7994ead1a25f343a15b46da9c36d5bb312145ab0e8d5aa43ab9295579167582fd5bce683f636adc6b108a98a81aa950fcc2e7deb668126171dddba6ef3b2fc79b1edddc78fc1fcb5da58f0e06485bb0d7b2b352046c05e208b1e0d797159b56739be1d96591a2fc16bd3ee254dbbb6e8d302272fce8d722bafd6c55ee754dcd98cede3c86fef969c1badccdfc071bd92d9dc65719676936bdf3e9aadeab2a19d8f7b15bdd574a7414f3246999ebbfbf777db5a55ff5d21f9f2aa50298cbd3e35fcff0076671765bdd9770a7e9c9c521269cc05e8e0838161971d7819f5732082ea78425d4ba60106ffe18720f6c4987578c5e6cc27182ef2c938eb85415f8830c6d8225e9fb583628a8868c8a27a7be126e38f30ea555981156a73098e9dc0224e672d3a06e49332d6b89b62d87882241d4a36139559f341e9e597a765676239b75c194796c104255f873e7ee926981e3648a62366c26109333bb5b9dc9b7cf63922814dce52669d7638e20c51e2b5e9e7a25e0ee5649574129a84a1ee603426a3982e1ade8cc1442a2913852ce3d6908a666aaa9b17a92956a78d7c6a4423786e895ba9a7d6ca676812265a4921ae1611ea2f914d35a5adc4fab92951c0f0daab2bbfc6c217955d162badb1628e256c2ccaf6daac3f6c7a384d08022d7204842bee3be28efbed76d54ab9ff1031cbf6e2ec4b0d9e0b59b903943baebde1c2832f01f20ab89c69ba0292ada4ee9212b093fdd25bafb9e4f23b9ac2fa32dcef75ec1985ed20da0e022ca9b47e8b6fc40e374c1ac40b7f3c71712a597b711e9f161c0a4f819d4c6fc8f52294afc3fbe66c2ec9214bdc2f1907f3c12ea11a8f32227113e7fc4fbe0debecb4d34b834cf3c4b3057d06c604e7613497c316eb73c9343f2df6d8538b2cf5cfd19682b599458bc26489d29abc34ce64d76d77c973df2c6fdaa4ac7d65db926c4963c5b5d22d37d876277e77d3f6463cad67a97a178adf386a3dd14f827b3db5e29c77ae78de659b2ae7ae78b0adccd64713cb2fcf9eb7eefabea07f8da9b77d97fefff7e96e93652bd38cc7fefaef9dcf5d33d8b60e587b3448e20e8975c2164eb2c8c0471ffdbca133da2d8590b05cb9f226514cb89f3afb2efdf8ae6bc4b4ec7d625fb124da63c87d20117eff26ef67936fbffd8e235e3daa45aaff91edee7bc4e5a0d2b53e7ded7e084ce0bd6067bd21054a68c843d0fbfa109568b9c970655320be0a40800278d083e2e260073ff8410d364e5f7823d7a98a643530b4af3c13dc8388aaf5a59dd9d084242ce10841182e11e6f087223421c886383be3092c823064032548043efdf54c8141cce1068318421e4e918a0abccb09a935a5ffb141820234c9bfc0773e13968b8455d4611a8188457b59518d08f44d08029da6d6e4c53624ff51897f48cfb50cf83c27924f8a6e64a32081b8431fead08af8b3e11c0fe2bf3d00103861f403c5f8743804aa9183251ca42637c9433416b28de3ebddf0f8f7bd3a72039291f44b842e483cc6fd118e9de4a42c67b92f4fe24f94b70a53241e599854ca902f348c91225d193d435e7296c84c2615d1084ae0b57261fc7ba023bf88ca3574ef58407a9efd6c9949657a53996bb425f9a4b6bf103152557d40622ff12849d440698bdb04640fbf49cf7ab2f1964e6cd484d2a9cea5f83212ef7ccc1f7366cf82d63390cd7c9d16e9f7a3c951739dd6a420233bf6208692f375700ca741379acc79223294a08312aef8694788a6218fb3921f842a293d4376d0a3ff1c8de9375f2a44f445a942d244c343bdc2ce5fceea49261bdf21654a548e5e119f7052550bb5d04fa6f49482990391c45e19428d16f5aadeace2fda2a6c2867aaf0c4d0dc953255a4007b10e78e2fc2456d74acfa33a7394360d902e6752527f46348f70fbd0ce2eea3a6eb2158806304001041bd8c0fe55902ffd2148fbf8a05c2d150b61fdca5ddb4951f830ec6668b52a5b05fbc1c272d6b09e0d2d670f0bd38cb60e97e69cca989e51d79a4cd6388383d159fb0acbc376d6b01e2c6c0e090b58dcfeb596095d5c0a63b4cfabb556acaf059aac4224b7df2956ad32f5ed6d479b5bd16a92b7d22dea194d1bbcb83ae89c103cae64ada19367c9b68c7e4cff4d08029c38d76adddd8af6bdf09d6e75b32bd3ed6252a10a2be77b1c250cf1ce25b955ab8e54a74a5b446215be084eb082433bdfcf62b5b4c1fddc701bdb4833ec14b927fd6554658451bf1295b0d25db088474c5dfa1215a6d3335b90faab06bb6618b630fb116d47a8597beab6b38325b18e455c5d1252d7a86a7dab77e173c4163b95bcc6b1a065cf975eb265b4a89ef5f18ea73ce5db6ab790bf3b1b841a834eb0fad73048c66b45857acc98b697caa13d809ad7ac66343338c737ae2f8d69ea395782e87a5c313286ad2043808d99989c8ba231371ae7069398cd884eb4a2d12ce52b6ff7b4c2a3309e9372ca8700d845657d4fe3306adfe8c679c78a0eb5a8ff17ad6338ff18c81e8574d3b63c510b7f5933619e8d92b9732f40d70d8483e62888413dea5efb9acd8cceb19cb11cbc67ca555d94ae343e2ecd9c60d2fab2ad63a6ae71ace35f5bfbda6d2eb5a9639aea08430d9a1f42366bf5fcdf172bf745ff61a8e73089eb694f77c4d8be360210806d120bdbd1f32c76fe580d392f2b3b1dccde14c29e6db3ceb5dbd3b88577bcd73cef863bfce1f45eb8bdadbc51fbd679d5fc6ee1ab5d136b0da7fb86eb36b3a1451c6f889bfce40d97388f4d7deab6b2dbdbe133369125e4ef7f7ba3e39299f576406eb765eafab387b636ca874ef479d79bc76faef80eebbcc5995778dc56b0b4b9c78039b36256bd572ce88d152effea8817fdeb5f3fba4d080282ef8deaa5730eb5ee11b70bc90de6a9631a51566fb2ce3c5ccf5ddb1dc1bf06bbdef57eed11fb58e93017ee7e534a868d0707e72e12b07b56576091bf3bc179dfbbe4f9fe6ba447b9a069ec6e579dce31a85761bce150a5d5a3fd61df92dcd7934ffddead5d65cc7f52c29be77c78a3be6cb7533dd3b6c96f876dbc7505a35ef5c097bcaf573eec8f926ddf836731ed016efbc4e39e36b50eb4cfb51ef45107fffa931ffed8ffee7ae31f1fdcffa1abcd39ce67185716fabc53ef50eb5e62dff71afbf34e80fc13d0f0f9cbbffef0d7beb60fcaddb14d38ed5f05176c076be5776e8aa71df4a37eddc47ea3b560bf977af4e770f6577fff13187f085081aaa77f08b66d4a573e44062d79f679cc57805407138b273e4f6360bcf778ef657d07007ff1178117687f18188332787da3b660dc67500a157e341782227873cd2770e7f7302838776fc480408777d6078126478350188550f870f7977abda68338e67aaa967c44926c414880a1277acf76753d7770df14650ed8847b47831428856ef88612387fd9778509c6723c48678ba35fb4c11635f785d3807801868033a338847677f0f57e92f7868ab8886e3883553887a2666f2dd7517396877ae82ffd0684e7d07661e87108c85729d869d4c7845d978832c88851a800f6a78aa8887d74b88159c87fde173e4d971ce2e787e4d789e5b5734f746bff0be84ded478aa1968831e888a84883ac4d0802287f0a908c8c4885375874af185ff35576b0a71dfca58952308257706e9eb178e9e78b2f77860d08796af875726883c7a888cb988e72c886941789b008676d956fc26551c7d16a5e3805da38054f4140de884162236de2787aa5a87713888acbc88cec988a0a1985ab978375787959a555dff77fc83157f9a88f60b88d62082e3ce734eba74cc17888e54874cfb890f3b7012ab9922a8990ad9881f0b88112094ec5366498e86acb978b1cf9142a857e649882492892e3288c89b686ed889229c9922bc988aa9890c8e890560891c447933d7437f67891b3b7897f3884de728235d373a2384bbd4792050976489900ff0da9944b998e0ac98a0d798eef486ad2487634d97f0c04209da75339790c5cd995b4363ce00861b2c45b2c976665699211f8866f397f4e99946a99900ab0000bb99835087652195f0e3691765949c79691512084bad86c0728884e966b42498ec3689671c894eb088591b9006aa99290b98c0bb000ad799670f988d01893ef457154398bb073897b8893b87878a1b92aedf18fa56950ee979a45778e93998cb69990b5199b1b309bb5399db3899b1418978956873d5697c01973b2e7791ab995c7091a03077d7207940349946c6690478994d9a99d91699df5599fb4999f92b9888b698396c99b676662945837e5898d9f899e3b0963c9b16ed03598cda968ff46899bfc699bf5899f159aa1d9a98eff099761176a1159684d0802b4647615892e59799ed4d0973a3732bdb89c42c98285559243379fc8489968499d16ca9fd6c9013cdaa33c5aa1b369a36809871678723eeaa3df3995c844a2626391b5718de6998d3ac98f0cdaa02d1a8a033972317a9888a9986ef89a389aa13b7aa43f9aa141faa54f999bcfd87064caa3721991e219784e3a9cfd13a509ca9724d86c45683e84a88485b9a5ce39a3b879a390a9a1d939a6646aa8f6199948897f10d7a61c20a067469578d8a469675c7ba90b2aaa3ea4098eeff9a781c5a527777f67499bfba9a8b0199b908aaab579aa2809a00e07a99739a9e29987dc314dc5291d796a80ffc771a57397584a6898126a8e349aa68cd994a7caaad5a9aa6daaacfc29a4503983b1daa64607a2d248a09ac4a4df364a265a78999a0b9bbaa202e5abb544632209a3a11aa8338a8e52d890f6e9ac87caac890aafd9c9a80b598cf306a92967adbd29a29ca4addf76954f7a30e3671ebb5a821e696b20994c0947964549acecca88fa49afcbaa96ab4ab1f9799bec98afd4baaf6ffa66d89aad67678b4fc70503a8abe909a53d39ae0049503536480d2b5aa20a7107c98eaf89b1f16ab16dda000d80b3f58a9bfaea70921ab33325a7dc6a1b3fb876df6ab029db6a9deaa26708aa334b85ab898aefcaaad689a847eab38bbab18e4a74fcda5e74f9af5569a9ff360982debab4ac70b071929cb95786bce7b0f1f99ca7988ead4aaf592baf5b9b4d08029f3c0baf90d9ae52f8b560fbb16818b2f754895073b668eb99f780a70b2a165ed99e083598e86a00ea3aaaa4aa986d49b13c9bb73a4ba63cdbb3a11bbace4a9d0cd9880f99a4fd6ab8cf359e0bd4ad99a8b45aa9a96c2b249a06b710aaa5e9fab05dca94f677b7ce3aba9eab94903abac64bbaaceaaacc68a3c247b8bdb9a49bc9584f8aabb30baeb5cb87cfc7a70a4b910fca46a6d782c36a926d48a89459a8c1dbb7c3cb92c57bbcc6ebb760ca98a95881ba8972617b79ac3b4896ea838ceb048efbb823b5b20bd5b253d4bd82a45b723bb7e26b8c4eb998da49afc29bbeff2ab9beecdbbecaba9ff0eb9aff39b8ce0b6233e57f3873918b6bb26a9b1fd78b4d3e09b5629986bc8b72757bc16ed8aa376ba83d9b9d0f0cc1123cc1c74baf1beba12737b44947b6655ba2d31b34054bc24d5ba756ca780b7b9aa06ab9e1cbc289c996c02bc338dc00101cc13b5bc5ecabc3e988af4357bf7309c48943b2c459bd4cebbfe101c005b7bd552598058cae974bb3e3bb88301cc3accabe5aeba325b0c77cbcc7378cbc0bd0b7c96baf2f99ba6b76ad938858d538bd986ac66b5bc27ef6b66c3c67c814b3c28a68741bb16f08c3774cc3139cc73ddac77dfcc7a31bc882aca8a6daae0d69c8c0f6bcb5ea7f645cc6524abb686cc2b937c93455c9ff4b78c9088cb9f467ac5158afa88abc550cca3c2aca7c4ccaa54cc3a8fab7f13b853c6c721bdcc1ae4d08022b9cf1a147086a08c649a5bcfab41bf4b2bd25b54feccb0abcc9e7dbb75a6ccc1c80cc7e9cc5381cc8b539c386eaccab28a4bba9ba4997c88414bdd6ac1cfbdb10db2c05b7b7a73623b9c0aacbe0bbc2a33ac7353a7f0d3ccca2abc556acb77accceca5cc5cd4c9b5e7bcf88868540ec6d473bb0ab7519b96ac4dc9c7304ed3801494ff0f98288a9c952c8c9772cd1a1abceec5c02178dd1a8fc9a5d1ca0f86cc0f73b544f13d2c339d29035c29ab0a91bf6303f095c950cc7e34cb399ab8c8a38c51a4aba34dd000c60d316dda60c90d5cb3ccf1b3aa4ff8ae8c53d3ccdfeaac8954a9e48dbc8287ac6279d15eb19c063038c301ac754dbd0cae896f207afe82cd10c10d85c8dcc901ad85f0dd6f2aca1160cadbf3cbf1007c6bbb6a482c7c87d38cb285bcb7e897e6c6c9a300b5a09ddcbe47c8c617ad57fadc586bdd5570ca9856dd8889dd866da987a5d991a7cc8ae4c89467b8f25cb5425bd09e19ad25d158a04fc43110adabe6cb5a39da1330cd8a78dda36acda64badc87add3a7acd81abb8ad1cad1b42db623bad67789db79b905489d2147acc6275cae6e2cdc9e2db30a2dd5367bdcfc29cfcabddc57bc01cefddcd04dd3f0dcccb5d9d36bfa70902d8fb214c4f94bd90153c4e21dd702378604c5d9de9bdeff9e85d70c4dc7eecdb7a58dc3d02dd8a95ddf3e7ae1d1add3fabddf2fe9d8fefdd3da2db2aeab62455dd9770ad7ec206b4d0802044dae8f16dcbda5de982ca8304da87dadacf05dc51c8ee1cdade13cdae31dbec5f1ecac2e1cb8222eb41b9cd68484b80c24b0d76cd40260e02a32de95d1aba0d8c6c048e3c4ed8c8d2db1331dcf3cdee30e30df40dea30e20e45a2ce61fde8a49aee41d1dc6ff7ae2b1c720d86ca7da7cd902bd8bec89cb328ede5cce70bd2bb1c95aa1583de617ee008a6ee667ce018a9ee61cbee680fcdad5bd88d89d6df91ce0d15be70c22cb2bfec8989dd946287782b64940cdcb6a269f743c9d8a9ad564fee88c7ee68f0ee9172ee9d30da4ffb709ad1f1ae7992ed901dbcf75aa978e9c20569ebd7cea9e29dcd2eb1a7f905aa385fede116de1f29de167ce02d67eedd63eeb8a1ee959bdd3fd69e9454abf24aecf221b7350ae150484e7fc6bbda19e8949bcc4c9fed982cec231d8ecf56cc7d01edfa71deb408eedd8aeeddb5eebd2ededdf5ed66f5eadbc3e93941a54c01eec0238ecbc3ddea33932edc9d2819eea505cef6d7aefad9edcd20eddfcaee1fe7eed001ff0f78dd1b7feac1a5be953f8c5e39e5bb444e758e9e979cee2a0d0cdecb9d2a7f9e0ebed8c8e68ef09f0d0c85de1ec9be8215fdf239fed254febcb2dd1839c8c509fc1e29ef0bda7e911668d6efde9268de089571b4dbde0a6eee0ff80dae5110ef4ac3ed31f7fda8b4eedfd9ef44b6ff24dffcea63ccf3c4dd6547ddd674df53f8cbf02cef0de5de0bb5de5c56eecd053d79c844d08029a645ff61b1ff4390ad1696fd8b0cef622eff66fcff4a7ede1ae9db1205ecf813bdbd92de787cbdd0bd4cfbcf1cfeccef5f042f8a3efd47fdec44e5ce383deecc27cd59e3cc1891ef93fdef6235ff970cfda03dfcc1b9df7ad0cfa877bdb740af8819f0890dc8de4bd6a4bfce7c3edd2743b7fb21fe688aef6b37ef4ce9df42cc0fbbd1fd8b69ed1c1ffd82f1fd47dcfd69dfedd240df1828ffad7e891c80ea1f28ef1a30af43478b1f5e9ead0aded830d0425a19053341e9149a383d9643ca18cc6945a5d4c17ff59ed76a1f026c061b11851369fcf07f5dad0761b0a71789c5ea713f079fd1e3ff0ff0103070408fd080f110f0316191b170120232527292b271d3113350b0f053d03f9f8ec4649df4cd750d1d0129438c6c25ab9aa6667a3a09a9a367477755b877e4b5a8595709d6ca56867b996bb14165ea155a51150d94ce7e648eb42b9f33e3d3b07371131312dcfd129cb1bc7110d05bebfbbf3e2f0b4b5af0daad5a6cbc05aa12d88252b5995630c8a31e1c5cb173022c3201649e8e060412bccb67879a600da987e69f6e59373cf0e817af306f48907a8ddb8758dd2c544f77251cb42e2e0ad0435cf64017b24ede4db77e0e33f2501076eb138e5e044070b773574ff1831a2d38a4bb334c098c559338e1d137c0459ed9a9c6c404f72f3a352274e9be468ca94ab8ee6db446dd7f2dc83766401a1d5c4960138264b52ad5796369d084d0802b59712870fa90a734af1d8522a5bb780edf871a848bea350e2fde3ce2ecd00735143326dd79de8947a7f026d63f6cdd0c008068b29ac44cbe1c4c72633de201558e461932947b17c197396305fc0060e59f673c96eae47b326643a35ead536dfe5c4aef7f3ecbf8003e706c3752016c4058107674cfc9771c993af5abc82d90b74cd64fae9cc94bed0b28727ecdc2a2daeeee4faaea5f0109cc7a79ed032ef9a7d8a0a8b95a374db2d89acb4facd16e484a36f08fb5a412e39e5f4730fa3fefffef328c0e906f48b2fd8d8c2eb26055f62b0c1bab4134fa73e248c4db67cf4c1b09f1893c2cc22c5e4134eca854c840c090854acacc5e6b88a51c66968a4ee461c09702d48ee7c8cc941f06e6a8bc86e26e40bc9366c9b260c04c06a521610e11b113908a60c342ac71e6b05022cf1d3b2202e9b79a6a3afeee42ccc37aa9bf0ba1c75640dcd346702f241045fe3a9d239934c65497ff2e48d99e51a8072a2430515b4ca609438344b5b2ce352232f6f1350ccea420335419716e4f49c35c70115c751e754d24e543bd2b3b7e5e273ea5040639d7256436d4d1457fd74752ec65ec9f2acd260cd8487c7758cedf4a5b7de11adcc6599adcdd90c5ff142dafdfff8a4c5d58410cd565b42a722e65ae414c56a2b18c795aedc5f81ea29b4323355f72dd34e6b97ae778394375451eb75e3de25c1f0afe47d7d7bd24f6b0316b844828babf56084bfcd4d0802f5c55dff23f7614a3f836d2dd1821400638d375e27e808c9abeebc35021b03525854552ae564fe2dc6566c5d866adb5a1d98d9aa9a15be9923934b8e34ac195121b54032296eebcc4d8956cd53d69006f948bf2e444f1a0d998c7adaf7a85e99e5aeb39e0fe6fa64be16d1af59b49919869f66180c3c254d7bceb54df2b9624d8b8d1b0064e1c58b62099586236fbd55f1f2398db6c24265c173293c561413ef7af1891206576cd527077367370824c940b5da065a3bb8ffe3061d3cd1f3e28659bced35d54edefb6b9d5ad863973d50da9338d86bdcc15e7461b29f7e056dcb793eeb9ee1af4bd7629b90275af94fdd6c1ece0a9b457deffffa631da3ebb1a710ed6d8f7b4750dcf712923b5ae82a72e58b54e5acc1b39e65ae7dd8e1c4c53a97bcb9b50327f29a17e9f087a491ad22461af1dfaa2c53ad840c9080052cc2019970bb62e467810c7454021cd83bb14c4a7d11a3a05a10b423f865507e1b4c56dde064a47b60e314232461be9ec6a87ef92b800264e1cb5cc80118768d668dab21bf1ee78c1ccae86cd2e0a104d7f7c350bcc678c723a2c6e67717243a4f89f8a08dc89c78062f758551af8b4294aea8b52c6a51714d90ff212e147891c384f1869af1c7f922083152b06f8d985a494ed6550ecf45228e9a708d379248213935517af8024bf5ac07b85a54d18a81a4d2200f88a84322327cc9e08fb81c4939481ee072c03a9099c24d0802d38ef8c1d188cb1bd2e8e828ca10e2b194ab3043094f489014b2f229ae1464166319c3593221915f5c46571a564633fe0e8d98aba0dbdcd8a34d7eae989b180f324311a7d2458f6962f152a3ace7c75b582b908f298170fc699f6e81af96ccb9e54672a64355f0b0527700a2fb82492c756eb293adf1a0fdf652477c2c8d1fcfc2d37fb8c24714ea132193c1da00fd09d0421967a0048582ee16a68531de49a16860a82fd155b1886e6298edaaa845ff3f19ca6592b2997a84d618b9e2a469fe9165fd7c8c4a0b161904d2d28bca90e20dc956d371a24f9293c41144313851cffdb44def4ce650e9d9518fc628a9ff03e03e5f7552eda594310165694b6758508336075263d459246b243c32b53193e6582759cbea413a8e127accace75acb2686af881485aa3408355b39d7a7d675a591b15d175feab86f66d57c8ff41d57cba90d89e9c5828575c43ad9c931bb04f563f7238985d24a94e97d1487f92a59735cd727a6be2ab3b2a32b54ecead96d1aa3aab6dc1def7689a473b1d67d437ca3b1109bd878bcc9b6773bdd6353c7bf92a152a9811b2ec08a5bb8e32e24b954592e7343bba845863172b9dc2a608187ffd335b676a79a181a45db7944377dd079e5311d51d51ade3d46d3ade6852bc06075c5f5f2a2bd11792f37f51adcf1f575a6e2b4293967532087ee375dfdf5ef7539955d21894ea8de45b06ef777cf2ee493a4258dab5c5b884d08020416ec98c73b9e55858d50486fc5b786f31d2d744f8bdffcfaf097ad752d4c002c5b0e8643b1f194e76d0f9c5b92f156b290e2d25b9fa0a20867ab153deef18f3b7ba5a95295c856e56bf9661add5e0a96bad5b52ebba26c343669571e2053e6461b4b27fde9916f9af9f2521fcc4f8195d9cc3e3e9c3f4f243315ade80930e54f97a393642587d89ce7bce4dbc45a4429876ec0a4fb7329b2ecd8049390cb1d39b48812fd2a97ff31bad1688eaa9a27dd4d232f2c9c1e1e0b7ef136c126ebe48261c5f35803ec4e16270dadaace50aba141d9910a37d686c4128e079684463b3a09904eb3016539e44a8b762b0d83a01aba4ae7fd16efd3264e444f539cec4eac7825f46a76a9c01b5e68bfa28fb00ef3e0b02d255a9bd9d631eb5eb819d766f161e6510f94736a99bc6ee3b91b2ea126e6a8053c4751cc53d53036e5a3a44852935e6bd64ad8360b0a8eb8830bd9a5e30e5bb9cdad695ea63b8d2426ec931971587953d9ac1b0f99a08baa60d2e270c6c0a5f6bf6f1c702cea78db298ff4cad78ce1e67a1323bc3af7cc033ba687dedcd89acc73393ab6ecee1e89a31e7f2234a53ded559eb7ff9ad664c820b796849623c3b9fc193a807688da1e767a0f4e7e9f30519c26c40ea2ca051e65d949b6e07e3b38d16e7f25dcbbfded252430c30c6c6069f30eec86e694d8a03eb6a8f54cea8bdeefd44111e1a0098df6575391ed6d77fc70201ff94d08025b1f61eee0dab54c9d117399d3bce65bef7cb1016f71ecee9ccff526f0c64b5f87fc051d5aaa77ab65a9a0c2f4ba32f6b23738126a2fbedb87b4919bc9bce66f9416df5f521cc33ab1f0e3bdf30ef6dcf068cd63ea7d9b80b6aa9df136cedeebab8f04204b84f2537733cc73e6eacc25e286edd330e9cebc4e83d48fe7c44e14926f14be6bd562cc69c260fe9601ccec6ffa0229ff8e60ff3820fb5eaeea74ff6fa140cc4608d0d30cf0ef24eaf32e0ee33c89018fa9c01eb02f22d0ec8c8ab7906af18e2e035f6f503890033c100417c8455e04c9ee0bdda44beb0af01bdaa4eb0c4b015df02e60d0f864b042ee08e8f28dd070d03fbc6cf5eaaf187ab0317e3008fb4fe19863fb3243751e8ef7b641733a2f3b5a02de7c0463e826a84c8de3b05002b590ad426e07c1300c5ba1e4b24808ad0a0d71c6ea8e10ebd8304e50f0f73807fdd22ff48ca901ad6c064d4fcb768b0f7570ed1a0f109540105d881015697cbacfbe4850ef962c8d2c850f82c8f312100ac16ecf688bf40eaf06b78cad186c5afc8d073d310940b18044f10c49715cb4ca0c188ad37a8ff3e2a10911fff009613113f68cdefaacb632ca12972f0b9f4975f089fe58af137b3010176d9082d13d0c31f756c77c8ab10c8e71efaca3ced0090e838f055b3016674be3ac0ccb020ddf6c70021f2517a7e80b71210c61cf17c37110f32ac3f68a0b2467bc9ec661f4aea156b1114d08029990e2b623f0e690f88a8f0a416889522d0f6fc3f91acc0f03b21791e017b9a70c5dced214927c306f0d9151d894111ccacf095febeba0b10e0bef1e5d2cad3e128a9ea30f455203af081cc94c1c0fd20c356c7cd4500017b11d593125b8ae196b12d9a250d9ecb0fd76d2d96ed127d7e3aa44eefe1c8f2867c728d92c259581088f6c29772f0995b0effc0ee71ec1261d21ec4a6d23b3ff320ff7b1f9b8b22bd3ee1fbb11e900c9f13cf0e4ec0325e9aec8b8442d1351112d646d22520ff2c2cee2d0221944c5a4d11360a374f2f1fdf66dbc3aa42fa18f1301d3290472309bce380c532501b0c39872405ed2ab1ed31ba05232e3f115418f1e71d2f8304a0fae8c2337f3fd26a7848aaeb26a6ce44a53f28a803051b32c0f93ea1e475ceeced77e0d09212e196d6e73e03263a852128f680a31139e1cd01a990813f9d1d086f302a7e62f331017c6ecf54cb3d69613beccf222f80a3a03702dab53b596d011b353e7aad23b73921e348a23c93375f43220b691c644733daded3867cf0894d3b398733936ec945af2c350f135d56dfc9870dea412cab6ff1337334e59ce0a0ff5312f75e99efc516a0052d17af03d092e3e296d3e9d13f73a2c38d3911a404c434b62c424121c3c74322151f030f232b7ab482c311f3bae27258b305634342fabf50cc941afef0822942a2694422f2da1a4d31877941db741fc9e92dd9631486bd3196ff32673534d080223ed06cbca0e45b3d1d09e140349240c61f4cc6454d71252043dd32372d4579a524c59914c3b14f856d036e7514debb12e996d89ae102f9b0624d1731719542859c83ebccd21f08a399bb3eebe09971ca94bbd74d37a4650217336d1c950798a32bbc3320374ec50ad234f34f1160c345945fa46f21b8d2353816153e5b353ffef394b311a44551d5151bfda87503fff8113ccefdd583535c84a5976532709d4166935da560734fd324aabcd52070853797508de4bd718458c4650d3ca024c9df2473b94222b72482ff23f0174bbfe8016ef6d56af158a266b456fb58a04125cc3b504964b4f6de8468b7554814d5ddb3026c92f9de4d1a78a5458a8911e1aea4d3f8e027f1228d59334493222025608408b46e9536ce02cd316335d15b61e4c95bb40a53fe5921db48344b1b2160b54c11aae2b35764119f45f77f563c54d64f774259ba149bd2f11458247db706509ac656912449f5151458f4d61d5fd500ffe402a671774313a16223eb6047e9655620a5437234775f421830d2607d5920af5111f76f88a342305814c2af6c5e0ffb433f90d6bb935d6783632ba36e19072640130548bf5a65276611916481d165121f66d8d346e1bd544f1756f9aafbe70b6bc76f14f6c65033f91b31e94ff52534b9b8357fe9470c7243641495911976ddb3612b9731263d02e65e35123375ffbb47215342889cbf5b4472c290c393fd0308135b8d0500bac4d08026e704bd0047dc874dfa48d9ad5599f155a315258ec463c4faf6aadd6d5c82b24ebaf52b549730912b97c771c93327489f64b5a337d4a1725d47659854848e1355e5b77445f95377d826673ab6eedd6699e745ba30fb394ae204b9273ab74f238152bd03223c4b668af8e31432c6505f452505710c2a1699df66961967e08cf1e29d6c0aa171bcfff4e33b2971b75f64fbc3780c1b7737f374b17ceee1cc8813e6a81d912594f5562b3533b43146aa74c66a995ec2cf6624fe93c27f572ebf45237f78407d873a5ee6f7d8385274b70cf37ebdad22d25b67915410e89545e3dc9631ed70a6b107ff3b7022d509aa0b46a72f55b8b98bdc2f75783971c59987746f74b0b77b580687d653271d1d48219e168e6d7e7209733af1741818b7f5b0557c15276787717c8308981f68047cb1c15f31433b47019517d81c98ea7f265f3185e2c46b126f681e5840ebaf8d9640c6ff37634e38a7004e64a81519117392b1805118df75837efaba2d27d153751e772b6e675278e6f6addb466594d1b3711770747770345954fff7246d7787899a11f1d6e971858920d97782258825df18ed3148731586adbd47e4f144e41b8cbf6174afb17b36ce77fa1029969479915869111587fa3c1211f1269f5939aab391082c68aaf188b997516339383e9d687cfb16c4238888b53ccd07921d4194566d46698b97f382c9e61186567d99e098b8aabf87de1377eb3186e4d0802fbcc97abd55a3f0e3afa2763954a90c9d86a5c66a1ed83865473259bd485c9b66c23398e29e92951f50ddd55689e177a892f5e74988fbdb9e3f01763a3ad8f047990cd79a54f338bf414701f079ed1f160cf283f175679dbe69e47832528382efd939f81fa933a7940095449fd384ef927e4c8f920b8d75b7981a58d0321a1ff1a8113389ec91650a158b0b09a8edb15a3337a75dd16acd7af7e982d49830df16ee38bc1585bc9b1c6da9aa9e1d3a99538441ebaaeedfafb4855860f37756b18b6624bb0cb4f8385da377fd37a3ff894f69755949a959c0a853975999999fb1e199a49c5a695568adfd15dff0bb6a275b019758b01cdac39b37754475b7511d1a4d498d52b8d9519b6cbf5100390aacfe86c45ecb66738555570557bdaa7399a83aed2cf003a948b02ad7128878cdb95c979b5a5b4b58ff877d95ab599d88def7aba83278add52abb9da922f19936b822e29d15eef152f8b9a7ac2784f929aad5748c2c2f7bdc1b68d4577a6f19a9e27c947afb396cf149bb3399763d663c6ff9a620dfbb0bb189c71b4760923412d777b7991853c90c16defb9a5da4fa5bb04535178287c4c21caaf797abbbd63f03298fd2af1c34159bc6917844d7c550e1cc1dd3a5056fca9d1fb958d1a40207cba253c69a90bbf8309c777fbabbbdba23cfaa3ab706ee9b66e477c2fcbdbb81bdbb14b8abd550e0998bcc98515abfaea4b625c96a7bcc6e7d84d0802cad7afb33d9b0e357997bd7c8721f79bede96c8abba0c518b96d41cd9f8ecdfd2f685f045429f799a1399acd026d27c6c9765a9f595744d9447aef50333bd8839f6972cd33b5857707a1c0248f83ad175978df6c58c7f6af940c942b5a7df11ca85d76cf79bcc799a7c3e9d7c0647728bcd88dbdc2e854fffb20545d18581db653e6cd1c994be55996913762ac1b99305d75313cc32ff853badc71d906c86557d099d44219f2d5d25bbd1920d95b81d541f7a121e7465f7881a3599a1dcaba23d3c22f7cbff9bbbf8da9db01e1dbc93aa4897ac0157b75fa2da99922d50138225c7a852daf7ced7ace378dde5576afad1ddf0ff596b53d93f578d97c9d827e2ec4ed89bccbfc6e81183d115ea9d55d099e7a7ceb53be7569d26bdb97aa5d364b0ccb357d9ff9598e2eeae337988baf51d46d76a04bdcd4cf3dfa563e091a7d08639b78e55be2277ec6f5dae26d9e36f3bd82b59cd395cdcfff3c3cc13dc8c33c520b3e5bafeae81b20e9195db529bbe92d9b58679aa649ff95e22984b5f87a6df5dcb33f7bcb27d8dfbfd3de425ec0c59ce441f8bca56929d0fe08d47eae57f2d989f160e13eb321d2cefbaeeed937bbb55ba3375d9b799eefebd5e723ff6c435d0f4f5b98491980921dbe1d3d23c0c98d135bd8d992dee5985d5350bfb17edf036051b9fedfa7d5e73ebc81df74c09fbeec139f164ebfdd2d6f58492be6319b3af37a82aa9d86554d0802f5ea730eeff35eebb79ef35115b887fa7e8b5af023eb33cf7bbe12bff843d0d9f7f5c1a33dea2112e0733a55773ac7315fe7adbfa3b19f976d0bc86bfb9bbdd8fb7b0b081242e162a1501493ca65b2e17c42a39b29b56add70b2da6c34ba6830c3c9a36298289bd309c410e17ec3ddff87397d6eb8e3ef0543a1efff03fa110c12161a120c0c0e2c32363a360a442e465256560660666a6602747a7e82868a8a6e960658a2520e543eb63a2a261eca06d206e6dde2d5d5c5f1baa9fd9e1d111921892975214b5d2d4f6d6d2543198721010b09b7b1adf5c2e9d2e1e2d6861308ca96bb9e3fa6a29a6e8ebabfbbb36faa5baeaaa2b796eb8f17f087db7ecbd56dce3638d50e222123ad4934684e983173a6a54b91680b971c3c63e68db68208061e0878eb5fa0417df6c9c2874e803d7a91e47182275326cc4c2ee9a97c442816ca93246b893400d2234721d9320e2173e4e29763d0202e93c8c5e21730178b2d409a86681c9021bfedd1f3b3164a44ff8872babab9aee6ccb6f16a9e528b0a6da39d65f9991c4b2be050ae468f6acca890a9d36450af48e5f084f012855ad5707d0332601f3e7a05914349b7154bb997d8ba0dfd096e5cb92d372fb25bf6a43fbd6245268edce67152ac84bd283b4c2559c5c58c8ba0a1edaba3c7c9412d5fee67b22ccfb39b5979862b7a7a27b89e3bb3449dfaec5de5adc7befe96f8806c6db4adfd66e8a477034d0802dd557857b57a55c9f98ec40b1a071b36b9f7bb661369d712766a49479d68d69916605ddcad46087f61f1219e5404f955d479b631265f55eeeda6e17a1a5e955070bf8cf85764720c24d28325f9a7e024a745079a816e21a8d62a2ec6c24877caf1874765b78c47ff2151f6d5975e180f71b8c17a0c19494630d594682257f981b3a24fac6986e38002d243da8ca19176dd69da39d7dd77978905e11d410ae9517d69288121534872281f888c3999c635bf00169957c7a5a9575efe15126076d709e0e5976d8589a824642ed893957bf801e484bbf8355b91c4c87951924a1ad95894489dc80d9579a8f9e0a084c2a220a28a2e4a538d88bac8e06a3cf618611e6cd271a2a6172a95dea7a10207dc9b1c9df827653ef2e7607ffaf0e42a23d7c11aeb3b8ddac84a80b0f887e5833ee2c16bafb259a8e7a8d60c46d8b0e905fbe67d7e9e8aea7ecd3a78978ece3d7728b5055a7bedac2e4dfb286af8767b658f95f2d557a646b91bff27b10b30f3b0bb1b254b6562c8358b65963b69574f8c30f52b6b4d624e921da4cd498a6b72188be41579e40e875089632c6564c44cd5bce7797d4ea96cb852612ce81f2de668a824afca18f25b3091acedc0aaddaaf2ca80baecab415096580670e9aabb4c88354f4c71cff126a6aa3f4417ddb1a32f25ad3429ffe224a082ac3adbcf8aa806e555a9e56a151cd75d5f618c527906664d4631571caf0165d3ab4d08027196001aadcac720bbbd34d3a6d53337dde4dc1d5ec203951ab6b97f8b71739cb6e95cf893c01c55aacfb8307e99b374b72a2d975df25b7928d8aeadf9e6de758ef0e7dd84fed763a3d64c7318372f952e30e76e359ceb8aff2c91d9cfa2edffe28004e6aefb687093bcad598472feade7df546d75cc081d44f3e064449c2ef4c2210b2ff57ac4fe13edadd69e2f2493cbc37b6f1bd9da0446a632156c52f352132ed2571ebe4dec7d4a6146bb4427a5bdb92c287dc81f49c641b7ba68ef50b7c35ddb040800d294e6265caa55a46e55b75c014a287adb1b6022a8065161257516844ce252b42ba9d48283b862d576f0859a02b2ad84024421ad9c76b22236e84ce6a3da0c7dc53077e9500d59dc21cfece7434b598f161c9c1ddafa77c4a3edab7b2664a267fe57abfdbd50817ac85b15cb631e7369717ec7d3231a4625bde9514f881b0462663c48c4b4a9ad80d532a12778a74248e08863b453e01f74d5ff320766ea6a3b44ca1683e147e301f27e822c40fe5a7348c8b9ea1e69a41c23bf47c03696cc64071c1f1ca538352a2aac78118c529e46d44952d1d0655f09c828199717c7d90b47b1dc1ef794b84647022c9691bc572de5184319d6716177a48dceb2e6cbb06130831a2c26218f49443326525f0064472b41c146cc3931929b3304252b49c75cda11829bdc19e2c2f93afd90d37a642454b4b42430a4397389d0a495325106c77a0a4d08026f78a0a3611cf6591f8af6e29ffa2125210391984260ef94a934d92a59d9ce132e346ef768a8437704bc4931eb38c27c194681a547fa515498c74995183b4a8b5a72cca0ff930b0a4fdac894aa63990dfd4f4bf7a1316bff9e0f7d98dc5bf42c7a108cea74a7100ac728815a28833e0aa1095528f86cc45228fe8e35509da34ca76a456caccf5d15155b28ef17a89f08d1abdc6129744aca4ea31eb5ac663d2bb758553e6bdaf3926eb5e2d534598dd661741b59d5aa5ef20ac757f055727e35056003fbcadeb1946069359895a2aad86cd29062aa856b0ddf95d3c952e647410b62479713d28d19b1a18a5ce449df89c4a58ad6b087a5e435ef30d3c8d64f6caced6264670a287b56b69c67fb6011cf3a42a2f2b69dbe2d6068a3b53f6f1137a66d5d2c72d950aef2f2c2b95a65d6653e3ad053063584484c54765b89c2148236b408142e48ebc95e5c9217bd02ee0a6c55245bfeb877ff39b45b5066e75bd4ce5607a9499526705f91d6638637b1f70cf080cb3bd3611617a218de1fca323bd4cd7216c22815ec845f24cb37eed7b07184a86c018cda0e3757bd1aac1225eb46e2e69cd5808ebaaf8a57fcd904c94dbf8ad0ab2defc6c0180a530e38c6ea8763c8401a7fe7c740d66d58d7f66015dfd751cb7c318c69594d1ad7d83250ee0ba6a65c9c0f83d8c007ae677f6ffb381d05198d5eaeaf76b79b2d345ab7b05e45b3f0d2bce1e3bad94d08025470b672a1453c62af5af7466316ab493b1be6dfda23d0db692af9a4465c438f17ce5386b337ae594934f797c9b915ea75b1ab46c0fa397c91be175a3b0d5e42836bcda41e973f771d6715c98bd06affad2514237dd056ab83c84536f291654d6665f2efa1cfc2759a8aebeb6bfb3ac435463520808a59eb3a6dcf7ceeb3845b3c26c27ef5ccc2d67044438ded77eb42dbebc64cb72f3beb74c852dc6325378b273c9740a75bdd6a45f35d8b8b4d785fdbe00b143686ed6c2f74825b95431e37bffb0d4b8007f7cc0d87a869ad8d701d9b7ace84a6a7c31f678859cff73314aff8e5526e40fdb650aff3a694bc0c2e908fdbc1e60061b8aa6bf7d588bb9cbe2bb76fac079be97b2f59d0d21e38b56deeee023b9dbdeb7ea15ed17aef49eb7bdf2c9707770376756a52f3bbf49e378fa36e7685f374ea3e66f296efedb1ac571acc9706ed4a91ce544e4fd2d3040fdaffd9fb1e5b914f7d88902e31ca03c6cc750670d99eb5b8599f0df0b003f5a9ebbe2ba8fd8ef653cf7c686cb7f0d549aa674ac7bdc873effab967fd73bcbb74682bb2c0095aeffad7c33ef6adbf8048468082dbe33ef7bac7fd0880dd870bc81ef6b73f8107c25181e0233ff614d032c4b96c786493f0d5722f3a92eb6e7a9fcbbc90fcd1000bbaeffdef833ffcddd7809a6f8102f1a3dffb28f82f7bb99f7ef083201c19783ffdbb9f01e67ffde858477ce2151f61ea3f52924d08027dddcff59ce4e9c5fcd5dffb911f7419c0f925e0f79d0040a489fb2560fcd502023ea0f8dd1f41e59f23489c83299bff315bb35d5c3cd91d83d49ad80dd15860600682df02224cff1f9c800b765f0402c26c5160fd59202db4200dda1f7314cdaa19db0722d17d0580082e1e09c293e35d1d0aa6a02138a00b466093f5c10364c01566800668e11672a106a480f8694044c9a0f88140176a0008889f0dd242046c211a861f0960e1048483156261166a0009881f1cd6e1153e8066045c077a9ecb8520121a61d0491a13629c8595431466e0146edc8acc60f885612d44e20b9e5a0e7a9f1afe032676df078cc52cb821f87dc082d15a075258d01921122661cb059df535617ce9432536a2213d6272c8a2f74d222ddce2f8050227b2802686832f7ae23fd48b217c80f88d220796a2296acbe74ddc97116221b6a2099ea011c9c22ed69f0dce02ff2482613860632efa812f02632d08a3383c1a211c63f8256332859d290ae0feb9dad0c1dae88999fe499a299edcbd30a2f76d20017c1f21f460279a1215fe413a5ae24f7c632fa6210b22a3396a5e2118e4f7ade33e409e10a21c99a55c2aaae22ab2a29809192246dae911c03efee020fce32004240b8c62b7d90d4944243f8e454202823832a43aaaded895c34b0a24101e823bbe233c36933cce233d369166bd5cfee5e3486a20219c2401a4643216522df6814eb24006c46437cee442fec44d0802530e5bbde52432f2e4e93163e640df4d68e446fe5fb9358d2b2225b790645532a5f7110205c85e07a48c1f4c0016e261f7a980eb51c055865f1976a141ae80ffeb8d404d8aa2019605554ee41f2ea33b4ea32518e111a2655aaaa59850e3003a0736f66353cad8a331267f6023fd8d234970e57ba10463424b61f9a4e145661209a5a549e37ced5f6b3a0267c665f70d1a3984a62dfa6069fec369ee8f6a4a52d2d9e6893963119e65654e267ed5e34782e4d5e1a649cae56ea26343fa260d02a7fc81251c11670b1d2772e65b462e2773cee66fbd1c5b7660077c407baa80f791407b46a47cd2a75db28a04c867259e807c5a6576825f7c82007dee250ba8c00704680710234a76e77022a34e34df5892252a96275a4ee6343e5f78d6c55b9226dd3ce5da0126f8f5e71fa4e438369c30d612633218867a607292e72056e6ff08325ee3499c8a6ae8fb9d00872e686620a40606c2880e5b892e28eda068dba96892a91308bae88b56a8cbb9a6d785678da6df8db24a879ea3f6f90167f6681ade059532a83a5657912a9578c29df46d64731aa200aa67feb1277db6a744b6e7801666ebd9a72cd065eb7d215ff2e721f487e40d02961ac288d2623970a99036282aa9e8918ae9986a9dff99692b9e983d16e9f731c2a0fea996ee08d511006e62898f3e64a5aae38f51650858e471926559c62334be28477624a629559ab6a6a42e02a51602a0e64d08021d6b68eaac5a2a4ac8ea9d852a98ae68b849e884a66aa33aaa3dbaaa3b4aaa827eaaa0e62a5025a4a7829f94ea6a905264da0ce9a11ee2ff6b4ae664a6eaee10ab21ae54a946da08c49e09500023c0ea003c650aa6649c269f5fc6a2f8a540ecdd290ba400162e5f39d4e909d4ebf7f5a59c566bab5c6b78ce85b652427376eb0011256d52d84f9e9509881f06a0abf7310206502baefae0f7f5e3218ca68d6e690636664fdac5c0da662a0025922669c236a773a6dcb9892b4b416cf849ec22a4abc52e6b503965c66a6cbc6ae7c73e60323e61ab8440a192aac99aea330aabca7eeb6b96cc8bcc5acc82dfcc0e40cd2ee882a4a40b6eac21746c94fa6c027e80838ae5d07a69c91ae5af4e23c226acc22eec991e27d466a009444a8a5664cfd12d2982a7afa685339a6db026add22eadb6724674a286ffdb3e20dcba42a1c062dd2a2eb4cc6d6ae0ed39640eb046e6ca5266da7aeb921aac2b1eebe0faa0e11e6ed2110cea2d6ed529627c3d2ebe3523119e2dda5aeee5626ee6a6eee6a285089840eddaeeede2aeed8a005d88e5dc8e2e757da9dc9e2e3ec4eee1f16ddf5a2ee5c26ee4fedbf07eae45c6d8ef56abe306aff3aac478bed8f2526eeb8e82f2666e93de8ef5e203e36e9ae8b21df629dda85aef9176d9c9a22cf226aff77eefbf65a6f8962ef6812ddd16dbfeaaaff8aaae081dada2c6a692caeff2de63d3da2fef1667c08d0f834d0802992e22a1afadf4afff42c721ba66e6526ee572afebfe2de066ef7826704e3c9c683d2f09b763085fafb90522066fefff065bceeb7eefb43caad3a2b04a2cb0a1062f1016540d136f0006b072b6b00bab2d0cc7b008492e0f2bb0e98aa4043f3012a7456d86ebf2c226b70af10b13b114d36ff33af1d328dd1647ce0cbbef6b66b00657b13b8d3116c74dab79f11a13ec11efad148f7119fb4b06a331e9b1f11d77de0507a21e6b6f1ccb71f79e711dd3ef0839291e1bb27ce971980ab2d005f11f0ff1154b71de4aaee01e72251bad0587310bfbb1233f322447f21b4f5a258b72e0a6310d2ff2b66e322773f0ca9e32f3b2e8cb8ef21affaf16ffb0188f3119abb22b05722b031afbfa3225c7f2e366b15146312f337206e7b215b3b231d79d13bd9dec063386b6583333332adf72ff322b73011b73c3366cc14633deceb21bbd712bdf724c6033209733cbf2b20cbb2f247d33d946a8381f54351f6c3ae3f239ebf22dd3b33757f03bc2f23b7399c93e5b5fedb3ca95333ecf713a17b4b9b998113733402b132daf68ab2e743ddb334227b44257b47a46539842740a9732bed5f229dbb339637427eff246976a05cf68217f74282bf23c1baf4a97b4499ff42a6bb44a4f729739f31e07f3ffc6f430ebf414a7f34dc3434ddbc4507b8c2917ec2c03b3f31e1ef8eeb452af05521bb5c82035556bb150877108575f14272a5523b5265cf5518f354d08022668754863c78d245548132c72fab39e39695aa7c25963425963f558d3f534f3b42baf74fd4674fffb4ab5b1caf54857b45ddf355ee7b55eefb50a49f49881af341d65def231450fb4471bf6612376622b7646db7563d723eaf675beb5339afed94083368a5975672ff667a7f6231d0d29f7742d87b54f17ef6b47df66b336a36cb626e0362cc9f45af37151f2f52fff76b2f5b64defb667f7f671b751ec221b5caf706ccbb073236d722f379824f73c5837661ab76c1f9d447737fff576766bf77673f77833944b9f2235ab37e8a1b7791f087a97c27bdbb74ed3778ac9f779e7b76fdff77ff3727febf77ef3b78027358023b8261b38591338752cb8292478840be283974283cf0885b383846b785062b8725b788177f8816fb88687f8807fb8819438d78df8ad7fa7b8899ff885b77886aff871c7f85fbdb8b5d4f8aace384de7b88ddf78c8f4b812ee38490779fffdb8d214798c0ef9f12679851f395935b98e2f39104779e83db9db54f9da4e795d67f9005f398c77b996af7898c3ef97570e992f7384a339eb9a3984ad391dd3f89b37729b8b9e9ceb337edb792ad3b908e679492f729f97f49e772ba09ff5fb12fa450b7aeb1efaa2f779a29731a3437a963bba2a477aa5b7f8a463b4a56b7a7f137810000021f904001e00ff002c00000000900190010006ff408070482c1a8fc8a4f218683a9fd0a8744aad5205d8ac76cbed7abfe0b04d0802784c2e9bbfd6b47abd5ebadff0b87c4e57b2ef78f579cfeffbff80637983844f758788898a75858d778190919293948e96698b999a9b87979e5094a1a2a3a4629fa7019caaabac42a897a5b1b2b3a2af96adb8b98cb684b4bebfc07ebc84bac5c648c378c1cbcccd61c977c7d2c6d07aced7d8d9d598d3ddabdb55d9e2e3cde054dee899e651e4c003efef5af1edcbeb50e9f8bbf601f4a5f0030200061488059ebc7ff3fa8ddad7249fc337fb144e327890e0c08a5910269c975062a07d0f432233e71190c5811dff15cc685025978d294bfe5927b2e6109232cfb44c49716547ff9f007b6ea12894e3c99ca6c0d914090e699978165dae7c7994ead1a25f343a15b46da9c36d5bb312145ab0e8d5aa43ab9295579167582fd5bce683f636adc6b108a98a81aa950fcc2e7deb668126171dddba6ef3b2fc79b1edddc78fc1fcb5da58f0e06485bb0d7b2b352046c05e208b1e0d797159b56739be1d96591a2fc16bd3ee254dbbb6e8d302272fce8d722bafd6c55ee754dcd98cede3c86fef969c1badccdfc071bd92d9dc65719676936bdf3e9aadeab2a19d8f7b15bdd574a7414f3246999ebbfbf777db5a55ff5d21f9f2aa50298cbd3e35fcff0076671765bdd9770a7e9c9c521269cc05e8e0838161971d7819f5732082ea78425d4ba60106ffe18720f6c4987578c5e6cc27182ef2c938eb85415f8830c6d8225e9fb583628a8868c8a27a7b4d0802e126e38f30ea555981156a73098e9dc0224e672d3a06e49332d6b89b62d87882241d4a36139559f341e9e597a765676239b75c194796c104255f873e7ee926981e3648a62366c26109333bb5b9dc9b7cf63922814dce52669d7638e20c51e2b5e9e7a25e0ee5649574129a84a1ee603426a3982e1ade8cc1442a2913852ce3d6908a666aaa9b17a92956a78d7c6a4423786e895ba9a7d6ca676812265a4921ae1611ea2f914d35a5adc4fab92951c0f0daab2bbfc6c217955d162badb1628e256c2ccaf6daac3f6c7a382d7204842bee3be28efbed76d54ab9ff1031cbf6e2ec4b0d9e0b59b903943baebde1c2832f01f20ab89c69ba0292ada4ee9212b093fdd25bafb9e4f23b9ac2fa32dcef75ec1985ed20da0e022ca9b47e8b6fc40e374c1ac40b7f3c71712a597b711e9f161c0a4f819d4c6fc8f52294afc3fbe66c2ec9214bdc2f1907f3c12ea11a8f32227113e7fc4fbe0debecb4d34b834cf3c4b3057d06c604e7613497c316eb73c9343f2df6d8538b2cf5cfd19682b599458bc26489d29abc34ce64d76db7d94df35b36b16993b2f6956d4bb2258d15d74ab7dc60dbadf8dd7943cc74b19ea5ea5d287fe3a8f5443f0deef5d48b77eef9e2733f6eab9cbbe2c1b6325b1f4dacde127feefad31cc42e7bec62874effb2a9defa6d3ae0a8bb4d96ada2f3fcfaf0f8ce3e7bed11d70cf6e8ea96ce06ef6c60fe1ddc98daabd1cdc4676faf4d0802f1b2d73defde8c764b21242c5bde7b20d022dca7ceb66bef3e01dcd3aef8f5879f3a7ec592948fe1f9904458389fa2cb5be2def7bef871e073c91b60a6d822a148e80f41fc431f873ae6a6af11f082c58b9ff60618c05b0d2950428bc6fe1ed13f06aacf4b872b1b067556000214e0852f14570b5d084318eecb80d98b1ac3c0e7c1c8590d0c0f8c4e04fdb2916a7d6967485c61b96a68431ac6305c3364a214678843f781ec8a982290c044881f120a0e517e629df51a77c1193af1894b34a30cd168af262af16b890b9f633ec245217afff10f70a3a08c92f8c634a291896d9ca21bf7f5473662b07d3c7cd284c857c7d60cd1388dd1dc116fc7410202329082cca414cf08c5261af27d25c35b0f73f5432eecce8e6b90607fde84b815bab18536d4a42c67f9c41a7672901714a0f250a5283ab60195a9c463842ab83c32bacf966bbc252d97494b42e2d28abaece198f670caccdc9188e931628c9028b5632ad38ccc0ca738d9684b3582d271890cd1fd18f94b47464f98c702d2edcaf8ca188ef39ef75ce3260fd938388147557d68a45caeb9875542698c957cdd3ebf89cf863a1499a03466a31619c2e759f39d2f7b12f82c99b3877ad4a198e4a7cd3a1823ca59b430047dca41ba06229226d473ffcf3ce347673a4e65ae70a42e0511ae027ad28106b30fd5092a8c5ae94d1aba90a1344daa388fda4731bec93ba5bc4c3bbd82d18206f54d08027f2d1de3fb3ca9d4aed2145f311d9e075515552c0894295505aa243fd4baad82539f5e8d2b483b29d25da63340ecd9e2546d9256a09e3040c2cb1e44912ad7c2e633a439b46b4ef14a2461ecb5267db52a4b01cbb49e1db39e8695a2010c5000ce6e76b399cde451179a584a3e88943c7d6c4822ab13a1426887621c1e38435b43cec2f0b3b6052d6e776bdbd0227583c50cd254a60944d53ee4a7ad2565568347bcc1d2f6b6a07de16799e8d9294ed7b76035a7e7b058d2355dcdb87341ee53641522b935f792868dff6e6dd52b5ddecab2baecf5aa1fb5bb5d387e68a5513d6b78add1daf60cb5b2b1fd9c73e5ea5eeaf2f6c008866e6eaf1b573f32d575c5bc2b771ce558352c85b5f1d2e37b022be0411218c1200eb18871dbdee8f6b6ab0c85a67de1d3c08a7203b2fc350ecce4a95088c6d5b3ec1db18e777ce2f8ca9793895d58942afc62b4a6c1aa33dea3ebec395ba532b8b39de5b19475dcdedafe98b4100ea570896c0518c758a5dadc70655f3a365c7a95c40a9eb29aa50cdd2b87757ed17450242367869e7ee5cb7e60ab5b0b99d402af79b70708b4a003fde7dd96d8c71fa5eb83b71bc7fb86e9bb1636b2150a0ab0070158a1c994a9479f1ce5290ffad3a00ef59fffd7fbe334663981726e5e528a7ce723eb64b262be17a6e1da67067b3ad4b8ce35a8a7dce91327d5c108e42e635b4c063be343bcb38956ac95b7645812f6a14d080238beb5aea74d6d418f3aca4a856bb04dfb9e01d519bcd34076b2ffaa1d747698c933ed6db4755ced76bb9bd06ceef5af9db868382fd63daa2e6ea45b3d6919bfe83f011430bdfbbc5e1ebfdbdd0840c0bb798ced522b1a7473d3e9b5b8c2ea74889b741ab64dc0610acbaea279c7071f74c2474ef2922b3ce40c6ff34c81dd39610ffb87e0760d9e910c703e729ca60b96f2c14dcef39e8f1ce554eeb5af41da71fa922dce2c26f6aa2bee8d994b46d9eeb179ddd458eb438f18e13ecfbad64fdeffee1d0b7dde6fae1d4293be4e8a7799df57907198b7236bc56917e72666b7ae4fbef5bad77de1236ef857f5c9686e2727df68d8b7c59d8e2b305296cc1dc5ac43d72d740457dbee9087bcbbbd7edb95d75bacfff957b1056f18c23327e32343bcd8ce5c70113f3ef2a8977cb5a96c688ff2bde53803d04abfcdf470bb9ae60092adc7d52bf769a7fef791ef3aaf5d2f5388936bd8a93dfbe0fbfd6ad08b4661e785f675afee7be05b1ff5d40e7ab61fce3821677e269cd7ccedc70bebdadc4bf4d99defe20d5efdebbb3ff8d3cebb9589ffc9a37bfffbc9afc27ec3e16fe77fcfb253c755eb577a8ed77eee970008980023978008b880efc775b9a666ae1776ff50b362c89157b4a77c9dc77c6340225117367603489bc67ba66780a8a78024c7800ba88209a7802c087cd92762f26679af9379e9b374e7b07cfc073430117588347a54277d694d08025680b8a6700fd8822888000cb88425978047a86bf2275d7b776adda674faa681b6c78155537eb4018201d864f8f47121668290978429b8846898864c7886300885325879c44785f8263e57a87f1bb883b8576e6d1782e81686d3457db9967a6ba8846a58888668862fa87a6e08625f477f2db74b1356249b577bc1317efdc57633b338e9b66e2046865b7788a0188a6848880df87bf1e77543575346656f12a61c13f70ce1770c9ee7223e684c4f13849bd88973778249288aff68a8000c088ca2f87ea7c888704874f5c73e63f7775c36053a9876d8a487dd04847d384e3d3686bb588648488abe188cc1288cc3c8868a886b6fd86953f888e8624238e88c773805e3a5261f088065568dd6a86ed8188865588adcd88d85a800e0d88dfb087f11688ce6884f99e63da2c48c65177858287378488bf0c81d52e734e5d450ec878ff9d880a2e88fffc88f69e88fa02890e41862337858dcf7342e77818d058b94281d96e86fc9017d642380d64880bce5893d6786fbd88d1bd0933ed9931b198ea638908c886626097116481bf9c78e59f8901d8855e6b787b7c867e24482ba588419e9821ec9803ff993a1088c1cb9841da98fd8b78851a88aff507437f7a6942e96834d098d1d081fb11782eac74cd37795589995fc38965de9937b29960838964e2892bb469088b64cb78490b207425b108bbaf09210e98329349551744fd5d578b8958d9f88824d080286289809189609d8973dc9910ab0001ee99989687766796050d69aaa48813c837c75c8940e0997b4e843721980cfb64c80186adab8825f0992bfb8000b209a1b409afe489cc2b9958348965ab79aada7774b759215287b19e896b5e98e3ce81935f785238897a0667783799ae0b800a4499cc6899cc4699ec8899aa1b882e35898095665af998c50837f66879db2a88559b1760f837e89e787f7189ee2e984cc8980ebc99ec9699c099aa0c9d9a0a6098aff9e89843ae973d02986a9389d8a1989906687d929056aa5879d5374f538a0045aa0079a00106a9e09caa02bfaa2eb7988cbc98483a99a23996046194e89b9a1dab19452f096daf98ed2688b2ce48743989918b9995af98bee799e2c0aa1c669402bda9e326a880e7877375a8e4b059b6d978e92c8921e4a0d90192f31298fb7a869bc197707a6994ada8ffda89c0ffaa2511a3f304aa56ad891ff089f582a6a7997a19ab4a362b796c1f2a5b3f9a31fca0e71c9858f31a2eba75b44e89b6dca9ced09a3eb39a7dc43a90a9a9ccc79a55b77a11f879697779f1c5a068e691efc191ee4b6a86ed7a89c88a490ba993be98bc919a7986aa9c683a9eb19a75b49a1ff7bcaa7f3e9a77fba8af6d78af1d1a1b459894e199731398d1d355aac0a6879a9752ae8a6df98001c89ab502a9a528aad10ea9e6aa8a79d9aa5ad7798b2446f63a32f553889faf998a75a35c7f138656654356975ae7a4d0802a2d24aa1d4ca8099caad2daaad74caaf0e1aa1fcb88dbdfa694549aea2c5a500866f07d392dfd0ae91a97193398fe1a4a63719ad59578a1e19b0008b9efe7aa91ddbadde5a8836eaab7e06acc16a7cc761855d50aa0f9bacf092aaf433b184446b694aaf9b95a43e37ad7b19b2d9da9706d4000de0b30e9aa2053b68bf8ab07f6a742643ac52c19866e5b00902b1b30795cfb7aa8b879906a0b308604067e88bfb8aadc669abb343b4ff700a9abe9882470b6fac499fcc2443e7aa652b4b4d52bb09548b5f56fb7f33f99d6bfaaa24e7b5f81a8acad9b163fbb1b7daa0420bb0a479a7dfda82256bb038aab453449dfb22b7737b9dc79a0b77aba8ff49a401ca9b47fa59183b725e2ba3781ab2425bb8401b3f423bb4addbbafc7aad1f899a65299feec569b344b91f23a8c5fa8a70d190a60ab342126b7b6b973977b1f65a720624a1fafaa4dcfabaaadb9541fbbad49bb8d8aaabffe89eb50bb95ada4c0a3baaa40abcac30a614c6b911877854394b5609adc9abbcf1f39968cba4b48aabb01bbd3f39bdd5fbba8a5b9ae6f9991fc982ced973e27a977325aa6407a6991bbcb6d99ffea7654088a6ffefe5a8c8dbbe7ffbbed60a929ea9a01d0bbdf6db93f89bbffacbad0feabf4cdab85947948626b9827474b1b7b237d8b2e2fbb20becae51e99d15db9b229775cb6bad8708a7d83ab4ebc9c11dfcc1204cbd1d3bb0356aa1035c608809b73c4d0802ca964153b71922bcea58a601e64c25aab55bebb73db7c3323ab8985ac4a9dbc11b40c4620cbb003bb08418aeb64b90cd848eb641b7313cb5542c1be042b36065b39a648f139cc3a41b3fc089805e6cb60b90bf642b3b2590c88a9cc8660cc485ecc898aaa969bbbd6c3bae288b65f677b9981b05625ac79526b19eab68378cb35bdcbe808b863b3cbf94eac8457cc8b1b3c88bdcc8898bc6915c9a9e39a3017cc2ff269ba33a2aac28a9909b7c0fc81aa4cabaaca2579937abb5a35bbadeb8bc4ebacad62bc6aecc01b0acc8b26cbdc409c92fbab8ff3b8a492cc06d8cbb4d6c9f49791bd9949f86caae332c16f1d8acbb695dad9ab35c9c70cc1c98821c3fcf0ca3fa7bc6d35ccd8cccba625cc8d98cabdc5cad56fa9cbb6c6b3a0a9bf859a8c2accec4ccc0793b2fe847a269dab714dcb5168ccaf8acca2b3acb67dc00fdeccfd70cc2042dc993ccc6dcebc6e59a9628e9b43b01b552ac089b4b67d2488d96f9a882e6735ebc8406e4d11f1dd2ad3bd2d55cd2265dcbc409908f8bb4b7abc25cf5d23dba92bf1ba60a1cd13be57f5289c57619baa5fc693cbdd13e8dcff40bd2ff21cd00440dcb06c400426dc4911ca33c7c8804abc4e12cc16febd2c8a3c9ea9ac0f951d36b75b5c55bb1a13bba15cc3d6ab8ad61ecba65cd00666db8b3e3cf2590d68abdd6b45ca7fcfbd670fdcd26b7c405d9c44fcc20c69ace2ee9c9323b52a18cccb4f4874d080218edc77597803d7dad878dd867acd88a4dc6656c40f123db6a2dd9da3ca5f10bbfa3189f07309faf99c971bc90a644d5e35bd3e61b356466daea6ba23b8da20930c8aebdcad91cdbb8bdd8436cdbdc93ddb91dd08f7cd2b79c86c01ddc6ddbcba18a38c5cd3130bcae326cd55067c5ee0cc19a25c1ecabda3c67a00c98cad5fda2ac8cddd94ddbdcddddde2dd4024dd0493dc9155a729a2dceff2b9cde95abc90133d349b2ce03229114e9dc7b6cdfa23bcf4db8a4acfdbe1a0ccdb05dc4de3ddb643ce0c673e2df0dde089ee0efb9c6babcd2e79dbbbe1ce1bc5b1febc8c99a2bda3dd885cc6a6af49d493a1d68d25a88864dbf412cc62c8ee2dbade2b1d3e42d9ebf41ccaf244cb2b94c724bcccba275e34debb41888c0a09ddc165eb5ef1ae44e9cd3f71ddd3b6b88490ecdd76de24dee00020ee5b1e300527ec6d7fde2c398e55a3ed74e1d4b4c0baf2eccdec78ddc7b5de6f1d4b9155d95a9cde66d5ed81dfdda8f2ce727ee00985ee7768ee978cee27a3ed9bc8dcb2189d034ce7b884981c787d73bfed0558da8420ae4cdadc7f01ccf1e9e9369f8d3fffcabcf423de79caee950cee99d7ee29f8ecddbbc9c23bbb6e77dc997749f39ae3262cee3a10ddfecfcae387dd1457e00191bc88638e2ba5ee920ecddbeaee22c30eee43eeec08ee99ebed6dc2a940bfee7a5aeec0fce3ef7a79450b1ea86d0e38a4e67133db3197ec3d77eafb17a4d0802a740bde4891de0296ee71c50eee57eeee82eece0bddb0d3ac2efe9e70997d0f01eef380ee6843ad57a6db79eec5a405eedfe5eaf906e721a2b9663d9df411de7f9cbe2e13ee00a4fee0cdff0051ed0c41eeade38ea72cdd4e3fab6e40cd350db98884ec7d2ee2d672ef2d6dee15e9db120eedbfaaaf2884bd6dfeedd747ef0761ef3e63ef3c19edd217dbdc67ee5bfbdf3ffd676b2a73ee8405f4a73ac22cabddcd883f4b38e99b51eb8823bf0516fe9b89de9560fe558cf025a4ff35c5fc47b4ed9c299bd262cf695ccc42d0de17473b9133ef49a40be8b7eb58dfedcffcef460ebbcaf3df5d9ddeb792fee58dff77e8fdb2e0ef1b92aeaa24ef1150fe80ebeec836eb9508cceacfedeaefe74e69bd50e96f46b6ee4915a88b96add2c5fbd97cef94faef79f0ffa5b2fdb7a7ee0820f98076df8e62ddc2d6df6e5fcb4b01ffb440fa23de25f23d3f6583ce45cadf4251fe93dfcc3250efc540fec2fcfdd7b6ffca11fd9364ffaa53fb283c873162f9dc12afdcdceb25a40e173000401e19018101c9149e46039703ea1d101815ab5560bff59ed96ab357cc1e0c3987c409cd1e9043ad176271470b782ae58dcf1f9c69edfef330003191c0809370e110f391619174b1e211f1b27292b170b0b0503fdfc16f6f2ee2cdf4647d34c4dcbc6c2c0bcba5caf6061a5669f9a946e058a7403007a7d7f818385817789706f998e6897a762ad5ca1bd56c54d080252cd4ed9ce48dbe8deea404139c31b3401310d13112d23232ddb2bcd09c919c4fbbe2d17b449afafab0fa60db2008ca6c5594102cca2d83a86a41891610f21066b2864a14284b30c52c9a27120977ffdf6655b8320df286fdfc0d1db230f9e0374e92aad83e48e26a396f2547e02754f4ec93621d3f4fb17b023c18d069b5dac55f1d6442111a14274ffca548093264a9d642470b4e8968fd580fef4d98d0eca94f458b67ca928a6cc12356bb6748053e59d0678ee2da8e31368d06ad3020aec5a006952ac549b4e8cba58e244c449b036d38aa5abc0af65fab2d9c68dd41d3b663dd9559916deda0deadcc2a529772eb99c3a17e41dab2fa450c083b9148e9c4c1962a78c81f79afa58d9eec91c3b7e091c0664e66edacaea051dda135a72ac4da396a9da1debd6825eebcc8b6f33dfbe7f6fe3265870f752e2bf83331e5ed16af1f65a072bbf8c39e4c83925a7c343a7d134f12ebbb6b6e3ce12efe8a2873a4bea8863363780b22d0ca2bad228a3f6787b0cbef8a29a6fa1faaabaaf20c2b6aa0ca0fdc6086b8de7fff20950b4eac4214dadb5b45b47c1051974cdc14feed96bc29f6a436f150c3b3aeea0dd8af34d311043748cb81295a242b25850ccef1f039adb67c8cd3e93d1ba020d34cdcc977264a71208bcfb6e931f65d4eb4b22f73132bda2945cf2b0f79e84322211e9b3ef222b0dcab2a82dbfe8f2140a273cc9acbb680ce73aef204d080238d352982871ebad35d964adc170e22cab240929acd0ce0b71dbd0caf6f86cc84fa800c585c3acf0c30d512e53094ba4b1f48a0ea5f06c8407824a2fb534cd99386dd34707031475b6cc10b0f048f550746656f72afaf0d561624586c3e3d4bb15acfe76f5a9d7e9802553ae61892dd6cc6325e1b453b93ee524d43b2684f65456ffa8d58dc9aa9c7475db87ba55a2bec80e0237dc5514ed0f3a09e38434523f8235a75377cf8477534a1c60b747f05e9b4ec8b1f44d65cb548fb2768ac8960858e0818991923884af2c7461e67275ae3c183d4357b41ad56d69d87330c611411de59d975e4dc203cd9b67339396df0cb5ca8ae5299de205e6981b9a924a846bd592e19c5dfc4f9b9e1f85744c412865b3dda2d1d1d812b787f694e9909de6863318fd33b58c5bf1ccf36a0fb5dd1a808247343123150b60d19a6b5e9c108f30bff98440b6dbee186ea3334d2de9ba970639a7bc2524158ebd5ff49b0cc093d4b0ea3d5b2dc6f05f103f86e69aaf58b8f1b1c95ef44b477fbd6bed406edcfcd21dffe5ed58697896ad8bf4398bfcfb36c106723d9695598d7d97d97da95d56ac96b459cbdd71e6cfcbdf7dadfcb5494b33fe78e427f1d863bb4567d6ac91b7318f9f7d91ac7eab0dff0530aa146e6bdef356956825be8188ab77901b4b8428a7becb61ae7deecb18fc1ac12e0d7eec4df6cb1b59f21135934d6b30d6bb1e877a33c03ecdce8002fc4d08021a4208a5c005226a5ce77ba01dd227c1e10d422e1634160619a1c14e2d0f13f5aa878c9cd513da9c6784a82ae1ffd883c212a9f0652c94197dbeb538e42c7039d468a0ef4881ba38fd4c524133870f2f08440e089110442ce2dd406597bcc989642489deea1015b86a5d6f554af11a0161d6c259e1678bd1b0ff0cefcc67439f44105d40332326d0f82e35ae71836da45f07e328b16f24d13c23d95f13ef040d13caa28f7e2451b65668b8160a6a5031c452219383c816e96c91394cc9c4fef048484692734014e210390808bcdd0f5f75f4e427f1389454019065a73c062007b6caabc0307cce3094d8bc480672952b1fc03bcb04cb811d5ea26992bf6ca31be30147e7a1e433503be629f63535aaf9eb22584b6501af8845b0251016d75451f9b4d917c9d9520fe00ca7d022a929d3684a41a0635ef33ad12c7c994e1b2479a75fa4e744f5443180cec40534b7b54a13f13377b084c6966ab8286e9eed5ca0c909fb108a4685ae85a1dc71e843eb1751914d8e6474822728ff95b34c7afab1494c01e9aba439c81399d423284da929fc933f9632b2a00665cdb012ea96857a4e35f3bb893a751aa73950d4a77502aa46a3a1a48e525176dc3b5c3e1397456b32d52b4e4da44a2d6a2ee9a4eda5ba3c675665b2d50475f5a66fcc69584566b625aa4e15276bdd7106e7b2edb935a9727d25e3a6f154a8ee8aa2a50b90e51c49bc3601761d82459a4d08026a9417cc798cee7ea80b6136eed8d8508a3265434508e1aaa84ab8c6b54a090b9b215724cbc7f92eaf64f56c2371c907985a8c68169ce94b6a8a5a746602ac7164a76beb884cd992709eb665066e731bc8ddf2969ab8cb1d6685ebb0458289aadfa4985f3bd65cf73d171dd185cb74a97bffd87a687293a823eb1b62eb0f653e5165fff26862ee19cdf1da0e7cbeb5e6f832fb45cd348aa03a7c2f05858555996a95a65cbd6f9bdc24cc1ff1370f23c32e80cd9a51eea6753d273470871672542849f385bd9d6b8a6648be6cced28192db6bf00cca43a169d85d9660c191917c648dd937835efdaa7e0724b2ffbe56bb021eb0ff981940b64ed68a5d630a6f1487257f9e34b800e531711fe60631f515c3432e9a91938ce4257bb8c985352c2611db5a939424c0acc3729661b7655d5076c12d6325336a85e31c47f8ae6a889c5e1b69d536bded7d9488b39c8fa6293551c2cee680e8119108422afff4acf2fc3347eb69cff02ad8cb8f019bcd140d5c1dff274ac222c92b803ecb66d152eacd95b8b49233ade978711abfe9843289efe7ce8ba2817f410d1ca0bfeb42a32638a4853e602b7f3b4316b9e8d6dd5cf30eafeab65e5bfad7731e6cfc80193a3c5b773a5063ac954dfdec13ea29d50746705bbb5c0cc430c13893c1a699878b665e7d3bb407cdb0e63006e74b9bfbb4e8b6a4ba45ccda7643a754ef9eed63e77d357b2b41c62012e4b54d08021667abf4d272546304f7bad835ee49fc9a050cdf34ba2bf9e475db2b40f9b2f8c54f6d05296a6fd0dc13a952c57cb31d07bcc72786c38f5d5a70216798c8c552789c5d8e2c62c71ca733cff3376cde679c8b12d581966ccff3bd8b29bdfa44ff06b87a67e34dbe7262ffb9e324e724833dec49c83ce23497f29451ccc464c65bdeb2d0328c3f4a6da45abb65647ff03f191dd01ea7bdbdeecda519dd1e37b8c77d6373af7addaf0e0afc61b7647b77b6505dec754117c1e7843f742bcdcb9158bb8286b55e69372b5c55b63f32f289983ce579e4e9eaf2418ead258ffeb48ed6ee863ed52944e5aa07dfea2f8fb4ecabef42eb1b3d61c6371eb4656cb34b6acf96db3782c936b9fc6a33394777079fefb4dd23f16f9b0cc0df9bcbf8243c98c37cf8438dbc6c616c03da807cf25d667ffb93e8fe25be6f984023eb52ccf33e2fe7ba2edaa668da90cf4fb2862ae0afdfe64ae4ce4ea028eefe90cef166effab24ffbfa8f03fe8f03e8ff0efc3cc82c08b0ca86827ab8ee75026dfd384ef066cc8022b0c11eccf93ca28b682dfa60abb862246224ad103af0343ed011e8ccfb74efd8aaa359be84fc562cad26634fb0e59960d0e364709a6c4ccc6cd02b70105774d0a28a6b6f48c507f54fbedc6e0889f0dc1a61049905d94061090b70bb9a7005a18d16ec63f41c22ecc46edf24b0f92870e8b84d1bc623e9ac6fd7c8709c2c41e530480dc5a1f74d0802aeebf7c60f154aed005f018ad0aff8c0abfddc4fdff4d0f0b050e87250f1046e140271ed2e8c10b18fff2a0111e14711c3cff7dc10051dcb7fce4fe7b287e748aff494cf764e6f195ca99f0803f1e82f14df6014654fe9cea8030f31e126891569ff8e0dcfe559ca0aa30c7077fa2e01a32d0a03af011df0fdac10d11cec95b2501a1c07ed4881180544d70cee146b2f198b6c19037011a9a311450dc0a291d9ce8a1a31cebbe8904aec7008082d17f5690fcb6ed164095a00b11204710cd531f2d8d1e9dcf1ceac0ed4faabb3504784544c12abb1129761018f0fdf740b20c98b066588f5ca6cc70cb21c11322107311d83b0212b0d88de719daeabb316eb0de10d23f3b1c0d2cff8626c0aa9102443929a4692cc668d0bcf8c1cdbc01c3550b982a625535119d52826ed0536ae6b48f4ce005530235785de6e4bd53c3213f3701339f1bcd0cbccfe102529410c3790109d9212541179a4b213a8b2bf5e1116afff2c27ab60e72e11ec3e52135d4d240772fe8a52b3a42f8c4c07ff2c6c2597ae873a3004594e41e2f2889c110fac32c06e32b8f4288a4ac91219f02bc50b28831223b28d202b50914ce23033b0181513c482d031cb8d3b2293f7c648b12a8a09f5232bbb609468912b39b32331f133fdf22f512ff5a04830130f14a1ead14a8efa8447e91613139a2ef25c73e160132249d0ee9ca6988cae1eedf12271d309f57123bdf237592d4d08023819ac1b69612b6f4c3007d3f5be04316f29b95602bea2d3eda613eaaa33bf22f25ec803efb8f30cf807f47452f43a933cab0d34d153209f81ae48b234f16a363ca3f1ce713551ae358b70111e333f8d2d2265732647a526a5ff110e850f01af20b25c30093a2e3e64f05a486a41c3f1f98271b3ba2d46626f42d7321d2dc642d190113214b5f49343e7b2c4b69351fe339e70720b708c052df14419c22755d4f476d11b97ea45b7d00f494eaad4ac46d7873e75b4e11aa147e1c23a9b26b17a6ad9ba132b8fd4286671374db41f9f0217cd130201732861d471880e8c00444bd1f139f7aff6ee33c920f347af93dd0670acf4a1488df43b27913d78533c79520ab5310611f47bae70349faf4a0933396f8839834c9c505135844d263a2dc4308f504bac987aea2a2f334d91b4b6fcae51f7f151b3d133cb332c8513dbfc2d964af2138fd2d18644ed6c5421fb9421b92354d761543f2df326ff0755f9c24ccf74550554656075167a83498f204583e3e3eea345834edb8ef34e0bd3fec024d784150891b1588d1512f02b5983949de808f8180b3014353794140aadf55a9d345b4d6f909e800fe76f1c91f2344b27f6d2e5fa0a919714245dd5f5924a55227dcf3fff33442fb37108cc1aebe95e9b34527f324e43b3529f815aecb4fec4751bc6483ec7c1afda122e14f611544be25acbb5f0ce32e5755ed59451379340d98f2fc15217c6ceb27c4d0802d113add43447b6644db66216b20cd1556119b6611db6bf7a856f40f459a195550dc566a755017d5367819363035228430e6833355c714d2d6f944f53b62656b60496764cdd955943286203946a5b8c8f6effd651f7f216f190677bd6630313188d1239f114d208ae6c9ff36c69226d218e699b1625f2056eef9162a3552363f56eef306f8bc06bc6f26781f66fc1d58e6ecd74c270708d31dcd824925c1211423071d976e2ca5466a78566b90229ea7672bf4e6b6bd556e5744ebbf55030d5f5c4f674de806c47775d0ef62d39c0b45e2e0dbf6f5079af430bd5986eee75a9664df37276a955566795566ff772c55241c9924a19c8775faf338055354bd1142d86d28ce7740f217563b379279332a1b6e2a2175560374b64f76a13a2a8b2d676b7d718ba37733f964a8b72e83af7770d5342c98842afca749f12ba2e54048ff0d89a333b1d91cf2cd23b2de3d9a8378606ff67e33256633716772995df7c962cfdd6418516f614784be10be17c887d37c07dc5b4045f766489f4dd56f57ee9557271f605f3555f2715326a8c6f29c3ec00ee8067743923ed071933861fb8be22788215576deeae749ad559a3251279786efd8e45ef356bdceaad86d86068c652b9e85b95787c476159f9aa6897eb18a1d82d3b6c470170433994113d147a6c7287e536450ac37aa540da0ad47fff7708305780351789c3565305d7a516f87c71d45ce778129057ea4d08022c0f8f997771358f931e1112b9f8893a9850980463f1558447586fbf4c805e8d388b9377b7b0619273893ba364f7944fd317868b054c1351933739ca6424ebb4389ea865944b34b26affb772e1948475314aa5a07ad118b862749687c4e45c187d0fee68cf84975791547f397eb12ecd22566aa1b55f54457ff7d71695d97201786674974ea539894576cfc6aa46239970412ce530869be1d28824337eede0346b535545141f23179ad1190afe288885b88c0186f972358539f7806be93fca37589d339fd5779b5f332ad95536013a420c356a4159830dba62494990d3999021557b0f1991e5d49979119ec9ccae0037703943a44936d7ee99295fb88d8a869f77c49fb153cf2cfa50b5788bb9f87eb1403712fa604038840df4a52922a68bd88819b44143d60269d32422a6a77dda60e578973b1a883e5a59796a1ee931a913f58f759316b1c794b0ff317b0df940cb18aa8dc39541f636a77985a1c3e44cf664e378ac2f45a81564f74cf554ddf6b51c379445b95e892aaaa5baae93efae6710865c193908981a01f6242134350b0aac05fb8583baac3188822b78a72e1883d9da48374aadb42c99d7b92fb9d68cd5ef84e52fc7da537c115860c9f59671599be18686bdf99bc1f9194fd075f3488f8c392f354eb2c5788cc9b8b621e3b2bd36a263a9777d97487e55789d1397492b798d501e8c3b543c99b5097a6a7938499fb04d0b99b22b9b4d080299bb1657436eb3c3b70b77b0db4e4c817b0fb88bc7b9a6b8b8c36332759a8ffb78c0bad8555fb5162977b6695b956f15ab7dd1beeffba61d39ede0131c305a9271ff34bc31390dc97bc09b6548d7bab54bad5fbcf88b195cb6fd51ba1f706f1128b30159e40ab81f285a2c46ba96ed79c31f0ff236cc8e3920c49de7b861f6bfbc508753506e7f51c18ff9a94944b273015b5319c2b1e8aaaf1b0b37bbae844b89e7e4e8765c6d82eca03c5cee1a81a841ba6471b854c6596a6e73999adb6adcfbbdf1f61f2dfbb6717b808bd94eb95c3905ba9e793ab0479b4cc6bcf2ca1cb13b94c0e51778b1944e4cdca44f1a2fe7cdc9e18fc5df748c5f7c951394be17797327da02d958605bb8fabe1b1006dd120cbd5d89c91141b7143aefc41f1d3c5f47d227dd4db5c6c569cc84ef9c32b29cb3b77a9be6b78d5b4a10019dbc19c07817ff84d88dbb39437ab5f92ca9019498fb67f8ac45a5af17caa57ccab93777ad3c3db97577b3bbc66579f120f4a2459b708dbd12901d6f507d72cefb6d9dddc611bc8498bcc965ddd0685dba85e3e3645a34f364d7abb4d33dfb43c7955c013dd08b1d2ae182d88729a4731a628fdc3277b898552f9025dd6ba29ca19f745ff1fa9dbfb60f93788d719cc27cb0dce793d411be26cc9c936fb8ab597dcd1355e2e77d372b7ea131bea1a9bb63f95dc6c74c576d1abf3d7746f10703413bb40b5eb0cf9d12ce1a7ec74d080228a0a1a7d1357844b92ee655dc5e29bdd62dfdd2dd799f64fc8879b7c27b35604f2c42797ac0c7e1e82701b5f7ebb8173bb94bfae9a17e12a5fffe98575cce1d9c9d617af9325dd34b2aabe3d980419ecf37956807dcec0b9dec6904cdad927e0f3c05513cee7d6b56681e95b751e3f3feca69baeffd5ea07adb3089b6e8099f11c85ee5d99de913ffddd95cc9617dda65fdc9ab1edff35de3edfc8ca3f9db7bfeeb2ffc3d6d39f47dda7845dc797d8fd9e115e26331c101790e7fb87fe7fcea61bff29fb9dbbf97c60b78a2ffbecb1340f075bf0f787fe191a8dd4fece7d33b16cdd9f159d4de69ddea95dfa19f3caf9d9feb39fde39d0381c94aec3fcb7ce921fb6572fb1bbe714dbfad251e0808c221b1281c1006ca25b3a914409fd029951ab862b35700b7ebfd82c3612d39503d4fa50227bb8d34160bff7282bc6ebfcb0dfa3d5f7ff803fe210c12161a2224242a2a2a2c262e2c28284052565a5236646a6e726e787e82866e7090969272722e345cb2524a36323aca22261e1e0606f6ed1518e0f9dec105271db9b9a50da09d959189353b8b2d67259f211f173b110bc7fd72f3eaf6e102da1eca9627bc3e464eb656a2ba778ac67b9a9abe6fb2b34e9a274a2e0ed68e2314eecfb73edd7cd199a3adc8b586d3ac44dbf26ce2c488581ea6a1d210db4223730ee229b867a0a080fff6ed9bf40a1fa67bf632c99347af142a48f7585a42794d0802cedf3f9383488ae403d28e10851d876c6cb30623148b0128426de6d40c536a4997203dfa71e89da0247d9e4c404b27a357ffeb58ae6af92e66bc99a76eaa4acbf22c5947600b913c50d05b2fae783a22b9caa62ac488510f7f994ab88a6025593b2af41bf2db57b00017c142b912a7a5976c45b9e5a089f3a5957567dd4500f45b1ec95b0b1c6ddc64e962014e11e306a09870b5358d1f2f8c2c594f9e82957d2a1a7b5a1269b599e26afa1cea9dcdd1cd21653e7df2eeeaa0ae6117054c44b646c2b7732376bab89a6cc749de041fe29a385f5dc74d5e3ecdefbaf3ea0da483421d74a49db5807e0021c2dd402215e7da51e30dd35e79559d875e54ea55d55e13d94026df7cc489745f406285a55f81cdc91517809f3cd7922ad731d74f4aa8a5a6da827b7d07cc831a3ed15b6f185568ff21451832850c8f6f600519781ff6659c88e390a8dc69fcb102d38a1bb4581d95e8c8584e76c9a5d69d2e39d69110780b1d6964464c4d25e4854416698d60efc1a70d6c64d2571f1f79dd75a02c959cc899952bca95228c5d96b58f720ade18545f7e1575e683740ae65b6d6dba39249cebc946a95664f25247884fdae28f9f0960c71c7f576249a525886a57e34f620a259483094d8a148f970699a9549bf2a6e17b0f0a375c2f5e915a6a2da79a15284bacba8a1d76a71212a54f7931b8cbadb88a470c794b2c86a9afceec16a79c730efba987c61e4d0802ebe440a945690eac986d461ab4fc996520b5b2dad8e898de7c4784a4c22429a1a5e1f63a2e18e56204ff6e149d3241ec6bc389ea6e38f026772aaaae44bb803c1d6bcc13a3e130d85a8edc02069fc16bb26991c2cf30dcb014c2baf7e992f3d9316ab2e454ab13acaea8ba6a3c04ae336f5d8b8295975e381e1b3051b121b9f28f2d1bf632b91671aa51a7c005572cbbc8ee6c88b59a7dd948aa41db3bf45c9b852cf2b5d8eed56ec066eee89e86b515168dd557639de18fc2e61ae99ddfd5aaf3c5fcfa9959bdcd7ddc4ab35d66f7256a60260d376ba13e2a59a4936275f7845457bdf718c02633358f81d36d26bbc5598c4b8d6d3bd22c678d035a20ac914b9e318295fbebe8c99ba39ee6c1a0eb2dfae87de3fdf0d6811b95639e601fde677e64e58eb63aac341eff63d0f21ebd5d98b47a476678c10b3ff543e21aef45ccb59d3ecca465aaee97b6d0476f59cf3ea304f4e3927c5c6fee7e16c25a26519a77e43637f2458d3cbe5103f19691be85912e58edf1d6fb40d520d651864f18bb1fecf6f70a79e40b7694e317014b6632a7052e62bbb294f9a681be07ea667da5630ccd92a42ec131c95106501abfa4a431c9bd2a684613a1dbde46abd058107875d3d5ca92f7c2074e852abcd1da0423462c1ce249873bd420c6c412b221d28b88e540dac848a60b248a4f89294ba0d47895b0f445915333031cead6654180d1cf75af9b5ea262f74d0802bf0381911f829c9c008dd8bb3da0f1807448211b1b93bc293c1186322c1d131638ff410ee5ea8ea2d2937d78b8410e8a31257f44c72c2e5323a52ded1b8974d0d3ea1698153e0c612e8361622248491fd1b14e75bca316b7183628b56d5ea4c45ddb7a88caa0ac922b3844e0913e47a137427192687098252156b33ac62f878e42a5ac7892b8c8f91133c53c65091994cca1082e578d6c22031b58065ad6d296d4a0619a74a9956d689293e0e062174119ca03dd8f84e5c4d1390fe2a11432d1730b7463e8e019437916a99ed8c4a726b7e9c91efaf39f28c1e82dc0f7af0214941b029b28a5a4d6cef345329a10a5e1b98eb4cbe6816a7e79ac1fe24c14488062f49805d496261739d17a2aaf85c988a243bb10c7acb51462e9aaa0c0622a53c3ffbd0ba376f1a14647484ecb958ca749246942d929d4a1a654a5c8635f3d6d88baa759d0203ae4660fa75a228d89ad88653ca441f2d9ca9fbe52782c7be62c8bca85a326afac05b367d76e96d6cc59f4a2350de0d87432168e8e43a7beb32bfceab8a1b23ad39dccf0eb5fa51951895a319344e16593b488ca03401669de1c218d207bdac9f2a5a74661a4b704fb48a272f6a1637da4443dc53cf8d9b5977e602b64492432abca55a003c5d105b73a5bced54cb05f055258c51a914752d1a52a7ba91db3489fb51237b501e4a0780df1dac96a15544db56c74f58a5ddb54178e80e5ad6029f8db4d0802a692f651e00d6f79fb6b8bf3c236bdbf930f7bed06d4f7c217ff9ab49cafdf7099a6da12b6b058746acef6abd8d484c6bf7801b070f3b9cce031e4c095c41b6e73cbe0cfaaa9ac4cdc6577292bdcd3a2b64619d6308c75c8490fa7937ce3c1ac25495c62ce9e58667f5331d726ea627d26b63231f6c98cc50be354ee54c0e2d31123ebc4e3e131b4a1400ef243da59df22bfd4c5b632ad92c5119026e7f4c95aac70e6d4bbae0277eecad345a98217cce569f828a80f5e2a49295bb1d292f9c9b640f3556b6ce33fdbd58e5c2d69f94e2acbbe9af8ce11d5b37691c455aff1128381163421086d4843af7993893ee8a219dd4c2cfbb8ce765e299ea5cb916b8a16a67ede452f9f8c0b4f9bd7d6b958b3adfc1c19bceed8b60bff9db3327e1c69cf76195cae4ea0910736ebe7d5dad6a1d13587032ce529df959979bdf24253ad6a494afa960e26b2ae9aed6b36eb37da8198f640d8adeb0e9f7bb454d6f6b2e7e868ea7e1bdcc89ea6f95c1de23ea355cc5d79f11fdc7d6bb7d85ab8063c371649ba4e576bcd89f15df5be1bfc65df027cc21505b4c20d60f075235cb2bd44b4afb781575d2e1bc19034766e75bbdbf72ebbb6a56e7170eba369917c1c10392748c72753f299cbbcab07567982f3ad6f565bc5defe761f9fc36c583177dce36e192ec867c2f3a87f94e11f7638caeb4d6ccdbeb3e5ea0bb7b829bd743a017c62befe28cea7ae4ab74d0802639de3f1965465b96a65af33e6b62c3f76ffc5f99dd42fe715e8981638ba1109f73e8426ee6c9efb9dd4884d58d7bbdbb4f136a4c5eef29707d6485e377084cf4af773e709dd897ffb4ca21e12c667fbe4834d3935bf5eec893b348a52a4efb8cf8e716c222447163801ef7beffbdf039ff717787b0b5c607ce3a320f9ca5fbef247902d395c20f8bf4ffe093cc08d0a483ffbc0a74081212c5de5edf5d195b7bcec678fb7d66f3ea1a5beab6b34c082f7c33ffef29ffffb35c07152b880fefa873f0a78da6bf7ef9ffc8100376440001ae0fb6540f76d1e7b5093c4ed5dcb951f7635e002de5de7791e7e0d45011e6000da5f85e1df06cadf094c469e00e0060ee02f682008d25f02421705a29fca959fffe5c553df255d76795db9351dee094736f9420aaaa0fc7560c57ce00fb2800876051e94e0019e600f12e1fcb1a0361898a941dc31c0a0ecc9e00c22dd3c995dfa715e47a040138a200fdac103644019668006a0611aaaa106a400fd69c09f495dfecd1f08aca1068000fd19a12f44401adee1fc9180194e003790a1199ea1069000fdfd212196e103a0c98e791fc435e07b59e1158e1dd9c5498fb8605769c3171261186adc779c801bfac2100261ce144012c25f1e76032abedf07a09347f4a1fc7d00333d62e4c552153ea0d84520d1d1d302065be7856227fad427fa453096221e9062fcbde11db062110e4533ba62371058117c004d0802fdcd620b721e0546dcffe43920ec1555f9991f2fba6005c29a1018a30a1a211c90c939c2df32de4132b62312e2e1335aa3486d9d1054e3fc5d23d498d538daa0244e22251a95ecc11c03626226fea21070a2fc3d61fc0d810fc2df2c061c48e4e3311e043bd69f3cce9f2a12603dfec23de2a335f2a3118ca3414622e58d1f258223cc05d516d65b422e64fc3524fc3da44802c3e0744345cae45060240bb8631d342347a2a0474e4cea18814e4624d490a43fb61440e622f9ed226f395349761d01c424fccde4fbd5a43ee61806e2015222204f8a2233ce234840642bfedabc1da548a249d795640d3aa5376e9925fa8d0d5260b95d25020e81430a0105045f0714561d4c80191ee2fffba940ef518058ce611d56e40af4de0864a047e2574780250bece3bff91655ba1e4aa6a44a4625d10d59497a4b4f66250bb0d887556634162318bac6595ae6993c9736a426c17088666e2667168f406261165292b8692669ee254da61d78a4a66bf4a4010ae541b8a62b62d36ce2a0fbd8e649dea60bc5a06eee266f5a454bbae40202a710f065c685a43e1a276b4ac6724e9473869614326576e1e2535ee14a229849d6de3876c007d8a70ac01f09d8a74eee677f0266ae48c07e1ae309ec67068ca71f7e0008f46761b2800a24e8077480340a817936a73572847aba20bf4d271a80a3754210418aa31a44e786e4e5019e40e05068ea282643e2816b0a4d080225ff1641e3795ae8ea8d68ebf1e2ca05a4870ee46716e436d6688922278ab2a551820469b668598e4ffcc46885eae335d5e888c5d2bd6599d1412588c6270339cc880269009e68aea4682bd59d1d18e91db8e851a428eaa4667b3d69684aa9f8c9a52ec2e79552d1df2d607df6a77dc6df7e32a863f2de7fc2815ff25e1b1a66817ac47a919a911641990e8c119c69e0a4e9b68d289641298281e353e8e875621eedfdcd765265fc2d41a3124199de90ea98e30aa28c8baae556ca227b55660860a866f6222f56eaa51e8f955e2996d269a7c2dfa70e29a3e2a1d395aa130e230188ea42806a5b2a41abaee96cd093ac7628ad62ea75dda8d2e5ea387aea84f66affa2feeaa2f5e41b6aeb469a69b6124c023d6a8d2e459b12ddac426b25f2687c5a432fbada08009f0950c01278aa122c6739122bfdf1a9f621a630f4640a009fa0b2400a9821f70503a09e00c1c6df61f6291492eb8c466adedd6815a8ebbab22b5d36d8bb56ab869800fd6180bdeeaa126080b8aa6a13ea65301c2797862b085e261c6c57b9daa6df552c8ee628c65e1e0d6608c776ac6c7cecfc85ac12dceb00942c5706dbbea22c56022c18b6ec065ea3be325108482cacd26ccd56aaa5e2ec8eb6ebb432603595d5cfca5fd00ec0d016edaa069d6bfee0131ac1caee5f971aab0a7ec0857695d43629d546c1b9d46cd1b9e7a55e6dde72aad781ad0a9a40ff6859d18600dd4d0802e1da9de1d6e2b2e6d93f56ecd5666db4662ad732ebb2052e080e6e1b4048d0216ee706437a961be31ac336829fd5426ee466acc64a20b37aed915cee0666aee61e81fa59a0e7969adc2eaee8f6db90f9ede9a2aed66eaddfa29a6089800918eff1226ff21eaf085cc52f82aeedc299d0e5aeee4e2aaee6edd562edef7656a50a6f76261df5b281d0c559ed422fedaa29f83a0494b26eeffaaef6e6acce9215efc22bfae26e42e6a0e7b291233a2ffd56d249cd51f762affba6aeade6edeeda25ffd66fe12aeee13a6903bf2afd52214ba16b5c3eab006f2ff7766f46542e022785fe7a70fe32ddabd1a8073f30049787e6491e0007b0055f30ff0667b0e665690c737031c446d0c9ae0df7e30c5f43ab1d6406eb6d75b2700b076fc5f6ef041ea40ed3302641aaca40edd14e2f1213dba40a2ff64a4410bfafeaae2e0bcde9df4231e4a5a702c36c17a7af5039980f37c50a5bb1100fb119dfe2fc8af14690f01b2b508fc9091be7cdc5a631155f811d6b280fcbf11faf67e97a2d1fff3010a7b11aaf31217f2f20333224faaf884ef0e3eaf1210f7022bfb09ac065236b322c49a7fcdab11e672f255f311683e660346bcf6eb226f7710f2bb2cda2b1288f322997b214a35aeba6f2260b192bb7722157302cc732fcd6acf526db2d3772040f73244f3128fb7225c7e92eb3472d3b1a318bb1f7865f0ab732ff2857f132ff323017b0117b991b4b4d0802b3e8de521def32876273282ff339ef71391b33eb4aa72d87b3dd46b30c9fe4359fb3367f2836b373b3d673acc6f3ccd6e088d9db3edff124e3b3e4363341dfeda6626924fe33decd9029dfad425bac3a1f743eeb33456ba8b245297b3eb47be56a1b73a346ab73365f342253b14683f3311ff0474bb46f56ae4a9b73499f34469fb34c979d0647b040bb342d1b31cf6ea83d97343ad7f4505f044e9f32e99233fa11b3313bf5bd21333b1b3551d7f436bb30529f300c4f9352b7b40e8f740a3774502bf4545375555bf55563357bb29453fb31fa6e2cc7d2725abbf2509b3534907538caf53f3e3319b77574d2f15ea92fff5c8bf53edf7559d77561e3755e03351933b69741f4c1542f2607b6482bf6eb91755dc30c6257f6ceaef4166b276d2485202bf57ca230396ff64c173666f38d669f76fcaeeff02a5b14872667b76e6b4fe965abf66ab3b66d27db423bc1464fb41c4dd70bb2356f8315629b746ed72a721b77b088b649aadc70437273bb696a2b774520b71650f714b5334b6775bff5d860f3767667c1754305796bf776b30f6527d5843c725cabf771a377729bb75dcff751c7f7f9f1b4fab2697eebdd7dd3777ddb378027b67f1bf85813381608f86124b8341cf8834b75832bf88233b884e3378463b80a5b788053b86e5b788683b8b36ef88477787a8c787a87788a839dc28497387a9c7819a8788ccff58bb7b890bc7834c838864d0802df78d8d5b88deff832e4f876ffb803f578a60cb9b406b95c1f796e16b9af2cf9e42639213fb99635b9914f399447b9e95e399357f9cb6c393767b97c7f399777b9d58c390187399d9d796796b997afb925abf89b1b729b1f9d9ca33984db391ed3f937e639f60a799fbff29ef31da0fb395213ba320bba401e7a494bf9a25b74a2eba8a39335054bfaa343faba567aa62ffaa56bafa67bfa99737a107ffaa8ef78a8fb32a9a33a800b7810000021f904001e00ff002c00000000900190010006ff408070482c1a8fc8a4f218683a9fd0a8744aad5205d8ac76cbed7abfe0b0784c2e9bbfd6b47abd5ebadff0b87c4e57b2ef78f579cfeffbff80637983844f758788898a75858d778190919293948e96698b999a9b87979e5094a1a2a3a4629fa7019caaabac42a897a5b1b2b3a2af96adb8b98cb684b4bebfc07ebc84bac5c648c378c1cbcccd61c977c7d2c6d07aced7d8d9d598d3ddabdb55d9e2e3cde054dee899e651e4c003efef5af1edcbeb50e9f8bbf601f4a5f0030200061488059ebc7ff3fa8ddad7249fc337fb144e327890e0c08a5910269c975062a07d0f432233e71190c5811dff15cc685025978d294bfe5927b2e6109232cfb44c49716547ff9f007b6ea12894e3c99ca6c0d914090e699978165dae7c7994ead1a25f343a15b46da9c36d5bb312145ab0e8d5aa43ab9295579167582fd5bce683f636adc6b108a98a81aa950f4d0802cc2e7deb668126171dddba6ef3b2fc79b1edddc78fc1fcb5da58f0e06485bb0d7b2b352046c05e208b1e0d797159b56739be1d96591a2fc16bd3ee254dbbb6e8d302272fce8d722bafd6c55ee754dcd98cede3c86fef969c1badccdfc071bd92d9dc65719676936bdf3e9aadeab2a19d8f7b15bdd574a7414f3246999ebbfbf777db5a55ff5d21f9f2aa50298cbd3e35fcff0076671765bdd9770a7e9c9c521269cc05e8e0838161971d7819f5732082ea78425d4ba60106ffe18720f6c4987578c5e6cc27182ef2c938eb85415f8830c6d8225e9fb583628a8868c8a27a7be126e38f30ea555981156a73098e9dc0224e672d3a06e49332d6b89b62d87882241d4a36139559f341e9e597a765676239b75c194796c104255f873e7ee926981e3648a62366c26109333bb5b9dc9b7cf63922814dce52669d7638e20c51e2b5e9e7a25e0ee5649574129a84a1ee603426a3982e1ade8cc1442a2913852ce3d6908a666aaa9b17a92956a78d7c6a4423786e895ba9a7d6ca676812265a4921ae1611ea2f914d35a5adc4fab92951c0f0daab2bbfc6c217955d162badb1628e256c2ccaf6daac3f6c7a382d7204842bee3be28efbed76d54ab9ff1031cbf6e2ec4b0d9e0b59b903943baebde1c2832f01f20ab89c69ba0292ada4ee9212b093fdd25bafb9e4f23b9ac2fa32dcef75ec1985ed20da0e022ca9b47e8b6fc40e374c1ac40b7f3c71712a594d08027b711e9f161c0a4f819d4c6fc8f52294afc3fbe66c2ec9214bdc2f1907f3c12ea11a8f32227113e7fc4fbe0debecb4d34b834cf3c4b3057d06c604e7613497c316eb73c9343f2df6d8538b2cf5cfd19682b599458bc26489d29abc34ce64d76d77c973df2c6fdaa4ac7d65db926c4963c5b5d22d37d876277e77d3f6463cad67a97a178adf386a3dd14f827b3db5e29c77ae78de659b2ae7ae78b0adccd64713cb2fcf9eb7eefabea07f8da9b77d97fefff7e96e93652bd38cc7fefaef9dcf5d33d8b60e587b3448e20e8975c2164eb2c8c0471ffdbca133da2d8590b05cb9f226514cb89f3afb2efdf8ae6bc4b4ec7d625fb124da63c87d20117eff26ef67936fbffd8e235e3daa45aaff91edee7bc4e5a0d2b53e7ded7e084ce0bd6067bd21054a68c843d0fbfa109568b9c970655320be0a40800278d083e2e260073ff8410d364e5f7823d7a98a643530b4af3c13dc8388aaf5a59dd9d084242ce10841182e11e6f087223421c886383be3092c823064032548043efdf54c8141cce1068318421e4e918a0abccb09a935a5ffb141820234c9bfc0773e13968b8455d4611a8188457b59518d08f49da6d6e4c53624ff51897f48cfb50cf83c27924f8a6e64a32081b8431fead08af8b3e11c0fe2bf3d00103861f403c5f8743804aa9183251ca42637c9433416b28de3ebddf0f8f7bd3a72039291f44b842e483cc6fd118e9de4a42c67b92f4f4d0802e24f94b70a53241e599854ca902f348c91225d193d435e7296c84c2615d1084ae0b57261fc7ba023bf88ca3574ef58407a9efd6c9949657a53996bb425f9a4b6bf103152557d40622ff12849d440698bdb04640fbf49cf7ab2f1964e6cd484d2a9cea5f83212ef7ccc1f7366cf82d63390cd7c9d16e9f7a3c951739dd6a420233bf6208692f375700ca741379acc79223294a08312aef8694788a6218fb3921f842a293d4376d0a3ff1c8de9375f2a44f445a942d244c343bdc2ce5fceea49261bdf21654a548e5e119f7052550bb5d04fa6f49482990391c45e19428d16f5aadeace2fda2a6c2867aaf0c4d0dc953255a4007b10e78e2fc2456d74acfa33a7394360d902e6752527f46348f70fbd0ce2eea3a6eb2158806304001041bd8c0fe55902ffd2148fbf8a05c2d150b61fdca5ddb4951f830ec6668b52a5b05fbc1c272d6b09e0d2d670f0bd38cb60e97e69cca989e51d79a4cd6388383d159fb0acbc376d6b01e2c6c0e090b58dcb29105c00d2e70673ac5df113146fbbc5a6bc5fa5aa0c92a4472fb9d62d52a53dfde76b4b915ad26796bdd020857b8075da333e3eaa0734270b992b5ff864e9e25db32fa3171e25cab76772bdafadaf7bad9c5ed77835bd0338230a1756b6539dfe32861a0772ecdad5a75a43a55da2212abf68db084271cdafc7276bfc335686901fcb914424842243da5534ffacba8ca08a37e252a61ad4be116bb4d080218bb18660151613a3db305c9c06ab02b89610bb31fd176849ab5a76e3b3bd8171bb9c51e8cf18cd5fa56f2c2e788391ef18e8d6341cb9eefbd64cb68513d4bc2237bf9c531c6ae510b695cd4ca55354bdd697aad00d0950af598319def97437b803adbb9ce73364098bbbbd179f6b07c8803d1f5b81265e64e196800ab28063d1745636e74c8d735f29d274de94a8b76cf5cf62e86c7ecdfd30aafb1ea22b415ff5cabdea794f53d8dc3a87f550ce92357fad5b0b634a643abe498aedad34dfbf044cda0667c24983955e6cebd8869b7ff6ed8a02b7675ac97cdec3acfdab37b96a97883f74cb9869ab58546f0a1c78039b35eb675cce4e86893dde2669b9bd9cf2eecac6dbd439a72cec6a09e2b197a6d985273bbdb006228a3db1de72e4bfadce74600025e9deec046bba881a476fe740d39b066dbd7f6ae1ac284bdb9cefd97d5b87531c0272df08e7bfce303af748ced4c6b0cb358cce1f5a8e78e5bde6b89ba0a866673f7f27d4346f7bbc8ff0e38c877ce73814f7ae47756b7c9339e690d63f2a38b632c77763def034f23e22e0af6766a5eec5523fbb32fd679cfb7cefff503007dd27a1eba6e2b3c66d306788b4f06b1c3459c0ea8037be2145f9de2da286ea25378d921e7badef7eef39f6318cf142eb2b4d3486da527e7da2e7cb8377e8d2b44791bcb3a4b713dc98d7309379bef98c7bc9dbf7e001777b9cfee7e6bdad9c36bc56bc64d0802ed2e5ab07be40e6e15fbfbeecccebcec33cf79c04fb8f228cfaacadf8d330031fde5e7d0763854e9edd657d7b7e58efdec97bff7da93fcc81afe6487bbfa1f288f1ae232d7c9a96da330e91634d3b08f35f3c7dffcbfbf1ac94b06f2f42d8a2ebab2fdf4d97f4a5eb5336cce3df8ea1ac73bf9f7bf75e783fdf69fd75fead761ecd77e210673d8377cf2a77a53c73bf0355493875de1076bfffc277009708109d0711878811a487b181672b1e665fd657663e36104f65570617aaeb16df15259231336c5166e11386e13a67ccb97811eb7811aa8831688003cd87331d671cc167845278080768228d8052a480d2c2816f3971c30188356f74dc8578314780015688138e8831bf8835ab885fb178200985b9cb672d5a77649f17ec7807ab4e3820f233e4e036754386456488137b8735d98877a98871fc781cbb76c814764466886a3472469787d8bd784f7b67a0bf48047474f5c368195367b5db8837b788998988318387b432861b8177d1ca634a3b474fd037c53d0768aa860f43733737775b8675ffa977998388bb478895ce8879c288648967b1d3580ff01064deec1166b8788f0a7802536757cf534cb547711168b98878bb5a8870ab081d3188dfc07889e28880745824a8376878763089888f1b75e0d988c91d74d54f87ab0287eb2a885b7188d5d588d17a800f2588b7d08867a878d11865fa0a770da5160a61805a8688ca9a7268cf8444d0802597671904883cdc88e7cb7895f088fb3488f12b98995a879ba585ffca87bbe5882f0f68d8da453c4f874e32827edb18a8ba68ce8e84d59e7900f6991b5488ff55891d238937a9879fa785f45d88b7e46362cf78dabb5054e271da9589050487571184b2ca98ef5e58c5c878f3489811b3095543995d168937b387e19a9913b894c66e864fea25c23c98425d92307c97aff622387c854850df96ab2089351798155599531990032198f37f9875b998d1c197a62038cc1785ee1b88265e984aba742551764db65774de9927b1797769987734995153993d58895b8c8777b59747c464bede6936766354b489404a98ac89892e7e8686b395816265a8eb9757e888998398f14299593b90132a9000b4093b3099138096bb7f759c4c58d95646d87187c24599aabc2802839364a39879667878fa98931599bf1b8000b709bb8999bbab900d60999d0888f5bb799adc68b9ba4553e3960b6219683b98685192727197709897febe8968f199b95298fde2993d8a99ddc899dfbc99de0b98318797efb985dba479ca25888c7798ac53805880677ff2303792a099d6d4969cf08975109a001aa9bdac9a11c4a8f208a9d759997bed975c079a090d6568b1398ec899ceea99c8b7894f6475db224891c97a1e039a2dec9a11fcaa3400aa0138999b7f89b96b68f5dc949bb079aa4384d63990b6ce82dab688e043587914667d2a9771a4a8dbd999bd8d99d20aa4d08029d1c30a6643aa63cca9dbd1999b6d8837b97a281084e0aca8aea192ca598784f4a9a326a984749a56e64a39b4487f539893a7a89b3d99dfc19a4625aa6641aa4684aa878e99b99399e061a9ce0f4997f0996f1218c0d2a05c97905f7b67dd4e38816fa8a85f59a78089e76f99f41da9fb7a9a88bbaaaff19971dd8a66e7a5facc9937ef93404f6a2ff0e1aa39e3a1b121aaa7523646317a839aaa5190899222aa2ab0aa089eaaacd0aa0ccba9b34f985b43aa91a79abbd887450338ac8e1a4301a1cef192fc78190ca985833e89af689ac1ce8a85c9aaa601aadcedaaaaeca01f27aa6d5ea8ed74a692a6a9e8364a9ba4a7d061890864098bfca63e56aae910764cac490ea2aa85a1a917b68931d7aaf3e4aafd06ab1214aad15a9aff988ad15b6a2b204b0015b80b5d170d816aeba5094d8541b6514836b89758d09b14f898334b9b11acbaa9359aff69ab323fa9d12a999200b7efefaafef0692392500a3991fe35aa7344a6c1ba49882c4989e95a53da783bce9b323faac8ada000da0b5213aa01f7ba472d699ff4a1a8a5786b407b3b409d2b4d8d39cf30989a46a0056cb73605891152bafdac9b5650ab65f9a9b1d3bab28caafb62a785ef9677f6982270bae2a8ba752e05c9e01b769f97d177a67f76989d1f8a539bbb718aba823eab51a0bb8d298956c3ab6ffc795666bb4dcfa31980a2d4d77a7ace0b66e281a0a3bb9b3e4b0588aa1ec4d0802fa8e35799d39ebb59cbbb3f5eab55f4bbcc46bb1fcd9bba45ba0a7ab5d227b9e1dd98d739aa92e27928d1bbbb2db18a806b3372ab30f7bacb0098ff5a8b9166bbcc13b973c6bbcea7bbcf23aad6a3a8f9968a4cd7ba0b414a726cb208ccba96479b059114cb48b9a09776c538bbba54ab3578bb9a25b93d32aafc77bbe5599beffebabbea16ba8188895f5e8b1924ab8659b72e1e37b04eb04be0aa1dc06aae6f3b2e7e8a7034c6e55bbaeb0199177899901fabbc4ebc05409c1112cc1f7caac15acbc7c38b81a1cb2458b5825d87bc7b13e9b7a0ffb2bc208ebb2dc1bb37508be768bb9efbb877fcbc01c6abe34bc01367cc3eb9bb31d7ba23c57ab85aba455f58b458cb229dbab2b2bbb26f6826859a50d0b5ac66a67c82ab1b468a8d1cac5c09bc55bacc7c6ebc541cb85a61b746f4ac6d3b79ebcaabf6b9ca77a012e00dca702cc46041c582c1cc5768c897f1baf0cbcbe7c4ba625f0c9a0fcc97d0cbad849cad12aa2812cbfb64776a97b4f87bcb8898cc48bccbf4ea85202f5c8e819b3ffad59c0ba1bbe977c89559cc700cac59d3ca6a11ccaa37cbcecdbaccb3ab136a9cacf375f95baba8783c8b15cb0b3fcb80b0885500bc9ba3cb7950c725bda9bd29ac7a4acc7c5cc01c70ccac9bccc0bf0b5cc7c97a3cb8760bc73644b76d31c8a4ba7471fdc10e24acbe42ab9908cc2bd05ce067caac9bac3c05cbeca8cce9d5ba6eb2ccac3abc74d0802ef5ccaa72ccfef1abf193cbfade695717a86478ccd50cac8fd739ace49d0bd35b3508c87521c8ffa79a8cd0aba7ebcc7c2ebaa115d02edccc517ad9b813bc8d14cbfd09babacfb8f490859b0dbb6000d2fb32b3cb6cb92738c8535fbcb7a18cce63cd3348dbef57ad339add3f14ca2f0c8bc840cc441ec49ffd4ac374099536ac8b424bd4709fbc6b5944c934cb7077d8f090dbf98dca3312dd356cd00e9acd5f5ca00568dc3b02aa4534cba910a72432bc763fd464c6acdc3a8c6e6c1c6c16a33c3dab0574ac973dd87bc6b9db5598d1aabd77ecc00a2ddd711cdb3a20dd8816dca8cda9d859d95f5fc71898d73876bc68efdbad78bd449ddb22fd8cd88ebc406bdd2e2dcae57b9c040dad0a17dda59acc53cfbd7a79ddaaa0da4099cd15ee8d3637cb8683bbd5281d6ed89bd6b3dd95ac4db34e5c44f0dd5350b8f311cd3a57cdca7cdd77cbcdcaebadea23dd3e9bdd3139b97fbfad349aa49651cb0df1a925c70d49ac0b234b7b0914c5f2acccb961bbef949dc9f3bccffeabddec9eddeef0ddfa8edc7157dca5e6d8d3ee8c3611d89ad0c48d78ddd3111d2203cd2b96d290d78c2288d5f2a9de0578bb7305ddca0cdc5143edaed2de1645ae3154ed1ed4bd8f628c81b8ddfd20cbd654d37671c3469bd096cfc84f3c2a7cfd9bddf4bc7beccbb5cead9f70acfefacc73a6ee3348ce365bae53b1ec1c36cb10a6d8b870ddbf79cad44ce611fd94d08021d45adb400ae22dd0d132eebe4059ec22b0cdcd449e50b6dcee94de35bee0011eee563ea00606ee1598ee11c3b8b401ee4ab8ccf235be428b49efc9cc68a1cd927aedb4d0ede529bd2b9ebe22f6ede0c0ea2c67dc381ee00827ee35e8eea86aee316eece678ad11aeee89d27cd8b4db2ff41d5df8f7de9dcadc4cec57de0dd687faad8790eeae53d8b542de3337deaa83ee884ceeaad5ee3affedc3fcbd9b478df8f8e7cb82a8af71b33fd9c0a26eeeba6491bce09d7d1a9e7a59bb931cea3331ec114eeec5e1e63d08eeaae1ed8001a63a8fce31b4eeb6a5ea91ddced794140962e90e1aecd92e1dd945da1b75bb975f694529d87ebfeb97bfdeeaa8ee3f23eefd10edf888ee5f8cedaf678e61e97e61faedfff2ee29a6aa790fd0d6bcd9c13dad4e6fee9526eb736ebd2103fea570ccf5a5ee3f06ef11886f1f42eed144dca3116a0d2bda63d27f2c219e96c0e92bb2ecb982eee014dee146aa1081ef332cfe7407bdeca9ee5800edfa9dee584ce01ff17eff3f5cee30b30f4446fd7a9babc61fcc380aaf4fc7dc6a577db19d2dd080f3de53eec072ed7e8cee7c86ef312dff5ebddec152fe1634ff6407fc3e98df63a3cc544cae1d99edfd325d4c304cb0113e789c0b2febb50147ae7975dec568fd0998bd7556dea14ceea3b6ff83deff3ac5ef6628e9d688fd735cff66dcfd1902ec4948f5922ce1b240eee4f6ff0074fc2b996948fb8984f4d08027d9fb458ce418ae539eff5a85ff8ee7df8ac9ff88a7ff618f6b33d5dfb1d3ee4aadbd8f88bc629b8dd4a3ee791cb7dbaffd6c58fe72d4edec77ed77edefc830feda91ffdabcffaad4fe1161efbd29aa63d0c0408e15078301e0f06e5d2505016a051a994402854b1ff59ed80dbf57e070231575c36970369f53a0d70bfe171f93cceb69ff1e33298efd5feaba60407990a918e8812111286121c1f1314221f152a15163033351b383b3d3d194245191c4a4b3750535139585b594b6063615d696b6d594d4d47453f3f331b3483172c218b8b1591110e930a9ba09c07a900a709fafaf6c2f2ccecece8bcbfe5b8d7b4cfb205acada9b1a2d99d9a95960f928518178d2325292b85377bfd7743e53aa52ad52d59b26e25b425b0144006fe3af1e3b7ef9eb17989e2bd7bd62e8aba69e8be602387469c1a7027bf954c33724c36907c3c5ab92293639477f12e3aa25711922589fd207272c8d001c182b60ec652b8b41551874139fdd4ff44311fcf7a17952dd3e8a42614991e075479d985251e956d50a6ada3b22c999663b9c4f44ab3ebcd65391959edb94fea02a80d861235ba0a69d2124c991275f034e82fa9978655b28a7548c642cfa0755517b71adcb26655aa15ede6ec673370c3c6ccd295ab3b438728efc457151226c81281f9851a98e1e00d060d235eaa7831c0bf51fb2ed06b719ee5cbaca76c46ed564fd9b3a3459736fd16aeea40354d08029fb85e829372cf7b7c6ff3cbbd1b2071dfc0930a5748bcf8a8e3c8fbea9b8c556b33e8d1a9998eaced04b80ebbb4b41b893a01395387b527ec826d9e7a28e12939dd30616f14fade2b2c3ef96ea18fb1c67293c812da96bbc8b92536d2cc0ab0ff0424b0c0d00e442941721614d0c1efc06b22424426ccabc28a2e8c4ac30ddd1b0cbe83400c5144e3482c7122c9967b44c5fe9ecb8c1def3a43ada5cf0cac119c1b3f434dac1de96ae71d78ee0ab2cad92ed4ed9ff638f4cd4ea39644c81608e8ab8f17122f4431c5e60e5953cb76b8ec722c02c314d31b3271e40ea433a999a92e43c943c6ca2a7dfa69bda0e8240e823b493daa16c30edb934fe246f427d04b7842913f2c9f630d2cb16234ad5147e780140f061b74103a430d6833190a978b2cbd60eee38d2808462d95d43c9552b54f281beb8ba241672d74abffa403d69c9176e575ad92da62d0bbff88355653d9ac8a4caa6677a10fda68a5b593da59ff545d55b1567b0914932a63a39589ffe6fa88c1ea582ad7dc377c2dc7a5ee52938bddd724c4aa222a8bfc052267195a35df3bf74db51607ee7dd2bee31ea352af82bdf5cfd6840189cb4b86c975d8dc8871a478dd8b9970d74d971dc9c7b6793304b55e51451eb9c35383ebd7df7f77b9ef279fb8bd32e6836d8dc966cf18d599579eb551d7e2079b115a53f3ee391ab74fe75c5a31685176fa695a50bd85cf9459ad9ae5ab25234d0802ba682b17d1fa08626b4a545190c2a6f16138c8cec36c8f2e156fbc8c15113259b7d503e6c880ecdddb6e253d64526abafb5ef92fc0f3a18d984d0d3702718ed651ede6edc47634f25f29ae18908b2d2f56ed46de84d353cfff3f0e3597d1f36db25f94a766085ba85a16743f640c0eefd041020970f1457177fc71d2d822d0cc60ff003e6dcc332fbed3ceff527e79e64b75be9694f9a65af56c4d14dc7ac2b197bd16d1ee45e102db39c024bef1ed4e6263e9ccd9d48429f6b5cf2a275a16b3e2273f53d0af7ef673c5bd40a8b23ff10f707ba9086504089dee05686108b48e021fc7407398a91a94bbd49a86473cbdec832f6ffb1c2914c3c16979b015205c55f47201304fbc4a3983bb07cc9020b3aecd4461b9a20e39722726194eae523c5213668296431d168368719253dc44912421decd83462c051293e83757650870c318d45514913dae21aa801fc115f8c25792f141ae7c2c01ff965cbcc80e67ac6f8289e094199526b7deac918df673e31b5337c2394a2918db7a59e192b1a25a6da98f35fbe3a2ae8845183e8c81929a14a57e97488e3012481adb610f3b77c64f68707e94c413115961c4238a30147f33d1c03e89c73c6e6d94898391975299872cd6a895d87809aeba98a65962ac96991be3c67089c10c222988befc253085f9463836448ed43b6613f7a34c8c30738f2e32e04b1a278e4142ac90869c0e36a761a96171d308e54d0802495638c5993c490a045f1c44956ff2261fd439657abed0d6c0feb7297956869e08a3d91672758e7169639a076aa58e1e1850594603878da407bc8824afe345328da2a2e443071351e14c94a2fbb3e863ff3291519de824941d55e1336f174dd008729f00a8e621b3d9a31f75d391b2f91fe7e04753d03daba1f4c3a951748a98fc49af9d3fbd907e98133b667c8b8fb64bea0b99bacf934255a5da14840491901398b66d1833fd21d36e6a1888466da73c154845cdfa9821a555ad8672a6776e97c0b80ef2a95c4c9f5defea2382ca6342562563d1fa622485d6b44e42fc2a41c29a18c31eb6ac739c9250890aca004691ad5bfa68150fd8b055eeac9ffeec4e0d21c852cd8631afc7d29ca05a175ae4a171ab211b8869059b53c2220665d76a6dc0fa07db631495b652b4e73df129d9c9c6b0b7bebd26702b55395a16d4b8152cdafbfcbacb85e6a269d04dca603fb4ffd33ef9a99880621ddb4ec8ddc3d59680b8059b52cf70960034b59a2275207a7f87b6e089d17d08cdaa7cc919326805f6bed2cdaf58f78bd825e24718afc3c7f596d9dd664683262c9cce97e0aa4fb996574128ad6b8f26ec527b5409ab091d2d6935dcd521d68205453672914b96da228e95ac3e5da25f5a563c42a978c5dcf35a0bc5cb0d06d3b81cd6fc6d40051ac11c17776d3bfeac2392731c5ed257c824b3c5918f9ce4e97e90c9ac75724492e33f9e4c79c06b7a4d08022c5273abdbf1b292cba7f1f22b8585d9294068b34132335a1390e67102796e4ebb059c8d2ce70fd339c4d725b16221cdd879d29345df757178032963ca165a725f4eafa2a5c068e2ff52950843d58ba4ffdaa736ebebcd986681a64d77bf75c6f1ce9fbeda1d375a848e86e7cfa7669c0b63ace519a36b3b340cae225b4aeb5a6b2e5616f6985681c8d5ba8decd2be06b69e848d49fd69122267fd6463abdcd69a85e566084ef06e75c7ea3d38f8c1d716ee7a396bdc479fc7db490337d3c6ddbc5e63fadcd54a7775d7dddfd5e5e73c00e4b3ece24d4a857dcf1a3016b4aa17a86f575a1bcc689b357b6d59c1827fbb176b86de86c9bd7038379c5fc20e61c41f3271a9100cde1967b18101a92b7c6b51e423ef77fa100670839e98e01714c6c1e7762f4bcb3ccea54315ba69914e9c1bf3273cbff85aebd96c90be389fd25e35b54d43f2924b55ffe9edad88af5980eb962fd49ce704a6d51d4e8b9eb2fbc9d5cbdac5bddb35a03f1b67241d3a358b8e40b547f8866d5f1b4fe0ae5ce636b7287557c5dd13a2645c3499ef78f67ba8631bbbc09b7aec818e7637ce2e8eb4a3d4775af00adb1beda67b447e5e3f0ef7062d6f2acce36dce4de1bcc4b1cbc9a9c0eadd5f1fbdd84b8f6a68ab72d0634bbcd95abf9a2bc0fee401a7e0db7dfd365d8262beb9d7fdee5ba1790eec1df816157e50898f6201633cec88ba6df219e792d3b361da688f944d0802d1d1e1ef7f5f8eccb28704ed9f6ed228aff2bc0ffca066d37ccfce3a2fb1f8c1ebd60fec4a0df906ef1a3c8ef9408ed0446e866c2c9606aafa96ae1800d0c726ff6f920ad0005d41fcc82fe7dc69e7fe2ec5faec60b60740ae2cb7464a9a0e0f3b14ac2d0eedbcc00cd65ac4f1bc69e01c21040310ea70af044df0157a6ff314b0fc46ecfca642ca1ed0b1486f02c1e02de66f0dea4ff50c6907112dc27cb03580d091b8edffb22fbee62ec30830f79230fc9670fc7e4f05832f39a470b65ed0e7a461069f6d4072a6f9f2edf9fec986c2d02662cfb8e0ae183221048df0b9d8d016a60e9852305ba0505eead005d9eff800848afe00cb84ce0fff900bd365f1906e1009d1030dd1d710111314d1f604c2fb08a3161e918822b1dda0ac7fe0a905398acada4f105668dec82ed5cc2ee4ecaf6cf00f2620ccf5a68ffaf84fdb76ffe2107b4215b34fcde8ce156f21163d681637a98e5224f446ed0e354b0237b1deec8d243c91e8865172bcb00f602996c210af98d11e9c9112a011d3b62f0d29cd157fc311630e12e35012b511f484c4f82e83d9340ed0f6701cc5a0a446a3b23630bdc46cbd28231edf6b01224f1ad5101fab711f65b1099d10bb5e8b8c8806858c0a5cf4109f107246ca11f1ceb1671a72ed846bcc506e1e247236684f006f6f0d2d2f23158e1f896d01fbee2301cce2a6100fadcc20af41fe3e2e18c96b2559d2d55c12db60d24d0802fa92211e25c1125691158fb011615123af9123a324ca1cd00e2f3102052f1c398e028111f5528f1baaad259151bd080a2fa89226cf90e530ff0cc830521f7772237bb223450b2cc3b21bc772177fce17232bcbd4521841b14c9cf229a1720cb70dfb30cde90c6e11cbc9fbc40fee40a41f69711233e14dd40a02bf91803411a44e49f992323197723119930785052e4dd1ed40d0d728b31eef72004930f732d3dce483335d8b0e9d28c086722063501a4a330bbee630fbf00231903543f195d06735566ad1866b19dfd1d6cc70328fc73601c3e5600e33df50337bb32fe5d023af06990467bb86932cc1110b381131e96f0befc09fd2110c008a1d712c2aa532328d01ee6a13392c93cdf07137196e3c75c1d33c33a8d0b3f82c51344912bc50330b4d423ed9e039e9eab248118cac733f1b61affcb336edff92fbd450405d914067ce40d9a9d87eb293d273b1849208f48820dbf334d1c1d052333ed7723e6b4c5ca2af7632543f3b6be03e54ee6ef326196a40c3933785833ccbf3375954bb764c20098c173bc228d172f90c2f254d2af1f8ad315d6f3aa973aa38f4fa126048d1d01e71f38d90140159413c97f4405574454b6c1b934dd974913db9e7fddc93de685042d122472bd47cbcd431334b4cc7943fcb943641d42229ad154b34490bf44d53d4273d8f05dfcb22b8114663b438797133ce920f6c743995b239d952508f4eff624d43374d0802f403bbed3f6dd248b33227e5e3ea0c63b5e0344e8d4d416f71cfead44e0753466deb3891934f83ae06978a39798b299bfff20b51b5148154366fc9556d528db412316835296c7552fdb2522702995ea657b3c21b395506a5e353af50f1fc74c128741c2cb47754a3f10af1f136461f40943b8562be62b5ee40e45a0f62d8f8ab49b9f598a0148a06b335669446c3eb245112599d4f594f435dbae0d5e03536e5b5e9de4b5a732d37655538f85516864dc402b6c42e6160bbc51b0db6c09ccd338c354b19f6134bb5352d4bfa80a6fa0e55085db45e81024d611527f575563b1616880960e5f4495124a3bece4181354f85159680053eb5705dd5c05403915023083211d518aac28cb81364187163adf5674b209328354179c875f66c3d592469337169d1ab69d375cbb8b418bfe06766ff964dfaaf62e3254e32b697aa9529c0366cb78eeb3ae933bfb55753486d8bd29410f64a9d7642013550dbf2545fd3e436b4666dd6182009dc8c342f39166c714e6887561808265335551707a80ac3d1f46ef4691f975d23d7351db26eedf63ae1c56cd18c48b132eaf884927412b5de307075ce522783747dd5644f9694d816b89473755957319d73472597f1ea4255673726a1f5521fa14818354dd58d77f5d277d9140e391274e5043893a9e7b8665ce7227953e3add2555da1762560766a4bae1dddf11dbf8948e0ebc2747667d5c97bb712ac7ed7374d08025d25574537285f542c4573915c847d1717542b90655bd66575d4bce8b70727b67259b55571b74875ff0d806901bf824defc6977a0cb8af76553843732bd4d747fdc85c4322826df006b7d461b9a34b07154c09e17e2df77241b25eb7977b138e837a571550d02b49e8bfce0c12ec6185a71465e12fa444755449b582bbf042918e7201ce72dd07857d686f05638d8a38158ef856b7753daaa77586d770490d710bd330c5e57d9bcaa9e21687f3af47dff241f4b3877d387b7b0c28b6d6e5787674c61815caf85f41178d95b81205f357f15469cb1586bd004ba71847e3370064e48227578bab978ffbf87643ab32fb975ae9a79037e0904136649f3485d5af9117d88d8df3565e6c6567788229187215c485ac0d8f57687aa93753ca8cc7325773f78b6e76cd37dcff942f95e8c912d45baf878defd4a3b8e4173bd196cdf179d1516efd601d633783c5a889df446f83b898eb4b5a92b92b975995bb8ee012b84117589a6f459227b9ec54d3795f76f5a27793951198c9748967036783d87f4d41ea46e69ced0791dde9848f06249f4824974d7dc97513f754752bb9795b376acbc48ef3ef18bbb96a37ab6655ae42f6b7087f48a0ffb7a0955416531940b5e54400125cc3359a61b9535f589eaf8896b781866bd886610c8bb39893295636a9c4a5414bb944b9484d7a884bc5a09d279d195064cd43509ad889fdecb1d83739135661151207b7484d08029bd5b1a3b729dbeeb662330a676bf155f7cb6998ba49563a74a3d08430155c37ff75a6a9e8aa89d524f9b0a21df79231395dbc7a6e79f9475d23788467acaff73cf4d65e1dc2a4d53aa53d08419f5a5759993988b7781d19a2d7b724c1476117968aabd88acb46031d28b0798414652da8f1627316156e264f881b3b528908573104a8269bb24b565c315b4fad9071e5788e733014ff7a6edfb572f638363ef96225ef55fd97c346d8159834919b991203f3015ff9913b55b7a3b8e31cacb77dbbe8722487a9963aa9b7b00d9b78f66a63b437a07796b9b1ceb9b5756c5f25fdce97aa6110b35bccadfa9479f7fa923359932536833558af60aa45cd9ab55b1b56d93befdc7bb1efc33389ba78a0399a4f1775f7d4a6f3ba71f7fba2fbfa75f3ff190c819a6637b882fe78134214a937778d5090c1ade6f3e854aef50861ee3b6529da02adf99ab1795927253a4771a0083b1e401a3b990e7365aa8345741aedabb95b41c5fd31cf8ad67aa6fa6835c2baa914bb1fe817b57aabb91a10359a59c150b07bfc9b8ffb19578e8eecb53b7923c16b8e169c9aa5e3046b1bbab22dfb9de93ab361c4c2c705a7c9514b6dfc9e5932b885fbbf6597bccbdbbcbb6d2f80d8c0fb1774d0dc64d41cb24bc4c10937c865e5a5e8bbd4e63c7987f5812158a430fc4fe196a7974f5c6cc8a3085bd0adb77dcebbe90e7db96c6f1416fd161cdd8c20232827dda1494d08020d33cab2ce43eacaf57ccf413b97453dd1d4c75035a676f3ff76cc2342b919c01a8763b1cf58b4c856bebf9560c5d52660dc6b349d0279bdc67d1d977774cbd551c7a5373f0d958f215c59923ba0995d219c1dba3fa5a5a59d5761dac7bfc5bea93ca576bd9a3d7b356ffc61fd5cdc47bd033fdab897a32a46ba08cbdccc4561dd13c2d98d29da871ab69e9cba5f199ea99c33a859dff7fdb3bd3db42746149b75ff68b68781fc96b4f7a8d188e161bdad155a646d37c0e03ca6713bb73be2de317e79f5dbd33fbddf717ca3391a43037de48b7daf4ccc8fbd58fb12decc55de16581e79e224dea73d34abfbd2bf639aad08cf1312cbb3bc8ec1dd1801fea767a9d43bd99385b0456de3d0935e2896be1670f509cd08c2dbff3917db9830adecde273ae3731e7ee7988ebd5bb463f64b75d8a32b97e4cb305ab5b6c1d7bed11b7cb9de1e34e35eee71fb7813a74a3dd5ce2f9cbbf7feb7e9f3dfb7996e83dec7873ecc27f2f08f23f15d61f1dd1afda05ede6dfd4e693e715fd86d29b996b9bddb5df7dbbb1e26483bf0a1b2d4f9196fc37998515fe9b9b2151abc7c5bda99a75b811dd9da55c8e6e358463a7be339fef6fbfcdf536ad433547bca3dc485599c87bf13187ec56bb17a58b94565ebb69b9fd4abde4a0109ebf3bcf65512d4391dfb2336e0835ee8433f56841c08148a05b16824368c8d25b3e96c6ca2d22975c3b962afcfe7b17b144d08020a1389b0b86c2e23c48835bbbd3ec0e3ff7003bd6e2fe0f3fa7d9ee0ff0306fe0d100c181e22261a0a302e323e4242064c52564e0260666a6e7276765a8206448e3e3a0a28a2a6120a06f6f1bde6d9c9d6c9c9b9ddba9d9929e812097901236d6d55154b65650d2f2d24057781edea9ea5a9e1b6d5c6cdd21518c07a17b08617faa996970e908e86827ab6bb7bae57a68fa29f972b92af8aff7d7b6bcb6283632d97345dd012f81ae24c983262c68a21c3d270d94223430a8a2153adda4004010ffcbbd36f0f813efb02dd4b394f52bc4bef5ebe6c496965294829f19d1484a7e4483d21e97c3cd0710dc6a243c05464d644a9b287102372e0c2b459522245c798619360a8c7803febf434b93327a09bffa94ed164243300ccb6edd68a4a4bcfeca141647786ddf3f323576a5baf9e01f3ab22d5a94f9c56811a75a9b0a40a17009ed6f7cdc77fdcb6e5257992105d547259b6742b7a13dccf913a1bb29b736c66bddaf872dd5886d755a4558b34444c453193db167f45d635b92b36cbdc5a8333b9193522b4a605ac1d2d1d40e9cff54ea1567d927566cc21610f45137cf6e3aa4e0ceb9e328c61e1aab4c713ddcab5f257e4fc72ea2b84dae6e7e8d347af655a3dcca5a6df5dfc74d7cd65af05d4976ce395771b634ca427c57a4cb967c4781cc937147ddae081595e6495350e81fcc9e5df7f6e0528178189e473a01fc881f55d83b169b5e1184d0802bee1a60414156e40ff5163ed2df48b46d2bc87c670c4d51212727c90a8df8bce5149938a2bc2d4625ae8bc58605dab81c3535e602d0810781d75a823423c76b10490411626e46dd01c199834c37d38cb93ae8cb55c97545eb7125c58b2a8e596f67426e5817b8af84f500eaa5986456cba09245544ba57e718494e93d57c793a99d98c6146296567d83d3728a1591a2a2073a6deb5e771213a7ae64059a999508449bd89a96f9a02b624655e812892a83c959acf94a6a9baea3bd53d871d8106c63a6a8265cef228a47fe928d8ae0bbdc966110a711a99569305e52499c7228bdf20271ec2ec95cec2d3ea3c81be1863b5d68eb98d8d37e2189f41e592375855e1f22818646a0acbff6493c68938e27df879c95c2381a6d52cbdf5ca649d29d32242229fad2988ad1ddac6265eaee38a4b84312d2f1c29479f120b62887bb64bf1bbfba198b14c1b3f6befbd8ee45b60ac61d2e853adb6de9aa3519c8e6bb06f2f3b462ec1c17aea61ba10cf2aaa1e24566c7123a9fe0cb43b42a7638ab4896ab71d77247f6540504239d8c6d376eafaad33543ba370cc3277a835a87774137158d6821d36cfd14257b6d91cb7e4b14dd3262ba69809fafb2f360d775b309b7c3fe3ed7b495eada49234d7ace771251fdb27c59c9dd8b395f33eae09b43461dc65e562d1e89de6b50c0778607e835b4ce8bfd9491e467ee13978a8ad2158b9a9f0623c8fc6b5db8e4d0802ffb68b9427dbe7938dfe6ecb64a64746b0d40b9cefb2f1e81f657041a5673db3e0c5c56d78ebd277196ff5d6d38e3d75da6f295fe38812efe0a6a0bda02c607e314a51a2263a21bccc36e813decc02d791b9fd6475ac9358e5beb4ace6f4a77fd8bb5db474a72891c98a56b1089ff820e534e13d100cc6501805e5d73ce7adab6bd02355e252f32754ed2f1dd7f3dfff0028bbb5652764284450efea3737ce51b05c5f3018b06a783a36b0208b5acca2c31e561f598daa5446fb21e31ae7382262022e71b1cee440f62519a59056717b62f0d420b32aee027e805ba035b6b8c5add50f8c61eca1b26257259f89b0766a7415d104283d7ea530734b03d8b604a6ffbce1d5108f19d9a470a8d1113f6a1187beb3dfe1261625c52d8e71434423095792082466475fa58a632c4c66a604862770562c5fe90ed229f958f016a0cc62ea6ca643fb7ced943e2423aa42784634a6d188a7f99823f323bd38d64f6eb8dc56a4347510d2e9b128c319260be8f7bc0db64e39cacc1fbec8f64c682ed263d7c9df091f79b926ce918ee3231f844887c9d9ec7132e49443206989b85316725917736768a0993d69d6a48decdc5d2b6829c7496e6e49a7db654099b7a481ce216e168d9e1877a6d078c9eb9dac6ce573d869347bde339208dca6b038baa186e162a05fcce19300c1c30ee6cf1e29552911e329b98bb9d49a2824954c0f38539affee3338bea4204e4d0802bbe845cb182b8e2581a94b911a4452a8d1a10fed98ab245a346a1190874d752a0b5b58534fd974790d9b1b48764a4afbc0d4a4866ca633895a54960630a94a4debdbbe47b8afd015a792b164a408724574d1f58b1655e72397c9ce23ceceaf7f852829045bb1ee159651ac436c6215abcbd38af3b155654364453a59ca8a316449c5aca012b959b29651b0b002edc8447bd1a7324da3fc04e6153bb95aab5ed5983ceda9eb629bd0aeaa7295f0042c234da8c45916109bd9d4a63eab4a5c0ec92f6b55a56b5d33b84283e62cb6faf06c19cda859ff19b5bd491d207db1cb445989249fdd3deeb92cc95f3790d7b5cbed294993f546e8b6d7ffbd0d156b26d4b8c6dceab69e69f5292dd7a5dffdfe37c3b708b06b17845e53aa7715b34db082e3c160d250376dd49ce8f476175afc8ef6c250d5f071c95bdeed8ef472f843097441c8d0059fb888b895279760c9bd37cef2beafb52546834be3b9723883aad3ea410d9c1fc17a355a0e0e728353dc59b545981c79856424990cdc8cd2edc94bb2f18dd595d514de137f2f1d315f7f6c622e47d3cb7399a64b4b94d72563ebb74d8ec3b0d2ac666bb0b9cdc691638eab1c62cb5e766c650c2b9e853c641745d4b3b28429a03d6ce66c25fad0d748744119dde8647295bd289db4741deae0043772be5efa33d226cbd66c265a2034ceb5a29f774c381738af9eff1dd05711f9de9572f6cbc356e24bb14d0802eb3d40d7c889bcd6f59aa7ddeb620d38c73f75ae5e23ad3f2d53bad2af86f02296ad2c7b3677c916c6b5b5db1de50ebf19ce9aa9ac6cd92b5470b7dad5f12532a2fa5c96c12eb5d3175da1b4dd6df06c6453e05f8312bd97fdcab545d7b6fad6f39ef93cdf7f733a99eadee076b97bf05c77fc320a8724579f3becc945fcd8c8a67860c37c5d74d77ae382deeec75b8b63532fb9a2f644f2f4104ce22d57bacb2c6ff9c55f3e6685178e4c1da745cdaf6d5ea5017acc3c9ef3c949fc08a007ddd291631c081d2ee277d1fac5155eba8c6d4e7659289ca9b005ead4976df512df39ebe32e214abd7ee066f336394847fbffcccfeef750c57bb214de7665ffedf0d3b03adf6275f0835b3a4fbb8b99e71927b3ad39fef7cb1bd3d302df6a7ae9dd762cafbad8fc53fce2e70e6b2ed95dc4787fa4eb044e4acc639e0fe8dcbcd471e275694514df1267b0e9b9be62739b34ec0b478e054e60fce3233ff9ca37fe0542320214403ffad29f7ef447a02e3c5c60f9c987fe093ce08d0a683ffccaa7809c557f78dc4b5af72a9ff8d0e7f278af07ffe8ea6c8d06c8697f506ae0d67440c1fdc98982758b48fdf59f1681803764c000f65f06945fcfd99b8fa5dcee95debe31925901dfb9495d7a65c60122a0fde51fd41900ff6da0169d80ecad8b00226001c2820686202829e03aa55ee8899effb14120fb251b9f5160057e96fcd55a4cbd820aaee016754d0802e07915c009fc200b8ca05ef081090e200af66011fa510beec367bd20bec46066911eeff59e80f4db0b528be4090208aee008f2a01e3c400698610668401aaae11a6a400a0c9306109c8210212881001b6a00080cd311be4204a8211e8212099ce1047843199e211a6a00090c132016a2193ec066601c03aa9ada2418d6659dd0b55fda00d114ead53e8061088a21e521c71cfa111cc2822802a14f1480128a604fa862167d404fb04201f8a11f7d0050a192dd9dc3db315e25a29804bedd145e9917fa81296ee009701e28e60531661129be8232b20033e6412b1a212b0ed32b7e0388f9c10754e3ffa399dcf92dd421d91990f122e335dedb195905b698203863ff1d612c3e893342e31ec06312e62135829235bec27d058236dea30b06e30b9ad52452222f6addd641589601a3352951276a11146ed11ff8a016d5a2c6f5043f8e624fcce31e48a31e7e4344baa237f08b2058e416d5e2eb0842427a9524aadffa9d1839c25a969da3c3191e2130641639a41641e4369284de7dc348362446be213d8212471a60350e1f5e34d71ff8a42b9205dea1e4160a64b811649ef9221be55e4ca2a381d4240bdc6416e5643f5a4e45c1c252722550e29f50fa1151a6a051224d9c8903599664142a644256cfaa25de157219e399639dd1e57ad1e43075250bfc01052c5fff07b88d1e4cc019226216a9c0f1518059fa511db2a145aec0f18d404f78240b4d080258e3e0e5045c8683e274e3eded256848e55416a441fee20d429e943863605e933e12005cb6c63ade9f5af64366be62b09d84677ea6bef46515dee50ce6a55e92984aa6245db6e61f3c64c68d856c66066dda9f6d76a4513e126fca92f9fd263d9823399a662f66a1e3c12456da5d72fac1724e5e36b2653216a1741625584a0f6fbedc6f3a6078b6177776e7585da27622d1164e61077cc07faa801691c07f8e24811aa861968a0410a8289e008166c06c26e2078080812e260ba880847e40075ca31fe0a63dc1254e4022302a9b2eeee27d5a627eaad8fbc9676a6c253b264bff871e14646ed183ee4166aa252449635c56ce877ad08a3e1c38fe5c899a28555625dda19c78da5d8bd6e68b6e63958d446bf2818db28692e5a8875623d5f92898a11e890ea489baa4d5d965ddc9a792462793ba27aacd5f1e40698de62159c0e87b5ea95f662915da657ddae79012298a4e531bf1e70bfaa781fe2749fe678556a6f121282b10a6f1b921633aa84e50d8a312009406828d1e6338bce98ec66988a2a4961ae703e265d0916339ca57981ee78a6ed1215ceaa4b6e9bee858a40266ce4829aaa9aa7bc616598680a6f6a5c56de79de2699ed6e0d080599ff6e5a91a42aa0202a5bad85824270f21eb4918ab9f0c80adcee98fde9bd5856aafe2a7ff9e7e59784eeba9726893b242b3c2d43cce6a5aba29b82e87b2f0a88fa245a7eee5b562abaffeaa4d08022b556ba926d508289f0950c02110eb00e0e6ea6566a18a9f638a8333a680f22d2a0ba4c019925f3824ea0924ec1635a6a1caa5bac6e98aeae7685e1dafc66ba88e260cd2e9b099c0306100bf6ad1216000ba96ab137265c1aee7b96ea08eb2c27ac5e6c56667c5692cdcb1e4387aecc7d62b9232c7c88252c91a42bfa62cad2a4a66ae2014aae3cbe684d236e9eaed4c08d82c5daa58ceeaeccef2ec97626d23012d6a08ad1f11ed00182db82a11d46e20d30602749293313e6d087e0088ea15d5dee3cda61fb5eeaa90c6eb89166971ca67d886a0095c17ffb319dd051aeecec148b74d6be8591c70f65597766ca88aeac72a82bd7609e06ea0e0a6829fedd6e17aae5cae1ea42d2ede726ace4a2e5becad777ea7c656aee51208e622a0e66eae9815527d7deeedf6dc498eae2ae06c9dbd2bbca66eb6f62debe64e52898009206ff22aeff226af08d0c54c162eeedaa29cf6e8eeaa442e5ee5ef026ff0f2edf0eea5715a6f3928ae65496f0fc10ef586ef3d405c4a62edc66e2ff79ee6bccad391aa66fa0ae36e49ade762e7238eaffd6ee99efaee689e2efcaa2e71b66f5d86acffceee4c3ed7ed6229c62930ef7e23cab9abb50e30010baff7a6e6c345b059f02fd8d12eb3755bed762e5ae1aaff22de96d629d69e2effea62b0bc6a7071eee7fa76f03d3425092f30fe22590dab6f8aa29ee306a7debe70fccaafe3955b981e310f8bef75e64d0802ae05826eff2a7105d367fbb6b00b0f3111173178961b9fba6e14f35ce2e2f06079b14a74eafbb56f24b4f01517b0019f31eeeccf18bf0a0887261c9f057dce671bab451aab71f7b2311ebb1fb0d27120032417c3921f93e6fbee71154fae21bbb1203bf2c9ad30c832721eebf11ef3f1ea1af216fff1d73e7227ff682453e124676d695a321667f1a8b62e2173b22707f28826b128a3b12297f21a73ad28a732f6d62f2b0b7223bf322cbb6f25cf320c637226b7132feb321de3322003b1c62ab21507b3296b6b6ab62b022bdb31d770ffef82e30a8b72333bf33373b32fbb5fc8225e2e5b7396a628a280b31071f3337302374f423ad3ef27abe40f9733bb4eb0441d273cff7215b3f327b8b33ef3a936eb6a3de7ea1f771db12df319bb7337f73334c7f02417594d706af11274d5759691d116402f7443fbf33f03b43247b4262364453393ebde7342fbf142333447abf422eb731dfb303993b4149b03907ef43e373347438e47df3420f3c7e3c1e44cdf3112572b4ac3724bafb44e23b54bdf3428873352096b2bdff3490791147f3452ebf4d920754fe34e26be31fd366e1467b396aa3257cba03b6775d06cb559bb92532733485beff6d0e914b335582d7552a7b5434b6e5dcbb5264774c68633ffc6cea738dfadd7f2756d2d755eabf5521f7660bdf5634f312e7ea303fa35e34e7563dbf55d2b764cdcf53b63b655aaa60da2b3a49905544d9701f7ae8aea0f617ff6e875f6662f7667af36b9912e45ff6f5b973526966a6c7b6a62bbf66bc3b66e6fcfd878c653dbb44f036b325b3570e3b466f7366777b63c287759a11f690bb4161ef76547b7153e375e377706ff767683365f15db604fb7447f1b78ef766b77775b6c7728a037d7613746671a02dff17b23767b57c27a170a7e5b827da372acc1203efb7710f3b77e8b067fbbf7802b78632378281838803438282cf8845f7584b3c38343b885f7378573b8216bb88363b8747c7882777889e7ed88e777884f07cc8aaf8389bb7838b2b88aaf088bc7c38bdb782cd3f885cbf88ce7788ddf7887f7f83aecb8b304396afe78761779dc0d39a124f9a51d395f37b9382ef9aa44f9293fb90057b9944f399567b9955f398c77798a6fb9228579347fb93a94f9a78ef97fa4791f9fb976b7b996aff9e3c479cfbe3925d73929cff96de5b99b73789f4bee9e8b1ba0b7f07b133a3f0bbadc1d7a3343f9a2cb72a24fa5a3abf4364bfa4643ba97563a63db69a663f5a5472ea7837aa57b3a01877aa9e7f9a8abb1a9ab7a93a33a3baffaab6bf8830701003b6821c15465af30cb735feed149f55056fd9477354d5181567cf2861e387d5fedf7002600000000" + }, + { + "title": "inscription/-471084", + "raw_tx": "01000000000102ae4d00eb904459b277dd9df2116c4fcbbc59a0827ffe06c396bce3e30f18ab8d0000000000fdffffff7679b145a178884bdcac8257e5c973f7fdf0ebb69806896e8d8e081e849ff8840000000000fdffffff65421f000000000000225120bc360e64e5a53856dcfee6ebfc08b12fed4f825b81a0bdc2ec59378baf1055acdf05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48df05000000000000225120f62926af7bdc500578d8d508de206a7d05bcc8f580ad640cba51e613935dcf48014056ba740d3420c1cde4faa91a306d9a72ad39a72a1fc693189827230597564a6d9531697738ed19d40d85799d5842129328b254efbf09bfe7afa3bbd1f8099a6e03406604b488b92800d76605701a989f335208ae0808dd251af8c28023ae3d3ca514a499b79c451011786a057116ed8e5e8681234565edc4b99e77fda2e6fa7b50affdcc9220ec5c2d8318671d39a0c21c82f9d188b5bfcdc8bf5e79d6228fdb66baa2fc27f2ac0063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102022125010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202002b010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202df30010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202be36010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102029d3c010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102027c42010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102025b48010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102023a4e010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102021954010542a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e65392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202f859010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202d75f010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202b665010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202956b010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102027471010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102025377010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202327d010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102021183010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202f088010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202cf8e010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6631392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202ae94010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102028d9a010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102026ca0010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102024ba6010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102022aac010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020209b2010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202e8b7010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202c7bd010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202a6c3010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020285c9010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6632392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020264cf010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020243d5010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020222db010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020201e1010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202e0e6010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010202bfec010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102029ef2010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102027df8010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102025cfe010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102033b0401010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6633392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102031a0a01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203f90f01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203d81501010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203b71b01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203962101010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203752701010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203542d01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203333301010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203123901010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203f13e01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6634392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203d04401010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203af4a01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102038e5001010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102036d5601010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102034c5c01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102032b6201010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102030a6801010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203e96d01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203c87301010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203a77901010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6635392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203867f01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203658501010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203448b01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203239101010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203029701010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203e19c01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203c0a201010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102039fa801010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102037eae01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102035db401010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6636392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102033cba01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102031bc001010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203fac501010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203d9cb01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203b8d101010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020397d701010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020376dd01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020355e301010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020334e901010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b01020313ef01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6637392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203f2f401010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203d1fa01010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203b00002010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102038f0602010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102036e0c02010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102034d1202010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102032c1802010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102030b1e02010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203ea2302010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203c92902010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6638392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203a82f02010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639302f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203873502010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639312f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203663b02010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639322f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203454102010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639332f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203244702010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639342f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203034d02010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639352f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203e25202010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639362f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203c15802010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639372f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b010203a05e02010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639382f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e680063036f726401010d696d6167652f7376672b786d6c010320e379bdff821b52e5883a912c32b85f7b48c3624315559638c0f96f1970a9901b0102037f6402010543a36a636f6c6c656374696f6e746c617365722065796573206d6f6e61206c6973616765646974696f6e6639392f313030666172746973746b62696c6c79726573746579004cef3c7376672076696577426f783d2230203020313030203130302220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b223e0a20203c696d616765206865696768743d2231303025222077696474683d22313030252220786c696e6b3a687265663d222f636f6e74656e742f316239306139373031393666663963303338393635353135343336326333343837623566623833323263393133613838653535323162383266666264373965336930222f3e0a3c2f7376673e6821c1ec5c2d8318671d39a0c21c82f9d188b5bfcdc8bf5e79d6228fdb66baa2fc27f200000000" + }, + { + "title": "inscription/48315131", + "raw_tx": "02000000000101f454f1291c1a556caea8f1abb407d2d34d153c3b15913ccb146634e0a9c8704d0000000000fdffffff01f4010000000000002251204dccd4890606e35f7ee18890491d6f99710293ceb37348b9d82d4406990f56160340c068215bbbcc797e164b0b587bfd041c11bac63b2a49c3f0fd337dfc4a27687cce134dcea66c82453ea5b28fdf62fa46a61e95f50d9894847acda321d39afb74fd5102209f9e0c3af2ac3528f42bdec98cc65e2936a7f2ea4b3ad5392a8613e6fda925c7ac0063036f726401010a746578742f706c61696e01054d8b01a5647469636b6453594d4d636d6178683231303030303030636c696d6431303030636465636138686d65746164617461a3646e616d656853796d6d657472796464657363789246697273742073796d6d6574726963616c20425243323020262043425243323020746f6b656e2c206465706c6f796564206f6e207468652073616d65207361742f696e736372697074696f6e2e205265646566696e657320656666696369656e6379206279206d657267696e6720425243323020262043425243323020616374696f6e732c20736176696e6720666565732e67707572706f736578a94578706572696d656e74616c2c20496e63657074696f6e2d6c696b652027746f6b656e20696e20746f6b656e272064657369676e2c20616c6c6f77696e672073696d756c74616e656f7573206465706c6f792c206d696e742c207472616e73666572206f6620626f746820746f6b656e20666f726d7320696e20612073696e676c6520696e736372697074696f6e2e20476f6f6462796520666565732c2068656c6c6f204d4f544f2e01070e636272632d32303a6465706c6f79004c777b0a202020202270223a20226272632d3230222c0a20202020226f70223a20226465706c6f79222c0a20202020227469636b223a202253594d4d222c0a20202020226d6178223a20223231303030303030222c0a20202020226c696d223a202231303030222c0a2020202022646563223a202238220a7d6821c09f9e0c3af2ac3528f42bdec98cc65e2936a7f2ea4b3ad5392a8613e6fda925c700000000", + "pubkey": "9f9e0c3af2ac3528f42bdec98cc65e2936a7f2ea4b3ad5392a8613e6fda925c7", + "tags": { + "contentType": "text/plain", + "metadata": { + "tick": "SYMM", + "max": "21000000", + "lim": "1000", + "dec": "8", + "metadata": { + "desc": "First symmetrical BRC20 & CBRC20 token, deployed on the same sat/inscription. Redefines efficiency by merging BRC20 & CBRC20 actions, saving fees.", + "name": "Symmetry", + "purpose": "Experimental, Inception-like 'token in token' design, allowing simultaneous deploy, mint, transfer of both token forms in a single inscription. Goodbye fees, hello MOTO." + } + }, + "metaprotocol": "cbrc-20:deploy" + }, + "body": "7b0a202020202270223a20226272632d3230222c0a20202020226f70223a20226465706c6f79222c0a20202020227469636b223a202253594d4d222c0a20202020226d6178223a20223231303030303030222c0a20202020226c696d223a202231303030222c0a2020202022646563223a202238220a7d" + }, + { + "title": "inscription/-381350", + "raw_tx": "0200000000010d61372aa4cc469d7eeda44c4581796a27fcdb66238b4d8d4926bbf57b5862e15a0000000000fdffffff6d1a7f225170ae2fb792cd6e68b91c64abaeb02dcbfc5d8d83b06c7ba28341240000000000fdffffff7a21269249e432887ebc3c7f6dcaf75d3d4835a5a774e6d7f948950927fae52a0000000000fdffffff2353c23894ee326c873473c932a9a52b10fd44483135758a6f8e9a51f4ed14ed0000000000fdffffffa891068e79a1dbb5559b56095b95d13d129b7c89cf3046f0fe5a6b0503cacb0d0000000000fdffffffe639922a18ee9e5c2e5fb2a2f96673a7e3192b93f33b025a9d234ce1935ce11b0000000000fdffffffe4d9f1ac4f6c3f47d4c74c996a6ff55a4fae90b3204bcace87e5658113156c2a0000000000fdffffffde552d317fd014e7393315dcb146d8678cbfa9747da186710f0318a32100292e0000000000fdffffff2c443a0a433b4d4dc9a7887a5337c636f7ed88b1d37e1396d6492ff6d5b0a4300000000000fdfffffffd9134a4870f649b0726ef717ef1c26afb2ba4474891a8f3c85b9280dde5d4310000000000fdfffffff3cf2fb8a87e1779458814d9bbb4ced54ddee0191ad47d7b8c794bf04ef330550000000000fdffffff54f438465945b7e28384af6a3030d145f14fa80d45b50a5bf4dae803e6ab82ac0000000000fdffffff61372aa4cc469d7eeda44c4581796a27fcdb66238b4d8d4926bbf57b5862e15a0700000000fdffffff0d102700000000000022512081e2a06fd1a84315e620e27ecb53e40c7c752bcf5a859aff6ce3daf0224b33bc5802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc55802000000000000225120943b0b2ffed25e042a7baa89ba540a8e9d2e38bec3f74407fa30db862b1b9cc54a01000000000000225120189c0049c95c84b14ade5f9464d98b5949b19641ac2fc1680224847cccc3d8cd034023dbb3e1cc4f845bf3c2060aa27735d2eac1b689f67396ffbf2892b2e194ee6ec05abaed06b7981d48c6d4fafd53ea699162dd641777bf0e7ba0365fffd75ecafd6102204f78e8f9691b8f03908ce5922fede5ed9557a4ea850b12de83fc54819d4862eaac0063036f7264010f1268747470733a2f2f63686973656c2e78797a53203cbf74df88a2dd22f0a47b81b0aa245e3e66063fd510ff4ce832950f4860730253200cd6f4dad468753f4d4c22f40df42c1345f96685c946133f11f6aaedb67aaa7353204a5c85e73b86a68d1aaedb75222c1f3b89aff2594b7bc3beb7f91289966f321d53209992c88e91641aaf7e392db65c0622011bb02eac6782e05ee06c51a4bc22fc555320dca358c5905e51332751829654384158bfbdfdecd2476e521e8a11e81d1a39fb5320297a216bd2edae1e23f8a2df9a9abfbd473814ed3212e1790c118ea6e31255a35320a768f373e4f4ce7365d0556838e1651019478af0949888e1a1c4b12d0ca9c121532072d1677b24410697f1e96987fd96777801438fc879e5650e95534ae40cfd0c355320111c891b41f3d7c1cd74c44306f9c06eaf2a665a6a359a251145b82cd574d2405320af31fab0cfc9340e4b5b3ef50042e85c0c998a96f2401c58078b7b944a507a6d532041ea9fae4ae1921507ccd610dc2ed041762f79365cfb26acd9bf5dd72ca60c09010117746578742f68746d6c3b636861727365743d7574662d38004c903c696d67207372633d222f636f6e74656e742f30393063613632636437356462666439616332366662356333363739326637363431643032656463313064366363303731353932653134616165396665613431693022207374796c653d2277696474683a20313030253b206865696768743a20313030253b206f626a6563742d6669743a20636f6e7461696e3b223e0a6821c04f78e8f9691b8f03908ce5922fede5ed9557a4ea850b12de83fc54819d4862ea014063e0e62b1d41c51e23e124d1e0a42db2ba75eaf1989614cc6ea5696937c02895adfeed9802ed274a935e89bf88d7f4765ec1f6ead14dc550dfd2e34f0aab73c8014065096e3f3b51132b2cd761dd8d8852dfcda580d032fa1142c0630e565813eb9122affda17ed84b5c8c1dbfeae000d79b1021deaa5ed9ec91ba4601c03a6b24bc0140e9fd5a85e4d3a02ef1b52b20aa3d3e869a657c26e1e11c0cfacce3cf3c4e0cfe2ec9ca9c459f29d5133468579781602b66d60a6cd446e6d5e5b2928e47d2787d014048cb316c7e2b23be66e5b2cb6a04284b1e0480d8a6b0d5c9e1435f07207421d60f4a63563753d47ef69d4a45dd1d2b6f004eff20e8b58f26b6d11a77c45efbac01402a8a32ee041368a2a8af213f191094e12d7b700dd0b8ff896f02250897c0c3eaf0c11f9233f9d1f6b75dff42ce929baa8f6a880713f39215fba4b25353661d3201401ac2896088ae34e0be869b15ce9c4f929f236244dd8f14db5a8fe0ff27d9f480a417f1cd3b7e0c526c9e62bc46081256fa16b777bef8098220fa635d4797378f01406c1d102800879d8b808d3a1c902c9e36e6144e92493ec98fe790e4e57072fef2fe55e2e419e5636f429fae1b9fe327cf5f97383c38d4774954a9397b6aa443b90140d136c198fa10cb14e7f4831a50af4d4cc4a3e68e03657c1716fc8e3298f2698943d9bf58192d14585095df85fb99f981bc2eb79c7c1a61b6b25b0246fba99fc701405c319e62c4b5c613ad0e4c7200b207df8ca91388b830303148245fbd3f8fbb952aac3acecf910a9c8c9e7597c11a8e9dc0f1557d6b55d2f73afe7246ef1b13c60140dd81b3d36a85fbc2c14bacaf9549a0b7a28936b3486283d79ab884de4548869124e9e204cf1bfb15c2542293653c756ec5ceaaa9b49831e97b65fa9e45baedb8014004c884ceeaeb84b9a6c536126df0baacc14298ad3cf287570edc98c4c43ec5bb6d2fa5642f2dc5ea586b930caac6669538017f2baa2f28fb1d144ac19cf7b1c3014018713c76959453d9d2fbe767213cff94f33f5e2379003925fbf73d7538b01e07aece5f38660b87c09834566bf9960b2cafb4385c5cd993a3bf69e3baf466c34a00000000", + "tags": { + "note": "https://chisel.xyz", + "parent": [ + "027360480f9532e84cff10d53f06663e5e24aab0817ba4f022dda288df74bf3ci0", + "73aa7ab6edaaf6113f1346c98566f945132cf40df4224c4d3f7568d4daf4d60ci0", + "1d326f968912f9b7bec37b4b59f2af893b1f2c2275dbae1a8da6863be7855c4ai0", + "55fc22bca4516ce05ee08267ac2eb01b0122065cb62d397eaf1a64918ec89299i0", + "fb391a1de8118a1e526e47d2ecfdbdbf584138549682512733515e90c558a3dci0", + "a35512e3a68e110c79e11232ed143847bdbf9a9adfa2f8231eaeedd26b217a29i0", + "21c1a90c2db1c4a1e1889894f08a47191065e1386855d06573cef4e473f368a7i0", + "350cfd0ce44a53950e65e579c88f4301787796fd8769e9f1970641247b67d172i0", + "40d274d52cb84511259a356a5a662aaf6ec0f90643c474cdc1d7f3411b891c11i0", + "6d7a504a947b8b07581c40f2968a990c5ce84200f53e5b4b0e34c9cfb0fa31afi0", + "090ca62cd75dbfd9ac26fb5c36792f7641d02edc10d6cc071592e14aae9fea41i0" + ], + "contentType": "text/html;charset=utf-8" + }, + "body": "3c696d67207372633d222f636f6e74656e742f30393063613632636437356462666439616332366662356333363739326637363431643032656463313064366363303731353932653134616165396665613431693022207374796c653d2277696474683a20313030253b206865696768743a20313030253b206f626a6563742d6669743a20636f6e7461696e3b223e0a" + } +] \ No newline at end of file diff --git a/test/index.test.js b/test/index.test.js new file mode 100644 index 0000000..26e4a93 --- /dev/null +++ b/test/index.test.js @@ -0,0 +1,7 @@ +import { should } from 'micro-should'; + +import './cbor.test.js'; +import './ordinals.test.js'; +import './cli.test.js'; + +should.run(); diff --git a/test/ordinals.test.js b/test/ordinals.test.js new file mode 100644 index 0000000..b93b66b --- /dev/null +++ b/test/ordinals.test.js @@ -0,0 +1,505 @@ +import { deepStrictEqual } from 'node:assert'; +import { describe, should } from 'micro-should'; +import { hex, utf8 } from '@scure/base'; +import * as btc from '@scure/btc-signer'; +import * as ordinals from '../lib/esm/index.js'; +import {TEST_NETWORK} from '@scure/btc-signer'; +import { schnorr as secp256k1_schnorr } from '@noble/curves/secp256k1'; +import { default as ordvectors } from './fixtures/ordinals.json' assert { type: 'json' }; + +// The file misses a bunch of valid test vectors for inscriptions. +// There are only a few official test vectors. +// We collect transactions with specific features manually. +// It is complicated: there are no filters. +// TODO: add more test vectors. + +describe('Ordinals', () => { + describe('Tags', () => { + should('pointer', () => { + const pointer = ordinals.__test__.TagCoders.pointer; + deepStrictEqual(pointer.decode(hex.decode('ff')), 255n); + deepStrictEqual(pointer.decode(hex.decode('0001')), 256n); + deepStrictEqual(pointer.decode(hex.decode('000100')), 256n); + }); + should('InscriptionId', () => { + const VECTORS = [ + [ + '1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100', + '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi0', + ], + [ + '1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100ff', + '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi255', + ], + [ + '1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201000001', + '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fi256', + ], + ]; + for (const [raw, exp] of VECTORS) { + deepStrictEqual(ordinals.InscriptionId.decode(hex.decode(raw)), exp); + deepStrictEqual(ordinals.InscriptionId.encode(exp), hex.decode(raw)); + } + }); + should('rune', () => { + const rune = ordinals.__test__.TagCoders.rune; + const VECTORS = [ + [0n, []], + [1n, [1]], + [255n, [255]], + [256n, [0, 1]], + [65535n, [255, 255]], + [65536n, [0, 0, 1]], + [340_282_366_920_938_463_463_374_607_431_768_211_455n, new Array(16).fill(255)], + ]; + for (const [exp, raw] of VECTORS) { + deepStrictEqual(rune.decode(new Uint8Array(raw)), exp); + deepStrictEqual(rune.encode(exp), new Uint8Array(raw)); + } + }); + should('multiple parents', () => { + const vector = [ + '027360480f9532e84cff10d53f06663e5e24aab0817ba4f022dda288df74bf3ci0', + '73aa7ab6edaaf6113f1346c98566f945132cf40df4224c4d3f7568d4daf4d60ci0', + ]; + const { TagCoder } = ordinals.__test__; + deepStrictEqual(TagCoder.encode(TagCoder.decode({ parent: vector })), { parent: vector }); + }); + }); + + should('inscription/11820782', () => { + // https://ordiscan.com/inscription/11820782 + const rawTx = ordvectors[0].raw_tx; + const tx = btc.Transaction.fromRaw(hex.decode(rawTx)); + const witness = tx.inputs[0].finalScriptWitness; + const script = btc.Script.decode(witness[1]); + // Not cursed, but strange script with DROP. + // This is valid inscription, but too complex script + deepStrictEqual(ordinals.OutOrdinalReveal.decode(script), undefined); + deepStrictEqual(ordinals.parseInscriptions(script), [ + { + tags: { contentType: 'image/svg+xml' }, + body: hex.decode(ordvectors[0].body), + cursed: false, + }, + ]); + }); + + should('inscription/62115659', () => { + // 664655e657046ffcc4ea5e6116ae51abb0922f0efa6be399baeb759e898ae6a0 + // https://ordiscan.com/inscription/62115659 + const rawTx = ordvectors[1].raw_tx; + + const tx = btc.Transaction.fromRaw(hex.decode(rawTx)); + const witness = tx.inputs[0].finalScriptWitness; + const script = btc.Script.decode(witness[1]); + const encoded = ordinals.OutOrdinalReveal.encode(script); + const newScript = btc.Script.encode(ordinals.OutOrdinalReveal.decode(encoded)); + deepStrictEqual(ordinals.OutOrdinalReveal.decode(encoded), script); + deepStrictEqual( + ordinals.OutOrdinalReveal.encode(btc.Script.decode(newScript)), + ordinals.OutOrdinalReveal.encode(btc.Script.decode(witness[1])) + ); + deepStrictEqual(newScript, witness[1]); + }); + + should('inscription/-471084', () => { + // 26f6901cc730eb0d2da547d34d1251008030090b574193dd0100b73ca6c23220 + // CBOR, complex + // https://ordiscan.com/inscription/-471084 + // parent: https://ordiscan.com/inscription/7523 + const rawTx = ordvectors[2].raw_tx; + const tx = btc.Transaction.fromRaw(hex.decode(rawTx)); + const witness = tx.inputs[1].finalScriptWitness; + const script = btc.Script.decode(witness[1]); + const encoded = ordinals.OutOrdinalReveal.encode(script); + const newScript = btc.Script.encode(ordinals.OutOrdinalReveal.decode(encoded)); + + deepStrictEqual(ordinals.OutOrdinalReveal.decode(encoded), script); + deepStrictEqual( + ordinals.OutOrdinalReveal.encode(btc.Script.decode(newScript)), + ordinals.OutOrdinalReveal.encode(btc.Script.decode(witness[1])) + ); + deepStrictEqual(newScript, witness[1]); + }); + + should('CBRC', () => { + // 49cbc5cbac92cf917dd4539d62720a3e528d17e22ef5fc47070a17ec0d3cf307 + // https://ordiscan.com/inscription/48315131 + const vector = ordvectors[3]; + const rawTx = vector.raw_tx; + const tx = btc.Transaction.fromRaw(hex.decode(rawTx)); + const witness = tx.inputs[0].finalScriptWitness; + const script = btc.Script.decode(witness[1]); + const encoded = ordinals.OutOrdinalReveal.encode(script); + deepStrictEqual(encoded, { + type: 'tr_ord_reveal', + pubkey: hex.decode(vector.pubkey), + inscriptions: [ + { + tags: vector.tags, + body: hex.decode(vector.body), + cursed: false, + }, + ], + }); + + const newScript = btc.Script.encode(ordinals.OutOrdinalReveal.decode(encoded)); + deepStrictEqual(ordinals.OutOrdinalReveal.decode(encoded), script); + deepStrictEqual( + ordinals.OutOrdinalReveal.encode(btc.Script.decode(newScript)), + ordinals.OutOrdinalReveal.encode(btc.Script.decode(witness[1])) + ); + deepStrictEqual(newScript, witness[1]); + }); + should('multiple parents', () => { + // f988fe4b414a3f3d4a815dd1b1675dea0ba6140b1d698d8970273c781fb95746 + // https://ordiscan.com/inscription/-381350 + const vector = ordvectors[4]; + const rawTx = vector.raw_tx; + const tx = btc.Transaction.fromRaw(hex.decode(rawTx)); + const witness = tx.inputs[0].finalScriptWitness; + const script = btc.Script.decode(witness[1]); + // We cannot encode/decode cursed using OutOrdinalReveal + deepStrictEqual(ordinals.OutOrdinalReveal.decode(script), undefined); + deepStrictEqual(ordinals.parseInscriptions(script), [ + { + tags: vector.tags, + body: hex.decode(vector.body), + cursed: true, + }, + ]); + }); + + describe('Parsing', () => { + const { parseEnvelopes } = ordinals.__test__; + should('checksig before', () => { + deepStrictEqual( + parseEnvelopes( + btc.Script.decode( + hex.decode( + 'ac0063036f7264010118746578742f706c61696e3b636861727365743d7574662d3800036f726468' + ) + ) + ), + [ + { + start: 4, + end: 8, + pushnum: false, + payload: [ + new Uint8Array([1]), + new Uint8Array([ + 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 99, 104, 97, 114, 115, 101, 116, + 61, 117, 116, 102, 45, 56, + ]), + 0, + new Uint8Array([111, 114, 100]), + ], + stutter: false, + }, + ] + ); + }); + should('checksig after', () => { + deepStrictEqual( + parseEnvelopes( + btc.Script.decode( + hex.decode( + '0063036f7264010118746578742f706c61696e3b636861727365743d7574662d3800036f726468ac' + ) + ) + ), + [ + { + start: 3, + end: 7, + pushnum: false, + payload: [ + new Uint8Array([1]), + new Uint8Array([ + 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 99, 104, 97, 114, 115, 101, 116, + 61, 117, 116, 102, 45, 56, + ]), + 0, + new Uint8Array([111, 114, 100]), + ], + stutter: false, + }, + ] + ); + }); + + should('multiple', () => { + deepStrictEqual( + parseEnvelopes( + btc.Script.decode( + hex.decode( + '0063036f7264010118746578742f706c61696e3b636861727365743d7574662d380003666f6f680063036f7264010118746578742f706c61696e3b636861727365743d7574662d38000362617268' + ) + ) + ), + [ + { + start: 3, + end: 7, + pushnum: false, + payload: [ + new Uint8Array([1]), + new Uint8Array([ + 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 99, 104, 97, 114, 115, 101, 116, + 61, 117, 116, 102, 45, 56, + ]), + 0, + new Uint8Array([102, 111, 111]), + ], + stutter: false, + }, + { + start: 11, + end: 15, + pushnum: false, + payload: [ + new Uint8Array([1]), + new Uint8Array([ + 116, 101, 120, 116, 47, 112, 108, 97, 105, 110, 59, 99, 104, 97, 114, 115, 101, 116, + 61, 117, 116, 102, 45, 56, + ]), + 0, + new Uint8Array([98, 97, 114]), + ], + stutter: false, + }, + ] + ); + }); + should('no endif', () => { + deepStrictEqual(parseEnvelopes(btc.Script.decode(hex.decode('0063036f7264'))), []); + }); + should('no 0', () => { + deepStrictEqual(parseEnvelopes(btc.Script.decode(hex.decode('63036f726468'))), []); + }); + should('second envelope', () => { + const script = hex.decode( + '0063036f7264010103666f6f004c6401010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101680063036f7264010103626172004c640101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010168' + ); + deepStrictEqual(parseEnvelopes(btc.Script.decode(script)), [ + { + start: 3, + end: 7, + pushnum: false, + payload: [ + new Uint8Array([1]), + new Uint8Array([102, 111, 111]), + 0, + new Uint8Array([ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + ]), + ], + stutter: false, + }, + { + start: 11, + end: 15, + pushnum: false, + payload: [ + new Uint8Array([1]), + new Uint8Array([98, 97, 114]), + 0, + new Uint8Array([ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + ]), + ], + stutter: false, + }, + ]); + }); + should('PushNum', () => { + const VECTORS = [ + ['0063036f7264004f68', new Uint8Array([129])], + ['0063036f7264005168', new Uint8Array([1])], + ['0063036f7264005268', new Uint8Array([2])], + ['0063036f7264005368', new Uint8Array([3])], + ['0063036f7264005468', new Uint8Array([4])], + ['0063036f7264005568', new Uint8Array([5])], + ['0063036f7264005668', new Uint8Array([6])], + ['0063036f7264005768', new Uint8Array([7])], + ['0063036f7264005868', new Uint8Array([8])], + ['0063036f7264005968', new Uint8Array([9])], + ['0063036f7264005a68', new Uint8Array([10])], + ['0063036f7264005b68', new Uint8Array([11])], + ['0063036f7264005c68', new Uint8Array([12])], + ['0063036f7264005d68', new Uint8Array([13])], + ['0063036f7264005e68', new Uint8Array([14])], + ['0063036f7264005f68', new Uint8Array([15])], + ['0063036f7264006068', new Uint8Array([16])], + ]; + for (const [scriptHex, exp] of VECTORS) { + const res = parseEnvelopes(btc.Script.decode(hex.decode(scriptHex))); + deepStrictEqual(res[0].pushnum, true); + deepStrictEqual(res[0].payload, [0, exp]); + } + }); + should('stutter', () => { + // 0 0 IF PROTOCOL_ID ENDIF + deepStrictEqual(parseEnvelopes(btc.Script.decode(hex.decode('000063036f726468'))), [ + { + start: 4, + end: 4, + payload: [], + pushnum: false, + stutter: true, + }, + ]); + // 0 IF 0 IF PROTOCOL_ID ENDIF + deepStrictEqual(parseEnvelopes(btc.Script.decode(hex.decode('00630063036f726468'))), [ + { + start: 5, + end: 5, + payload: [], + pushnum: false, + stutter: true, + }, + ]); + // 0 IF 0 IF 0 IF PROTOCOL_ID ENDIF + deepStrictEqual(parseEnvelopes(btc.Script.decode(hex.decode('006300630063036f726468'))), [ + { + start: 7, + end: 7, + payload: [], + pushnum: false, + stutter: true, + }, + ]); + // 0 0 AND 0 IF PROTOCOL_ID ENDIF + deepStrictEqual(parseEnvelopes(btc.Script.decode(hex.decode('0000840063036f726468'))), [ + { + start: 6, + end: 6, + payload: [], + pushnum: false, + stutter: true, + }, + ]); + }); + }); + should('unknown fields', () => { + const t = btc.Script.decode(new Uint8Array([0, 99, 3, 111, 114, 100, 1, 255, 1, 0, 104])); + deepStrictEqual(ordinals.parseInscriptions(t), [ + { + body: new Uint8Array([]), + cursed: false, + tags: { unknown: [[new Uint8Array([255]), new Uint8Array([0])]] }, + }, + ]); + deepStrictEqual( + ordinals.OutOrdinalReveal.decode({ + type: 'tr_ord_reveal', + pubkey: new Uint8Array(32), + inscriptions: [ + { + tags: { unknown: [[new Uint8Array([255]), new Uint8Array([0])]] }, + body: new Uint8Array([]), + }, + ], + }), + [ + new Uint8Array(32), + 'CHECKSIG', + 0, + 'IF', + new Uint8Array([111, 114, 100]), + new Uint8Array([255]), + new Uint8Array([0]), + 0, + 'ENDIF', + ] + ); + }); + should('Example (fake)', () => { + const TESTNET = TEST_NETWORK; + const privKey = hex.decode('0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a'); + const pubKey = secp256k1_schnorr.getPublicKey(privKey); + // We need this to enable custom scripts outside + const customScripts = [ordinals.OutOrdinalReveal]; + + // This inscribes on first satoshi of first input (default) + const inscription = { + tags: { + // can be any format (MIME type) + // contentType: 'application/x-javascript', + // contentType: 'text/html', + contentType: 'application/json', + // compression: only brotli supported + // ContentEncoding: 'br', // brotli + }, + body: utf8.decode(JSON.stringify({ some: 1, test: 2, inscription: true, in: 'json' })), + // we can use previously inscribed js scripts in html + // body: utf8.decode( + // `test` + }; + + const revealPayment = btc.p2tr( + undefined, + ordinals.p2tr_ord_reveal(pubKey, [inscription]), + TESTNET, + false, + customScripts + ); + + // We need to send some bitcoins to this address before reveal. Also, there should be enough + // to cover reveal tx fee. + console.log('ADDRESS', revealPayment.address); + + deepStrictEqual( + revealPayment.address, + 'tb1p5mykwcq5ly7y2ctph9r2wfgldq94eccm2t83dd58k785p0zqzwkspyjkp5' + ); + + // You need to be extra careful with these, since it is possible to accidentally send + // inscription as fee. + // Also, rarity is only available with ordinal wallet. But you can parse + // other inscriptions and create common one using this. + const changeAddr = revealPayment.address; // can be different + const revealAmount = 2000n; + const fee = 500n; + + const tx = new btc.Transaction({ customScripts }); + tx.addInput({ + ...revealPayment, + // This is txid of tx with bitcoins we sent (replace) + txid: '75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858', + index: 0, + witnessUtxo: { script: revealPayment.script, amount: revealAmount }, + }); + tx.addOutputAddress(changeAddr, revealAmount - fee, TESTNET); + tx.sign(privKey, undefined, new Uint8Array(32)); + tx.finalize(); + + const txHex = hex.encode(tx.extract()); + + // Hex of reveal tx to broadcast + deepStrictEqual( + txHex, + '0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff01dc05000000000000225120a6c9676014f93c456161b946a7251f680b5ce31b52cf16b687b78f40bc4013ad03400e0888a69181fb2745c81cb595bdc1966e8b974a1c06b944e5f2be655af01fe5e1cc9626d6a97041a4b18654e20f7bd88a6ab1d12f6518b03264a19493946a7e7020f76a39d05686e34a4420897e359371836145dd3973e3982568b60f8433adde6eac0063036f72640101106170706c69636174696f6e2f6a736f6e00327b22736f6d65223a312c2274657374223a322c22696e736372697074696f6e223a747275652c22696e223a226a736f6e227d6821c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac000000000' + ); + // Parsing inscriptions + // console.log('HEX', txHex); + const tx2 = btc.Transaction.fromRaw(hex.decode(txHex)); + // console.log('PARSED', ordinals.parseWitness(tx2.inputs[0].finalScriptWitness)); + // Reveal tx should pay at least this much fee + // console.log('VSIZE', tx2.vsize); + }); +}); + +// ESM is broken. +import url from 'url'; +if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { + should.run(); +} diff --git a/test/package.json b/test/package.json new file mode 100644 index 0000000..8769641 --- /dev/null +++ b/test/package.json @@ -0,0 +1 @@ +{ "type": "module", "sideEffects": false } diff --git a/tsconfig.esm.json b/tsconfig.esm.json new file mode 100644 index 0000000..47df20f --- /dev/null +++ b/tsconfig.esm.json @@ -0,0 +1,8 @@ +{ + "extends": "@paulmillr/jsbt/tsconfigs/esm.json", + "compilerOptions": { + "outDir": "lib/esm" + }, + "include": ["index.ts", "src"], + "exclude": ["node_modules", "lib"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3180636 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@paulmillr/jsbt/tsconfigs/cjs.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["index.ts", "src"], + "exclude": ["node_modules", "lib"] +}