From 3a1611a92ebab548dd10fb5e34f0b890ac2b109e Mon Sep 17 00:00:00 2001 From: rob thijssen Date: Tue, 15 Sep 2026 14:14:34 +0300 Subject: [PATCH] feat: add @quantus/codec, driving encode and decode from runtime metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The extension has to build a signing payload, assemble an extrinsic and decode a call well enough to show a user what they are approving. The obvious route was @polkadot/api's codec. That is closed, and quantus/api#1 carries the tested evidence: - @polkadot/types caps fixed arrays at 2048 bytes, and ML-DSA signatures are [u8;5261] and [u8;7219], so every Quantus extrinsic trips it - api.rpc.chain.getBlock throws on every block of this chain, at the timestamp inherent, because it reads the extrinsic preamble byte as a version when the top two bits are a type tag - it *guesses* that signed extensions it does not recognise contribute nothing to the signed payload The third is why this is a package rather than a patch. The guess is right today — the registry says ReversibleTransactionExtension and WormholeProofRecorderExtension are empty on both halves — and it is right only by luck. This chain's encoding has changed between runtimes, transactionVersion has gone 2 -> 3 -> 6 across four upgrades, and when the guess stops holding the wallet keeps signing: valid signatures over a payload missing bytes the runtime put there, reported by the chain as BadProof, which is also what it reports for a wrong key. So nothing here names a pallet, a call, an extension or a signature scheme. Every type id is read from metadata the node produced by running Metadata_metadata against the runtime WASM in a given block's state, the same oracle blackbeard.observer has been decoding against across four upgrade boundaries. encode_extensions walks the declared extensions in order and refuses to build a payload when one that encodes to something has no value supplied — a wallet that cannot sign is a bug report, one that signs the wrong bytes is a support case nobody diagnoses. Proven end to end on Heisenberg at spec 148: a balances.transfer_keep_alive built entirely here, signed by @quantus/crypto under QUANTUS_EXTRINSIC, included at block 1050475 and read back from that block — inherent at index 0 included, which is the block @polkadot/api cannot decode at all. Two notes carried over from @quantus/crypto, both load-bearing: decode_checked walks with scale_decode's IgnoreVisitor before scale_value touches the bytes, because scale_value sizes a Vec from the length prefix before decoding an item and an aborted allocation leaves no Err to catch; and the build needs binaryen 123, since 105 silently corrupts the output. Closes #3 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f --- packages/quantus-codec/Cargo.lock | 502 +++++++++++++++++ packages/quantus-codec/Cargo.toml | 56 ++ packages/quantus-codec/README.md | 88 +++ packages/quantus-codec/package.json | 24 + packages/quantus-codec/rust-toolchain.toml | 8 + packages/quantus-codec/src/base64.ts | 51 ++ packages/quantus-codec/src/bytes.d.ts | 6 + packages/quantus-codec/src/bytes.js | 10 + packages/quantus-codec/src/codec.ts | 176 ++++++ .../src/generated/quantus_codec.d.ts | 100 ++++ .../src/generated/quantus_codec.js | 401 ++++++++++++++ packages/quantus-codec/src/index.ts | 6 + packages/quantus-codec/src/init.ts | 61 +++ packages/quantus-codec/src/lib.rs | 34 ++ packages/quantus-codec/src/rs/bindings.rs | 169 ++++++ packages/quantus-codec/src/rs/decode.rs | 275 ++++++++++ packages/quantus-codec/src/rs/encode.rs | 503 ++++++++++++++++++ packages/quantus-codec/src/rs/runtime.rs | 230 ++++++++ packages/quantus-codec/src/rs/tests.rs | 109 ++++ .../tests/heisenberg-v148.metadata.hex | 1 + packages/quantus-codec/tsconfig.build.json | 18 + scripts/build-quantus-js.sh | 7 +- scripts/build-quantus.sh | 10 +- 23 files changed, 2839 insertions(+), 6 deletions(-) create mode 100644 packages/quantus-codec/Cargo.lock create mode 100644 packages/quantus-codec/Cargo.toml create mode 100644 packages/quantus-codec/README.md create mode 100644 packages/quantus-codec/package.json create mode 100644 packages/quantus-codec/rust-toolchain.toml create mode 100644 packages/quantus-codec/src/base64.ts create mode 100644 packages/quantus-codec/src/bytes.d.ts create mode 100644 packages/quantus-codec/src/bytes.js create mode 100644 packages/quantus-codec/src/codec.ts create mode 100644 packages/quantus-codec/src/generated/quantus_codec.d.ts create mode 100644 packages/quantus-codec/src/generated/quantus_codec.js create mode 100644 packages/quantus-codec/src/index.ts create mode 100644 packages/quantus-codec/src/init.ts create mode 100644 packages/quantus-codec/src/lib.rs create mode 100644 packages/quantus-codec/src/rs/bindings.rs create mode 100644 packages/quantus-codec/src/rs/decode.rs create mode 100644 packages/quantus-codec/src/rs/encode.rs create mode 100644 packages/quantus-codec/src/rs/runtime.rs create mode 100644 packages/quantus-codec/src/rs/tests.rs create mode 100644 packages/quantus-codec/tests/heisenberg-v148.metadata.hex create mode 100644 packages/quantus-codec/tsconfig.build.json diff --git a/packages/quantus-codec/Cargo.lock b/packages/quantus-codec/Cargo.lock new file mode 100644 index 00000000..36870f36 --- /dev/null +++ b/packages/quantus-codec/Cargo.lock @@ -0,0 +1,502 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const_format" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "either" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "frame-metadata" +version = "23.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba5be0edbdb824843a0f9c6f0906ecfc66c5316218d74457003218b24909ed0" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quantus_codec" +version = "0.0.0" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-decode", + "scale-info", + "scale-value", + "serde_json", + "wasm-bindgen", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "scale-bits" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27243ab0d2d6235072b017839c5f0cd1a3b1ce45c0f7a715363b0c7d36c76c94" +dependencies = [ + "parity-scale-codec", + "scale-info", + "scale-type-resolver", + "serde", +] + +[[package]] +name = "scale-decode" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d6ed61699ad4d54101ab5a817169259b5b0efc08152f8632e61482d8a27ca3d" +dependencies = [ + "parity-scale-codec", + "scale-bits", + "scale-type-resolver", + "smallvec", + "thiserror", +] + +[[package]] +name = "scale-encode" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2a976d73564a59e482b74fd5d95f7518b79ca8c8ca5865398a4d629dd15ee50" +dependencies = [ + "parity-scale-codec", + "scale-bits", + "scale-type-resolver", + "smallvec", + "thiserror", +] + +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" +dependencies = [ + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-value" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3b64809a541e8d5a59f7a9d67cc700cdf5d7f907932a83a0afdedc90db07ccb" +dependencies = [ + "either", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-type-resolver", + "thiserror", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "smallvec" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.5", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.13+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "wasm-bindgen" +version = "0.2.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.5", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/packages/quantus-codec/Cargo.toml b/packages/quantus-codec/Cargo.toml new file mode 100644 index 00000000..e9e6739d --- /dev/null +++ b/packages/quantus-codec/Cargo.toml @@ -0,0 +1,56 @@ +# Metadata-driven SCALE encode/decode for the Quantus chain, compiled to WASM. +# +# A separate crate from `quantus-crypto` for the same reason that one is separate +# from `wasm-crypto`: different dependency graphs, built independently. They ship +# as sibling packages and the extension uses both — this one decides *what bytes* +# get signed, that one signs them. +# +# Why this exists at all rather than `@polkadot/api`: quantus/api#1. In short, +# polkadot-js cannot decode a Quantus block (it reads the extrinsic preamble byte +# as a version when the top two bits are a type tag), it refuses fixed arrays +# longer than 2048 (ML-DSA signatures are 5261 and 7219 bytes), and — the part +# that matters after those are patched — it *guesses* that signed extensions it +# does not recognise contribute nothing to the signed payload. On a chain whose +# encoding has already changed between runtimes, a guess like that produces a +# valid signature over the wrong bytes, which arrives as `BadProof` and looks +# exactly like a wrong key. See quantus/wasm#3. + +[package] +authors = ["Quantus Network Developers "] +description = "Metadata-driven SCALE codec for the Quantus chain, as WASM bindings." +edition = "2021" +license = "Apache-2.0" +name = "quantus_codec" +publish = false +repository = "https://git.lair.cafe/quantus/wasm" +resolver = "2" +version = "0.0.0" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +# Versions match blackbeard.observer's, which is the other consumer decoding this +# chain against its own metadata and the reference implementation for this crate. +frame-metadata = { version = "23", default-features = false, features = ["current", "decode"] } +parity-scale-codec = { version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2", default-features = false } +scale-value = { version = "0.18", default-features = false } +# Only for `IgnoreVisitor`. `scale_value` sizes a sequence's Vec from the length +# prefix *before* decoding an item, so a blob that disagrees with the registry can +# ask for an allocation of any size and abort the process — there is no Err to +# catch. Pinned to the version `scale-value` itself resolves so both see one +# registry. blackbeard.observer took a 76 GiB allocation to find this. +scale-decode = { version = "0.16", default-features = false } +serde_json = "1" +wasm-bindgen = "0.2" + +[profile.release] +codegen-units = 1 +debug = false +debug-assertions = false +incremental = false +lto = true +opt-level = "z" +panic = "abort" +rpath = false diff --git a/packages/quantus-codec/README.md b/packages/quantus-codec/README.md new file mode 100644 index 00000000..cce5e038 --- /dev/null +++ b/packages/quantus-codec/README.md @@ -0,0 +1,88 @@ +# @quantus/codec + +Metadata-driven SCALE encode and decode for the [Quantus](https://quantus.com) +chain, compiled to WASM. + +Nothing in this package names a pallet, a call, a signed extension or a signature +scheme. Everything is read from the metadata the node produced by running +`Metadata_metadata` against the runtime WASM in a given block's state, which +makes the runtime the oracle rather than this package's author. + +## Why not `@polkadot/api` + +Three reasons, in increasing order of importance — the evidence is on +[quantus/api#1](https://git.lair.cafe/quantus/api/issues/1). + +1. `@polkadot/types` refuses fixed arrays longer than 2048 bytes. ML-DSA + signatures are `[u8;5261]` and `[u8;7219]`, so every Quantus extrinsic trips + it. +2. `api.rpc.chain.getBlock` throws on **every block of this chain**, at the + timestamp inherent. The extrinsic preamble byte's top two bits are a type tag + (`0b00` bare, `0b10` signed, `0b01` general) and the low six are the version; + Quantus emits `0x84` — signed, v4 — and `0x05` — bare, v5 — in the same block + while the metadata declares version 4. polkadot-js reads that byte as a + version. +3. It **guesses** that signed extensions it does not recognise contribute nothing + to the signed payload, logging `Unknown signed extensions … treating them as + no-effect`. + +The third is why this package exists rather than a patch. The guess is correct +only while every unrecognised extension happens to be zero-sized. This chain's +encoding has already changed between runtimes — `transactionVersion` has gone +2 → 3 → 6 across four upgrades, each an extrinsic-format change — and when the +guess stops being correct the wallet keeps signing. Those signatures are +cryptographically valid, over a payload missing bytes the runtime put there, and +the chain reports them as `BadProof`, which is also what it reports for a wrong +key. Silent, remote, and indistinguishable from the one thing it is not. + +Here the registry decides. An extension whose declared type encodes to nothing +contributes nothing; anything else must be supplied by the caller or no payload +is produced at all. + +## Use + +```ts +import { Runtime } from '@quantus/codec'; + +const runtime = Runtime.fromMetadata(await fetchMetadata()); // state_getMetadata + +const call = runtime.encodeCall('Balances', 'transfer_keep_alive', { + dest: { Id: '0x…' }, + value: '1000000000' +}); + +const values = runtime.standardExtensions({ + blockHash: genesisHash, // immortal era + genesisHash, + nonce, + specVersion, + transactionVersion +}); + +const payload = runtime.signerPayload(call, values); +// sign `payload` with @quantus/crypto under the QUANTUS_EXTRINSIC context, +// hashing it first with BLAKE2b-256 if it is longer than 256 bytes +const extrinsic = runtime.encodeExtrinsic( + { Id: accountId }, + signature, + runtime.encodeExtra(values), + call +); +``` + +`standardExtensions` fills in the extensions Substrate itself defines. Anything +else this runtime declares as non-empty is refused by name — see above for why +that is the desired behaviour rather than a limitation. + +## Build + +``` +./scripts/build-quantus.sh quantus-codec +``` + +Same constraints as `@quantus/crypto`: a modern toolchain (separate from +`wasm-crypto`'s 2022 nightly), `initSync` over base64+zlib for the MV3 CSP, +wasm-bindgen's own glue rather than `@polkadot/wasm-bridge`, and **binaryen 123** +— version 105 silently corrupts the output. See +[quantus/wasm#1](https://git.lair.cafe/quantus/wasm/issues/1) and +[#3](https://git.lair.cafe/quantus/wasm/issues/3). diff --git a/packages/quantus-codec/package.json b/packages/quantus-codec/package.json new file mode 100644 index 00000000..31f236f0 --- /dev/null +++ b/packages/quantus-codec/package.json @@ -0,0 +1,24 @@ +{ + "author": "Quantus Network Developers ", + "bugs": "https://git.lair.cafe/quantus/wasm/issues", + "description": "Metadata-driven SCALE encode/decode for the Quantus chain", + "engines": { + "node": ">=18" + }, + "homepage": "https://git.lair.cafe/quantus/wasm/src/branch/main/packages/quantus-codec#readme", + "license": "Apache-2.0", + "name": "@quantus/codec", + "repository": { + "directory": "packages/quantus-codec", + "type": "git", + "url": "https://git.lair.cafe/quantus/wasm.git" + }, + "sideEffects": false, + "type": "module", + "version": "0.1.0", + "main": "index.js", + "dependencies": { + "fflate": "^0.8.2", + "tslib": "^2.7.0" + } +} diff --git a/packages/quantus-codec/rust-toolchain.toml b/packages/quantus-codec/rust-toolchain.toml new file mode 100644 index 00000000..53e44918 --- /dev/null +++ b/packages/quantus-codec/rust-toolchain.toml @@ -0,0 +1,8 @@ +# Matches the chain's toolchain (chain/rust-toolchain), so this crate is built by +# the same compiler that builds the runtime it has to agree with. Upstream's +# `wasm-crypto` keeps its own nightly-2022-06-24 pin; the two builds are separate +# on purpose. See quantus/wasm#1. +[toolchain] +channel = "1.93.0" +targets = ["wasm32-unknown-unknown"] +profile = "minimal" diff --git a/packages/quantus-codec/src/base64.ts b/packages/quantus-codec/src/base64.ts new file mode 100644 index 00000000..986f48a5 --- /dev/null +++ b/packages/quantus-codec/src/base64.ts @@ -0,0 +1,51 @@ +// Copyright 2026 @quantus/crypto authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +// An array indexer rather than a Map: the input is ASCII by construction, so it +// cannot overflow, and array access is measurably faster on the hot loop. +const MAP = new Array(256); + +for (let i = 0; i < CHARS.length; i++) { + MAP[CHARS.charCodeAt(i)] = i; +} + +/** + * Decode base64 into a caller-supplied buffer. + * + * Deliberately not `atob` or `Buffer.from`: the first is browser-only, the second + * node-only, and this runs in an MV3 service worker, a Worker, node tests and a + * bundled extension page. The output length is known at build time, so the + * caller provides the buffer and there is no growth or reallocation. + * + * This is a reimplementation of `@polkadot/wasm-util`'s base64Decode, which was + * the dependency it replaced. That package's index re-exports `packageDetect`, + * dragging in a `@polkadot/util` peer dependency for a side effect we do not + * want, and being a workspace package it resolved through its own repo's + * node_modules when consumed by symlink from another checkout. Fifteen lines is + * cheaper than either problem. + */ +export function base64Decode (data: string, out: Uint8Array): Uint8Array { + let byte = 0; + let bits = 0; + let pos = 0; + + for (let i = 0; i < data.length && pos < out.length; i++) { + const value = MAP[data.charCodeAt(i)]; + + if (value === undefined) { + continue; + } + + byte = (byte << 6) | value; + bits += 6; + + if (bits >= 8) { + bits -= 8; + out[pos++] = (byte >>> bits) & 0xff; + } + } + + return out; +} diff --git a/packages/quantus-codec/src/bytes.d.ts b/packages/quantus-codec/src/bytes.d.ts new file mode 100644 index 00000000..92d7bbe1 --- /dev/null +++ b/packages/quantus-codec/src/bytes.d.ts @@ -0,0 +1,6 @@ +// Copyright 2026 @quantus/crypto authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +export declare const lenIn: number; +export declare const lenOut: number; +export declare const bytes: string; diff --git a/packages/quantus-codec/src/bytes.js b/packages/quantus-codec/src/bytes.js new file mode 100644 index 00000000..99d425e1 --- /dev/null +++ b/packages/quantus-codec/src/bytes.js @@ -0,0 +1,10 @@ +// Copyright 2026 @quantus/crypto authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +// Generated as part of the build, do not edit + +export const lenIn = 0; + +export const lenOut = 0; + +export const bytes = ''; diff --git a/packages/quantus-codec/src/codec.ts b/packages/quantus-codec/src/codec.ts new file mode 100644 index 00000000..5af0eb89 --- /dev/null +++ b/packages/quantus-codec/src/codec.ts @@ -0,0 +1,176 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { initWasm } from './init.js'; + +import { QuantusRuntime } from './generated/quantus_codec.js'; + +/** What one signed extension needs from the caller, as the runtime declares it. */ +export interface ExtensionNeed { + identifier: string; + /** Whether its `ty` encodes to anything — i.e. whether it goes on the wire. */ + needsExtra: boolean; + /** Whether its `additional_signed` encodes to anything. */ + needsAdditional: boolean; +} + +/** A value for one signed extension. Omit a half the runtime declares as empty. */ +export interface ExtensionValue { + extra?: unknown; + additional?: unknown; +} + +export type ExtensionValues = Record; + +export interface DecodedExtrinsic { + /** The preamble byte's low six bits — **not** the byte. See `decodeExtrinsic`. */ + version: number; + signed: boolean; + address: unknown; + signature: unknown; + extra: unknown; + call: unknown; +} + +/** Everything needed to fill in the signed extensions Substrate itself defines. */ +export interface PayloadOptions { + specVersion: number; + transactionVersion: number; + genesisHash: string; + /** The era's birth block. For an immortal era this is the genesis hash. */ + blockHash: string; + nonce: number; + tip?: bigint | string; + /** `'Immortal'`, or `{ MortalN: phase }` as the registry spells it. */ + era?: unknown; + /** `CheckMetadataHash`: `null` disables it, which is what a wallet wants. */ + metadataHash?: string | null; +} + +/** + * A runtime, loaded from the metadata it produced about itself. + * + * Construct one per spec version and keep it: parsing metadata is the expensive + * part, and the blob does not change until the chain upgrades. + */ +export class Runtime { + readonly #inner: QuantusRuntime; + + private constructor (inner: QuantusRuntime) { + this.#inner = inner; + } + + /** + * Parse metadata exactly as `state_getMetadata` returns it. + * + * That RPC takes a block hash and makes the node run `Metadata_metadata` + * against the runtime code in *that block's* state — so this is the runtime + * describing itself, and it is the only description that cannot go stale. + */ + static fromMetadata (metadata: Uint8Array): Runtime { + const failed = initWasm(); + + if (failed) { + throw new Error(`@quantus/codec: WASM unavailable: ${failed}`); + } + + return new Runtime(new QuantusRuntime(metadata)); + } + + /** The extrinsic format version the metadata declares. */ + get extrinsicVersion (): number { + return this.#inner.extrinsicVersion(); + } + + /** + * Every signed extension, in the order the runtime applies them — which is the + * order their bytes appear in the payload. + */ + signedExtensions (): ExtensionNeed[] { + return JSON.parse(this.#inner.signedExtensions()) as ExtensionNeed[]; + } + + /** Encode a call by name. `args` is keyed by the runtime's own argument names. */ + encodeCall (pallet: string, call: string, args: Record): Uint8Array { + return this.#inner.encodeCall(pallet, call, JSON.stringify(args)); + } + + /** The `extra`: what the extensions contribute to the extrinsic itself. */ + encodeExtra (values: ExtensionValues): Uint8Array { + return this.#inner.encodeExtra(JSON.stringify(values)); + } + + /** + * The bytes to sign: `call ‖ extra ‖ additional`. + * + * Substrate's rule that a payload over 256 bytes is signed as its BLAKE2b-256 + * hash is **not** applied here — that belongs with the signing code, which also + * chooses the FIPS 204 context. Splitting one rule across two packages is how + * the halves drift apart. + */ + signerPayload (call: Uint8Array, values: ExtensionValues): Uint8Array { + return this.#inner.signerPayload(call, JSON.stringify(values)); + } + + /** + * Assemble a signed extrinsic, ready for `author_submitAndWatchExtrinsic`. + * + * `signature` is the encoded `Signature` type with its variant byte already in + * place: the signer knows which ML-DSA scheme its key is, and re-deriving that + * here from the byte length would be a second source of truth. + */ + encodeExtrinsic (address: unknown, signature: Uint8Array, extra: Uint8Array, call: Uint8Array): Uint8Array { + return this.#inner.encodeExtrinsic(JSON.stringify(address), signature, extra, call); + } + + /** + * Decode one extrinsic, length prefix and all. + * + * The returned `version` is the preamble byte's low six bits. The top two are a + * type tag — `0b00` bare, `0b10` signed, `0b01` general — so Quantus emits + * `0x84` (signed, v4) and `0x05` (bare, v5) in the same block while the + * metadata declares version 4. Three numbers, all correct. Reading that byte as + * a version is why `@polkadot/api` cannot decode a single block of this chain. + */ + decodeExtrinsic (blob: Uint8Array): DecodedExtrinsic { + return JSON.parse(this.#inner.decodeExtrinsic(blob)) as DecodedExtrinsic; + } + + /** Decode a bare call — what an approval screen shows the user. */ + decodeCall (bytes: Uint8Array): unknown { + return JSON.parse(this.#inner.decodeCall(bytes)) as unknown; + } + + /** + * Fill in the signed extensions that Substrate itself defines, from one + * options object. + * + * This covers the extensions whose meaning is fixed by Substrate. It + * deliberately does **not** try to cover every extension a runtime might + * declare: anything else that needs a value will be refused by + * `signerPayload` with the extension's name, which is the correct outcome — + * a wallet that cannot sign is a bug report, and one that signs a payload + * missing bytes the runtime put there is a `BadProof` nobody can diagnose. + * + * Pass the result, extended with whatever else this runtime asks for, to + * `signerPayload` and `encodeExtra`. + */ + standardExtensions (options: PayloadOptions): ExtensionValues { + const values: ExtensionValues = { + ChargeTransactionPayment: { extra: (options.tip ?? 0n).toString() }, + CheckGenesis: { additional: options.genesisHash }, + CheckMetadataHash: { + // `Mode::Disabled`, and `None`. Enabling it would mean shipping a + // metadata hash this package has no way to compute. + additional: options.metadataHash ? { Some: options.metadataHash } : 'None', + extra: 'Disabled' + }, + CheckMortality: { additional: options.blockHash, extra: options.era ?? 'Immortal' }, + CheckNonce: { extra: options.nonce }, + CheckSpecVersion: { additional: options.specVersion }, + CheckTxVersion: { additional: options.transactionVersion } + }; + + return values; + } +} diff --git a/packages/quantus-codec/src/generated/quantus_codec.d.ts b/packages/quantus-codec/src/generated/quantus_codec.d.ts new file mode 100644 index 00000000..b8d81c1b --- /dev/null +++ b/packages/quantus-codec/src/generated/quantus_codec.d.ts @@ -0,0 +1,100 @@ +/* tslint:disable */ +/* eslint-disable */ + +/** + * A loaded runtime description, held across calls so the metadata is parsed + * once per spec version rather than once per signature. + */ +export class QuantusRuntime { + free(): void; + [Symbol.dispose](): void; + /** + * Decode a bare call — what an approval screen shows the user. + */ + decodeCall(bytes: Uint8Array): string; + /** + * Decode one extrinsic as this runtime describes it, as JSON. + */ + decodeExtrinsic(blob: Uint8Array): string; + /** + * Encode a call by name. `args` is a JSON object keyed by argument name. + */ + encodeCall(pallet: string, call: string, args: string): Uint8Array; + /** + * The `extra` alone, which the extrinsic carries and the payload repeats. + */ + encodeExtra(extensions: string): Uint8Array; + /** + * Assemble a signed extrinsic, ready for `author_submitAndWatchExtrinsic`. + */ + encodeExtrinsic(address: string, signature: Uint8Array, extra: Uint8Array, call: Uint8Array): Uint8Array; + /** + * The extrinsic format version this runtime declares. + */ + extrinsicVersion(): number; + /** + * Parse metadata as `state_getMetadata` returns it. + */ + constructor(metadata: Uint8Array); + /** + * Every signed extension, in order, as + * `[{ identifier, needsExtra, needsAdditional }]`. + * + * The two booleans are what a caller has to satisfy, read from the + * registry. A caller that ignores them gets an error rather than a short + * payload. + */ + signedExtensions(): string; + /** + * The bytes to sign, given an encoded call and the extension values. + * + * `extensions` is a JSON object keyed by extension identifier, each value + * `{ extra?, additional? }`. Omitting one the runtime declares as non-empty + * is an error — see [`Runtime::encode_extensions`]. + */ + signerPayload(call: Uint8Array, extensions: string): Uint8Array; +} + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly __wbg_quantusruntime_free: (a: number, b: number) => void; + readonly quantusruntime_decodeCall: (a: number, b: number, c: number) => [number, number, number, number]; + readonly quantusruntime_decodeExtrinsic: (a: number, b: number, c: number) => [number, number, number, number]; + readonly quantusruntime_encodeCall: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number, number]; + readonly quantusruntime_encodeExtra: (a: number, b: number, c: number) => [number, number, number, number]; + readonly quantusruntime_encodeExtrinsic: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number, number, number]; + readonly quantusruntime_extrinsicVersion: (a: number) => number; + readonly quantusruntime_new: (a: number, b: number) => [number, number, number]; + readonly quantusruntime_signedExtensions: (a: number) => [number, number, number, number]; + readonly quantusruntime_signerPayload: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; + readonly __wbindgen_externrefs: WebAssembly.Table; + readonly __wbindgen_malloc: (a: number, b: number) => number; + readonly __externref_table_dealloc: (a: number) => void; + readonly __wbindgen_free: (a: number, b: number, c: number) => void; + readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; + readonly __wbindgen_start: () => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; + +/** + * Instantiates the given `module`, which can either be bytes or + * a precompiled `WebAssembly.Module`. + * + * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. + * + * @returns {InitOutput} + */ +export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; + +/** + * If `module_or_path` is {RequestInfo} or {URL}, makes a request and + * for everything else, calls `WebAssembly.instantiate` directly. + * + * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. + * + * @returns {Promise} + */ +export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; diff --git a/packages/quantus-codec/src/generated/quantus_codec.js b/packages/quantus-codec/src/generated/quantus_codec.js new file mode 100644 index 00000000..a6fd94b7 --- /dev/null +++ b/packages/quantus-codec/src/generated/quantus_codec.js @@ -0,0 +1,401 @@ +/* @ts-self-types="./quantus_codec.d.ts" */ + +/** + * A loaded runtime description, held across calls so the metadata is parsed + * once per spec version rather than once per signature. + */ +export class QuantusRuntime { + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + QuantusRuntimeFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_quantusruntime_free(ptr, 0); + } + /** + * Decode a bare call — what an approval screen shows the user. + * @param {Uint8Array} bytes + * @returns {string} + */ + decodeCall(bytes) { + let deferred3_0; + let deferred3_1; + try { + const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.quantusruntime_decodeCall(this.__wbg_ptr, ptr0, len0); + var ptr2 = ret[0]; + var len2 = ret[1]; + if (ret[3]) { + ptr2 = 0; len2 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } + } + /** + * Decode one extrinsic as this runtime describes it, as JSON. + * @param {Uint8Array} blob + * @returns {string} + */ + decodeExtrinsic(blob) { + let deferred3_0; + let deferred3_1; + try { + const ptr0 = passArray8ToWasm0(blob, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.quantusruntime_decodeExtrinsic(this.__wbg_ptr, ptr0, len0); + var ptr2 = ret[0]; + var len2 = ret[1]; + if (ret[3]) { + ptr2 = 0; len2 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred3_0 = ptr2; + deferred3_1 = len2; + return getStringFromWasm0(ptr2, len2); + } finally { + wasm.__wbindgen_free(deferred3_0, deferred3_1, 1); + } + } + /** + * Encode a call by name. `args` is a JSON object keyed by argument name. + * @param {string} pallet + * @param {string} call + * @param {string} args + * @returns {Uint8Array} + */ + encodeCall(pallet, call, args) { + const ptr0 = passStringToWasm0(pallet, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(call, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(args, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + const ret = wasm.quantusruntime_encodeCall(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2); + if (ret[3]) { + throw takeFromExternrefTable0(ret[2]); + } + var v4 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v4; + } + /** + * The `extra` alone, which the extrinsic carries and the payload repeats. + * @param {string} extensions + * @returns {Uint8Array} + */ + encodeExtra(extensions) { + const ptr0 = passStringToWasm0(extensions, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.quantusruntime_encodeExtra(this.__wbg_ptr, ptr0, len0); + if (ret[3]) { + throw takeFromExternrefTable0(ret[2]); + } + var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v2; + } + /** + * Assemble a signed extrinsic, ready for `author_submitAndWatchExtrinsic`. + * @param {string} address + * @param {Uint8Array} signature + * @param {Uint8Array} extra + * @param {Uint8Array} call + * @returns {Uint8Array} + */ + encodeExtrinsic(address, signature, extra, call) { + const ptr0 = passStringToWasm0(address, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passArray8ToWasm0(signature, wasm.__wbindgen_malloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(extra, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passArray8ToWasm0(call, wasm.__wbindgen_malloc); + const len3 = WASM_VECTOR_LEN; + const ret = wasm.quantusruntime_encodeExtrinsic(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3); + if (ret[3]) { + throw takeFromExternrefTable0(ret[2]); + } + var v5 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v5; + } + /** + * The extrinsic format version this runtime declares. + * @returns {number} + */ + extrinsicVersion() { + const ret = wasm.quantusruntime_extrinsicVersion(this.__wbg_ptr); + return ret; + } + /** + * Parse metadata as `state_getMetadata` returns it. + * @param {Uint8Array} metadata + */ + constructor(metadata) { + const ptr0 = passArray8ToWasm0(metadata, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.quantusruntime_new(ptr0, len0); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + this.__wbg_ptr = ret[0]; + QuantusRuntimeFinalization.register(this, this.__wbg_ptr, this); + return this; + } + /** + * Every signed extension, in order, as + * `[{ identifier, needsExtra, needsAdditional }]`. + * + * The two booleans are what a caller has to satisfy, read from the + * registry. A caller that ignores them gets an error rather than a short + * payload. + * @returns {string} + */ + signedExtensions() { + let deferred2_0; + let deferred2_1; + try { + const ret = wasm.quantusruntime_signedExtensions(this.__wbg_ptr); + var ptr1 = ret[0]; + var len1 = ret[1]; + if (ret[3]) { + ptr1 = 0; len1 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred2_0 = ptr1; + deferred2_1 = len1; + return getStringFromWasm0(ptr1, len1); + } finally { + wasm.__wbindgen_free(deferred2_0, deferred2_1, 1); + } + } + /** + * The bytes to sign, given an encoded call and the extension values. + * + * `extensions` is a JSON object keyed by extension identifier, each value + * `{ extra?, additional? }`. Omitting one the runtime declares as non-empty + * is an error — see [`Runtime::encode_extensions`]. + * @param {Uint8Array} call + * @param {string} extensions + * @returns {Uint8Array} + */ + signerPayload(call, extensions) { + const ptr0 = passArray8ToWasm0(call, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(extensions, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.quantusruntime_signerPayload(this.__wbg_ptr, ptr0, len0, ptr1, len1); + if (ret[3]) { + throw takeFromExternrefTable0(ret[2]); + } + var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v3; + } +} +if (Symbol.dispose) QuantusRuntime.prototype[Symbol.dispose] = QuantusRuntime.prototype.free; +function __wbg_get_imports() { + const import0 = { + __proto__: null, + __wbg_Error_67e7344beaa85059: function(arg0, arg1) { + const ret = Error(getStringFromWasm0(arg0, arg1)); + return ret; + }, + __wbg___wbindgen_throw_5d9e815e6fdf150f: function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }, + __wbindgen_init_externref_table: function() { + const table = wasm.__wbindgen_externrefs; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + }, + }; + return { + __proto__: null, + "./quantus_codec_bg.js": import0, + }; +} + +const QuantusRuntimeFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_quantusruntime_free(ptr, 1)); + +function getArrayU8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); +} + +function getStringFromWasm0(ptr, len) { + return decodeText(ptr >>> 0, len); +} + +let cachedUint8ArrayMemory0 = null; +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} + +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1, 1) >>> 0; + getUint8ArrayMemory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +function passStringToWasm0(arg, malloc, realloc) { + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8ArrayMemory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); + const ret = cachedTextEncoder.encodeInto(arg, view); + + offset += ret.written; + ptr = realloc(ptr, len, offset, 1) >>> 0; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function takeFromExternrefTable0(idx) { + const value = wasm.__wbindgen_externrefs.get(idx); + wasm.__externref_table_dealloc(idx); + return value; +} + +let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); +cachedTextDecoder.decode(); +const MAX_SAFARI_DECODE_BYTES = 2146435072; +let numBytesDecoded = 0; +function decodeText(ptr, len) { + numBytesDecoded += len; + if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) { + cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + cachedTextDecoder.decode(); + numBytesDecoded = len; + } + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} + +const cachedTextEncoder = new TextEncoder(); + +if (!('encodeInto' in cachedTextEncoder)) { + cachedTextEncoder.encodeInto = function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; + }; +} + +let WASM_VECTOR_LEN = 0; + +let wasmModule, wasmInstance, wasm; +function __wbg_finalize_init(instance, module) { + wasmInstance = instance; + wasm = instance.exports; + wasmModule = module; + cachedUint8ArrayMemory0 = null; + wasm.__wbindgen_start(); + return wasm; +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (!module.ok) { + throw new Error(`failed to fetch Wasm: ${module.status} ${module.statusText} fetching '${module.url}'`); + } + + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + } catch (e) { + const validResponse = expectedResponseType(module.type); + + if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { throw e; } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + } else { + return instance; + } + } + + function expectedResponseType(type) { + switch (type) { + case 'basic': case 'cors': case 'default': return true; + } + return false; + } +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + + if (module !== undefined) { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({module} = module) + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead') + } + } + + const imports = __wbg_get_imports(); + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + const instance = new WebAssembly.Instance(module, imports); + return __wbg_finalize_init(instance, module); +} + +export { initSync }; diff --git a/packages/quantus-codec/src/index.ts b/packages/quantus-codec/src/index.ts new file mode 100644 index 00000000..25e8c1f0 --- /dev/null +++ b/packages/quantus-codec/src/index.ts @@ -0,0 +1,6 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +export { Runtime } from './codec.js'; +export type { DecodedExtrinsic, ExtensionNeed, ExtensionValue, ExtensionValues, PayloadOptions } from './codec.js'; +export { initWasm, isReady } from './init.js'; diff --git a/packages/quantus-codec/src/init.ts b/packages/quantus-codec/src/init.ts new file mode 100644 index 00000000..21ea5e23 --- /dev/null +++ b/packages/quantus-codec/src/init.ts @@ -0,0 +1,61 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { unzlibSync } from 'fflate'; + +import { base64Decode } from './base64.js'; + +import { bytes, lenOut } from './bytes.js'; +import { initSync } from './generated/quantus_codec.js'; + +/** + * Instantiate the WASM, synchronously, from bytes compiled into this file. + * + * Three constraints shape this, and all three rule out the obvious approach: + * + * - the background context is an **MV3 service worker**, so there is no DOM, no + * reliable `fetch` of extension-relative URLs at arbitrary times, and the + * worker can be killed and cold-started between any two messages + * - the extension CSP is `script-src 'self' 'wasm-unsafe-eval'`, which permits + * compiling WASM but not fetching it from anywhere interesting + * - callers are synchronous — `pair.sign()` in the keyring has no `await` to give + * + * So the WASM is zlib-compressed, base64'd into `bytes.js` at build time, and + * instantiated here with wasm-bindgen's `initSync`. Nothing is fetched, and the + * whole module is ready before the first call returns. + * + * Deliberately *not* using `@polkadot/wasm-bridge`: its `Bridge` implements + * wasm-bindgen 0.2.79's JS-heap ABI, and this crate is built with 0.2.128, which + * uses externref tables. See quantus/wasm#1. + */ + +let initialised = false; +let initError: string | null = null; + +/** + * Ensure the WASM is instantiated. Idempotent and cheap after the first call. + * + * Returns `null` on success, or the failure reason. It does not throw: a caller + * deciding whether to offer a Quantus account at all wants to ask, and an + * exception thrown from module scope in a service worker is hard to attribute. + */ +export function initWasm (): string | null { + if (initialised) { + return initError; + } + + initialised = true; + + try { + initSync({ module: unzlibSync(base64Decode(bytes, new Uint8Array(lenOut))) }); + } catch (error) { + initError = (error as Error).message; + } + + return initError; +} + +/** Whether the WASM is available. Callers that can fall back should ask first. */ +export function isReady (): boolean { + return initWasm() === null; +} diff --git a/packages/quantus-codec/src/lib.rs b/packages/quantus-codec/src/lib.rs new file mode 100644 index 00000000..09c5aab3 --- /dev/null +++ b/packages/quantus-codec/src/lib.rs @@ -0,0 +1,34 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Metadata-driven SCALE encode and decode for the Quantus chain. +//! +//! Nothing here names a pallet, a call, a signed extension or a signature +//! scheme. Everything is read from the metadata the node produced by running +//! `Metadata_metadata` against the runtime WASM in a given block's state, which +//! makes the runtime the oracle rather than this crate's author. +//! +//! That is not fastidiousness. This chain's encoding has changed between +//! runtimes — `transactionVersion` has gone 2 → 3 → 6 across four upgrades, and +//! each of those is an extrinsic-format change. A signer holding a hand-written +//! idea of the format keeps producing signatures after such an upgrade; they are +//! cryptographically valid, over the wrong bytes, and the chain reports them as +//! `BadProof`, which is what it also reports for a wrong key. See quantus/wasm#3. + +extern crate alloc; + +#[path = "rs/runtime.rs"] +pub mod runtime; + +#[path = "rs/decode.rs"] +pub mod decode; + +#[path = "rs/encode.rs"] +pub mod encode; + +#[path = "rs/bindings.rs"] +mod bindings; + +#[cfg(test)] +#[path = "rs/tests.rs"] +mod tests; diff --git a/packages/quantus-codec/src/rs/bindings.rs b/packages/quantus-codec/src/rs/bindings.rs new file mode 100644 index 00000000..65d93b78 --- /dev/null +++ b/packages/quantus-codec/src/rs/bindings.rs @@ -0,0 +1,169 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +//! The `wasm_bindgen` surface. +//! +//! Deliberately thin: every one of these is a parse of the JS argument, a call +//! into a module that knows nothing about JS, and a serialisation back. The +//! logic lives in [`crate::runtime`], [`crate::decode`] and [`crate::encode`] +//! because `JsError` cannot be constructed outside a wasm target, so anything +//! built on it is untestable by `cargo test` — a lesson from quantus/wasm#1, +//! where the error paths were the ones that turned out to be wrong. + +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +use wasm_bindgen::prelude::*; + +use crate::encode::ExtensionValue; +use crate::runtime::Runtime; + +/// A loaded runtime description, held across calls so the metadata is parsed +/// once per spec version rather than once per signature. +#[wasm_bindgen] +pub struct QuantusRuntime { + inner: Runtime, +} + +#[wasm_bindgen] +impl QuantusRuntime { + /// Parse metadata as `state_getMetadata` returns it. + #[wasm_bindgen(constructor)] + pub fn new(metadata: &[u8]) -> Result { + Runtime::from_metadata(metadata) + .map(|inner| QuantusRuntime { inner }) + .map_err(|e| JsError::new(&e.to_string())) + } + + /// The extrinsic format version this runtime declares. + #[wasm_bindgen(js_name = extrinsicVersion)] + pub fn extrinsic_version(&self) -> u8 { + self.inner.extrinsic_version() + } + + /// Every signed extension, in order, as + /// `[{ identifier, needsExtra, needsAdditional }]`. + /// + /// The two booleans are what a caller has to satisfy, read from the + /// registry. A caller that ignores them gets an error rather than a short + /// payload. + #[wasm_bindgen(js_name = signedExtensions)] + pub fn signed_extensions(&self) -> Result { + let described: Vec = self + .inner + .extensions() + .iter() + .map(|e| { + serde_json::json!({ + "identifier": e.identifier, + "needsExtra": !self.inner.is_empty_ty_pub(e.ty), + "needsAdditional": !self.inner.is_empty_ty_pub(e.additional) + }) + }) + .collect(); + + serde_json::to_string(&described).map_err(|e| JsError::new(&e.to_string())) + } + + /// Encode a call by name. `args` is a JSON object keyed by argument name. + #[wasm_bindgen(js_name = encodeCall)] + pub fn encode_call(&self, pallet: &str, call: &str, args: &str) -> Result, JsError> { + let args: serde_json::Value = + serde_json::from_str(args).map_err(|e| JsError::new(&e.to_string()))?; + + self.inner + .encode_call(pallet, call, &args) + .map_err(|e| JsError::new(&e.to_string())) + } + + /// The bytes to sign, given an encoded call and the extension values. + /// + /// `extensions` is a JSON object keyed by extension identifier, each value + /// `{ extra?, additional? }`. Omitting one the runtime declares as non-empty + /// is an error — see [`Runtime::encode_extensions`]. + #[wasm_bindgen(js_name = signerPayload)] + pub fn signer_payload(&self, call: &[u8], extensions: &str) -> Result, JsError> { + let encoded = self.encoded_extensions(extensions)?; + + Ok(self.inner.signer_payload(call, &encoded)) + } + + /// The `extra` alone, which the extrinsic carries and the payload repeats. + #[wasm_bindgen(js_name = encodeExtra)] + pub fn encode_extra(&self, extensions: &str) -> Result, JsError> { + Ok(self.encoded_extensions(extensions)?.extra) + } + + /// Assemble a signed extrinsic, ready for `author_submitAndWatchExtrinsic`. + #[wasm_bindgen(js_name = encodeExtrinsic)] + pub fn encode_extrinsic( + &self, + address: &str, + signature: &[u8], + extra: &[u8], + call: &[u8], + ) -> Result, JsError> { + let address: serde_json::Value = + serde_json::from_str(address).map_err(|e| JsError::new(&e.to_string()))?; + + self.inner + .encode_extrinsic(&address, signature, extra, call) + .map_err(|e| JsError::new(&e.to_string())) + } + + /// Decode one extrinsic as this runtime describes it, as JSON. + #[wasm_bindgen(js_name = decodeExtrinsic)] + pub fn decode_extrinsic(&self, blob: &[u8]) -> Result { + let xt = self + .inner + .decode_extrinsic(blob) + .map_err(|e| JsError::new(&e.to_string()))?; + + serde_json::to_string(&serde_json::json!({ + "version": xt.version, + "signed": xt.signed, + "address": xt.address, + "signature": xt.signature, + "extra": xt.extra, + "call": xt.call + })) + .map_err(|e| JsError::new(&e.to_string())) + } + + /// Decode a bare call — what an approval screen shows the user. + #[wasm_bindgen(js_name = decodeCall)] + pub fn decode_call(&self, bytes: &[u8]) -> Result { + let call = self + .inner + .decode_call(bytes) + .map_err(|e| JsError::new(&e.to_string()))?; + + serde_json::to_string(&call).map_err(|e| JsError::new(&e.to_string())) + } + + fn encoded_extensions( + &self, + extensions: &str, + ) -> Result { + let parsed: BTreeMap = + serde_json::from_str(extensions).map_err(|e| JsError::new(&e.to_string()))?; + + let values: BTreeMap = parsed + .into_iter() + .map(|(k, v)| { + ( + k, + ExtensionValue { + extra: v.get("extra").cloned(), + additional: v.get("additional").cloned(), + }, + ) + }) + .collect(); + + self.inner + .encode_extensions(&values) + .map_err(|e| JsError::new(&e.to_string())) + } +} diff --git a/packages/quantus-codec/src/rs/decode.rs b/packages/quantus-codec/src/rs/decode.rs new file mode 100644 index 00000000..0767b2de --- /dev/null +++ b/packages/quantus-codec/src/rs/decode.rs @@ -0,0 +1,275 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Reading a chain's own data using the chain's own description of it. + +use alloc::format; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +use parity_scale_codec::Decode; + +use crate::runtime::{CodecError, Runtime}; + +/// One decoded extrinsic, named as the runtime names it. +#[derive(Debug, Clone, PartialEq)] +pub struct DecodedExtrinsic { + /// The **version** from the preamble byte — its low six bits, not the byte. + pub version: u8, + /// Whether the preamble's type tag says signed. + pub signed: bool, + /// The address as the runtime's `Address` type decodes, rendered as JSON. + pub address: serde_json::Value, + /// The signature, rendered as JSON. For Quantus this is a + /// `DilithiumSignatureScheme` variant carrying `sig ‖ pk`. + pub signature: serde_json::Value, + /// The signed extensions as submitted — mortality, nonce, tip, and whatever + /// else this runtime declares. + pub extra: serde_json::Value, + /// The `extra` exactly as it appeared on the wire. Kept because it is half + /// of the signed payload, and re-encoding it from `extra` would be a second + /// implementation that could disagree. + pub extra_bytes: Vec, + /// The call, SCALE-encoded, as it appeared on the wire. + pub call_bytes: Vec, + /// The call, decoded. + pub call: serde_json::Value, +} + +impl Runtime { + /// Decode one extrinsic, exactly as this runtime describes it. + /// + /// ## The preamble byte is not the version + /// + /// The **top two bits are a type tag** and the low six are the version: + /// `0b00` bare, `0b10` signed, `0b01` general. Quantus emits `0x84` — + /// signed, v4 — and `0x05` — bare, v**5** — in the same block, while the + /// metadata declares extrinsic version 4. Three different numbers, all + /// correct. + /// + /// A decoder that reads the byte as a version and checks it against the + /// metadata rejects every timestamp inherent on the chain. `@polkadot/api` + /// does exactly that, which is why it cannot read a single Quantus block + /// (quantus/api#1), and it is the first thing to break when someone + /// "simplifies" this function. + /// + /// `blob` is the extrinsic as the node hands it over: its own length prefix + /// first. A partial read is refused — trailing bytes mean the metadata does + /// not match these bytes, and a decoder that shrugs at that is how a block + /// gets silently mis-read after an upgrade. + pub fn decode_extrinsic(&self, blob: &[u8]) -> Result { + let mut cursor = blob; + let declared = >::decode(&mut cursor) + .map_err(|e| CodecError::Decode(format!("no length prefix: {e}")))? + .0 as usize; + + if cursor.len() != declared { + return Err(CodecError::Decode(format!( + "declared {declared} bytes, {} present", + cursor.len() + ))); + } + + let preamble = *cursor + .first() + .ok_or_else(|| CodecError::Decode("empty extrinsic".to_string()))?; + cursor = &cursor[1..]; + + let signed = preamble & 0b1100_0000 == 0b1000_0000; + let version = preamble & 0b0011_1111; + let tys = self.extrinsic; + + let (address, signature, extra, extra_bytes) = if signed { + let address = self.decode_at(tys.address, &mut cursor, "address")?; + let signature = self.decode_at(tys.signature, &mut cursor, "signature")?; + + let before = cursor; + let extra = self.decode_at(tys.extra, &mut cursor, "signed extensions")?; + let extra_bytes = before[..before.len() - cursor.len()].to_vec(); + + (address, signature, extra, extra_bytes) + } else { + ( + serde_json::Value::Null, + serde_json::Value::Null, + serde_json::Value::Null, + Vec::new(), + ) + }; + + let call_bytes = cursor.to_vec(); + let call = self.decode_at(tys.call, &mut cursor, "call")?; + + if !cursor.is_empty() { + return Err(CodecError::Decode(format!( + "{} trailing bytes; metadata does not match this extrinsic", + cursor.len() + ))); + } + + Ok(DecodedExtrinsic { + version, + signed, + address, + signature, + extra, + extra_bytes, + call_bytes: call_bytes[..call_bytes.len() - cursor.len()].to_vec(), + call, + }) + } + + /// Decode a bare call — what an approval screen needs to say what is about + /// to be authorised. + pub fn decode_call(&self, bytes: &[u8]) -> Result { + let mut cursor = bytes; + let call = self.decode_at(self.extrinsic.call, &mut cursor, "call")?; + + if !cursor.is_empty() { + return Err(CodecError::Decode(format!( + "{} trailing bytes after call", + cursor.len() + ))); + } + + Ok(call) + } + + fn decode_at( + &self, + ty: u32, + cursor: &mut &[u8], + what: &str, + ) -> Result { + let value = self + .decode_checked(ty, cursor) + .map_err(|e| CodecError::Decode(format!("{what}: {e}")))?; + + Ok(render(&value)) + } + + /// Decode one registry type, walking the bytes first without building + /// anything from them. + /// + /// **`scale_value` sizes a sequence's `Vec` from the length prefix before it + /// decodes a single item.** A blob that disagrees with the registry can + /// therefore ask for an allocation of any size at all, and Rust aborts on a + /// failed one — so there is no `Err` for a caller to catch, and `.ok()` at + /// the call site cannot help. blackbeard.observer found this in production + /// as a 76 GiB request that took the daemon down every two minutes. + /// + /// `scale_decode`'s `IgnoreVisitor` walks the same bytes against the same + /// type and allocates nothing at all, so a length that cannot be satisfied + /// runs out of input on the first item and comes back as an error. The + /// second pass costs one more walk of a few kilobytes. + fn decode_checked( + &self, + ty: u32, + cursor: &mut &[u8], + ) -> Result, String> { + let mut probe: &[u8] = cursor; + + scale_decode::visitor::decode_with_visitor( + &mut probe, + ty, + self.types(), + scale_decode::visitor::IgnoreVisitor::::new(), + ) + .map_err(|e| e.to_string())?; + + scale_value::scale::decode_as_type(cursor, ty, self.types()).map_err(|e| e.to_string()) + } +} + +/// Render a decoded value as JSON, for the boundary to JavaScript. +/// +/// Byte sequences become `0x…` hex rather than arrays of numbers: an account id +/// as 32 JSON integers is technically the same information and useless to every +/// consumer, and a 7219-byte signature as an array is 30 KiB of JSON. +fn render(value: &scale_value::Value) -> serde_json::Value { + use scale_value::{Composite, Primitive, ValueDef}; + + match &value.value { + ValueDef::Primitive(p) => match p { + Primitive::Bool(b) => serde_json::Value::Bool(*b), + Primitive::Char(c) => serde_json::Value::String(c.to_string()), + Primitive::String(s) => serde_json::Value::String(s.clone()), + // u128/i128 do not survive a JSON number. Strings keep every digit, + // and every consumer of a balance on this chain needs all of them. + Primitive::U128(n) => serde_json::Value::String(n.to_string()), + Primitive::I128(n) => serde_json::Value::String(n.to_string()), + Primitive::U256(b) | Primitive::I256(b) => serde_json::Value::String(hex(b)), + }, + ValueDef::Composite(Composite::Named(fields)) => serde_json::Value::Object( + fields + .iter() + .map(|(k, v)| (k.clone(), render(v))) + .collect(), + ), + ValueDef::Composite(Composite::Unnamed(values)) => { + if let Some(bytes) = as_bytes(values) { + serde_json::Value::String(hex(&bytes)) + } else if values.len() == 1 { + // A newtype wrapper is noise; unwrap it so `Compact` reads + // as a number rather than a one-element array. + render(&values[0]) + } else { + serde_json::Value::Array(values.iter().map(render).collect()) + } + } + ValueDef::Variant(v) => { + let inner = render(&scale_value::Value { + value: ValueDef::Composite(v.values.clone()), + context: value.context, + }); + + // `Era::Immortal` and friends carry nothing; render them as the name + // alone rather than `{"Immortal": []}`. + match &inner { + serde_json::Value::Array(a) if a.is_empty() => { + serde_json::Value::String(v.name.clone()) + } + serde_json::Value::Object(o) if o.is_empty() => { + serde_json::Value::String(v.name.clone()) + } + _ => { + let mut map = serde_json::Map::new(); + map.insert(v.name.clone(), inner); + serde_json::Value::Object(map) + } + } + } + ValueDef::BitSequence(bits) => { + serde_json::Value::Array(bits.iter().map(serde_json::Value::Bool).collect()) + } + } +} + +/// A sequence of `u8` primitives, if that is what this is. +fn as_bytes(values: &[scale_value::Value]) -> Option> { + use scale_value::{Primitive, ValueDef}; + + if values.is_empty() { + return None; + } + + values + .iter() + .map(|v| match &v.value { + ValueDef::Primitive(Primitive::U128(n)) if *n < 256 => Some(*n as u8), + _ => None, + }) + .collect() +} + +fn hex(bytes: &[u8]) -> String { + let mut s = String::with_capacity(2 + bytes.len() * 2); + s.push_str("0x"); + + for b in bytes { + s.push(char::from_digit((b >> 4) as u32, 16).unwrap()); + s.push(char::from_digit((b & 0x0f) as u32, 16).unwrap()); + } + + s +} diff --git a/packages/quantus-codec/src/rs/encode.rs b/packages/quantus-codec/src/rs/encode.rs new file mode 100644 index 00000000..5c2abbdb --- /dev/null +++ b/packages/quantus-codec/src/rs/encode.rs @@ -0,0 +1,503 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Building the bytes that get signed, and the extrinsic that carries them. + +use alloc::collections::BTreeMap; +use alloc::format; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +use parity_scale_codec::Encode; +use scale_value::{Composite, Primitive, Value, ValueDef}; + +use crate::runtime::{CodecError, Runtime}; + +/// What the caller knows about one signed extension. +/// +/// Both halves are optional because most extensions need neither: a zero-sized +/// `ty` contributes nothing to the extrinsic, and a zero-sized `additional` +/// contributes nothing to the payload. Supplying a value for a zero-sized type +/// is not an error; *omitting* one for a non-zero-sized type is. +#[derive(Debug, Clone, Default)] +pub struct ExtensionValue { + pub extra: Option, + pub additional: Option, +} + +/// The two byte strings a signed extrinsic needs from its extensions. +#[derive(Debug, Clone)] +pub struct EncodedExtensions { + /// Goes into the extrinsic, after the signature. + pub extra: Vec, + /// Goes into the signed payload only — never on the wire. + pub additional: Vec, +} + +impl Runtime { + /// Encode a call by name, against this runtime's own call type. + pub fn encode_call( + &self, + pallet: &str, + call: &str, + args: &serde_json::Value, + ) -> Result, CodecError> { + // The outer `Call` enum is a variant per pallet, and each of those + // carries that pallet's own call enum. So a call is two nested variants + // by name, and the indices — which are what actually go on the wire — + // come from the registry rather than from a table in this crate. + let pallet_ty = self.extrinsic.call; + let inner = Value::variant( + call.to_string(), + self.composite_for_call(pallet, call, args)?, + ); + let outer = Value::variant( + pallet.to_string(), + Composite::Unnamed(alloc::vec![inner]), + ); + + let mut out = Vec::new(); + + scale_value::scale::encode_as_type(&outer, pallet_ty, self.types(), &mut out) + .map_err(|e| CodecError::Encode(format!("{pallet}.{call}: {e}")))?; + + Ok(out) + } + + /// Build the argument composite for one call, interpreting `args` against + /// the types the runtime declares for it. + fn composite_for_call( + &self, + pallet: &str, + call: &str, + args: &serde_json::Value, + ) -> Result, CodecError> { + let calls_ty = self + .calls + .get(pallet) + .copied() + .ok_or_else(|| CodecError::NoSuchCall(pallet.to_string()))?; + + let variant = match self.types().resolve(calls_ty).map(|t| &t.type_def) { + Some(scale_info::TypeDef::Variant(v)) => v + .variants + .iter() + .find(|v| v.name == call) + .ok_or_else(|| CodecError::NoSuchCall(format!("{pallet}.{call}")))?, + _ => return Err(CodecError::NoSuchCall(format!("{pallet}.{call}"))), + }; + + let mut fields = Vec::new(); + + for field in &variant.fields { + let name = field.name.clone().unwrap_or_default(); + let supplied = args.get(&name).ok_or_else(|| { + CodecError::Encode(format!("{pallet}.{call}: no value for argument {name}")) + })?; + + fields.push((name, self.json_to_value(supplied, field.ty.id)?)); + } + + Ok(Composite::Named(fields)) + } + + /// Encode every signed extension this runtime declares, in order. + /// + /// ## Why an unsupplied extension is fatal + /// + /// `@polkadot/api` logs `Unknown signed extensions … treating them as + /// no-effect` and writes zero bytes for anything it does not recognise. That + /// guess is correct only while every unrecognised extension happens to be + /// zero-sized, and when it stops being correct the wallet keeps signing — + /// valid signatures over a payload that is missing bytes the runtime put + /// there. The chain calls that `BadProof`, which is also what it calls a + /// wrong key, so the failure is silent, remote and indistinguishable from + /// the one thing it is not. + /// + /// Here the registry decides. An extension whose declared type encodes to + /// nothing contributes nothing and needs no value; anything else must be + /// supplied by the caller or this refuses to build a payload at all. A + /// wallet that cannot sign is a bug report; a wallet that signs the wrong + /// bytes is a support case that never gets diagnosed. + pub fn encode_extensions( + &self, + values: &BTreeMap, + ) -> Result { + let mut extra = Vec::new(); + let mut additional = Vec::new(); + + for def in &self.extensions { + let supplied = values.get(&def.identifier); + + self.encode_half( + def.ty, + supplied.and_then(|v| v.extra.as_ref()), + &def.identifier, + &mut extra, + )?; + + self.encode_half( + def.additional, + supplied.and_then(|v| v.additional.as_ref()), + &def.identifier, + &mut additional, + )?; + } + + Ok(EncodedExtensions { extra, additional }) + } + + fn encode_half( + &self, + ty: u32, + supplied: Option<&serde_json::Value>, + identifier: &str, + out: &mut Vec, + ) -> Result<(), CodecError> { + if self.is_empty_ty(ty) { + // Encodes to nothing whether or not a value was supplied. Writing + // nothing here is a reading of the registry, not an assumption. + return Ok(()); + } + + let value = supplied.ok_or_else(|| CodecError::MissingExtension(identifier.to_string()))?; + let converted = self.json_to_value(value, ty)?; + + scale_value::scale::encode_as_type(&converted, ty, self.types(), out) + .map_err(|e| CodecError::Encode(format!("{identifier}: {e}"))) + } + + /// The bytes a signer signs: `call ‖ extra ‖ additional`. + /// + /// Substrate's own rule from `unchecked_extrinsic.rs` — a payload longer than + /// 256 bytes is signed as its BLAKE2b-256 hash — is **not** applied here. + /// That is the caller's, because the hash belongs with the signing code that + /// also chooses the FIPS 204 context, and splitting one rule across two + /// packages is how the halves drift apart. + pub fn signer_payload( + &self, + call: &[u8], + extensions: &EncodedExtensions, + ) -> Vec { + let mut out = Vec::with_capacity(call.len() + extensions.extra.len() + extensions.additional.len()); + + out.extend_from_slice(call); + out.extend_from_slice(&extensions.extra); + out.extend_from_slice(&extensions.additional); + + out + } + + /// Assemble a signed extrinsic. + /// + /// The preamble is `0b10 << 6 | version`: the type tag says signed and the + /// low six bits carry the version the metadata declares. Not a hard-coded + /// `0x84` — if this runtime ever declares a different extrinsic version, the + /// byte follows it. + /// + /// `signature` is the already-encoded `Signature` type, variant byte + /// included: the signing side knows which ML-DSA scheme the key is, and + /// re-deriving it here from the byte length would be a second source of + /// truth. It is written raw — a fixed-size array takes **no compact length + /// prefix**, which is the detail that a `Vec`-shaped assumption gets + /// wrong by exactly two bytes. + pub fn encode_extrinsic( + &self, + address: &serde_json::Value, + signature: &[u8], + extra: &[u8], + call: &[u8], + ) -> Result, CodecError> { + let mut body = Vec::new(); + + body.push(0b1000_0000 | (self.extrinsic_version() & 0b0011_1111)); + + let addr = self.json_to_value(address, self.extrinsic.address)?; + + scale_value::scale::encode_as_type(&addr, self.extrinsic.address, self.types(), &mut body) + .map_err(|e| CodecError::Encode(format!("address: {e}")))?; + + body.extend_from_slice(signature); + body.extend_from_slice(extra); + body.extend_from_slice(call); + + // The node expects the extrinsic length-prefixed. + let mut out = parity_scale_codec::Compact(body.len() as u64).encode(); + + out.extend_from_slice(&body); + + Ok(out) + } + + /// Interpret a JSON value as a particular registry type. + /// + /// Type-directed on purpose. The same JSON string `"0xa5aa…"` is an + /// `AccountId32`, an `H256` or a `Vec` depending only on what the runtime + /// says goes there, and JSON carries no way to tell them apart. Asking the + /// registry is the only way that stays right across an upgrade. + pub(crate) fn json_to_value( + &self, + json: &serde_json::Value, + ty: u32, + ) -> Result, CodecError> { + use scale_info::TypeDef; + + let def = self + .types() + .resolve(ty) + .map(|t| &t.type_def) + .ok_or_else(|| CodecError::Encode(format!("no registry type {ty}")))?; + + match def { + TypeDef::Compact(c) => self.json_to_value(json, c.type_param.id), + + TypeDef::Primitive(p) => primitive(json, p), + + TypeDef::Array(a) => { + let inner = a.type_param.id; + let want = a.len as usize; + + if let Some(bytes) = hex_bytes(json) { + if bytes.len() != want { + return Err(CodecError::Encode(format!( + "expected {want} bytes, got {}", + bytes.len() + ))); + } + + return Ok(byte_composite(&bytes)); + } + + self.unnamed(json, |_| inner) + } + + TypeDef::Sequence(s) => { + if let Some(bytes) = hex_bytes(json) { + return Ok(byte_composite(&bytes)); + } + + self.unnamed(json, |_| s.type_param.id) + } + + TypeDef::Tuple(t) => { + // An empty tuple is the unit type; JSON `null` and an empty + // array both mean it, and so does anything else, since it + // encodes to no bytes either way. + if t.fields.is_empty() { + return Ok(Value::unnamed_composite([])); + } + + let ids: Vec = t.fields.iter().map(|f| f.id).collect(); + + self.unnamed(json, move |i| ids[i.min(ids.len() - 1)]) + } + + TypeDef::Composite(c) => { + // A single-field struct is transparent, named or not, unless the + // caller actually spelled the field out. `AccountId32(pub [u8; + // 32])` should take the hex string its inner array takes, and + // `CheckMetadataHash { mode }` should take `"Disabled"` — neither + // wrapper is something a caller should have to know about, and + // both are wrappers the *runtime* chose, so the registry is what + // tells us they are there. + if c.fields.len() == 1 { + let name = c.fields[0].name.clone(); + let spelled_out = name + .as_ref() + .zip(json.as_object()) + .is_some_and(|(n, map)| map.contains_key(n.as_str())); + + if !spelled_out { + let inner = self.json_to_value(json, c.fields[0].ty.id)?; + + return Ok(match name { + Some(n) => Value { + value: ValueDef::Composite(Composite::Named(alloc::vec![(n, inner)])), + context: (), + }, + None => Value::unnamed_composite([inner]), + }); + } + } + + match json { + serde_json::Value::Object(map) => { + let mut fields = Vec::new(); + + for f in &c.fields { + let name = f.name.clone().unwrap_or_default(); + let v = map.get(&name).ok_or_else(|| { + CodecError::Encode(format!("no value for field {name}")) + })?; + + fields.push((name, self.json_to_value(v, f.ty.id)?)); + } + + Ok(Value { + value: ValueDef::Composite(Composite::Named(fields)), + context: (), + }) + } + _ => { + let ids: Vec = c.fields.iter().map(|f| f.ty.id).collect(); + + self.unnamed(json, move |i| ids[i.min(ids.len().saturating_sub(1))]) + } + } + } + + TypeDef::Variant(v) => { + // Two spellings, both unambiguous: `"Immortal"` for a variant + // that carries nothing, `{"Id": "0x…"}` for one that does. + let (name, payload) = match json { + serde_json::Value::String(s) => (s.clone(), None), + serde_json::Value::Null => ("None".to_string(), None), + serde_json::Value::Object(map) if map.len() == 1 => { + let (k, v) = map.iter().next().expect("len == 1"); + + (k.clone(), Some(v)) + } + _ => { + return Err(CodecError::Encode(format!( + "cannot read {json} as a variant" + ))) + } + }; + + let variant = v + .variants + .iter() + .find(|x| x.name == name) + .ok_or_else(|| CodecError::Encode(format!("no variant {name}")))?; + + let composite = match (payload, variant.fields.len()) { + (_, 0) => Composite::Unnamed(Vec::new()), + (Some(p), 1) => { + Composite::Unnamed(alloc::vec![self.json_to_value(p, variant.fields[0].ty.id)?]) + } + (Some(p), _) => { + let ids: Vec = variant.fields.iter().map(|f| f.ty.id).collect(); + + match self.unnamed(p, move |i| ids[i.min(ids.len() - 1)])?.value { + ValueDef::Composite(c) => c, + _ => unreachable!("unnamed always returns a composite"), + } + } + (None, _) => { + return Err(CodecError::Encode(format!( + "variant {name} needs a payload" + ))) + } + }; + + Ok(Value::variant(name, composite)) + } + + TypeDef::BitSequence(_) => Err(CodecError::Encode( + "encoding a bit sequence is not supported".to_string(), + )), + } + } + + fn unnamed( + &self, + json: &serde_json::Value, + ty_at: impl Fn(usize) -> u32, + ) -> Result, CodecError> { + let items = match json { + serde_json::Value::Array(a) => a, + _ => { + return Err(CodecError::Encode(format!( + "expected an array, got {json}" + ))) + } + }; + + let mut out = Vec::with_capacity(items.len()); + + for (i, item) in items.iter().enumerate() { + out.push(self.json_to_value(item, ty_at(i))?); + } + + Ok(Value::unnamed_composite(out)) + } +} + +/// Read a JSON value as a SCALE primitive. +/// +/// Numbers arrive as JSON numbers when they fit and as **decimal strings** when +/// they do not: a `u128` balance loses precision above 2^53 in JSON, and this +/// chain's balances are 12 decimal places, so that boundary is reached by +/// ordinary amounts rather than exotic ones. +fn primitive( + json: &serde_json::Value, + p: &scale_info::TypeDefPrimitive, +) -> Result, CodecError> { + use scale_info::TypeDefPrimitive as P; + + let as_u128 = || -> Result { + match json { + serde_json::Value::Number(n) => n + .as_u64() + .map(u128::from) + .ok_or_else(|| CodecError::Encode(format!("{n} is not a whole number"))), + serde_json::Value::String(s) => { + let s = s.trim(); + + if let Some(h) = s.strip_prefix("0x") { + u128::from_str_radix(h, 16) + } else { + s.parse::() + } + .map_err(|e| CodecError::Encode(format!("{s} is not a number: {e}"))) + } + _ => Err(CodecError::Encode(format!("{json} is not a number"))), + } + }; + + Ok(match p { + P::Bool => Value { + value: ValueDef::Primitive(Primitive::Bool(json.as_bool().ok_or_else(|| { + CodecError::Encode(format!("{json} is not a boolean")) + })?)), + context: (), + }, + P::Str => Value { + value: ValueDef::Primitive(Primitive::String( + json.as_str() + .ok_or_else(|| CodecError::Encode(format!("{json} is not a string")))? + .to_string(), + )), + context: (), + }, + P::U8 | P::U16 | P::U32 | P::U64 | P::U128 | P::U256 => Value { + value: ValueDef::Primitive(Primitive::U128(as_u128()?)), + context: (), + }, + P::I8 | P::I16 | P::I32 | P::I64 | P::I128 | P::I256 => Value { + value: ValueDef::Primitive(Primitive::I128(as_u128()? as i128)), + context: (), + }, + P::Char => Err(CodecError::Encode("char is not encodable".to_string()))?, + }) +} + +/// `0x…` as bytes, if this is a hex string. +fn hex_bytes(json: &serde_json::Value) -> Option> { + let s = json.as_str()?.strip_prefix("0x")?; + + if s.len() % 2 != 0 { + return None; + } + + (0..s.len() / 2) + .map(|i| u8::from_str_radix(&s[i * 2..i * 2 + 2], 16).ok()) + .collect() +} + +fn byte_composite(bytes: &[u8]) -> Value<()> { + Value::unnamed_composite(bytes.iter().map(|b| Value { + value: ValueDef::Primitive(Primitive::U128(u128::from(*b))), + context: (), + })) +} diff --git a/packages/quantus-codec/src/rs/runtime.rs b/packages/quantus-codec/src/rs/runtime.rs new file mode 100644 index 00000000..af0956d1 --- /dev/null +++ b/packages/quantus-codec/src/rs/runtime.rs @@ -0,0 +1,230 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +//! The runtime's description of itself, and the handful of things this crate +//! needs to look up in it. +//! +//! Every type id here is *read* from the metadata. Nothing in this file names a +//! pallet, a call, a signed extension or a signature scheme, which is what lets +//! it keep working across a runtime upgrade that changes any of them. + +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +use frame_metadata::v14::RuntimeMetadataV14; +use frame_metadata::{RuntimeMetadata, RuntimeMetadataPrefixed}; +use parity_scale_codec::Decode; + +/// Failures reading a runtime's description, or its data. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum CodecError { + /// The blob is not SCALE-encoded prefixed metadata. + Malformed, + /// Metadata this crate does not read. v14 is what every Quantus runtime + /// observed so far emits; a chain that moves to v15/v16 needs this widened + /// deliberately rather than silently mis-read. + UnsupportedVersion(u8), + /// The runtime does not describe its extrinsic in the usual shape. + NoExtrinsicTypes, + /// No such pallet, or no such call in it. + NoSuchCall(String), + /// A value did not match the type the registry said it would. + Decode(String), + /// A value could not be encoded as the type the registry declares. + Encode(String), + /// A signed extension declares a non-empty type and the caller supplied no + /// value for it. Deliberately fatal — see [`crate::encode`]. + MissingExtension(String), +} + +impl core::fmt::Display for CodecError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Malformed => write!(f, "metadata did not decode"), + Self::UnsupportedVersion(v) => write!(f, "unsupported metadata version {v}"), + Self::NoExtrinsicTypes => write!(f, "runtime describes no extrinsic type"), + Self::NoSuchCall(s) => write!(f, "no such call: {s}"), + Self::Decode(s) => write!(f, "decoding against the registry failed: {s}"), + Self::Encode(s) => write!(f, "encoding against the registry failed: {s}"), + Self::MissingExtension(s) => write!( + f, + "signed extension {s} declares a non-empty type and no value was supplied" + ), + } + } +} + +/// The four type parameters of the extrinsic envelope. +#[derive(Debug, Clone, Copy)] +pub struct ExtrinsicTypes { + pub address: u32, + pub signature: u32, + pub extra: u32, + pub call: u32, +} + +/// One signed extension, as the runtime declares it. +/// +/// `ty` is what it contributes to the extrinsic; `additional` is what it +/// contributes to the signed payload but *not* to the extrinsic. Both are read +/// from the metadata, in the order the runtime applies them, because that order +/// is the payload's byte order. +#[derive(Debug, Clone)] +pub struct ExtensionDef { + pub identifier: String, + pub ty: u32, + pub additional: u32, +} + +/// A runtime, as described by its own metadata. +pub struct Runtime { + pub(crate) metadata: RuntimeMetadataV14, + pub(crate) extrinsic: ExtrinsicTypes, + pub(crate) extensions: Vec, + /// Call type id per pallet name, so `encode_call` need not walk the pallet + /// list for every argument. + pub(crate) calls: BTreeMap, +} + +impl Runtime { + /// Parse metadata exactly as `state_getMetadata` returns it. + /// + /// That RPC takes a block hash and makes the node run `Metadata_metadata` + /// against the runtime code in *that block's* state, so what arrives here is + /// the runtime WASM describing itself, executed by the node. It is the only + /// oracle on this chain that cannot go stale. + pub fn from_metadata(raw: &[u8]) -> Result { + let prefixed = + RuntimeMetadataPrefixed::decode(&mut &raw[..]).map_err(|_| CodecError::Malformed)?; + let metadata = match prefixed.1 { + RuntimeMetadata::V14(v) => v, + other => return Err(CodecError::UnsupportedVersion(version_of(&other))), + }; + + // The envelope's four parameters, by the names `UncheckedExtrinsic` + // gives them. Read from the registry rather than assumed, which is the + // whole point: `Signature` here is + // `qp_dilithium_crypto::types::DilithiumSignatureScheme`, and no decoder + // written against vanilla Substrate would guess that. + let extrinsic = metadata + .types + .resolve(metadata.extrinsic.ty.id) + .and_then(|e| { + let param = |name: &str| { + e.type_params + .iter() + .find(|p| p.name == name) + .and_then(|p| p.ty) + .map(|t| t.id) + }; + Some(ExtrinsicTypes { + address: param("Address")?, + signature: param("Signature")?, + extra: param("Extra")?, + call: param("Call")?, + }) + }) + .ok_or(CodecError::NoExtrinsicTypes)?; + + let extensions = metadata + .extrinsic + .signed_extensions + .iter() + .map(|e| ExtensionDef { + identifier: e.identifier.to_string(), + ty: e.ty.id, + additional: e.additional_signed.id, + }) + .collect(); + + let calls = metadata + .pallets + .iter() + .filter_map(|p| p.calls.as_ref().map(|c| (p.name.to_string(), c.ty.id))) + .collect(); + + Ok(Self { + metadata, + extrinsic, + extensions, + calls, + }) + } + + /// The extrinsic format version the metadata declares. + /// + /// Not to be confused with the preamble byte of any particular extrinsic — + /// see [`crate::decode::decode_extrinsic`], which is where that distinction + /// has teeth. + pub fn extrinsic_version(&self) -> u8 { + self.metadata.extrinsic.version + } + + /// The signed extensions, in the order the runtime applies them. + pub fn extensions(&self) -> &[ExtensionDef] { + &self.extensions + } + + pub fn extrinsic_types(&self) -> ExtrinsicTypes { + self.extrinsic + } + + pub(crate) fn types(&self) -> &scale_info::PortableRegistry { + &self.metadata.types + } + + /// Whether a registry type encodes to nothing at all. + /// + /// The question [`crate::encode`] asks of every signed extension: a + /// zero-sized one contributes no bytes and needs no value from the caller, + /// and anything else does. Answering it from the registry rather than from a + /// list of known extension names is the difference between this crate and + /// the thing it replaces. + pub(crate) fn is_empty_ty(&self, id: u32) -> bool { + match self.metadata.types.resolve(id).map(|t| &t.type_def) { + // The unit type, and a tuple of nothing, are the same thing here. + Some(scale_info::TypeDef::Tuple(t)) => { + t.fields.iter().all(|f| self.is_empty_ty(f.id)) + } + Some(scale_info::TypeDef::Composite(c)) => { + c.fields.iter().all(|f| self.is_empty_ty(f.ty.id)) + } + Some(scale_info::TypeDef::Array(a)) => { + a.len == 0 || self.is_empty_ty(a.type_param.id) + } + _ => false, + } + } +} + +fn version_of(md: &RuntimeMetadata) -> u8 { + match md { + RuntimeMetadata::V14(_) => 14, + RuntimeMetadata::V15(_) => 15, + _ => 0, + } +} + +impl Runtime { + /// [`Runtime::is_empty_ty`], for the bindings module. + pub fn is_empty_ty_pub(&self, id: u32) -> bool { + self.is_empty_ty(id) + } +} + +impl Runtime { + /// [`Runtime::types`], for tests. + pub fn types_pub(&self) -> &scale_info::PortableRegistry { + self.types() + } + + /// [`Runtime::json_to_value`], for tests. + pub fn json_to_value_pub( + &self, + json: &serde_json::Value, + ty: u32, + ) -> Result, CodecError> { + self.json_to_value(json, ty) + } +} diff --git a/packages/quantus-codec/src/rs/tests.rs b/packages/quantus-codec/src/rs/tests.rs new file mode 100644 index 00000000..cca78933 --- /dev/null +++ b/packages/quantus-codec/src/rs/tests.rs @@ -0,0 +1,109 @@ +// Copyright 2026 @quantus/codec authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Tested against metadata captured from the chain, not against a fixture this +//! crate wrote. The point of the package is agreeing with a runtime; a test that +//! agrees with itself proves nothing. + +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +use crate::encode::ExtensionValue; +use crate::runtime::Runtime; + +/// Heisenberg at spec 148, `transactionVersion` 6 — the runtime quantus/extension#7 +/// tier 1 submits to. +const HEISENBERG_V148: &str = include_str!("../../tests/heisenberg-v148.metadata.hex"); + +fn unhex(s: &str) -> Vec { + let s = s.trim(); + let s = s.strip_prefix("0x").unwrap_or(s); + + (0..s.len() / 2) + .map(|i| u8::from_str_radix(&s[i * 2..i * 2 + 2], 16).expect("fixture is hex")) + .collect() +} + +fn heisenberg() -> Runtime { + Runtime::from_metadata(&unhex(HEISENBERG_V148)).expect("fixture is v14 metadata") +} + +#[test] +fn metadata_loads_and_describes_its_extrinsic() { + let rt = heisenberg(); + + assert_eq!(rt.extrinsic_version(), 4); +} + +/// The listing that `@polkadot/api` cannot produce, and the reason this crate +/// exists. Two of these extensions are Quantus-only and polkadot-js writes zero +/// bytes for both halves of them by assumption; here the answer comes from the +/// registry. +#[test] +fn every_signed_extension_is_read_from_the_registry() { + let rt = heisenberg(); + let names: Vec<&str> = rt + .extensions() + .iter() + .map(|e| e.identifier.as_str()) + .collect(); + + for e in rt.extensions() { + println!( + "{:<40} extra={:<5} additional={}", + e.identifier, + !rt.is_empty_ty_pub(e.ty), + !rt.is_empty_ty_pub(e.additional) + ); + } + + // Not an exhaustive list on purpose — asserting the whole tuple would make + // this test a second copy of the runtime, which is the mistake the crate is + // here to avoid. These two are asserted because they are the ones no + // Substrate-shaped decoder knows about. + assert!(names.contains(&"ReversibleTransactionExtension")); + assert!(names.contains(&"WormholeProofRecorderExtension")); +} + +/// The guarantee in [`Runtime::encode_extensions`]: a declared, non-empty +/// extension with no supplied value refuses to produce a payload. +#[test] +fn a_missing_extension_value_is_an_error_not_a_short_payload() { + let rt = heisenberg(); + let empty: BTreeMap = BTreeMap::new(); + + let err = rt + .encode_extensions(&empty) + .expect_err("CheckSpecVersion declares a u32 additional; nothing supplied it"); + + assert!( + err.to_string().contains("no value was supplied"), + "unexpected error: {err}" + ); +} + +/// A `MultiAddress::Id` is a variant carrying a newtype around `[u8; 32]`, and +/// the caller should be able to say so with a hex string and a variant name +/// without knowing about either wrapper. +#[test] +fn an_account_id_encodes_from_its_hex() { + let rt = heisenberg(); + let tys = rt.extrinsic_types(); + let id = "0x".to_string() + &"11".repeat(32); + let json = serde_json::json!({ "Id": id }); + + let value = rt + .json_to_value_pub(&json, tys.address) + .expect("MultiAddress::Id from hex"); + + let mut out = Vec::new(); + + scale_value::scale::encode_as_type(&value, tys.address, rt.types_pub(), &mut out) + .expect("encodes"); + + // Variant index 0 for `Id`, then 32 raw bytes with no length prefix. + assert_eq!(out.len(), 33); + assert_eq!(out[0], 0); + assert_eq!(&out[1..], &[0x11u8; 32]); +} diff --git a/packages/quantus-codec/tests/heisenberg-v148.metadata.hex b/packages/quantus-codec/tests/heisenberg-v148.metadata.hex new file mode 100644 index 00000000..37e596ae --- /dev/null +++ b/packages/quantus-codec/tests/heisenberg-v148.metadata.hex @@ -0,0 +1 @@ +6d6574610e9503000c1c73705f636f72651863727970746f2c4163636f756e7449643332000004000401205b75383b2033325d0000040000032000000008000800000503000c08306672616d655f73797374656d2c4163636f756e74496e666f08144e6f6e636501102c4163636f756e74446174610114001401146e6f6e63651001144e6f6e6365000124636f6e73756d657273100120526566436f756e7400012470726f766964657273100120526566436f756e7400012c73756666696369656e7473100120526566436f756e740001106461746114012c4163636f756e74446174610000100000050500140c3c70616c6c65745f62616c616e6365731474797065732c4163636f756e7444617461041c42616c616e63650118001001106672656518011c42616c616e6365000120726573657276656418011c42616c616e636500011866726f7a656e18011c42616c616e6365000114666c6167731c01284578747261466c61677300001800000507001c0c3c70616c6c65745f62616c616e636573147479706573284578747261466c61677300000400180110753132380000200000050000240c346672616d655f737570706f7274206469737061746368405065724469737061746368436c6173730404540128000c01186e6f726d616c2801045400012c6f7065726174696f6e616c280104540001246d616e6461746f7279280104540000280c2873705f77656967687473247765696768745f76321857656967687400000801207265665f74696d652c010c75363400012870726f6f665f73697a652c010c75363400002c000006300030000005060034083c7072696d69746976655f74797065731048323536000004000401205b75383b2033325d00003800000208003c102873705f72756e74696d651c67656e65726963186469676573741844696765737400000401106c6f677340013c5665633c4469676573744974656d3e000040000002440044102873705f72756e74696d651c67656e6572696318646967657374284469676573744974656d0001142850726552756e74696d650800480144436f6e73656e737573456e67696e654964000038011c5665633c75383e00060024436f6e73656e7375730800480144436f6e73656e737573456e67696e654964000038011c5665633c75383e000400105365616c0800480144436f6e73656e737573456e67696e654964000038011c5665633c75383e000500144f74686572040038011c5665633c75383e0000006452756e74696d65456e7669726f6e6d656e745570646174656400080000480000030400000008004c00000250005008306672616d655f73797374656d2c4576656e745265636f7264080445015404540134000c01147068617365a101011450686173650001146576656e7454010445000118746f70696373350101185665633c543e000054083c7175616e7475735f72756e74696d653052756e74696d654576656e740001401853797374656d04005801706672616d655f73797374656d3a3a4576656e743c52756e74696d653e0000002042616c616e636573040080017c70616c6c65745f62616c616e6365733a3a4576656e743c52756e74696d653e000200485472616e73616374696f6e5061796d656e7404009801a870616c6c65745f7472616e73616374696f6e5f7061796d656e743a3a4576656e743c52756e74696d653e0003001051506f5704009c016c70616c6c65745f71706f773a3a4576656e743c52756e74696d653e000500344d696e696e67526577617264730400ac019470616c6c65745f6d696e696e675f726577617264733a3a4576656e743c52756e74696d653e00060020507265696d6167650400b0017c70616c6c65745f707265696d6167653a3a4576656e743c52756e74696d653e000700245363686564756c65720400b4018070616c6c65745f7363686564756c65723a3a4576656e743c52756e74696d653e0008001c5574696c6974790400cc015470616c6c65745f7574696c6974793a3a4576656e740009004c52657665727369626c655472616e73666572730400d001ac70616c6c65745f72657665727369626c655f7472616e73666572733a3a4576656e743c52756e74696d653e000b003854656368436f6c6c6563746976650400ec01a070616c6c65745f72616e6b65645f636f6c6c6563746976653a3a4576656e743c52756e74696d653e000d0034546563685265666572656e64610400fc01f470616c6c65745f7265666572656e64613a3a4576656e743c52756e74696d652c2070616c6c65745f7265666572656e64613a3a496e7374616e6365313e000e0038547265617375727950616c6c657404008101017c70616c6c65745f74726561737572793a3a4576656e743c52756e74696d653e000f00204d756c746973696704008901017c70616c6c65745f6d756c74697369673a3a4576656e743c52756e74696d653e00130020576f726d686f6c6504008d01017c70616c6c65745f776f726d686f6c653a3a4576656e743c52756e74696d653e001400185a6b5472656504009901017870616c6c65745f7a6b5f747265653a3a4576656e743c52756e74696d653e0015001c56657374696e6704009d01017870616c6c65745f76657374696e673a3a4576656e743c52756e74696d653e00160000580c306672616d655f73797374656d1870616c6c6574144576656e740404540001204045787472696e7369635375636365737304013464697370617463685f696e666f5c014444697370617463684576656e74496e666f00000490416e2065787472696e73696320636f6d706c65746564207375636365737366756c6c792e3c45787472696e7369634661696c656408013864697370617463685f6572726f7268013444697370617463684572726f7200013464697370617463685f696e666f5c014444697370617463684576656e74496e666f00010450416e2065787472696e736963206661696c65642e2c436f64655570646174656400020450603a636f6465602077617320757064617465642e284e65774163636f756e7404011c6163636f756e74000130543a3a4163636f756e7449640003046841206e6577206163636f756e742077617320637265617465642e344b696c6c65644163636f756e7404011c6163636f756e74000130543a3a4163636f756e74496400040458416e206163636f756e7420776173207265617065642e2052656d61726b656408011873656e646572000130543a3a4163636f756e7449640001106861736834011c543a3a48617368000504704f6e206f6e2d636861696e2072656d61726b2068617070656e65642e4455706772616465417574686f72697a6564080124636f64655f6861736834011c543a3a48617368000134636865636b5f76657273696f6e200110626f6f6c00060468416e20757067726164652077617320617574686f72697a65642e8052656a6563746564496e76616c6964417574686f72697a656455706772616465080124636f64655f6861736834011c543a3a486173680001146572726f7268013444697370617463684572726f720007041101416e20696e76616c696420617574686f72697a65642075706772616465207761732072656a6563746564207768696c6520747279696e6720746f206170706c792069742e04704576656e7420666f72207468652053797374656d2070616c6c65742e5c08306672616d655f73797374656d4444697370617463684576656e74496e666f00000c0118776569676874280118576569676874000114636c6173736001344469737061746368436c617373000120706179735f666565640110506179730000600c346672616d655f737570706f7274206469737061746368344469737061746368436c61737300010c184e6f726d616c0000002c4f7065726174696f6e616c000100244d616e6461746f727900020000640c346672616d655f737570706f727420646973706174636810506179730001080c596573000000084e6f0001000068082873705f72756e74696d653444697370617463684572726f7200013c144f746865720000003043616e6e6f744c6f6f6b7570000100244261644f726967696e000200184d6f64756c6504006c012c4d6f64756c654572726f7200030044436f6e73756d657252656d61696e696e670004002c4e6f50726f76696465727300050040546f6f4d616e79436f6e73756d65727300060014546f6b656e0400700128546f6b656e4572726f720007002841726974686d65746963040074013c41726974686d657469634572726f72000800345472616e73616374696f6e616c04007801485472616e73616374696f6e616c4572726f7200090024457868617573746564000a0028436f7272757074696f6e000b002c556e617661696c61626c65000c0038526f6f744e6f74416c6c6f776564000d00105472696504007c0124547269654572726f72000e00006c082873705f72756e74696d652c4d6f64756c654572726f720000080114696e64657808010875380001146572726f7248018c5b75383b204d41585f4d4f44554c455f4552524f525f454e434f4445445f53495a455d000070082873705f72756e74696d6528546f6b656e4572726f720001284046756e6473556e617661696c61626c65000000304f6e6c7950726f76696465720001003042656c6f774d696e696d756d0002003043616e6e6f7443726561746500030030556e6b6e6f776e41737365740004001846726f7a656e0005002c556e737570706f727465640006004043616e6e6f74437265617465486f6c64000700344e6f74457870656e6461626c650008001c426c6f636b65640009000074083473705f61726974686d657469633c41726974686d657469634572726f7200010c24556e646572666c6f77000000204f766572666c6f77000100384469766973696f6e42795a65726f0002000078082873705f72756e74696d65485472616e73616374696f6e616c4572726f72000108304c696d6974526561636865640000001c4e6f4c61796572000100007c0c2873705f72756e74696d653070726f76696e675f7472696524547269654572726f7200013840496e76616c69645374617465526f6f7400000048496e636f6d706c65746544617461626173650001005056616c75654174496e636f6d706c6574654b6579000200304465636f6465724572726f720003002c496e76616c696448617368000400304475706c69636174654b65790005003845787472616e656f75734e6f64650006003c45787472616e656f757356616c75650007005c45787472616e656f7573486173685265666572656e636500080054496e76616c69644368696c645265666572656e63650009003456616c75654d69736d61746368000a003c496e636f6d706c65746550726f6f66000b0030526f6f744d69736d61746368000c002c4465636f64654572726f72000d0000800c3c70616c6c65745f62616c616e6365731870616c6c6574144576656e740804540004490001741c456e646f77656408011c6163636f756e74000130543a3a4163636f756e744964000130667265655f62616c616e6365180128543a3a42616c616e6365000004b8416e206163636f756e74207761732063726561746564207769746820736f6d6520667265652062616c616e63652e20447573744c6f737408011c6163636f756e74000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e63650001083d01416e206163636f756e74207761732072656d6f7665642077686f73652062616c616e636520776173206e6f6e2d7a65726f206275742062656c6f77204578697374656e7469616c4465706f7369742c78726573756c74696e6720696e20616e206f75747269676874206c6f73732e205472616e736665720c011066726f6d000130543a3a4163636f756e744964000108746f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e63650002044c5472616e73666572207375636365656465642e2842616c616e636553657408010c77686f000130543a3a4163636f756e74496400011066726565180128543a3a42616c616e636500030468412062616c616e6365207761732073657420627920726f6f742e20526573657276656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365000404e0536f6d652062616c616e63652077617320726573657276656420286d6f7665642066726f6d206672656520746f207265736572766564292e28556e726573657276656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365000504e8536f6d652062616c616e63652077617320756e726573657276656420286d6f7665642066726f6d20726573657276656420746f2066726565292e4852657365727665526570617472696174656410011066726f6d000130543a3a4163636f756e744964000108746f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e636500014864657374696e6174696f6e5f7374617475738401185374617475730006084d01536f6d652062616c616e636520776173206d6f7665642066726f6d207468652072657365727665206f6620746865206669727374206163636f756e7420746f20746865207365636f6e64206163636f756e742ed846696e616c20617267756d656e7420696e64696361746573207468652064657374696e6174696f6e2062616c616e636520747970652e1c4465706f73697408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365000704d8536f6d6520616d6f756e7420776173206465706f73697465642028652e672e20666f72207472616e73616374696f6e2066656573292e20576974686472617708010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e63650008041d01536f6d6520616d6f756e74207761732077697468647261776e2066726f6d20746865206163636f756e742028652e672e20666f72207472616e73616374696f6e2066656573292e1c536c617368656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e63650009040101536f6d6520616d6f756e74207761732072656d6f7665642066726f6d20746865206163636f756e742028652e672e20666f72206d69736265686176696f72292e184d696e74656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365000a049c536f6d6520616d6f756e7420776173206d696e74656420696e746f20616e206163636f756e742e304d696e746564437265646974040118616d6f756e74180128543a3a42616c616e6365000b04e0536f6d6520637265646974207761732062616c616e63656420616e6420616464656420746f2074686520546f74616c49737375616e63652e184275726e656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365000c049c536f6d6520616d6f756e7420776173206275726e65642066726f6d20616e206163636f756e742e284275726e656444656274040118616d6f756e74180128543a3a42616c616e6365000d04cc536f6d65206465627420686173206265656e2064726f707065642066726f6d2074686520546f74616c2049737375616e63652e2453757370656e64656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365000e041501536f6d6520616d6f756e74207761732073757370656e6465642066726f6d20616e206163636f756e74202869742063616e20626520726573746f726564206c61746572292e20526573746f72656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365000f04a4536f6d6520616d6f756e742077617320726573746f72656420696e746f20616e206163636f756e742e20557067726164656404010c77686f000130543a3a4163636f756e74496400100460416e206163636f756e74207761732075706772616465642e18497373756564040118616d6f756e74180128543a3a42616c616e63650011042d01546f74616c2069737375616e63652077617320696e637265617365642062792060616d6f756e74602c206372656174696e6720612063726564697420746f2062652062616c616e6365642e2452657363696e646564040118616d6f756e74180128543a3a42616c616e63650012042501546f74616c2069737375616e636520776173206465637265617365642062792060616d6f756e74602c206372656174696e672061206465627420746f2062652062616c616e6365642e184c6f636b656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e636500130460536f6d652062616c616e636520776173206c6f636b65642e20556e6c6f636b656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e636500140468536f6d652062616c616e63652077617320756e6c6f636b65642e1846726f7a656e08010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e636500150460536f6d652062616c616e6365207761732066726f7a656e2e1854686177656408010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e636500160460536f6d652062616c616e636520776173207468617765642e1048656c640c0118726561736f6e880150543a3a52756e74696d65486f6c64526561736f6e00010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e636500170480536f6d652062616c616e63652077617320706c61636564206f6e20686f6c642e284275726e656448656c640c0118726561736f6e880150543a3a52756e74696d65486f6c64526561736f6e00010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365001804a048656c642062616c616e636520776173206275726e65642066726f6d20616e206163636f756e742e385472616e736665724f6e486f6c64100118726561736f6e880150543a3a52756e74696d65486f6c64526561736f6e000118736f75726365000130543a3a4163636f756e74496400011064657374000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365001904150141207472616e73666572206f662060616d6f756e7460206f6e20686f6c642066726f6d2060736f757263656020746f206064657374602077617320696e697469617465642e3c5472616e73666572416e64486f6c64100118726561736f6e880150543a3a52756e74696d65486f6c64526561736f6e000118736f75726365000130543a3a4163636f756e74496400011064657374000130543a3a4163636f756e74496400012c7472616e73666572726564180128543a3a42616c616e6365001a04090154686520607472616e73666572726564602062616c616e636520697320706c61636564206f6e20686f6c642061742074686520606465737460206163636f756e742e2052656c65617365640c0118726561736f6e880150543a3a52756e74696d65486f6c64526561736f6e00010c77686f000130543a3a4163636f756e744964000118616d6f756e74180128543a3a42616c616e6365001b0490536f6d652062616c616e6365207761732072656c65617365642066726f6d20686f6c642e28556e65787065637465640400940138556e65787065637465644b696e64001c04b0416e20756e65787065637465642f646566656e73697665206576656e7420776173207472696767657265642e047c54686520604576656e746020656e756d206f6620746869732070616c6c65748414346672616d655f737570706f72741874726169747318746f6b656e73106d6973633442616c616e636553746174757300010810467265650000002052657365727665640001000088083c7175616e7475735f72756e74696d654452756e74696d65486f6c64526561736f6e00010820507265696d61676504008c016c70616c6c65745f707265696d6167653a3a486f6c64526561736f6e0007004c52657665727369626c655472616e7366657273040090019c70616c6c65745f72657665727369626c655f7472616e73666572733a3a486f6c64526561736f6e000b00008c0c3c70616c6c65745f707265696d6167651870616c6c657428486f6c64526561736f6e00010420507265696d61676500000000900c6c70616c6c65745f72657665727369626c655f7472616e73666572731870616c6c657428486f6c64526561736f6e000104445363686564756c65645472616e7366657200000000940c3c70616c6c65745f62616c616e6365731870616c6c657438556e65787065637465644b696e640001083842616c616e636555706461746564000000544661696c6564546f4d75746174654163636f756e7400010000980c6870616c6c65745f7472616e73616374696f6e5f7061796d656e741870616c6c6574144576656e74040454000104485472616e73616374696f6e466565506169640c010c77686f000130543a3a4163636f756e74496400012861637475616c5f66656518013042616c616e63654f663c543e00010c74697018013042616c616e63654f663c543e000008590141207472616e73616374696f6e20666565206061637475616c5f666565602c206f662077686963682060746970602077617320616464656420746f20746865206d696e696d756d20696e636c7573696f6e206665652c5c686173206265656e2070616964206279206077686f602e047c54686520604576656e746020656e756d206f6620746869732070616c6c65749c0c2c70616c6c65745f71706f771870616c6c6574144576656e740404540001083850726f6f665375626d69747465640c01146e6f6e6365a001244e6f6e636554797065000128646966666963756c7479a4011055353132000134686173685f6163686965766564a401105535313200000048446966666963756c747941646a75737465640c01386f6c645f646966666963756c7479a40128446966666963756c74790001386e65775f646966666963756c7479a40128446966666963756c747900014c6f627365727665645f626c6f636b5f74696d65300134426c6f636b4475726174696f6e000100047c54686520604576656e746020656e756d206f6620746869732070616c6c6574a0000003400000000800a4083c7072696d69746976655f7479706573105535313200000400a801205b7536343b20385d0000a8000003080000003000ac0c5470616c6c65745f6d696e696e675f726577617264731870616c6c6574144576656e74040454000110344d696e657252657761726465640801146d696e6572000130543a3a4163636f756e74496404344d696e6572206163636f756e74011872657761726418013042616c616e63654f663c543e041d015175616e74697a6564207265776172642028626c6f636b20726577617264202b20666565732c20616c69676e656420746f2074686520776f726d686f6c65207175616e74756d2900049c41206d696e657220686173206265656e206964656e74696669656420666f72206120626c6f636b3446656573436f6c6c6563746564080118616d6f756e7418013042616c616e63654f663c543e045054686520616d6f756e7420636f6c6c65637465640114746f74616c18013042616c616e63654f663c543e048c546f74616c20666565732077616974696e6720666f7220646973747269627574696f6e0104d85472616e73616374696f6e2066656573207765726520636f6c6c656374656420666f72206c6174657220646973747269627574696f6e385061796f75744465666572726564040118616d6f756e7418013042616c616e63654f663c543e0478416d6f756e742068656c6420666f7220746865206e657874206d696e657202043d014e6f206d696e657220696e20746865206469676573743b207468652063726564697420737461797320696e2060436f6c6c6563746564466565736020666f7220746865206e65787420626c6f636b2e3c4d696e65724d696e744661696c65640801146d696e6572000130543a3a4163636f756e74496404b4546865206d696e65722077686f2073686f756c6420686176652072656365697665642074686520726577617264011872657761726418013042616c616e63654f663c543e04685468652072657761726420616d6f756e742072657461696e6564030405014d696e6572206d696e74206661696c65643b207468652063726564697420737461797320696e2060436f6c6c6563746564466565736020666f722072657472792e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574b00c3c70616c6c65745f707265696d6167651870616c6c6574144576656e7404045400010c144e6f7465640401106861736834011c543a3a48617368000004684120707265696d61676520686173206265656e206e6f7465642e245265717565737465640401106861736834011c543a3a48617368000104784120707265696d61676520686173206265656e207265717565737465642e1c436c65617265640401106861736834011c543a3a486173680002046c4120707265696d616765206861732062656e20636c65617265642e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574b40c4070616c6c65745f7363686564756c65721870616c6c6574144576656e74040454000120245363686564756c65640801107768656eb8016c426c6f636b4e756d6265724f7254696d657374616d704f663c543e000114696e64657810010c753332000004505363686564756c656420736f6d65207461736b2e2043616e63656c65640801107768656eb8016c426c6f636b4e756d6265724f7254696d657374616d704f663c543e000114696e64657810010c7533320001044c43616e63656c656420736f6d65207461736b2e28446973706174636865640c01107461736bbc01405461736b416464726573734f663c543e0001086964c001404f7074696f6e3c5461736b4e616d653e000118726573756c74c401384469737061746368526573756c74000204544469737061746368656420736f6d65207461736b2e2052657472795365741001107461736bbc01405461736b416464726573734f663c543e0001086964c001404f7074696f6e3c5461736b4e616d653e000118706572696f64b8016c426c6f636b4e756d6265724f7254696d657374616d704f663c543e00011c726574726965730801087538000304a0536574206120726574727920636f6e66696775726174696f6e20666f7220736f6d65207461736b2e38526574727943616e63656c6c65640801107461736bbc01405461736b416464726573734f663c543e0001086964c001404f7074696f6e3c5461736b4e616d653e000404ac43616e63656c206120726574727920636f6e66696775726174696f6e20666f7220736f6d65207461736b2e3c43616c6c556e617661696c61626c650801107461736bbc01405461736b416464726573734f663c543e0001086964c001404f7074696f6e3c5461736b4e616d653e00050429015468652063616c6c20666f72207468652070726f7669646564206861736820776173206e6f7420666f756e6420736f20746865207461736b20686173206265656e2061626f727465642e2c52657472794661696c65640801107461736bbc01405461736b416464726573734f663c543e0001086964c001404f7074696f6e3c5461736b4e616d653e0006085d0154686520676976656e207461736b2077617320756e61626c6520746f20626520726574726965642073696e636520746865206167656e64612069732066756c6c206174207468617420626c6f636b206f722074686572659c776173206e6f7420656e6f7567682077656967687420746f2072657363686564756c652069742e545065726d616e656e746c794f7665727765696768740801107461736bbc01405461736b416464726573734f663c543e0001086964c001404f7074696f6e3c5461736b4e616d653e000704f054686520676976656e207461736b2063616e206e657665722062652065786563757465642073696e6365206974206973206f7665727765696768742e04304576656e747320747970652eb8083071705f7363686564756c657258426c6f636b4e756d6265724f7254696d657374616d70082c426c6f636b4e756d6265720110184d6f6d656e74013001082c426c6f636b4e756d626572040010012c426c6f636b4e756d6265720000002454696d657374616d7004003001184d6f6d656e7400010000bc00000408b81000c004184f7074696f6e04045401040108104e6f6e6500000010536f6d650400040000010000c40418526573756c7408045401c8044501680108084f6b0400c8000000000c4572720400680000010000c80000040000cc0c3870616c6c65745f7574696c6974791870616c6c6574144576656e74000108384261746368436f6d706c65746564000004c84261746368206f66206469737061746368657320636f6d706c657465642066756c6c792077697468206e6f206572726f722e344974656d436f6d706c657465640001041d01412073696e676c65206974656d2077697468696e2061204261746368206f6620646973706174636865732068617320636f6d706c657465642077697468206e6f206572726f722e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574d00c6c70616c6c65745f72657665727369626c655f7472616e73666572731870616c6c6574144576656e7404045400011c3c4869676853656375726974795365740c010c77686f000130543a3a4163636f756e744964000120677561726469616e000130543a3a4163636f756e74496404e054686520677561726469616e2077686f2063616e2063616e63656c207472616e736665727320616e64207265636f7665722066756e64732e011464656c6179b8016c426c6f636b4e756d6265724f7254696d657374616d704f663c543e000004c04120757365722068617320656e61626c656420746865697220686967682d73656375726974792073657474696e67732e505472616e73616374696f6e5363686564756c65641c011066726f6d000130543a3a4163636f756e744964000108746f000130543a3a4163636f756e744964000120677561726469616e000130543a3a4163636f756e74496404a854686520677561726469616e2077686f2063616e2063616e63656c2074686973207472616e736665722e012061737365745f6964d401504f7074696f6e3c417373657449644f663c543e3e000118616d6f756e7418013042616c616e63654f663c543e00011474785f696434011c543a3a48617368000128657865637574655f6174d801a8446973706174636854696d653c426c6f636b4e756d626572466f723c543e2c20543a3a4d6f6d656e743e000104dc41207472616e73616374696f6e20686173206265656e207363686564756c656420666f722064656c6179656420657865637574696f6e2e505472616e73616374696f6e43616e63656c6c656408010c77686f000130543a3a4163636f756e74496400011474785f696434011c543a3a48617368000204e041207363686564756c6564207472616e73616374696f6e20686173206265656e207375636365737366756c6c792063616e63656c6c65642e4c5472616e73616374696f6e457865637574656408011474785f696434011c543a3a48617368000118726573756c74dc01684469737061746368526573756c7457697468506f7374496e666f000304d841207363686564756c6564207472616e73616374696f6e2077617320657865637574656420627920746865207363686564756c65722e3846756e64735265636f766572656408011c6163636f756e74000130543a3a4163636f756e744964000120677561726469616e000130543a3a4163636f756e7449640004041901416c6c2066756e64732077657265207265636f76657265642066726f6d206120686967682d7365637572697479206163636f756e742062792069747320677561726469616e2e585472616e736665725265636f766572794661696c656404011474785f696434011c543a3a4861736800050841014661696c656420746f2072656c656173652068656c642066756e647320647572696e67207265636f766572792e20546865207472616e73666572206d657461646174612069732070726573657276656478666f72206d616e75616c20726574727920766961206063616e63656c602e4c5265636f7665727953776565704661696c656408011c6163636f756e74000130543a3a4163636f756e744964000120677561726469616e000130543a3a4163636f756e74496400060c31015468652066696e616c20667265652d62616c616e6365207377656570206f6620607265636f7665725f66756e647360206661696c65642e20416c6c2070656e64696e672d7472616e736665722d0163616e63656c6c6174696f6e7320706572666f726d6564206279207468652073616d652063616c6c2072656d61696e20696e206566666563743b2074686520677561726469616e2063616e2d01726574727920607265636f7665725f66756e64736020746f2073776565702074686520667265652062616c616e6365206f6e636520746865206361757365206973207265736f6c7665642e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574d404184f7074696f6e04045401100108104e6f6e6500000010536f6d650400100000010000d8083071705f7363686564756c657230446973706174636854696d65082c426c6f636b4e756d6265720110184d6f6d656e7401300108084174040010012c426c6f636b4e756d6265720000001441667465720400b801ac426c6f636b4e756d6265724f7254696d657374616d703c426c6f636b4e756d6265722c204d6f6d656e743e00010000dc0418526573756c7408045401e0044501e80108084f6b0400e0000000000c4572720400e80000010000e00c346672616d655f737570706f727420646973706174636840506f73744469737061746368496e666f000008013461637475616c5f776569676874e401384f7074696f6e3c5765696768743e000120706179735f666565640110506179730000e404184f7074696f6e04045401280108104e6f6e6500000010536f6d650400280000010000e8082873705f72756e74696d656444697370617463684572726f7257697468506f7374496e666f0410496e666f01e000080124706f73745f696e666fe00110496e666f0001146572726f7268013444697370617463684572726f720000ec0c6070616c6c65745f72616e6b65645f636f6c6c6563746976651870616c6c6574144576656e740804540004490001142c4d656d626572416464656404010c77686f000130543a3a4163636f756e7449640000047841206d656d626572206077686f6020686173206265656e2061646465642e2c52616e6b4368616e67656408010c77686f000130543a3a4163636f756e74496400011072616e6bf0011052616e6b000104f4546865206d656d626572206077686f6073652072616e6b20686173206265656e206368616e67656420746f2074686520676976656e206072616e6b602e344d656d62657252656d6f76656408010c77686f000130543a3a4163636f756e74496400011072616e6bf0011052616e6b0002041901546865206d656d626572206077686f60206f6620676976656e206072616e6b6020686173206265656e2072656d6f7665642066726f6d2074686520636f6c6c6563746976652e14566f74656410010c77686f000130543a3a4163636f756e744964000110706f6c6c100144506f6c6c496e6465784f663c542c20493e000110766f7465f40128566f74655265636f726400011474616c6c79f8013454616c6c794f663c542c20493e0003085501546865206d656d626572206077686f602068617320766f74656420666f72207468652060706f6c6c6020776974682074686520676976656e2060766f746560206c656164696e6720746f20616e2075706461746564206074616c6c79602e3c4d656d62657245786368616e67656408010c77686f000130543a3a4163636f756e74496400011c6e65775f77686f000130543a3a4163636f756e744964000404f0546865206d656d626572206077686f602068616420746865697220604163636f756e74496460206368616e67656420746f20606e65775f77686f602e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574f00000050400f4086070616c6c65745f72616e6b65645f636f6c6c65637469766528566f74655265636f72640001080c4179650400100114566f7465730000000c4e61790400100114566f74657300010000f8086070616c6c65745f72616e6b65645f636f6c6c6563746976651454616c6c790c045400044900044d00000c0124626172655f6179657310012c4d656d626572496e64657800011061796573100114566f7465730001106e617973100114566f7465730000fc0c4070616c6c65745f7265666572656e64611870616c6c6574144576656e74080454000449000140245375626d69747465640c0114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e0114747261636bf0013c547261636b49644f663c542c20493e04250154686520747261636b2028616e6420627920657874656e73696f6e2070726f706f73616c206469737061746368206f726967696e29206f662074686973207265666572656e64756d2e012070726f706f73616c0101014c426f756e64656443616c6c4f663c542c20493e04805468652070726f706f73616c20666f7220746865207265666572656e64756d2e00048041207265666572656e64756d20686173206265656e207375626d69747465642e544465636973696f6e4465706f736974506c616365640c0114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e010c77686f000130543a3a4163636f756e744964048c546865206163636f756e742077686f20706c6163656420746865206465706f7369742e0118616d6f756e7418013c42616c616e63654f663c542c20493e048454686520616d6f756e7420706c6163656420627920746865206163636f756e742e010494546865206465636973696f6e206465706f73697420686173206265656e20706c616365642e5c4465636973696f6e4465706f736974526566756e6465640c0114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e010c77686f000130543a3a4163636f756e744964048c546865206163636f756e742077686f20706c6163656420746865206465706f7369742e0118616d6f756e7418013c42616c616e63654f663c542c20493e048454686520616d6f756e7420706c6163656420627920746865206163636f756e742e02049c546865206465636973696f6e206465706f73697420686173206265656e20726566756e6465642e384465706f736974536c617368656408010c77686f000130543a3a4163636f756e744964048c546865206163636f756e742077686f20706c6163656420746865206465706f7369742e0118616d6f756e7418013c42616c616e63654f663c542c20493e048454686520616d6f756e7420706c6163656420627920746865206163636f756e742e03046c41206465706f73697420686173206265656e20736c61736865642e3c4465636973696f6e53746172746564100114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e0114747261636bf0013c547261636b49644f663c542c20493e04250154686520747261636b2028616e6420627920657874656e73696f6e2070726f706f73616c206469737061746368206f726967696e29206f662074686973207265666572656e64756d2e012070726f706f73616c0101014c426f756e64656443616c6c4f663c542c20493e04805468652070726f706f73616c20666f7220746865207265666572656e64756d2e011474616c6c79f80120543a3a54616c6c7904b85468652063757272656e742074616c6c79206f6620766f74657320696e2074686973207265666572656e64756d2e0404bc41207265666572656e64756d20686173206d6f76656420696e746f20746865206465636964696e672070686173652e38436f6e6669726d53746172746564040114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e050038436f6e6669726d41626f72746564040114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e060024436f6e6669726d6564080114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e011474616c6c79f80120543a3a54616c6c7904b05468652066696e616c2074616c6c79206f6620766f74657320696e2074686973207265666572656e64756d2e0704210141207265666572656e64756d2068617320656e6465642069747320636f6e6669726d6174696f6e20706861736520616e6420697320726561647920666f7220617070726f76616c2e20417070726f766564040114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e08040d0141207265666572656e64756d20686173206265656e20617070726f76656420616e64206974732070726f706f73616c20686173206265656e207363686564756c65642e2052656a6563746564080114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e011474616c6c79f80120543a3a54616c6c7904b05468652066696e616c2074616c6c79206f6620766f74657320696e2074686973207265666572656e64756d2e0904ac412070726f706f73616c20686173206265656e2072656a6563746564206279207265666572656e64756d2e2054696d65644f7574080114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e011474616c6c79f80120543a3a54616c6c7904b05468652066696e616c2074616c6c79206f6620766f74657320696e2074686973207265666572656e64756d2e0a04d841207265666572656e64756d20686173206265656e2074696d6564206f757420776974686f7574206265696e6720646563696465642e2443616e63656c6c6564080114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e011474616c6c79f80120543a3a54616c6c7904b05468652066696e616c2074616c6c79206f6620766f74657320696e2074686973207265666572656e64756d2e0b048041207265666572656e64756d20686173206265656e2063616e63656c6c65642e184b696c6c6564080114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e011474616c6c79f80120543a3a54616c6c7904b05468652066696e616c2074616c6c79206f6620766f74657320696e2074686973207265666572656e64756d2e0c047441207265666572656e64756d20686173206265656e206b696c6c65642e645375626d697373696f6e4465706f736974526566756e6465640c0114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e010c77686f000130543a3a4163636f756e744964048c546865206163636f756e742077686f20706c6163656420746865206465706f7369742e0118616d6f756e7418013c42616c616e63654f663c542c20493e048454686520616d6f756e7420706c6163656420627920746865206163636f756e742e0d04a4546865207375626d697373696f6e206465706f73697420686173206265656e20726566756e6465642e2c4d65746164617461536574080114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e01106861736834011c543a3a486173680438507265696d61676520686173682e0e049c4d6574616461746120666f722061207265666572656e64756d20686173206265656e207365742e3c4d65746164617461436c6561726564080114696e64657810013c5265666572656e64756d496e6465780460496e646578206f6620746865207265666572656e64756d2e01106861736834011c543a3a486173680438507265696d61676520686173682e0f04ac4d6574616461746120666f722061207265666572656e64756d20686173206265656e20636c65617265642e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574010110346672616d655f737570706f72741874726169747324707265696d616765731c426f756e6465640804540105010448017901010c184c656761637904011068617368340124483a3a4f757470757400000018496e6c696e6504007d010134426f756e646564496e6c696e65000100184c6f6f6b757008011068617368340124483a3a4f757470757400010c6c656e10010c753332000200000501083c7175616e7475735f72756e74696d652c52756e74696d6543616c6c0001301853797374656d0400090101ad0173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c53797374656d2c2052756e74696d653e0000002454696d657374616d700400190101b90173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c54696d657374616d702c2052756e74696d653e0001002042616c616e63657304001d0101b50173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c42616c616e6365732c2052756e74696d653e00020020507265696d6167650400310101b50173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c507265696d6167652c2052756e74696d653e0007001c5574696c6974790400390101b10173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c5574696c6974792c2052756e74696d653e0009004c52657665727369626c655472616e73666572730400410101e10173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c52657665727369626c655472616e73666572732c2052756e74696d653e000b003854656368436f6c6c6563746976650400450101cd0173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c54656368436f6c6c6563746976652c2052756e74696d653e000d0034546563685265666572656e64610400490101c90173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c546563685265666572656e64612c2052756e74696d653e000e0038547265617375727950616c6c65740400610101cd0173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c547265617375727950616c6c65742c2052756e74696d653e000f00204d756c74697369670400650101b50173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c4d756c74697369672c2052756e74696d653e00130020576f726d686f6c650400710101b50173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c576f726d686f6c652c2052756e74696d653e0014001c56657374696e670400750101b10173656c663a3a73705f6170695f68696464656e5f696e636c756465735f636f6e7374727563745f72756e74696d653a3a68696464656e5f696e636c7564653a3a64697370617463680a3a3a43616c6c61626c6543616c6c466f723c56657374696e672c2052756e74696d653e0016000009010c306672616d655f73797374656d1870616c6c65741043616c6c04045400012c1872656d61726b04011872656d61726b38011c5665633c75383e00000c684d616b6520736f6d65206f6e2d636861696e2072656d61726b2e008843616e20626520657865637574656420627920657665727920606f726967696e602e387365745f686561705f7061676573040114706167657330010c753634000104f853657420746865206e756d626572206f6620706167657320696e2074686520576562417373656d626c7920656e7669726f6e6d656e74277320686561702e207365745f636f6465040110636f646538011c5665633c75383e0002046453657420746865206e65772072756e74696d6520636f64652e5c7365745f636f64655f776974686f75745f636865636b73040110636f646538011c5665633c75383e000310190153657420746865206e65772072756e74696d6520636f646520776974686f757420646f696e6720616e7920636865636b73206f662074686520676976656e2060636f6465602e0051014e6f746520746861742072756e74696d652075706772616465732077696c6c206e6f742072756e20696620746869732069732063616c6c656420776974682061206e6f742d696e6372656173696e6720737065632076657273696f6e212c7365745f73746f726167650401146974656d730d0101345665633c4b657956616c75653e0004046853657420736f6d65206974656d73206f662073746f726167652e306b696c6c5f73746f726167650401106b657973150101205665633c4b65793e000504744b696c6c20736f6d65206974656d732066726f6d2073746f726167652e2c6b696c6c5f70726566697808011870726566697838010c4b657900011c7375626b65797310010c75333200061011014b696c6c20616c6c2073746f72616765206974656d7320776974682061206b657920746861742073746172747320776974682074686520676976656e207072656669782e0039012a2a4e4f54453a2a2a2057652072656c79206f6e2074686520526f6f74206f726967696e20746f2070726f7669646520757320746865206e756d626572206f66207375626b65797320756e6465723d0174686520707265666978207765206172652072656d6f76696e6720746f2061636375726174656c792063616c63756c6174652074686520776569676874206f6620746869732066756e6374696f6e2e4472656d61726b5f776974685f6576656e7404011872656d61726b38011c5665633c75383e000704a44d616b6520736f6d65206f6e2d636861696e2072656d61726b20616e6420656d6974206576656e742e44617574686f72697a655f75706772616465040124636f64655f6861736834011c543a3a486173680009106101417574686f72697a6520616e207570677261646520746f206120676976656e2060636f64655f686173686020666f72207468652072756e74696d652e205468652072756e74696d652063616e20626520737570706c696564186c617465722e001901546869732063616c6c2072657175697265732060436f6e6669673a3a417574686f72697a65557067726164654f726967696e602028526f6f742062792064656661756c74292e80617574686f72697a655f757067726164655f776974686f75745f636865636b73040124636f64655f6861736834011c543a3a48617368000a206101417574686f72697a6520616e207570677261646520746f206120676976656e2060636f64655f686173686020666f72207468652072756e74696d652e205468652072756e74696d652063616e20626520737570706c696564186c617465722e005d015741524e494e473a205468697320617574686f72697a657320616e207570677261646520746861742077696c6c2074616b6520706c61636520776974686f757420616e792073616665747920636865636b732c20666f7259016578616d706c652074686174207468652073706563206e616d652072656d61696e73207468652073616d6520616e642074686174207468652076657273696f6e206e756d62657220696e637265617365732e204e6f74f07265636f6d6d656e64656420666f72206e6f726d616c207573652e205573652060617574686f72697a655f757067726164656020696e73746561642e007c546869732063616c6c20726571756972657320526f6f74206f726967696e2e606170706c795f617574686f72697a65645f75706772616465040110636f646538011c5665633c75383e000b24550150726f766964652074686520707265696d616765202872756e74696d652062696e617279292060636f64656020666f7220616e2075706772616465207468617420686173206265656e20617574686f72697a65642e00490149662074686520617574686f72697a6174696f6e20726571756972656420612076657273696f6e20636865636b2c20746869732063616c6c2077696c6c20656e73757265207468652073706563206e616d65e872656d61696e7320756e6368616e67656420616e6420746861742074686520737065632076657273696f6e2068617320696e637265617365642e005901446570656e64696e67206f6e207468652072756e74696d65277320604f6e536574436f64656020636f6e66696775726174696f6e2c20746869732066756e6374696f6e206d6179206469726563746c79206170706c791101746865206e65772060636f64656020696e207468652073616d6520626c6f636b206f7220617474656d707420746f207363686564756c652074686520757067726164652e0060416c6c206f726967696e732061726520616c6c6f7765642e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e0d010000021101001101000004083838001501000002380019010c4070616c6c65745f74696d657374616d701870616c6c65741043616c6c0404540001040c73657404010c6e6f772c0124543a3a4d6f6d656e7400004c54536574207468652063757272656e742074696d652e005501546869732063616c6c2073686f756c6420626520696e766f6b65642065786163746c79206f6e63652070657220626c6f636b2e2049742077696c6c2070616e6963206174207468652066696e616c697a6174696f6ed470686173652c20696620746869732063616c6c206861736e2774206265656e20696e766f6b656420627920746861742074696d652e0041015468652074696d657374616d702073686f756c642062652067726561746572207468616e207468652070726576696f7573206f6e652062792074686520616d6f756e7420737065636966696564206279685b60436f6e6669673a3a4d696e696d756d506572696f64605d2e00c4546865206469737061746368206f726967696e20666f7220746869732063616c6c206d757374206265205f4e6f6e655f2e0051015468697320646973706174636820636c617373206973205f4d616e6461746f72795f20746f20656e73757265206974206765747320657865637574656420696e2074686520626c6f636b2e204265206177617265510174686174206368616e67696e672074686520636f6d706c6578697479206f6620746869732063616c6c20636f756c6420726573756c742065786861757374696e6720746865207265736f757263657320696e206184626c6f636b20746f206578656375746520616e79206f746865722063616c6c732e0034232320436f6d706c657869747931012d20604f2831296020284e6f7465207468617420696d706c656d656e746174696f6e73206f6620604f6e54696d657374616d7053657460206d75737420616c736f20626520604f283129602955012d20312073746f72616765207265616420616e6420312073746f72616765206d75746174696f6e2028636f64656320604f283129602062656361757365206f6620604469645570646174653a3a74616b656020696e402020606f6e5f66696e616c697a656029d42d2031206576656e742068616e646c657220606f6e5f74696d657374616d705f736574602e204d75737420626520604f283129602e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e1d010c3c70616c6c65745f62616c616e6365731870616c6c65741043616c6c080454000449000110507472616e736665725f616c6c6f775f646561746808011064657374210101504163636f756e7449644c6f6f6b75704f663c543e00011476616c75652d010128543a3a42616c616e636500001cd45472616e7366657220736f6d65206c697175696420667265652062616c616e636520746f20616e6f74686572206163636f756e742e003501607472616e736665725f616c6c6f775f6465617468602077696c6c207365742074686520604672656542616c616e636560206f66207468652073656e64657220616e642072656365697665722e11014966207468652073656e6465722773206163636f756e742069732062656c6f7720746865206578697374656e7469616c206465706f736974206173206120726573756c74b06f6620746865207472616e736665722c20746865206163636f756e742077696c6c206265207265617065642e001501546865206469737061746368206f726967696e20666f7220746869732063616c6c206d75737420626520605369676e65646020627920746865207472616e736163746f722e4c7472616e736665725f6b6565705f616c69766508011064657374210101504163636f756e7449644c6f6f6b75704f663c543e00011476616c75652d010128543a3a42616c616e6365000318590153616d6520617320746865205b607472616e736665725f616c6c6f775f6465617468605d2063616c6c2c206275742077697468206120636865636b207468617420746865207472616e736665722077696c6c206e6f74606b696c6c20746865206f726967696e206163636f756e742e00e8393925206f66207468652074696d6520796f752077616e74205b607472616e736665725f616c6c6f775f6465617468605d20696e73746561642e00f05b607472616e736665725f616c6c6f775f6465617468605d3a207374727563742e50616c6c65742e68746d6c236d6574686f642e7472616e73666572307472616e736665725f616c6c08011064657374210101504163636f756e7449644c6f6f6b75704f663c543e0001286b6565705f616c697665200110626f6f6c00043c05015472616e736665722074686520656e74697265207472616e7366657261626c652062616c616e63652066726f6d207468652063616c6c6572206163636f756e742e0059014e4f54453a20546869732066756e6374696f6e206f6e6c7920617474656d70747320746f207472616e73666572205f7472616e7366657261626c655f2062616c616e6365732e2054686973206d65616e7320746861746101616e79206c6f636b65642c2072657365727665642c206f72206578697374656e7469616c206465706f7369747320287768656e20606b6565705f616c6976656020697320607472756560292c2077696c6c206e6f742062655d017472616e7366657272656420627920746869732066756e6374696f6e2e20546f20656e73757265207468617420746869732066756e6374696f6e20726573756c747320696e2061206b696c6c6564206163636f756e742c4501796f75206d69676874206e65656420746f207072657061726520746865206163636f756e742062792072656d6f76696e6720616e79207265666572656e636520636f756e746572732c2073746f72616765406465706f736974732c206574632e2e2e00c0546865206469737061746368206f726967696e206f6620746869732063616c6c206d757374206265205369676e65642e00a02d206064657374603a2054686520726563697069656e74206f6620746865207472616e736665722e59012d20606b6565705f616c697665603a204120626f6f6c65616e20746f2064657465726d696e652069662074686520607472616e736665725f616c6c60206f7065726174696f6e2073686f756c642073656e6420616c6c4d0120206f66207468652066756e647320746865206163636f756e74206861732c2063617573696e67207468652073656e646572206163636f756e7420746f206265206b696c6c6564202866616c7365292c206f72590120207472616e736665722065766572797468696e6720657863657074206174206c6561737420746865206578697374656e7469616c206465706f7369742c2077686963682077696c6c2067756172616e74656520746f9c20206b656570207468652073656e646572206163636f756e7420616c697665202874727565292e106275726e08011476616c75652d010128543a3a42616c616e63650001286b6565705f616c697665200110626f6f6c000a1cfc4275726e2074686520737065636966696564206c697175696420667265652062616c616e63652066726f6d20746865206f726967696e206163636f756e742e002501496620746865206f726967696e2773206163636f756e7420656e64732075702062656c6f7720746865206578697374656e7469616c206465706f736974206173206120726573756c7409016f6620746865206275726e20616e6420606b6565705f616c697665602069732066616c73652c20746865206163636f756e742077696c6c206265207265617065642e005101556e6c696b652073656e64696e672066756e647320746f2061205f6275726e5f20616464726573732c207768696368206d6572656c79206d616b6573207468652066756e647320696e61636365737369626c652c21017468697320606275726e60206f7065726174696f6e2077696c6c2072656475636520746f74616c2069737375616e63652062792074686520616d6f756e74205f6275726e65645f2e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e21010c2873705f72756e74696d65306d756c746961646472657373304d756c74694164647265737308244163636f756e7449640100304163636f756e74496e64657801c8011408496404000001244163636f756e74496400000014496e6465780400250101304163636f756e74496e6465780001000c526177040038011c5665633c75383e0002002441646472657373333204000401205b75383b2033325d000300244164647265737332300400290101205b75383b2032305d000400002501000006c80029010000031400000008002d01000006180031010c3c70616c6c65745f707265696d6167651870616c6c65741043616c6c040454000114346e6f74655f707265696d616765040114627974657338011c5665633c75383e000010745265676973746572206120707265696d616765206f6e2d636861696e2e00550149662074686520707265696d616765207761732070726576696f75736c79207265717565737465642c206e6f2066656573206f72206465706f73697473206172652074616b656e20666f722070726f766964696e67550174686520707265696d6167652e204f74686572776973652c2061206465706f7369742069732074616b656e2070726f706f7274696f6e616c20746f207468652073697a65206f662074686520707265696d6167652e3c756e6e6f74655f707265696d6167650401106861736834011c543a3a48617368000118dc436c65617220616e20756e72657175657374656420707265696d6167652066726f6d207468652072756e74696d652073746f726167652e00fc496620606c656e602069732070726f76696465642c207468656e2069742077696c6c2062652061206d7563682063686561706572206f7065726174696f6e2e0001012d206068617368603a205468652068617368206f662074686520707265696d61676520746f2062652072656d6f7665642066726f6d207468652073746f72652eb82d20606c656e603a20546865206c656e677468206f662074686520707265696d616765206f66206068617368602e40726571756573745f707265696d6167650401106861736834011c543a3a48617368000210410152657175657374206120707265696d6167652062652075706c6f6164656420746f2074686520636861696e20776974686f757420706179696e6720616e792066656573206f72206465706f736974732e00550149662074686520707265696d6167652072657175657374732068617320616c7265616479206265656e2070726f7669646564206f6e2d636861696e2c20776520756e7265736572766520616e79206465706f7369743901612075736572206d6179206861766520706169642c20616e642074616b652074686520636f6e74726f6c206f662074686520707265696d616765206f7574206f662074686569722068616e64732e48756e726571756573745f707265696d6167650401106861736834011c543a3a4861736800030cbc436c65617220612070726576696f75736c79206d616465207265717565737420666f72206120707265696d6167652e002d014e4f54453a2054484953204d555354204e4f542042452043414c4c4544204f4e20606861736860204d4f52452054494d4553205448414e2060726571756573745f707265696d616765602e38656e737572655f75706461746564040118686173686573350101305665633c543a3a486173683e00040cbc456e737572652074686174207468652062756c6b206f66207072652d696d616765732069732075706772616465642e003d015468652063616c6c65722070617973206e6f20666565206966206174206c6561737420393025206f66207072652d696d616765732077657265207375636365737366756c6c7920757064617465642e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e3501000002340039010c3870616c6c65745f7574696c6974791870616c6c65741043616c6c0404540001042462617463685f616c6c04011463616c6c733d01017c5665633c3c5420617320436f6e6669673e3a3a52756e74696d6543616c6c3e000240ec53656e642061206261746368206f662064697370617463682063616c6c7320616e642061746f6d6963616c6c792065786563757465207468656d2e21015468652077686f6c65207472616e73616374696f6e2077696c6c20726f6c6c6261636b20616e64206661696c20696620616e79206f66207468652063616c6c73206661696c65642e00b04d61792062652063616c6c65642066726f6d20616e79206f726967696e2065786365707420604e6f6e65602e005d012d206063616c6c73603a205468652063616c6c7320746f20626520646973706174636865642066726f6d207468652073616d65206f726967696e2e20546865206e756d626572206f662063616c6c206d757374206e6f74390120206578636565642074686520636f6e7374616e743a2060626174636865645f63616c6c735f6c696d6974602028617661696c61626c6520696e20636f6e7374616e74206d65746164617461292e0055014966206f726967696e20697320726f6f74207468656e207468652063616c6c7320617265206469737061746368656420776974686f757420636865636b696e67206f726967696e2066696c7465722e202854686973ec696e636c7564657320627970617373696e6720606672616d655f73797374656d3a3a436f6e6669673a3a4261736543616c6c46696c74657260292e0034232320436f6d706c6578697479d02d204f284329207768657265204320697320746865206e756d626572206f662063616c6c7320746f20626520626174636865642e00190143616c6c20696e6465782032206973207072657365727665642066726f6d2074686520757073747265616d207574696c6974792070616c6c657420736f206578697374696e6735016062617463685f616c6c6020656e636f64696e6773206b656570206465636f64696e6720616674657220746865206f7468657220636f6d62696e61746f727320776572652072656d6f7665642e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e3d0100000205010041010c6c70616c6c65745f72657665727369626c655f7472616e73666572731870616c6c65741043616c6c040454000118447365745f686967685f736563757269747908011464656c6179b8016c426c6f636b4e756d6265724f7254696d657374616d704f663c543e000120677561726469616e000130543a3a4163636f756e7449640000c8f4456e61626c6520686967682d736563757269747920666f72207468652063616c6c696e67206163636f756e742077697468206120737065636966696564507265766572736962696c6974792064656c61792e000d014f6e636520616e206163636f756e742069732073657420617320686967682073656375726974792069742063616e206f6e6c79206d616b652072657665727369626c65b47472616e73666572732e204974206973206e6f7420616c6c6f77656420616e79206f746865722063616c6c732e009423205761726e696e673a205065726d616e656e7420616e6420497272657665727369626c650035012a2a456e61626c696e672068696768207365637572697479206d6f64652069732061206f6e652d776179206f7065726174696f6e20746861742063616e6e6f7420626520756e646f6e652e2a2a0041014f6e636520746869732066756e6374696f6e2069732063616c6c6564207375636365737366756c6c792c20746865206163636f756e74206973207065726d616e656e746c79207265737472696374656484746f206f6e6c792074686520666f6c6c6f77696e67206f7065726174696f6e733a41012d205b607363686564756c655f7472616e73666572605d2853656c663a3a7363686564756c655f7472616e7366657229202d205363686564756c652064656c61796564206e617469766520746f6b656e2c20207472616e7366657273d42d205b6063616e63656c605d2853656c663a3a63616e63656c29202d2043616e63656c2070656e64696e67207472616e736665727355012d205b607265636f7665725f66756e6473605d2853656c663a3a7265636f7665725f66756e647329202d20477561726469616e2d696e6974696174656420656d657267656e63792066756e64207265636f766572790035015468657265206973206e6f206d656368616e69736d20746f2064697361626c652068696768207365637572697479206d6f6465206f7220726573746f7265206e6f726d616c206163636f756e74450166756e6374696f6e616c6974792e20546869732064657369676e20697320696e74656e74696f6e616c20746f2070726f76696465206d6178696d756d2073656375726974792067756172616e746565733a4901616e2061747461636b65722077686f206761696e732061636365737320746f20746865206163636f756e742063616e6e6f742073696d706c792064697361626c65207468652070726f74656374696f6e732e00390154686973207065726d616e656e636520616c736f20656e7375726573207468617420616e792066756e64732073756273657175656e746c792073656e7420746f206120636f6d70726f6d697365643d016163636f756e742028652e672e2c2066726f6d2070656e64696e67207061796d656e74732c20636f6e7472616374732c206f72206163636964656e74616c206465706f73697473292072656d61696ec870726f74656374656420616e642063616e206265207265636f76657265642062792074686520677561726469616e2076696135015b607265636f7665725f66756e6473605d2853656c663a3a7265636f7665725f66756e6473292e2054686520677561726469616e2063616e2063616c6c20607265636f7665725f66756e6473605472657065617465646c79206173206e65656465642e00410155736572732077686f206e6f206c6f6e676572207769736820746f2075736520686967682d73656375726974792066656174757265732063616e2073696d706c79207472616e73666572207468656972490166756e647320746f206120646966666572656e74206163636f756e74207573696e67205b607363686564756c655f7472616e73666572605d2853656c663a3a7363686564756c655f7472616e73666572292e00302320506172616d65746572730055012d206064656c6179603a20546865207265766572736962696c6974792074696d6520666f7220616e79207472616e73666572206d6164652062792074686520686967682d7365637572697479206163636f756e742e59012d2060677561726469616e603a2054686520677561726469616e206163636f756e7420746861742063616e2063616e63656c2070656e64696e67207472616e736665727320616e64207265636f7665722066756e647388202066726f6d207468697320686967682d7365637572697479206163636f756e742e007c232043686f6f73652074686520677561726469616e206361726566756c6c7900010154686520677561726469616e20686f6c647320696e7374616e742c20746f74616c207365697a75726520706f7765723a20607265636f7665725f66756e647360fc73776565707320657665727920686f6c6420706c75732074686520656e7469726520667265652062616c616e636520746f2074686520677561726469616e2cec77697468206e6f2064656c61792c206e6f207365636f6e6420617070726f7665722c20616e64206e6f2077617920746f206368616e676520746865f472656c6174696f6e7368697020616674657277617264732e20412073696e676c652d6b657920677561726469616e206973207468657265666f72652061f873696e676c6520706f696e74206f66206661696c75726520666f72207468652077686f6c6520736368656d652e202a2a5573652061206d756c74697369670101616464726573732061732074686520677561726469616e2a2a3a206070616c6c65745f6d756c74697369676020646973706174636865732063616c6c732061730501697473206465726976656420616464726573732c20736f2061206d756c74697369672063616e2063616e63656c20616e64207265636f7665722065786163746c79546c696b65206120706c61696e206163636f756e742e00f4477561726469616e7368697020697320646973636f76657261626c65206f6666636861696e2028652e672e205375627371756964292076696120746865e86048696768536563757269747953657460206576656e743b2074686572652069732064656c696265726174656c79206e6f206f6e2d636861696e8c677561726469616e20696e64657820746f2066696c6c207570206f722067726965662e1863616e63656c04011474785f696434011c543a3a4861736800010c010143616e63656c20612070656e64696e672072657665727369626c65207472616e73616374696f6e207363686564756c6564206279207468652063616c6c65722e00f82d206074785f6964603a2054686520756e69717565206964656e746966696572206f6620746865207472616e73616374696f6e20746f2063616e63656c2e40657865637574655f7472616e7366657204011474785f696434011c543a3a486173680002643101457865637574657320612070726576696f75736c79207363686564756c6564207472616e73666572206166746572207468652064656c617920706572696f642068617320656c61707365642e001d01546869732065787472696e7369632069732063616c6c6564206175746f6d61746963616c6c7920627920746865205363686564756c65722070616c6c6574207768656e20746865390164656c617920706572696f6420657870697265732e204974206d757374206265207369676e656420627920746869732070616c6c65742773206163636f756e7420286e6f7420612075736572292eec5468652070616c6c6574206163636f756e742069732073657420617320746865206f726967696e207768656e207363686564756c696e67207669617460646f5f7363686564756c655f7472616e736665725f696e6e6572602e00302320506172616d65746572730011012d206074785f6964603a2054686520756e69717565206964656e746966696572206f66207468652070656e64696e67207472616e7366657220746f20657865637574652e002901457865637574696f6e207573657320607472616e736665725f616c6c6f775f64656174686020736f20612073656e6465722077686f207370656e74207468656972206c6566746f7665723101667265652062616c616e636520647572696e67207468652064656c6179207374696c6c20636f6d706c657465732e2041206661696c656420696e6e6572207472616e736665722028652e672e110164657374206f766572666c6f772c206f722060616d6f756e74203c2045446020746f2061206e6577206163636f756e742920646f6573206e6f74206661696c20746869732d0165787472696e7369633a2074686520686f6c6420697320616c72656164792072656c656173656420616e64207468652070656e64696e67207472616e7366657220697320616c72656164790d0172656d6f7665642e2050726f7061676174696e672074686174206572726f7220776f756c6420726f6c6c206261636b2074686f73652077726974657320284652414d452d01646973706174636861626c657320617265207472616e73616374696f6e616c29207768696c65205363686564756c6572207465726d696e616c6c792064726f707320746865206e616d656435017461736b2c20667265657a696e67207468652066756e64732077697468206e6f2072657472792e2054686520696e6e657220726573756c74206973207374696c6c207265636f72646564206f6e7c5b604576656e743a3a5472616e73616374696f6e4578656375746564605d2e002023204572726f7273005d012d205b60496e76616c69645363686564756c65724f726967696e605d284572726f723a3a496e76616c69645363686564756c65724f726967696e293a2043616c6c656420627920616e206163636f756e74206f746865727420207468616e20746869732070616c6c65742773206163636f756e742e51012d205b6050656e64696e6754784e6f74466f756e64605d284572726f723a3a50656e64696e6754784e6f74466f756e64293a204e6f2070656e64696e67207472616e73666572207769746820746869732049442e447363686564756c655f7472616e7366657208011064657374210101f43c3c54206173206672616d655f73797374656d3a3a436f6e6669673e3a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f75726365000118616d6f756e7418013042616c616e63654f663c543e000304b45363686564756c652061207472616e73616374696f6e20666f722064656c6179656420657865637574696f6e2e707363686564756c655f7472616e736665725f776974685f64656c61790c011064657374210101f43c3c54206173206672616d655f73797374656d3a3a436f6e6669673e3a3a4c6f6f6b7570206173205374617469634c6f6f6b75703e3a3a536f75726365000118616d6f756e7418013042616c616e63654f663c543e00011464656c6179b8016c426c6f636b4e756d6265724f7254696d657374616d704f663c543e0004182d015363686564756c652061207472616e73616374696f6e20666f722064656c6179656420657865637574696f6e2077697468206120637573746f6d2c206f6e652d74696d652064656c61792e001501546869732063616e206f6e6c792062652075736564206279206163636f756e747320746861742068617665202a6e6f742a2073657420757020612070657273697374656e74d47265766572736962696c69747920636f6e66696775726174696f6e207769746820607365745f686967685f7365637572697479602e0041012d206064656c6179603a205468652074696d652028696e20626c6f636b73206f72206d696c6c697365636f6e647329206265666f726520746865207472616e73616374696f6e2065786563757465732e347265636f7665725f66756e647304011c6163636f756e74000130543a3a4163636f756e74496400078c1501416c6c6f77732074686520677561726469616e20746f207265636f76657220616c6c2066756e64732066726f6d206120686967682d7365637572697479206163636f756e74c46279207472616e7366657272696e672074686520656e746972652062616c616e636520746f207468656d73656c7665732e0051015468697320697320616e20656d657267656e63792066756e6374696f6e20666f72207768656e2074686520686967682d7365637572697479206163636f756e74206d617920626520636f6d70726f6d697365642e350149742063616e63656c7320616c6c2070656e64696e67207472616e736665727320666972737420286170706c79696e6720766f6c756d652066656573292c207468656e207472616e7366657273ac7468652072656d61696e696e6720667265652062616c616e636520746f2074686520677561726469616e2e0078232043616e63656c207673207265636f7665727920617574686f726974790039015065722d7472616e73666572206063616e63656c6020667265657a657320617574686f7269747920696e206070656e64696e672e677561726469616e60206174207363686564756c652074696d65390128736f2061206c6174657220607365745f686967685f7365637572697479602063616e6e6f7420726577726974652063616e63656c20726967687473206f6e207072652d656e726f6c6c6d656e7441016f6e652d74696d65207472616e7366657273292e20607265636f7665725f66756e64736020646f6573202a2a6e6f742a2a20757365207468617420667265657a653a20697420617574686f72697a65733901616761696e737420746865202a6c6976652a20686967682d736563757269747920677561726469616e20616e64207365697a65732065766572792070656e64696e6720686f6c64206f6e207468652d016163636f756e742028766f6c756d6520666565206170706c696564292e2054686174206173796d6d6574727920697320696e74656e74696f6e616c20e28094207265636f76657279206973e47365697a652d7468652d6163636f756e742c206e6f742061206261746368206f662066726f7a656e2063616e63656c20706f6c69636965732e004c23205265706561746564205265636f76657279004501546869732066756e6374696f6e2063616e2062652063616c6c6564206d756c7469706c652074696d6573206f6e207468652073616d65206163636f756e742e2054686520686967682d7365637572697479550173746174757320616e6420677561726469616e2072656c6174696f6e736869702061726520696e74656e74696f6e616c6c7920707265736572766564206166746572207265636f766572792c20656e737572696e6749017468617420616e792066756e64732073756273657175656e746c79206465706f736974656420746f20746865206163636f756e742028652e672e2c2066726f6d2070656e64696e67207061796d656e74732c1101636f6e7472616374732c206f72206163636964656e74616c206465706f73697473292072656d61696e2070726f74656374656420616e64207265636f76657261626c652e004023204572726f722048616e646c696e6700490149662072656c656173696e672068656c642066756e6473206661696c7320666f7220616e79207472616e736665722c2074686174207472616e7366657220697320736b697070656420286d65746164617461410170726573657276656420666f72206d616e75616c20726574727920766961206063616e63656c602920616e64206120605472616e736665725265636f766572794661696c656460206576656e74206973c8656d69747465642e204f74686572207472616e736665727320636f6e74696e756520746f2062652070726f6365737365642e00350154686520636c6f73696e6720667265652d62616c616e636520737765657020746f2074686520677561726469616e206973206c696b657769736520626573742d6566666f72743a2069662069743d016661696c732028652e672e2074686520677561726469616e2063616e6e6f742072656365697665207468652066756e6473292c207468652063616c6c207374696c6c20737563636565647320616e643901616c6c2063616e63656c6c6174696f6e7320706572666f726d65642061626f76652072656d61696e20696e2065666665637420e280942074686579206d757374206e6f7420626520726f6c6c65643d016261636b2c206f72207468652070656e64696e67207472616e736665727320776f756c642062652072652d61726d656420616e642065786563757465206174207468656972207363686564756c65643d0174696d652e204120605265636f7665727953776565704661696c656460206576656e7420697320656d697474656420696e7374656164206f66206046756e64735265636f7665726564602c20616e64fc74686520677561726469616e2063616e2063616c6c20607265636f7665725f66756e64736020616761696e20746f207265747279207468652073776565702e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e45010c6070616c6c65745f72616e6b65645f636f6c6c6563746976651870616c6c65741043616c6c08045400044900011c286164645f6d656d62657204010c77686f210101504163636f756e7449644c6f6f6b75704f663c543e0000185c496e74726f647563652061206e6577206d656d6265722e00902d20606f726967696e603a204d7573742062652074686520604164644f726967696e602ee82d206077686f603a204163636f756e74206f66206e6f6e2d6d656d6265722077686963682077696c6c206265636f6d652061206d656d6265722e00385765696768743a20604f283129603870726f6d6f74655f6d656d62657204010c77686f210101504163636f756e7449644c6f6f6b75704f663c543e000118c0496e6372656d656e74207468652072616e6b206f6620616e206578697374696e67206d656d626572206279206f6e652e00a02d20606f726967696e603a204d75737420626520746865206050726f6d6f74654f726967696e602e902d206077686f603a204163636f756e74206f66206578697374696e67206d656d6265722e00385765696768743a20604f283129603464656d6f74655f6d656d62657204010c77686f210101504163636f756e7449644c6f6f6b75704f663c543e00021c5d0144656372656d656e74207468652072616e6b206f6620616e206578697374696e67206d656d626572206279206f6e652e20496620746865206d656d62657220697320616c72656164792061742072616e6b207a65726f2c7c7468656e2074686579206172652072656d6f76656420656e746972656c792e009c2d20606f726967696e603a204d75737420626520746865206044656d6f74654f726967696e602ef82d206077686f603a204163636f756e74206f66206578697374696e67206d656d626572206f662072616e6b2067726561746572207468616e207a65726f2e0009015765696768743a20604f283129602c206c65737320696620746865206d656d626572277320696e646578206973206869676865737420696e206974732072616e6b2e3472656d6f76655f6d656d62657208010c77686f210101504163636f756e7449644c6f6f6b75704f663c543e0001206d696e5f72616e6bf0011052616e6b00031c6c52656d6f766520746865206d656d62657220656e746972656c792e009c2d20606f726967696e603a204d75737420626520746865206052656d6f76654f726967696e602ef82d206077686f603a204163636f756e74206f66206578697374696e67206d656d626572206f662072616e6b2067726561746572207468616e207a65726f2ec02d20606d696e5f72616e6b603a205468652072616e6b206f6620746865206d656d626572206f7220677265617465722e00585765696768743a20604f286d696e5f72616e6b29602e10766f7465080110706f6c6c100144506f6c6c496e6465784f663c542c20493e00010c617965200110626f6f6c00042cf041646420616e20617965206f72206e617920766f746520666f72207468652073656e64657220746f2074686520676976656e2070726f706f73616c2e00c42d20606f726967696e603a204d75737420626520605369676e6564602062792061206d656d626572206163636f756e742eac2d2060706f6c6c603a20496e646578206f66206120706f6c6c207768696368206973206f6e676f696e672e29012d2060617965603a206074727565602069662074686520766f746520697320746f20617070726f7665207468652070726f706f73616c2c206066616c736560206f74686572776973652e0045015472616e73616374696f6e2066656573206172652062652077616976656420696620746865206d656d62657220697320766f74696e67206f6e20616e7920706172746963756c61722070726f706f73616c5101666f72207468652066697273742074696d6520616e64207468652063616c6c206973207375636365737366756c2e2053756273657175656e7420766f7465206368616e6765732077696c6c206368617267652061106665652e0035015765696768743a20604f283129602c206c65737320696620746865726520776173206e6f2070726576696f757320766f7465206f6e2074686520706f6c6c20627920746865206d656d6265722e30636c65616e75705f706f6c6c080128706f6c6c5f696e646578100144506f6c6c496e6465784f663c542c20493e00010c6d617810010c753332000528d452656d6f766520766f7465732066726f6d2074686520676976656e20706f6c6c2e204974206d757374206861766520656e6465642e00b02d20606f726967696e603a204d75737420626520605369676e65646020627920616e79206163636f756e742e49012d2060706f6c6c5f696e646578603a20496e646578206f66206120706f6c6c20776869636820697320636f6d706c6574656420616e6420666f7220776869636820766f74657320636f6e74696e756520746f20202065786973742efc2d20606d6178603a204d6178696d756d206e756d626572206f6620766f7465206974656d732066726f6d2072656d6f766520696e20746869732063616c6c2e00ec5472616e73616374696f6e2066656573206172652077616976656420696620746865206f7065726174696f6e206973207375636365737366756c2e00150157656967687420604f286d6178296020286c65737320696620746865726520617265206665776572206974656d7320746f2072656d6f7665207468616e20606d617860292e3c65786368616e67655f6d656d62657208010c77686f210101504163636f756e7449644c6f6f6b75704f663c543e00011c6e65775f77686f210101504163636f756e7449644c6f6f6b75704f663c543e000614050145786368616e6765732061206d656d62657220776974682061206e6577206163636f756e7420616e64207468652073616d65206578697374696e672072616e6b2e00a42d20606f726967696e603a204d75737420626520746865206045786368616e67654f726967696e602e39012d206077686f603a204163636f756e74206f66206578697374696e67206d656d626572206f662072616e6b2067726561746572207468616e207a65726f20746f2062652065786368616e6765642e59012d20606e65775f77686f603a204e6577204163636f756e74206f66206578697374696e67206d656d626572206f662072616e6b2067726561746572207468616e207a65726f20746f2065786368616e67656420746f2e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e49010c4070616c6c65745f7265666572656e64611870616c6c65741043616c6c080454000449000124187375626d69740c013c70726f706f73616c5f6f726967696e4d01015c426f783c50616c6c6574734f726967696e4f663c543e3e00012070726f706f73616c0101014c426f756e64656443616c6c4f663c542c20493e000140656e6163746d656e745f6d6f6d656e7459010188446973706174636854696d653c426c6f636b4e756d626572466f723c542c20493e3e000024b050726f706f73652061207265666572656e64756d206f6e20612070726976696c6567656420616374696f6e2e0059012d20606f726967696e603a206d75737420626520605375626d69744f726967696e6020616e6420746865206163636f756e74206d757374206861766520605375626d697373696f6e4465706f736974602066756e6473302020617661696c61626c652e2d012d206070726f706f73616c5f6f726967696e603a20546865206f726967696e2066726f6d207768696368207468652070726f706f73616c2073686f756c642062652065786563757465642e6c2d206070726f706f73616c603a205468652070726f706f73616c2e15012d2060656e6163746d656e745f6d6f6d656e74603a20546865206d6f6d656e742074686174207468652070726f706f73616c2073686f756c6420626520656e61637465642e0048456d69747320605375626d6974746564602e58706c6163655f6465636973696f6e5f6465706f736974040114696e64657810013c5265666572656e64756d496e646578000120ac506f737420746865204465636973696f6e204465706f73697420666f722061207265666572656e64756d2e0039012d20606f726967696e603a206d75737420626520605369676e65646020616e6420746865206163636f756e74206d75737420686176652066756e647320617661696c61626c6520666f7220746865a020207265666572656e64756d277320747261636b2773204465636973696f6e204465706f7369742e51012d2060696e646578603a2054686520696e646578206f6620746865207375626d6974746564207265666572656e64756d2077686f7365204465636973696f6e204465706f7369742069732079657420746f206265242020706f737465642e0078456d69747320604465636973696f6e4465706f736974506c61636564602e5c726566756e645f6465636973696f6e5f6465706f736974040114696e64657810013c5265666572656e64756d496e64657800021c2901526566756e6420746865204465636973696f6e204465706f73697420666f72206120636c6f736564207265666572656e64756d206261636b20746f20746865206465706f7369746f722e009c2d20606f726967696e603a206d75737420626520605369676e656460206f722060526f6f74602e4d012d2060696e646578603a2054686520696e646578206f66206120636c6f736564207265666572656e64756d2077686f7365204465636973696f6e204465706f73697420686173206e6f7420796574206265656e2c2020726566756e6465642e0080456d69747320604465636973696f6e4465706f736974526566756e646564602e1863616e63656c040114696e64657810013c5265666572656e64756d496e6465780003187443616e63656c20616e206f6e676f696e67207265666572656e64756d2e009c2d20606f726967696e603a206d75737420626520746865206043616e63656c4f726967696e602edc2d2060696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f2062652063616e63656c6c65642e0048456d697473206043616e63656c6c6564602e106b696c6c040114696e64657810013c5265666572656e64756d496e646578000418d043616e63656c20616e206f6e676f696e67207265666572656e64756d20616e6420736c61736820746865206465706f736974732e00942d20606f726967696e603a206d7573742062652074686520604b696c6c4f726967696e602edc2d2060696e646578603a2054686520696e646578206f6620746865207265666572656e64756d20746f2062652063616e63656c6c65642e0090456d69747320604b696c6c65646020616e6420604465706f736974536c6173686564602e406e756467655f7265666572656e64756d040114696e64657810013c5265666572656e64756d496e6465780005101d01416476616e63652061207265666572656e64756d206f6e746f20697473206e657874206c6f676963616c2073746174652e204f6e6c79207573656420696e7465726e616c6c792e006c2d20606f726967696e603a206d7573742062652060526f6f74602ea42d2060696e646578603a20746865207265666572656e64756d20746f20626520616476616e6365642e486f6e655f66657765725f6465636964696e67040114747261636bf0013c547261636b49644f663c542c20493e0006240901416476616e6365206120747261636b206f6e746f20697473206e657874206c6f676963616c2073746174652e204f6e6c79207573656420696e7465726e616c6c792e006c2d20606f726967696e603a206d7573742062652060526f6f74602e902d2060747261636b603a2074686520747261636b20746f20626520616476616e6365642e005101416374696f6e206974656d20666f72207768656e207468657265206973206e6f77206f6e65206665776572207265666572656e64756d20696e20746865206465636964696e6720706861736520616e64207468651501604465636964696e67436f756e7460206973206e6f742079657420757064617465642e2054686973206d65616e7320746861742077652073686f756c64206569746865723a25012d20626567696e206465636964696e6720616e6f74686572207265666572656e64756d2028616e64206c6561766520604465636964696e67436f756e746020616c6f6e65293b206f72702d2064656372656d656e7420604465636964696e67436f756e74602e64726566756e645f7375626d697373696f6e5f6465706f736974040114696e64657810013c5265666572656e64756d496e64657800071c3101526566756e6420746865205375626d697373696f6e204465706f73697420666f72206120636c6f736564207265666572656e64756d206261636b20746f20746865206465706f7369746f722e009c2d20606f726967696e603a206d75737420626520605369676e656460206f722060526f6f74602e55012d2060696e646578603a2054686520696e646578206f66206120636c6f736564207265666572656e64756d2077686f7365205375626d697373696f6e204465706f73697420686173206e6f7420796574206265656e2c2020726566756e6465642e0088456d69747320605375626d697373696f6e4465706f736974526566756e646564602e307365745f6d65746164617461080114696e64657810013c5265666572656e64756d496e6465780001286d617962655f686173685d01013c4f7074696f6e3c543a3a486173683e00081c98536574206f7220636c656172206d65746164617461206f662061207265666572656e64756d2e002c506172616d65746572733a45012d20606f726967696e603a204d75737420626520605369676e65646020627920612063726561746f72206f662061207265666572656e64756d206f7220627920616e796f6e6520746f20636c65617220619020206d65746164617461206f6620612066696e6973686564207265666572656e64756d2e0d012d2060696e646578603a202054686520696e646578206f662061207265666572656e64756d20746f20736574206f7220636c656172206d6574616461746120666f722e51012d20606d617962655f68617368603a205468652068617368206f6620616e206f6e2d636861696e2073746f72656420707265696d6167652e20604e6f6e656020746f20636c6561722061206d657461646174612e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e4d01083c7175616e7475735f72756e74696d65304f726967696e43616c6c65720001081873797374656d0400510101746672616d655f73797374656d3a3a4f726967696e3c52756e74696d653e0000001c4f726967696e7304005501017470616c6c65745f637573746f6d5f6f726967696e733a3a4f726967696e0017000051010c346672616d655f737570706f7274206469737061746368245261774f726967696e04244163636f756e7449640100011010526f6f74000000185369676e656404000001244163636f756e744964000100104e6f6e6500020028417574686f72697a6564000300005501143c7175616e7475735f72756e74696d6528676f7665726e616e63651c6f726967696e735470616c6c65745f637573746f6d5f6f726967696e73184f726967696e0001042c466173745570677261646500000000590110346672616d655f737570706f727418747261697473207363686564756c6530446973706174636854696d65042c426c6f636b4e756d62657201100108084174040010012c426c6f636b4e756d626572000000144166746572040010012c426c6f636b4e756d626572000100005d0104184f7074696f6e04045401340108104e6f6e6500000010536f6d65040034000001000061010c3c70616c6c65745f74726561737572791870616c6c65741043616c6c040454000104507365745f74726561737572795f6163636f756e7404011c6163636f756e74000130543a3a4163636f756e744964000018590153657420746865207472656173757279206163636f756e742e20526f6f74206f6e6c792e205a65726f20616464726573732069732072656a6563746564202866756e647320776f756c64206265206c6f636b6564292e0059012a2a496d706f7274616e742a2a3a2054686973206f6e6c79206368616e676573207768657265202a6675747572652a2074726561737572792063726564697473206172652073656e742e20416e792062616c616e63654501746861742068617320616c726561647920616363756d756c6174656420696e207468652063757272656e74207472656173757279206163636f756e74206973204e4f54206175746f6d61746963616c6c794d016d6967726174656420746f20746865206e6577206163636f756e742e20496620796f75206e65656420746f206d6f7665206578697374696e672066756e64732c20706572666f726d2061207365706172617465310162616c616e6365207472616e736665722028652e672e2c2076696120676f7665726e616e63652070726f706f73616c29206166746572207570646174696e6720746865206163636f756e742e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e65010c3c70616c6c65745f6d756c74697369671870616c6c65741043616c6c04045400011c3c6372656174655f6d756c74697369670c011c7369676e657273690101445665633c543a3a4163636f756e7449643e0001247468726573686f6c6410010c7533320001146e6f6e636530010c75363400003ce04372656174652061206e6577206d756c7469736967206163636f756e7420776974682064657465726d696e69737469632061646472657373002c506172616d65746572733af42d20607369676e657273603a204c697374206f66206163636f756e747320746861742063616e207369676e20666f722074686973206d756c74697369670d012d20607468726573686f6c64603a204e756d626572206f6620617070726f76616c7320726571756972656420746f2065786563757465207472616e73616374696f6e73d42d20606e6f6e6365603a20557365722d70726f7669646564206e6f6e636520666f72206164647265737320756e697175656e65737300dc546865206d756c746973696720616464726573732069732064657465726d696e6973746963616c6c7920646572697665642066726f6d3adc686173682870616c6c65745f6964207c7c20736f727465645f7369676e657273207c7c207468726573686f6c64207c7c206e6f6e63652900ec5369676e6572732061726520736f72746564206265666f72652068617368696e672c20736f206f7264657220646f65736e2774206d61747465722e804475706c6963617465206163636f756e7473206172652072656a65637465642e003c45636f6e6f6d696320636f7374733acc2d204d756c74697369674665653a206275726e656420696d6d6564696174656c7920287370616d2070726576656e74696f6e291c70726f706f73650c01406d756c74697369675f61646472657373000130543a3a4163636f756e74496400011063616c6c6d010140426f756e64656443616c6c4f663c543e000118657870697279100144426c6f636b4e756d626572466f723c543e00014cd050726f706f73652061207472616e73616374696f6e20746f20626520657865637574656420627920746865206d756c7469736967002c506172616d65746572733a15012d20606d756c74697369675f61646472657373603a20546865206d756c7469736967206163636f756e7420746861742077696c6c2065786563757465207468652063616c6c942d206063616c6c603a2054686520656e636f6465642063616c6c20746f2065786563757465cc2d2060657870697279603a20426c6f636b206e756d626572207768656e20746869732070726f706f73616c206578706972657300ac5468652070726f706f736572206d7573742062652061207369676e657220616e64206d757374207061793a25012d2041206465706f7369742028726566756e6461626c65202d2072657475726e656420696d6d6564696174656c79206f6e20657865637574696f6e2f63616e63656c6c6174696f6e29b02d20412066656520286e6f6e2d726566756e6461626c652c206275726e656420696d6d6564696174656c7929003d012a2a466f72207468726573686f6c643d313a2a2a205468652070726f706f73616c206973206372656174656420776974682060417070726f766564602073746174757320696d6d6564696174656c790501616e642063616e2062652065786563757465642076696120606578656375746528296020776974686f7574206164646974696f6e616c20617070726f76616c732e0039012a2a5765696768743a2a2a204368617267656420757066726f6e7420696e636c7564657320626f6f6b6b656570696e67202b204d6178496e6e657243616c6c57656967687420746f20636f766572590174686520636f7374206f66206465636f64696e67206172626974726172792052756e74696d6543616c6c207374727563747572657320616e642063616c6c696e67206765745f64697370617463685f696e666f28292e41014f6e20737563636573732c20726566756e6473206261736564206f6e2061637475616c20696e6e65722063616c6c207765696768742e204f6e2072656a656374696f6e206166746572206465636f64653d0128652e672e2c2043616c6c576569676874457863656564734c696d69742c2043616c6c4e6f74416c6c6f776564466f724869676853656375726974794d756c7469736967292c207468652066756c6c4d01726573657276656420776569676874206973206275726e656420746f2070726576656e74206772696566696e67207769746820636f6d706c65782063616c6c732074686174206765742072656a65637465642e1c617070726f76650c01406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c75333200011063616c6c6d010140426f756e64656443616c6c4f663c543e00024478417070726f766520612070726f706f736564207472616e73616374696f6e002d0154686520617070726f766572206d7573742072657375626d6974207468652070726f706f73616c277320696e6e65722063616c6c2062797465733b2074686520617070726f76616c20697325016f6e6c792076616c696420696620746865792061726520627974652d657175616c20746f20746865207061796c6f61642073746f726564206174206070726f706f73616c5f6964602e2501546869732062696e64732074686520617070726f7665722773207369676e617475726520746f207468652061637475616c2063616c6c206265696e6720617070726f7665642c20736f21016f66666c696e652f636f6c642d77616c6c6574207369676e6572732063616e206465636f646520616e6420696e73706563742077686174207468657920617265207369676e696e67a8696e7374656164206f66207472757374696e6720616e206f70617175652070726f706f73616c2069642e0019014966207468697320617070726f76616c206272696e67732074686520746f74616c20617070726f76616c7320746f206f722061626f766520746865207468726573686f6c642c39017468652070726f706f73616c20737461747573206368616e67657320746f2060417070726f7665646020616e642063616e206265206578656375746564207669612060657865637574652829602e002c506172616d65746572733aa82d20606d756c74697369675f61646472657373603a20546865206d756c7469736967206163636f756e74d82d206070726f706f73616c5f6964603a20494420286e6f6e636529206f66207468652070726f706f73616c20746f20617070726f766541012d206063616c6c603a2054686520656e636f64656420696e6e65722063616c6c206f66207468652070726f706f73616c20286d757374206d61746368207468652073746f726564207061796c6f61642900e85765696768743a204368617267657320666f72204d41582063616c6c2073697a652c20726566756e6473206261736564206f6e2061637475616c1863616e63656c0801406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c753332000314c043616e63656c20612070726f706f736564207472616e73616374696f6e20286f6e6c792062792070726f706f73657229002c506172616d65746572733aa82d20606d756c74697369675f61646472657373603a20546865206d756c7469736967206163636f756e74d42d206070726f706f73616c5f6964603a20494420286e6f6e636529206f66207468652070726f706f73616c20746f2063616e63656c3872656d6f76655f657870697265640801406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c75333200042ce452656d6f766520657870697265642070726f706f73616c7320616e642072657475726e206465706f7369747320746f2070726f706f7365727300b843616e206f6e6c792062652063616c6c6564206279207369676e657273206f6620746865206d756c74697369672e2d0152656d6f76657320416374697665206f7220417070726f7665642070726f706f73616c732074686174206861766520657870697265642028706173742065787069727920626c6f636b292e2901457865637574656420616e642043616e63656c6c65642070726f706f73616c7320617265206175746f6d61746963616c6c7920636c65616e656420757020696d6d6564696174656c792e004501417070726f7665642b657870697265642070726f706f73616c732063616e206265636f6d6520737475636b2069662070726f706f73657220697320756e617661696c61626c652028652e672e206c6f737441016b6579732c20636f6d70726f6d697365292e20416c6c6f77696e6720616e79207369676e657220746f2072656d6f7665207468656d2070726576656e7473207065726d616e656e74206465706f736974a06c6f636b757020616e6420656e61626c6573206d756c746973696720646973736f6c7574696f6e2e002101546865206465706f73697420697320616c776179732072657475726e656420746f20746865206f726967696e616c2070726f706f7365722c206e6f74207468652063616c6c65722e38636c61696d5f6465706f736974730401406d756c74697369675f61646472657373000130543a3a4163636f756e744964000528a4436c61696d20616c6c206465706f736974732066726f6d20657870697265642070726f706f73616c73000d01546869732069732061206261746368206f7065726174696f6e20746861742072656d6f76657320616c6c20657870697265642070726f706f73616c732077686572653a602d2043616c6c6572206973207468652070726f706f736572d82d2050726f706f73616c20697320416374697665206f7220417070726f76656420616e6420706173742065787069727920626c6f636b0041014e6f74653a20457865637574656420616e642043616e63656c6c65642070726f706f73616c7320617265206175746f6d61746963616c6c7920636c65616e656420757020696d6d6564696174656c792c2901736f206f6e6c79204163746976652b4578706972656420616e6420417070726f7665642b457870697265642070726f706f73616c73206e656564206d616e75616c20636c65616e75702e00190152657475726e7320616c6c2070726f706f73616c206465706f7369747320746f207468652070726f706f73657220696e20612073696e676c65207472616e73616374696f6e2e1c657865637574650c01406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c75333200011063616c6c0501017c426f783c3c5420617320436f6e6669673e3a3a52756e74696d6543616c6c3e000670704578656375746520616e20617070726f7665642070726f706f73616c00250143616e2062652063616c6c656420627920616e79207369676e6572206f6620746865206d756c7469736967206f6e6365207468652070726f706f73616c206861732072656163686564350174686520617070726f76616c207468726573686f6c642028737461747573203d20417070726f766564292e205468652070726f706f73616c206d757374206e6f7420626520657870697265642e002501546865206578656375746f722072657375626d697473207468652070726f706f73616c277320696e6e65722063616c6c3b20657865637574696f6e2070726f6365656473206f6e6c791d01696620697420697320627974652d657175616c20746f20746865207061796c6f61642073746f726564206174206070726f706f73616c5f69646020e28094207468652073616d65d462696e64696e672060617070726f76656020656e666f726365732e2054686973207365727665732074776f20707572706f7365733a5d012d202a2a436c6561727369676e696e673a2a2a20746865206578656375746f72277320286861726477617265292077616c6c657420646973706c61797320616e64207369676e73207468652061637475616c2063616c6cb820206265696e6720646973706174636865642c206e6f7420616e206f70617175652070726f706f73616c2069642e51012d202a2a53656c662d64657363726962696e67207765696768743a2a2a2074686520657865637574696e672065787472696e73696320636172726965732074686520696e6e65722063616c6c2c20736f206974734d0120206465636c617265642077656967687420636172726965732074686520696e6e65722063616c6c2773206f776e206465636c61726564207765696768742028726566756e64656420746f2061637475616c7339012020706f73742d64697370617463682920696e7374656164206f6620726573657276696e67206120666c617420604d6178496e6e657243616c6c576569676874602c20616e642072756e74696d65390120207472616e73616374696f6e20657874656e73696f6e732063616e20696e73706563742074686520696e6e65722063616c6c20616e64207072696365206974732073696465206566666563747349012020286163636f756e742d7265617020636c65616e75702c207472616e736665722d70726f6f66207265636f7264696e67292065786163746c79206173207468657920646f20666f72206469726563746c795d0120207375626d69747465642063616c6c732e204e6f7468696e672061626f75742074686520646973706174636820697320696e76697369626c6520746f207072652d64697370617463682061646d697373696f6e206f7261012020666565732e20284f6e6c792074686520626f6f6b6b656570696e67207465726d20697320726573657276656420617420604d617843616c6c53697a65602c2073696e6365207468652073746f72656420627974657327110120206c656e67746820697320756e6b6e6f776e207072652d64697370617463683b2074686520756e757365642072656d61696e64657220697320726566756e6465642e2900344f6e20657865637574696f6e3ac02d205468652063616c6c206973206469737061746368656420617320746865206d756c7469736967206163636f756e74882d2050726f706f73616c2069732072656d6f7665642066726f6d2073746f72616765942d204465706f7369742069732072657475726e656420746f207468652070726f706f736572002c506172616d65746572733aa82d20606d756c74697369675f61646472657373603a20546865206d756c7469736967206163636f756e74d82d206070726f706f73616c5f6964603a20494420286e6f6e636529206f66207468652070726f706f73616c20746f206578656375746515012d206063616c6c603a205468652070726f706f73616c277320696e6e65722063616c6c2c20627974652d657175616c20746f207468652073746f726564207061796c6f6164040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e690100000200006d010c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e64656456656308045401080453000004003801185665633c543e000071010c3c70616c6c65745f776f726d686f6c651870616c6c65741043616c6c040454000108507665726966795f707269766174655f626174636804012c70726f6f665f627974657338011c5665633c75383e0002142501566572696679206120707269766174652d626174636820776f726d686f6c652070726f6f6620616e642070726f6365737320616c6c20657869747320696e207468652062617463682e00490152657475726e7320604469737061746368526573756c7457697468506f7374496e666f6020746f20616c6c6f772077656967687420636f7272656374696f6e206f6e206561726c79206661696c757265732e150149662076616c69646174696f6e206661696c73206265666f7265205a4b20766572696669636174696f6e2c2077652072657475726e206d696e696d616c207765696768742e21014966205a4b20766572696669636174696f6e206661696c732c2077652072657475726e2066756c6c207765696768742073696e63652074686520776f726b2077617320646f6e652e4c7665726966795f7075626c69635f626174636804012c70726f6f665f627974657338011c5665633c75383e00031c25015665726966792061207075626c69632d626174636820776f726d686f6c652070726f6f6620616e642070726f6365737320616c6c2076616c69642065786974207365676d656e74732e004501496e76616c6964207365676d656e74732028616c72656164792d7370656e74206e756c6c69666965727329206172652064656e69656420696e646976696475616c6c793b2064756d6d792d70616464656445017365676d656e74732028616c6c2d7a65726f206e756c6c696669657273292061726520736b69707065642073696c656e746c792e204120706f7274696f6e206f6620746865206275726e206275636b65742d016973206d696e74656420746f207468652070726f6f662773206061676772656761746f725f61646472657373603b2069662074686174206d696e74206661696c732028652e672e2074686529016163636f756e7420646f65736e277420657869737420616e6420746865207265626174652069732062656c6f7720746865206578697374656e7469616c206465706f7369742920746865d4726562617465206973206275726e656420696e7374656164206f66206661696c696e6720746865207573657273272065786974732e040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e75010c3870616c6c65745f76657374696e671870616c6c65741043616c6c04045400011014636c61696d04012c7363686564756c655f696430010c753634000028310150617920746865206c6172676573742076616c696420636c61696d206f6e20607363686564756c655f69646020746f206974732062656e65666963696172792e205061796f757473206172653d01726f756e64656420646f776e20746f205b60436f6e6669673a3a5061796f75745175616e74756d605d2c206d757374206d656574205b60436f6e6669673a3a4d696e696d756d5061796f7574605d2c3d01616e642072657365727665206174206c65617374206f6e65206d696e696d756d2d73697a65642066696e616c20636c61696d20756e6c65737320746865207363686564756c652069732066756c6c79d47665737465642e204e6f6e2d66696e616c207061796f75747320617265206675727468657220726f756e64656420646f776e20746f2d015b604e4f4e5f46494e414c5f5041594f55545f5155414e5441605d206c656166207175616e74613b20746865206c6566746f766572207374617973206f6e20746865207363686564756c65b8756e74696c2061206c6174657220636c61696d206f72207468652065786163742066696e616c207061796f75742e0035015065726d697373696f6e6c6573733a20616e79207369676e6564206163636f756e74206d61792063616c6c207468697320666f7220616e79207363686564756c653b20746865207061796f75741901616c7761797320676f657320746f207468652073746f7265642062656e65666963696172792e205468697320697320746865206f6e6c7920636c61696d207061746820666f72310162656e6566696369617269657320746861742063616e6e6f74207369676e2028776f726d686f6c65206164647265737365732c20686967682d7365637572697479206163636f756e7473292e3c6372656174655f7363686564756c6514012c62656e6566696369617279000130543a3a4163636f756e74496400011473746172743001184d6f6d656e74000114636c6966663001184d6f6d656e7400010c656e643001184d6f6d656e74000114746f74616c18013042616c616e63654f663c543e00010815014372656174652061206e6577207363686564756c6520756e64657220746865206e65787420667265652069642c206d6f76696e672060746f74616c602066726f6d20746865bc7472656173757279206163636f756e7420696e746f2074686520706f7420696e207468652073616d652063616c6c2e30656e645f7363686564756c6504012c7363686564756c655f696430010c7536340002142901456e642061207363686564756c65206561726c793a20746865207374696c6c2d756e706169642076657374656420706172742028726f756e64656420746f20746865206e656172657374f85b60436f6e6669673a3a5061796f75745175616e74756d605d2920676f657320746f207468652062656e6566696369617279206966206974206d6565747315015b60436f6e6669673a3a4d696e696d756d5061796f7574605d3b206f7468657277697365207468617420736c6976657220697320726566756e6465642077697468207468651501756e7665737465642072656d61696e6465722e20546865207472656173757279206973207369676e61747572652d636f6e74726f6c6c656420616e64206e65656473206e6f1901776f726d686f6c65206c6561662c20736f2074686520726566756e64206973206e6f74207175616e74697a656420616e64206e6576657220626c6f636b7320656e64696e672e4472657461726765745f7363686564756c6508012c7363686564756c655f696430010c75363400013c6e65775f62656e6566696369617279000130543a3a4163636f756e74496400031825014368616e676520746865207363686564756c6527732062656e656669636961727920776974686f757420706179696e6720616e797468696e67206f75742e204120726574617267657431017265706c61636573207468652077616c6c6574206f6620746865202a73616d652a206772616e74656520286c6f73742d6b65792072656d656479293a20746865206f6c64206164647265737321016d6179206265206c6f7374206f722073746f6c656e2c20736f20736574746c696e6720697420776f756c64206275726e2066756e6473206f7220706179207468652074686965662e250145766572797468696e67207665737465642062757420756e636c61696d6564207374617973206f6e20746865207363686564756c6520616e6420676f657320746f20746865206e6577110177616c6c657420617420697473206e65787420636c61696d2e202841207065726d697373696f6e6c65737320636c61696d206c616e64696e67206265666f726520746865e47265746172676574207374696c6c207061797320746865206f6c6420616464726573732c20736f20726f746174652070726f6d70746c792e29040d01436f6e7461696e7320612076617269616e742070657220646973706174636861626c652065787472696e736963207468617420746869732070616c6c6574206861732e79010c2873705f72756e74696d65187472616974732c426c616b6554776f323536000000007d010c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e64656456656308045401080453000004003801185665633c543e000081010c3c70616c6c65745f74726561737572791870616c6c6574144576656e740404540001045854726561737572794163636f756e745570646174656408012c6f6c645f6163636f756e74850101504f7074696f6e3c543a3a4163636f756e7449643e0429015468652070726576696f7573207472656173757279206163636f756e7420284e6f6e652069662074686973206973207468652066697273742074696d652073657474696e67206974292e012c6e65775f6163636f756e74000130543a3a4163636f756e74496404e8546865206e6577207472656173757279206163636f756e7420746861742077696c6c20726563656976652066757475726520637265646974732e001484546865207472656173757279206163636f756e742077617320757064617465642e0035014e6f74653a2054686973206f6e6c7920726564697265637473207768657265206675747572652074726561737572792063726564697473206172652073656e742e20416e792062616c616e63653d01616363756d756c6174656420696e20746865206f6c64206163636f756e742072656d61696e7320746865726520616e64206973204e4f54206175746f6d61746963616c6c79206d696772617465642ee855736520612073657061726174652062616c616e6365207472616e736665722069662066756e6473206e65656420746f206265206d6f7665642e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574850104184f7074696f6e04045401000108104e6f6e6500000010536f6d65040000000001000089010c3c70616c6c65745f6d756c74697369671870616c6c6574144576656e740404540001203c4d756c74697369674372656174656414011c63726561746f72000130543a3a4163636f756e7449640001406d756c74697369675f61646472657373000130543a3a4163636f756e74496400011c7369676e657273690101445665633c543a3a4163636f756e7449643e0001247468726573686f6c6410010c7533320001146e6f6e636530010c7536340000088841206e6577206d756c7469736967206163636f756e74207761732063726561746564d85b63726561746f722c206d756c74697369675f616464726573732c207369676e6572732c207468726573686f6c642c206e6f6e63655d3c50726f706f73616c437265617465640c01406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012070726f706f736572000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c7533320001046c412070726f706f73616c20686173206265656e2063726561746564385369676e6572417070726f7665641001406d756c74697369675f61646472657373000130543a3a4163636f756e744964000120617070726f766572000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c75333200013c617070726f76616c735f636f756e7410010c7533320002040d0141207369676e65722068617320617070726f76656420612070726f706f73616c2028646f6573206e6f7420696d706c79207468726573686f6c642072656163686564295850726f706f73616c5265616479546f457865637574650c01406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c75333200013c617070726f76616c735f636f756e7410010c753332000304e0412070726f706f73616c206861732072656163686564207468726573686f6c6420616e6420697320726561647920746f20657865637574654050726f706f73616c45786563757465641801406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c75333200012070726f706f736572000130543a3a4163636f756e74496400011063616c6c38011c5665633c75383e000124617070726f76657273690101445665633c543a3a4163636f756e7449643e000118726573756c74c401384469737061746368526573756c7400040870412070726f706f73616c20686173206265656e206578656375746564c4436f6e7461696e7320616c6c2064617461206e656564656420666f7220696e646578696e672062792053756253717569644450726f706f73616c43616e63656c6c65640c01406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012070726f706f736572000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c753332000504b4412070726f706f73616c20686173206265656e2063616e63656c6c6564206279207468652070726f706f7365723c50726f706f73616c52656d6f7665641001406d756c74697369675f61646472657373000130543a3a4163636f756e74496400012c70726f706f73616c5f696410010c75333200012070726f706f736572000130543a3a4163636f756e74496400012872656d6f7665645f6279000130543a3a4163636f756e744964000604a4457870697265642070726f706f73616c207761732072656d6f7665642066726f6d2073746f726167653c4465706f73697473436c61696d65641001406d756c74697369675f61646472657373000130543a3a4163636f756e74496400011c636c61696d6572000130543a3a4163636f756e744964000138746f74616c5f72657475726e656418013042616c616e63654f663c543e00014470726f706f73616c735f72656d6f76656410010c753332000704584261746368206465706f7369747320636c61696d6564047c54686520604576656e746020656e756d206f6620746869732070616c6c65748d010c3c70616c6c65745f776f726d686f6c651870616c6c6574144576656e74040454000118444e61746976655472616e7366657272656414011066726f6d0001983c54206173206672616d655f73797374656d3a3a436f6e6669673e3a3a4163636f756e744964000108746f0001983c54206173206672616d655f73797374656d3a3a436f6e6669673e3a3a4163636f756e744964000118616d6f756e7418013042616c616e63654f663c543e0001387472616e736665725f636f756e74300140543a3a5472616e73666572436f756e740001286c6561665f696e64657830010c75363404fc496e646578206f662074686973207472616e7366657220696e20746865205a4b20747269652028666f72204d65726b6c652070726f6f66206c6f6f6b75702900109441206e617469766520746f6b656e207472616e7366657220776173207265636f726465642e00ec54686520606c6561665f696e646578602063616e206265207573656420746f206665746368204d65726b6c652070726f6f66732076696120746865e0607a6b547269655f6765744d65726b6c6550726f6f66602052504320666f72205a4b206369726375697420766572696669636174696f6e2e4041737365745472616e7366657272656418012061737365745f6964100128543a3a4173736574496400011066726f6d0001983c54206173206672616d655f73797374656d3a3a436f6e6669673e3a3a4163636f756e744964000108746f0001983c54206173206672616d655f73797374656d3a3a436f6e6669673e3a3a4163636f756e744964000118616d6f756e74180144417373657442616c616e63654f663c543e0001387472616e736665725f636f756e74300140543a3a5472616e73666572436f756e740001286c6561665f696e64657830010c75363404fc496e646578206f662074686973207472616e7366657220696e20746865205a4b20747269652028666f72204d65726b6c652070726f6f66206c6f6f6b7570290110a441206e6f6e2d6e6174697665206173736574207472616e7366657220776173207265636f726465642e00ec54686520606c6561665f696e646578602063616e206265207573656420746f206665746368204d65726b6c652070726f6f66732076696120746865e0607a6b547269655f6765744d65726b6c6550726f6f66602052504320666f72205a4b206369726375697420766572696669636174696f6e2e3450726f6f66566572696669656408012c657869745f616d6f756e7418013042616c616e63654f663c543e0001286e756c6c696669657273910101345665633c5b75383b2033325d3e000200484d696e6572566f6c756d65466565506169640801146d696e65720001983c54206173206672616d655f73797374656d3a3a436f6e6669673e3a3a4163636f756e744964000118616d6f756e7418013042616c616e63654f663c543e000310110154686520626c6f636b20617574686f722773207368617265206f662074686520776f726d686f6c65206578697420766f6c756d652066656520776173206d696e7465642e001d014e4f54453a206b656570207468697320617320746865206c6173742076617269616e7420e2809420696e646578657273206465636f6465206576656e74732062792074686569721101706f736974696f6e20696e207468697320656e756d2c20736f206578697374696e672076617269616e7473206d757374206e657665722062652072656f7264657265642e385365676d656e747344656e69656404011c696e6469636573950101205665633c7533323e00040c2901536f6d65207365676d656e7473206f6620616e20657869742062756e646c6520776572652064656e69656420287468656972206e756c6c696669657273207765726520616c72656164793101757365642c20652e672e20626563617573652074686520756e6465726c79696e672070726976617465206261746368206c616e646564206f6e2d636861696e2073657061726174656c79292ebc5468652072656d61696e696e67207365676d656e747320776572652070726f636573736564206e6f726d616c6c792e38457869744d696e744661696c656408011c6163636f756e740001983c54206173206672616d655f73797374656d3a3a436f6e6669673e3a3a4163636f756e744964000118616d6f756e7418013042616c616e63654f663c543e0005183101416e206578697420736c6f7420636f756c64206e6f74206265206d696e7465642028652e672e20612062656c6f772d6578697374656e7469616c2d6465706f7369742063726564697420746f2d0161206672657368206163636f756e742920616e642077617320736b697070656420736f207468652072657374206f66207468652062756e646c65207374696c6c2070726f6365737365642e290154686520736b697070656420657869742773206e756c6c6966696572207374617973206d61726b65642c20736f207468697320657869742063616e6e6f7420626520726574726965642e003d014e4f54453a206b656570206e65772076617269616e747320617070656e6465642061742074686520656e6420e2809420696e646578657273206465636f6465206576656e74732062792074686569721101706f736974696f6e20696e207468697320656e756d2c20736f206578697374696e672076617269616e7473206d757374206e657665722062652072656f7264657265642e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574910100000204009501000002100099010c3870616c6c65745f7a6b5f747265651870616c6c6574144576656e74040454000108304c656166496e736572746564040114696e64657830010c753634000014190141206e6577206c6561662077617320696e73657274656420696e746f2074686520747265652e2054686520726f6f7420696e636c7564696e672074686973206c6561662069731d01636f6d70757465642061742074686520656e64206f662074686520626c6f636b20616e64207075626c697368656420696e2074686520626c6f636b206865616465722e2054686515016c65616620686173682069732064656c696265726174656c79206e6f7420696e636c756465643a20697420697320646572697661626c652066726f6d20604c656176657360190128616e64207365727665642062792074686520525043292c20616e642068617368696e67206974206865726520776f756c6420646f75626c6520746865207065722d6c656166ac506f736569646f6e20776f726b20746865206261746368656420736574746c656d656e742073617665732e2054726565477265770401246e65775f64657074680801087538000104545472656520646570746820696e637265617365642e047c54686520604576656e746020656e756d206f6620746869732070616c6c65749d010c3870616c6c65745f76657374696e671870616c6c6574144576656e740404540001103c5363686564756c654372656174656418012c7363686564756c655f696430010c75363400012c62656e6566696369617279000130543a3a4163636f756e74496400011473746172743001184d6f6d656e74000114636c6966663001184d6f6d656e7400010c656e643001184d6f6d656e74000114746f74616c18013042616c616e63654f663c543e000004010141206e6577207363686564756c6520776173206372656174656420616e642074686520706f742066756e6465642066726f6d207468652074726561737572792e1c436c61696d65640c012c7363686564756c655f696430010c75363400012c62656e6566696369617279000130543a3a4163636f756e744964000118616d6f756e7418013042616c616e63654f663c543e000104b85665737465642066756e647320776572652070616964206f757420746f207468652062656e65666963696172792e345363686564756c65456e64656410012c7363686564756c655f696430010c75363400012c62656e6566696369617279000130543a3a4163636f756e74496400012c7665737465645f7061696418013042616c616e63654f663c543e000144756e7665737465645f72657475726e656418013042616c616e63654f663c543e000208090141207363686564756c652077617320656e646564206561726c793a20756e7061696420766573746564207061727420746f207468652062656e65666963696172792ca0756e7665737465642072656d61696e646572206261636b20746f207468652074726561737572792e485363686564756c65526574617267657465640c012c7363686564756c655f696430010c75363400013c6f6c645f62656e6566696369617279000130543a3a4163636f756e74496400013c6e65775f62656e6566696369617279000130543a3a4163636f756e74496400030c210141207363686564756c6527732062656e656669636961727920776173206368616e6765642e204e6f7468696e67207761732070616964206f75743a2074686520726574617267657429017265706c61636573207468652073616d65206772616e74656527732077616c6c65742c20736f20746865206163637275656420656e7469746c656d656e7420666f6c6c6f777320746865707363686564756c6520746f20746865206e657720616464726573732e047c54686520604576656e746020656e756d206f6620746869732070616c6c6574a10108306672616d655f73797374656d14506861736500010c384170706c7945787472696e736963040010010c7533320000003046696e616c697a6174696f6e00010038496e697469616c697a6174696f6e00020000a501000002a90100a90100000408101000ad0108306672616d655f73797374656d584c61737452756e74696d6555706772616465496e666f0000080130737065635f76657273696f6eb101014c636f6465633a3a436f6d706163743c7533323e000124737065635f6e616d65b5010144436f773c277374617469632c207374723e0000b1010000061000b501040c436f7704045401b901000400b901000000b9010000050200bd0108306672616d655f73797374656d60436f646555706772616465417574686f72697a6174696f6e0404540000080124636f64655f6861736834011c543a3a48617368000134636865636b5f76657273696f6e200110626f6f6c0000c1010c306672616d655f73797374656d186c696d69747330426c6f636b5765696768747300000c0128626173655f626c6f636b2801185765696768740001246d61785f626c6f636b2801185765696768740001247065725f636c617373c50101845065724469737061746368436c6173733c57656967687473506572436c6173733e0000c5010c346672616d655f737570706f7274206469737061746368405065724469737061746368436c61737304045401c901000c01186e6f726d616cc90101045400012c6f7065726174696f6e616cc9010104540001246d616e6461746f7279c9010104540000c9010c306672616d655f73797374656d186c696d6974733c57656967687473506572436c6173730000100138626173655f65787472696e7369632801185765696768740001346d61785f65787472696e736963e401384f7074696f6e3c5765696768743e0001246d61785f746f74616ce401384f7074696f6e3c5765696768743e0001207265736572766564e401384f7074696f6e3c5765696768743e0000cd010c306672616d655f73797374656d186c696d6974732c426c6f636b4c656e677468000004010c6d6178d10101545065724469737061746368436c6173733c7533323e0000d1010c346672616d655f737570706f7274206469737061746368405065724469737061746368436c6173730404540110000c01186e6f726d616c1001045400012c6f7065726174696f6e616c100104540001246d616e6461746f7279100104540000d501082873705f776569676874733c52756e74696d65446257656967687400000801107265616430010c753634000114777269746530010c7536340000d901082873705f76657273696f6e3852756e74696d6556657273696f6e0000200124737065635f6e616d65b5010144436f773c277374617469632c207374723e000124696d706c5f6e616d65b5010144436f773c277374617469632c207374723e000144617574686f72696e675f76657273696f6e10010c753332000130737065635f76657273696f6e10010c753332000130696d706c5f76657273696f6e10010c75333200011061706973dd01011c4170697356656300014c7472616e73616374696f6e5f76657273696f6e10010c75333200013873797374656d5f76657273696f6e08010875380000dd01040c436f7704045401e101000400e101000000e101000002e50100e50100000408e9011000e901000003080000000800ed010c306672616d655f73797374656d1870616c6c6574144572726f720404540001283c496e76616c6964537065634e616d650000081101546865206e616d65206f662073706563696669636174696f6e20646f6573206e6f74206d61746368206265747765656e207468652063757272656e742072756e74696d6550616e6420746865206e65772072756e74696d652e685370656356657273696f6e4e65656473546f496e63726561736500010841015468652073706563696669636174696f6e2076657273696f6e206973206e6f7420616c6c6f77656420746f206465637265617365206265747765656e207468652063757272656e742072756e74696d6550616e6420746865206e65772072756e74696d652e744661696c6564546f4578747261637452756e74696d6556657273696f6e00020cec4661696c656420746f2065787472616374207468652072756e74696d652076657273696f6e2066726f6d20746865206e65772072756e74696d652e0009014569746865722063616c6c696e672060436f72655f76657273696f6e60206f72206465636f64696e67206052756e74696d6556657273696f6e60206661696c65642e4c4e6f6e44656661756c74436f6d706f73697465000304fc537569636964652063616c6c6564207768656e20746865206163636f756e7420686173206e6f6e2d64656661756c7420636f6d706f7369746520646174612e3c4e6f6e5a65726f526566436f756e74000404350154686572652069732061206e6f6e2d7a65726f207265666572656e636520636f756e742070726576656e74696e6720746865206163636f756e742066726f6d206265696e67207075726765642e3043616c6c46696c7465726564000504d0546865206f726967696e2066696c7465722070726576656e74207468652063616c6c20746f20626520646973706174636865642e6c4d756c7469426c6f636b4d6967726174696f6e734f6e676f696e67000604550141206d756c74692d626c6f636b206d6967726174696f6e206973206f6e676f696e6720616e642070726576656e7473207468652063757272656e7420636f64652066726f6d206265696e67207265706c616365642e444e6f7468696e67417574686f72697a6564000704584e6f207570677261646520617574686f72697a65642e30556e617574686f72697a656400080494546865207375626d697474656420636f6465206973206e6f7420617574686f72697a65642e40496e76616c696448656170506167657300090445015468652070726f7669646564206e756d626572206f662068656170207061676573206973206f7574736964652074686520737570706f727465642072616e6765206f66206036342e2e3d3635353336602e046c4572726f7220666f72207468652053797374656d2070616c6c6574f1010c4c626f756e6465645f636f6c6c656374696f6e73407765616b5f626f756e6465645f766563385765616b426f756e64656456656308045401f501045300000400fd0101185665633c543e0000f5010c3c70616c6c65745f62616c616e6365731474797065732c42616c616e63654c6f636b041c42616c616e63650118000c01086964e90101384c6f636b4964656e746966696572000118616d6f756e7418011c42616c616e636500011c726561736f6e73f901011c526561736f6e730000f9010c3c70616c6c65745f62616c616e6365731474797065731c526561736f6e7300010c0c466565000000104d6973630001000c416c6c00020000fd01000002f5010001020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e646564566563080454010502045300000400090201185665633c543e000005020c3c70616c6c65745f62616c616e6365731474797065732c52657365727665446174610844526573657276654964656e74696669657201e9011c42616c616e63650118000801086964e9010144526573657276654964656e746966696572000118616d6f756e7418011c42616c616e6365000009020000020502000d020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e646564566563080454011102045300000400150201185665633c543e0000110214346672616d655f737570706f72741874726169747318746f6b656e73106d697363204964416d6f756e740808496401881c42616c616e636501180008010869648801084964000118616d6f756e7418011c42616c616e63650000150200000211020019020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e646564566563080454011d02045300000400250201185665633c543e00001d0214346672616d655f737570706f72741874726169747318746f6b656e73106d697363204964416d6f756e74080849640121021c42616c616e63650118000801086964210201084964000118616d6f756e7418011c42616c616e636500002102083c7175616e7475735f72756e74696d654c52756e74696d65467265657a65526561736f6e0001000025020000021d020029020c3c70616c6c65745f62616c616e6365731870616c6c6574144572726f720804540004490001283856657374696e6742616c616e63650000049c56657374696e672062616c616e636520746f6f206869676820746f2073656e642076616c75652e544c69717569646974795265737472696374696f6e73000104c84163636f756e74206c6971756964697479207265737472696374696f6e732070726576656e74207769746864726177616c2e4c496e73756666696369656e7442616c616e63650002047842616c616e636520746f6f206c6f7720746f2073656e642076616c75652e484578697374656e7469616c4465706f736974000304ec56616c756520746f6f206c6f7720746f20637265617465206163636f756e742064756520746f206578697374656e7469616c206465706f7369742e34457870656e646162696c697479000404905472616e736665722f7061796d656e7420776f756c64206b696c6c206163636f756e742e5c4578697374696e6756657374696e675363686564756c65000504cc412076657374696e67207363686564756c6520616c72656164792065786973747320666f722074686973206163636f756e742e2c446561644163636f756e740006048c42656e6566696369617279206163636f756e74206d757374207072652d65786973742e3c546f6f4d616e795265736572766573000704b84e756d626572206f66206e616d65642072657365727665732065786365656420604d61785265736572766573602e30546f6f4d616e79486f6c6473000804f84e756d626572206f6620686f6c647320657863656564206056617269616e74436f756e744f663c543a3a52756e74696d65486f6c64526561736f6e3e602e38546f6f4d616e79467265657a6573000904984e756d626572206f6620667265657a65732065786365656420604d6178467265657a6573602e048054686520604572726f726020656e756d206f6620746869732070616c6c65742e2d020c3473705f61726974686d657469632c66697865645f706f696e7424466978656455313238000004001801107531323800003102086870616c6c65745f7472616e73616374696f6e5f7061796d656e742052656c6561736573000108245631416e6369656e7400000008563200010000350210346672616d655f737570706f7274187472616974731c73746f72616765184e6f44726f7004045401390200040039020104540000390218346672616d655f737570706f72741874726169747318746f6b656e732066756e6769626c6524696d62616c616e636524496d62616c616e63650c04420118184f6e44726f7000384f70706f736974654f6e44726f700000040118616d6f756e741801044200003d02083c70616c6c65745f707265696d616765404f6c645265717565737453746174757308244163636f756e74496401001c42616c616e6365011801082c556e72657175657374656408011c6465706f73697441020150284163636f756e7449642c2042616c616e63652900010c6c656e10010c753332000000245265717565737465640c011c6465706f736974450201704f7074696f6e3c284163636f756e7449642c2042616c616e6365293e000114636f756e7410010c75333200010c6c656ed4012c4f7074696f6e3c7533323e00010000410200000408001800450204184f7074696f6e0404540141020108104e6f6e6500000010536f6d650400410200000100004902083c70616c6c65745f707265696d616765345265717565737453746174757308244163636f756e7449640100185469636b6574014d0201082c556e7265717565737465640801187469636b65745102014c284163636f756e7449642c205469636b65742900010c6c656e10010c753332000000245265717565737465640c01306d617962655f7469636b65745502016c4f7074696f6e3c284163636f756e7449642c205469636b6574293e000114636f756e7410010c7533320001246d617962655f6c656ed4012c4f7074696f6e3c7533323e000100004d02103c7175616e7475735f72756e74696d6528676f7665726e616e63652c646566696e6974696f6e733c507265696d6167654465706f7369740000040118616d6f756e7418011c42616c616e63650000510200000408004d0200550204184f7074696f6e0404540151020108104e6f6e6500000010536f6d650400510200000100005902000004083410005d020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e64656456656308045401080453000004003801185665633c543e000061020c3c70616c6c65745f707265696d6167651870616c6c6574144572726f7204045400012018546f6f426967000004a0507265696d61676520697320746f6f206c6172676520746f2073746f7265206f6e2d636861696e2e30416c72656164794e6f746564000104a4507265696d6167652068617320616c7265616479206265656e206e6f746564206f6e2d636861696e2e344e6f74417574686f72697a6564000204c85468652075736572206973206e6f7420617574686f72697a656420746f20706572666f726d207468697320616374696f6e2e204e6f744e6f746564000304fc54686520707265696d6167652063616e6e6f742062652072656d6f7665642073696e636520697420686173206e6f7420796574206265656e206e6f7465642e2452657175657374656400040409014120707265696d616765206d6179206e6f742062652072656d6f766564207768656e20746865726520617265206f75747374616e64696e672072657175657374732e304e6f745265717565737465640005042d0154686520707265696d61676520726571756573742063616e6e6f742062652072656d6f7665642073696e6365206e6f206f75747374616e64696e672072657175657374732065786973742e1c546f6f4d616e7900060455014d6f7265207468616e20604d41585f484153485f555047524144455f42554c4b5f434f554e54602068617368657320776572652072657175657374656420746f206265207570677261646564206174206f6e63652e18546f6f466577000704e4546f6f206665772068617368657320776572652072657175657374656420746f2062652075706772616465642028692e652e207a65726f292e048054686520604572726f726020656e756d206f6620746869732070616c6c65742e65020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e646564566563080454016902045300000400710201185665633c543e0000690204184f7074696f6e040454016d020108104e6f6e6500000010536f6d6504006d0200000100006d02084070616c6c65745f7363686564756c6572245363686564756c656418104e616d6501041043616c6c0101012c426c6f636b4e756d62657201103450616c6c6574734f726967696e014d01244163636f756e7449640100184d6f6d656e740130001001206d617962655f6964c001304f7074696f6e3c4e616d653e0001207072696f726974790801487363686564756c653a3a5072696f7269747900011063616c6c0101011043616c6c0001186f726967696e4d01013450616c6c6574734f726967696e000071020000026902007502084070616c6c65745f7363686564756c65722c5265747279436f6e6669670418506572696f6401b8000c0134746f74616c5f72657472696573080108753800012472656d61696e696e670801087538000118706572696f64b80118506572696f64000079020c4070616c6c65745f7363686564756c65721870616c6c6574144572726f72040454000124404661696c6564546f5363686564756c65000004644661696c656420746f207363686564756c6520612063616c6c204e6f74466f756e640001047c43616e6e6f742066696e6420746865207363686564756c65642063616c6c2e5c546172676574426c6f636b4e756d626572496e50617374000204a4476976656e2074617267657420626c6f636b206e756d62657220697320696e2074686520706173742e5454617267657454696d657374616d70496e5061737400030498476976656e207461726765742074696d657374616d7020697320696e2074686520706173742e4852657363686564756c654e6f4368616e6765000404f052657363686564756c65206661696c6564206265636175736520697420646f6573206e6f74206368616e6765207363686564756c65642074696d652e144e616d6564000504d0417474656d707420746f207573652061206e6f6e2d6e616d65642066756e6374696f6e206f6e2061206e616d6564207461736b2e50506572696f6469634e6f74537570706f7274656400060494506572696f646963207363686564756c696e67206973206e6f7420737570706f727465642e4c5265747279506572696f644d69736d61746368000710d8526574727920706572696f64207479706520646f6573206e6f74206d61746368207461736b207363686564756c696e6720747970652e00e8426c6f636b2d7363686564756c6564207461736b732072657175697265206120626c6f636b2d6e756d62657220726574727920706572696f642cfc616e642074696d657374616d702d7363686564756c6564207461736b73207265717569726520612074696d657374616d7020726574727920706572696f642e48496e76616c69645265747279506572696f6400081c78526574727920706572696f642076616c756520697320696e76616c69642e003d014120726574727920706572696f64206d757374206265206e6f6e2d7a65726f2c20616e6420612074696d657374616d7020726574727920706572696f64206d757374206164646974696f6e616c6c792d01626520612077686f6c65206d756c7469706c65206f66205b60436f6e6669673a3a54696d657374616d704275636b657453697a65605d2e2041207a65726f20706572696f6420776f756c64310172652d74617267657420746865206167656e64612063757272656e746c79206265696e6720736572766963656420286c6f73696e672074686520726574727920746f20746865207374616c6535016167656e64612077726974652d6261636b292c20616e642061206e6f6e2d6275636b65742d616c69676e65642074696d657374616d7020706572696f6420776f756c6420706c61636520746865dc726574727920696e20616e206167656e6461206b65792074686520736572766963696e67206c6f6f70206e65766572207669736974732e048054686520604572726f726020656e756d206f6620746869732070616c6c65742e7d020c3870616c6c65745f7574696c6974791870616c6c6574144572726f7204045400010830546f6f4d616e7943616c6c730000045c546f6f206d616e792063616c6c7320626174636865642e7443616c6c4e6f74416c6c6f776564466f72486967685365637572697479000104c043616c6c206973206e6f7420616c6c6f77656420666f72206120686967682d7365637572697479206163636f756e742e048054686520604572726f726020656e756d206f6620746869732070616c6c65742e8102086c70616c6c65745f72657665727369626c655f7472616e73666572735c4869676853656375726974794163636f756e744461746108244163636f756e74496401001444656c617901b800080120677561726469616e0001244163636f756e74496400011464656c6179b8011444656c6179000085020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e6465645665630804540110045300000400950101185665633c543e00008902086c70616c6c65745f72657665727369626c655f7472616e73666572733c50656e64696e675472616e736665720c244163636f756e74496401001c42616c616e636501181c4173736574496401100014011066726f6d0001244163636f756e744964000108746f0001244163636f756e744964000120677561726469616e0001244163636f756e74496400012061737365745f6964d4013c4f7074696f6e3c417373657449643e000118616d6f756e7418011c42616c616e636500008d020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e6465645665630804540134045300000400350101185665633c543e000091020c3473705f61726974686d65746963287065725f7468696e67731c5065726d696c6c0000040010010c753332000095020c6c70616c6c65745f72657665727369626c655f7472616e73666572731870616c6c6574144572726f72040454000140684163636f756e74416c72656164794869676853656375726974790000043d01546865206163636f756e7420617474656d7074696e6720746f20656e61626c65207265766572736962696c69747920697320616c7265616479206d61726b65642061732072657665727369626c652e584163636f756e744e6f744869676853656375726974790001040501546865206163636f756e7420617474656d7074696e672074686520616374696f6e206973206e6f74206d61726b656420617320686967682073656375726974792e50477561726469616e43616e6e6f74426553656c66000204fc477561726469616e2063616e6e6f7420626520746865206163636f756e7420697473656c662c206265636175736520697420697320726564756e64616e742e4450656e64696e6754784e6f74466f756e64000304cc546865207370656369666965642070656e64696e67207472616e73616374696f6e20494420776173206e6f7420666f756e642e204e6f744f776e657200040459015468652063616c6c6572206973206e6f7420746865206f726967696e616c207375626d6974746572206f6620746865207472616e73616374696f6e20746865792061726520747279696e6720746f2063616e63656c2e68546f6f4d616e7950656e64696e675472616e73616374696f6e730005043901546865206163636f756e7420686173207265616368656420746865206d6178696d756d206e756d626572206f662070656e64696e672072657665727369626c65207472616e73616374696f6e732e3444656c6179546f6f53686f7274000604ec546865207370656369666965642064656c617920706572696f642069732062656c6f772074686520636f6e66696775726564206d696e696d756d2e405363686564756c696e674661696c65640007041d014661696c656420746f207363686564756c6520746865207472616e73616374696f6e20657865637574696f6e207769746820746865207363686564756c65722070616c6c65742e4843616e63656c6c6174696f6e4661696c6564000804f84661696c656420746f2063616e63656c20746865207363686564756c6564207461736b207769746820746865207363686564756c65722070616c6c65742e2c496e76616c696443616c6c0009044043616c6c20697320696e76616c69642e58496e76616c69645363686564756c65724f726967696e000a0460496e76616c6964207363686564756c6572206f726967696e3c496e76616c69645265766572736572000b044c526576657273657220697320696e76616c6964b44163636f756e74416c726561647952657665727369626c6543616e6e6f745363686564756c654f6e6554696d65000c08450143616e6e6f74207363686564756c65206f6e652074696d652072657665727369626c65207472616e73616374696f6e207768656e206163636f756e742069732072657665727369626c65202874686566742c646574657272656e636529484173736574734e6f74537570706f72746564000d04884173736574207472616e736665727320617265206e6f7420737570706f727465642e285a65726f416d6f756e74000e0811015a65726f2d616d6f756e74207472616e73666572732063616e6e6f74206265207363686564756c65643a207468657265206973206e6f7468696e6720746f20686f6c642c50657865637574652c206f7220726576657273652e6c486967685365637572697479547851756f74614578636565646564000f04510154686520686967682d7365637572697479206163636f756e7420616c7265616479207573656420697473207472616e73616374696f6e2071756f746120666f72207468652063757272656e742077696e646f772e048054686520604572726f726020656e756d206f6620746869732070616c6c65742e9902086070616c6c65745f72616e6b65645f636f6c6c656374697665304d656d6265725265636f7264000004011072616e6bf0011052616e6b00009d0200000408f00000a10200000408f01000a50200000408100000a9020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e64656456656308045401080453000004003801185665633c543e0000ad020c6070616c6c65745f72616e6b65645f636f6c6c6563746976651870616c6c6574144572726f7208045400044900012c34416c72656164794d656d626572000004704163636f756e7420697320616c72656164792061206d656d6265722e244e6f744d656d626572000104604163636f756e74206973206e6f742061206d656d6265722e284e6f74506f6c6c696e67000204b854686520676976656e20706f6c6c20696e64657820697320756e6b6e6f776e206f722068617320636c6f7365642e1c4f6e676f696e670003048054686520676976656e20706f6c6c206973207374696c6c206f6e676f696e672e344e6f6e6552656d61696e696e67000404ac546865726520617265206e6f2066757274686572207265636f72647320746f2062652072656d6f7665642e28436f7272757074696f6e00050468556e6578706563746564206572726f7220696e2073746174652e2852616e6b546f6f4c6f7700060494546865206d656d62657227732072616e6b20697320746f6f206c6f7720746f20766f74652e38496e76616c69645769746e6573730007049854686520696e666f726d6174696f6e2070726f766964656420697320696e636f72726563742e304e6f5065726d697373696f6e000804f8546865206f726967696e206973206e6f742073756666696369656e746c792070726976696c6567656420746f20646f20746865206f7065726174696f6e2e2853616d654d656d626572000904e0546865206e6577206d656d62657220746f2065786368616e6765206973207468652073616d6520617320746865206f6c64206d656d62657238546f6f4d616e794d656d62657273000a04cc546865206d6178206d656d62657220636f756e7420666f72207468652072616e6b20686173206265656e20726561636865642e048054686520604572726f726020656e756d206f6620746869732070616c6c65742eb1020c4070616c6c65745f7265666572656e6461147479706573385265666572656e64756d496e666f201c547261636b496401f03452756e74696d654f726967696e014d01184d6f6d656e7401101043616c6c0101011c42616c616e636501181454616c6c7901f8244163636f756e74496401003c5363686564756c654164647265737301bc01181c4f6e676f696e670400b502018d015265666572656e64756d5374617475733c547261636b49642c2052756e74696d654f726967696e2c204d6f6d656e742c2043616c6c2c2042616c616e63652c2054616c6c792c0a4163636f756e7449642c205363686564756c65416464726573732c3e00000020417070726f7665640c001001184d6f6d656e740000bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e0000bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e0001002052656a65637465640c001001184d6f6d656e740000bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e0000bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e0002002443616e63656c6c65640c001001184d6f6d656e740000bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e0000bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e0003002054696d65644f75740c001001184d6f6d656e740000bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e0000bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e000400184b696c6c656404001001184d6f6d656e7400050000b5020c4070616c6c65745f7265666572656e6461147479706573405265666572656e64756d537461747573201c547261636b496401f03452756e74696d654f726967696e014d01184d6f6d656e7401101043616c6c0101011c42616c616e636501181454616c6c7901f8244163636f756e74496401003c5363686564756c654164647265737301bc002c0114747261636bf0011c547261636b49640001186f726967696e4d01013452756e74696d654f726967696e00012070726f706f73616c0101011043616c6c000124656e6163746d656e7459010150446973706174636854696d653c4d6f6d656e743e0001247375626d69747465641001184d6f6d656e740001487375626d697373696f6e5f6465706f736974b902016c4465706f7369743c4163636f756e7449642c2042616c616e63653e0001406465636973696f6e5f6465706f736974bd02018c4f7074696f6e3c4465706f7369743c4163636f756e7449642c2042616c616e63653e3e0001206465636964696e67c10201784f7074696f6e3c4465636964696e675374617475733c4d6f6d656e743e3e00011474616c6c79f8011454616c6c79000120696e5f7175657565200110626f6f6c000114616c61726dc90201844f7074696f6e3c284d6f6d656e742c205363686564756c6541646472657373293e0000b9020c4070616c6c65745f7265666572656e64611474797065731c4465706f73697408244163636f756e74496401001c42616c616e636501180008010c77686f0001244163636f756e744964000118616d6f756e7418011c42616c616e63650000bd0204184f7074696f6e04045401b9020108104e6f6e6500000010536f6d650400b9020000010000c10204184f7074696f6e04045401c5020108104e6f6e6500000010536f6d650400c5020000010000c5020c4070616c6c65745f7265666572656e6461147479706573384465636964696e67537461747573042c426c6f636b4e756d62657201100008011473696e636510012c426c6f636b4e756d626572000128636f6e6669726d696e67d4014c4f7074696f6e3c426c6f636b4e756d6265723e0000c90204184f7074696f6e04045401cd020108104e6f6e6500000010536f6d650400cd020000010000cd020000040810bc00d1020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e64656456656308045401a901045300000400a50101185665633c543e0000d502000002d90200d90200000408f0dd0200dd020c4070616c6c65745f7265666572656e646114747970657330547261636b44657461696c730c1c42616c616e63650118184d6f6d656e740110104e616d6501b901002401106e616d65b90101104e616d650001306d61785f6465636964696e6710010c7533320001406465636973696f6e5f6465706f73697418011c42616c616e6365000138707265706172655f706572696f641001184d6f6d656e7400013c6465636973696f6e5f706572696f641001184d6f6d656e74000138636f6e6669726d5f706572696f641001184d6f6d656e740001506d696e5f656e6163746d656e745f706572696f641001184d6f6d656e740001306d696e5f617070726f76616ce1020114437572766500012c6d696e5f737570706f7274e102011443757276650000e1020c4070616c6c65745f7265666572656e646114747970657314437572766500010c404c696e65617244656372656173696e670c01186c656e677468e502011c50657262696c6c000114666c6f6f72e502011c50657262696c6c0001106365696ce502011c50657262696c6c000000445374657070656444656372656173696e67100114626567696ee502011c50657262696c6c00010c656e64e502011c50657262696c6c00011073746570e502011c50657262696c6c000118706572696f64e502011c50657262696c6c000100285265636970726f63616c0c0118666163746f72e90201204669786564493634000120785f6f6666736574e90201204669786564493634000120795f6f6666736574e9020120466978656449363400020000e5020c3473705f61726974686d65746963287065725f7468696e67731c50657262696c6c0000040010010c7533320000e9020c3473705f61726974686d657469632c66697865645f706f696e7420466978656449363400000400ed02010c6936340000ed020000050c00f1020c4070616c6c65745f7265666572656e64611870616c6c6574144572726f72080454000449000148284e6f744f6e676f696e67000004685265666572656e64756d206973206e6f74206f6e676f696e672e284861734465706f736974000104b85265666572656e64756d2773206465636973696f6e206465706f73697420697320616c726561647920706169642e20426164547261636b0002049c54686520747261636b206964656e74696669657220676976656e2077617320696e76616c69642e1046756c6c000304310154686572652061726520616c726561647920612066756c6c20636f6d706c656d656e74206f66207265666572656e646120696e2070726f677265737320666f72207468697320747261636b2e285175657565456d70747900040480546865207175657565206f662074686520747261636b20697320656d7074792e344261645265666572656e64756d000504e4546865207265666572656e64756d20696e6465782070726f766964656420697320696e76616c696420696e207468697320636f6e746578742e2c4e6f7468696e67546f446f000604ac546865726520776173206e6f7468696e6720746f20646f20696e2074686520616476616e63656d656e742e1c4e6f547261636b000704a04e6f20747261636b2065786973747320666f72207468652070726f706f73616c206f726967696e2e28556e66696e69736865640008040101416e79206465706f7369742063616e6e6f7420626520726566756e64656420756e74696c20616674657220746865206465636973696f6e206973206f7665722e304e6f5065726d697373696f6e000904a8546865206465706f73697420726566756e646572206973206e6f7420746865206465706f7369746f722e244e6f4465706f736974000a04cc546865206465706f7369742063616e6e6f7420626520726566756e6465642073696e6365206e6f6e6520776173206d6164652e24426164537461747573000b04d0546865207265666572656e64756d2073746174757320697320696e76616c696420666f722074686973206f7065726174696f6e2e40507265696d6167654e6f744578697374000c047054686520707265696d61676520646f6573206e6f742065786973742e84507265696d61676553746f72656457697468446966666572656e744c656e677468000d04150154686520707265696d6167652069732073746f7265642077697468206120646966666572656e74206c656e677468207468616e20746865206f6e652070726f76696465642e54416c61726d5363686564756c696e674661696c6564000e04d8546865207265666572656e64756d27732077616b652d757020616c61726d20636f756c64206e6f74206265207363686564756c65642e34546f6f4d616e79416374697665000f04e854686572652061726520616c726561647920746865206d6178696d756d206e756d626572206f66206f6e676f696e67207265666572656e64612e60546f6f4d616e7941637469766542795375626d69747465720010040901546865207375626d697474657220616c72656164792068617320746865206d6178696d756d206e756d626572206f66206f6e676f696e67207265666572656e64612e38507265696d616765546f6f4269670011040d015468652070726f706f73616c277320707265696d616765206973206c6172676572207468616e205b60436f6e6669673a3a4d617850726f706f73616c53697a65605d2e048054686520604572726f726020656e756d206f6620746869732070616c6c65742ef5020c3c70616c6c65745f74726561737572791870616c6c6574144572726f7204045400010458496e76616c696454726561737572794163636f756e7400000431015472656173757279206163636f756e742063616e6e6f74206265207a65726f2061646472657373202866756e647320776f756c64206265207065726d616e656e746c79206c6f636b6564292e048054686520604572726f726020656e756d206f6620746869732070616c6c65742ef902083c70616c6c65745f6d756c7469736967304d756c7469736967446174610c244163636f756e744964010038426f756e6465645369676e65727301fd0264426f756e64656450726f706f73616c735065725369676e65720101030014011c63726561746f720001244163636f756e74496400011c7369676e657273fd020138426f756e6465645369676e6572730001247468726573686f6c6410010c75333200013870726f706f73616c5f6e6f6e636510010c75333200015070726f706f73616c735f7065725f7369676e657201030164426f756e64656450726f706f73616c735065725369676e65720000fd020c4c626f756e6465645f636f6c6c656374696f6e732c626f756e6465645f76656328426f756e6465645665630804540100045300000400690101185665633c543e000001030c4c626f756e6465645f636f6c6c656374696f6e7344626f756e6465645f62747265655f6d61703c426f756e64656442547265654d61700c044b0100045601100453000004000503013842547265654d61703c4b2c20563e00000503042042547265654d617008044b010004560110000400090300000009030000020d03000d03000004080010001103083c70616c6c65745f6d756c74697369673050726f706f73616c4461746114244163636f756e74496401001c42616c616e636501182c426c6f636b4e756d62657201102c426f756e64656443616c6c016d0140426f756e646564417070726f76616c7301fd020018012070726f706f7365720001244163636f756e74496400011063616c6c6d01012c426f756e64656443616c6c00011865787069727910012c426c6f636b4e756d626572000124617070726f76616c73fd020140426f756e646564417070726f76616c7300011c6465706f73697418011c42616c616e63650001187374617475731503013850726f706f73616c53746174757300001503083c70616c6c65745f6d756c74697369673850726f706f73616c5374617475730001081841637469766500000020417070726f76656400010000190308346672616d655f737570706f72742050616c6c6574496400000400e901011c5b75383b20385d00001d030c3c70616c6c65745f6d756c74697369671870616c6c6574144572726f7204045400016c404e6f74456e6f7567685369676e6572730000086c4e6f7420656e6f756768207369676e6572732070726f7669646564ac4d756c7469736967207265717569726573206174206c65617374203220756e69717565207369676e657273345468726573686f6c645a65726f0001048c5468726573686f6c64206d7573742062652067726561746572207468616e207a65726f405468726573686f6c64546f6f486967680002048c5468726573686f6c642065786365656473206e756d626572206f66207369676e65727338546f6f4d616e795369676e65727300030440546f6f206d616e79207369676e657273544d756c7469736967416c72656164794578697374730004045c4d756c746973696720616c726561647920657869737473404d756c74697369674e6f74466f756e64000504484d756c7469736967206e6f7420666f756e64284e6f74415369676e65720006049c43616c6c6572206973206e6f742061207369676e6572206f662074686973206d756c74697369674050726f706f73616c4e6f74466f756e640007044850726f706f73616c206e6f7420666f756e642c4e6f7450726f706f7365720008046843616c6c6572206973206e6f74207468652070726f706f7365723c416c7265616479417070726f7665640009047c416c726561647920617070726f7665642062792074686973207369676e6572484e6f74456e6f756768417070726f76616c73000a047c4e6f7420656e6f75676820617070726f76616c7320746f206578656375746530457870697279496e50617374000b047850726f706f73616c2065787069727920697320696e20746865207061737430457870697279546f6f466172000c04110150726f706f73616c2065787069727920697320746f6f2066617220696e2074686520667574757265202865786365656473204d61784578706972794475726174696f6e293c50726f706f73616c45787069726564000d045050726f706f73616c2068617320657870697265642c496e76616c696443616c6c000e04684661696c656420746f206465636f64652063616c6c206461746164546f6f4d616e7950726f706f73616c73496e53746f72616765000f042101546f6f206d616e7920746f74616c2070726f706f73616c7320696e2073746f7261676520666f722074686973206d756c74697369672028636c65616e75702072657175697265642964546f6f4d616e7950726f706f73616c735065725369676e6572001004150154686973207369676e65722068617320746f6f206d616e792070726f706f73616c7320696e2073746f72616765202866696c696275737465722070726f74656374696f6e294c496e73756666696369656e7442616c616e636500110480496e73756666696369656e742062616c616e636520666f72206465706f7369744850726f706f73616c4861734465706f7369740012046c50726f706f73616c2068617320616374697665206465706f7369744850726f706f73616c4e6f74457870697265640013047050726f706f73616c20686173206e6f742065787069726564207965744450726f706f73616c4e6f744163746976650014040d0150726f706f73616c206973206e6f7420696e20612063616e63656c6c61626c6520737461746520286d75737420626520416374697665206f7220417070726f766564294c50726f706f73616c4e6f74417070726f766564001504e850726f706f73616c20686173206e6f74206265656e20617070726f7665642079657420287468726573686f6c64206e6f742072656163686564299443616c6c4e6f74416c6c6f776564466f724869676853656375726974794d756c7469736967001604b843616c6c206973206e6f7420616c6c6f77656420666f7220686967682d7365637572697479206d756c74697369675850726f706f73616c4e6f6e6365457868617573746564001704ac50726f706f73616c206e6f6e63652065786861757374656420287533323a3a4d41582072656163686564295843616c6c576569676874457863656564734c696d6974001804b043616c6c207765696768742065786365656473204d6178496e6e657243616c6c576569676874206c696d69743043616c6c4d69736d61746368001904e050726f76696465642063616c6c20646f6573206e6f74206d61746368207468652073746f7265642070726f706f73616c207061796c6f6164404475706c69636174655369676e657273001a04d05369676e6572206c69737420636f6e7461696e73207468652073616d65206163636f756e74206d6f7265207468616e206f6e6365048054686520604572726f726020656e756d206f6620746869732070616c6c65742e21030c3c70616c6c65745f776f726d686f6c651870616c6c6574144572726f720404540001304c496e76616c69645075626c6963496e70757473000000504e756c6c6966696572416c72656164795573656400010c25014e6f207365676d656e74206f66207468652062756e646c65206973207370656e6461626c653a206576657279206e6f6e2d64756d6d79207365676d656e7420636f6e7461696e73206121016e756c6c6966696572207468617420697320616c7265616479207573656420286f72207468652073696e676c65207365676d656e74206f66206120707269766174652d62617463683070726f6f6620646f6573292e3c4e6f56616c69645365676d656e747300020c0d015468652062756e646c6520686173206e6f7468696e6720746f20736574746c653a206f6e6c792064756d6d792028616c6c2d7a65726f292070616464696e672c206f72390165766572792076616c6964207365676d656e74206578697473207a65726f2e2044697374696e63742066726f6d205b604572726f723a3a4e756c6c6966696572416c726561647955736564605d2c8c77686963682069732061207265706c6179206f66207265616c207365676d656e74732e34426c6f636b4e6f74466f756e640003005056657269666965724e6f74417661696c61626c650004006850726f6f66446573657269616c697a6174696f6e4661696c65640005003450726f6f66546f6f4c617267650006083101546865207375626d69747465642070726f6f6620626c6f622065786365656473205b6063726174653a3a4d41585f50524f4f465f4259544553605d2e2052656a6563746564206265666f72652501616e7920636f7079206f722070617273696e6720736f206f76657273697a656420756e7369676e6564207370616d20636f737473206f6e6c792061206c656e67746820636865636b2e644e6f6e43616e6f6e6963616c50726f6f66456e636f64696e6700070c21015468652070726f6f6620627974657320617265206e6f74207468652063616e6f6e6963616c2073657269616c697a6174696f6e206f6620746865206465636f6465642070726f6f661d0128652e672e20612076616c69642070726f6f66207769746820747261696c696e672062797465732c2077686963682074686520706c6f6e6b79322070617273657220776f756c64150173696c656e746c792069676e6f7265292e2045766572792070726f6f66206861732065786163746c79206f6e65206163636570746564206279746520656e636f64696e672e5c50726f6f66566572696669636174696f6e4661696c656400080060496e76616c696450726f6f665075626c6963496e7075747300090050496e76616c6964566f6c756d6546656552617465000a04090154686520766f6c756d6520666565207261746520696e207468652070726f6f6620646f65736e2774206d617463682074686520636f6e666967757265642072617465684e6f6e4e617469766541737365744e6f74537570706f72746564000b04f44f6e6c79206e6174697665206173736574202861737365745f6964203d20302920697320737570706f7274656420696e20746869732076657273696f6e048054686520604572726f726020656e756d206f6620746869732070616c6c65742e2503083870616c6c65745f7a6b5f74726565185a6b4c6561660c244163636f756e74496401001c4173736574496401101c42616c616e6365011800100108746f0001244163636f756e7449640001387472616e736665725f636f756e7430010c75363400012061737365745f696410011c41737365744964000118616d6f756e7418011c42616c616e636500002903000004080830002d030c3870616c6c65745f7a6b5f747265651870616c6c6574144572726f7204045400010c504c656166496e6465784f75744f66426f756e6473000004644c65616620696e646578206f7574206f6620626f756e64732e304c6561664e6f74466f756e640001043c4c656166206e6f7420666f756e642e444c6561664e6f74596574536574746c656400020811014c6561662077617320617070656e646564207468697320626c6f636b20616e64206973206e6f742079657420666f6c64656420696e746f2074686520726f6f743b206974b46265636f6d65732070726f7661626c65206f6e63652074686520626c6f636b2069732066696e616c697a65642e048054686520604572726f726020656e756d206f6620746869732070616c6c65742e31030c3870616c6c65745f76657374696e671870616c6c65743c56657374696e675363686564756c6508244163636f756e74496401001c42616c616e63650118001c012c62656e65666963696172790001244163636f756e74496400011473746172743001184d6f6d656e74000114636c6966663001184d6f6d656e7400010c656e643001184d6f6d656e74000114746f74616c18011c42616c616e636500011c636c61696d656418011c42616c616e63650001346c6173745f636c61696d5f6174350301384f7074696f6e3c4d6f6d656e743e0000350304184f7074696f6e04045401300108104e6f6e6500000010536f6d65040030000001000039030c3870616c6c65745f76657374696e671870616c6c6574144572726f72040454000124284e6f5363686564756c65000004844e6f207363686564756c652065786973747320756e64657220746869732069642e3c496e76616c69645363686564756c6500010c0d015363686564756c6520706172616d65746572732076696f6c61746520607374617274203c3d20636c696666203c3d20656e64602c20607374617274203c20656e64602c110160746f74616c203e3d204d696e696d756d5061796f7574602c206f722060746f74616c60206973206e6f742061206d756c7469706c65206f6620746865207061796f7574207175616e74756d2e384e6f7468696e67546f436c61696d0002082d014e6f7468696e6720697320636c61696d61626c65207269676874206e6f7720286265666f72652074686520636c6966662c20616c72656164792066756c6c7920636c61696d65642c206f72986c657373207468616e20746865206d696e696d756d207061796f75742061636372756564292e30436c61696d546f6f536f6f6e000304150154686973207363686564756c652068617320616c72656164792070616964206f75742077697468696e20746865206d696e696d756d20636c61696d20696e74657276616c2e4c436c61696d576f756c644c65617665447573740004082d01506179696e67206e6f7720776f756c64206c6561766520612072656d61696e6465722062656c6f7720746865206d696e696d756d207061796f75743b207761697420756e74696c2074686570656e746972652072656d61696e64657220686173207665737465642e5454726561737572794e6f74436f6e666967757265640005040901546865207472656173757279206163636f756e74206973206e6f7420636f6e66696775726564206f7220616c6961736573207468652076657374696e6720706f742e38506f74556e64657266756e646564000604150154686520706f7420646f6573206e6f7420686f6c6420697473206578697374656e7469616c2d6465706f736974206275666665723b20656e646f772069742066697273742e48496e76616c696442656e656669636961727900070435015468652062656e6566696369617279206d757374206e6f742062652074686520706f742c20616e64207265746172676574696e67206d757374206368616e676520746865206163636f756e742e585061796f757450726f6f664e6f745265636f7264656400080c29015468652070726f6f66207265636f72646572207265706f7274656420746865207061796f7574206372656469742061732064726f707065643a206e6f20776f726d686f6c65206c6561662d0177617320637265617465642c20736f20746865207061796f757420697320726f6c6c6564206261636b20726174686572207468616e2066696e616c697a656420776974686f757420746865cc70726f6f66206d6174657269616c2061206b65796c6573732062656e6566696369617279206e6565647320746f20657869742e048054686520604572726f726020656e756d206f6620746869732070616c6c65742e3d03102873705f72756e74696d651c67656e657269634c756e636865636b65645f65787472696e73696348556e636865636b656445787472696e736963101c416464726573730121011043616c6c010501245369676e61747572650141031445787472610155030004003800000041030c4c71705f64696c69746869756d5f63727970746f1474797065736044696c69746869756d5369676e6174757265536368656d650001082c44696c69746869756d383704004503017844696c69746869756d38375369676e6174757265576974685075626c69630000002c44696c69746869756d363504004d03017844696c69746869756d36355369676e6174757265576974685075626c69630001000045030c4c71705f64696c69746869756d5f63727970746f1474797065737844696c69746869756d38375369676e6174757265576974685075626c696300000401146279746573490301bc5b75383b2044696c69746869756d38375369676e6174757265576974685075626c69633a3a544f54414c5f4c454e5d00004903000003331c000008004d030c4c71705f64696c69746869756d5f63727970746f1474797065737844696c69746869756d36355369676e6174757265576974685075626c696300000401146279746573510301bc5b75383b2044696c69746869756d36355369676e6174757265576974685075626c69633a3a544f54414c5f4c454e5d000051030000038d140000080055030000043059035d036103650369037103750379037d03810385038d0300590310306672616d655f73797374656d28657874656e73696f6e7354636865636b5f6e6f6e5f7a65726f5f73656e64657248436865636b4e6f6e5a65726f53656e646572040454000000005d0310306672616d655f73797374656d28657874656e73696f6e7348636865636b5f737065635f76657273696f6e40436865636b5370656356657273696f6e04045400000000610310306672616d655f73797374656d28657874656e73696f6e7340636865636b5f74785f76657273696f6e38436865636b547856657273696f6e04045400000000650310306672616d655f73797374656d28657874656e73696f6e7334636865636b5f67656e6573697330436865636b47656e6573697304045400000000690310306672616d655f73797374656d28657874656e73696f6e733c636865636b5f6d6f7274616c69747938436865636b4d6f7274616c697479040454000004006d03010c45726100006d03102873705f72756e74696d651c67656e657269630c6572610c4572610001010420496d6d6f7274616c0000001c4d6f7274616c31040008000001001c4d6f7274616c32040008000002001c4d6f7274616c33040008000003001c4d6f7274616c34040008000004001c4d6f7274616c35040008000005001c4d6f7274616c36040008000006001c4d6f7274616c37040008000007001c4d6f7274616c38040008000008001c4d6f7274616c3904000800000900204d6f7274616c313004000800000a00204d6f7274616c313104000800000b00204d6f7274616c313204000800000c00204d6f7274616c313304000800000d00204d6f7274616c313404000800000e00204d6f7274616c313504000800000f00204d6f7274616c313604000800001000204d6f7274616c313704000800001100204d6f7274616c313804000800001200204d6f7274616c313904000800001300204d6f7274616c323004000800001400204d6f7274616c323104000800001500204d6f7274616c323204000800001600204d6f7274616c323304000800001700204d6f7274616c323404000800001800204d6f7274616c323504000800001900204d6f7274616c323604000800001a00204d6f7274616c323704000800001b00204d6f7274616c323804000800001c00204d6f7274616c323904000800001d00204d6f7274616c333004000800001e00204d6f7274616c333104000800001f00204d6f7274616c333204000800002000204d6f7274616c333304000800002100204d6f7274616c333404000800002200204d6f7274616c333504000800002300204d6f7274616c333604000800002400204d6f7274616c333704000800002500204d6f7274616c333804000800002600204d6f7274616c333904000800002700204d6f7274616c343004000800002800204d6f7274616c343104000800002900204d6f7274616c343204000800002a00204d6f7274616c343304000800002b00204d6f7274616c343404000800002c00204d6f7274616c343504000800002d00204d6f7274616c343604000800002e00204d6f7274616c343704000800002f00204d6f7274616c343804000800003000204d6f7274616c343904000800003100204d6f7274616c353004000800003200204d6f7274616c353104000800003300204d6f7274616c353204000800003400204d6f7274616c353304000800003500204d6f7274616c353404000800003600204d6f7274616c353504000800003700204d6f7274616c353604000800003800204d6f7274616c353704000800003900204d6f7274616c353804000800003a00204d6f7274616c353904000800003b00204d6f7274616c363004000800003c00204d6f7274616c363104000800003d00204d6f7274616c363204000800003e00204d6f7274616c363304000800003f00204d6f7274616c363404000800004000204d6f7274616c363504000800004100204d6f7274616c363604000800004200204d6f7274616c363704000800004300204d6f7274616c363804000800004400204d6f7274616c363904000800004500204d6f7274616c373004000800004600204d6f7274616c373104000800004700204d6f7274616c373204000800004800204d6f7274616c373304000800004900204d6f7274616c373404000800004a00204d6f7274616c373504000800004b00204d6f7274616c373604000800004c00204d6f7274616c373704000800004d00204d6f7274616c373804000800004e00204d6f7274616c373904000800004f00204d6f7274616c383004000800005000204d6f7274616c383104000800005100204d6f7274616c383204000800005200204d6f7274616c383304000800005300204d6f7274616c383404000800005400204d6f7274616c383504000800005500204d6f7274616c383604000800005600204d6f7274616c383704000800005700204d6f7274616c383804000800005800204d6f7274616c383904000800005900204d6f7274616c393004000800005a00204d6f7274616c393104000800005b00204d6f7274616c393204000800005c00204d6f7274616c393304000800005d00204d6f7274616c393404000800005e00204d6f7274616c393504000800005f00204d6f7274616c393604000800006000204d6f7274616c393704000800006100204d6f7274616c393804000800006200204d6f7274616c393904000800006300244d6f7274616c31303004000800006400244d6f7274616c31303104000800006500244d6f7274616c31303204000800006600244d6f7274616c31303304000800006700244d6f7274616c31303404000800006800244d6f7274616c31303504000800006900244d6f7274616c31303604000800006a00244d6f7274616c31303704000800006b00244d6f7274616c31303804000800006c00244d6f7274616c31303904000800006d00244d6f7274616c31313004000800006e00244d6f7274616c31313104000800006f00244d6f7274616c31313204000800007000244d6f7274616c31313304000800007100244d6f7274616c31313404000800007200244d6f7274616c31313504000800007300244d6f7274616c31313604000800007400244d6f7274616c31313704000800007500244d6f7274616c31313804000800007600244d6f7274616c31313904000800007700244d6f7274616c31323004000800007800244d6f7274616c31323104000800007900244d6f7274616c31323204000800007a00244d6f7274616c31323304000800007b00244d6f7274616c31323404000800007c00244d6f7274616c31323504000800007d00244d6f7274616c31323604000800007e00244d6f7274616c31323704000800007f00244d6f7274616c31323804000800008000244d6f7274616c31323904000800008100244d6f7274616c31333004000800008200244d6f7274616c31333104000800008300244d6f7274616c31333204000800008400244d6f7274616c31333304000800008500244d6f7274616c31333404000800008600244d6f7274616c31333504000800008700244d6f7274616c31333604000800008800244d6f7274616c31333704000800008900244d6f7274616c31333804000800008a00244d6f7274616c31333904000800008b00244d6f7274616c31343004000800008c00244d6f7274616c31343104000800008d00244d6f7274616c31343204000800008e00244d6f7274616c31343304000800008f00244d6f7274616c31343404000800009000244d6f7274616c31343504000800009100244d6f7274616c31343604000800009200244d6f7274616c31343704000800009300244d6f7274616c31343804000800009400244d6f7274616c31343904000800009500244d6f7274616c31353004000800009600244d6f7274616c31353104000800009700244d6f7274616c31353204000800009800244d6f7274616c31353304000800009900244d6f7274616c31353404000800009a00244d6f7274616c31353504000800009b00244d6f7274616c31353604000800009c00244d6f7274616c31353704000800009d00244d6f7274616c31353804000800009e00244d6f7274616c31353904000800009f00244d6f7274616c3136300400080000a000244d6f7274616c3136310400080000a100244d6f7274616c3136320400080000a200244d6f7274616c3136330400080000a300244d6f7274616c3136340400080000a400244d6f7274616c3136350400080000a500244d6f7274616c3136360400080000a600244d6f7274616c3136370400080000a700244d6f7274616c3136380400080000a800244d6f7274616c3136390400080000a900244d6f7274616c3137300400080000aa00244d6f7274616c3137310400080000ab00244d6f7274616c3137320400080000ac00244d6f7274616c3137330400080000ad00244d6f7274616c3137340400080000ae00244d6f7274616c3137350400080000af00244d6f7274616c3137360400080000b000244d6f7274616c3137370400080000b100244d6f7274616c3137380400080000b200244d6f7274616c3137390400080000b300244d6f7274616c3138300400080000b400244d6f7274616c3138310400080000b500244d6f7274616c3138320400080000b600244d6f7274616c3138330400080000b700244d6f7274616c3138340400080000b800244d6f7274616c3138350400080000b900244d6f7274616c3138360400080000ba00244d6f7274616c3138370400080000bb00244d6f7274616c3138380400080000bc00244d6f7274616c3138390400080000bd00244d6f7274616c3139300400080000be00244d6f7274616c3139310400080000bf00244d6f7274616c3139320400080000c000244d6f7274616c3139330400080000c100244d6f7274616c3139340400080000c200244d6f7274616c3139350400080000c300244d6f7274616c3139360400080000c400244d6f7274616c3139370400080000c500244d6f7274616c3139380400080000c600244d6f7274616c3139390400080000c700244d6f7274616c3230300400080000c800244d6f7274616c3230310400080000c900244d6f7274616c3230320400080000ca00244d6f7274616c3230330400080000cb00244d6f7274616c3230340400080000cc00244d6f7274616c3230350400080000cd00244d6f7274616c3230360400080000ce00244d6f7274616c3230370400080000cf00244d6f7274616c3230380400080000d000244d6f7274616c3230390400080000d100244d6f7274616c3231300400080000d200244d6f7274616c3231310400080000d300244d6f7274616c3231320400080000d400244d6f7274616c3231330400080000d500244d6f7274616c3231340400080000d600244d6f7274616c3231350400080000d700244d6f7274616c3231360400080000d800244d6f7274616c3231370400080000d900244d6f7274616c3231380400080000da00244d6f7274616c3231390400080000db00244d6f7274616c3232300400080000dc00244d6f7274616c3232310400080000dd00244d6f7274616c3232320400080000de00244d6f7274616c3232330400080000df00244d6f7274616c3232340400080000e000244d6f7274616c3232350400080000e100244d6f7274616c3232360400080000e200244d6f7274616c3232370400080000e300244d6f7274616c3232380400080000e400244d6f7274616c3232390400080000e500244d6f7274616c3233300400080000e600244d6f7274616c3233310400080000e700244d6f7274616c3233320400080000e800244d6f7274616c3233330400080000e900244d6f7274616c3233340400080000ea00244d6f7274616c3233350400080000eb00244d6f7274616c3233360400080000ec00244d6f7274616c3233370400080000ed00244d6f7274616c3233380400080000ee00244d6f7274616c3233390400080000ef00244d6f7274616c3234300400080000f000244d6f7274616c3234310400080000f100244d6f7274616c3234320400080000f200244d6f7274616c3234330400080000f300244d6f7274616c3234340400080000f400244d6f7274616c3234350400080000f500244d6f7274616c3234360400080000f600244d6f7274616c3234370400080000f700244d6f7274616c3234380400080000f800244d6f7274616c3234390400080000f900244d6f7274616c3235300400080000fa00244d6f7274616c3235310400080000fb00244d6f7274616c3235320400080000fc00244d6f7274616c3235330400080000fd00244d6f7274616c3235340400080000fe00244d6f7274616c3235350400080000ff0000710310306672616d655f73797374656d28657874656e73696f6e732c636865636b5f6e6f6e636528436865636b4e6f6e636504045400000400b1010120543a3a4e6f6e63650000750310306672616d655f73797374656d28657874656e73696f6e7330636865636b5f7765696768742c436865636b5765696768740404540000000079030c3c7175616e7475735f72756e74696d65587472616e73616374696f6e5f657874656e73696f6e737852657665727369626c655472616e73616374696f6e457874656e73696f6e040454000000007d030c3c7175616e7475735f72756e74696d65587472616e73616374696f6e5f657874656e73696f6e7378576f726d686f6c6550726f6f665265636f72646572457874656e73696f6e040454000000008103086870616c6c65745f7472616e73616374696f6e5f7061796d656e74604368617267655472616e73616374696f6e5061796d656e74040454000004002d01013042616c616e63654f663c543e0000850308746672616d655f6d657461646174615f686173685f657874656e73696f6e44436865636b4d657461646174614861736804045400000401106d6f6465890301104d6f64650000890308746672616d655f6d657461646174615f686173685f657874656e73696f6e104d6f64650001082044697361626c65640000001c456e61626c6564000100008d0310306672616d655f73797374656d28657874656e73696f6e73387765696768745f7265636c61696d345765696768745265636c61696d040454000000009103083c7175616e7475735f72756e74696d651c52756e74696d6500000000481853797374656d011853797374656d501c4163636f756e7401010402000c4101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008004e8205468652066756c6c206163636f756e7420696e666f726d6174696f6e20666f72206120706172746963756c6172206163636f756e742049442e3845787472696e736963436f756e74000010040004b820546f74616c2065787472696e7369637320636f756e7420666f72207468652063757272656e7420626c6f636b2e40496e686572656e74734170706c696564010020040004a4205768657468657220616c6c20696e686572656e74732068617665206265656e206170706c6965642e2c426c6f636b576569676874010024180000000000000488205468652063757272656e742077656967687420666f722074686520626c6f636b2e40416c6c45787472696e736963734c656e000010040004410120546f74616c206c656e6774682028696e2062797465732920666f7220616c6c2065787472696e736963732070757420746f6765746865722c20666f72207468652063757272656e7420626c6f636b2e24426c6f636b486173680101040510348000000000000000000000000000000000000000000000000000000000000000000498204d6170206f6620626c6f636b206e756d6265727320746f20626c6f636b206861736865732e3445787472696e736963446174610101040510380400043d012045787472696e73696373206461746120666f72207468652063757272656e7420626c6f636b20286d61707320616e2065787472696e736963277320696e64657820746f206974732064617461292e184e756d6265720100101000000000040901205468652063757272656e7420626c6f636b206e756d626572206265696e672070726f6365737365642e205365742062792060657865637574655f626c6f636b602e28506172656e744861736801003480000000000000000000000000000000000000000000000000000000000000000004702048617368206f66207468652070726576696f757320626c6f636b2e1844696765737401003c040004f020446967657374206f66207468652063757272656e7420626c6f636b2c20616c736f2070617274206f662074686520626c6f636b206865616465722e285a6b54726565526f6f740100348000000000000000000000000000000000000000000000000000000000000000001490205a4b207472656520726f6f7420666f72207468652063757272656e7420626c6f636b2e002501205365742062792070616c6c65742d7a6b2d7472656520647572696e6720626c6f636b2066696e616c697a6174696f6e2e205468697320697320696e636c7564656420696e207468652d0120626c6f636b20686561646572206173206120646564696361746564206669656c6420286e6f7420696e206469676573742920746f20656e737572652061206669786564206f66667365747420666f72205a4b206369726375697420766572696669636174696f6e2e184576656e747301004c04001ca0204576656e7473206465706f736974656420666f72207468652063757272656e7420626c6f636b2e001d01204e4f54453a20546865206974656d20697320756e626f756e6420616e642073686f756c64207468657265666f7265206e657665722062652072656164206f6e20636861696e2ed020497420636f756c64206f746865727769736520696e666c6174652074686520506f562073697a65206f66206120626c6f636b2e002d01204576656e747320686176652061206c6172676520696e2d6d656d6f72792073697a652e20426f7820746865206576656e747320746f206e6f7420676f206f75742d6f662d6d656d6f7279fc206a75737420696e206361736520736f6d656f6e65207374696c6c207265616473207468656d2066726f6d2077697468696e207468652072756e74696d652e284576656e74436f756e74010010100000000004b820546865206e756d626572206f66206576656e747320696e2074686520604576656e74733c543e60206c6973742e2c4576656e74546f706963730101040234a5010400282501204d617070696e67206265747765656e206120746f7069632028726570726573656e74656420627920543a3a486173682920616e64206120766563746f72206f6620696e646578657394206f66206576656e747320696e2074686520603c4576656e74733c543e3e60206c6973742e00510120416c6c20746f70696320766563746f727320686176652064657465726d696e69737469632073746f72616765206c6f636174696f6e7320646570656e64696e67206f6e2074686520746f7069632e2054686973450120616c6c6f7773206c696768742d636c69656e747320746f206c6576657261676520746865206368616e67657320747269652073746f7261676520747261636b696e67206d656368616e69736d20616e64e420696e2063617365206f66206368616e67657320666574636820746865206c697374206f66206576656e7473206f6620696e7465726573742e005901205468652076616c756520686173207468652074797065206028426c6f636b4e756d626572466f723c543e2c204576656e74496e646578296020626563617573652069662077652075736564206f6e6c79206a7573744d012074686520604576656e74496e64657860207468656e20696e20636173652069662074686520746f70696320686173207468652073616d6520636f6e74656e7473206f6e20746865206e65787420626c6f636b0101206e6f206e6f74696669636174696f6e2077696c6c20626520747269676765726564207468757320746865206576656e74206d69676874206265206c6f73742e484c61737452756e74696d65557067726164650000ad0104000455012053746f726573207468652060737065635f76657273696f6e6020616e642060737065635f6e616d6560206f66207768656e20746865206c6173742072756e74696d6520757067726164652068617070656e65642e545570677261646564546f553332526566436f756e740100200400044d012054727565206966207765206861766520757067726164656420736f207468617420607479706520526566436f756e74602069732060753332602e2046616c7365202864656661756c7429206966206e6f742e605570677261646564546f547269706c65526566436f756e740100200400085d012054727565206966207765206861766520757067726164656420736f2074686174204163636f756e74496e666f20636f6e7461696e73207468726565207479706573206f662060526566436f756e74602e2046616c736548202864656661756c7429206966206e6f742e38457865637574696f6e50686173650000a101040004882054686520657865637574696f6e207068617365206f662074686520626c6f636b2e44417574686f72697a6564557067726164650000bd01040004b82060536f6d6560206966206120636f6465207570677261646520686173206265656e20617574686f72697a65642e6045787472696e7369635765696768745265636c61696d65640100280800001ca02054686520776569676874207265636c61696d656420666f72207468652065787472696e7369632e002101205468697320696e666f726d6174696f6e20697320617661696c61626c6520756e74696c2074686520656e64206f66207468652065787472696e73696320657865637574696f6e2e2101204d6f726520707265636973656c79207468697320696e666f726d6174696f6e2069732072656d6f76656420696e20606e6f74655f6170706c6965645f65787472696e736963602e007101204c6f67696320646f696e6720736f6d6520706f73742064697370617463682077656967687420726564756374696f6e206d7573742075706461746520746869732073746f7261676520746f2061766f6964206475706c69636174652c20726564756374696f6e2e01090101581830426c6f636b57656967687473c101fd01620f55a9000b0060defb740513ffffffffffffffffa217f0b600010b400e0cb28b031366666666666666a6010b00c8e6bc170413ffffffffffffffbf010000a217f0b600010b40a603f1e8041366666666666666e6010b0060defb740513ffffffffffffffff010b0098f73e5d01130000000000000040a217f0b60000000004d020426c6f636b20262065787472696e7369637320776569676874733a20626173652076616c75657320616e64206c696d6974732e2c426c6f636b4c656e677468cd013000003c00000050000000500004a820546865206d6178696d756d206c656e677468206f66206120626c6f636b2028696e206279746573292e38426c6f636b48617368436f756e74101000100000045501204d6178696d756d206e756d626572206f6620626c6f636b206e756d62657220746f20626c6f636b2068617368206d617070696e677320746f206b65657020286f6c64657374207072756e6564206669727374292e204462576569676874d5014040787d010000000000e1f505000000000409012054686520776569676874206f662072756e74696d65206461746162617365206f7065726174696f6e73207468652072756e74696d652063616e20696e766f6b652e1c56657273696f6ed90109033c7175616e7475732d72756e74696d653c7175616e7475732d72756e74696d6501000000940000000100000030df6acb689907609b0500000037e397fc7c91f5e40200000040fe3ad401f8959a06000000d2bc9897eed08f1503000000f78b278be53f454c02000000ab3c0572291feb8b010000001328a9fc2e30061301000000245859d9e78bc66901000000bc9d89904f5b923f0100000037c8bb1350a9a2a804000000f3ff14d5ab52705903000000fbc577b9d747efd60100000006000000010484204765742074686520636861696e277320696e2d636f64652076657273696f6e2e2853533538507265666978f008bd0014a8205468652064657369676e61746564205353353820707265666978206f66207468697320636861696e2e0039012054686973207265706c6163657320746865202273733538466f726d6174222070726f7065727479206465636c6172656420696e2074686520636861696e20737065632e20526561736f6e20697331012074686174207468652072756e74696d652073686f756c64206b6e6f772061626f7574207468652070726566697820696e206f7264657220746f206d616b6520757365206f662069742061737020616e206964656e746966696572206f662074686520636861696e2e01ed01002454696d657374616d70012454696d657374616d70080c4e6f7701003020000000000000000004a0205468652063757272656e742074696d6520666f72207468652063757272656e7420626c6f636b2e24446964557064617465010020040010d82057686574686572207468652074696d657374616d7020686173206265656e207570646174656420696e207468697320626c6f636b2e00550120546869732076616c7565206973207570646174656420746f206074727565602075706f6e207375636365737366756c207375626d697373696f6e206f6620612074696d657374616d702062792061206e6f64652e4501204974206973207468656e20636865636b65642061742074686520656e64206f66206561636820626c6f636b20657865637574696f6e20696e2074686520606f6e5f66696e616c697a656020686f6f6b2e0119010004344d696e696d756d506572696f6430206400000000000000188c20546865206d696e696d756d20706572696f64206265747765656e20626c6f636b732e004d012042652061776172652074686174207468697320697320646966666572656e7420746f20746865202a65787065637465642a20706572696f6420746861742074686520626c6f636b2070726f64756374696f6e4901206170706172617475732070726f76696465732e20596f75722063686f73656e20636f6e73656e7375732073797374656d2077696c6c2067656e6572616c6c7920776f726b2077697468207468697320746f61012064657465726d696e6520612073656e7369626c6520626c6f636b2074696d652e20466f72206578616d706c652c20696e2074686520417572612070616c6c65742069742077696c6c20626520646f75626c6520746869737020706572696f64206f6e2064656661756c742073657474696e67732e00012042616c616e636573012042616c616e6365731c34546f74616c49737375616e6365010018400000000000000000000000000000000004982054686520746f74616c20756e6974732069737375656420696e207468652073797374656d2e40496e61637469766549737375616e636501001840000000000000000000000000000000000409012054686520746f74616c20756e697473206f66206f75747374616e64696e672064656163746976617465642062616c616e636520696e207468652073797374656d2e1c4163636f756e74010104020014010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080600901205468652042616c616e6365732070616c6c6574206578616d706c65206f662073746f72696e67207468652062616c616e6365206f6620616e206163636f756e742e00282023204578616d706c650034206060606e6f636f6d70696c65b02020696d706c2070616c6c65745f62616c616e6365733a3a436f6e66696720666f722052756e74696d65207b19022020202074797065204163636f756e7453746f7265203d2053746f726167654d61705368696d3c53656c663a3a4163636f756e743c52756e74696d653e2c206672616d655f73797374656d3a3a50726f76696465723c52756e74696d653e2c204163636f756e7449642c2053656c663a3a4163636f756e74446174613c42616c616e63653e3e0c20207d102060606000150120596f752063616e20616c736f2073746f7265207468652062616c616e6365206f6620616e206163636f756e7420696e20746865206053797374656d602070616c6c65742e00282023204578616d706c650034206060606e6f636f6d70696c65b02020696d706c2070616c6c65745f62616c616e6365733a3a436f6e66696720666f722052756e74696d65207b7420202074797065204163636f756e7453746f7265203d2053797374656d0c20207d102060606000510120427574207468697320636f6d657320776974682074726164656f6666732c2073746f72696e67206163636f756e742062616c616e63657320696e207468652073797374656d2070616c6c65742073746f7265736d0120606672616d655f73797374656d60206461746120616c6f6e677369646520746865206163636f756e74206461746120636f6e747261727920746f2073746f72696e67206163636f756e742062616c616e63657320696e207468652901206042616c616e636573602070616c6c65742c20776869636820757365732061206053746f726167654d61706020746f2073746f72652062616c616e6365732064617461206f6e6c792e4101204e4f54453a2054686973206973206f6e6c79207573656420696e207468652063617365207468617420746869732070616c6c6574206973207573656420746f2073746f72652062616c616e6365732e144c6f636b730101040200f101040010b820416e79206c6971756964697479206c6f636b73206f6e20736f6d65206163636f756e742062616c616e6365732e2501204e4f54453a2053686f756c64206f6e6c79206265206163636573736564207768656e2073657474696e672c206368616e67696e6720616e642066726565696e672061206c6f636b2e00ad0120557365206f66206c6f636b73206973206465707265636174656420696e206661766f7572206f6620667265657a65732e20536565206068747470733a2f2f6769746875622e636f6d2f706172697479746563682f7375627374726174652f70756c6c2f31323935312f602052657365727665730101040200010204000ca4204e616d6564207265736572766573206f6e20736f6d65206163636f756e742062616c616e6365732e00b10120557365206f66207265736572766573206973206465707265636174656420696e206661766f7572206f6620686f6c64732e20536565206068747470733a2f2f6769746875622e636f6d2f706172697479746563682f7375627374726174652f70756c6c2f31323935312f6014486f6c647301010402000d020400046c20486f6c6473206f6e206163636f756e742062616c616e6365732e1c467265657a6573010104020019020400048820467265657a65206c6f636b73206f6e206163636f756e742062616c616e6365732e011d01018010484578697374656e7469616c4465706f736974184000ca9a3b00000000000000000000000020410120546865206d696e696d756d20616d6f756e7420726571756972656420746f206b65657020616e206163636f756e74206f70656e2e204d5553542042452047524541544552205448414e205a45524f2100590120496620796f75202a7265616c6c792a206e65656420697420746f206265207a65726f2c20796f752063616e20656e61626c652074686520666561747572652060696e7365637572655f7a65726f5f65646020666f72610120746869732070616c6c65742e20486f77657665722c20796f7520646f20736f20617420796f7572206f776e207269736b3a20746869732077696c6c206f70656e2075702061206d616a6f7220446f5320766563746f722e590120496e206361736520796f752068617665206d756c7469706c6520736f7572636573206f662070726f7669646572207265666572656e6365732c20796f75206d617920616c736f2067657420756e65787065637465648c206265686176696f757220696620796f7520736574207468697320746f207a65726f2e00f020426f74746f6d206c696e653a20446f20796f757273656c662061206661766f757220616e64206d616b65206974206174206c65617374206f6e6521204d61784c6f636b7310103200000010f420546865206d6178696d756d206e756d626572206f66206c6f636b7320746861742073686f756c64206578697374206f6e20616e206163636f756e742edc204e6f74207374726963746c7920656e666f726365642c20627574207573656420666f722077656967687420657374696d6174696f6e2e00ad0120557365206f66206c6f636b73206973206465707265636174656420696e206661766f7572206f6620667265657a65732e20536565206068747470733a2f2f6769746875622e636f6d2f706172697479746563682f7375627374726174652f70756c6c2f31323935312f602c4d617852657365727665731010000000000c0d0120546865206d6178696d756d206e756d626572206f66206e616d656420726573657276657320746861742063616e206578697374206f6e20616e206163636f756e742e00b10120557365206f66207265736572766573206973206465707265636174656420696e206661766f7572206f6620686f6c64732e20536565206068747470733a2f2f6769746875622e636f6d2f706172697479746563682f7375627374726174652f70756c6c2f31323935312f60284d6178467265657a657310100000000004610120546865206d6178696d756d206e756d626572206f6620696e646976696475616c20667265657a65206c6f636b7320746861742063616e206578697374206f6e20616e206163636f756e7420617420616e792074696d652e01290202485472616e73616374696f6e5061796d656e7401485472616e73616374696f6e5061796d656e740c444e6578744665654d756c7469706c69657201002d0240000064a7b3b6e00d0000000000000000003853746f7261676556657273696f6e010031020400003c54785061796d656e744372656469740000350204000cf02054686520604f6e4368617267655472616e73616374696f6e602073746f726573207468652077697468647261776e2074782066656520686572652e00350120557365206077697468647261775f74786665656020616e64206072656d61696e696e675f74786665656020746f206163636573732066726f6d206f757473696465207468652063726174652e00019804604f7065726174696f6e616c4665654d756c7469706c696572080405545901204120666565206d756c7469706c69657220666f7220604f7065726174696f6e616c602065787472696e7369637320746f20636f6d7075746520227669727475616c207469702220746f20626f6f73742074686569722c20607072696f726974796000510120546869732076616c7565206973206d756c7469706c69656420627920746865206066696e616c5f6665656020746f206f627461696e206120227669727475616c20746970222074686174206973206c61746572f420616464656420746f20612074697020636f6d706f6e656e7420696e20726567756c617220607072696f72697479602063616c63756c6174696f6e732e4d01204974206d65616e732074686174206120604e6f726d616c60207472616e73616374696f6e2063616e2066726f6e742d72756e20612073696d696c61726c792d73697a656420604f7065726174696f6e616c6041012065787472696e736963202877697468206e6f20746970292c20627920696e636c7564696e672061207469702076616c75652067726561746572207468616e20746865207669727475616c207469702e003c20606060727573742c69676e6f726540202f2f20466f7220604e6f726d616c608c206c6574207072696f72697479203d207072696f726974795f63616c6328746970293b0054202f2f20466f7220604f7065726174696f6e616c601101206c6574207669727475616c5f746970203d2028696e636c7573696f6e5f666565202b2074697029202a204f7065726174696f6e616c4665654d756c7469706c6965723bc4206c6574207072696f72697479203d207072696f726974795f63616c6328746970202b207669727475616c5f746970293b1020606060005101204e6f746520746861742073696e636520776520757365206066696e616c5f6665656020746865206d756c7469706c696572206170706c69657320616c736f20746f2074686520726567756c61722060746970605d012073656e74207769746820746865207472616e73616374696f6e2e20536f2c206e6f74206f6e6c7920646f657320746865207472616e73616374696f6e206765742061207072696f726974792062756d702062617365646101206f6e207468652060696e636c7573696f6e5f666565602c2062757420776520616c736f20616d706c6966792074686520696d70616374206f662074697073206170706c69656420746f20604f7065726174696f6e616c6038207472616e73616374696f6e732e00031051506f57011051506f570c344c617374426c6f636b54696d6501003020000000000000000000444c617374426c6f636b4475726174696f6e010030200000000000000000004443757272656e74446966666963756c74790100a40101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019c0c44496e697469616c446966666963756c7479a4010100093d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003c546172676574426c6f636b54696d653020e02e00000000000000344d617852656f72674465707468101064000000000005344d696e696e675265776172647301344d696e696e67526577617264730434436f6c6c6563746564466565730100184000000000000000000000000000000000041501204665657320616e64206661696c65642d6d696e742072657472696573206177616974696e6720646973747269627574696f6e20627920606f6e5f66696e616c697a65602e0001ac10244d6178537570706c791840000034bbbcfc6e230100000000000000048c20546865206d6178696d756d20746f74616c20737570706c79206f6620746f6b656e733c456d697373696f6e44697669736f721840a860e700000000000000000000000000040901205468652064697669736f72207573656420746f2063616c63756c61746520626c6f636b20726577617264732066726f6d2072656d61696e696e6720737570706c7910556e697418400010a5d4e8000000000000000000000004f420546865206261736520756e697420666f7220746f6b656e20616d6f756e74732028652e672e2c203165313220666f7220313220646563696d616c7329384d696e74696e674163636f756e7400800101010101010101010101010101010101010101010101010101010101010101045901204163636f756e74204944207573656420617320746865202266726f6d22206163636f756e74207768656e206372656174696e67207472616e736665722070726f6f667320666f72206d696e74656420746f6b656e73000620507265696d6167650120507265696d6167650c24537461747573466f7200010406343d020400049020546865207265717565737420737461747573206f66206120676976656e20686173682e4052657175657374537461747573466f72000104063449020400049020546865207265717565737420737461747573206f66206120676976656e20686173682e2c507265696d616765466f720001040659025d0204000001310101b00001610207245363686564756c657201245363686564756c65721850496e636f6d706c657465426c6f636b53696e6365000010040004490120547261636b7320696e636f6d706c65746520626c6f636b2d6261736564206167656e6461732074686174206e65656420746f2062652070726f63657373656420696e2061206c6174657220626c6f636b2e60496e636f6d706c65746554696d657374616d7053696e6365000030040004590120547261636b7320696e636f6d706c6574652074696d657374616d702d6261736564206167656e6461732074686174206e65656420746f2062652070726f63657373656420696e2061206c6174657220626c6f636b2e584c61737450726f63657373656454696d657374616d70000030040008ec20547261636b7320746865206c6173742074696d657374616d70206275636b65742074686174207761732066756c6c792070726f6365737365642ef0205573656420746f2061766f696420726570726f63657373696e6720616c6c206275636b6574732066726f6d2030206f6e2065766572792072756e2e184167656e646101010405b865020400044d01204974656d7320746f2062652065786563757465642c20696e64657865642062792074686520626c6f636b206e756d626572207468617420746865792073686f756c64206265206578656375746564206f6e2e1c5265747269657300010402bc7502040004210120526574727920636f6e66696775726174696f6e7320666f72206974656d7320746f2062652065786563757465642c20696e6465786564206279207461736b20616464726573732e184c6f6f6b75700001040504bc040004f8204c6f6f6b75702066726f6d2061206e616d6520746f2074686520626c6f636b206e756d62657220616e6420696e646578206f6620746865207461736b2e0001b40c344d6178696d756d57656967687428400b00804b965d0413cccccccccccccccc04290120546865206d6178696d756d207765696768742074686174206d6179206265207363686564756c65642070657220626c6f636b20666f7220616e7920646973706174636861626c65732e504d61785363686564756c6564506572426c6f636b101032000000141d0120546865206d6178696d756d206e756d626572206f66207363686564756c65642063616c6c7320696e2074686520717565756520666f7220612073696e676c6520626c6f636b2e0018204e4f54453a5101202b20446570656e64656e742070616c6c657473272062656e63686d61726b73206d696768742072657175697265206120686967686572206c696d697420666f72207468652073657474696e672e205365742061c420686967686572206c696d697420756e646572206072756e74696d652d62656e63686d61726b736020666561747572652e4c54696d657374616d704275636b657453697a653020c05d0000000000000c9020507265636973696f6e206f66207468652074696d657374616d70206275636b6574732e0041012054696d657374616d7020626173656420646973706174636865732061726520726f756e64656420746f20746865206e656172657374206275636b6574206f66207468697320707265636973696f6e2e017902081c5574696c6974790001390101cc044c626174636865645f63616c6c735f6c696d69741010aa2a000004a820546865206c696d6974206f6e20746865206e756d626572206f6620626174636865642063616c6c732e017d02094c52657665727369626c655472616e7366657273014c52657665727369626c655472616e736665727314504869676853656375726974794163636f756e7473000104020081020400083101204d617073206163636f756e747320746f2074686569722063686f73656e207265766572736962696c6974792064656c617920706572696f642028696e206d696c6c697365636f6e6473292ee4204163636f756e74732070726573656e7420696e2074686973206d61702068617665207265766572736962696c69747920656e61626c65642e4c486967685365637572697479547851756f746101010402008502040014350120526f6c6c696e672077696e646f77206f6620696e636c75646564207369676e65642065787472696e7369637320666f72206561636820686967682d7365637572697479206163636f756e742e000d01204f6c6465737420626c6f636b206e756d62657220697320617420696e64657820302e205265636f7264696e672061207478206973204f2831293a20636f6d70617265190120606e6f77202d206f6c646573746020746f205b60436f6e6669673a3a486967685365637572697479547857696e646f77426c6f636b73605d2c206d61796265206576696374fc2074686174206f6e6520686561642c207468656e20707573682e204e6f726d616c206163636f756e747320617265206e6f742073746f72656420686572652e4050656e64696e675472616e73666572730001040234890204000831012053746f726573207468652064657461696c73206f662070656e64696e67207472616e73616374696f6e73207363686564756c656420666f722064656c6179656420657865637574696f6e2e90204b657965642062792074686520756e69717565207472616e73616374696f6e2049442e6050656e64696e675472616e7366657273427953656e64657201010402008d02040004fc204d6170732073656e646572206163636f756e747320746f207468656972206c697374206f662070656e64696e67207472616e73616374696f6e204944732e444e6578745472616e73616374696f6e49640100302000000000000000000c2901204d6f6e6f746f6e6963616c6c7920696e6372656173696e6720636f756e746572207573656420746f2067656e657261746520756e69717565207472616e73616374696f6e204944732e25012045616368207363686564756c6564207472616e7366657220696e6372656d656e747320746869732076616c756520746f20656e73757265206e6f2074776f207472616e736665727309012070726f64756365207468652073616d65206074785f6964602c206576656e20696620746865792068617665206964656e746963616c20706172616d65746572732e01410101d01c504d617850656e64696e675065724163636f756e7410101000000004f4204d6178696d756d2070656e64696e672072657665727369626c65207472616e73616374696f6e7320616c6c6f77656420706572206163636f756e742e6c4d617848696768536563757269747954787350657257696e646f77101010000000081501204d6178696d756d207369676e65642065787472696e73696373206120686967682d7365637572697479206163636f756e74206d617920696e636c75646520696e206f6e65c820726f6c6c696e672077696e646f772e20557064617465206f66207468652071756f74612072696e67206973204f2831292e68486967685365637572697479547857696e646f77426c6f636b731010201c000008fc204c656e677468206f662074686520686967682d73656375726974792065787472696e7369632071756f74612077696e646f772c20696e20626c6f636b732ed8204174207468652072756e74696d65277320313273207461726765742074686973206973206f6e65206461792028604441595360292e3044656661756c7444656c6179b81400201c00000c2d01205468652064656661756c742064656c617920706572696f6420666f722072657665727369626c65207472616e73616374696f6e73206966206e6f6e65206973207370656369666965642e00a4204e4f54453a2064656661756c742064656c617920697320616c7761797320696e20626c6f636b732e504d696e44656c6179506572696f64426c6f636b7310100200000004250120546865206d696e696d756d2064656c617920706572696f6420616c6c6f77656420666f722072657665727369626c65207472616e73616374696f6e732c20696e20626c6f636b732e504d696e44656c6179506572696f644d6f6d656e743020e02e000000000000043d0120546865206d696e696d756d2064656c617920706572696f6420616c6c6f77656420666f722072657665727369626c65207472616e73616374696f6e732c20696e206d696c6c697365636f6e64732e24566f6c756d65466565910210102700000c350120566f6c756d65206665652074616b656e2066726f6d207265766572736564207472616e73616374696f6e7320666f7220686967682d7365637572697479206163636f756e7473206f6e6c792c6101206578707265737365642061732061205065726d696c6c2028652e672e2c205065726d696c6c3a3a66726f6d5f70657263656e74283129203d203125292e20526567756c6172206163636f756e747320696e637572206e6fdc20666565732e2054686520666565206973206275726e6564202872656d6f7665642066726f6d20746f74616c2069737375616e6365292e0195020b3854656368436f6c6c656374697665013854656368436f6c6c656374697665182c4d656d626572436f756e7401010405f010100000000008690120546865206e756d626572206f66206d656d6265727320696e2074686520636f6c6c6563746976652077686f2068617665206174206c65617374207468652072616e6b206163636f7264696e6720746f2074686520696e64657830206f6620746865207665632e1c4d656d62657273000104050099020400049c205468652063757272656e74206d656d62657273206f662074686520636f6c6c6563746976652e244964546f496e64657800010805059d021004000461012054686520696e646578206f6620656163682072616e6b732773206d656d62657220696e746f207468652067726f7570206f66206d656d626572732077686f2068617665206174206c6561737420746861742072616e6b2e24496e646578546f49640001080505a102000400085d0120546865206d656d6265727320696e2074686520636f6c6c65637469766520627920696e6465782e20416c6c20696e646963657320696e207468652072616e67652060302e2e4d656d626572436f756e74602077696c6c65012072657475726e2060536f6d65602c20686f77657665722061206d656d626572277320696e646578206973206e6f742067756172616e7465656420746f2072656d61696e20756e6368616e676564206f7665722074696d652e18566f74696e670001080205a502f4040004b420566f746573206f6e206120676976656e2070726f706f73616c2c206966206974206973206f6e676f696e672e34566f74696e67436c65616e75700001040210a90204000001450101ec0001ad020d34546563685265666572656e64610134546563685265666572656e64611c3c5265666572656e64756d436f756e74010010100000000004310120546865206e6578742066726565207265666572656e64756d20696e6465782c20616b6120746865206e756d626572206f66207265666572656e6461207374617274656420736f206661722e504163746976655265666572656e6461436f756e74010010100000000014350120546865206e756d626572206f66207265666572656e64612063757272656e746c7920696e2074686520604f6e676f696e67602073746174652c206163726f737320616c6c20747261636b732e00450120496e6372656d656e746564206f6e20607375626d69746020616e642064656372656d656e746564207768656e657665722061207265666572656e64756d20726561636865732061207465726d696e616c45012073746174652028617070726f7665642c2072656a65637465642c2074696d6564206f75742c2063616e63656c6c6564206f72206b696c6c6564292e20426f756e64732061646d697373696f6e732061745c205b60436f6e6669673a3a4d6178416374697665605d2e544163746976655375626d697373696f6e436f756e74010104050010100000000018210120546865206e756d626572206f66207265666572656e64612063757272656e746c7920696e2074686520604f6e676f696e676020737461746520706572207375626d69747465722e005101204d61696e7461696e656420616c6f6e6773696465205b604163746976655265666572656e6461436f756e74605d2028696e6372656d656e746564206f6e20607375626d6974602c2064656372656d656e7465641901206f6e206576657279207465726d696e616c207472616e736974696f6e2920616e6420626f756e64732065616368206163636f756e7427732061646d697373696f6e732061743d01205b60436f6e6669673a3a4d61784163746976655065724163636f756e74605d2c20736f206e6f2073696e676c65207375626d69747465722063616e2065786861757374207468652073686172656480205b60436f6e6669673a3a4d6178416374697665605d2063617061636974792e445265666572656e64756d496e666f466f720001040210b102040004b420496e666f726d6174696f6e20636f6e6365726e696e6720616e7920676976656e207265666572656e64756d2e28547261636b517565756501010405f0d1020400105d012054686520736f72746564206c697374206f66207265666572656e646120726561647920746f206265206465636964656420627574206e6f7420796574206265696e6720646563696465642c206f7264657265642062797c20636f6e76696374696f6e2d776569676874656420617070726f76616c732e00410120546869732073686f756c6420626520656d70747920696620604465636964696e67436f756e7460206973206c657373207468616e2060547261636b496e666f3a3a6d61785f6465636964696e67602e344465636964696e67436f756e7401010405f010100000000004c420546865206e756d626572206f66207265666572656e6461206265696e6720646563696465642063757272656e746c792e284d657461646174614f66000104021034040018050120546865206d6574616461746120697320612067656e6572616c20696e666f726d6174696f6e20636f6e6365726e696e6720746865207265666572656e64756d2e490120546865206048617368602072656665727320746f2074686520707265696d616765206f66207468652060507265696d61676573602070726f76696465722077686963682063616e2062652061204a534f4e882064756d70206f7220495046532068617368206f662061204a534f4e2066696c652e00750120436f6e73696465722061206761726261676520636f6c6c656374696f6e20666f722061206d65746164617461206f662066696e6973686564207265666572656e64756d7320746f2060756e7265717565737460202872656d6f76652944206c6172676520707265696d616765732e01490101fc20445375626d697373696f6e4465706f736974184000a0724e18090000000000000000000004350120546865206d696e696d756d20616d6f756e7420746f20626520757365642061732061206465706f73697420666f722061207075626c6963207265666572656e64756d2070726f706f73616c2e244d617851756575656410106400000004e4204d6178696d756d2073697a65206f6620746865207265666572656e64756d20717565756520666f7220612073696e676c6520747261636b2e244d6178416374697665101080000000283901204d6178696d756d206e756d626572206f66207265666572656e64612074686174206d617920626520604f6e676f696e6760206174206f6e63652c206163726f737320616c6c20747261636b732e0041012054686973206973206120676c6f62616c2061646d697373696f6e20626f756e6420656e666f7263656420696e20607375626d6974602e20497420616c736f20636f76657273207265666572656e646139012074686174206e6576657220726563656976652061206465636973696f6e206465706f73697420616e64207468657265666f7265206f6363757079206e6569746865722061206465636964696e67310120736c6f74206e6f7220612060547261636b51756575656020656e7472792c2079657420686f6c642073746f7261676520616e642061207363686564756c6572206167656e646120736c6f747c20756e74696c207468652060556e6465636964696e6754696d656f7574602e004901204d757374206265206174206c6561737420604d61785175657565646020706c7573207468652073756d206f6620616c6c20747261636b732720606d61785f6465636964696e676020706c7573206f6e652c410120736f207468617420746865206465636964696e6720736c6f747320616e6420747261636b207175657565732072656d61696e2066756c6c79207574696c697a61626c652028636865636b65642062794c2060696e746567726974795f7465737460292e4c4d61784163746976655065724163636f756e7410100800000024410120546865206d6178696d756d206e756d626572206f66207265666572656e646120616e79206f6e65206163636f756e74206d6179206861766520696e2074686520604f6e676f696e676020737461746524206174206f6e63652e002d01205b60436f6e6669673a3a4d6178416374697665605d206973206120736861726564207265736f757263653a20776974686f75742061207065722d6163636f756e74206361702c20616e7931012073696e676c65206163636f756e742070617373696e6720605375626d69744f726967696e6020636f756c642066696c6c206974207769746820726566756e6461626c652d6465706f7369743d01207265666572656e646120616e6420667265657a65207375626d697373696f6e20666f722065766572796f6e6520e2809420696e636c7564696e67207468652076657279207265666572656e64756d3901206e656564656420746f20696e74657276656e6520e2809420756e74696c207468652060556e6465636964696e6754696d656f757460202872656e657761626c79292e2053697a6520697420736f05012074686174206e6f20706c61757369626c6520636f616c6974696f6e206f66207375626d6974746572732063616e20726561636820604d6178416374697665603a210120604d61784163746976655065724163636f756e746020c39720286d6178696d756d20636f6e63757272656e74207375626d69747465727329203c20604d6178416374697665602e3c4d617850726f706f73616c53697a65101000000100241101204d6178696d756d20656e636f646564206c656e677468206f66206120604c6f6f6b7570602070726f706f73616c20616363657074656420627920607375626d6974602e00410120607375626d69746020607265717565737460732074686520707265696d61676520736f2061206c617465722060756e6e6f74655f707265696d616765602063616e6e6f742064656c657465207468653d01206279746573206265666f726520656e6163746d656e743b2074686174207265717565737420616c736f206c65747320746865206e6f746572207265636c61696d2074686569722073746f726167653901206465706f736974207768696c652074686520627974657320737461792070696e6e656420756e74696c20746865207265666572656e64756d20656e64732e20576974686f757420612073697a65390120626f756e642c20604d61784163746976656020c3972034204d6942206f66206465706f7369742d667265652073746174652063616e20616363756d756c61746520616761696e7374206f6e6c7935012074686520726566756e6461626c65205b60436f6e6669673a3a5375626d697373696f6e4465706f736974605d2e2053697a65207468697320736f20746861742074686520707265696d6167653d01206465706f73697420666f722061206d61782d73697a656420626c6f6220646f6573206e6f742065786365656420605375626d697373696f6e4465706f7369746020e28094207468656e206576656e2d012061667465722060756e6e6f74656020746865207375626d697373696f6e206465706f736974207374696c6c20636f6c6c61746572616c697a6573207468652068656c642062797465732e44556e6465636964696e6754696d656f75741010a0f1040008550120546865206e756d626572206f6620626c6f636b73206166746572207375626d697373696f6e20746861742061207265666572656e64756d206d75737420626567696e206265696e6720646563696465642062792ee4204f6e63652074686973207061737365732c207468656e20616e796f6e65206d61792063616e63656c20746865207265666572656e64756d2e34416c61726d496e74657276616c1010010000000c5d01205175616e74697a6174696f6e206c6576656c20666f7220746865207265666572656e64756d2077616b657570207363686564756c65722e204120686967686572206e756d6265722077696c6c20726573756c7420696e5d012066657765722073746f726167652072656164732f777269746573206e656564656420666f7220736d616c6c657220766f746572732c2062757420616c736f20726573756c7420696e2064656c61797320746f207468655501206175746f6d61746963207265666572656e64756d20737461747573206368616e6765732e204578706c6963697420736572766963696e6720696e737472756374696f6e732061726520756e61666665637465642e18547261636b73d502d50208000064746563685f636f6c6c6563746976655f6d656d6265727300000100000000a0724e18090000000000000000000058020000201c0000201c0000201c00000000ca9a3b80dc5b2480dc5b240000ca9a3b0046c3230046c323010064666173745f75706772616465000000000000000000000000000100000000a0724e18090000000000000000000032000000201c000032000000320000000000ca9a3b0008af2f0008af2f0000ca9a3b0008af2f0008af2f0c482041206c697374206f6620747261636b732e005d01204e6f74653a2069662074686520747261636b73206172652064796e616d69632c207468652076616c756520696e2074686520737461746963206d65746164617461206d6967687420626520696e61636375726174652e01f1020e38547265617375727950616c6c65740138547265617375727950616c6c6574043c54726561737572794163636f756e74000000040004c020546865207472656173757279206163636f756e74207468617420686f6c64732074726561737572792066756e64732e0161010181010001f5020f204d756c746973696701204d756c746973696708244d756c7469736967730001040200f902040004c0204d756c7469736967732073746f7265642062792074686569722064657465726d696e697374696320616464726573732450726f706f73616c7300010802050d031103040004e02050726f706f73616c7320696e646578656420627920286d756c74697369675f616464726573732c2070726f706f73616c5f6e6f6e63652901650101890128284d61785369676e65727310106400000004c0204d6178696d756d206e756d626572206f66207369676e65727320616c6c6f77656420696e2061206d756c7469736967684d6178546f74616c50726f706f73616c73496e53746f726167651010c80000000cd4204d6178696d756d206e756d626572206f662070726f706f73616c7320696e2073746f7261676520706572206d756c74697369672e1901204f6e6c792041637469766520616e6420417070726f7665642070726f706f73616c73206172652073746f7265643b20657865637574656420616e642063616e63656c6c656445012070726f706f73616c73206172652072656d6f76656420696d6d6564696174656c792e2054686973206c696d69742070726576656e747320756e626f756e6465642073746f726167652067726f7774682e2c4d617843616c6c53697a651010002800000480204d6178696d756d2073697a65206f6620616e20656e636f6465642063616c6c2c4d756c746973696746656518400070c9b28b000000000000000000000008f820466565206368617267656420666f72206372656174696e672061206d756c746973696720286e6f6e2d726566756e6461626c652c206275726e6564292ec820546869732070726576656e7473207370616d206372656174696f6e206f66206d756c7469736967206163636f756e74732e3c50726f706f73616c4465706f73697418400010a5d4e8000000000000000000000004f8204465706f736974207265717569726564207065722070726f706f73616c202872657475726e6564206f6e2065786563757465206f722063616e63656c292c50726f706f73616c46656518400010a5d4e8000000000000000000000004090120466565206368617267656420666f72206372656174696e6720612070726f706f73616c20286e6f6e2d726566756e6461626c652c207061696420616c7761797329405369676e657253746570466163746f72910210102700001011012050657263656e7461676520696e63726561736520696e2050726f706f73616c46656520666f722065616368207369676e657220696e20746865206d756c74697369672e004d0120466f726d756c613a206046696e616c466565203d2050726f706f73616c466565202b202850726f706f73616c466565202a205369676e6572436f756e74202a205369676e657253746570466163746f7229606501204578616d706c653a204966204665653d3130302c205369676e6572733d352c20466163746f723d31252c207468656e204578747261203d20313030202a2035202a20302e3031203d20352e20546f74616c203d203130352e2050616c6c6574496419032070792f6d6c74736704b02050616c6c657420494420666f722067656e65726174696e67206d756c746973696720616464726573736573444d61784578706972794475726174696f6e1010c0890100184501204d6178696d756d206475726174696f6e2028696e20626c6f636b7329207468617420612070726f706f73616c2063616e2062652073657420746f2065787069726520696e20746865206675747572652e2d0120546869732070726576656e74732070726f706f73616c732066726f6d206265696e67206372656174656420776974682065787472656d656c7920666172206578706972792064617465730501207468617420776f756c64206c6f636b206465706f7369747320616e6420626c6f61742073746f7261676520666f7220657874656e64656420706572696f64732e00f0204578616d706c653a2049662073657420746f203130305f30303020626c6f636b7320287e32207765656b732061742031327320626c6f636b73292cfc20612070726f706f73616c206372656174656420617420626c6f636b20313030302063616e6e6f74206861766520657870697279203e203130315f3030302e484d6178496e6e657243616c6c5765696768742828070010a5d4e80200a000201901204d6178696d756d2077656967687420616c6c6f77656420666f7220696e6e65722063616c6c73206578656375746564207468726f75676820746865206d756c74697369672e002901205468697320626f756e6420656e7375726573207468617420746865206065786563757465602065787472696e7369632063616e20736166656c79207265736572766520776569676874210120666f722074686520696e6e65722063616c6c206174207072652d64697370617463682074696d652e2050726f706f73616c7320776974682063616c6c7320657863656564696e67c0207468697320776569676874206c696d6974206172652072656a65637465642061742070726f706f73652074696d652e0041012054686520657865637574652065787472696e73696327732077656967687420616e6e6f746174696f6e2069733a20626f6f6b6b656570696e67202b204d6178496e6e657243616c6c5765696768742e350120546869732067756172616e746565732074686520626c6f636b20776569676874206973206e657665722065786365656465642062792061726269747261727920696e6e65722063616c6c732e011d031320576f726d686f6c650120576f726d686f6c650838557365644e756c6c696669657273010104020420040000345472616e73666572436f756e74010104020030200000000000000000185101205472616e7366657220636f756e742070657220726563697069656e74202d207573656420746f2067656e657261746520756e69717565206c65616620696e646963657320696e20746865205a4b20747269652e004101204b65796564206f6e20746865202a63616e6f6e6963616c2a20726563697069656e7420286561636820382d62797465206c696d622072656475636564206d6f642074686520476f6c64696c6f636b735101207072696d652c206d61746368696e6720746865205a4b206c65616620656e636f64696e6720e2809420736565206063616e6f6e6963616c5f6c6561665f726563697069656e7460292c20736f20746861742061390120726563697069656e7420616e6420697473206e6f6e2d63616e6f6e6963616c206279746520616c6961736573207368617265206f6e6520636f756e742073657175656e636520616e642074776fe02064697374696e6374206465706f736974732063616e206e6576657220636f6d6d697420746f206964656e746963616c206c65617665732e017101018d0110384d696e74696e674163636f756e7400800101010101010101010101010101010101010101010101010101010101010101045901204163636f756e74204944207573656420617320746865202266726f6d22206163636f756e74207768656e206372656174696e67207472616e736665722070726f6f667320666f72206d696e74656420746f6b656e7340566f6c756d654665655261746542707310100400000008e420566f6c756d6520666565207261746520696e20626173697320706f696e747320283120626173697320706f696e74203d20302e303125292edc2054686973206d757374206d6174636820746865206665652072617465207573656420696e2070726f6f662067656e65726174696f6e2e48566f6c756d65466565734275726e5261746591021020a107000859012050726f706f7274696f6e206f6620766f6c756d65206665657320746f206275726e20286e6f74206d696e74292e205468652072656d61696e64657220676f657320746f2074686520626c6f636b20617574686f722e0d01204578616d706c653a205065726d696c6c3a3a66726f6d5f70657263656e7428353029206d65616e7320353025206275726e65642c2035302520746f206d696e65722e60566f6c756d654665657341676772656761746f725261746591021020a107000c350120466f72207075626c69632d62617463682070726f6f66732c207468652070726f706f7274696f6e206f6620746865206275726e206275636b6574207265646972656374656420746f207468651d012061676772656761746f7220696e7374656164206f66206265696e672064657374726f7965642e20546865206d696e6572277320736861726520697320756e6368616e6765642e5d01204578616d706c653a205065726d696c6c3a3a66726f6d5f70657263656e7428353029206d65616e732068616c6620746865206275726e20706f7274696f6e20676f657320746f207468652061676772656761746f722e01210314185a6b5472656501185a6b5472656518184c6561766573000104063025030400046c204c65616620646174612073746f72656420627920696e6465782e144e6f6465730001040629030404000cb420496e7465726e616c2074726565206e6f6465733a20286c6576656c2c20696e64657829202d3e20686173682ec4204c6576656c203020697320756e7573656420286c65617665732061726520686173686564206f6e2d64656d616e64292ea0204c6576656c20312b20636f6e7461696e7320696e7465726e616c206e6f6465206861736865732e244c656166436f756e740100302000000000000000000478204e756d626572206f66206c656176657320696e2074686520747265652e14446570746801000804000405012043757272656e74206465707468206f66207468652074726565202830203d20656d7074792c2031203d20757020746f2034206c65617665732c206574632e292e10526f6f74010004800000000000000000000000000000000000000000000000000000000000000000147c2043757272656e7420726f6f742068617368206f662074686520747265652e00190120436f766572732065786163746c792074686520666972737420604c656166436f756e74202d20556e70726f6365737365644c656176657360206c65617665733a20726f6f742901207265636f6d7075746174696f6e2069732062617463686564206f6e63652070657220626c6f636b20696e20606f6e5f66696e616c697a65602c20736f20647572696e6720626c6f636b010120657865637574696f6e20746869732069732074686520726f6f74206173206f662074686520656e64206f66207468652070726576696f757320626c6f636b2e44556e70726f6365737365644c6561766573010030200000000000000000081901204e756d626572206f6620747261696c696e67206c656176657320617070656e646564207468697320626c6f636b20627574206e6f742079657420666f6c64656420696e746fec20604e6f646573602f60526f6f74602e20416c7761797320647261696e6564206261636b20746f203020627920606f6e5f66696e616c697a65602e0001990100012d03151c56657374696e67011c56657374696e6708384e6578745363686564756c654964010030200000000000000000040501204e657874207363686564756c6520696420746f2061737369676e2e20496473206172652073657175656e7469616c20616e64206e65766572207265757365642e245363686564756c657300010405303103040004410120416c6c2076657374696e67207363686564756c65732062792069642e20412062656e6566696369617279206d61792061707065617220696e20616e79206e756d626572206f6620656e74726965732e017501019d01102050616c6c657449641903207176657374696e67049420446572697665732074686520706f74277320736f7665726569676e206163636f756e742e345061796f75745175616e74756d184000e40b5402000000000000000000000010350120576f726d686f6c65206c65616620616d6f756e74207175616e74756d2e205a4b2d74726565206c656176657320636f6d6d69742060616d6f756e74202f207175616e74756d602c20736f20612901207061796f75742062656c6f77206f6e65207175616e74756d20776f756c64206372656174652061207a65726f2d76616c7565206c6561663a2066756e6473206d6f76656420746f20612d01206b65796c6573732062656e656669636961727920776f756c642062652069727265636f76657261626c652e204576657279207363686564756c6520746f74616c206d75737420626520610901206d756c7469706c65206f6620746869732c20616e64206576657279207061796f757420697320726f756e64656420646f776e20746f2061206d756c7469706c652e344d696e696d756d5061796f757418400010a5d4e80000000000000000000000082d0120536d616c6c6573742062656e6566696369617279207061796f75742e204d757374206265207175616e74756d2d616c69676e65642c206174206c656173742074776f207175616e74612ca420616e64206c6172676572207468616e20746865206578697374656e7469616c206465706f7369742e404d696e436c61696d496e74657276616c3020005c260500000000042101204d696e696d756d20656c6170736564206d696c6c697365636f6e6473206265747765656e207375636365737366756c20636c61696d73206f6e206f6e65207363686564756c652e013903161c4f726967696e730000000000173d03043048436865636b4e6f6e5a65726f53656e6465725903c840436865636b5370656356657273696f6e5d031038436865636b547856657273696f6e61031030436865636b47656e6573697365033438436865636b4d6f7274616c69747969033428436865636b4e6f6e63657103c82c436865636b5765696768747503c87852657665727369626c655472616e73616374696f6e457874656e73696f6e7903c878576f726d686f6c6550726f6f665265636f72646572457874656e73696f6e7d03c8604368617267655472616e73616374696f6e5061796d656e748103c844436865636b4d65746164617461486173688503c0345765696768745265636c61696d8d03c89103 \ No newline at end of file diff --git a/packages/quantus-codec/tsconfig.build.json b/packages/quantus-codec/tsconfig.build.json new file mode 100644 index 00000000..44c4904c --- /dev/null +++ b/packages/quantus-codec/tsconfig.build.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "baseUrl": "..", + "composite": false, + "declaration": true, + "outDir": "./build", + "rootDir": "./src", + "emitDeclarationOnly": false + }, + "exclude": [ + "**/*.spec.ts" + ], + "include": [ + "src/**/*.ts" + ], + "references": [] +} diff --git a/scripts/build-quantus-js.sh b/scripts/build-quantus-js.sh index c909dc31..58a8642c 100755 --- a/scripts/build-quantus-js.sh +++ b/scripts/build-quantus-js.sh @@ -21,10 +21,11 @@ set -e -PKG=packages/quantus-crypto -CRATE=quantus_crypto +NAME=${1:-quantus-crypto} +PKG=packages/$NAME +CRATE=$(echo "$NAME" | tr '-' '_') -echo "*** Building @quantus/crypto" +echo "*** Building $NAME" rm -rf $PKG/build-tsc yarn polkadot-exec-tsc --outDir $PKG/build-tsc --project $PKG/tsconfig.build.json diff --git a/scripts/build-quantus.sh b/scripts/build-quantus.sh index 4e0120d9..daa6c097 100755 --- a/scripts/build-quantus.sh +++ b/scripts/build-quantus.sh @@ -14,8 +14,12 @@ set -e -PKG=quantus-crypto -CRATE=quantus_crypto +# Which package to build. Two now — quantus-crypto and quantus-codec — built +# the same way from the same toolchain, so the script takes the name rather than +# being copied. `quantus_codec` is the crate name for `quantus-codec`: cargo +# wants underscores, npm wants hyphens. +PKG=${1:-quantus-crypto} +CRATE=$(echo "$PKG" | tr '-' '_') BINDGEN_VER=0.2.128 WASM=packages/$PKG/build-wasm/${CRATE}_bg.wasm @@ -53,7 +57,7 @@ echo "*** Optimising WASM output" ./binaryen-quantus/bin/wasm-opt $WASM -Oz -o $OPT # Must come before packing: tsc clears build/, which is where bytes.js lands. -./scripts/build-quantus-js.sh +./scripts/build-quantus-js.sh "$PKG" echo "*** Packing WASM into baseX" PKG_NAME=$PKG CRATE_NAME=$CRATE node ./scripts/pack-quantus-base.mjs