diff --git a/README.md b/README.md index 844f9bcd9..5ecaa737b 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,10 @@ - Rust: [privacy-scaling-explorations/zk-kit.rust](https://github.com/privacy-scaling-explorations/zk-kit.rust) - Solidity: [privacy-scaling-explorations/zk-kit.solidity](https://github.com/privacy-scaling-explorations/zk-kit.solidity) +## 📄 Papers + +- LeanIMT ([Download PDF](https://github.com/privacy-scaling-explorations/zk-kit/raw/main/papers/leanimt/paper/leanimt-paper.pdf)) + ## 📦 Packages diff --git a/packages/eddsa-poseidon/README.md b/packages/eddsa-poseidon/README.md index c566034fc..7c5134d53 100644 --- a/packages/eddsa-poseidon/README.md +++ b/packages/eddsa-poseidon/README.md @@ -92,6 +92,8 @@ or [JSDelivr](https://www.jsdelivr.com/): ## 📜 Usage +The public key is generated using [BLAKE]() by default and BLAKE2 if specified in the import as follows: `import { ... } from "@zk-kit/eddsa-poseidon/blake-2b"`. + ```typescript import { derivePublicKey, diff --git a/packages/eddsa-poseidon/package.json b/packages/eddsa-poseidon/package.json index 3bd13c3b4..95f569b8c 100644 --- a/packages/eddsa-poseidon/package.json +++ b/packages/eddsa-poseidon/package.json @@ -1,6 +1,6 @@ { "name": "@zk-kit/eddsa-poseidon", - "version": "1.0.3", + "version": "1.1.0", "description": "A JavaScript EdDSA library for secure signing and verification using Poseidon the Baby Jubjub elliptic curve.", "type": "module", "license": "MIT", @@ -14,6 +14,16 @@ "types": "./dist/index.d.ts", "require": "./dist/index.cjs", "default": "./dist/index.js" + }, + "./blake-1": { + "types": "./dist/index.d.ts", + "require": "./dist/lib.commonjs/eddsa-poseidon-blake-1.cjs", + "default": "./dist/esm/eddsa-poseidon-blake-1.js" + }, + "./blake-2b": { + "types": "./dist/index.d.ts", + "require": "./dist/lib.commonjs/eddsa-poseidon-blake-2b.cjs", + "default": "./dist/esm/eddsa-poseidon-blake-2b.js" } }, "files": [ @@ -41,7 +51,6 @@ "@rollup/plugin-typescript": "^11.1.6", "circomlibjs": "0.0.8", "ffjavascript": "0.2.38", - "poseidon-lite": "0.2.0", "rimraf": "^5.0.5", "rollup": "^4.12.0", "rollup-plugin-cleanup": "^3.2.1", @@ -51,6 +60,8 @@ "dependencies": { "@zk-kit/baby-jubjub": "1.0.3", "@zk-kit/utils": "1.2.1", - "buffer": "6.0.3" + "blakejs": "^1.2.1", + "buffer": "6.0.3", + "poseidon-lite": "0.3.0" } } diff --git a/packages/eddsa-poseidon/rollup.config.ts b/packages/eddsa-poseidon/rollup.config.ts index 1e54692e2..984a87d08 100644 --- a/packages/eddsa-poseidon/rollup.config.ts +++ b/packages/eddsa-poseidon/rollup.config.ts @@ -32,14 +32,10 @@ export default [ "@zk-kit/utils/f1-field", "@zk-kit/utils/scalar", "@zk-kit/utils/error-handlers", - "@zk-kit/utils/type-checks" + "@zk-kit/utils/type-checks", + "poseidon-lite/poseidon5" ], - plugins: [ - typescript({ tsconfig: "./build.tsconfig.json" }), - nodeResolve(), - commonjs(), - cleanup({ comments: "jsdoc" }) - ] + plugins: [typescript({ tsconfig: "./build.tsconfig.json" }), cleanup({ comments: "jsdoc" })] }, { input: "src/index.ts", @@ -70,5 +66,47 @@ export default [ input: "src/index.ts", output: [{ file: "dist/index.d.ts", format: "es" }], plugins: [dts()] + }, + { + input: "src/eddsa-poseidon-blake-1.ts", + output: [ + { + dir: "./dist/lib.commonjs", + format: "cjs", + banner, + entryFileNames: "[name].cjs" + }, + { dir: "./dist/lib.esm", format: "es", banner } + ], + external: [ + ...Object.keys(pkg.dependencies), + "@zk-kit/utils/conversions", + "@zk-kit/utils/f1-field", + "@zk-kit/utils/scalar", + "@zk-kit/utils/error-handlers", + "@zk-kit/utils/type-checks" + ], + plugins: [typescript({ tsconfig: "./build.tsconfig.json", declaration: false, declarationDir: undefined })] + }, + { + input: "src/eddsa-poseidon-blake-2b.ts", + output: [ + { + dir: "./dist/lib.commonjs", + format: "cjs", + banner, + entryFileNames: "[name].cjs" + }, + { dir: "./dist/lib.esm", format: "es", banner } + ], + external: [ + ...Object.keys(pkg.dependencies), + "@zk-kit/utils/conversions", + "@zk-kit/utils/f1-field", + "@zk-kit/utils/scalar", + "@zk-kit/utils/error-handlers", + "@zk-kit/utils/type-checks" + ], + plugins: [typescript({ tsconfig: "./build.tsconfig.json", declaration: false, declarationDir: undefined })] } ] diff --git a/packages/eddsa-poseidon/src/HashFunction.ts b/packages/eddsa-poseidon/src/HashFunction.ts new file mode 100644 index 000000000..f776d9123 --- /dev/null +++ b/packages/eddsa-poseidon/src/HashFunction.ts @@ -0,0 +1,6 @@ +import { Buffer } from "buffer" + +export interface HashFunction { + update(data: Buffer): HashFunction + digest(): Buffer +} diff --git a/packages/eddsa-poseidon/src/blake.ts b/packages/eddsa-poseidon/src/blake.ts index d9b8169ff..aad3d8895 100644 --- a/packages/eddsa-poseidon/src/blake.ts +++ b/packages/eddsa-poseidon/src/blake.ts @@ -20,6 +20,7 @@ */ import { Buffer } from "buffer" +import { HashFunction } from "./HashFunction" const zo = Buffer.from([0x01]) const oo = Buffer.from([0x81]) @@ -156,7 +157,7 @@ function lengthCarry(arr: number[]) { * hashing, allowing data to be added in chunks. */ /* eslint-disable import/prefer-default-export */ -export class Blake512 { +export default class Blake512 implements HashFunction { private _h: number[] private _s: number[] private _block: Buffer diff --git a/packages/eddsa-poseidon/src/blake2b.ts b/packages/eddsa-poseidon/src/blake2b.ts new file mode 100644 index 000000000..c90d420f4 --- /dev/null +++ b/packages/eddsa-poseidon/src/blake2b.ts @@ -0,0 +1,51 @@ +import { blake2bInit, blake2bUpdate, blake2bFinal, Blake2bCTX } from "blakejs" +import { HashFunction } from "./HashFunction" + +/** + * @module Blake2b + * Implements the Blake2b cryptographic hash function. + * Blake2b is a second iteration of the blake algorithm + * + * This code is a wrapper around the "blakeJS" JavaScript library. + * It supports hashing with optional keys, or output length for enhanced security in certain contexts. + */ + +export default class Blake2b implements HashFunction { + key: Uint8Array | null = null + outlen: number = 64 + context: Blake2bCTX + /** + * Constructor of the Blake2b engine + * @param outlen The fixed output length of the generated hash + * @param key Optional key parameter if keyed hashes are required + * @returns This instance, to allow method chaining. + */ + constructor(outlen: number = 64, key?: Uint8Array) { + if (key) this.key = key + if (outlen <= 0 || outlen > 64) throw new Error("Illegal output length, expected 0 < length <= 64") + else this.outlen = outlen + + this.context = blake2bInit(this.outlen, key) + } + + /** + * Updates the hash with new data. This method can be called multiple + * times to incrementally add data to the hash computation. + * @param input The data to add to the hash. + * @returns The instance, to allow method chaining. + */ + update(input: Buffer) { + blake2bUpdate(this.context, input) + return this + } + + /** + * Completes the hash computation and returns the final hash value. + * This method applies the necessary padding, performs the final compression, + * and returns the output. + * @returns The Blake2b hash of the input data. + */ + digest() { + return Buffer.from(blake2bFinal(this.context)) + } +} diff --git a/packages/eddsa-poseidon/src/eddsa-poseidon-blake-1.ts b/packages/eddsa-poseidon/src/eddsa-poseidon-blake-1.ts new file mode 100644 index 000000000..61e77d6d9 --- /dev/null +++ b/packages/eddsa-poseidon/src/eddsa-poseidon-blake-1.ts @@ -0,0 +1,15 @@ +import { EdDSAPoseidonFactory, SupportedHashingAlgorithms } from "./eddsa-poseidon-factory" + +export const { + EdDSAPoseidon, + derivePublicKey, + deriveSecretScalar, + packPublicKey, + packSignature, + signMessage, + unpackPublicKey, + unpackSignature, + verifySignature +} = EdDSAPoseidonFactory(SupportedHashingAlgorithms.BLAKE1) + +export * from "./types" diff --git a/packages/eddsa-poseidon/src/eddsa-poseidon-blake-2b.ts b/packages/eddsa-poseidon/src/eddsa-poseidon-blake-2b.ts new file mode 100644 index 000000000..cac69205d --- /dev/null +++ b/packages/eddsa-poseidon/src/eddsa-poseidon-blake-2b.ts @@ -0,0 +1,15 @@ +import { EdDSAPoseidonFactory, SupportedHashingAlgorithms } from "./eddsa-poseidon-factory" + +export const { + EdDSAPoseidon, + derivePublicKey, + deriveSecretScalar, + packPublicKey, + packSignature, + signMessage, + unpackPublicKey, + unpackSignature, + verifySignature +} = EdDSAPoseidonFactory(SupportedHashingAlgorithms.BLAKE2b) + +export * from "./types" diff --git a/packages/eddsa-poseidon/src/eddsa-poseidon-factory.ts b/packages/eddsa-poseidon/src/eddsa-poseidon-factory.ts new file mode 100644 index 000000000..5cbf6b15b --- /dev/null +++ b/packages/eddsa-poseidon/src/eddsa-poseidon-factory.ts @@ -0,0 +1,313 @@ +import { + Base8, + Fr, + Point, + addPoint, + inCurve, + mulPointEscalar, + packPoint, + subOrder, + unpackPoint +} from "@zk-kit/baby-jubjub" +import type { BigNumberish } from "@zk-kit/utils" +import { crypto, requireBuffer } from "@zk-kit/utils" +import { bigNumberishToBigInt, leBigIntToBuffer, leBufferToBigInt } from "@zk-kit/utils/conversions" +import { requireBigNumberish } from "@zk-kit/utils/error-handlers" +import F1Field from "@zk-kit/utils/f1-field" +import * as scalar from "@zk-kit/utils/scalar" +import { Buffer } from "buffer" +import { poseidon5 } from "poseidon-lite/poseidon5" +import { Signature } from "./types" +import { checkMessage, checkPrivateKey, hashInput, isPoint, isSignature, pruneBuffer } from "./utils" + +export enum SupportedHashingAlgorithms { + BLAKE1 = "blake-1", + BLAKE2b = "blake-2b" +} + +export const EdDSAPoseidonFactory = (algorithm: SupportedHashingAlgorithms) => { + /** + * Derives a public key from a given private key using the + * {@link https://eips.ethereum.org/EIPS/eip-2494|Baby Jubjub} elliptic curve. + * This function utilizes the Baby Jubjub elliptic curve for cryptographic operations. + * The private key should be securely stored and managed, and it should never be exposed + * or transmitted in an unsecured manner. + * + * The private key must be an instance of Buffer, Uint8Array or a string. The input will be used to + * generate entropy and there is no limit in size. + * The string is used as a set of raw bytes (in UTF-8) and is typically used to pass passwords or secret messages. + * If you want to pass a bigint, a number or a hexadecimal, be sure to convert them to one of the supported types first. + * The 'conversions' module in @zk-kit/utils provides a set of functions that may be useful in case you need to convert types. + * + * @param privateKey The private key used for generating the public key. + * @returns The derived public key. + */ + const deriveSecretScalar = (privateKey: Buffer | Uint8Array | string): bigint => { + // Convert the private key to buffer. + privateKey = checkPrivateKey(privateKey) + + let hash = hashInput(privateKey, algorithm) + + hash = hash.slice(0, 32) + hash = pruneBuffer(hash) + + return scalar.shiftRight(leBufferToBigInt(hash), BigInt(3)) % subOrder + } + + /** + * Derives a public key from a given private key using the + * {@link https://eips.ethereum.org/EIPS/eip-2494|Baby Jubjub} elliptic curve. + * This function utilizes the Baby Jubjub elliptic curve for cryptographic operations. + * The private key should be securely stored and managed, and it should never be exposed + * or transmitted in an unsecured manner. + * + * The private key must be an instance of Buffer, Uint8Array or a string. The input will be used to + * generate entropy and there is no limit in size. + * The string is used as a set of raw bytes (in UTF-8) and is typically used to pass passwords or secret messages. + * If you want to pass a bigint, a number or a hexadecimal, be sure to convert them to one of the supported types first. + * The 'conversions' module in @zk-kit/utils provides a set of functions that may be useful in case you need to convert types. + * + * @param privateKey The private key used for generating the public key. + * @returns The derived public key. + */ + function derivePublicKey(privateKey: Buffer | Uint8Array | string): Point { + const s = deriveSecretScalar(privateKey) + + return mulPointEscalar(Base8, s) + } + + /** + * Signs a message using the provided private key, employing Poseidon hashing and + * EdDSA with the Baby Jubjub elliptic curve. + * + * The private key must be an instance of Buffer, Uint8Array or a string. The input will be used to + * generate entropy and there is no limit in size. + * The string is used as a set of raw bytes (in UTF-8) and is typically used to pass passwords or secret messages. + * If you want to pass a bigint, a number or a hexadecimal, be sure to convert them to one of the supported types first. + * The 'conversions' module in @zk-kit/utils provides a set of functions that may be useful in case you need to convert types. + * + * @param privateKey The private key used to sign the message. + * @param message The message to be signed. + * @returns The signature object, containing properties relevant to EdDSA signatures, such as 'R8' and 'S' values. + */ + function signMessage(privateKey: Buffer | Uint8Array | string, message: BigNumberish): Signature { + // Convert the private key to buffer. + privateKey = checkPrivateKey(privateKey) + + // Convert the message to big integer. + message = checkMessage(message) + + const hash = hashInput(privateKey, algorithm) + + const sBuff = pruneBuffer(hash.slice(0, 32)) + const s = leBufferToBigInt(sBuff) + const A = mulPointEscalar(Base8, scalar.shiftRight(s, BigInt(3))) + + const msgBuff = leBigIntToBuffer(message, 32) + + const rBuff = hashInput(Buffer.concat([hash.slice(32, 64), msgBuff]), algorithm) + + const Fr = new F1Field(subOrder) + const r = Fr.e(leBufferToBigInt(rBuff)) + + const R8 = mulPointEscalar(Base8, r) + const hm = poseidon5([R8[0], R8[1], A[0], A[1], message]) + const S = Fr.add(r, Fr.mul(hm, s)) + + return { R8, S } + } + + /** + * Verifies an EdDSA signature using the Baby Jubjub elliptic curve and Poseidon hash function. + * @param message The original message that was be signed. + * @param signature The EdDSA signature to be verified. + * @param publicKey The public key associated with the private key used to sign the message. + * @returns Returns true if the signature is valid and corresponds to the message and public key, false otherwise. + */ + function verifySignature(message: BigNumberish, signature: Signature, publicKey: Point): boolean { + if ( + !isPoint(publicKey) || + !isSignature(signature) || + !inCurve(signature.R8) || + !inCurve(publicKey) || + BigInt(signature.S) >= subOrder + ) { + return false + } + + // Convert the message to big integer. + message = checkMessage(message) + + // Convert the signature values to big integers for calculations. + const _signature: Signature = { + R8: [BigInt(signature.R8[0]), BigInt(signature.R8[1])], + S: BigInt(signature.S) + } + // Convert the public key values to big integers for calculations. + const _publicKey: Point = [BigInt(publicKey[0]), BigInt(publicKey[1])] + + const hm = poseidon5([signature.R8[0], signature.R8[1], publicKey[0], publicKey[1], message]) + + const pLeft = mulPointEscalar(Base8, BigInt(signature.S)) + let pRight = mulPointEscalar(_publicKey, scalar.mul(hm, BigInt(8))) + + pRight = addPoint(_signature.R8, pRight) + + // Return true if the points match. + return Fr.eq(pLeft[0], pRight[0]) && Fr.eq(pLeft[1], pRight[1]) + } + + /** + * Converts a given public key into a packed (compressed) string format for efficient transmission and storage. + * This method ensures the public key is valid and within the Baby Jubjub curve before packing. + * @param publicKey The public key to be packed. + * @returns A string representation of the packed public key. + */ + function packPublicKey(publicKey: Point): bigint { + if (!isPoint(publicKey) || !inCurve(publicKey)) { + throw new Error("Invalid public key") + } + + // Convert the public key values to big integers for calculations. + const _publicKey: Point = [BigInt(publicKey[0]), BigInt(publicKey[1])] + + return packPoint(_publicKey) + } + + /** + * Unpacks a public key from its packed string representation back to its original point form on the Baby Jubjub curve. + * This function checks for the validity of the input format before attempting to unpack. + * @param publicKey The packed public key as a bignumberish. + * @returns The unpacked public key as a point. + */ + function unpackPublicKey(publicKey: BigNumberish): Point { + requireBigNumberish(publicKey, "publicKey") + + const unpackedPublicKey = unpackPoint(bigNumberishToBigInt(publicKey)) + + if (unpackedPublicKey === null) { + throw new Error("Invalid public key") + } + + return unpackedPublicKey + } + + /** + * Packs an EdDSA signature into a buffer of 64 bytes for efficient storage. + * Use {@link unpackSignature} to reverse the process without needing to know + * the details of the format. + * + * The buffer contains the R8 point packed int 32 bytes (via + * {@link packSignature}) followed by the S scalar. All encodings are + * little-endian. + * + * @param signature the signature to pack + * @returns a 64 byte buffer containing the packed signature + */ + function packSignature(signature: Signature): Buffer { + if (!isSignature(signature) || !inCurve(signature.R8) || BigInt(signature.S) >= subOrder) { + throw new Error("Invalid signature") + } + + const numericSignature: Signature = { + R8: signature.R8.map((c) => BigInt(c)) as Point, + S: BigInt(signature.S) + } + + const packedR8 = packPoint(numericSignature.R8) + const packedBytes = Buffer.alloc(64) + packedBytes.set(leBigIntToBuffer(packedR8, 32), 0) + packedBytes.set(leBigIntToBuffer(numericSignature.S, 32), 32) + return packedBytes + } + + /** + * Unpacks a signature produced by {@link packSignature}. See that function + * for the details of the format. + * + * @param packedSignature the 64 byte buffer to unpack + * @returns a Signature with numbers in string form + */ + function unpackSignature(packedSignature: Buffer): Signature { + requireBuffer(packedSignature, "packedSignature") + if (packedSignature.length !== 64) { + throw new Error("Packed signature must be 64 bytes") + } + + const sliceR8 = packedSignature.subarray(0, 32) + const sliceS = packedSignature.subarray(32, 64) + const unpackedR8 = unpackPoint(leBufferToBigInt(sliceR8)) + if (unpackedR8 === null) { + throw new Error(`Invalid packed signature point ${sliceS.toString("hex")}.`) + } + return { + R8: unpackedR8, + S: leBufferToBigInt(sliceS) + } + } + + /** + * Represents a cryptographic entity capable of signing messages and verifying signatures + * using the EdDSA scheme with Poseidon hash and the Baby Jubjub elliptic curve. + */ + class EdDSAPoseidon { + // Private key for signing, stored securely. + privateKey: Buffer | Uint8Array | string + // The secret scalar derived from the private key to compute the public key. + secretScalar: bigint + // The public key corresponding to the private key. + publicKey: Point + // A packed (compressed) representation of the public key for efficient operations. + packedPublicKey: bigint + + /** + * Initializes a new instance, deriving necessary cryptographic parameters from the provided private key. + * If the private key is not passed as a parameter, a random 32-byte hexadecimal key is generated. + * + * The private key must be an instance of Buffer, Uint8Array or a string. The input will be used to + * generate entropy and there is no limit in size. + * The string is used as a set of raw bytes (in UTF-8) and is typically used to pass passwords or secret messages. + * If you want to pass a bigint, a number or a hexadecimal, be sure to convert them to one of the supported types first. + * The 'conversions' module in @zk-kit/utils provides a set of functions that may be useful in case you need to convert types. + * + * @param privateKey The private key used for signing and public key derivation. + */ + constructor(privateKey: Buffer | Uint8Array | string = crypto.getRandomValues(32)) { + this.privateKey = privateKey + this.secretScalar = deriveSecretScalar(privateKey) + this.publicKey = derivePublicKey(privateKey) + this.packedPublicKey = packPublicKey(this.publicKey) + } + + /** + * Signs a given message using the private key and returns the signature. + * @param message The message to be signed. + * @returns The signature of the message. + */ + signMessage(message: BigNumberish): Signature { + return signMessage(this.privateKey, message) + } + + /** + * Verifies a signature against a message and the public key stored in this instance. + * @param message The message whose signature is to be verified. + * @param signature The signature to be verified. + * @returns True if the signature is valid for the message and public key, false otherwise. + */ + verifySignature(message: BigNumberish, signature: Signature): boolean { + return verifySignature(message, signature, this.publicKey) + } + } + + return { + deriveSecretScalar, + derivePublicKey, + signMessage, + verifySignature, + packPublicKey, + unpackPublicKey, + packSignature, + unpackSignature, + EdDSAPoseidon + } +} diff --git a/packages/eddsa-poseidon/src/eddsa-poseidon.ts b/packages/eddsa-poseidon/src/eddsa-poseidon.ts deleted file mode 100644 index fe7c7b584..000000000 --- a/packages/eddsa-poseidon/src/eddsa-poseidon.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { - Base8, - Fr, - Point, - addPoint, - inCurve, - mulPointEscalar, - packPoint, - subOrder, - unpackPoint -} from "@zk-kit/baby-jubjub" -import type { BigNumberish } from "@zk-kit/utils" -import { crypto, requireBuffer } from "@zk-kit/utils" -import { bigNumberishToBigInt, leBigIntToBuffer, leBufferToBigInt } from "@zk-kit/utils/conversions" -import { requireBigNumberish } from "@zk-kit/utils/error-handlers" -import F1Field from "@zk-kit/utils/f1-field" -import * as scalar from "@zk-kit/utils/scalar" -import { Buffer } from "buffer" -import { poseidon5 } from "poseidon-lite/poseidon5" -import { Signature } from "./types" -import { hash as blake, checkMessage, checkPrivateKey, isPoint, isSignature, pruneBuffer } from "./utils" - -/** - * Derives a secret scalar from a given EdDSA private key. - * - * This process involves hashing the private key with Blake1, pruning the resulting hash to retain the lower 32 bytes, - * and converting it into a little-endian integer. The use of the secret scalar streamlines the public key generation - * process by omitting steps 1, 2, and 3 as outlined in RFC 8032 section 5.1.5, enhancing circuit efficiency and simplicity. - * This method is crucial for fixed-base scalar multiplication operations within the correspondent cryptographic circuit. - * For detailed steps, see: {@link https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5}. - * For example usage in a circuit, see: {@link https://github.com/semaphore-protocol/semaphore/blob/2c144fc9e55b30ad09474aeafa763c4115338409/packages/circuits/semaphore.circom#L21} - * - * The private key must be an instance of Buffer, Uint8Array or a string. The input will be used to - * generate entropy and there is no limit in size. - * The string is used as a set of raw bytes (in UTF-8) and is typically used to pass passwords or secret messages. - * If you want to pass a bigint, a number or a hexadecimal, be sure to convert them to one of the supported types first. - * The 'conversions' module in @zk-kit/utils provides a set of functions that may be useful in case you need to convert types. - * - * @param privateKey The EdDSA private key for generating the associated public key. - * @returns The derived secret scalar to be used to calculate public key and optimized for circuit calculations. - */ -export function deriveSecretScalar(privateKey: Buffer | Uint8Array | string): bigint { - // Convert the private key to buffer. - privateKey = checkPrivateKey(privateKey) - - let hash = blake(privateKey) - - hash = hash.slice(0, 32) - hash = pruneBuffer(hash) - - return scalar.shiftRight(leBufferToBigInt(hash), BigInt(3)) % subOrder -} - -/** - * Derives a public key from a given private key using the - * {@link https://eips.ethereum.org/EIPS/eip-2494|Baby Jubjub} elliptic curve. - * This function utilizes the Baby Jubjub elliptic curve for cryptographic operations. - * The private key should be securely stored and managed, and it should never be exposed - * or transmitted in an unsecured manner. - * - * The private key must be an instance of Buffer, Uint8Array or a string. The input will be used to - * generate entropy and there is no limit in size. - * The string is used as a set of raw bytes (in UTF-8) and is typically used to pass passwords or secret messages. - * If you want to pass a bigint, a number or a hexadecimal, be sure to convert them to one of the supported types first. - * The 'conversions' module in @zk-kit/utils provides a set of functions that may be useful in case you need to convert types. - * - * @param privateKey The private key used for generating the public key. - * @returns The derived public key. - */ -export function derivePublicKey(privateKey: Buffer | Uint8Array | string): Point { - const s = deriveSecretScalar(privateKey) - - return mulPointEscalar(Base8, s) -} - -/** - * Signs a message using the provided private key, employing Poseidon hashing and - * EdDSA with the Baby Jubjub elliptic curve. - * - * The private key must be an instance of Buffer, Uint8Array or a string. The input will be used to - * generate entropy and there is no limit in size. - * The string is used as a set of raw bytes (in UTF-8) and is typically used to pass passwords or secret messages. - * If you want to pass a bigint, a number or a hexadecimal, be sure to convert them to one of the supported types first. - * The 'conversions' module in @zk-kit/utils provides a set of functions that may be useful in case you need to convert types. - * - * @param privateKey The private key used to sign the message. - * @param message The message to be signed. - * @returns The signature object, containing properties relevant to EdDSA signatures, such as 'R8' and 'S' values. - */ -export function signMessage(privateKey: Buffer | Uint8Array | string, message: BigNumberish): Signature { - // Convert the private key to buffer. - privateKey = checkPrivateKey(privateKey) - - // Convert the message to big integer. - message = checkMessage(message) - - const hash = blake(privateKey) - - const sBuff = pruneBuffer(hash.slice(0, 32)) - const s = leBufferToBigInt(sBuff) - const A = mulPointEscalar(Base8, scalar.shiftRight(s, BigInt(3))) - - const msgBuff = leBigIntToBuffer(message, 32) - - const rBuff = blake(Buffer.concat([hash.slice(32, 64), msgBuff])) - - const Fr = new F1Field(subOrder) - const r = Fr.e(leBufferToBigInt(rBuff)) - - const R8 = mulPointEscalar(Base8, r) - const hm = poseidon5([R8[0], R8[1], A[0], A[1], message]) - const S = Fr.add(r, Fr.mul(hm, s)) - - return { R8, S } -} - -/** - * Verifies an EdDSA signature using the Baby Jubjub elliptic curve and Poseidon hash function. - * @param message The original message that was be signed. - * @param signature The EdDSA signature to be verified. - * @param publicKey The public key associated with the private key used to sign the message. - * @returns Returns true if the signature is valid and corresponds to the message and public key, false otherwise. - */ -export function verifySignature(message: BigNumberish, signature: Signature, publicKey: Point): boolean { - if ( - !isPoint(publicKey) || - !isSignature(signature) || - !inCurve(signature.R8) || - !inCurve(publicKey) || - BigInt(signature.S) >= subOrder - ) { - return false - } - - // Convert the message to big integer. - message = checkMessage(message) - - // Convert the signature values to big integers for calculations. - const _signature: Signature = { - R8: [BigInt(signature.R8[0]), BigInt(signature.R8[1])], - S: BigInt(signature.S) - } - // Convert the public key values to big integers for calculations. - const _publicKey: Point = [BigInt(publicKey[0]), BigInt(publicKey[1])] - - const hm = poseidon5([signature.R8[0], signature.R8[1], publicKey[0], publicKey[1], message]) - - const pLeft = mulPointEscalar(Base8, BigInt(signature.S)) - let pRight = mulPointEscalar(_publicKey, scalar.mul(hm, BigInt(8))) - - pRight = addPoint(_signature.R8, pRight) - - // Return true if the points match. - return Fr.eq(pLeft[0], pRight[0]) && Fr.eq(pLeft[1], pRight[1]) -} - -/** - * Converts a given public key into a packed (compressed) string format for efficient transmission and storage. - * This method ensures the public key is valid and within the Baby Jubjub curve before packing. - * @param publicKey The public key to be packed. - * @returns A string representation of the packed public key. - */ -export function packPublicKey(publicKey: Point): bigint { - if (!isPoint(publicKey) || !inCurve(publicKey)) { - throw new Error("Invalid public key") - } - - // Convert the public key values to big integers for calculations. - const _publicKey: Point = [BigInt(publicKey[0]), BigInt(publicKey[1])] - - return packPoint(_publicKey) -} - -/** - * Unpacks a public key from its packed string representation back to its original point form on the Baby Jubjub curve. - * This function checks for the validity of the input format before attempting to unpack. - * @param publicKey The packed public key as a bignumberish. - * @returns The unpacked public key as a point. - */ -export function unpackPublicKey(publicKey: BigNumberish): Point { - requireBigNumberish(publicKey, "publicKey") - - const unpackedPublicKey = unpackPoint(bigNumberishToBigInt(publicKey)) - - if (unpackedPublicKey === null) { - throw new Error("Invalid public key") - } - - return unpackedPublicKey -} - -/** - * Packs an EdDSA signature into a buffer of 64 bytes for efficient storage. - * Use {@link unpackSignature} to reverse the process without needing to know - * the details of the format. - * - * The buffer contains the R8 point packed int 32 bytes (via - * {@link packSignature}) followed by the S scalar. All encodings are - * little-endian. - * - * @param signature the signature to pack - * @returns a 64 byte buffer containing the packed signature - */ -export function packSignature(signature: Signature): Buffer { - if (!isSignature(signature) || !inCurve(signature.R8) || BigInt(signature.S) >= subOrder) { - throw new Error("Invalid signature") - } - - const numericSignature: Signature = { - R8: signature.R8.map((c) => BigInt(c)) as Point, - S: BigInt(signature.S) - } - - const packedR8 = packPoint(numericSignature.R8) - const packedBytes = Buffer.alloc(64) - packedBytes.set(leBigIntToBuffer(packedR8, 32), 0) - packedBytes.set(leBigIntToBuffer(numericSignature.S, 32), 32) - return packedBytes -} - -/** - * Unpacks a signature produced by {@link packSignature}. See that function - * for the details of the format. - * - * @param packedSignature the 64 byte buffer to unpack - * @returns a Signature with numbers in string form - */ -export function unpackSignature(packedSignature: Buffer): Signature { - requireBuffer(packedSignature, "packedSignature") - if (packedSignature.length !== 64) { - throw new Error("Packed signature must be 64 bytes") - } - - const sliceR8 = packedSignature.subarray(0, 32) - const sliceS = packedSignature.subarray(32, 64) - const unpackedR8 = unpackPoint(leBufferToBigInt(sliceR8)) - if (unpackedR8 === null) { - throw new Error(`Invalid packed signature point ${sliceS.toString("hex")}.`) - } - return { - R8: unpackedR8, - S: leBufferToBigInt(sliceS) - } -} - -/** - * Represents a cryptographic entity capable of signing messages and verifying signatures - * using the EdDSA scheme with Poseidon hash and the Baby Jubjub elliptic curve. - */ -export class EdDSAPoseidon { - // Private key for signing, stored securely. - privateKey: Buffer | Uint8Array | string - // The secret scalar derived from the private key to compute the public key. - secretScalar: bigint - // The public key corresponding to the private key. - publicKey: Point - // A packed (compressed) representation of the public key for efficient operations. - packedPublicKey: bigint - - /** - * Initializes a new instance, deriving necessary cryptographic parameters from the provided private key. - * If the private key is not passed as a parameter, a random 32-byte hexadecimal key is generated. - * - * The private key must be an instance of Buffer, Uint8Array or a string. The input will be used to - * generate entropy and there is no limit in size. - * The string is used as a set of raw bytes (in UTF-8) and is typically used to pass passwords or secret messages. - * If you want to pass a bigint, a number or a hexadecimal, be sure to convert them to one of the supported types first. - * The 'conversions' module in @zk-kit/utils provides a set of functions that may be useful in case you need to convert types. - * - * @param privateKey The private key used for signing and public key derivation. - */ - constructor(privateKey: Buffer | Uint8Array | string = crypto.getRandomValues(32)) { - this.privateKey = privateKey - this.secretScalar = deriveSecretScalar(privateKey) - this.publicKey = derivePublicKey(privateKey) - this.packedPublicKey = packPublicKey(this.publicKey) - } - - /** - * Signs a given message using the private key and returns the signature. - * @param message The message to be signed. - * @returns The signature of the message. - */ - signMessage(message: BigNumberish): Signature { - return signMessage(this.privateKey, message) - } - - /** - * Verifies a signature against a message and the public key stored in this instance. - * @param message The message whose signature is to be verified. - * @param signature The signature to be verified. - * @returns True if the signature is valid for the message and public key, false otherwise. - */ - verifySignature(message: BigNumberish, signature: Signature): boolean { - return verifySignature(message, signature, this.publicKey) - } -} diff --git a/packages/eddsa-poseidon/src/index.ts b/packages/eddsa-poseidon/src/index.ts index 1ce366761..8b4f94db7 100644 --- a/packages/eddsa-poseidon/src/index.ts +++ b/packages/eddsa-poseidon/src/index.ts @@ -1,2 +1 @@ -export * from "./eddsa-poseidon" -export * from "./types" +export * from "./eddsa-poseidon-blake-1" diff --git a/packages/eddsa-poseidon/src/utils.ts b/packages/eddsa-poseidon/src/utils.ts index 01dee09cb..7ffc3dea2 100644 --- a/packages/eddsa-poseidon/src/utils.ts +++ b/packages/eddsa-poseidon/src/utils.ts @@ -4,9 +4,11 @@ import { bigNumberishToBigInt, bufferToBigInt } from "@zk-kit/utils/conversions" import { requireTypes } from "@zk-kit/utils/error-handlers" import { isArray, isBigNumber, isBigNumberish, isObject } from "@zk-kit/utils/type-checks" import { Buffer } from "buffer" -import { Blake512 } from "./blake" +import Blake512 from "./blake" +import Blake2b from "./blake2b" import { Signature } from "./types" - +import { SupportedHashingAlgorithms } from "./eddsa-poseidon-factory" +import { HashFunction } from "./HashFunction" /** * Prunes a buffer to meet the specific requirements for using it as a private key * or part of a signature. @@ -72,16 +74,27 @@ export function checkMessage(message: BigNumberish): bigint { } /** - * Computes the Blake512 hash of the input message. - * Blake512 is a cryptographic hash function that produces a hash value of 512 bits, - * commonly used for data integrity checks and other cryptographic applications. + * Computes a hash of an input, given a specified hashing algorithm. * @param message The input data to hash, provided as a Buffer. - * @returns A Buffer containing the 512-bit hash result. + * @param algorithm The selected algorithm + * @returns A Buffer containing the result */ -export function hash(message: Buffer | Uint8Array): Buffer { - const engine = new Blake512() +export function hashInput(message: Buffer | Uint8Array, algorithm?: SupportedHashingAlgorithms) { + let engine: HashFunction + switch (algorithm) { + case SupportedHashingAlgorithms.BLAKE1: { + engine = new Blake512() + break + } + case SupportedHashingAlgorithms.BLAKE2b: { + engine = new Blake2b() + break + } + default: { + throw new Error("Unsupported algorithm. Cannot hash input.") + } + } engine.update(Buffer.from(message)) - return engine.digest() } diff --git a/packages/eddsa-poseidon/tests/index.test.ts b/packages/eddsa-poseidon/tests/eddsa-poseidon-blake1.test.ts similarity index 99% rename from packages/eddsa-poseidon/tests/index.test.ts rename to packages/eddsa-poseidon/tests/eddsa-poseidon-blake1.test.ts index 6f5ca5044..f0f13c817 100644 --- a/packages/eddsa-poseidon/tests/index.test.ts +++ b/packages/eddsa-poseidon/tests/eddsa-poseidon-blake1.test.ts @@ -5,7 +5,6 @@ import { utils } from "ffjavascript" import { r, packPoint, Point } from "@zk-kit/baby-jubjub" import { EdDSAPoseidon, - Signature, derivePublicKey, deriveSecretScalar, packPublicKey, @@ -14,7 +13,9 @@ import { unpackPublicKey, unpackSignature, verifySignature -} from "../src" +} from "../src/eddsa-poseidon-blake-1" + +import { Signature } from "../src/types" import { isPoint, isSignature } from "../src/utils" function stringifyPoint(publicKey: Point): Point { @@ -352,7 +353,7 @@ describe("EdDSAPoseidon", () => { const packedSignature = packSignature(signature) packedSignature.set([1], 35) - unpackSignature(packedSignature) + expect(() => unpackSignature(packedSignature)).not.toThrow() }) it("Should handle a signature with values smaller than 32 bytes", async () => { diff --git a/packages/eddsa-poseidon/tests/eddsa-poseidon-blake2.test.ts b/packages/eddsa-poseidon/tests/eddsa-poseidon-blake2.test.ts new file mode 100644 index 000000000..74dfb389f --- /dev/null +++ b/packages/eddsa-poseidon/tests/eddsa-poseidon-blake2.test.ts @@ -0,0 +1,61 @@ +import fs from "fs" +import path from "path" +import { bufferToHexadecimal, hexadecimalToBuffer } from "@zk-kit/utils" +import Blake2b from "../src/blake2b" + +describe("Blake2b Basic test", () => { + test("Basic case should return correctly", () => { + // From the example computation in the RFC + const instance = new Blake2b() + instance.update(Buffer.from("abc")) + + expect(bufferToHexadecimal(instance.digest())).toBe( + "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923" + ) + }) + + test("Empty string should return correctly", () => { + // From the example computation in the RFC + const instance = new Blake2b() + instance.update(Buffer.from("")) + + expect(bufferToHexadecimal(instance.digest())).toBe( + "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce" + ) + }) + test("Longer string should return correctly", () => { + // From the example computation in the RFC + const instance = new Blake2b() + instance.update(Buffer.from("The quick brown fox jumps over the lazy dog")) + + expect(bufferToHexadecimal(instance.digest())).toBe( + "a8add4bdddfd93e4877d2746e62817b116364a1fa7bc148d95090bc7333b3673f82401cf7aa2e4cb1ecd90296e3f14cb5413f8ed77be73045b13914cdcd6a918" + ) + }) + + test("Passing an output length too high should throw", () => { + expect(() => new Blake2b(65)).toThrow("Illegal output length, expected 0 < length <= 64") + }) + + test("Passing an output length too low should throw", () => { + expect(() => new Blake2b(-1)).toThrow("Illegal output length, expected 0 < length <= 64") + }) +}) + +test("BLAKE2b generated test vectors2", () => { + const contents = fs.readFileSync(path.resolve(__dirname, "./generated-test-vectors.txt"), "utf8") + contents.split("\n").forEach((line) => { + if (line.length === 0) { + return + } + const parts = line.split("\t") + const inputHex = parts[0] + const keyHex = parts[1] + const outLen = Number(parts[2]) + const outHex = parts[3] + + const instance = new Blake2b(outLen, hexadecimalToBuffer(keyHex)) + instance.update(hexadecimalToBuffer(inputHex)) + expect(bufferToHexadecimal(instance.digest())).toBe(outHex) + }) +}) diff --git a/packages/eddsa-poseidon/tests/generated-test-vectors.txt b/packages/eddsa-poseidon/tests/generated-test-vectors.txt new file mode 100644 index 000000000..1d89d21c9 --- /dev/null +++ b/packages/eddsa-poseidon/tests/generated-test-vectors.txt @@ -0,0 +1,100 @@ +d3c32a9419c9874c0d240e203c0e2784742808fcc02518879c65f75b0ca07963ae3d765d6d6e2c18a74ddfabe84e0b703afe111deccba4bf39121531eb54271efc9a9d010eca12c9500216a4d8abc57ce730897209f3f5aef2b4dda332879ce4ba2a12093f3bbaccb36affffe69c9b30720e774556fcf19b84887b4a9be90656eed06a14f4fc012fcfe5c206cc93f20bf73eddfa3e223478506ea962389133728e55454b590eb4032b9e62b9e68a575c97cbcaee2bb3a840817da2ff03053a9d702d4aeceaef3e871a0d172720805da82f82799a712ee7302b6d76827bbf5e6ae4e719262e871e50c7f9cb9c5e65da1a0dd8d9ed9552d538672f2513a05dae121eee5ead6168ad780837e6dad09127b4eed74a69fa5ca80b97e30ec7a97f4ed06cc3ff3c4940ff806cdef0873d0a105935ac76fd16ae39ef92523c81fb7ac9877dd834171ebff47aa0f44cf2b640b27d655bbe174ecfde5fc313e5d203a79537690a1d45bbff85c0d77156eebc7e79d4ccc8fadd39afd2427dde389884f636d419fbcf89a9761637c25f3cc145b159bfb54376106fefed56759572bc05537f8852a3d63c4cc9105f3d86ca1591b6029aa40f1218e70928816ca54dec30af2d1c97cac704bcfb9cc89d4f074f4e1b38c00e52b27c83dff6a22a575d35a94405827e7b219ee761f64abe8ccdc1da319e1f5565b88f52764796d2415398a181a90742257d9c6cc9db3b71311e89e8ee5b476b690138771fc4a541764d955c0c35c05d5abb007df42dc83b2f0def5487eb0433a8c8f6571c42d9917688b941995a9ff968fa928435abf789382f7899822f1c6bb82ecbf60dbce71ddf9719a4cb48a567e14f473cee212d60e1793307ce9cabc3a1bbb89400553c0236fd0f083910ba30db50ef9b97f5 5c76e8ca30fcfd6d16b717ee89654f184027bbaa99a7c22c0f3797a32b5c5134359647393ba45611231928ea5d2a682a418a1ab64d834dcaf60c 48 af7a96c83a98e9fb636bbbd383dfa33a0831dd0773261105c06e527a5be398b5335c36e088c274be825178bd1c702523 +0581d66f43af761873012d1205329b0dbb1656aeff344a3a590c0302d4e313d820f76ca9cd30db9ec2330b00f5e2e939e9a477f4864127bdc365d6d590d17dad8267312ee40648a8f2b55bf92c87249814449519fe10dc5e378376909c21a8b1accdd189abdf8501baafe91a62dd1f4b9bde729aebf6e09070a4df87144f34193fd85eb438d8aa2938f1e109a22365bd3fce1a86df671e567342ef397f61e7f351458cbcc6639791edf245ab3620c8447f69739235ea18e0872eaf5227aa1abe884492a3cc0e77b12982cf2296de7c90a211c933cda6512284e2cf56661ec27b9f4757fbc80a09763b8f0e41f819793d0a7990744bdda8ee970d176e68237a35930e09456f433343a51e801bd55faa96fd560d75ed21d630a72d93c0d76066 ec74ff71f99ff481d9f176013f8511fdb8fa21406489248a2e92 43 005e5ab08cc7c35691ab705c2ddfc76482b40f1794028816591b0645661325029bfd7dc9007a786b08b53f +bf267d559dec13c127dcba0d2962f142b8516421a67de8a9a6e71d3bd70445964e764175f43f3e70a3b26bd8522b92ae86342fbfdac665d01c37e08ad94a56efec612678219b1c02dc45f97c189baf6c9973c79756d56f84cbd1b37f83ecb1171b15093c01727f19dc2f4e530da59b9d5871e7ffaae069201cd18d5d1f4a51e1cceb381b9a25a6d18f39d3ca3d25322605c1dc97201e6924773802ad87576489a9b6c6663f97d2dc24e1d37b03636b2442e19d4bee2b48b12de59a12df0addce75a2ac07bacee84eeb69df1b5e7d45209794cd7c77b1aff576ce8551320f26cae5ea1ecc469bf3fd62a6839a29a38e2566914f5b2dd51f7e9bc2d20ae8f941d5741ce45e29b33f021389f693964753a96b695fa51945625392ad1deb79f77e5ed97ec8f2826e855f4de8e350825429d741cf818fa0ffe34d8c89a458a2938903f81370af0deeb38d293a7bd73ec2eae65323ef51575d47de0b012315ae879efe04c5b38c066e9752d1b262361fd34a8d57e33b5819af500145569bc630f6c60117accb807d37fd2935f7208875bdd5707e6ae5449ecb769f7db94fb1b686eb40e8f5255bb6b0540d671a40e31c6086ccb83fbfe9dfe9279cd188837de755669ba94411277c76e1774076a9fe4c8c48f95fd46b0f9f4d57fdabc6a7cc44344aad2d350e078a3e0c927b75989c9aa389155e8f92869f6b14d019e61749cd189eeb424709322543834173e2134ad60d01210c1b286285 bebff6651767c1cb345bb53942b7f126d78830591953d3bb908d1a4d5928582143bf 54 8fd58157cb9b471d05d3147299dd6c6bebf3b4ed26007d94ccbdc8da8b3b1aaea7898c131de13be0850e89347fc9af64dcfb716e7bd3 +bf2da91f9932e5c0b33e9e8c7d8bbf3fdd3f8840ff924612da56a7814c0f56a1be5350c885ddfc203abd71014cef4f96a75ebdd140439d04807f5c6895c200a9ef3953e37933a9ea577839de0aeb2f861da4ded4210a64c38a61cfba3ff7bedeb142ac8110c3776ccc80f13ef7f38c520d68a279bfddc93693ed3b4e2b944773f3d6b79e0c2fce7c6a2741c22d6226fdb760765488a8ed4bd058dbed8c3410875e011632aa3321697ccbbe3e206106b2222e931cd1ff980cd79f76b442f74baaf11c2a7dca56912e772e94c8633c26fc833519a38d4ae543e4322d3849a3856bb655ac9b4669486814feb22ce3bd852b904b908758bf90639a587191650fea658765b5704817ec3c2ad05af4a86177f83c06b22c0abfbbcecc6060b381165a79199993adeda1f949d1849231eb08fc4d7f4f5cd67572415349cbbcfefda9991145314c23ff830bef677b6d64ab0c920a018f497f15b2bdaff81094bf2f7a66a34b0386efab6dd1dbfa8e9c561bb148f6c6ba52823fee3b336a1bcae2fe6acafe0e80db5f686a901eb7e22547a47cfda4142333de02e783366de45d06a0c522e1e0e69b3e5ab039ad762427f01c8dbc9e1a27b62e24c2b33ae3d3d7274a8fc6c55a6e826f6143283c 876adb584a86572a0abff5813e1bffc892320f72205278dd297ea3096552 58 593d7d604aa64687b27280b75813a4e44af62b4637fdf6cd763cb7227357fb8e03ccf7ffe3b109d6beb7ed3befd3293612652e3db6f0dc7c94c9 +c1e0a9973357062ad326e0283ef60d2eac7164fb1710c78f50ea9dde6cad0a9dee99c310eac07f23d097559b5fab611c4e632327f0225576bfbb91b36e69e9aa5ff50cd3ab6280aa36711b94953b653fc40422dffacb523ad53e6006044ea9a6b4ad59327eb3bb2e46c78b6fc5ad3b686a0379668f07e57ff6f9a6b8eab1ae09e677e5d561cf9809d0d19d6491076ad456ead57c0b5f5bf1ab9fc9744143eab29934e2941296d8471d 0285e7106d58aa6bed2e94d4144feed38f972eda27ed8b49d7fdaef67c665f72924bf251bbf2355f 43 e7a60021c13ab2cab8c7f2e625df33fb295387ff156b119c0a9e25dc2213825e20ef3d1352723ab0e6a152 +b6b7838f11aa5240892aeea4aa402bfa124c600a6deb2b0d8df15cf4427d3af347a5399d7be634dfbdb686984637207c20eb1630ccebdb205b0a0ca6037ef2c9c451ae02836eb5d41e1a55b5160a9d55b64bc481bdf70e57c55df953b5d84a0da1eda9f3aff9e5124f17ec714326734752a43a459dfeebcb98d162392cc7ec8e7bb2780d004362c029d70454fe387af21ba4cfe1868b006f8d87489eb460fe2c5386243898e24b25de7633eeef1c50b9bef978a7ebc6f6aef021c862766c95bc4de75b0f4e1bfeef8822946735576c4210d79945714f76953afa84793e2603ec2b3d20bbfcf7627146f6d346e4f71d934c89df77cbd2ec522a6eddfea034480a8a35d3fae7149f1b423bd944ea80fd5d3f72eadd45ceb09dcbca808348d9e2fdbdcd4a38f2ed05431c705350ffd2f45935a199cb27c54118e6db6fd6f5b5e1aeb8d7ac7bc6a397ad86ecc24bb57bf7ce9b4b546f66dd0021ca0e9485e862c520cb81d198fd8ededdc6d1288c628333b9ad43a4c2f0c8a9abcf6e33e5d004463c8cc0241e947dd7fed618bcabff22da47c8fda92f479381b23548b4d9375f7a849677090ef53684bff715837f6e52af54594a94dfe6d5cbdd6c20473e783321f160842e4edd225d72ce00cb4571446150481984d130364e0141f9e0f55f78f832d9798e5863edf86e285c3ec2518bb28145116a57431210d99c7b74f22c0e55f7000eeca58cd6c823eeca7c30d47c0bc2208218794d497b8dfd0502c309fd194fc7a6b082b0a3fda9322b7da7b9a0bcdc8437c1fa2fd423032d6fe04ea3670538b6953ed21a11a02486dd62d709ad08564d10119ca0c45608d9781945766a2aebdd80620b86ffbf9706aa8471b794f80cdf8f319ad643aeeb8acdc53dace71e7b52c4330ae134ec9e0c9bc5fac5092d37d6d378e56af9670770a7c747105bc3cf6e77e531015ee9714b647222330a51659aac49d269c437d77f3522ded11b34c3be688d91e708efc69589b5367cddc67cebbe9670d3da936d170f711560693380dcb70d7ef5fa33f5d91bad68ded7cf9fee382d75bb0e691435801677e9fe14f39a349b5af56e599eaac38598b170e26a59f5b080977bcc5b43d0ad1838a40e286c19a659adb0d8767be056db1446 540e6e533711695e9e9e01cf3ffdb6ba7a4545e4b6c2b3be742056d6b6ac159dc05fb78311542287cee3c15fd515e441b433e66d80485883 30 683f9aa0c469abdf72e50a86a344bd835b84823ca80db731d2e6f1c3ce16 +1c9380b8d55feeb8078b458c6cdada60bd33439d9ab1d4afb71d7a094af7bd2da7813df84e5ea15683ab6b747a6d51b5428e4cfb40fd1aac22cde153f4666dd0fe66d66457e28d68b06d8489cf44c0c1bf6cac607654d1c7ddd5495b9ad1c0a1d92e687f1b3df7b87ca206821d5d1d097250d63e44b26dcf29dff1cdb20140bda4aa0437db88a1dd57fa24a5090a3e92c499231d6e42d83805774e3738c1ed2ca7a9e351b347d32718fbdc679fd4d30860a8fcc652d0eee78055e808287cd3e742b45c3f98c3507815f64b8dc58e855f202b46965029a0451fdd55640afa2855472d92f2d160a434848bdea7bc5b77544337779d136673c8a98d02150b06a613101945ea3bab04fe03478f5f35533fff2053f94db9f24d13303f23520d270f306bea8451efc1de9dba38969c6dff9e027cbef6cac942e3fc43b2f2d1e57db94773bfe27ea1e35b500a53f5216ee639d9379674b9667729ab72f217d7978799bd2ac70505e1ba8102dced3cbd442605c4355be30d8a6901d6a343dc13586b599c99110a4ad60d817f72e75561bfa630ff97fd9fad27a6ee50f89b795796cabb83ff3407945eeabef1611eb0e631789d808d7cd2bc00cf3e1440e867a4ead39452f494c4d7b24c60035d07c5aa3fa18e6e37321bffa11fb69de8758812ec9544cfa16c49e58d8d0c8b73b3d1bd0e8d3268d80dabfcec46a1258e2a4ca2419dde 5e9a2f959716d14200bf2f2e8aa826f4cae8b5df1efbacbcb8352d1826af0f3269b447ac3e8667e4f496e88a2c5471e91f46cd4fe93d6489a3800ac84e 64 6450b247b2db2e36a03a619ea706ac0dcf1e091b9212e3b4019edb34040c51e74372e1b0e2c666f9f4098c8cfd14fa5f9a86ba24875d61771a74e311964869f6 +394cbe5daa1c8832428b97dc3c4f2f59d358426e71b48f407707466c5e0c7d71fdf4fecbda9d29fcf11dbcce052bcf96a1aede91afe064860aa57710e5a18ddc589c3e476ea4dcc9778df5a6d1588a52012e6e73be8c7b90f060bb2e9cace99b0be5663f717cc2e337c2ecaeaa1609beb7b734deba3533b313f9a89b953a663995a9abdbca4eda54526eb54f128cee44cc02d1c15cc41b46ee2153a15fb40ef4fbd882763d85dad8febfa1d5488f3f6668b482b5a2150294e995c69bd7fb86a7eb8bf5c87e0527b11db21f10ca105332bc6f3f7a151ae721c5d1c2790ee4e73b53be5370afba0e089f711503bf9383eab0d0bc157a29c72cbad1d895f7d5319f4d270fc2696288f4d139a8e62a486575960e40afada06742a60fa8c082336d08b37bbc733ee57329cc0de7c3fb6e46abe0a0039e2a291160a7dc172106e851a23a92e5b202b8cb164c1dd7be0a727ecc33bbb9412598f8ca3e5e6b17eca231689eaee0b34ffe27f70d7b701ea6ef918660a21a17ba05c3fc8057895a76342e2652733eda4e98a046b77ca83cf7bfd87338220d605ed5275f8ba72e4babfd6449465477f4019c81fed54cacd95d1f72c31c458e9d0ad9c9c30a6fc44497af2fc4d1cab364f5c24ec5ad2bb5fc766b7e913c9911a541d6e0536fe1eb99d131864bc16a96af16c362a8c03890ee6c0c9d486e0abdbde74e24b53016a44fc99b2ad70d17fecb19d4c16fbca677c3b177b3b29a36db92e4da23e7e24f6585fc562c6b82897ed7744b7fb64d210dac2b6ec2ebe8f99a1b6865e0dd7752a4b09f56bd595b13a23956ce7e04cef6d1f2e20b28ddf62185fc22d141635ffbe9132e3914ebac82cff784d792fe8428a03fb72363106dea af8aeaa5137f9bb3ad8c0dabcc84f344f0ab839157eceffd5734b3ecd0bc33dd61d3b8dca93e59bf58 25 76abbc6f563861c15cbd00a099d16350f0eb146f5d20715f66 +4f38d3aba6687fa2d009951bc5ca6ab8bdff60f206d90e431b32c899dedcc2ad2a0dc8e04947c28258680074cd20c88e8b95eadf1fa795bb1e7bd6c50c7642c135801552f9f683f54c09209e0e884a09fa a264c7c52253a6a04033ca74399c6a98360cee09d19ddbc741ea5623f870c431860bb0649cab9b8e33a7a5e25d0b291dcbffdd2b 36 c1cf33f49052810b1308732c2bce883001fc62c7b816008e3df2fd6e2cdb956fc717db1f +9d0917969db748cecb19089f8d2284a63a57553e6d0567f669ef20369a4641e417907c33d05764062bb41d8af5203685d0ae77fe2967b17313def03791d15d02a6b18498a1a47cc10a80c9489029663d56d4119b4e2bfe123aa59b8ef8270570c49afded56bb29fe14e8c53a4a333a83cd6c457e1552e8803c70f9c62657efbc4c3ef21361bf134163a6c420be27c2e33f027e393f8a9651eb280d91c4d8cf21a24356a59730fa949694e8a37aa8ec3f39d0200e1952573210e2bab949d3d8c09953b3a2792f03809ee1e23498b2c69f6220fbbe022f40dc5a9b68bcac29b8175e20c056848e02cd288d7c2468fedda26386887592845a954aefaebe4fece00f6ec2fabfd4f95a385f2b414614111d24c22a0e4aa249a91e472284db789c601203ffe1f98fc990f984ec301a602981bdd8353158e71753021bfe3efc2cf8adb7a5b828cd274d1763d0631457a5dca412949cb602acb3bbe13aa014a7ba863ebfdfa2239adbb05deb5c1669cfbc6bf9a7bf409e88ae23d2fb4bd10a5e21482373d2a0fefb822a5834bfff7845851535367d3b23b4401cdef68dd7bfa875c355e49fc54178c72aaa5e3516d1247ffee42203ceb92021ded353f889b88268ecd849620f5da279ca659cc0086f102847a72741810461d01659001020b48885d9e5ddd96141581529307e5ed28e0865ea417090c7a373ebc46a34c77aef20cba235feea6215b4523a32be2ee15174b09aef534ca90398940150ff868db9aee33c127603b7f8cf84cfe0b0da0b062823a78a1d2629fdfc6b5ddfbe3305f1260af48589f59368ec0994cdd441c2011b28e5fcf63516e46ae859fccc283ac423d47cd83cf84786cc329e6d69fdddd71caadedf295ce086b120f8c66c56e91505f128efc28086465a4a341a0a123938e4fbbec8d06b13a4e5817b2c0ae982033ddb0a0ffc2de4c3dd0ff63949a191f05214da7fa4318ea3487ca5dc5516ae4bf7247cdbd2326034f92664d6d38459f3237daad93982f402b139e1aa885ba4b9501bcdbda29ee92537fa1f637568bb08129cd56de333a4f3a93febcee0d77b988765a0900006651e00aa9468a59d18ba9a66f477c3f19fe2f775b3727b6880bbaf2c6720747908f2d030b4dcc28ae795cfd9fd3b88bf72b94d8bc83cbd354d62266b0fde7d552c564e33a9516114165eeafe4281f3a211a653ed0d3d475269b1dbc9740a2233d2d98847f4614a616994693e99c54f7dba896e2eaef325ca9daca5512ac3d2713908f4f6517e7473b6f59c16a36995050539ba704216d7329810e24c1dd076d560e99670c02f355dc0bf0bfba59e3390 89923501695e2d4978ddeda7c1a58ac986f54e493e263d6d8430a2d931afeccfd3711c750fb85535f62cc243dafbb494011b3c2e00e574e10dd6b696ff68b9 32 6c3141ddb56dc865a40f5c41341fcf531009c2cd2fbcf20aed7eb41fb3b48e81 +e33ae1f521b4dfb9c4c082bd00d33edb37120b0959e5adce23a65d194cdfcb690d825b91d37f5c81cb9a63e543d7037f9cfcc25daf1662c8eb05738dc0ed22a071805a124b3afc4f5d762c9437fe03e0d0fb1e54f61629f69054fea2c6f75d736a138f46cbbee47a154a1bc8c6df0b58b2a2f96fd0010a2953a914f8a9fc2fd7f2cf1c2fe0726c138590109029815004901ef032e7bcb90deb1339e34040f1451e98620d3ed13837892791140173abc99d5a24d8eb60d9d55b7a7f339e1c83604a971fdb2eb1ed2c725c60b503dfe1af91719a1c2a9a625688e3b88322358353e890f40cc8415dfc9cb0af761d2c5c4195d0a4776d389d6dcba38d2b34a22b73641f35ef880b91027fe8f171beefbd41f65cbd124f890ba2d05c130c287562154d2a6feecec63a43d32f614c3d5cf313e3df0aeb9170cfce3fa927c987924706f8662ca31e32998b78dd3f63ce8b89ddb891b2cc118d88cd6cccd4962e2b6ff13b4be0a5e1d199a6baa1bb4cf7b3e06d707092930b386482b858994bd4f03fe54ee7e198c56888c737eb870a4783afa9bfa8e00537a25c62186e4536fcc2c040564442ff9bed27fdbc8e94ebf8b2ff33cd515c1d726fbe263a7b06dc9f68707381748534c45da37ff7a98e71d73af0921b94eb1e51983fe4368a4ab667e875d55b7dc60d85daa82e67f9e25676a9a0ffcdfc4e276a11b63201556dca4e5ecaa0debb0a1b0ef7292f9e51817376d7e5218444a45870dd7fc80984adb7daf6bb32cc42f4dcc18158861dd81f9c73a8e4746cd27cffa42d58cacfb6057f9c3fd10c502e596a99304ad033c032291c1e7b24f126917fa73fd6d1f72ef5da26c5e16ad6e4b1b72b2290a6cc58a00e1d84c7488c86de4183af02924804839ce72b06af9cf275ee9ff3d45985dce3bbfdf25890d864c22679b09c5eef4e6452008f517aef737f8940868a3901e5cd966bdbc741cf21b87f3234e6d6949c468b0eda3b566f455c1bb1971996acbcdd2b415888e229229903a7c02029c790b001e1851e1ca95869751852111d8379935e33dd5e6693fe00e54bf1910e5b92e48878e1761100be958c1822999bad109e396ceaafbc332e80b5565cfe75cb2e25695b4f2371317802 6ea28091829c23769124728156d5d7f65c62244c5ae3019d35704d0d7f09c49334a2b9bed9122ac334129e2f32f35282edd910 55 224a07ff090e05e08c1fb2f9b27af87a4a6c1a2e1304295fea6772a4f1cdfa6e45a6cc5f94170f335aa9eea08808d75b17add0c6b60dfb +c6b5782d97501b3b9fab94d6d668a9914ee8473ba0983ab7c3e982fc5be7c51383ea602c0f33 b03fa4c35cba87e1b7c96ddc16040356396c88be43ec62ae08e5e0e09ee97cb6ce9802dfa6b3 54 d8a995a6b8413633009b2456d7a3d5202719edd61e1795dace9f440f50b6053bfb40bb69e9e114d345ed587528e52534f4f37430ce3d +b86522bd35f246651fc3a4423c79e1c8d4d8244b26fa38378102aeaff5f84ebd8691b5e22efd63699f073acff29f07b748b4e951550abef130a8611fe8e038ed26c00f8e2fc2e4ff715ff3dd2a17b314df892a2c62d979c33d1501790ecffb23600ded42fa3aef4ed556f7559a00d4169c00ed41c8da82e82a28ed53e5a7753a141de55272a069bb0a54547845309f27abda98fc7ca694dd439ca8c85705013e50b951f90884b5cc3bfac2f7453a452c3cb44fd17c047c091a25e58d03f7ed3b3a29858aa884eb8020401f7a829446a8e9db330fb2fdc15bbe1bf708c7e59e1e2628213f30388b43f06cdf5279999d54e6d71ad12b3c28fb60d2001c435c50e47583bec1a0ca1427b870db5bf423f28b49c7c12f6711660a7a7fa7bf6e590ec47e77c204ed6fc9d0ab6ed6e83634c89663ade410f0a894b73fd2948e758e2e5c5e8f1fbe59f4d726c0d9a930b7ac81d328f9634f4d134a537c239d7ba4d761ba9d37c65e2144082f494850f9978408b23ef2136c1df31b72a68682d64bfdf894c287b4c1bff32da204753ccb135729527ba5c5b0853da10b440814f057a3bc 70799db7f0203cc3b7d4ebc2039cad4a13ebab8c634820c510974cfbcf6c580891871ff6c310f85a09e3cf0ae17e16b1fab2d4adb0cb3629d2c8f6b164a5 32 378ab69e1ca74ab1345fd3e8b87a746ae33f85a6d3bfbd29531f5bd1a973c769 +8167c99983372b30ff9113dd83ee0c8b7fee45607e0113a20490796dfd1b3c50ad429408794149d6fbd1fc827db4fc8dae952c714a1a7748cacd0a897d4fd1abfdf76e0b37863959e2b5a3cd5456dc7bf289812f2894fe38102d236a6ec7f022e3ca5888f0d58ee678be7b0287edeb3db8efadfbedc44a6928e435d3ea67328621b1b1c229f02ea396eaab2ac3513a656b8c48725ba23334eaaaa4344b4464a59cce079392773ca7f17a84563a1d0576bd4f41435d380528700b455fd74dfab3417a08276a425695e2da53a253722a6181148e8fa7d91c9643e6d2bccae7e58f3c3484130acb0252354e91db61fdf7bd5d87bd4c7736ae375b215cd762a91db9a0dd72b37f4a76a33331091d90741e28a1ae28a7a472d9498c748189fb10f56a69ce0b771cfbfa81f4d4c3cda3f4165cc79f4d6c39b50e1b186a80316a54561ed939d3d3d3f1e551ef6e883b714f3fb56c900682e9319669576d72866fa9f393f22e69c54780319733e82a54b9c6fa1cb4fac5ddc4b7e9bef4bca565ac789577de1464e099f7c2e7447eae3b4788fb41305ed7496bbf64ba1e7452bdcf775d6a568f8f84a500261ddb20cfcdf8709333f871f656871f4f1f7e99ebb9af15be0cc16d42ad2b0210bb4cd8e5c522bf15cfb52d71d4ad5468427f4b5306f6dbd46f372b9efa7cabd3be1ab114d3c6455e01a8a73c0986bd828115b7ba755e7ca645b4dd8b11d393d27b1e2b78692271505bc9750948587a92bd825e03d3f1572760aacdbdd0319acd695b55e02619ad60ae054d154764df07ae0e86c5ce75c7b73d3c15294eadb182327584bb3bf42d1ad044dc992ec351f094697366b1758717091d22184fb1fc384f1e71839d1db69f2db4d376a666fd527221 a2b1ab458a84d03b50f58b8048845590d0c9813ff321f692f1e22582e8a4ebfd9ed20bd6 53 fb0d0ecda82aabff2de9eaceb51fb575a511433827b8ade783f082c72c3381bed9f801574b1e1af95c5a5764f6a2da7c8f10358821 +7d4786ac2e900ee4ab99e47d6fcdf673cbaa5dea15906824368b3a7a335299716444240047fd5c7bb10fac051e14ba3aaa5ccb2168c254e2a1d58bbfb6d809015a41d1d6045148f0205f0bcaa26a8ad37d900c80bce8f976b2b25cb3025677384fe5c697a16435a042d6f3ecf2c7bf2a03d0e438893945fab98fa35d200ab855be31006ca702bcf44197e73f38656d811d14eea7539ce54a73704226648a7071727e6e5e5cf91e07a22724fe701de3858551fb96d771da48a93a5ebe12673df56778036bd6ced0e9c49225fb973822bc1ca5f285d869dbb2112c6868f98448d56efd88aa9a1982e3275dfd14a2c070618701005ae4b134ad9a28deb48bb6ae4f32014af8a37ca2ba637c51fc79775da8a2a0e73ed2efdd307c9b536148537e092f259a4f048a0f3021b39ea1acfa53df90cf244688b643a6787c88fe21cdf33b9653c846a65e9af8fce8fda9fb6aad19d43341b3257c834bb5e4928612df832164bc030af20830f2353b6e760267100e51efbc132e9ff2e8101a33db7d3b9021564e386bb3a122afe0dc309152b0b234011be7133d4210c3c0ec5eef2de289d15a55b7b28dc8bcf2d43c6c6de2bbae6fd1f4ecb608d61d9e4c87cd607e220f78058acc54d1c09a027a10dbbf69242510969a3335f7009b226bae3a35035fbf584e0087290e5eee0e72558de1fa451239419a41fa326c0748f8b5b84e66a2e221d50b11d4c38d4d6bd7d54947b6f5730b26645693c1f1ba31c82f9885f850e6c95b124d88ac496ba7ff6fa402f930af8266bed449bddde8f32c97026d345b3a12476d4fd9b4c317b789ac646b0ec724cc5b632292bde94e18ad290d5ff8bd34b90cdefe05387d1c940061cb56bb8d13fd8060332ed4d0bbd66c06cad7d892816e5f9cbb966d43e17d56449a96b5d7f4194179e0349aedd38f75bcff16dbee36368c76688662ecf7773a60b0cf6f7d1fb531c515a953c27cafbdccf763489f3df62c069732824e24258772b6629ef9d1b9851ff5ea6187edee31a5039642567a0798cfe7b2174fad7def82384ea891324860d35365a277e5874ac48919570877b2866b21c6cf1dc40214c12db99056e25660653091f33307b311928dcfff83ec2dc126479a048912d9c2c15ccdc57e2656e0027c3d4db1f49866bd2ae1a2b25a65d784a0dc801f593c606ec0debc26511687d147ae86113c3c6ab1a8fa 901dc9cd10ee9b7cb46c56ffb7b7ef89997fe31d27be4d2abfa5be0d4e1118814e06166de05ce12b15ea65c798f7b2b415ea1ebe084bc1fd4dbe57 61 27e402e910db4a5118709521ffcc8858759ffc15cdd13f5847a68cb38d4a232cb14123736ba6ea4a1269b7bc2cd18b09efa7ceb9fc6c4199db2af96102 +c4db75e2663ede1eb9003bd3897d458336486cb1ba19bacfbf60958eb6e2c595c6e7f5f24a14704dc1ff9983a8c697c38d4e6b876c5d40878a6c1cf9ca4fa07a17dcbd19abe769ce8212f645b67f9c9804f53d33a6bc7e8043284f87d91e319183e7d4c6dd23c7d4414ca65dc969f630d5cb0486650267e830af0fc36d1ea95b8a4b4d1d96f8f06bfdd40cf9f2c989c2783484db916f66c5e74346df660171daf5c17dcd7e648bbd9e0295accc7e76afca272fffd14564fc60b12124d4b5de0df8b2255785f46e5e3ed038f817732638d6588edb9397530e32233a175db5ab3901a0533f4cf8ba44251cf16ab6fe914bc36424d5e164d47626f66dd28753ffc2944af862e0435d26e891d90e532e395c8f32e568e517b8cea667b7e494f3785e087e55997d1c2bdd9dcf6e8458027bcc0cab1b6a10f6a75864675d030629f2183a419f0cf76117fc3f90a23d28ea90d96f1dd838bcfaa75761fd8defa4024962ce4f7f3ae52fca204443c1bbecdcef66720fa41f9b0cdd3a53641d3744139441715bd9379ede6f1c5349c7b2c1fc7a03a45a9cef2e7f63573565978d1a784cefeedc1a23e4ddae179879fd1a5f13138176f4e699fe5f375e9122431120a24058d8635db99fe1b3046960429190ad8b2a9cad0e3b9a200f595ee2df26284b69ef8cf6dab25dc17bd0e42e096845d6978bcee7d5710b4d52563a2ca96036e9e26536301227c61b6327b6e25c8339da56f9b5f8ef41173cf9d63c382260e9b2e733e9d74d33e44d791e089a79aa4605127407d279bf78c116518848ccaf60e0e93b0960f4d6c565f5ae6d7134c215a814bb5136342e284779682ba755c42e0ab7503a8baf9181b707d7ff6b47a07687b30891aa8055dc6afa9a7f6ba065244f49121b98421ea635cc33657d63c0990e32bdd9cf62cfa0aeed33e2b348b36607935b472e3fb773fa92abc2d4d6d00dd3786e69e8117d6bb9ff356b8d0cba217290f4fa84dd7e08dd09c0bde5d1f29b7e4d6e7cb6c28825c26470bc0cfac601873c4d934a42b83b5a6a227c1d7d949796e6eea398654602804d9c732603c585f30ca60b42a3dd4a0aa94691d7f077fabb0bac240a01671d5542acb38499d975b1175218691a5a2a2aa4d5448f015167feafac403f6d757a6b507504371194c43700299e534ab857f44b7a091929d150fcd339d37bf6d5f90110d1cc5ee0618d3cbb15743dbe77f84b74e6bd74748e646c15df53940ae8db77078ea9bc7a7d0bd5e09461e2a3aee4b79e84c52840fbb1ae863215c703a2175e55206bdaf7a67cfa3b53a8896a15ee086e9ebfcbf69f8c03cd4b0326028abb67b83180e0a97ce1 9b1f474eed1208c60b361b9fa1ae748ac52e9ca1ffd08ef21a3b5f540cd780cd3ee03b 27 8d1c1f830f192a4f7033e1668431117e49c8108c68b6002222df2b +85103f18d0bf4906c4b5978700b3f36d0ef4cac23688a805b6c32be6b355aec6c037f1bb1771f353f51b09e19b51970fe43141424a63b9c4f7569cfa23282b2c92940038eefcf4774fae5dc8d1ed5436a0a4c79dda1542ce735f613e29c950a6bf2b1f5a2054a6e2f56c87e4a31acb722caf7e3ede956eb662c9f6ffff5152b87c83ea02ae5448a9ec5deb17b88db96f5622612b0987e880b360d072f3c9323fb5ef8873976f75b688bc94117a40914347e38f1b7b6825c3bd1882fc9d3b2ceec20d7c8a492a0333b4425c393af671b5f7e1a1191b04b18f4de98ff72ed7a1e68125aa67b640015ef3f32f18d213ce70c5bc53837b5e5b786981b9e5999a95f3ff9f8d9cf202ff7e7095384c1687c3bc5d48cd7f6e61832e7740acbe383c74bb584edf6424ddd4f1a7242196e12d0c3902cbc567e9e4ed838ae8f051c0ce210a745e6331abb44c2835db04616145b9772e130eb087e572ed8e7becd40ff8f5e5f5f9a1ec9b190ab89e571340500cd44c73c7426d79567280de2c3b27483cf6ee60af752f83c488c2fc726016c8c1b8bed3ed027e5ee80f8162d36efed6154116d14fa584a727694ca0e1ac38d257dd64ee58c4b94b5526bd913bb9393b3d4aa80ddbb7d84b43255d52c30a8c173a408b05bb6fce972b63617b714e36cd2606f05e739bb49334fa3c4b4116b7664762dbebc34862fdb02483ec84f74e841169cb9f61baefaa10cb6ddcc92dd5cfecae877b25b65a53fcfc3a220ab69df0b1edbd219e15ceb0696a9d3310d17afe9d0da6c86020782c1fc1cb4a138b677ba3bde1993888e4afcde66d50ab8f987126a258d8d3f92b695984aaea7e894cede163c573fc6578d652c87877921f1679ff01c496a20afd350f1f54eed33f537d14457f0ced4ab1fa2a109f96aea2af6d51de819a65655ecb321cb94cd9166f4af991656db923a8745469aad063d118114ddeee5deb54e4ea6990127b7b251c1319c5bc127f7a3796f213d05449ba8c4b816b130b3b5d7d11f1c2c5e32468d3e5821cd8525794730fd2bf5c30055ce574db9a5b76296a601032 514fea4c995761dca81422fa13944623384f8f6d7b6b1d36a133e23f3359fc11b6f58ebc16ea2cabf67d4152ee7618ff519ed3169a 58 2ba25a645f49e95709e1061220d82623427e4af51210571ed587a40f7f28f4f423a6d835a394e20e29ee4b7c37090768e02eff6915bc9b5ebb18 +26bd569b73f76be5a98406af16d2a4329f61028331bc43b5a8a53dd76611e0a40938209fc7f50a5aa9ce177e8c4dfea55252ece24867bb2efc667e8df85f7876be0bdc0943b6b9d3e21f661299ddcbc48c023b3af359d8b816e7a42048b80a01939d6eaff11251024e5dc7ed021c86e5729d82592fb36f7a6362539129da889ad40740a8977d3e4539781263bd4ee9035eaad9bb129c9e312d61592ab873b0b595c0e3d6292186cee79157258020738bfdaa2809662a4ed5e77cd740efa682d680bf1ff8004cfda320753095f00a0c03549069896e32d8b9aad6a3120d11b09d65d8aab8ec00e935fdf0cf281d9e09c4b45396ca91715234ceef52cd3ac4395b798de414a058b63aae67f85a057286adf4ee68a284486efa1038440526685ae8aa4328c62ef8cc42bf8da586eff040a5ad5da7c0095b59c51b4d0f056bfc8c19389e2b6af2f787ab66b610023b59a62e27f9ef5c205f267e91a4b3df4dfc27dd814f140cd859331fff9e666416db5bb3642dba8291b9b85588c186c40667ec4d480dbe4f39caa5835bb5a0d4bd567ba0d2bc76da635152a2cbe170c362afb7c524811d6329fe80515b3037f2a0ce08d9e7ad6d4352f6717cffe74ad90e637bf3e43685a7d2ceee328cf6a376683bc0d25c156714aede5571ce35a1f1bf66165d0773526704c41c5db190e900e3be405f1f733fb4503d40880fb8f486730c0ea99fa12b812b6a5e77f7590c1970c5 410899917816bdcf669bb7dc179d71caf2d48a3eb52e873bb7ad5a3ca0aeabed4e217928cb32324e 44 d47bbd668a015f96921f0d1d447942952a3ca8b7140558e7f2559769600babf05d085112fc11a4673e65114b +d0545748c870e728fccc1afad7d79be56c3cf2b0e146a4f4306de57069497b15e786b52b717279705956dac298bf5b414bd868a7220fcf83730ecd6c0c73a6a34f6f6eacb19318d710a366de85f66549e81df6194d76dfd732a510af981c02fe74b48a9d4f3cba8a9223f32e5ec43eec0f965152d1d296d9fcf21157ebb9403be0f59f16f6525d0787cf2c1fd9009e3d1b4c520204af289cb109ac453836324e598e05cf7c21e1d30bd1267f5804714537b26306a650ee922ae646dbca70805dae6a5f3b874ad12d131f680a4d13eef4b194dc3ae3cd71068020a49865d2a8b71675b50db980a32871f2a3a4eb9a85fc1506adfe4d64e404ec4601bff303c05f7655f418fed598a1b3afb89140320d44ab73ef074481f1f1b43701972c5d7f7757634f5350b65be1ff7eaba99f2d808b54f407868fe508e7edf39dd2daaeb1cc71a77f79cb693775d103280d22c2ce334663060ed2e3b611f5e74c1c6bb39ea101ffb94507a19e2df3ef848d8c40bd8cc8d788279cab381ae5192bfe1b2041eea9c646611abd1442fb55ac1cca29ed083fc2a4aded94fbaaaa3f1e45c7bf3dbc460dd23b661ca26de35275766e1069b3171f605055b1dd11f2e4b86816fe42ee8f0747a8321057763997c1a82e3541ab383eacda39d4b80b7aa68445c15b9f730aec2ca18f520605e20ba07ee8050d31c56c20c9ec980f7eb56890f97d68b21f7799a4d546914c92c182264f50f3f935184010349c63a0e328e509e66f15fe54bfdfc1da60ed2441e768cc46b83d9610fd0cd747d33eca03d2f10b479082090cd8ae39de412821a3ab3e0138cf609078bc1d7475f965cd5532256aaf3a0fead1a6607af7c6b444c43a7b1506e90047e925b7e07d23abf6820d30d8fe7e9057fc623098ee0049267e437a1a220b56a8afa64b4007865c1223e63e9bebb69020fbf817bd87395122adeec3f2218f9a4fde3b84a665735e2df3b461619b9931d6b10b823cb9acb38b556cb12147d3ca09eb1c50be1e954c3f4778f1a0e3b1318c2b6e96c6f331f27ef8a1781144e94205ee4385e412ffc4c0f7a6322233a2113c188fff270d8aeb7098eb2372d22ea6c400a16a61311a63affd36eebbac2c30812dd6919d8591d13f8207f7b89da55bc27c48a4a1ab14002dda384ed55c96bc23a9875e76b8008311063e459ec564e03ae9a52725c4632929a8a72697ae7a9a710f1c5f41745d85843329c48dc66e467af8bb9ada421c16f5278960b49c847a7b76f36c786df3f1a9b8395d7d75f037c479c299ba76b98e54b52c18c8fca3a4d3bdd3f63b81455045ce05ea53b56f31913f4bf20a24590200f50158a0de264b50085af4482887b8de4d3d4e9ef753b03a4b f318fa72be78626d8577c5d7c8f1d5da161dd8a2b6915209598d8e94 36 468c88c13d84efc5aa7143e39e84f4e400a526aa9acc5daa0dbc43bd7d5784ac4ee2d71f +e42ac8428d1ddf026c4eee4aa55463b78f1e28a795a3fb3f8c99029d5448cdc0ea8ae8a0112d2ddb8887b6200826d0b7e9d9c73bb581fefbf85f344bc830462507c9bee7e255024c6a4f88a518b310ab7c287a992ff9353085ae6ed95bf35bf777941975529155f31f4a13a518d41db0a8c58aff55ec21d6856da122f4e942be4f4a27edb68af324eece5c522bd732eedb12f7a35fc8de91660c7c2d1ee7a79faaf93e19cd9510a396cfd453b5a66672446464a73eb01bc964695cb30807eb108c8cbd3bb61f32f4198dabb928428632ff024dfa98cc19607d78e0fb02cb81305e07ac33de83e2e125214a535663494768230bd1307ea89b092cb137f4374054a280619e3efb21d45b6051ef49e13e26714fcd0711d33aa3e3eb21215eab80335473d6c0533cad7d9f3aedd1b4b83977afdb6743232e7cb5c754530eee299cdda0d487db9dbb5ab6cc0a9281545a63d85a9aeabd4a39c2e83fdd6e6a089b17402c9fe930d40c704a2e8866bc199deca80ed5e443b334d752c77cadd6bb3112eeca33b5e34c7f68081583b67817b1770a41ec17ea9f1ad44548de86cd7527aa1c7b19c8fc2d71d6ad137d2d34b72c1a97413891606ec44b9197485b25e43a0b8c526d0af66f428ec0d369e5390c03492cebf83265e3665d4b66d48b4fca8fc432d383d586c21ff36a0365adeac2048d7fdc9abfa505b293fd466ddbf8da09cae91d269f47fe368bdf20c35812f19b26c9d45923189350647bda5c083000dce3b3a817 2a36f186fe7ff39234bf32bce635f3de1c0eb25489f91e7828b534b6fa2987330c8ec3301465dcb723718b1afc8fdca205eb 39 392e0a2ea1effac6e4556584d468cef564decb0d12ee3a364cab9da6680ca517a3d72902692fca +1b881c4c2dddcf42c41313fc127eb17b86789cc912357d91c90cf72ed9d1336580909d6bd28c5a31ff1ac81a14ab4a647ae924bbab045ca25315cc86a2903d3828b738f9d7fcdc0a93fc8102ad36dcfe82fe468aa8f543cddff9a3b2c27c4327a63f153d5657e9c650b0410a1927467756e4481d343bc2daa80e43 26761e1e7ddc8bce508fbea2a5a0f3e197be079e27f41e67b6398e13e02fbae90b1c2b8edc3c979a5bf6d3 44 d6ec79bf7f2226c2e5da868e69f3b64018a41d47eb681307da3f0bb6b632fb202ae834981465601518decf24 +287363e561f701662456e97d0e38b853dee982f29af86c5c35854d632c2ad703a1666b410aa6634f7115b9aa8bb0b136dc362ae71e0c94cc5b2dca48aedca4464ed2dcbca48477fc5e13f8ab651f938946a209adc9d0bf71f81db30a525c8e3133b68338f18b7d9d8f81eb6c52643a55c8ea883f15ffea62cd3d17528f6d06fcd5e79e4722c95c2e9c2dcf04269970b9c3c32b084804f7dfcf305fc4be50ff68c2ac429cc2077da479ce686f33ff693b8c031917716ffbdf752d72f2e5288c7bbc35b22ef54cdef10c89eedac1f3c700a50358fe56c98a1e16508ea90b557a045eb30ad9e59703c3d182a1c483d0149e032ca23fad2587effe26f5c23781478221cf1fbef6c6e126d9443a7ab899b86e48ed49ea8e4f7664b7dff8c9ef3506376612a80cbf85e115c07c5a6d92abaf1014f5813a1df7da636cb83a547b9eb67d7112c48436902cdccdb59672ae61 87eeb50209010d29e9e4a8c6a52c510733b63491e7ba36c4d25fc621843312ffd31c71feac383a1c4b3581 25 3a0bc45eb55e364c4214212edc26b4aca5939865a9a3c1fec1 +6f3a3c93fd120a71b592a698f4943a513b52e3086f6cdf0986b0d801f85acd57c696694425be1361b5ac138dee889180d955fd965b369c01cc53d7bebca6a963e9de60ea56f6f4b8604a46ac0e236dcaa905d046e01e59108ac4601aef6777a485800cd34989f3f097709e14ef81fce72e95377831e4cb551babeb73b707bea416db5941ca526fb7677ed52ae92f404bc005a084362aaf5a2e6465fe619e703ffa3e533f1fc45623d748e083a9e8cc541146fdc1bd4f1087169e557befe7bf210604b16394db82e330f4ec4e2b03c0671a2b8ac5ebb3179dcf8dd900a5cc983ec3b7211452002027274a0f7a109753e28fc3f0fbaec422d4b2d93dc93d91db4c410eb96bf4252910a47b3ec2632e169c1e7f9a110781c8e854352d0f88bf1bd1ba43bf77bb8b688dd33c486d256d29965f2d4e37b2f540dc5b63e2430e24c2213c961fd511a6677c915e92aa0fbbfd57ce82037d36fb3eba388ca7d67b2b5102f1eb3df2f581708b9e52acff2a13549130a176e353 8c1a3bb0390c3e39fa632e18b812f0767caafb4ccdf9fef355 64 21c21d805949d798ca3231ca8528e9c3090fe198805fa8341feba842c966c0cb786c47cc8a4e497d0742c0351249d4d21c1cec78d606f1f6fefe9f1efe67f9f2 +ea99c227d9cc8b47278d2d712adcb88043c5f5f12a36cf45d6de01a74fbfd97cc10174133e170dad22007002f2cdc997e21764c6eb2ef6028d60cf56214e41e541980fdcb61a0d8fff6e6ac0cecbe98c996454784edea045cc552ffbcd2a69a5b4265155ffe1548655ae0da10067f36483299840e6ac82a3e017fde842f55322a79dffb67a05e6e7b2c6281bdb0cf96424df9bcaa9d3f7f83fc4532bc46773d2b1ea0a824588832d8597b6f17e7263b2943bb65b62dabb6ae75dc0cce4237e6ce5cb9519b8b9489132d248e102007db3441e9061b3b19d0b3af5b823ca986c3bdedb38840620abcfb525776a9f6b39b1310fc51dfd27ede85373d3f6e353c786ab6083272e19d8ccd353f45447b158505e26f018473cc808f798ace2f38aea7a5bd8e67ffbfb22b0300917076e4ab7d574379b5e18037a1f4258550eb5d807a17a41fdf596f705f3d502c2348b630870d51bc4e7a8c080cb112f324b3a7fc43eb6854b951e444361bacded0967f483d5b07b952d1571c584a6a3db1817501216056efc45093e296a1af92c730e131c4bc01cb32fc98e0074b2be79ef4adfe99eb8f2baa274c7a6662be0a71c65030e8f77375e7094bbacd8f3c05234044061869a2d5048d0796d53c3a8e550b4c41792b63528eb7cb4d90dae604468429dcbc3d9de07d80c7a59237ec744af57904a5d8dc824fa2a0afccfdf60f4c31ddc2a77b449b0ed18b2d87625a52213a1c362574f036b8633ae86ee39cc7465bb059a40c536e825814747f712778af7d6dc1e2f429beedfb0a1c38445206bbd21186d50a0ac457164a0d8750bbdccbb74ba4902c2365b27b8dcb8191298af549410e7119cc5f93e50c5faeecffe4342e13cbf990df9f0f75d32144d4b79d2237c42b83a44d40d59cb15ab75a0cf17c73c1ebeee5ac3668f30a25e1c860913021a95c281f52bef7616a817a3e2096a705665e0449ecaf0dcb71d40dce6f925a1df3aeff6e203768ca26da575b6f6899d89186ae31f263f20f6b50f02fef83543b9aad9fca6917fd136412e325180c3561bd73bee476fe55b4a6b034581d6d67955c4719bf64466371b54bc2a88f217176c3e706a8c6a2e2024a2390f693f5e01076101324cd5b32c06121a0a96a636d59c55281b7401403e8e984e7f58bc368fa17d1b9487605fc490af75a58ce56cc6c1a30b04093d06d62924e927e59840011e040c 3fc3e409c428411bf5a270dbe776cf7339acf8dcaf0904f169bcb8d5e3923e63bf739b162c9189 35 b6c4ee4e8658e39bfa715ada2f5b0ef755e99c89e258f7f059f8bb4e504f6cf992a8eb +61b2fd377d22e9eeed9be6a51ae2aa75164ae510b8d0619325d655973f5728a5580e48a47bf4aca8be8baa38f0e2598cac45b6a98e4e6433f449e06dc2c32285746726c63bbf3b69649f2cf66c470d30e8cbb20d3ea632bdf274a407d0b045214f1632f267d6b71c7d576b1b18c4b4d98b08113674d9d5d0229ef9ebc18a25935e75967e006d129985ebdbf0b03856a5785aa045a22a5821badb02ca16fff4974e65ec04b48b759ecd5925236c28af490a309aaec351c804af2299871dd81878276083671a45f0b78abb21f2769de1e1e5487d22ab80986d360e9d5e6d6d50d5d955475e55e9c0436ef39b4bed07da3e195b0b28e9e5eddfae2eca9b21c9ba2fc9976a1fb0a3530e04d8057076ffc80953a0ebbcdbf9e6bed55f714a85e64b4c28e9fc4440a3cc5682c7a3a1ee9f0040a4cdfd87d8d7de484a8aa565f09c6eaa 8a22e6105f6590b3739a611145d35e005f4d492fdaca6f8bde0291957d93264057e6acc80551d560123e66 31 44f8374f86ca3fbe551de74613d778c5040ad83015b200d6c1cdbddd646446 +79e5367ae68811950806bb03affbebb8e433afca58b3dadcf5ca63cee7e49343d3489c51cf0689f20a773426fcc9eae60f752ef3cffab181d29df963791675e290af3a4a8da181a61475ab3f7078bfd420454e2e24e56947867db9e430f90553548332795153a570a8 9c140e4c14b7fa7392ab83cb25b1868c9a50630f1748cead9ce75663 52 6a6296b2294556aef163e39c98200366e3739858c107cd9d1f12dc941c41766fd738b5e715bf2ada84f33ab429be4ad8a52d1776 +0be66102f687117909227011cf688dcfc1479703e9de7a8a5accd94a77fb08362a0e0cb9867b5e012c1db4f825195f9d2a080a6aae208b3c8440e1b5c816ab58fc5b81e35939db78dc11808c7b4fa9ab772630d6b6fe6922717e4c885fc57540139f9288ad3cd60980c3fe16d1535d81d79e46e16cc1674b9cf195c5a3b41ddd85ba7d1af8e6f35b3f79eea148a5f0b8228b7e9b6de63b8ce7734559089bb76dbe4fab1654a8 75f1f91695e51772bd3cadaf3dd3c2172605ea11bab632e2d83b5691ce77909aebc3b43a44c8659350ae66a3cd2646 51 d5e179c03ef75449698e00ece56672c5d44cffde87f85edaa68293d7e77c50a347d301ac4186b5d6dd4ebb9802e8114b215dc0 +1e2ca725d0174f03608d880fa3e5071a83 dbcd6ce9067a5b29d9d0af09382c8839bfc8aac7a43449de6171e8da6ddcc6a542 44 17fccbcb3b8c67d2449036600a4441c16d71f48c621bff0908a77e22804216f6459222a4058e81b9793bd7a2 +bfee74b51c521bc67bc5e3206e24ae0ffe687faf2935aea6efa68a045b92ab6e0c028eeea1647b1bbff35a1710e3530e1fcbcc759f877d3f1f46c907cea5ca1de5b5347bed174369591c46d5dff0f8f25f2c595146549428c0e2ec822f0c4d30ae6d7b1720c4ce9154568cf83a668cb54a2849db14d3be27 8e221f676090d840936bd62bf26875ed9e5c4847135d875e77cd 63 e46555c0ba76dd07e83ac80fa1bb1ee3519375b5b7e696c2fcc680c3634ea7b9cf1e375a81dc1b9feba35d0d74fae0c4160d9ea76f97180474bd65e1be3c8e +b9b5e6f941182efccf3fac88513ea6e5f33dc077f2f444d538875ec7fbbf6becc4be7fac2b752413a8c2552af60d6fc8ae96875bb69e2931fec4353d11ca48987fd391fa90a6415077a3280c803e52d84e0bf2dde19b7224f80b40a2b55ccdf5491a9a9b04536ef9250a81ed749339a685ff9d72e1b6a0ded49d6f864c288e44b72ed10622eb6020c2f6a01cb9429ed1867233ae13fb1ce1b437ac8f5556e996c6b0d9bb125e83924bb0e8bcd382e4c153c4b123af6aa3829a7d53aa5cf2844d1a675a4706eb9c5a2dae1e3f1f6ddfe196c8d5339b2b3dd5e240966dea3ba2e1b84cea38e598d9966dd7a0186b58fbd208e666ae5b6c6408be71b7e1b3875e48befc73d1c06004c1312d4d11590cf902a75bebefcce66969d717045f62bbf01df52241c3e9c6c2bf4184b956623c383179a907bc09cdf5c3b2e315cf6e724bad7997e3162d8badec4cbc89690a0cadf9d0ee307c7d82d74e551de03fbe37c7838d9cc26424cd61b934c60993683bcb8f0d02f151c46012496feee27063d9828429e9dec90683e7b5199cb4f3d288367a3b2aaef555338e5afcd6a9a7ccec79d1cb4dfe930dd5d734be34 a780bf01f7016a0f0e955207458ba17a9d8ed01533c2bfa2931571f28cdd969d 28 e0cba2e490e79b70ea7010a79bdc5ba0b830a728febbb7ec2c707d8c +10333b502936d19ac8d3457f3a933eb30abbe3e391e2fd3e3acf59852b6396e3bae72958ed584ad238c4cfa57910e1d8419894663364efbde537c12fe533eab11a8c2294b67a292fadabf42802ec29a9650ff42e8510d831f2ac53f305b3c4bc449e42121c67ad64c1ba0fc3fca6a32c35e5beb411bc9587cd41d09a2d61c37c37f2fe1c750d5581d75b4579602f8f32227fd10c038cc4b1e2842c4c635b4f82d1637df5b19cee772576ef3c16a0631c61a96ee0b5d19e8fc93c1b1ba9c823cd7a55500962e78a35fa1e349094f97fb9d659ff0c48205bd6a93d0f88984f19268772a89ed82a0d7efd6b14acfa5a42c60cd6a4ac8439b007c59d7583f71cfd6ca9c56c253899 9a7341440e7a8208545122b40087369dfd9ba9af09 34 dae56a6b00ea5ad5da4fd90c87aedc58702ae597ccd9bbcaecce899dfbbfea03cb7d +be97299d56d72513d2728ac78dfd176f35eea2356059eccba39a80b6b79b090b4f446233115199a4a0601b9e0375c4d6830f039ee61157e1e5cfda738d91ca4ea092e1ae6e990e1bfe159c8b082552ab0625a7dc23bf6f65fdbce41021ab920dce7b4bad0c13c00f2264b1548b66ab70ae127c7575c0a29e0ca29b231f85d1a7e42f4ce837d64e6ea9ef474eb42caaf45374f6bd9af58b083dbfc7516c845aee7de53d1470641ee3024e79e15dbb02d811c106540cb02b1f75fbcc6d23d066a7a9f42dab9aeb2b1555c7f60ecae74da71c5f6c365aa22b52a5791e12e12e638344bb81ccf6059c24d39eb69b1b14f42a26358c4ceb5183ab3d0e163fa1bae5a32ba8c832958574b03c08cc7062abba5eb2f51a8af7800f0746d69b3e26d291a888d24a4e5627679d7dc1740bba9ffbbf31e84e0bbccec53910511ec645284d3987e5597108415ee19479402b7309ec8aa7 b2f864c30a02d7a269bf2c64a2fa88286be13a1dd4d14e217e3c05bd45305c 52 c301f8e1bc57e87c1b58d11cf3b3fa738b577700fec27044be62bad06aea0ee233a4f379a32e545a5042c315d84faa9e4b08dc2c +4f9299eaf22efe1e649bb1d2a6bb798ac3b2b3563cb1a8bdd055374600a60d038f791cc80437e35a1fbde56a89561887319d3677d410c4f632e799a8d6a425e41a407d84b6071ba49078ca9ba77bafb6eb5b2a73fccb45b0b7eeacbd46cff5856888868541738ce25aec2834e453e71205e307f11e6e7ff6d0674f53adf9669c134073531007f97e15dbeffa8f4fc6e3cbeb7d6c8b028529bb64cf94c3eab78807c5b3a60e13cdd437db464b838f67e62bd422bc879ae5bb283b94d6a1ea3ecb7734505da3aa9af6e870ccd3db0293162d42aa37618766c0766c9478f8474fc2912655ac8ab2356fc85994025f05f6baa3e3f63ab842341d7c1ad88edaf34c1cc17fa4e6e8a089f8d0b295ececf4ab9c832f247794c04f1203f9b871cad76b85e1f68f22aa261038d2a3554bf6f4863074c344c7fee67bfe7141a4c400e90a18d2d54766e148aba689ac3119f4282260ed0247009a3c16907f3a9ee71b20625db94a1771ad955bb069925db696119d9a762c5c73435c33c61db89e7e10e2f83e39117ae04b522def26523c33face23cd89355ed0d5207825f1e1db2e6c8d05efa878b960bbd008a840a11471e5de411b0c7a91f56250b52f855f604832008f4e533390fb2bb586df0b6e8167d9e7d9f6d82456da4200671c71de32d64bd57360be2f562f20ad8807cd8cc8690e357c28a6240b69bf60126eebf8c009e131f0b75b45ae3630b9c4c70734223166a985f17e18c40e158e261a34c25b9d7afe403e4922973826a2b63fc1a76bf73e2f3de8d84e62366f9421feab738bbbbe9fdcc950d098d1a27d24033b00f34515aca1b0092db2ce3e0ee3b2a8486a855b9283c8350ad43dd4b248fccd1c3c607802d1d373f7c9e2112a8ba6471ca5e25c2727accae158c97c3ef9e55e1ce22e5ba04f4610a379f7de9ddf11c1775979e7c85b9d1455705fb3a3cb5b7efa05998652530a6afa3dc890e97ee9c0a9af28f473f3df74ec2de406dbc9c49fab341c84f7c2149c9735624911be7635e18adae5ce911676d26c4064ce9f5f39016c766e369b993c56aab8a4d4a6d5d5a231f79cc04db265f9124f24c7c5e8039a58ced302d0f930f519dbccb33e0113269aecd3a73f4c28ca3441b0e93e03c3c704bd9c84d90a85dabde3069199ef89431048ea3f577900137fd47936ee06ce96fdf597a362d1fb0a7c041ce00e7d43c6f26ad0e7b5e23a52082611825dbfcd88022ba197cd0318c9aacc29d339a0289e1a365a1325995d28e91d2ef35a44cba4c2c7421c2358e79021f9d8f16456c5fbd3b4056f9feef895a2b35f49836ec57b73e81209b3e4f08e5ff78b7d11e220d815ea4cd5ca8ea9918289172d7ee99892f5157ea39b6c51c456cf13d1859362ced6874d17129350e19d0cd476d27be9 927a239b3a774e855b65a1affa336bb0a7c2842d77beea1998eb8cbdd2 42 7707be326e10de6f4bee05610de24ad928b7900d2981120cd071d826e2943954b95e4b05f6218678963e +cf4c8208fc017582be93c66de5ccee26227bc5f9b76ca2aecb1ddc63d7a2c3ee23c0d050a1ad6b6ccb6dfa47a49a08306882ec2bdbf000dd357d6f8783588b87d2dbf71c20ef6bfb63982635db222ad0d5873b6bc6b694b84f8b2428ff507dfc0d47297e709c3e4042f7019cd552395cc2fc747fa770e65b36687454b23ad7e9d6645c8f35e56684e931a5f7fdc2999d05bafc98dbf6324f47f3c0042a9fae3973a5d7e2b85ba17d0d78fbff23a1acfeb6d9279fa9af451563b78ea1e962dcfc55f9cf579247ff2c37cb1185006cf022f81a64170551e7d797ffb605c1f0b664d0721d1102cc55dc1544e14921d5a4f7db62b2eead70581fcd621ea27ae74ee3ce835cb21260940aa11ccb042ffd5504b871aede04b3b5bd48a2a7fb1d53904c7938ece72ca41eae4a4b3b82b1788367c5cc42a7b72ffd5b85e81b213bae700691ff5a4052215a43e1c40ab24dcb91b5c127acb0a9d578500fdd44b66cf50f074c88fb078eaab39f03e29cffbe5a6e0e0c59e52039119c3c30b0c0c23c2bd718a8884448ddd4dcbc8fa7b01536daa2bd6d72e82520f0594b15d229bdbcfab6856ed49eb3cf9cbcf4cb85bcd7a5b791013a184b0cf4cb77 e5f4c56065d06c536577c670cfd2e6c31f26fa6d63c7689121b6b23928b101 49 33352fc192a5fba2cd5438196bec0cb8375dfa3fab868a6f14b9ea6dfe6f35bf14d8a6da489e1c4e16db8195bda0c2f6cf +75ae041c217326ac8afbe84dbeedb2ecbb580bbc4b50582a4519447fc2661996746998d68080182a000ee87e34e8aae3774cfad702be526136d596c663d6e3e6163f045d65a5835ce03843ceed8e11a61a3aa96355a707affe2d219a656de586ea3628e4d91f210cc5039487c670d3548e01f21369eedc9fb60b3e9d253afc737fc7c35639d7817be9edd67df1e0cb9222e296c069a4bac108079f012110e8abb2ff3c8c89ba4db541b534272351343191d71f4769bab5140bc4b29041f110f138bada7deb09b2ba6bc9cfa462e33cbec33ccb10d663fc4995e6666c8aa58ed03bb00a4f0a795009ee8c6b14f5897f9dc3a7bafeebe4eb55648c382b6c5fab6a37d418d1f59b4ce1cba497d66a2193acb6cbb67200eb45aa392c9d65d058d0caf555a4c34aa6192f06333717b98327245d60164e02233af886f030b0ac7a26bed2e7eb64e17e062ed49a7fef790158a26e56e547693b2297a2e4f9c18ecbeeb8bc1f51d037ad5c5e63bb28b4f85a2c9770423ea2f866835db3d3da1166e73cc760f133a2d9b0dbe61e2ac52612186b99cf55a33cf0a9da84377576a3ec51fe7bab94fa7da7a75780ec01da24179f4c57c5dcc54f07ba86770bff54cf673e7998f9a9be4deae429631d92d642614b988dad7165a4effbe8d0df9866680ec52f52ba458325920e636338f9740fc4e53b236fa7be869d3f1faf23eba16094fe8946330832597d1c490666566705b35b329daa403682f38f02e8bf13246f341a415085ad3cf4637caeacd5792db8649f0d39ec4a2049a4888de248023030dfea503c857fe23ff1867c1b356afd8dfb3d2126a1874c6826137a7ea7c78bc9e4b977001da45aad37dc85af759933352dc480df03038eb8a2b2f14d72f8a8b866d5aace69 764caef77bdd114966a4bfb67dbec6a4458d36bf510f2ed362946b7e3ca226 30 b664c9a344909c1ec8af01461837d51f682eb0e13a756aeadecff7e1b9f7 +2369872762ddb37d020cc791bfa6ecc6604f446b44227bbdf99700ec1e6f81dacf98479bc6969304f989daf8b1701602cfed924ec10ffff9041d81ea04cbe33f57fd14c7fbad290aa391b7aa9e948dc1a452bd0a001351133e722f37ed928c4b21a9d8b30a1fb52707be2988b75d2671e34876fadba4226e480325e9008ef8973689c1695d12b56927e0e205ad05b69cae395fdef7d5d1f5c81036049aa01713ff516c968851cd3f7bd39b0dfedf652ada3fa0674e883cb8d2135fb0eb93a004e95f19f49f5645e86fc9b86749a561e8c5031c4642bd705b7d80213ba977c99932fbe5fc954d9cb87942fd9703c296a742505a5117404a968a6aa6394ed74476b23803deed00151b200f3cbceb010e6908f1a4a7d06a6bb2cfe412da9df935c6ac69d0a374196a3a90789a0a91fd66a94b986e995ecac27f7a2705011180e171f38b7963d633bd00293ffe10a6b23e74aecf37687e58a135635532103a889c576b963d8b931d36bcea9e60c921b39905f2c917a863ac238b2c35fda727e9c73cfd208ce59c20def5aab809a89fc745c949f497bcbacc1258a6557df469900318a9220901026d6e9f514da8e7b1ff5cfe729e4d3d733948565a57910803b3966323ae8eab38a01dbfde430862aa58314a27a3e84b637be2ff3209c6be32ab650d460b0e6ac34051f0b8a5b04d412fbe851b1827fb7959c57c7b28f4ee699d467a178b53aaafef59f4fc489dce328dd90b727636d57066f0ab7c6afdbbfc6e84a41b5df8edfc84f3d868ca2ce61da9b9d8347bc38970e68644 fd1770752781b76259bf89e10d3d19d3a13d1441e5a780b67a4f 45 62a8e17b29c6ab5631d708b9a7404f76b004c492cf18b8092f97ff730839de6f6887fcb13ec1597097cde4af6f +40eb1dc2d3188af40201a57f05b545a0ba76ab5c3a49c5f7479e8541d6d3d5c0d5955b8166b8fc4b6af3a8086a21057752c36fd2aac9a9aa67312f6b9bd13c6831038007b79b7fb7aece118e54ae3e4771c9994006b705d45158a9c47ce40f9fea6f1b45ae17e9660128fc3964c7194b11d2ba04d447df0de28d0058d1a40754468c6d127d9a1d9fc5480d5505290eaf75b7105a6ca310a06cbcc5d3b53298deeda194603fe77116fd72b7730911ac3ffb33c018a68d3034b3d52d95b1e418453737f0ef1e59357105f0b8228ba2280715255816dd51 5ef80f90e8b75fbe47d3ae9b2a3b600f0ca14af776f2ad913618949c 57 5a433a32ae7c98ec7e2290c024194344c4393550c349761665cafacb74abac966257cba593d6dbcfd534db2c4f36d23624dda47c59dbbfe917 +930027362c2bfc419df0375fbea19e0ff85886591d5aad2158995107acdd4c487f10cea856f0b6e57d9b1cbcfa277b33e2239e716e40e35bbeaf8e6c6ca1024fe2ead55fb00ff001cdd0d0efa94739ce06fa311ce45ae0682625d90e8adf45278dddebc26cb9a248d80824aa84805572ca85f0cf9283c1d222cee217a7cda0a48fab23c6b64a6c26c1b21ff237d63ce4c65703cd3a546f71942a632c953736e5f12c3aba6bbae19b3ce2a26c5bb1201831b61583ae1eb27f99f6c17590992149b0a124533cfd25f2c52e0a16aced8cdb5655fd9696023dd6d0e3f691eea54d3a4b73c8fbe0a816f0784e822712281d248e01c487e15e0d466edda2c1b8a7bf97652f94b661d6851eabbb776e3104583a1c7d68a2d34d6e03c41e4e9f31a9c3a324bbd438a032071c3e5452c141277a938b7c148b2f6fcdbd64a1fca7d3771bb8b8ffe6aa401a507027a5788b3ab8a5df5642378108b89d3f027288086d204b39b9d1b62e40fd88f9fb8b7482b3e9d7ecacf052c646daeb3c2dcc4d5c45bb204de074de7cf140e19c2a983107f29997bf85ecbf5df50b9bb92d93772024d6088964a69ae22f3d01a579d03222615234aad54aea5312992db5a8600db4879534b6f23d79c4528aa67ab2eea202 ab895c83b99e92cc110ba3b14f6961e077a13cb5a6bb2fe87f6466081049db19da2d8a7361b83bbcc894fd0397a63ffbd9a1b5 58 8b62c0d4fda3854a519b630f36a8d6cda7c5f24809afbf231dfb27bc1d33c077415353ed5ccdc0cc06d7c684581d1b662a04847dcb5d0094c2d6 +3a619ea1346e63583fbf35cd9497536dd1f99085ccdf4e175268a2e72a41709d9abf39f8ef9cac1adac26f2121c2320c3711d55ac674c658a52416658de6732ab3d5b8f8be87748164806475b877b71be99f6369c8a2ef585938112d4cbd47ee175dafb5d43e79051b9e03118400f58c36dac521832d2c336aefd603f7198d1d5521e10ff0405a72cd5a64a5e81bbde3a4fd94b1238223ee0adc5ca94071e1107bb92334ed553513cee899c7f06c7592f9af116c09e7a9dbaa8cb08307a03bccff490458b8c86fcdf4bcfe2af136241bae89c45773e9854c9d068d 1be9e1cfb84ebc73d32f885f5aa18699e0562a2fcf6b23d7bb8525fcb11adfb2a4743ecdce 37 808267748f5582229d6553940480d24594a4d6634c28e2093b022127dbfc54a2c43dd5c413 +9b4a4a0180a20d28afa1b8c724b7f695fc0fa56bfb1a08d974aa36723da71b387b8baa 2f3111942e1165ffdf3eb2511f25f58809ee75d48653a6552a75249355eab191230fe4d0e55bf96266fac5e3b9 25 81eada8ad99c06c0887776e1cf73d8214487c253ed6deed49d +2ecd77d592ad306c7d233b1a148a9796ddf69460e4fbc6aea85c2f1f7dfaff694c040568ebf514439c5564ab16ecba37a202d7b5c0b08ce1a604671a9ec7d23c9f3bd8417c0261a7eb543ed855e15bd9bb5f400d12b4fa3ecd8a20a259a6ff3fe5aa0c816141cf2fc055adf5d539bc52aba56bdb0b930b6128b255174dc8f849e242051c004ee5c0688f006f82fd67fb06712f4b463c1bfcdeeea0bacf14675b62646f332fd188bb6d4c05cfc1c2582a77eb6633b2c96ccaf0fc6560cce0c5097e76a5c8fe4aee303d92719b6801cf8836de8a266482506d49d7868720e58adbe1691272ab 774af859d8e235164021cb40d5e1adea69eac76f29f4f25acf9c4e9efeca6f5ac0ffdb9c403dbd4851744145194495ef01b5 25 aef33fd10b5c5ed67bb298ecf509945f19776f9896998c6662 +0ae2f094d53f6d575a38ffc61ebd12b22c6d42008b88775e497aa3f805692ae4aeb127b4d8c2c3952c2f4338e3b866f696198e76b911c5a0ba7b91a96ff7fd0b399277f14d164fc9948d6fc0696bf97f109a1db5a266a8d63c3a48bac560065d37abdfb8b38dd2d3cbe8526c40f59fd6ce33636cc8a4d8da56dd80a551230403034400edd059823556cf77058d541752b7b70186ea787dcbe48b815fd397df820882c3fa9bf9a08889fea705daddfb2e28305d8a57d24856376cd91d65d1d8993f0fcf4d257fecf333ac0978c9ba9d78ebaf5539227cfce922d1ad71bc1ed8aa298082c319ea76a9dec7579a23881bc737d852ae5175997501ef10bedcc6e3932ac8e3947ec8a54e2e4f317ee264cc0040d493a80d7a19fe42657c5de446a119d8fb238c353653a128b104deae96899c15608e18d8a2c4c26885c2008bc00fcc269fb967304439f2be1ce9a8c7e2ce0b8dca179adcf1fb0a2305729fa1b2fc410e62080f9bd549c51fc90300d3b3b37a515fec829f10a920351a9fd9bb50e686d4b15b9f1e32eb4c49c49b1bdd1a15127e2cd44930fe23bd86aac35cac96aa7498c3f2247cb32e6a6985fe5a1dc6418661370c5618580b52b6587c1e3fc61ca5898fa955960829eac30e6d617cb97f8986e5c4d617d1001c457ab29b364cfc62f2533b0c4fbc6cc3aff892463ea263287f34fba6e962a89133f42436775c5d896edba425105e835094fcdced36d645dc4df5c04c7ac92aff5027d7f5e6643b3697504ebfb94784dbeeb3d40e8f03e6dcfa2097732b9384ed80320e742e87f577b45c449bfeb744dc26d31600726b3afd9acec33132545c3c538d42f1c5676a77a552fc6b4cd54ce4eac0416b974a147630e51586f27848455cdc5e863017aa1200e2ad8efe57a0dc02d26c28bc8061d2d29747520489824aff547c9935e76df237099c6e7b237886caefac2656c405b93626d0569b604d8ed9daa5851980b67d0137ca967c6c77c1f4d2a63f252f80ec1a94222aa1b69a060489016102 8dace9349129b62c3efbdc857994c68de985d2195d8ea4899e9ed39ecb869052aa6f4a267ecacfcf4dcf4ffe 58 0ee6c8f88c142b53e2040e4d2986b4bc26bb04bd67cffb1623de67c5e2d659b81d8c5beb86dbfcb6371e1fc944252f03392fd486abcee7956705 +f3af581abb0b77ef8fb66699837689687f6aca671bb46def74cd181eca17733a3b856a58a821e32843df222c06cb796f488fd1675fdc06751b72548cd339cb9995598574861f267fa8cbeed48fcd8d4a0f90d06fcea3d75652f5665082e4a4159789ea543a5d39642ee48788a02a9aae6a819c70472734d50b9c9de47e4a05bebef682a3291a3f36961eb00cf4f9740e9e38ce51ce0f624caae56c57518cd480df3067574c2e5cd42b90d821812ed7ef39157069d60eeb328749c44fcc450b22804ba38025434e4040b67a36805bdcfe7007327c0052449630b2786538bff1ee916b89e4d27c59390e6b26ebd5a04ae6704e2b15fb3b347ad5c20c306257affd2fe046e1b84595485742ac7f661a47831a40fca46f335eb57b4dcf311661a4670972abd6d766e391a38976d8c77ea09d6bf50eb295654fbce33b8e73596ce007951dec4887ad75b0eb098a84a8e5c39050980af4e108e93ba37437c7441bbe6d7c89d4f8fff5c8660f6113df3608160b5737665474deab4d2790d6e5cd2f00dc5d6f0ace91c2f4138acb6528947680b973fc32f2f079872149d94532ffeca4bab52f1d468f3ea1f29ad4939fb3b142da3efea5468b91a1947894a016c5d4 3b49cef87a92b56539aac2719ab6638b99 62 5f93a54258ff33fdf9fa195d89205d2c71be67617f03654853c4571346652cb324dcec7f978beda14ec1cdf276401b2bcefca2f96a161bf5f663087f9bf0 +eb53a334505ac516a2b82bedbf85bed16b76b76cb9fb02d904de9780265e829fcf5f8d69e6cb85883b5b8332f8cd293562f9c9853876994d2162ec1df6378511e8de31e29f0000851ce1d32c026b1fca8dce4b7c0fe82f11e5212a609a536e32914ae89c9203808dd819a2ee54d5dd2e5f23a513e9a1a2174c945345c88ee08de729c5865d7f07b93749bf417585710876b79f94be730a420c71f4b4bb5df1e54d290dd748387650fb2e2b8dc2719d52cba970c2d821df35511f7c1a973999bf2f5a420b3a8b33062923603ea8bffc08ea61e08bc5070af01f26bdac98bf8e3d918cf0ad74c2c80e1caee0a109e3d090e4b3815dc3a8944427823fe242d28becda5d3900a0536c3505a62aa3aa51d8697e6f4ee2eff2160c1855ba144a80785ec863ca16eb3c51f1b256e06e4b bb6355ca82f715da26001cba0a5fc574e32bcd6a6644e06cf1c42e0b2d427b4016d046e8cde903b1a96042bc2a71e6 33 a8aae594ea251c8ebbbe0e4b2067f9be00fa233a0074f9412dc0ac909a4a85eff1 +fcd1a691e4ec9089874b1447db105b5eac1232271d5955e877c689e4273c6c77062f95ecadef77f4771d7b948169bfc9a83ad5ea4c90234e38d5cf2e0f2d58b76cb8051b0b991bfd0772ea11aa5e6a31e0ccdd71142a589acd4473f47c26c011cab94eeff3ef4fe91ace330eab32b7e2ca45aa24f910dfff0f980cf9ec26d6640588dc885b08a52e45936223f17a6787171fbb3091b804480114cbac23e8d31449b07683b6deb1b4a769fa50c013e5f2eef8fe7b68132ae96f47be3a82bb3d995807f7a9677be536ba91b3342de553ce08d8955d9e30c740f51c4ad6a5db4ff645951fac514e552d07edb823616362c1a5235f570cdb7763f67548e2e2482f4f25023f8bb59f62cec0272adcd56b87e4d86aee14f054eb102101c721ff275ada9062151d3eb5074144ad13a07b58d8d91b00f7024a654d1c0523b572714d40b3913ce028fcc5afe095e567586b6c497ffffbb7f225cf0c6750601642d6e63c9b78a60d6566ed7d946a4a8afd3074bd49f0236462e3651cda1b9c4b76e01d0b06ecf82ecb6e1c603bf4ae14c8663aa999b1a5ee6421eb2355e2264311b2118fbcadbf365c0dc6fe2b9d4c1a2f081b93f55b6527 9a2f054c962de578ce7441995b326f32803d098ba4e7cc5d47f2623bda62c0b32fb8eb8557c15fd90207539e020187897cc9cae9b361ce677feb79b1 60 5b35fcbea381b21a75043cf49cb165965836676562eb40b18209841585b06e08214e630d01c410a98845801a8c5c1116c26b8aed86ec5ac522b1d2f7 +8128fa46e6b2176e1a4ea7d7ce2640064510eaf453eb329efb1d4bf16e4dbe91dc491d279e00d17fb7fee1a1ce48353b05baf01e24fd271b8d94d67af24d2eef174d14ac01e7a2d1e6eec6644a525661b6106a6a5c703a36f70b25b699c8767d9c758d15dafd15a5b1db03ac33567cd170525d4500d9a14467b76b091ef13a704f82847d59bb3673a4a2aa3b1dacdb40b8b6ffaebe03990a292868b4d70fb187f724c999d05a0b27ad6c44a788efe4a8cd655b9b7c1b26ec9437ae0458c0797c74c003c628980d66233c2b7aa856d8c341897b3df1bd011f630d1a356cab14afa1558846294cff16c6c4bb5343e758454fe9fb5adc877a0c49e2be8c9fe8bc1f41cf8d5ae8d9666e4fc4919e9e3caef7000eba7f57e63293b9aae27bfc7a7986225790f671849417abc0331ad84478ae81e6f7d4f8308e50a3d22b512456a93b1d7e23d7e7ce1fd1f9e01938360b1d99c6b7017c7bf06c2d23a3fbaabba1ce9e44fd77ec1dd83d5ec0ad c1de2e8bdcaeb6c338ea1a6b077ac49740dcc173c942f60f779169e9b581277394fad2ff9bfe74b8af3ec7 63 ab553baa52151532e10b67e356b1df0ae49aafc0979983cf222f7ec63e5589c7eaf6a1371ae33994cb656b6fe2493631d48034695d63e3eb832f96a87215b1 +6dbd631d4483a152a411f5167324fbf9 5071b50d9980ad86a1f5fbe75d7940136d8df94b5e474c29f1bac0d5d588c939de4a7217af9c231470f76875734d 31 cf84b5128df94a065bcb0b5b69a4a59d445863a5ea46c8b293f6212e717d5c +1646c6c8dc16cfbfb9d3cf0cfff15977676c606e680c240941f5079fb2988b8e1398574f36aaedee89ae34d0a1d6a19a4dff066c8684713de1846bfb771756f326e88167926a4cd156fa9201642e993a3070238f185b981614aabcd5630afdf038f2b378b08c789184dc721a162ddb25c5aaa85128a7e286e12a3db34c2dc66be09023739b83f24e483bdc9d218a128d1834e796f5829b3ffe9528f426cf56d517449147b53d639403900b3578b36f60b05ee7256ab55e112e8e7b00a286f02709b25a565a526a1ed5d7c9ff8f5e4b39754ff313a4c6bfb16808f52de989651f39322e1f4829782ff8044e5a038dc9c3a30a118021b21e449cc3272c3bd1005b75baa7504d235bd5d1e146c0605908e9be872cdd283fe772b7c89b0b5f1760a4336a62cc8eea621776a4682a3b9b157304f3b5aa965c6c6e09f346aea244fe158fe99d50d764868b4ac05ddbbfb1e084312a276ecfdf9f1d33ddde8fbefbeb47e51712190c5b03078c8577d3ba75f49fe6562fee662e0247a936454465e52db736e25b0960e642ed54a3645496e55b5bab558db55c7c7eb6065052d2fa00261404d419b8e01c22fef8a2754bc63888e8d2f1a3ec462ec41a8277b5312c7e7928b1ff5cbe5b14bd3015b3e4451a ab65e27ac595a4ecbad67535538b26c1cc53779a868ff67d1a0c27d34578664ba32301cc38e7c3931554fedd2087a4 37 484047e2f45a0c6fc222c40a7e677a0f12d4d05066839e5e77f0f44142be4e228b39e2121b +7b04dcaa6a82e7c8628176122d8236e42e78afb4c7a1297b5d007de82d9888fbcf0c59cb2e1a7edcc42950dd5e946e803832f31ce1426a02298465c33ffa196a32bb7ebc6801200775f4e6177cca415349a1791f1d3a43bec10950a2d30cb330b065584fed4868079a798f12512386e072fda5cf8b962243895b7d97e6ff8586f2997241b7a00cb898a15d3021c94e3fb7f5fa3fe4a455c460b85f66073a40dd4191263ca8d953728f70d541dc583811283ebd2f3fe7329d8d139545842ca9ee6c58f80ede19c95c11c3f46a0b6740daf7c50220437a966903a23c7c153c6eb9f2428d6faa5c9e4562d63d458f1cda8d9d95c61d19b9a2fd2432845da951915c9e334a765dd1deaa33d15999e03daedba14eb31c30d8fb2107beaaca128a6aa0999a7c61c5dde972ad9994e413c5af9e0ce0866a9e5a451987055929dc522a0d28a4267421ecc5696560212f2e5ae2b4b6b2cac0b66716eb11a08490d1db916d1839343202622e5d0a3f5edaa2e1e96f474fef98faef01f50351a4c36d7ba08ec21ce574a9a7 96baf7f58d6283f1f04c71864d18f65741a3a732540e710eadc00b38668d7638b27a7c239fb335358241797207e7e7251a6d342d9bcf90b551 52 dd11f313c631411f4998a5f6df162fc60068b80d092c630eb4e71fb45f280270adff232ea468dafb4337bee595c51de4e7052a3b +af94a675f1018816aa4cce72bbf08d3d8749b1171c9995db252889bf887611a78e04a0310a2484b5d376ff5f7e5892c0dc708ffcb50c8c98ace2c68a48f428342332bab8ba0124326f2724628c513be7b3fc7f4ffd6c084da793f4ce727443cd0a748badd9e3c5be66b6f37395fd18b8158e54a747f680181e17c57026c8fd366f0e62c20bd39d93e9e8c294022de20dd8d39549d4429771a2d83509970f534495bea108bfb206c8b795232d3d2bf2879b3b702cf69a123d37cb0a3eaff8199e544ed17980d8ddd533e84389643a4a587c09340e94fc572e1d3333a89297f40f2ce1d698fceac9050f4ce2a390cef3bea5b2171572335a72ce67e7d72c1e452c15860da9ae798441af3c3c596de557a6b814cc874f4d16aae35a6dece67fc1acdf9b4b06d7961cb651e523d85cf263c995c717e89e2e40bac0a139e2590419b76b76e7199a32601ea063e3c607996579f289c94ee7f35ecc7f7050bd540e6ed0baae485eb8c26f832bf6945ae086eff7991b02e07ce1f2b59142aa735446af390891263144f085d50443ab50e489ca9cd87ce72628c59a413f8f57544e213307da611bf0e64b0aece6098d0ce39a4b64dc02fd7bb8994d671ece6eae73034edda5f6daf31f822156141c0ee98017455f2419894af690856caa63455a84dcfbf53cba4a854edee6c69e1d7f064c443e7cf3bc0fa09a44499b96500b0d42428b2689067f192e6988d55d1da177f77f536722d1363de07ea74d8dda61cc52fed67b8f5924d6200ead11632a62c67e0278007f576859d56902f1a20c29cc6110f98ee4d569f2c75ef3b6eff26500cf8b495933da3433e0f1b5a75335386da6c32c9f4df6c60e86035246f5724181db6b7e7c4da1018c1f0850cd58d2438526bacb16c8e720f56de29768c88ebcceb4c7e474d838d9904ee7de1d30a1e5a26cdc26208efe907ebc48bb265086735c2f722e6ca7acc6c202ca87c32df26cc7e03fa56b8bd053b7eaea1ad1a98b88c4d6ee561d19f41f23dfe1d6c794bba9757354dfe422ddd17103db065f20d29291c7773f0b75ae6915149c0c0b612315e847117462c2e60b434c0c17100469ddc82a524c1643a668c20401a573c3b3477c7662ba5ce23aaf01e39dd757b2b072e02f6eda526b8f403c6b7e4ba4ae2abf0f63f94256f06e8ca5af99d579359f56a16e283f1f9c932e3a7151eaba92fd80e6eed4f5fabe58dd2b82eb3285b3513844a40bdcfd624ecacb80df3ba7770c04af392ebce41dd1e1eaa8653194f5b5e080bb4a64b5a5144f430d9e6227e9c37d 6898606b9b85afd562fb5b9be9c4542c1dbd2bd5c866d95d3f2bf34cd4a15a4e97bf36ad3ad816b567b84321b385e5ba6d 20 18438e1552e103d75365640c877cc25b592ef134 +fe2825ba10011119a3d754238303f03b2b6a92e0cad836184387dcda09129c60e4c446e655781561d6488a38ebd2ce14bda7aa5126c2afbfef61c229ef757f5f9343dbaa792b199d1be9b820566662a2af06d9dde931f3f6abd291c2da72a42b3159171ab60cb6ad5d4ec8c052270b08b87c4604a4b3e748510b8789a53b5c25a9c85603088873c03e06a9f22ab4f5111d902caf07f96bdbae9c4b1a0889a49bef2495ebe36959db571c62cbd1e3ffe393ac702663dc670a1f5f140ffe6c7e719319cb66e1a448 ed58165ee10126352046ff1f77a3a0f1c361020009a52392a9f20bd8ef703d98df00271d360992e534cba5328e93e7d1f2d191de5f88099636a8201531 52 15cddd56ab352ff6e1fa1d33ac14369b1369ec682d51bf9b031a310f09950333ec7f171c904de6e664abae366c190ab58faa2da5 +deadb387e65d82ab39e04792841a193802a671f63b7163d6081c5eefe18c427b22e0c714388601eb594f70b409240626ba1071c450a531cae2993e34690689e1d497b8ee848f9b09008761870a3c6354450e785b1af1ae391a0ec7c5ad40db1fc4f74dc0dbc6c47e030f6b2669a94e7b5373b866fbc4ed427e20c5b5b0384403c9afb35e939dc6b63dfe64b23e124ab4e91bf052ab900bc9da18d7fc75f842a59b815a6b14e6f9901a8732fa8aaa14eaf3539be5a1496b5c5cb90c9ea877c702e5cc5951ab0de4bc1ac4375e344f7931a2299991883a0cd2d932692ce8f5eb6eadc70ee98e4be4e8f1208ccce4175a2940e6d83154ff42b8949452f823d305881ef209d1247d8f76bff29a29b6c8611ccadeb40d519e92babff6f56b6c58a4a74724a52506e1f71cd4d1dd6b5fd4b32685d4bae308f468c9e963a01f3997839353f617c3b0eb80f903d0fb70493788b363159190c7abb30eb16a6edd392288184fae58223db96efa9d17524abcba25f05b91ac7562dfe529772dd418c98750c7d7aa3c031c8bfc37ccdf4b697783bf8b00aa10934ad133e6611615eb94641295277200dc7e55b235133425eea20fbf7db3ef4a70a0d634bb18198b3452bdc9ff653cf0f29d63a1d7853b02fd54e436b84c83a2481c4080a27b883b0334e81237a3c9a37da37766d8f1171624e59c3d39303ce29dce6ad350a8d91c026a63281104793fa52e0bc12359bd347d748a279dff27c23451021fc023814c79f4728da7517f524b0b431ec44e881c8676ca05b30f0bc166f7edef028b14adda089c9fb4dadd5615a28e3b3e48fa1a89e60cd622b60442c52d0c3643497234493c9fef71e4b7f5846690c15081c63510897d56f5641ed17905a72e7c816ea6bb7f76bf4650b7cb7e741c7b62099b 2e6edda4ecd1819db9a02d2b8fd09b2e9f0fc30660efc0f10c7e8824b15d2a2dd9 43 e0d4208ab4457cf4de31e51c4f42a5e96cf27f3c861a762a7687508c841b46264d3487d378a0eae6abb6a7 +0f2c0965696b8c83bd972fecfba084b21321639cab9cd09d5ad754a1359405fbf201496e9e59828ff06bd04874b794846a86768f64898d5db4cbcebe55c4febabea08c41d07be61a29ad361ac4c760b9a5faccc069b731854aa2802830650b56161f609522e5300af364f7863589ded2305ec4dee1469b256409c06aedb95ad99da1a0c21c1730a7 961e18536ba86f8a14f65c8ae47e34f12c8ed16dc019e080062b5f9db30496da40a85e81422c265fc85c5f2a3317881b945d79fc512b 40 604897df891afa76ddf7d8a7aee94dd457a54187ab7526c16554580be7a103507a95b07b154d1163 +960cb416d1e5cbecf82b72459c715c0b9a73803547ef57b595f95e008f59dc7ff02429def4b7c19402c408e5698effc8c7a2d2adfaa2c02392e9e5dcbd759eb4d848e45e9866059c341d520701b448ef60895bd5af66e58cc08803c628e83d3db2680d2b3774432cdcd4e3ebe0401a2e4226ccff5bd1cae9ae058aeac2e2d4b653ce46874c03d7af49b03f2e19beed51b933c899aa2afa7fca4cc3fcd37059ab1546d5bc735b01b3e41115150ba04f7e81c4600c79772e7bb1bb12d8ce07f9bfeef2f587d60f4632d5e7a500feb6b672e2baeb29a429dab1ad9b7adb3ae9dfc57ae320bd50ccb59e323192762dc5fbcc70ebb887370a9732159ae450773ad730c6f123a33c2be8fb71734c3e27a17ea7872ed143d9ac6f7e08d08900173720d16b5e40293594de7686e3e8a1bb9fae7ed0e16250dbb7487702ab1a7ff0c6ae8dde33f25ffb4b3c19472c5688fd7d58792a69feee57759e6ce5dde5b8220443a9d5d97dc75d520da28181e4cc90dd9bcf04ec8f643e55bf70b13b18e37e557d6d7512dfd32472e6a7d125a925782d0d8422aaa313483f11524d1ceb06fba94b2c4f772eeaaf5e2344bfe0d98b1d28bce16d50ae0034611a06c6b268aac8b66123e290b31df9bf9cb4262cf1d0bc2796c7a88a441ca5571d55528c6a6e2f98e3fba38abf600b1e62cb211cbb99a97823e1f6c859b584b18e45fe52f6467d6409c7ef3239e790959c16cbdf55e71ed8f0535c88f13a09fad41cd1af258c62a509733cf7237073110aa51ebcf414406c702e4d4c91e9dabf246f7a6566679297fb009545a1c34406a47e5eff5ac304a9a394df71828738d50bcd07ac312c0a69c6408123ce379458f92a99802bf278e6acad9f0cdda5f83d2681bc9cbefdbab1e7d77e715bf4170c347a5d2bc641cb04d7b493667b6371c582aae93bc2beb0c8bdac622335405c352d24761c37d3766c23052fc42a0e6eee33beb80b6624eaea96e914c3721ff3eee922617984854e6adbb3dbae2bb6b392ec278178c9e3a467e65718dae366243ab089ef26388cdfa931fd68c924c9dab8ac5d06fe72 5a685f930c29f3e5c85908a2ce922104551dddecd50fc7cf857a762807e4318dc6b5926d9977e516d7f41632c133d1a40a0a8bdaffc2327f1239a262a138df 38 fafc7692a0caa0b926816945b5ef0702252907e6db908254e77db0166dc29f362d2b024589a4 +54463fd1b87c7c149a18eeabb05c43a3c195ff7646f3ce7fd72b66f6ce5b4f1f8680a6160eb310e16ac4dea09962145584b7c5b1cc100c4d626bac75f6a50bbb7c11658aa13fa850d6505ee559d08454d454c9f261cd9397a562dd73f55b938e8cf5e27e7e04b56e8cfda42043e026d108cd873c41fbdb0583a6197c5abae0294bbcd992e250e08563566167f4ecfd2d7fdf32c4833d78fa4d6d41c09e5fc4c027b47a54d15f7a3e182a3fb6dc498142b8cd5803be4cbdc1b42423d31310942a574ce72dca2ef967a22a11ea59b0ee8eb817db16cc7022783495017c3f2aed1fdae592efccd89aeda6f15ab2d2c450ef6dfbda622d981d0c11d97016a66b1c4691623a1066126105 866135c473bfac21bd9a2b6d66b0092b59 27 5ede2eb7ff4a67672c5d2f025f5720d7a426570a585f93921cd830 +06139863388302394ee6691baef2841e7b1c99cdc66a1c85c18816784e22c9f3b1742770b5567fcf555b9a038685c76b30ab4833d8e74059f42d22ca77e33796298b98faa61fefd570c37090e2fafe372503db0c593b68ad6bf18738ff6e28d48cda3970bf06fa3091c7fe646fb48bfabd0dbc7eb887af83a0f349d7cd9d812897f6103d095015eb7be009c2963fbf083039ff6540bdd1cdf2653592808570e3c58f9b439fbfcee52dbb34707e2eae28abb551cf656886fe7e08ed4325c5a4c5e019b90f92eb356cf578dd035baff28cad5654b7b1aa10fedf136a5c045752e9b27e0c2e1b166652b366fa345436b95b9eea0160e836e1a6f36e7031367aff7fc5bededb3f45e29c4c53be88c5e53bd540571e4082f6df81d893eab9fa25498221feca7c8b6177ea6b98f8726f173786e343d917a9a9a0946cb6a2685ccbe65edcf3acad131b1f721a0327e3ad254ffa1e5c4ec554fffa00659f93c07d2758c6b858ddebc903bc237ac5423830816ab8dc8ff8fdbc3e334f6eca70b73461057a45cf29b1a5ba0b7d0113bf529a91d8f878495b3eb26e3c55e57bf41d369b8f7aa82b48b88885cc4dfefe298c5dbae79654f649052888e3575b037a433de86501adcee84715636bf3ae610df3bdd93ef52ac89baf32bab33a264c429442fc58ee7f43c0e4533b61838190f731c4ca3460fe22f694e293db3df76efa76c6d9568d0496d251a87d73633196ef38386f24ddc3252afaa977fb75084e4f2eae4303876214d15e22801a66941970833dc347307b38a2ccd50c4faba5c5104f663d583f0f43e80014125b1a56b028c3fcbaa0277edd8dc877db90433c791821d0481d2d2d0d68b666daef1c73cdb61537872cdaef97559d482851cde44a31375352f21257f91651aa8d25573aa7e53f30d4a0c6c63f3814c13227268d2a0314f8fb84b29f294e6bf5694352e20e18298d8ed94ccb76ac81e7d96e1b785d7d8f70aa6f2a4a1c8bcfe82d6180c90170f4bb919c2231212e601320fbb9cecbae446fecb7116513c7b801ec95ef6e174a6dfe0ed221d894f8284e413df247b55cb670032f33517887ea4c811349185d98bd31ac4f41cc55a40c99d52268b56778c2458abcf0eaaf43ecf88d0ddcd1c197dcd40e7cacbf95f28d49d02cf864f1735eba7ad6517e2d2e84c0885f68fbd1a219bae4d6487124c55320445ddbe9afb227599911c47ae6553750b532875b5cba236d435bf06f1f8b322a56c3406fcd83410242ce4d440ddba57afd883d505181b7ce2fe514a894a8106c3bf7224ad4f1d56e489afa5b804c84ee531dc46a6c7e5a209890 e30a109423f371457fe02946a067d8eb92678ffd7fccba7a196b266d7b599e6f0f5435b395ad79 49 0273152f3e7460314afa0b1088e0d5da446683a00ff0c48be7c432289ab528fb97cbc20b3930307b9dfaee40a799bcbd43 +29ab7c62b954163126f014d2e84c6162415042b19d48245937174a77e40b76214b7cdea7cfac756aa3c5d01756cc4b4eec395e97b95c09fbb4fde128b27a50ccde7b5aef3d92da971030193e1a26a923ff3948991f9e1b2656a8367ebadac94fa2da1f7b43343a15d0a735792ae249d774869321e1980bf069050539945e8d5328494fe1b961509b69f996de76d232c669da93a1a89e1b80195bb8b0cf7a64596843a6ff2c5f35e9e9c1eda02e9cc317536bea238d0a7510413a256ab9a2095976af36b89baa0bb27b7c053cff6a5e3eb5b6a8191c4f6cc4880e4b7dece7c8cf23fa5262bcf0184c5c093dda773b4924d7508db39e3ec8708e1e36502e9049a1ed51daabfde3d67c9a9bd78684a1825cca9d0895c5aa68f5f1a0df0ed880ee7269737d72b1564137b75d45e11b2f64f87543392cefc4725707f1b2b9edd1263604c298742823ef835ebce8c8d56344e425b7f9046d911311e0c2c63ee4d9a68e843661852f930de160f15bd10dae0f02b43d79cf42fcb061a868029b751cf51dc98a096b8c5d1dfcf3a0852344a4b807fdaf5c8e7afb445d4241a2a4b8e668c2c6bd59ff3c51dfb7bc06402e622ba9728132927bcf4245c2a18ddf4bbb77612bc1cbd72f34a0c80e2f1712372f454672f7e23e7924f29b542b8ac80b9e62b0a455ca0c7e89bb4888d6ba1527a9044ec8eb210f91447177f3916bdb223a74bcf6171d34e51cf06a6f80f44f34c4f0dfc2b0a3a8ed71c23d1355255f0970d51dd9f23938808b3e8cdd97d40c26d363201af0c755ffb364ffcda141e8c386cdaa630832e264eb319581b5b39b1ad371b49b96b6ec28843c715a7d12df6133623702ac9eb3607c66294325ae008a185ac738e77c1a08ec2638a71e4a 9c34e3c735d33c191b7a6e932925b896964d989fe41d1e5c21f02df49fb248fcd7bc028c802fac1ecee1e6fcf3 42 15c83f17d67f95d8b88a8182bd722c8a2b328f184ecc4d01d89d59ce11c866511ce37a21bf69c3915502 +c7bbf32cd06b60d5c9c0ce4e4130e1fcedf87ed0d67c20d3736e2346ab9feebc4cc5bb1bbaa0c17193c18634d926915b2c48cd2a0c77eb8c1fbc7649eed466905ed382b704528427c07a2cbfa2d2b93139cb360bd2df75b9f3acd760b733007388ad2e897917c687020df1f7509d1290bee6cee6f992449bac2311899c60fdae41fad979905c96b538ad1389c27c6c74201be93d2c43d2dff82ed0c3b8b3ae5bb95b2c9c543229de5904228136acdf3cdf67a5e46913526c804dcf29df4e7c28f242b8d14dc6e2ed8c0def2312ec8321758861f7f8e4f712d461b8fd571459a380f85676747d10ae2a5803d26f492681ec31e164cc91a8be6cf5b688d83c8e3e60fbe03121017ceaefb76e76edc6554e6304ca09f7dc8eb0b9269be6d8a4cd61e1b2cd1633da3b69f48e564d6b3b0c34f67ecc9851f618494e983571fc66cd6b5d4e9220f0ed5cd7166a5b0eb84f9248c01b2381ea531ed3c89f18d86db93f998419621968df7cd8fa0d865bfa0bbc1a203c58a193e8ba76d6c231cf5ba91285e09a1435cd73b585f301b4648cef45b66f5dc81551d74c2ce882a6e0580fcb5e4a897a876754c71d12a30003e840f7a41ef9c993b75e17db51f52611c4700afc5107b000728be933a2dbd4eef27f4189068164a16bc00d21963b5927535bf5efc7b487825c20d21b562e2dcdc73fafc4285e3137a476d9cb39ea811d14df36de004cb91ff1465cd8862e213ffa94a124ce58156ea5cdc8cf5ed2ea7e5958b2314d2700aaf412f1715aff4db34742e9c3dc35a2d257177227e44320066615819acddc0ae7d810adfdc6fc25fec99a8927216f6db23cb5390122846588553d9fbc433ca5bfff27e3d99c9cd6a0b8a1b0bff642e2351f23482473dabac11814d57c1175c99ab88cd7f14445f1ce7cc129dcdda8795d578c30da15c4fd076cf9af1e76198dce9d4adb1ab8896d09277352a3a2dcc05c45e0b2c88f3212d3b05a63e637560c0df7cb2dc71cb850fd3a12ae657ded074e0d7dea6434e3364947e19f07f2482d18df6deab11ce4a150beebeb4b392ac1eb7d70cbf42b62663910d70ef67c0c44c5955904347b48b72435ccb4ec8bbca95d9a56b3cc3bc65bef8cc21ce3f5a049b6848635bd713b57e18ec43f0080c3f51549a6252ff74d724b8cc9cc3e51d817e6b25f454f0f8bf279d3544b11fe5b0a3a757b61ff71b4d4bc123b7b92cd8d41605fabb8a6a6441bd3423eedd8591cf92178f3e653d112813961c41cdc2e999996f80509fce0d98059a1e29273eaf255641f9ec4c6cbb7ac18 11edc67fc12cc9630889d90cb5a8c7ef4c1bb442359dff6c8fed5cecc27f 52 39faad60e9136c50ce863d101c23b5ca5b59493d836b23337d6771ee4f794aa0dabc4b5135915216fa82f76067add01c4fc8e32c +2a3ffda005f2ec2ffad4fcc7f0a81ac10ac13af097fb1dfd0a13e90a8a3db4b0baa986d56ede97d4129fd0c802af0b0e1bb621e080754162686e698b231362e77d07438fbed5719dbcc0901a73aac849854900a59a361f6a54285f48e5105ba07b11169f76d4d4a032bbcc831b43b0d283154e06f563d15fc812c98bb0cb75adb3a8b0bd9ef339c8f3e6afbeec3c9d53a88682de272ae07c3da98ee88ad004e992ea9233d74a53da7a9c10b70a56a17f179631f57a276420aa5ac51ac8e15b9a61d0f1f84c60d1de0fc0a3e0ea45898bac0115aac6346befc1fb95e154409cb6586d66d25e14d289b4465cfb57283cbecf146a6c11df5c13f731baf846ec75ea7c8762ffaf8cc216f8b5024a0704264c470185cc814625960530413258cf0179b1e78986c5796c2a5b327644299a58a059a2e47df349fe16ebf8781fb81a92b0b9df684ae3282782a31b4fb985ffefaa51b9810ef60e8913f4a9cefd40c04c919c8826f9bea982acb29ab3c7af0c021793e851ce60ab9e95aebb77635111d1e80564ad5dfeec1128346eed8b438389c8e81826b1e85b0a96a8e3afc5bad13a9496f3a9ab001a378e41ce92b6145feca2e573bcac251a8882da4ee74b0d8e794f0e529937c659d1633e209e12df86da0091cb9e23c8cb4121e8d5c917320d3cf9633f59bf16ad4ac3f5ba48869e4e34f8cde4d0cb68d366c5116d4cbb80eb1e8ddd350e498f97f0e555128db0e079b95b8063dd264f93eaea08f12afd77c0861538c9728501eea01540c00c74c4b0324d72aa55e33d777f3af4d32db6b6ddc29ea137d0c22af345dd26116c3c966872aa39811cfb7a811244f24aafe448264efca0524a82b3dcabb9bd6eb6a82a6db403f627567b2b02f44660d7c9abc20c009606d792da7cafeee631399097f95d626391a72507b2f9813fca93cda9b878fab0822bf9820edcf5b1ba952028a08c35109e 320aa37ae768e12898787737ba8f7723802ca6abc93fb56550c14b57c30e 22 de31baa4a5b98753d600d0ac0049d41811261385ce8e +7c23cea93123edd3d9e8b4bfdf2259cd284d0ddcb7a1fd64f0a53e41be2c7a484ddd7f2b95faaf8a543eec317deef189b445347c3bd4186e42ca03f09bb80f1c2a996ffbceec8ed2130ffdb6034f14b51d137e4376952fb4cf8e4f17c040f88ec1e9f85463b0c70335c89c0b3ecaa05d55a7097b4ae8cd3022c7b9977adfbec6d81a4ab98d437ae19d5646fe0d5ac3037dd224516c3d2b79e1ffe13cab873bfd3145fa8b2cbc6229c7c58dc882095c2ebb43ca1b347896dc5e7a8aede53263d28fc32b79321859f80445f0b3a3cc41c3992baf6d9ebea262c1826ead56461c38c703d821923bce32682b3158a930223f555905b1c7e926c904d5513952cc4bd7e199057941bd033eb4d8f04372dfa970815facea2c807e6626689866a60e35081ecb216793b479a4c5465e12757cbbd3cf95ef7bd0554b86413faa4a485b86ac9508b9ce76cf0747bc89811725664eea39e8f37f67fd380395fa269ab63cee33b391acd226ab8518161833ee28c86e86b90837a24fff88f1feeb59f57eb8b78e0a53bf11f444b7bff291cc3767d1c402d067de9387d1513d789887556874b508072cfc7a589213e051747caf3c4765ae8f71b05a5c00c796fc2b9eeaf4719cafe53419b69fbc7dd054459b512fd722ee495ca06ed430bd47fdfed794da4d7e59a1ae9fb3bfc7063b24b170d423ac5738ab00ec20ccfae0f30613bfc603c34667cb7c34a0b6c26d24da026c3c01c88fe23202d036769ef913d2368572d223e81eb23ff0766ecbd543c7da61e0bbe9108a4acdf935a7e21d9aa9beb32272410de14ef52219aa0ee6264dfd065f27ca1984de1a2ba4f7ff9668b6cfa0e2fcac7ee5c5939d629bb5c8e6b0935af496d572c5af37bd10ddc36a23680bc8715e2e155c1d79f5264adc23c2d18e82dd587ca68d8af8d2114b97e69d2b112faded97702d22fe66732c80723c4bc20e3930aa2adc48b24fa710989aae49dbfca728b32ed9ac66b3b937956cc54252e623983251324cc576e11e344c24e2349e701e8757cb6ad3cc99db6aa3f13836121b0573dea08fb6 df21e725154ee04010fa20bb007a472e3a9cb2585d7e9dd0088068d65a8e7a7e51fe3f 20 a486b25f09ac6b6cc238db378893d7d7f8412fef +886210df26c7f6c2b07667dc813f5af3d5d10aad3553fec29ad4ff494eb0a996b58c1d0341870a5a75c158d4e9ccd802af6151c4b27617ef3c3190ba10eb87712e3b7c69c9ee9eb84b76b6ee19c7b5a6279140ad290048767496052c83f428f9063e929af5bf89435ccacc3c451c66487a0aead6671a60bb511bbcbd8b4874072075564aa13e5573eb020b851971983867215d967371b38c0e8c108d1e0780cfc0d4ff668f825ea5890734af825090e2c8f49f32c498c60a36583eef8ab02642b80e9be9417fa0bc31205254695b0c785f69a101640a3575adffed69ceb88ade837611bd1b1b2b55c513a6013d8efd0ce0c12e53625b6127177bd0e4c1fe09dc53bc5371fdfe9b8235ac5c79fef613bf78c85fc9236f135ba1564a63a07143d5649812d5ee08 58eb6b8d0527fd8c6d16a0591656aa1978574eeccc6f549ac956ab947db66bdca2864ec19c1053b26c50dd2f17e01866efd0fc52 49 aff241cfce6c89d093c1c2d7b43d74ce4922f3432ace24a010d3305489f4ceb06fd47aa451d94f78fa8cb7624952e3e3e5 +80dd33ad80ec72aa8e0f69cc519dd545c13d86b11d44e0b27935bb4ad492c336754d8695f0a9b0f49bbac7a63a25b42c286dc7bd656a85c9af9355ad7d251561c4c82caab17dda3e17e6b21bd09f54db0fde9b92bb21191689e7f2d6efae04cb70ff22196952d09a97b9ce78e2dd50161e67006214e43096cd4cf4af07b17e6986cd2519e87ecd189adc3daea782aec81b27936c460dfcfcad0ffe35022495e421643bee637b65ed0d3e72ba8f744be971b0a6d386890aad7b3462c929eb2ee0173d6d2b39b2c65c44a82a7b3750b15b45e0c841e6f6f2058d7fa0746228e12e8f95401194eb61f6d1ed2f7a75b7a3a1a3fb673c8359a82571c02b31c6d9f581d705501f46c91fe7c3bce67101cb7e7c5ee3882e66fd63630aecad826c1f4666090129a322acdc3b16da37ffef8936a888b84d9c7181bbf5283ab5a3c09baa95ac5d20cfd4a61a83521bbd9d75d65353603d5b77b6745fc31a465ba916bdfeaa14a9341c7be42b20fa6245e6c62dfc624e025fd4720ac1769ead97b0e0c54eaa12427e1726b8e7926b9e4f037a0cd2a36e4003dcee528ae9cd67aeec8ccda44a34c90696c03f1d1c861f4a521765bf4feb1e6129ce9299d00e2ed88b57e90418465725d9c3f7cc01465ee6ac426e39f73e9cd54d9bc960e6648184220e2e5ab37e0372a070ba99c3df8c21c0d91ec38150ca39b6820e0df879a2cc1bf753dcc10a229ec09bc018663264f6d8ec07235ef0fb8f5cf53d4c2490907e59fe296c144916683dd1cb12bdf2fb3c3447e647805dfa72dd946d38c4738ce78940f1c8c67d66b1a99ed4d5f0ca7981dec3d756e7f766649578b44853c1b93ac72dcf2b35ee3fda7086c2dea98766da6b1a92cd2333bb7739f41e825205d02529c2d36c4ac7c114f5f7431ae5139daed0327f7375248e6e370c9f01bbc1be762a05a007fd1907c22594617bf35157c1cc0defa522e9505eb9d5f2978143b210ee7ac0311df7fe52cf972ff131578539c5b2ae99e24f5898d746c5edc8094fdce1bffb358043aba83e0b20bd684e7cb04f33952a46924f131529f14bb46de46af20097f104867be34b6fef7ada9f7fbb453a01aeb0b3552d0d4005d928e2f9eca4db9c697738e82324c554cf3da62869fe0daf6efc3d0216ddee4ea25227ad3f077a2c6f92f36b8f31ba04b05d6ca4acf7f0228bca6f211e36f3df19e16b002aa175696e20438ade1468510ee85c6a06d76443c5e310edcfec16a4f5485f2cb4f025605405da232fe267aed47be66dea25ef7815827caddc918ea080a13a4fdddc37316fbe7c14b89e71 314203978f5ae4e7a11cf1874f368ab34f999f66c4c259ff63cb9e78723a5d6358e3488ba4af5d1a62e1a58bae0b68 60 5df01dd31311be0f23e67a179fef2a1205a1387e3387cac3df8463125629027da13075a71a41ebfd8216d226b3acd5b6f1722b07aae901510c9c50cd +37d6dc924de24c05e0d7eefbe5bd0029ca0fa308da95c151f4f3c357603369079daf6e2d54642a051c49575336f7527b6645fb343f98c516517d5c9ac1ffdb6773349eff5b118ffecf1f31651d2c826f117abba594228e80a927ea9ad7c72295ddd9ccbf5deea58420722824f3f7f32c594b4fe57c92a5b5bb29f5e68aa600d01abad6479e4de2174e770cc2409be3324f79c9d493f87b69f0aed39b00a65d8237d95741624b2cd808ec87bc79aaacb14ae64d949ecb05d96bd14f7855cc7ed77a60d2e14692aaa30afa7408e45499ab25affdef50a2256820b7d4378ba4a6b985905c75072d57c937b495a9406594072e835fa08a4d1695e3a4e8fd6ed09f270a3461b67a7ce776c5b0edc1daa6421db574fbb597b3cf29af2bba607bf414af5e97222771eb8de037f3da145517ec03a309f64cfb584baac6ef810333cec654a00641238a749e698150ee370bc4456779cb61218a309b08fe75f500f21233925edb7b5e2de78e8bdae78296c8fe5d2f059d20c3125ffbaa86abfc2b5fd8002fca6d0a3f9244fa499ce3e0da81b5b7c1e149859bf8e5c34f1a6495470808bdb2c7bb674066cdecf17b71a7778691e87c97ca972d5e0dea775b433c6fed22cf2b3989fd9382e39efc6f5426b193c353dafe2ef2e043513b55760b89ab77e72533b3a436f2417dc01f63a467389301486a19a59383508502160dc9b7b5b288b0f8904e0cfdb2766aed2af598fbe478152a6d4c875d89c4f2769effe2f144eb73645a8bbfcdb2aa26be2fe14e895f0203174b00ba58f9041897f599603ef70e3ce2d37799b82c4cda87a79ba2fbaf1923c176319f85d4e587b530982eed54cd331135fecefff448ef789334 99d86d71938b21eb366090f664dac270869afa57e367cb145845943efc1a0773 62 13e1c0205a8ced1a3924d28ba27d5bdff6d28aa4fc6420a699843aeaae34212d263d2cc6e3f64547e14eb39008baca44013afbcf40e5ac72d0effb600e2f +5349f0ee dff2ccf58391f7c3398716955c32b49db4572c9fbb2caf63212461ef1800478e1c0a715ab5e455971f75a238b9758da4b6d3ff 27 0fc36fcb7a499692c0a3aaed3b901e16c5f9f49a66a62573117217 +2ebe51c9e91eea51822764b75d7614e6900cee11cff8d36db67960ae8af4b4236f501c8dfacce618e857cce57aba00a8c13ea38efb12403f10b11613892c55fe0f15af55795f30ee04475bea2908fe190eeb3d1591aba4f30263fda01d96f5e664a5de7b1c69e538c1ceece0ae9b0e1e5ea108c52b1e9b3526905d5321022412e2614203b5a4b881edec642fe6e05f8d965a2bfdf75fb5228570f85cfa9b5240cb83759960161c10005c2f07689c24e3ce091a4903f1f51cb41f813da73abe0a1e66880b4782494361fe1106cbdf0fe5ddd422eb4a257baec4547a27731cd61521806e01ac1ed60f7b97b89814327ae51112a935410f9a3b81f0a409f7642a325f0e1502aa1fddb414a367c5d55c4c4676961966b045182bed1306b332a8486079266603f6455f39e25f6c4137f6914daabd6ce146c9bade0f8112d1056916cb69cdd85099494624f95359699152bb28b11b419fe3d200eaf81d3f2b55e317f461f7346a8e09801480e5cf5cfddbe8e6be23e06de84f640c127a33ddd2a6272e6c133821a9cc7be6b2c1a24781cb37918f31d9f369a472d7244f534f389d563fe71998f1dbab4b6e07c159bb93a527b9b7c25f7db25ad7e12758786485a53a41cbebdd6164126bc84913ea2ad224ed6798ba9dd782650078ccd40b8076482e9dd260b86660d333a7ab78dafac5847a8dd633751e578062fe69f92f5745be0d680af43ca924fcc2d86dc574bddf7f6acb8a6bd618403c343e208e1c5c076b11eee9626eada7f571fcba6f24e164255da7222052cfe2ec5c2c9862b64d91e79607576e75150ec9b966bb300887eae437cb9a047e4d98aafeaddf7f70cd3b8067be2ba71781d67b98f10bf20b6489a7523d47eaecbae57bd73d7605a23289c5520a29c795eb820fb70a5e270fa4537ddd4434999a16f24f83193a190091a4828671ddc2a1e5c9a1ffd06c775e58499addadbc0cc1fd57602f8ef591eb0504e5c0451aef01a2bd07462666ae309e6060b436b6b7c9d6aa6b4b5314b1d0ea49b6cbc5f0645e3cbd47121dfc5a9d30810ee029cbfac4385da506371980daa8bfaa25e6950e21bc7a9bdd820b015adc0ade0ce562a552f7f9ada99b31c87ffe04e39f92c8c9abe480770e3cac7a451e7890158749f0aaec7eec6dafdc614af9f51b2acdad0c088e7caf636da12e945b11a34f6376a94e3e9847719e32f503c7e62a4c54fcf524ccde8ce624c2b7feaf37c9f29173eb7e77e04a99dce9e156abd086a894c3f3431b21594998332d7cb0dd972b650270b072ac40acc09cd78940708d23c8d5af0e1f814b93d4d06837ab4ba994aca059640787c35252f076e02278256927552f5c9bf14e49ca38b431924021c2605e071ed220947d39560b4d319279451029ea43aee088510a54e835 0a7942cd65546e8811bea7f2c340b407b6d974a1fac96cd20b5e23190538945568e0 21 a2e9daeff6e2d3929210075216c830b271d646a253 +fe8a4578904827e06b71039823c1499dd8513f3b83a31eb7b78748558326b66db13c11a237c1fb03e619f14f3087f4e9f1a7ba9e689c20dfa49896ac97984d61fa75f0c46dabe617d6be808d186a221fdbfc4e5244d25b0e1112c51d24fa344df90671f8bcd448e6c125aad935d1c6173a39acf2c78dcc3353dfd8187ec5592cae1ec6656814e7a5233a2ca02219161bf8c59126c1011d4b4586aaadbcbc57af03372aa97ad9fbe1190534d7354146808c830c11080c0b1818b792d8ffed92693201a03c8b44431a7ef30b5e8f667f8691b1138e66c5e8b144d9d49d168fdfd63aded3aac18b35032ecc7b99768d 7066679d1bd485b5c79d3e3a06b5e0059f5fb3c49c76468e 49 add7b3fc020972ae59fd34db314455c21eb22edf6f3bcee825cecf3de774bd4484551cbbf9eaacf98fd83faa826bbe8e89 +5ed1e289f5725f6eb0137b75f5067b2945c8e3449276f80fa9141fd1e8cdc34677b73e9e7f63d5e607a7155f39b3691ae3b02dd90d0625fcdb1766677bc79aea7569019856f968d0be663f07bd9e46672f588fed481af0b20b3e5ee61421a5df71e0f3ff63105f3377023c452ad73b2f4fa62415b533cdb0d50507406d282ce2f2e2c46bca3e8570c219b4d66f62bfcf32b92e461b71bd68c24b69d8f54a55d46d0eec68cae75d9d8f88fb06c87e1458a36f69e6318d4269d538a4cf491f36fb0b70976693f487b6ee8ca00b323893ebc94f8924f9bda0e6890ae4d40446fc858589d83bc685317143fe059254feab9fe76a27c9f135b6e4cbd1e8007bdbb78255a76ae12574c046099923b12b2fe12a470d70e7c39f7bff0ea00d4ca9ed317ef5cfb8817b0a45417916e5c5b3801639c7c82db97165eff61c662cac42daa9bf68f39e10823ffab77a3bdfff2dee76d4200c902e89ff9119eb0c5760ca82539d9261edc5c7b0386b6d2eedcd22350c896585e88a03749cb20aecd0e90ce802beda4fbf05985b384548a50345a71c65009bdba9c85a3842048d88ff35cc9892d5cc64b276c286973ef36d0f4339fdf3d35f9100c61dc7e1792ef1929757f25a9236267d066087f0e742ed8c1514ab3ed6403bba7ff67c41e19c5658937c8c2a992ae31414e4a21ae776ffebaf8b91847c0c5da3dba521db59e5cdc19af6ae3ba3e3d0b8e32047345ff13b1560d9f9925e7b58f1fdb3703cb22ab05e5eb1c2d3251d90f3bd1336f7e96c20259b9ee04c182cdbcb48df0043cd3f314d9179e5735704b02020488c4dc0b89b5a38be2b972b0dd770c48eb9a1d480c0ce418b08d4d1b5bb7b556ca25d9839a8f0d04a6abe6b8a108204f5df1f3edd39d24d1e1ac5c3a2b71b1c1b6fe57b5e0d7c9e5a9a681aea160692d64706cbf344f0b6072cf3ebb4405c54abd97a163fc6f3cedb78c57f12cbd0e904684972677b58c781280d426aab5d08d4935ceb59faaab3c1aee2a4ab284afb488caf123e03e9b881b5537be1779a4560ea66f35c5cdc60b5502dbab2cb5dd9961377955f7dd8d2d47222e043db550d501a19974683a53542df2b36aafdae261bdcc113138ce780f01d346b5100ab9c158f2f18398f5be89c85120518f701abdc5673c05d204a1598446a539e3bdfc057215406bb5a649b1342a98880d762af37616283db323dbea20917f89ee8c41249b6fb31ed77efaa0d1777fa844838eccedbeae486f318dd508e4271d271f3d1baa43ba4098134089551598de46e12904b025c45d8da84a8cafc28466511df79f8c4fd70f8d4292b4a2bb3be7efa4ae58ebceec71c39c6691351f4d9740639030999e63a757362797f7ed992582fe9dfdfe78e0728e5b8d742d45107bded313d56115b21125c77 3b279c2f803aa09b87092c265754bf8ca51f349c0916e91e46c71e7d1e71c9a5d8e8f7d77d 64 167f64a10f818dc14ead72fa88f147222f7e675699b60ea8b3d0ab5be18ea0798be8e6255042fd5119740f5ffe8a6acc41e4c63a80e9a64cdc0c1e93ae63dc22 +306845ad4d008bba322d4585d851fa7de6c159bd4217e28dd1d7d8f72b0c874d9f5055c061348d2ce606c21d2d91f45a3e068fe40b56137c3ca4aa2968e3c7890269757c13c7981b9794798d46d80980de527590c365f382d9deb36eaa545563c2c35f803ec702e86fa47fabf172c8967bfc0f78f50390e145a50e45609edfd4e4875261ba5943fcc0762f00f4c1230343217361c4a5e12c5f5c21e8e7ecb96d64b338fc814c919be098874a4abfa9454706ccafdc52a3cde439cac049caca494772f017cac9a9bac0dc71c1ddcb268420a39169460d72615fb63808d3889b7d6d7ad8cc9ba5d77aa415c6c91386c0d47b151378 ec74036737c9ea524b8d07af28a0362f4bf3b44746a12849bfb51bb0 18 90af3f3bdaaef8ce79b0e3501cfece88c64a +5e13526c6fd82e04cb7a57264577cc8831f6e764bd1e1b51e6de78bdd2595d32a0aabbea7dacc2be8de06f424eae425e17b7888dc05c7cf5c0cfeb206dce2e61e6e154f777a9f87b1847827283fcf1f331768ddc69587ddd37ebca1bb9c4afcc9bf37132564b8c2e6c2d7b174c4f3cfbc191ba2868ac3aa33b536eaeb819a2665c1609424dc6b49ab4a9a1df0cabec4277f3276d2c948a71866c0f75ead3290be785109d9f799d75db9dfe3a2532a0c0cfd34f30a1023fb610406f3e8396f051052024966df5a08a5282e9b66af8c9ef2f5a95bccd8f52fcf08d324e111bc01c42c231133084171dcbc884b20bd64ff13c07906373a183dceb27430f585bbfbe32ca6ac29d99eb15e3078e65786b84069b3d9dc68aaebf525d3b9a968560ebcccd6f0884c076d4f660dd607c1810e851718150e4853fa6969284c55b39ee12b81f91e58bb9ebee4c560b69919b4d16541a66277040b6c5604ecbcc44cc9b8439abdf773e309230193ad3285deb886ade42edd84370c75335f0de504b573d5742fa3eb33da87bf0c13b00f4f0084c6f55f4bd963e491aeac241c865379fc5f369a3014cd6b823f54f2f59f121269c4939ac9840ec07472f5e7436c284ea79f07a05f5fea4f834cdbb7c151a93832eb2d8885271f353a3f19ca772dd949385dca2fa84d888e4cb150e29be339d59be2b921808916db51a64b3eddea11491b7133104e439de31dbd42326281a9b092dc5e695d1058d24c2f6e338c5da2828cdf672695a2e12cae9776e4e069bae35d1bb886c2a978283b75cf1ee42224680ea19165b8fcc1b2c7b7c3ab20be59be9341b0dbc3fdd66 af5c1c9397c868ca9a08c50ec165eb01d00bd7b78abb3921cd3446ec7ea8c1d919c3979734b432a0b3acfc9b72699a013264512c671619e0219b96 34 08777ffd6eaa764cd459bc910d9424cc122984f851cd55992982660eb598272e49ed +248f71d5760743a417e921bbcd9fa6e8f1bcad220a6880688db162b8651cf95cce4de9ec19ad56ba4f60763d3efaee9950275d54fc90a2fac93f5977b9dcd6aba2e608a0fc575d06c66c311449ff4be5557e315ff033d05bff9c1c1148f4ce9818ec3850741557e9bc3f02117aee3736f6e30945c1c4c639312c761cdcf5735554e7 8fbb413212dad1d85b6de312d28ea7cc955778922b3a772311 34 9da3c63d629b26514f43478b162915cc887cb55b61e3b081274b4227d4f8f24ec9ca +47c338df57528ffb185420c6a0ce075ba7e56ce013eb159e2d6fd961c67caaac93c0d1d230091fdbd17b0648a4d674dd232b66013b31f432db160d0a48 d33b54ed63fddde49e6fe7d824082aa0953e7ccc23afb659fb86e02deaa92b6c00b36e4f1c0afa9f0c2ee3766fc812b8e7fb4d9b39fb46d474a102f8bcc029 43 58eab40e5e9b5cae950b4c34f0a7f821e8fbdd3af84a569cbcae761280912071456af863beea2233bc96f1 +c8c1214cadc3674120906903b2193424bde831b8c7a38d3545b07248528a2aefe791f32b7cdf3b957d94b70e32d4e86ca5626bb56122b260ae522fa5fe866f5ef4eebd4d4c7501538a0168fbda21a60f1aee6477325157220e8fa8c1789336d176ba06ed733b8e23cad3c70f24155bb04744edd04fdb43d3fa34bcc9e7c93c3fb490aec5bba224e70d77565eb7a7b3368c1f097b59bdf92b6c3fea7fb539962e61dfd3c4444ca281712eac2722c5b6f7d7ae9aeb43fee4b6a3e072ad2efd4b3c6d1e774df6ea37bc8e311cd4718b3edabd292107de7952379c0106cd9b7f57c6dec57d44cfef5988a9cb52477d1ff62871eb26865c206e27053858375591785032b8d98a3d2d764be4afc8c2e71356bc38b379262309b6b2a9fdd5aaaefdd1cd901d404ede3c6246cbbc222275517ee5ba50eb2beddb2b745f70fbbe41685b8429563e79c648d066fc6bcc34d8c23b3565a5dc6bbd54411b86c760521b2c2e4dcdc7c155500821bcd32c7f3355b7b77cede3a135c4138776bd9cbccf43595390242f305a5596264bd6feb7a5724ce15f30e5b86b47210a104bddcd6adf2f25c4a23c0efb8f5cc6227dccc6e34274fad23edf4b1190d98ed7d288f2aa7a82372ddb87ebc94118c374111972da454fba7adccec9f3111461f2d76d5d7823f33d6eac73dfe15dae91c91382a5c52ab3a4a2e7e35feaa55ce4d9e61561c1db938814172bd541235258b8ab8dc1092909686a0857d4c35e28f246145a5660388c0444fcc99d1ed6e4fc6af451291555cbd77401c3478522a0edce754de83f561cea9f5d23f977736274861d10636ff68cba720f8b47e5de21fa3b7123a754e3f48bfbf24461120b90e65690174bcc451c49486da8e35e16765c7a65110f1980962911d4307e57d64534af5016d92495e5dabe9fa7a014146bc74a3877c83f9a3b5706e344686a1873121d89389c449f7263caaff4b76ed43add21fa2fc2367c98c988e9c330e791e9721b4b8fbc33d832f5454cbbc8761e0af683dad5e37eb7302f9d3e09ea4c7e9b25d4e3e018bf8af11486a08e7f90ee0718c8d691e096c6e18424a08cbbd72ea86038f23ddd2955593fa92f3af08d5a742668f31361b4a9c7ffda214d85066d5e0e61318401887cb6f537bb7b3cae0f824d7ccd52897cde9fd17722a309221e4538c065c97beb47 277064386edf26314debb85dcc87f74cd66e 37 32aa6ade4a0c1df8174a578ec3a084c1e6acd135cfa1bec3b270327ceea8879889e6dcc915 +5d34547f399ff7e0acddec3c0e78e725315fd59f174610fd8a6ea6e4d3c2945e62bcd9c5bada82099b4ab659f4177f93001e1fd39ac37a9f07192d247aa7b9c174b4d304c772d1c0bf249ae75fe60b2fc927c133042c8d1a9d41baae7f66ceb2bcf9fc3f95dbdaa53cb1a6c19bfe5b375d8ae345ee095bd4f5bfec0bd01bb43d5d506d8cc49e786e006739eab695d67b6fa2e87eec680f4b86f0ec7ea6254b433889c762b87051c565f2e2287f48f52224e64b16d066a52cd9d796126e162f606ca2225deed5df4b9250741988c024d52e712ee80ea0237a596c03464f1b585e9060c972341f8f098b1bfa32ff5c75cf8a365a98f47f793354c4932c6f06fe1a12038ea1ed4b0f9f5ec19b634cde8412ee213603a7805f6faad3738dcceb3529e53b5e5d313449660ab4efe626aa6820bce99c64f1e5bc64cf4cb60719aa24db1880020dce821b41e46aeb6e1e6767abac8823dacf37eaaf8ae6f3a6c6be37a1bdd1ef7afe74b651966da1e1adfe0a8e97f6d7bde8711a58083963a64e28d703a2ea16091e41b51a7a06df5d0488a8ac19c9998b5f59ed534fd353bc8a78fe5c9955dc3410ad22cece448a2f1bd1920f17e7486209cf4dfd0051396fa63ef090a79f51ca993f406e394e961ec384ea50a0eaab8eee3e3e03c24a9e28c53da313075ef936a3105493fc1d 4a14a00d359d50dec4d97c507479e0253f073d1e945dea02b91198c7a175f874a3e3a98e34946301 45 efab0ff7b34fba4cca43fdb19838a26005990223d95c9ddc3b602fa034046a03e14378ad89fe53d6ca5a1f034e +d38ac9257183ca95b9755f1c6ddc7ece4ad907d39af0b49ce7118079e883d0634124a74aa7e788b6816856a00452c8c82cddf8e7f2fb21d3b037a60a7be869616373434f770d9c7cf4346789af8eaa73a592b4432875b33b456e83db3c16f2a173af5c4c8b83f1972a13313e482204f1dc3160c2c7ce62b851a0b76b041cba3a3630f11018a0c982e69c5161c0516de58a40c7259f2d385aa90ec0c599ae26083796698d0cebf51a59fa5d5a208f0fac726d5339bc89a8bcf37fafaf902bd3e3ebf08a722a38bae451d795f2395adc1f423e656b3423fe263c27504702b476bd48836b9349660a80b6963733096a8d7d538765da6b369d834818943b5b73f4fe070190b3f3009f7a5288a3659098c41b1447f412a56ae168edf071f9de892b82807b49db0914df202503d8f8599e5d7d0612d7231e607da34ea127dcf35a07670b0b769aefbc2290c8e118c5428df5559f83d48cd10b49049268a66629aef7f7fcc1d2d622293cfa0ec745c7511fa1b61e6178abcf3da47a86952f1bde6a81baf2d1092a91533bfeaf35c5da5b86aaf4ba4934267acf7960ac88d3dc3fd7151ddab65da63b195559c23c1690ebe25040b043d662b3a26b39dd28903ff0cbf46a80d481723b92d0d3f6b3314475b2a19af554be573ebee1f60c3f5c1080d4ede23da11f62b18019b5bc714d572b93e10d726e4b69c12cd3bb6268ac74c2b588e0ab8546c2ff962bdfd651fadcdcb78d0c398c5eefebb866397205507838c260ae4256fb97fb3467c6ce2e514d8cd4b7e17ff2c161331c404d113e8de88f5253edfd4e952ee04b19802059c355a1278f44007f026e8d72669333f83c142626319d58c3274dbf1d2e8f3909c1b18a6c2997fc2108393e9ec5fd42fd3e6dc2333a5f91658049cba8e6c2f42977997c123f6858e720050c21d168c84545325600dc4c93a24eeb8990fff67e3e34d6496c72f3f9a68077ec46466d99c62a3df15b68b468ac6f05f0f44dcccf17cd532863e3c3eaeb52134e8681aeffbcaafe615c52badc7a4f008182fec418848c60554877e24b7af6d2be45cb06dce92bd39d764dc64b82627bfdb2f5bf937ed9b818fc3e0f0cd09fa28e4ed5f05aff5b192b513a59cf10e2c70254c607ef2716fe4af3b734937e8688da1ec521df68b1f422672888fd4e669cd62f88e33001c5312869bc47e7ef6529a6b6615e29f85a78d763be8c2e472a729bcb0cb342c9ba7eabdcf39cdd2e974024d67710126a2ebb81909e2b906c88308c1bfe52e009 d30e8055e3e6a1d6b74d73f37fe361aa6440da576b5d734ff0eb31ae2a934907659e170d803a9adbc5c62ae248a1b5d79dc728739eb5ebcf 33 ca3f8eb0e8a823302748c2c367ebc43eb4c4b14af235ed61a10fe94c47c576afac +c3ce2f359c86641e62758fe49212f7d9a5e5519a944ef380141edd12b3ef5cbffa623d6c4b990ec079db93c080856675eb043efe91edda7fb44829df27f371d86cfad971d38d1ac9ac73ffabac3af97a7179781327fcffcc0fe54f53d638d7dd156cbd07ce7e11180ccf7f74b0be2e17ffbae6039193354be3d4f86c34fe79330eeb6073b038ce8f5e9b901d5ebb9eeca06ba6647123f021f48b3b9d1cd965600be7a617c0a89ae45571ca14937620a52ea715aeed6414a8c76886a54788b6db11dc3ac586e42e02560021ea0eedd060e85b1510d2aa485cce4756a2ca50229e4d333a9187e0d3fd7c709e5b30722e6e09e2405e754df5ef6f8b8b3f402f1f1277b1cfd80a6170c38a300a17ca9cd0f4b7c814a6cd72f587c9a65210ffa6cb501e4c482fbc0f8631914db4f3d176e7ce6add61d6785ebfc167c3b726fe7e9e6718e5b476fa0134c4776bfffaf18738e4e06da56c229cfbf208e759ac986053ad44e9792dec23495d865377f5211be22e6b859ff3aa670cc719e8adc12a2985966f56c332c554a4eb9df2e350012f9b529710aaacd9942d0e31a0d51f4c6dfeb7122caba14fa9678b43337b9229e2c54e48f09f0a2fd56b557d7438dee06c426ece9afc973e6de579d081d540d8eecc8b1fcc384cf4391248ba6e819159f45663e2da2be4989abfeedb1c63bcc13919483fcc6d11d2dabbcaa465a8b0dde42079356b57d42110720275df30cf3dc0dd8f584f392c4cf7c21c3785900f82721467596eb0ebd1f9ac400a82c86504bfaf2a37c690c51db6a5d0d5b609c29b12c78b800aabd5660708760b2807e144a24f6d86224858e2f04d91df3e8e252c73b654f1f20af7a10e44be4acfadd139d4f54b6303ca4767c959d4d220ff265cf20bfd284145ac519565604c40243779ac378ffa0a6133ee860059218efd06ba124816cebc85c6e403f50f5fca9605e5b03bf800f91dd9d111597becb5c1ba4ef6e893814338e3122d4a09820e3c67842db35497c5b53026f4313d66cd80a05ef36da07d5fed5d7b7fd9b0a275305b80dc236d53e722b351499471d06c3d80743f82a079ddc0498a8694951fc75989abcb62144a2600aa2272023eb8e0e929e62aa4bce5a4dd66ba6563f78774a3fd07179c32b225c9e23b2634bf2713c7074eb09ecc97603ba927c9 eff71132e385c0c916c0215b4932b466 49 67755b29edc437e8a8382c8b1ff73723ba6f2a07925a816b10549053705269096d0e71d31f04bea3b7970695769e471474 +413747de85c0bace53efdc3336ac0b9415fb5596afea71907e7e2bea92c5f17356bfbc7c2cde6877bf1f955dc4e20237fc845b16e288c79ae43862981c3d37413fcb71ab5e358c1c99489a7a3cdff1b0e16a22b832c8cdeef6093dd04727f34514b762cfc20a9dc5903f9df8df2490dc5f657ca1e21659aa3b64c757b8a916434ad95dbcd0c0c0b25cce50df67920fbf4c6f8f479e04dabbe43305adc484747ad854b0f4d145727f1bd2a6191c7f04a73df7cda8410ab8165b97ecf385bfeb63d0f0f9d0714805ea04414834cb529027fe0a75a948d759846594897368e85158acba09807d44f9389bbe9b3adb33e19d74e49e5f5dcf818cdcc341b5210a47f955ac2f8d550a311610ac612b47a9bcf7d4c00ee53237543000642935fdb6cb385de587b146f2b5d9032418a96c6f5c09b42ef1952e33fa4b2d77124f04947a8583f63856a732e1085e6efbb501493def20a2cbfcb1dc1d9562f0a9a27df3bec01d6ed8cc73ab16c0bad113cbe53c610024cd87f16149ff816d6809c0ee50bacde4e1f9cf5847c93d68b2ff08dc61cb53adb3e0e6ff100bfc4c37df29c73b8d3dfe23180dbf3553e46fbb683af6d75402ab29625842913ffeb4f4e9766096dc60b1dbbb0f8a924fc64dd9d7c28403c032d1ea3633e6a48a3e20a739878f9d8bbecb6c5c9ff73186b4a1756b2c3259bed0f3a1df15532ae43202f4f685f63f5d24b33db5969ba008537d32d456b2ef2bf25f7779390367f5f74eca9a804a27bf13a2cc7a7b194d3697ac52c3147536576d8535c7795b5cf5d92d941129f789e456944968181c5df36f55b5bad6edd5be636434e8a0268c816399a312783e53fc18949eb42605a520f3a76731a426f96cec95ec576a62247ffbf67c66fbf0fd6f24c1397ad9fe7311a5a30f86ffbb5bb05771e5b908802ec71b0726965273ac79a39baf11f8485bcfa30be079b87ed288240c5d12a982ac2873e679d8829fa42236c2cf9d8933a9c94e54285e38fa8d9af91c76ab9ea3d6e29e878156a4a95061c1461861f74cf2f309056cb43d4993868ca8714384a98e59a0ba832290f0472a4f73af32ca3cf286b449d974454036b95f9233c235e129a00277da7a4167744e319403a325309054233bcc4152e42302b8be251ae1eeda7da7b0d96c50fda756de320a6fe5754fb756de45cd5f512534d1037702003976cc928a0dca5c7bda2ca06e126a7680796b14cbb2ab1429243aeff2170a30b3956c2f6425345996231ceec628493e56b2ca144d5ea83f0a2278d70f4932daa6ad5d1e73cde9a7f81c68a5c10ea73d9a53301a15499bafc05e9484621c201b3d917c5107f7cef2b40528882123fc47d10b763f0f187fbab45e022985435fcee0b7ec1a0ba34204f334117f52e8c6a0df8087eec1ea27ac1b2bcc0d9b7d8b2f5fe215091f9df4 03de747f07653b95ac3dbea167528c9b53fdf433 57 3845a2e92cd09c00030dc5f2e0c3b183005b06062d2746a179221942b4b36b5f4f3c9e7c2f6f4b740a2c044e7926a668907675fbe3d93ed2b4 +ca4164beb0a82a55b17dd157cb41af0c006115a925614dc155f1958b3d05e091ea67ca76fb45648076f36acc4409d80ae85ba5645b4408ff284f4ab7ac3bffcc320ffc89c32cdf7c8102b796ad09a1590c3d9c9aeadfb94a5668ff5190f1f97ffd26703691f2fdc664fbf2800adfba8c13de7143dc351c7a9819cfc787af5fe1d5601db220e3c6cf31343e5b2323d55969cea63c8e5528000a78134695072b8d1a0a3573a3c90096b6de3e69e87aff101a4dbd44e2aba9542e32bc4ec2736ada49085cbe8bc7a11bd71af2a061913364045b470b541389c289790c61675fa7c3a3e7993683d1b6741a4ac90b624586bec7d001a847a48d6d009c742d14e4dbc915d7628c47e184123044dcd90a3dadf32ff447643fe160f0c015df984bfb9b16271a15720da12c6f09ddac852e10fd8a2a922b09fde3aa09b3eaa38d200d72baf3bdf98cc795c89901fc3e8db87098ee2a8a3625b6dce0ba27aa4e5685647b2bb23eaaac8df2d0ec52631c1f6c0f0e460b6931ae48ae84b93f723cb8b5ed44739f42b29974373a38e1e2e85c144a689300e94c495852718f88bf501d7ff1a4ecfb2e339a25e8ba26c87e9e6287dc2ff39d511011feabaa6af9acdec82906217dc9859f22a404ddd6b033f6958d6a789d5487dd7a0a93203f05abd4438bfdeae40e479cb263c80b484d0a36c92a876ba13d8cfc3e2b4de0ae92b964ae1fb6bafdd4349562b2053595e79644ffbbaa049afff743c2350f8300c4a4e959f3edf4fc0a5d592f1cc774ecbbced263cabac2b5629693d4e17bdcf723c8ac9ba311894ef125969512a2ab334685c056f6a837c55085a33fd388bddb726fa45a6149ff42fe596f3b996cfeeee13eb9598ff0a1c00d8a61acaa892691d64ea356d48f7bf61f77af24b14ac8f5e10f0ac98864b6c3ce2a34352a3dbeea294c8cdbcd03f18c978ea58fb3083cc73b7c3281c0932f1e42d3017c27321351621e56ac8550e1d3605a22b81ee6e5e6a2cc5bdea866e4bd36bfcb30e01fbea9db77e90a4b8f36d9014d286445091845a9fa593107fc33b6b1ed8c794ebc27fe9522ae38ed598c93a37522b72b b66014b4101b41361799baa430078e0e0f37cacfc72977ff4cc03bd1bd982d8060b6a030b6e61a7c1988ba001fc66ccef3a6915018fdf650349f82 34 57e38ef2ba1ba1df2f6543ba9cc1688c725d2c45680ce4b0ae0986dae3dbc4192b94 +d88e350d4d633094c0390aecf8966ccddea41e82a91d7cd2446461ee432c9c18f41df9bd0386f1a5cdebac2e2943d7e2b007631a5d95c50d72e2294036d4935f3e4c0e49cff7e466a4f0dee49f946880b40b29df8c52e68b16c8101ecb4369fd228554c98e39b47538a83c7d71b58ba994689ca4ff627b83d66a013d19d4d56e85b4d1062e7f38b202a5d9e54aa39bbc239d7c8674547ea05edb39a9794005bdb56feec26b627bc56953c065d0e9b40d6f56ca058af97c99746cbba77d4bf258172358ed17441646834faba8aeb852d8635846ccf57520bccf804494f7156348615a0d6c3e4fbb7bcafb275704e5841537ca6410b9ccefcf977681c26f69c056d1fca5e24ebf2f6328215d813672d2126d2860bbec5a3fdda45bbae56fa758f5a8fe6e90a1f8f923dfc31414b10fa9b83de9345ea15c178e7c8025cbfef5d5e766fe16a93ffe0db1ef6ece545b34fe6e475947543737297f9c64e5dec02f13cbc586e9c53181147ea91922d26d819c4e65d0189f0d5ee6e455986a49c875b97f71222ae8580f017fdcfa23384356dc80949b6363b55bc6c1cee2446e42e17adda58cf5f362988a679fa712c5505c37f8834f28a6473c1c8fbbf78c5e97 836cd76f6b0a0c6a7c1071ae97958974cd3b 19 61b65caef6c3f060c327eb7e78874ee8465fe9 +673bbd1fcb4b21cb71a4e275a2506ef89f7884039d2f68423c29c82c24d3d5476308e30d1a7da1fe3c1b5b64d341d56b66a198c3ab59797e7df3bd3636159630b5930067fe68f6cf6e02200d0c177dc81db5317066c06f2c02a8f3e1efbd8c80d16e1f15a41f93face99c9abe23ac87b11eed71dd3c2db20d2d313e685b6ef1bdcf23877716e8c6b0fcf0c90f2e7ad0a87b25d199b8764489d7aa9981a535cc66c84bf11a83777115988be74482d33579ba54f8ff0869789eb785eeb76be5dbd80dae710139fd9276e0d46fb32eb6a031b0d443ccb01aa46faa541c0147ec0cd113b74367f8642cf65e23ca748c6731cd3df122935e549ea7c9c36043316a8eb551777c43a6337dced146eac525152244a510007ce5e9e882642fae4658efc08296db472eca84d3db605e5182c7a1a7f2f8dd132cf13d5b1427ef86faf37ee4d85e260c14fe59d21ff42834af1497618c23735a7a0e72ccf299369467cb1b40d7eeb6e53159f0ba115f501170020d6e782f30542cda2c9b00ee92f2809a7bb9c64a50ba860fb1e8fc41b8898f037259046b484c482cd2078669a78eab83e113076f25f76da6af1b80ab47161db76e2ff8d5d66cbdbcb7252e190345ed19a4619cfcccaaf3f8e82706ff1400bb7dc387f9f8978f2ef05dd397214c9b86944ff2dab4186a55f80a25c7dd820eb6a55a6dbe8cb27c16106942de19d521e32ce70828ba596c4b2962432df44d3df0d9e3eb9f74cbab166906f27b058902ff735acd4f3970a2858372790097cf767efd115e90785f7dff0147cbdff1c8a063e13b16e68fee520a96512ce0d3589b811bacf91b9bd136b5f81c748916eaa76b74abbd910325691d19c6b66d5a1eb8ecd795447a068310d41a6bc971a3b292f11455bb6aad579ebecc1bc9a69151b1746752811ad302f880d024c97e3b5f1bfbfa0009a5aea0c1075370d664e08df66afa5aaf6f2c6edbc1a66a527b12accd00337aa764c2498fc00e559b7623137e160de05e61a8f1bd505f4c8eff5de44501891085097157e3bff26a54db9f457c6 a241274ef127ef83fa938d386e209f10a67540990d47975ae4a8 38 a4980f752fed8127666a2d457cfb599eac0bf400b966822bf410a45e2879f50a34b21f9080f1 +baed26274bb4c998e8f68990f3903575e26f500d09d4a61c097265b3884e4210a35312cb048e901595186227ac9c1e252d150115ac1c090621874eb06c30fadf7b67bc8df2489ffde085ee34af5a128f45ef991f6668527e968c8f62a1e12d02826503126a2f4183d285dba1201cd14df024e2daeb13bd35a07b11a6e3a92708833696e9434a42f7e3ecd600852dfd198ebf7587d8c7f8a0bc9a08044b0f99ea32f2d00292c715f135e573d413689dd04022b8d79864153c0238782e49201d8ff41837f7c959f67e98b4a4d902e2a49dabdb959357883a02fc9a8aab6ca33b6b72 be69df9ae936f7847aabbc9e57fe6c250c4a1f1c2c3c1f4e79e9c7b50b71d7b8640b798a530d80f39d62eda43299ca0b 47 a58dc5b12779589c2092659f9068e0923d473b19bd695c87491e616b0af1d1eaf0888a285600daa305567f703c7cba +ee4c23dba5a950c3ce0e1c1911c55adacdcad5333736341f58790df21a6bed27733508af71a3ff4f0562cd240b5b842c5e82c2705f891b6fbd7ff7325d27221a6488ed7d4f64e8f75a2fe014f74c06b86b0f08c0b0524003dc9027f533ba1ee4d574d18f3e3a36823a5f5e213ff8c9a78d7fe9ceab1594d24aaee23b9341abcb78ffe7ad0c27a25c0be509e3dfa860fa2ad59456e9e47ba16c9363f2b311895d66e6885d1878cb052c6b92b1c316fa5e60445cf627ac491c1a20b6c260898de4c225c893eaa83e292a51d3ffa1aed3f875186731b22f9021b3aed8abe4d60740801507a67889a80d69a3e4c2c7fb0f3ee1fa57eb8beb77ee352dceb5c653be1dd5d27df0c42b2a50f727c034763cbf647e7922f95861e8a599e63071c164b1470ef5ff94c000e4034ecc23517b65935c4786846b1629c73ce0ee928bdda07f4fec41fbb328921c82b08d2a64e890a82eea1cf285e207f53d79a5dd78232b75eb90e2f16d0701257a969a34186a0632a44fb27399a13260c1883555d1f923df 1dd8834198999b803ede0dae272e6e50bcb92a9fe56ffaf578 36 c447bb67a9ba73b899949f29c37355073921c656c913197bb159a281ca46f3319166de15 +be2c3ebb765459933380a05f6aa3a095c2bc5d698da65b56c8f2eb71a8a403101286f65e674345de8898707ceccb71153f5eb4d3549c88b79cac7bbeab0b5d1913d2950e2529354a3c19731f6c75cd7d5d1f8842c9b080eb9a7cb08521c2b17923983ec54ab7f997263ae41e5b40eea6a16128ff9b5eda06766ab03c8e82e6342d39982b864df032e46a02afa0a789e9c254945171150e9131d7cba2d78273958738897d3b655ff99b020f7f774f882ecffa599e1e87e3007ad058d92ae56f3ae235c1e4e80a0e76bf37f55ec523b24dca689c9a7e85596de1eaf2c60336108a82a5b6c392bf4d4706656eac0db29ad5336de9af92012c0c216ef86d95a25b30a9b55114ccbfadc4be8c2fdd112683b5f4c35a004d5991ee5e69c725a614630db7f3bcdb9f24ba8504180cc47da3d3770bb2cbc6d21b5c908913718e6366663ee6ff7a6a940f5a5323209995a2c8329433d0685c108e0281f4d53724bfefc6ebb3fa1b72b0252040cfe10f812340a848c644d80f9f1522 21adaa88212ce94b22d32ae416e9dbd267bb55798a9012 37 7e9346f1eeaab1257ea04856d07db2543c5ea4d2b20fa6f283d8a2b2986b37f5fd114e9f6c +ca76935465db0a4bb6464c169ad0aa1c905366fe3cd6cd0d680ef1a6846fb565a9cd42c219e5f9dbd41ea68e932a422e9e7a849ddd5a879a3a227b9920c39e0c76edaf54dfba26d1e2da5e900f2d7cded00f59be2e5cea960db5709db935e20702ef88491145ebb0f1ca15899956bc875bcb14398eaf6a60742c02ebf92da6956d9c06775cd5ab171145811f413ae3b00238e6770c6d0a9cb72e8d1ae34bd2f91de8cf51b80cc49eb34a7fd9c7027473df3eca9fd4d108984642e7e86c81fe30c3beb237e63aa02923500feba19e42c79e75c53e0efed6ca44c3e54a8ae490b8cfe70c8bc274d500ebec4948736fa6961e858651c2be55ecc2a316acc9430036beaaf71e18454a214e467c521757a60bdfe9a2580b836d78c2ae85d344d3cc829ee01021ce11755910be0bf5b3aed1ef29b51c594fa04809f7c8855c086806f5136dbdd648032140b73e8ca88b9db1f10c2f1d2cee1c07d154519c6fde3a537d9985f2f69de7d5fe5bd9f279d9d474ec784b1bab4efcbd44d3b12ff19b0d479e45632ad1762e39376a4e0158126fb0805677906885a6336d0059503ee4277c82ee72038f0d73474c63a06434ab988153ce66af8a5ebf85841ace1717bd662aee7d4d98b684151ed899de0bc0610dc7bc1b0f5701caebad1e27191170d0ab5bfd5376e9fe1f63daa80b0700d1a94ebca029f7d2ae96db7129737451ac2327051a6125ee2b8f6c72c274b48db0446eac1a84ca166667781d1881b607b1db9842bff9950f416ffa8005a616e1b8a86b32d1fdcff7f29e36b7a229e19639930cef42906fcf76ae8434516c72d7c6359ce3956549437af98b52b6c43430d595f90953d68c9e56d9cd651d582504a3e37dcef65ce9447c4832ae9b3adb56a1d1974522de52b8540e511bcbf331649bb39b18120d740e36455e47bb4da17848b7885a6a149aca89796e0bb9f9c9987aa389fb60e76329ca553a742cdef832e92645f6ba549d4935f4ed53fc92db550c3e44b7f08eb88d192aa691a54e9a56f1a0c44e7bf29a2193eedcee9eb15ec02d3d93484eaeccc7e09a36a1589cdb9642e6807fcc79d81ed7f4a816fe0dc5cd4577e842c683be19c224356cbfd0eb 7f2ce44569909654bdeb3fbeb651614f019a2d0fe3cf36180701036355fb1fcd965c02d97393b257c1d135cdee7c 20 cf4f80131d3f4ab53a76a80a2171cdf2e4e490b1 +6f1fba243b58d431c16a3624487a95309f6c78f8f6da85ab8a541364ab887e48f8e070c9abafcb12094503a554d4f4f2e6d3e74a0399daa742df8d4496e320327dbdab5cc9547895307eab8c82007ee586332f8d36e09357e624a4cde17fdeabee550fea1ce06132f368284720d5663477a89a9d3cfcad42c53428c937a63060376f4fb7f791855b1ee80ff87c4492517c6c70fea7e58761d7ca8cb8d7bd7f0690216e0d4bd44309df93719087f4466e58e0b8ef75a6adb3afa32e0cf52db0e0a53a08991bbfda3bd28cb1bfd6da5e167e9ddde2c393569d45a02993fbf340f94aefbe389bf70550d5c488641cc24bc5a6b33377f9106eb52ae218a2c27ba0db0aa7f41b483a9ba8f686a644b21e9ebcc09983eee530a61b8c3d587508e9a96310910a0759a7f6807fb22b3252021d17923884a94cd6e2df8fa422f96cd93d930132a4207ff7ab64e8fad1b929d2e91af9eae25ea97fba4dfc8e3ebadc3ba6f9cd45d98014d8e2d6ca30a2e163ef99833b0f2166bf0ed831a096709640c4f7ca86d75d4d523626c6dc91aa31c8ddfd342fd9f13b75efd0d406d8c693ad5f7343a82d02433c60e1246c9b9aa12f4e0d17551da75601cb83ae0b308e7cd100825f23c6ecdb342027fc4b5095d12cf70bce1ca87e2b646192794f01fca37d18a2714d2f3bcfa71fffd1374d425b8660286b59a69c440cbb3b6f8daf000967ef6a67905fb38224f588494c67f7224f45e000890262dce19907b85213f10f9dd5f508ace52e7ec2b98254020820a46addf5d3d5dc212562534ce54decdf820d9c478328dafd06c70dd4d77fcc6ff7cbe9f311b47364ad0c9d04886ddebe81990fb623c74a252088c104022ba24fa4966620e66065c934ed2f4f10ade28d8f0adaf9ee3055bfd8427ee580cb0ab2b3ee158d293fcff5b62ea94543128255001c8325907a929638dfb1340afd2cf9fcd96729730b7f43baeefe4320624d5b5282808c51b1ed56a91f13c89ba7920f3824b74482e181f9b20d31119c68b6325c400010244eef0538d9d500094094e99fb392286dad1f26 1171c9e060e4cf3867f0c833baa04d1d8db18184346e77fed1302ac1fa868fc85560c3a4a265d6eeecac67991e 28 23d4c517a128167ea5d44179a53e225de57ee2e0d9eed6f5a993bddd +282f578e382f9b834453d81cd976f477df85d48a901988a08d64363fb5678a4223abf704e6c5cf71c44f843ed404f55d83313be98543bbb06f4bcc2f821478677d842594570f21847a42a65ac836500d59e9acd4f8d42d838f7b0fb8726b56590302982f70434e1b58d7c20dd3f5a1aaa6cbb6b4894fd5db82354e8a95213e92620d852d7de3280adcdf4486821c9d79c1421d5b959e33f8089892f863958effab1fd23ce36bdbb98af050d9cec36fca640399d2df4b311bb21d33146e9d3090157a7955f1d60c2161c90c3080ac4163f0d177118ee956eb398ac185fa4132e8b335bd54ee079b42a31f6e23e20573c7169927b4ae917270442e80c0ce027ea33d2d5d76802ac94ed3f195689010f4d02468300b171fb795da62c4d4d7aa380f4fba19cb8237967ae2045723419256a11b45078ce983aec98646114248934c99f6b14529322a2ed5340157ae7f39bbc4a14b3a83b7c3e1522285a6 c9d7c4cceef7a3ad27ad38f4d91e6ef6201532f10c4ec356d41d3fd51cc099fa63260f3fc9a6c0dc0b66b3d8 35 0ca5751182d0dd65e801dde9684f97bd173241bb009f1963b4c838c27dc1fd9b0f6002 +51203466ea1ae231c105684c46311dce946a507f77475baa28cd5dbd1fc1734d065677a34d2f825b1c29d57526f13ee61ea4d2ce406ff7feb77db62d023ae632116ea2458f3c270cd37c63da3131f0837c0b1db6834dc226cfc75b20f9ee608c383364e857e4bacd8a0cbb12b80f1e0ad02b4d772623b45f57142acf25c0bdc85ca50d484819b72c0b362108060b978f134567db56441344b5eaf6d9700669af40f59cad12444b8c13903de6f667aaea2ea391a260696734f5d9bf934d791aecb3ce75534d977ecfecafd013a0c973da75c7db81f1b0cc27ec784c0e07179fb8db57d164b48d8054eb01e12333f35697b46b2807d098fe2a652379cbb3a0a4b6043a5650bcd2db778d87f7d69d492c0c6092c6170899da27ad73f63d7d12640aa988ecb74ca70039c73ad785bc3360c723d1eb6240d94b4ef00ac6a2bff8ff6a8ecea19972cb3741b88b2847265c857680db9a104f06f35e93f4dc71c49dd2020cf968f677ce35be42d7d5fdc2c6add8f37a3be19190f136e0b7e19ae53f536eb2c103a3e8aef7fac31903fcf4269badce8a9b4e4ca9e0c9eac4915789b2de04431f096eaf8d1f5c667eabfd32cae51740fc784ca1618881f4c6fc6102b7d3d9e151793bf9931cf662f8de0ed0ee21c12a3b9d2b0dce6f14c6238852c725beccf0fc1e42e2f721b046dfac15ccdcdc66000c14f0eab2a40117bf40d047021bc98abd3c2be12c6f884818508ae42748c13e89826efe777cf29a436d497b730eee726ffad0a4245c9eaa91ad36a4aae6c639d7b37b853d02fd28b292d93db0c8e42b7cf27f7b6347e48620352a4fa58d752c21aed982b07ccfffb58ed7cb3a6766c92c337ff1563ece53c6d0048688404a916e23619589be8ff5a86f3d86ae355443ed6993fc0356fdf2c321ce8a5f64a3031bd6137d75db9f415ab0973c55175d8e601e4d3e1a102f79e8ba15cd3e94a92aac4b1255a8f8c3ff7f2160a467e5518cd81d822fff2df8b2e6235aa83841e23de6ef00b5e63b5b428ca6b9a3b3b874b75cdeaf963e308b0c302eff5c74a5c6e92a1e1d4d1d8959a8da7f387c96e2255541fe554190352b8875e0dc9045cbe4a02b7aeb29c5b192c1716466fb343f3ec7645f79debff5c10d50945b26871793cfbc5bcda5a6a2169ebb84f05102f9f252dd4962b3d940cfe7862d37084da3c456c689cdef320ba5cfeca317d1cdc6c58f692e0d14845fd07be16fdee8dacb6b5b3ed814d56a55e7b8e80b1c01131ba9e5a9dfc0e390b62ef7e4c5933066d9a8ce66d28a12ac68aac805ea790259f41e7c29f590af75978fbac82fee6f7e00111f480da47f566d76ad9a60b9052f1b05c42168b079e9beaf51baba2c eb4e7e1f0a210f8fcf56b23196dd9553cb3fdfa552bf128d14e6910c72e24d2f3d45354dad3980 36 1f7a52e12d8d36eeb66e3194021209f57bb0d66a153526603d5ceb93d9b91d0055313f60 +841f103405eda410324161e92b1921127d45f04c61efb97afe8245074a67e28615b07871e4ed1212e7353a831c28d65ea304d6cc7b7ebd577ecb951d988749ff7af2d52d252b7244626bca45d43307d665e54415233d17c7221b7b8040ec01a1ccf35d15bc7073560ea0d9b0e65ecce5ec8520f2d85c8d99cace11347bb46af146e5fc77db2867d14a3d8d8c13b8432e9b88f3e9f90c479d1ea5a8b59876bef9b1666521b0087ab58a0516987fa16992b12b0620d985bbb4a76581ce023624ed0d998f5b91c1dbd2f27b5a44512089c389889d0ad6f148c5a4adb23ba74230017ff72768c358ca9faf65e2b414d9dd7f2119589808fdccb58d2f34e442c0aebb4a3a96b13d26dee99740e8 12017aae9b0f14c2ea23d873d1f0e965a1da782e47317c73b810041192117270bfcc42dec5641c29b6a61d966ceb8ef126b450e988ff120b097af040221c7beb 47 74df73f143eff21646af854e1433e4ca74bf030efeff17b93d2a44a3bd3462a9ce3c0c07281e65ba562c3ff8ebcdc5 +976806b832743477a8d1240277352428df9aedcfe179674b9e6bb876f89f620fc8248292bb5b19586c0379469b38b64c34423e275426b800a75c08edf9846f4653b90d42b7f4c9660bd10f6c1e49a67d07e411a9991e571110e80500a16b999b710b4af83ae946a59b23905097c7b7022af9611ae8b2062f282a1d525069a7a9a7e0b76badd5b253174787547548abf1ad970134a7064304669933638c2cbf1138bbc817e7f3a3a20f21b304a2372125e15ad89940746abe0f2e205598e3dfbd1607310634934fb179f80bee14fe7aaa2bfad9f8578932ff2076372ed33a5933a9936bb51dbc60bf799bee74fc052fd2751df6b74409435e7499ceeb28e2d6310439c2828cdd3319f7c6991c0c26bd0aa42e863303ed25248e804c20736354aebfad4fd96f669527e36b65b4c11c182617195552e721d4a9cdf08ac3bb3d8dcf6aebe53575dac13cfa52f2c3234da0ef7de0d7b1f6f3347861c3131b3013a86d6951875cfb6b9ad9ecf0c9e5f49d020eae9e66e9093e6015289e334fc9345341a996f0793a1d154b949dae94bf40da78f6631354e7690b72211a3cc8f23b18167e8f05bec26a664c1c1ff39ef00881a5566ab0b3f010e7064732ec83de7a3e52116eaedf78b48de9eef4722ede0d6148cd0d4842607a648c88c9256b78be2f74130c63570cf7b9f0d998bf0b4326d652fa733ed4f0ee6657292b7b06cfa7e0892e3406a7c6cea2bb690a448b6265964bf84c07b5d60f107fde3b5323d933abb1b6feecda95e57a832ba749ffbc89da2257d51c457c6744373d2e43a2d565487fc43e0ff4e97fb7085015b65b54b8411890d4306200ed774060d1d4615535a40677569c62b7 3da1ea61a57b4a313acf00f8bf05a7be02 45 aec1667288a19f5f7d73d600217d199649c20b9df1d09aeafc593a3df301ae6f6db08b0bc3526700402478e965 +ea0df4fc050adc54339a6a4fc8eba9348c806bbd94be39a8e2a61c1c117668f5d8d5dc14dcb8923d46b2c45cc88dd5601bc09044909a9b030fccd1a8113636274fab65140fd98c5f2e2128b6558f8855ddcb6e9ae3ff13e0438f1d1994aae3a96757910244a92e5e59e3302f538e274f302d61f409297f98d12270a0b4a54ab0de1e3cbe7949c027c6ffc2745501c5d59d8d6981594a82d699a06d6087f87a8573ce987a4e37d3a604a17e3d52adcd5145ea218f6297557eb94f4c969560a098ffd6d9be8056bbafb87cf793370cdf85a41b0fbcdd5665fbbf170fd43df08d9416243a2fd5b8da248c28c166407ff84d307708051aeecf367f87d3f68e378e161edb2901e830bdce91bfaf90993b1ab7aa372784979e79495205698dcc1ff8553407750c78963d516d82e7747fe5c17774c64088ea092d4f645764574149f7c80379d5a2f1290ca4fb6d7e89483ac805e27b6b77e98423762f175aba5193ab948a0d16222d1f710dbfc151105ecefa80a28b968979d78674d53871e0529c13f2c4a7e90e44a42525deddae479d1d19be6a2ee9cb0a5c6df5d4cd7cb9403b4677e4b05bd0dde7eef136aadcf2bc2a2c21140b2762dc858013894d83f19fa62bcf9e1de289bd3e6ac9dc1b2a42cde74c59386c965b9c3b6c2e6944b280bf3446dcdfd54eea851b92089b4a10256b17664bc3df253eddc20233aac39da7e621479ed448b5343b36faf89d3402a13af92d3548def1a0f395e1725655cf1d1acb6277b9803084339fc3021a835ce2fe26d95ad5b73c615b507d9f36101913aed0a996fdcc1df9182d2ac7d773cffcd67c8a38172263af146b77720cfb34c44253fe4112fa7859ffc436bdaa423a141e4b81b85dcf44479e84821ae76dac1bc032dc8c744278cc2c94aa 5442f96916b9ddda62dd129f1dfe130878b0f5b18c532d1aac8ebd7d13fab935bcbe17f8ed60eca798f1a97f231b5174f9d0cceee1520d1a8afcb64e 23 b3a2d9aff08a07eec8fb25adf62fc034c4ece2709e0bda +c322771a323cdada255ba78f4001317f5b1a7f8442d5fbf5ac3ff6c73351c97605fd871759c5bba3cdaa762c8927628e7e92e3553732f02de84bbf2a2e358dc6cef3c69ffa6a006940fdb5d3e70262762c10890b0d8a6402d5426b9641dca5d0a3dd58061fd0b5e56e4af8d5460ba5ac02fb09c3e7e3a4c568e96c0e202203d1408a08caed86813a6eca47fcf8e063a8fbf8729654a9185db11ab53e5c1b05388953982c4bc7d3cb7d0fff7969cf527207b1a0de4314fd077a9cc3dbf3dcbf57f6f67c4a0bfa95131b25777354e91c1d364af9d530a1fa708592c8124fe3e5cac36038ebb3e1bb3007722019ef24a268b5beb8c219a0a7d3dbe1637983c9dbda1a9069e7327a2232444da0d1fa43563666e461f7e071b46a3fb63d03f06bc37bd000f95f894f5744bc685a8540f1bb79c5815c958da907e285da4475883ed45a724ba0f012e92aa243e602ae5bd2aca62f11fba28849e2d902490b9c06435152035292acc2eb5a1c42183e9bf2b841bf3f6a14d28505a00aa7d774a98f32a0efa8ccef6d7d665fe43dc7bb0804d311bb249ad36a99284b07da0b87732f8edd0984f26f00ac5c47b79b9b25785f0732c44b3aa2c0a807632c6ae82d1c5bf54eb6fa2de9dfb14698fd3bd1f3bc70c39ed828927911d4edfaf8376f1d7fd478137197fc767d55908b7f9b77353a28366b2d8e36e50c78b67b6a8a26485841c55f4e4f7a3a08b2e01825f496f1323768df11e5ba24b53198cb111ec2b2958a37bbafd43388a4ee92c0b74bccd18a05ee9a792b770d78b48b86b53384225bd7cccd43ae0274c0799a1c4938c8004b3c64c1f973c56909b7a68e4cab43fb6f2b0e50ae8c087b3d9c946e8806ec3dc97b92d15927e33f679387158975416a07f4b46dc9ff0d 578dd0d2283c3220362020daf997f42f6b6916cf6992afe37c24f7d028630f34 25 0b8154810adfa1b54301aa8a5715338fca2566f3da744fc935 +df48b4b5d87bad798b4e85038fe367fb81fc06f05ff0b4e032cc8bc87e703a708934da0f870323b54226bec315010ea913043cbe809f599d0dd98a25c242a721a7f99ca2effb71b4d6388228c5c95993740efa852ca9d7705fe4fa325574c7a13eb0ac954569d7763bb29c16985820b1f45971eb46477ca20429b9d32854755e8e47f7c312e67904d9b28f9faef660acad26cb6d470dbe1306198ea9ff04a645a3a63ef2532f64889e80ad80f668769e2ee8620aebfdef8a75aa0b98785d0486859de6851ed7887380e7010c99f64750face7543c840a4efa7c6425e38ed1c7259b1632f2ef5f3d3568351ee06fc423e31cf9439d71e71c9bc19fd7765eccf3f1dc3ea6f891ac7cbc31f180133a0fba81adf8fd4ee050ca2ee486d786504bb1806955be0c9a7fd4dd4aefec217ef904cdd6dabf28be3c953fdbc2646eb327f003c966e70c5c36f97db1e7ecb985017d3c07053ba308aa48ea1bfb9347f00e74ba0c7b1bdcb33509ae195870658e96033914e7668eff5c36e164b632dffa83e7dd9e46042d924bec58f0fdcceab3994e39ed8b0 5465ff41bafd082950ac93a444f13c40e1c02191f6aa3c9a6ecd89ea55491d1c2251372e90d857 20 6c78d55f0f9d24c2877ec0b4bf55df224ac11830 +74fa10636b1d6eb513c329c0fc09aa0301e8bc103a3bad111c5a1f17892d470bf9e3227eba841defd5becf122b7a9dbe68863344c5c55ea09ad437806f8a1d2f0d75c9cca88238ae74b5e2a73fa6ee2367f977a43eb5e0dd4b87f69d3d30906c19f4d83b4c5094cb14bce277c10d24bf44956ab1a9526e608ba76932e1d3a44b0834ebc63064af0890c9ecee256a5a6cfca8d9f8c93fa091ae0d0a2cd77b97e43ae2bdedce9112a62145a491356946d64629b3af8aa925e35ece4865f49421e633a2c55de0cce903c57859573d238f2ce46fd62e0375aa467b973999ddb3f7fdb7858288488d702a01205198cedbef62f0dc030327805079f7d195dbfbe9966d4c76e971b77951f392b570fa686fc631bf5f1d176917339e7451cf0f43f2936db382e8bbab3a7b85fc4b5b6233549e01c10cc0b6774c15922642adbbfd0fbbd1e197f8364422906650fecbc2b38adc7f6471ef31edc1dd182af3ebb19f95c8e035ecb2f5c8ac85a3b1f10dbe19e3aee7bd748c2d393a1313b3af39c44ea8d238b8e2d8601ed36201cb5203d7085099812072494adfa539f86d613e2676bce40447d658ccc58035d0ac90ba7677acd32d4b0222df2ff8fb7d3250f4ea594c04d62f1fd8c9c962bca100f09e6f2e10ecdb95b41674fbe0efb77e18784d61dd845a78d75bac28b2bdcb058a6add3145e2db406670456cc1eed22b263ceffc0ef349dd2fa6198bde19109a3e46c88589d64aa8caf43d4017e737e292e89b0dd9050c7bb5589d87e3bbade901c33a7d30e56606b207df1df1d037d062883c82c439ca77446c0a3fe7c2b090ff3f99fa48cbf1b2cd0a372a6f7b175cd425b19f66b5819fc0a32b23a255f01ed5c6fec34d04e9ec8fb3c918807d9f5d5e3664aefb5882252d3aa1feeaf53e4c28faa826a15088ce8a2296e5a96b3380acf21ce0e29f 0c4285dc588074c1e2810439b53f21bcf9fb8f75b16933bce6a63e0528c5301372 32 7f9fdd506f702157e6bc3011df62c48e876216d2d1c94fb327aafc68d2b17401 +3429dee22edc69507562e52f8a6a5eb8ce137deb87959f9ee1a7b4dd88dd6034d80aa10fdb18aecff60f4e565a3fa47bc78633403a443f625ff2f06e5c7c1d2cdf3541fa6c4819e66b7eba1aa84ee84a8afe7d439a562cfaa05b43fc21e639a76b2221b593a9d53f94959f1e25312b6244aa0ad286a7a24a56e7f920cf0cdc198a3c560836e6704a45ad54792c4e19bb625d736e9639d400307c1e94ca7c2dae581a8a3c91973351228c566252ad672f95bdfcbd6f5bfc2147c743090fde71fd1b5f938f70da444be5ce3a6cdd27e49d27ef49a7bf3734274a809bdffefd994e61baec5b896957c575bb03c1f730f309ae87e94d900ffad05f9bbdfd581ac10ee25965d79a4fac996ff08a1c55e2e9544001bf411d661cbdea0ec2277938bc19e2bad94461b8e431b7a9efd3775e66dc27ec7a3b661b95ca0069c30e348f54945c0c7d0a4743e7bb09dd45714e38ef2cff2a70492c458192282281a218ec2102213822315b72f5aeaa42f137906d2f1d8633d27cbae0d6d666d3e93e24beeac61c1e85a0d3383caab79b129c6739dd4e05fddf5e97381ef6d095c595d7390ad660060276c0f2005c669cc859150c526d6e059bbecbd4b3ca5ac9d2bf7fc650e14c9c64f96c7a242988960fcd15ce3aa9ed9af47e80219173a6ffa4b737309eb8420d53c9970728d05529ca7d6f08e8f2752e8959fd82d7bf4e62741023984d3b874911b93a88c41809777beb51136c115836e6ff321c4eab70644425a51e088d4b6c6d8b834c666c89359b40e84d25304f4165e13b63ae6658a3985302d3981d 6ab870977103b1ae1a7d7b5f597b22f92a549bdc9e3d6d19226283985f9cf5afc76fb0dbf94660f84161ddbb9c8dc464b3d53c973a3d73a9fa026832477d 35 93fc10fd2421bc89fe982637c3651aa03b73e7f32bc04d2a7b2ee2067d2dbbe3879132 +67fb5006d67c4538cced5433cc4b0875a89109e53c78e905c8fe292a2c7aae5d7c6562500ad610fe1387fcfbfea3b098b651121c5293be0d3ee9e0177f09832935f43a27701b5ad416fe60b1b9ecc071006c3d5370b7b5a9f9ffc6cb1516a1353d3eeb9840ec150d8cd2d0ca2859ad97ded65339eaaeaf480b7262c4647deb46403b4d049a7398e4b4900e16c4309b55c7402fe6ed5e2158ea1b15ba8ca7395a61647c4ec8e39a0fca56a3c58d01398d2ab21c1df7287f2cd91cb79a2ccf3a51c03465a6192dd40cad44d8bc3b7d75ebbe570aefcac3e3efa5188ac939c56410eda393d27c327651e593e359434ed663ca624d73acb9717f3f2a155b148989c52a6248b4a3965f5aca1670faff4531df17c10357cded839e4e2280fddb565a1248e3b66709394b1b12b23c31a17de09167645dc620224c1fbbd0d0a2114b9edfa5d828a4011470b417511886c383fd9a50d7900b07144b24c0fa6c25b4d313b7073b779e8a01a58c380b1824ea7056eabd1d2b7ecda778ce22b6cede91ca0ca718a2d386fd2389d77b6a0912304bec268cf34ad64706c797e38778826ccfda663343c657a758452aba0c37a979089b3094edf74f4a0d40c87e153b1af4bcd0e47be0948cffe9dfb7c3e8c9e9c53deae8f693475a3061a8e61a93104c69e02682d3d42a3f133ab7171b9e064deaf6e555bbc012b464b0d89fede6d50467ed11ab67ab5385f7786934fa126aff93c60d7f0ac9dbea5c58ed336b699bbb7060a3d6b23d15dfb62b141848574588ef3a984a9491341816576836f1e65824b416b1661938d7a932f1c0d395cda8d746425261d5eefe684d764941a01421c7dd5ab425209a641c82076ccc3781923b17ece83d173f6d3e4a767ed1dbe7ca91c2b10d031c98c2d5ce70ac6c3fd774fc0bf1b7f68167eb48f64a6cb3ff556020aea98de288ffd5797a7a9ddfa09dea7f2cbf337789e9786785333180f4fd68bc331dc790754a4a68dfaa03521ae7c6eae84a941db4135f62b6d8d6fcff555a4c8f44b425855ccef313a9ff9fa74b508dacd77e8f3e33f858e4c46ec0014e4e9a9b364c6cab822bb4df44393f27e67a668078cc00a4a8b888bbc0979b0651ac92f06d74ead33abd29f0fbddcbf33d1cf8c1cdf8a964c658b2d1ea8986e0e9ff8c1adff4626506af7609d1ab9812b1a4ef1d94738a6ece2e6c1641dba5b0640545a225d7f500e6e2df8f7dbaa316159fba954580a5cd15fc9dfc4d12e3952c01130781cb75fd46074cc713d941adcbfd7ad952414f5fb1dcc50368c52385f527b5c8d95a419db16806f2db00df6f 7fdedab66fcaf3da000cac4bd77a8896fcf2b9f32311582d11965c03 17 3ea34686b4989f5f09fbab010ca1d39324 +b862d0a53afcab1fc4ee7eafc30cd29cd9a2251990a19f0856dc73d4a308f2c6e1e785127bd203802b83e26b4aa61c4dbaa26d75e1ced03b166ed108b301eb3287bd33a1adf7c99ccfab2d5c8c9fece75ed46ce471a0a33ad01aa986f583373d91a2bc021c4bd23583ddf738359eefb351388319d43223c6edfa2fa8cbc40761a307766cce221e2e43d91efeb6371e5b905b7b34250c9ccc38c8b62297f2228c72906c0b896d06e1e02384e3f719327fee3e8cfc4d319edcc0d9dc3544488a891aef03b7a43da0b8f2a5a61b4e51fec34150313d1fe83975ef48b303e26ec83a364b8a3a6c03e1 d0174fd37f069c515b539b7a6a805317010b808d 62 ffdeafa93e39b2018231bd28d605460d4a87066795479a6223040c279b452d642fc78d582d45ef57a6daab7d28d592dda09f9fb741be73aa0cf892fa0a4d +516f44294f8e78ad6cdbb35cb7d13bb21cd54b089a9e33628e32093387fecdcf649bf1ed21d7c9093b1214e681adc7bf975262daff15765aad847053b803db2b54f35a282469ff43adf148993da681b17c6aa046af37110b8f6361bc1017a2f6e19946c739288d80779b5f183e052b0bc29417171384a175989bb2f2f89a07f09703d3f7dc2c0f61d00742e87136a0ba20dddb50e4dc358fb1268821dd617ef39f842caf47eac3efcf5a2affd6bfb8a7a1b863f02141bf2c60817f84adc8fd6c06b3ed2874107c4eb9b5b55d024a65a286b35a33582c2e318d79a05993dfc916fa2b0a870ddd6e6c110bea4c3224e0e4270ae68dda2f277a722b88b26fcb7d94cc9f13fda3d0402e6a4f84318b74c8b407c1468f88da2c549a10edd82bd6168c3226853b59833159ab4de1f75071f3b826cc1354b74a5c6ae1f35afe2b9f04b1ad90d0b6500b06077dbd033ef7b51200a1202db6e6f2444bc6b2afa4d31fc9ab25fe97af5c408c7f0b10bbb75848c538576d4e00fff9766f9107320064056bbb11f4919aeb50db44b97ff783779db77d6deb961d3822fa940f4216deb6ff8fdef9f59b9e253988de84a27f36b0aa861b0ff5460049a3132114b996e9a1e0b45e90068a1f5f7a86542e176b7be36f80c7065f58f5ba0c63adb58e7793ad122ca871042f56ffe765968d3a46a54d329c2a84a517af3d8827af26690f70730e9ba6441cb928328dda13fb8b7127c74f8970d5ec493ec9265950af8816f04e91c97cf19159f29dd334e70b75cde462bbabb9ebc7846a64a87c29f03f06aa62b948554653c13ae8742c6afed83b16e1286e3a4f1c9e8a106e3524bd0d5031dd960b0176276371cfb89e555a6ff835ae3b9eea67dca59a7e207fd05a573a134407c6ec1ef4f6cdbc9bc7ffac261131320015d51edbae4cbc68a5a3b1eeab2af465504ae58ef38c0683cf910f8e2c76f46c2c86a3fa1589fcf443560d4a5a3717b8f300a73a4948abbd7f92cf4ab43bbad4aae52b05cc8cffc3e0e512349fdcde99c75f58f2d4c77831c5b1cfd3ab2d7028f973bf03a8c0c73f82d7375d629334b4b58e061e9938a42748af1f509d14faee14c163a164b16b21fa9a9cd378fc60c10c6490be4395c5c832a9f30178b47fd5b596c31f4b866b8ca43eac98c78c12994450da3f21ad837fba3ef130838ec952cc48a1b13fd8f563b7498f43bbc2818964715489ee557fa729e2765c118363f088f34d7ed0a3454729deca7729b27637c91b19fa2bb9ac1c2cec9bc31e103a63b66bbebbedb524701e47f6063a205a84610aaeba89a95e5824684ab3 cfa2b964d97b2c3166e787355663a0cf513855971e52f4c827453f1dda8f76107b68bbcecd5367f5d080e39ecb69457c81d00f 50 23f229a9ce5e1a6491905baac4188cf7a042ecc4801ee49bf2070a9385f8a84d47595975f5023bc82e258c7f26fb2a6f6949 +eddaa3cea7f3738b1162b8943efc03fe9538505fdaa39babfaefb0734f4755e80f1c05dff8ed933d1aceec9f6783fb3b1bc216945435396728db74c2874e0d636c23326bddb67daf07d2ca86ec747731c0f26ef6f20117e7413e2653b3facee7cc625d8af2f2155f141d2f7e37a55bf7b9ba6fff385e31eee07aba2309f307c863c6b5a2f264a4fe228328936af30a4963bb5b54ca6efa7a17f3593411bc39936aa264a961b9e789c8ae277d1cc44dcae0d40e08827cc55fffeefff75e8fd9cba1503a519805b54705698bd333caa3f79f3c72481ea89deb3589276223bf6e6f2e5c55cb234beba0b9cfac76b299fcc2f2819aa0020d9f4cc3190e0167b83d6f0677eaad6613d6c28df44e03de15ad284c49cb9792c95d39b04aa0498b509ebd1fe17a5492be0d71a34f32a118aa9685d7f09951aab91b469aa384aba8d41f47beedd94d83597b2962a416915c34337bfe96ec5d2fef59bd718a3c311659f8decad75b2eda7e21f5c4d7a6afa531b4c3a10802bdcb231ce1bd26207c6b70adc6075ec4cabfe43262466527a35cca232b6a58402e4080786a2381568e21cbf9761ccd13e9f611db6c1872919abc317b6034b2264becbd1a5966533838e8ec956c2e177b63bd3ec3a7909a4f2fb7438293db8ae706a6d91a412064062549ea791977d2dbe7c9234dcf296c0bead8803af78d4cc1d69f629cb09ca5b066a63d02a17b9ddb71ea8dd93033bfdea9215b6570b0c5f051fa1c0a691e36d8b76b3533104a77cebcf9a94ae539e6a7e59cc039200f441881be5234bd891f257fdf238e0a011c1cafc99dbbc3ece236a46dfd1ea469ec140dbfcfa214f80b345c5430f915ed5beefe57c4270eef55f64847c4800e877ffd79021aba48f2d957fbf7a99cd7bb5a38e662543a42f22f2a5fecc4054d90876faa6b2ee928f90b8e64d58a84256efa6c73c345941e69fffd8ae444092625b5eb5fc2388ee36e668d9cc6cf072d75508c2b296bff8b5e9271bad0b24ae6aecb70c2e613271e7e0e28f411d72dccbe9d58c2f8292815008688ee97aca2eff4dab5f8e42b5572b39fba266f2c58b253c3eb2045c3ca9de4835e078a567ecf6b752c989b583afcec452bc0097b 6a489a2286c35668a0826c3d8f00e5927a9738b49b40fd01db5bbac7459744cd60563bce831da60e31e46388700b105cc1d3c4169439ac 55 aca5479fc26412a105ef58500ea9ea954271ae4c15acf730dca7f3a7ea2b41e0719731c64bda1500ec0039b10c620701f34bac7fa6800a +9c5b8df1d06464933b82f55f92da5641dc37bde4d58821595875ff42a6627f8c675486fadf26a5ee31c92859e87259312b20d3a08ded1e8dd4f7e06772d0266e7684ec70e144d211602ea971e9a2c06ccf6c2e084d22689976b5b878ebb42bb7a33714d16048fb7dc8b80aced56edf294de70a64fa8fefbf7bc6ff55e3d73a21cc12dc5062b7950c40a9be0a42b30b3a4b37dc818f754caf1dfd32268cc2c57c7e9c84066461d5dda10514c9386ae89da411cd60bf7eb67a3e803b9a7f6a5ad822679f5602cd271b5abe290d996124477162adf1dcbd6c96a94d3cdc72985c84df23a2486bcd603fc95d017b4d4b0d8c2dfeaa84bb44cd2e2f9b1baacfa3fb99b50d62fe1673a5678c2762108095a2161982c7badd8812b22176175d9b9c970b99abc984ebb34a31cdd04e6a8f3b3f536c68b62333792ab57a368d1c5efd107bb66e89108a032022af22d93497df68583e1c16a7ac8dc3fef80830aebf3cb3e33f5c9450e769368fd12bdd320144066b7d2a5ef8a5c92f902aa8e24673c7a0f9913735f47b42efd7a9d1d1aa7c34ff68bf43ac1f824afef384233b38edf1aca2459db89fe30438912d79b6e53824e01cca878c3b2e2ed2c1765c7d03d9f3b5c50f396ccc1c63e6f59534f5f617f187ab19b8e9ebfccfcc196bf7e47e54417e1bd937c274e9922a2f5aa183c39968227eb1842572742063c2c04cbace98e642554b81d308ed9db126648601335fc93bb430b2540dd974c539e8ad852497c4f3c70fe4c1d1025471e2e2c1a246edd1b4fd409a72967476722b2f6274cbc5a40e59dd31757cc687036ee3ee9e727b54cff52901edbca4e7ab2ed1f79fc6006d5a030b7768d9f13f1b2df0f464cecc70958157ebac52375c360f80e35a73d05369653f6f71fdb5c65fe815ddf6401005a2e6110400f7b22576da05529f6054240cc9f9bac8c73ff22e738f161c8b37de3e1b8d0e793b9bc62643355f99915bcf7aaa7e7f5a14bfcb8dc74f68f8693f78892551948f1e76bedcacd96896fed4cfe960ffccaf6dd5a97b4ca7227d14362de7fa1c964850bb0d2cf0ee2b3c6284c0f21812a03248892390ab5cafcf5236ddad7a4aa69bdcf19e5476e2 ee0d8246f2b4a3b9a78a79a1527a69f396cf7794840c9b0adf 19 2585d7d7e322823b0fe8732edff200ddc8c145 +47673827adfa4d28a73200286a53e4f2ca3719f8f1813358d007070a8e95c0cf3db63733329754c5a2654340501e12fb4d77db5085ab6cff88dd60b0d7144c9d412c843e75db47c37181af39d3ca8dfaeba4864d05402624dfd6de4f44b0e6e90971fc93388854dfc26d8246ea8d8f7cd07815f366bdf2d1c8eb4c9040bfb567a4eb56b3bd71fce6901337eb1bf09b173d88ae62a29e0466e01b719a1854dbaeff1ef34fbce17faab46350561d22229d7186629760db8adcaa2168a7dc42f0d540d08edb25cf943c094c0e0c31230ae0bb20d17c7b01b53664ef8737ebd52c335eaa6f8041f57a041480bc1c5cd5f761bb5998c78a98356ac1711a572a6836e613be225b3318c0707cfb39e836e394f24c24208beedf0a485f5fcede45c469db1431fee5aeeefb6cb889156807e5da5450c48ae37dcfaec6fe17475502c85ec9d577715c268843192bf18e80b64062445fe0f2c9044b53750815d0cea796c3dfc2f98f4f3867a402dd9537603074685472c3ac0849e0cef81d5674a5428857207fb391198094108c2df34cf2009e8c208fc4682474ad8185c298719f9d4a8dc7afcd1e46cf7da0aac79b1286c00c756a40d481e62b3ce6c969054640994be5a67b8558e7f178c10c321158b1ac0135dfd0964b484a6a3b69f430164686df401732e4f8725673886a489a74a3a09836e53411f59021b8b2d739a2cef46f624b02b44f8e8df35448dc1a42fa98e9b1a699a0927e26e4701e3c3efe0a7797f33c4168f3e3a18b360ecaeac60f8a1fc83ca88376d81c9ca9395252f085d8be3e825250b82452afad0afa8732ad9ef9140666b8c358358000e87f5793de6847b3c72fd3b96538eb26a54ac21cb2de6967d382c741d3a4cdfbaa61948805fe529621007f4bce07f7b455bc2577c2ed9d8c7279b0d5e2d7e8292d15bd47764d21285306b64b95e579d3400cd1e4500ee7eeb17c164183305cf094206b747fd71319d9a9dca1b22e4ea05c1366b1b4c9ce3b5c3cbfa08b19b3caf1a8552893e6ed73a0b462af044f4e9c91d106c6a8806baf716b6b49692e681643f0b350776ce501a3e3d98662b30a32b5ca570835467d3907d57f61d67b18873951af919b9dc73102ab19c513ad2ed11ab21b3e3a42dd7395e251135ba5fac646d656eee42251e364635936596faea0059623948c2302e0b34e7039fe9859187e151675b1b2371cdbc766aa5b273a37c8c0f28c30fa0a2eaa2b8f7b6668d830c291f661c29fe6169e73eb3843cf42886a45afa21ffa2465da71efb67859dcf264a0194ce4302899ca2bb6f3bba5b1e9f2ffdfd2afdc01f135c295b67c1ec53c080d6b66 d73d88c2fba99dfdf17382e1da7ed13b59606c223b72b895600b23ef 58 a162c44d5d2d5772f5bff39184393092401ddae3105e47fc4f40b41db1f8e36a4c33f67f0e9b34a29207cb23edefa60f0b01299e68b4ef15c790 +c8baeb0c1df3005521157b7a77040a45facdcf0a790169bd2f01be60b0fe206f50aee0e2f1b447362067be6d51058fcd1395b66dab079195fbb4442330425792b559a0b99c127788cb992c1f25f7b9f8ceef5a274c47a8cb29849fb2d646f55ec8f362dda4096c1c566ffca1fd4be00949f6ec7efe7cf090cdc05248cfc02045d736fd2f07d4e6bfa903779c44527a338b570c2745a23c96cc438d990dad7d20b7fb24f2a4671ebe627a74142e852de0fb95830b1e20b1e9777bfe994b84ed958ec92a49e8af5dd54c11485aa2fc9103e6eb7f3a4650f1c8202d2d709b632f1347e31139bd0b89af969cd7dd7ecfcc4fec4fea6cb9e056a8728ee83e6433e3c15433e687703dac8f03d66e79396bedb77e44fadc21d171d779a7da2edb823a754c70c89af08e35a30930857f2a8efbc925868dc2f183dd72f89491f1f03754d175c4690f63b0ab5fdc6556131587899875b8f0bc6127179f8800018a53edc60542d5512eed66bd1028d3d0386b8d85690437f03444df72 7696795d159ca50b2140461c8cfba69552541f5ff9 23 8d7f4c1b08ee0c258b2911baf2534d902ef074496abc04 \ No newline at end of file diff --git a/papers/leanimt/README.md b/papers/leanimt/README.md index 928f46629..ba92f392a 100644 --- a/papers/leanimt/README.md +++ b/papers/leanimt/README.md @@ -1,6 +1,6 @@ # LeanIMT Paper -This folder contains the LeanIMT Paper. +This folder contains the LeanIMT Paper ([Download PDF](https://github.com/privacy-scaling-explorations/zk-kit/raw/main/papers/leanimt/paper/leanimt-paper.pdf)). ## Related work diff --git a/yarn.lock b/yarn.lock index 13f9ee550..37ee5dfcc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -87,7 +87,17 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.24.2, @babel/code-frame@npm:^7.24.7": +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13": + version: 7.24.6 + resolution: "@babel/code-frame@npm:7.24.6" + dependencies: + "@babel/highlight": "npm:^7.24.6" + picocolors: "npm:^1.0.0" + checksum: 10/e9b70af2a9c7c734ac36c2e6e1da640a6e0a483bfba7cf620226a1226a2e6d64961324b02d786e06ce72f0aa329e190dfc49128367a2368b69e2219ffddcdcc5 + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.24.2, @babel/code-frame@npm:^7.24.7": version: 7.24.7 resolution: "@babel/code-frame@npm:7.24.7" dependencies: @@ -200,6 +210,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.24.6": + version: 7.24.6 + resolution: "@babel/helper-validator-identifier@npm:7.24.6" + checksum: 10/7e725ef0684291ca3306d5174a5d1cd9072ad58ba444cfa50aaf92a5c59dd723fa15031733ac598bb6b066cb62c2472e14cd82325522348977a72e99aa21b97a + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.24.7": version: 7.24.7 resolution: "@babel/helper-validator-identifier@npm:7.24.7" @@ -224,6 +241,18 @@ __metadata: languageName: node linkType: hard +"@babel/highlight@npm:^7.24.6": + version: 7.24.6 + resolution: "@babel/highlight@npm:7.24.6" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.24.6" + chalk: "npm:^2.4.2" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.0.0" + checksum: 10/e11cd39ceb01c9b5e4f2684a45caefe7b2d7bb74997c30922e6b4063a6f16aff88356091350f0af01f044e1a198579a6b5c4161a84d0a6090e63a41167569daf + languageName: node + linkType: hard + "@babel/highlight@npm:^7.24.7": version: 7.24.7 resolution: "@babel/highlight@npm:7.24.7" @@ -1590,6 +1619,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.4.15": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: 10/89960ac087781b961ad918978975bcdf2051cd1741880469783c42de64239703eab9db5230d776d8e6a09d73bb5e4cb964e07d93ee6e2e7aea5a7d726e865c09 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:0.3.9": version: 0.3.9 resolution: "@jridgewell/trace-mapping@npm:0.3.9" @@ -2664,11 +2700,11 @@ __metadata: linkType: hard "@types/node@npm:*": - version: 22.5.5 - resolution: "@types/node@npm:22.5.5" + version: 20.14.0 + resolution: "@types/node@npm:20.14.0" dependencies: - undici-types: "npm:~6.19.2" - checksum: 10/172d02c8e6d921699edcf559c28b3805616bd6481af1b3cb0299f89ad9a6f33b71050434c06ce7b503166054a26275344187c443f99f745d0b12601372452f19 + undici-types: "npm:~5.26.4" + checksum: 10/49b332fbf8aee4dc4f61cc1f1f6e130632510f795dd7b274e55894516feaf4bec8a3d13ea764e2443e340a64ce9bbeb006d14513bf6ccdd4f21161eccc7f311e languageName: node linkType: hard @@ -3056,10 +3092,11 @@ __metadata: "@rollup/plugin-typescript": "npm:^11.1.6" "@zk-kit/baby-jubjub": "npm:1.0.3" "@zk-kit/utils": "npm:1.2.1" + blakejs: "npm:^1.2.1" buffer: "npm:6.0.3" circomlibjs: "npm:0.0.8" ffjavascript: "npm:0.2.38" - poseidon-lite: "npm:0.2.0" + poseidon-lite: "npm:0.3.0" rimraf: "npm:^5.0.5" rollup: "npm:^4.12.0" rollup-plugin-cleanup: "npm:^3.2.1" @@ -3290,7 +3327,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.11.0, acorn@npm:^8.11.3, acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": +"acorn@npm:^8.11.0": version: 8.12.1 resolution: "acorn@npm:8.12.1" bin: @@ -3299,6 +3336,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.11.3, acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.11.3 + resolution: "acorn@npm:8.11.3" + bin: + acorn: bin/acorn + checksum: 10/b688e7e3c64d9bfb17b596e1b35e4da9d50553713b3b3630cf5690f2b023a84eac90c56851e6912b483fe60e8b4ea28b254c07e92f17ef83d72d78745a8352dd + languageName: node + linkType: hard + "adm-zip@npm:^0.4.16": version: 0.4.16 resolution: "adm-zip@npm:0.4.16" @@ -4065,7 +4111,7 @@ __metadata: languageName: node linkType: hard -"blakejs@npm:^1.1.0": +"blakejs@npm:^1.1.0, blakejs@npm:^1.2.1": version: 1.2.1 resolution: "blakejs@npm:1.2.1" checksum: 10/0638b1bd058b21892633929c43005aa6a4cc4b2ac5b338a146c3c076622f1b360795bd7a4d1f077c9b01863ed2df0c1504a81c5b520d164179120434847e6cd7 @@ -5699,15 +5745,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:~4.3.6": - version: 4.3.7 - resolution: "debug@npm:4.3.7" +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": + version: 4.3.5 + resolution: "debug@npm:4.3.5" dependencies: - ms: "npm:^2.1.3" + ms: "npm:2.1.2" peerDependenciesMeta: supports-color: optional: true - checksum: 10/71168908b9a78227ab29d5d25fe03c5867750e31ce24bf2c44a86efc5af041758bb56569b0a3d48a9b5344c00a24a777e6f4100ed6dfd9534a42c1dde285125a + checksum: 10/cb6eab424c410e07813ca1392888589972ce9a32b8829c6508f5e1f25f3c3e70a76731610ae55b4bbe58d1a2fffa1424b30e97fa8d394e49cd2656a9643aedd2 languageName: node linkType: hard @@ -5732,6 +5778,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.3.5, debug@npm:~4.3.6": + version: 4.3.7 + resolution: "debug@npm:4.3.7" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10/71168908b9a78227ab29d5d25fe03c5867750e31ce24bf2c44a86efc5af041758bb56569b0a3d48a9b5344c00a24a777e6f4100ed6dfd9534a42c1dde285125a + languageName: node + linkType: hard + "decamelize-keys@npm:^1.1.0": version: 1.1.1 resolution: "decamelize-keys@npm:1.1.1" @@ -11172,7 +11230,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.10, magic-string@npm:^0.30.3": +"magic-string@npm:^0.30.10": version: 0.30.11 resolution: "magic-string@npm:0.30.11" dependencies: @@ -11181,6 +11239,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.3": + version: 0.30.10 + resolution: "magic-string@npm:0.30.10" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.4.15" + checksum: 10/9f8bf6363a14c98a9d9f32ef833b194702a5c98fb931b05ac511b76f0b06fd30ed92beda6ca3261d2d52d21e39e891ef1136fbd032023f6cbb02d0b7d5767201 + languageName: node + linkType: hard + "make-dir@npm:^4.0.0": version: 4.0.0 resolution: "make-dir@npm:4.0.0" @@ -12778,10 +12845,10 @@ __metadata: languageName: node linkType: hard -"poseidon-lite@npm:0.2.0": - version: 0.2.0 - resolution: "poseidon-lite@npm:0.2.0" - checksum: 10/63c7668b480ee3d57aaca0eda7e56d563ab2bfcc40bbce0e4bccdc9deed4c0d68255749356e328b622ce8715b1f1ba689fe1a86ca78eb1056a51a18daa252ee1 +"poseidon-lite@npm:0.3.0": + version: 0.3.0 + resolution: "poseidon-lite@npm:0.3.0" + checksum: 10/1e7294f7fed91e1cdc3aee7bd0380461bfdba74ba34d100c2fc4e3d5434d09af0644f6c889b749b9511fd3867216a1aa6d575f070b716c6756b1f56c0067b71d languageName: node linkType: hard @@ -12934,7 +13001,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.13.0, qs@npm:^6.5.2": +"qs@npm:6.13.0": version: 6.13.0 resolution: "qs@npm:6.13.0" dependencies: @@ -12943,6 +13010,15 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.5.2": + version: 6.12.1 + resolution: "qs@npm:6.12.1" + dependencies: + side-channel: "npm:^1.0.6" + checksum: 10/035bcad2a1ab0175bac7a74c904c15913bdac252834149ccff988c93a51de02642fe7be10e43058ba4dc4094bb28ce9b59d12b9e91d40997f445cfde3ecc1c29 + languageName: node + linkType: hard + "qs@npm:~6.5.2": version: 6.5.3 resolution: "qs@npm:6.5.3" @@ -15472,6 +15548,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 10/0097779d94bc0fd26f0418b3a05472410408877279141ded2bd449167be1aed7ea5b76f756562cb3586a07f251b90799bab22d9019ceba49c037c76445f7cddd + languageName: node + linkType: hard + "undici-types@npm:~6.19.2": version: 6.19.8 resolution: "undici-types@npm:6.19.8"