From 43b5e506e4f24fc07904a7adc7362f3f7c982f46 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 29 Jul 2024 10:13:56 +0200 Subject: [PATCH 001/157] Prepare to use Orchard ZSA --- Cargo.lock | 344 +++++++++++++++++++++++++++++++++++------ zebra-chain/Cargo.toml | 18 ++- 2 files changed, 309 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea09e646716..0e3ac5e59dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,6 +337,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.11.0" @@ -1035,6 +1041,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -1180,6 +1198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -1220,6 +1239,20 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "ed25519" version = "2.2.3" @@ -1273,6 +1306,25 @@ dependencies = [ "void", ] +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -1298,6 +1350,14 @@ dependencies = [ "regex", ] +[[package]] +name = "equihash" +version = "0.2.0" +dependencies = [ + "blake2b_simd", + "byteorder", +] + [[package]] name = "equihash" version = "0.2.0" @@ -1334,6 +1394,13 @@ dependencies = [ "once_cell", ] +[[package]] +name = "f4jumble" +version = "0.1.0" +dependencies = [ + "blake2b_simd", +] + [[package]] name = "f4jumble" version = "0.1.0" @@ -1548,6 +1615,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1664,11 +1732,10 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" dependencies = [ - "cfg-if 1.0.0", "crunchy", ] @@ -1682,7 +1749,24 @@ dependencies = [ "bitvec", "ff", "group", - "halo2_proofs", + "halo2_proofs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "pasta_curves", + "rand 0.8.5", + "subtle", + "uint", +] + +[[package]] +name = "halo2_gadgets" +version = "0.3.0" +source = "git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11#7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" +dependencies = [ + "arrayvec", + "bitvec", + "ff", + "group", + "halo2_proofs 0.3.0 (git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11)", "lazy_static", "pasta_curves", "rand 0.8.5", @@ -1712,6 +1796,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "halo2_proofs" +version = "0.3.0" +source = "git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11#7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "halo2_legacy_pdqsort", + "maybe-rayon", + "pasta_curves", + "rand_core 0.6.4", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2086,6 +2185,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb1872810fb725b06b8c153dde9e86f3ec26747b9b60096da7a869883b549cbe" dependencies = [ "either", + "proptest", + "rand 0.8.5", + "rand_core 0.6.4", ] [[package]] @@ -2340,6 +2442,20 @@ dependencies = [ "subtle", ] +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + [[package]] name = "known-folders" version = "1.1.0" @@ -2757,6 +2873,36 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "orchard" +version = "0.8.0" +dependencies = [ + "aes", + "bitvec", + "blake2b_simd", + "ff", + "fpe", + "group", + "half", + "halo2_gadgets 0.3.0 (git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11)", + "halo2_proofs 0.3.0 (git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11)", + "hex", + "incrementalmerkletree", + "k256", + "lazy_static", + "memuse", + "nonempty", + "pasta_curves", + "rand 0.8.5", + "reddsa", + "serde", + "subtle", + "tracing", + "zcash_note_encryption 0.4.0 (git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1)", + "zcash_spec", + "zip32", +] + [[package]] name = "orchard" version = "0.8.0" @@ -2769,8 +2915,8 @@ dependencies = [ "ff", "fpe", "group", - "halo2_gadgets", - "halo2_proofs", + "halo2_gadgets 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "halo2_proofs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex", "incrementalmerkletree", "lazy_static", @@ -2782,7 +2928,7 @@ dependencies = [ "serde", "subtle", "tracing", - "zcash_note_encryption", + "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_spec", "zip32", ] @@ -3591,6 +3737,16 @@ dependencies = [ "winreg", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "rgb" version = "0.8.37" @@ -3809,7 +3965,7 @@ dependencies = [ "redjubjub", "subtle", "tracing", - "zcash_note_encryption", + "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_spec", "zip32", ] @@ -3830,6 +3986,20 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "secp256k1" version = "0.26.0" @@ -4149,6 +4319,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ + "digest", "rand_core 0.6.4", ] @@ -5612,6 +5783,17 @@ version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" +[[package]] +name = "zcash_address" +version = "0.3.2" +dependencies = [ + "bech32", + "bs58", + "f4jumble 0.1.0", + "zcash_encoding 0.2.0", + "zcash_protocol 0.1.1", +] + [[package]] name = "zcash_address" version = "0.3.2" @@ -5620,9 +5802,9 @@ checksum = "827c17a1f7e3a69f0d44e991ff610c7a842228afdc9dc2325ffdd1a67fee01e9" dependencies = [ "bech32", "bs58", - "f4jumble", - "zcash_encoding", - "zcash_protocol", + "f4jumble 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -5655,15 +5837,23 @@ dependencies = [ "tonic-build 0.10.2", "tracing", "which", - "zcash_address", - "zcash_encoding", + "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_keys", - "zcash_note_encryption", - "zcash_primitives", - "zcash_protocol", + "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_primitives 0.15.1", + "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "zip32", ] +[[package]] +name = "zcash_encoding" +version = "0.2.0" +dependencies = [ + "byteorder", + "nonempty", +] + [[package]] name = "zcash_encoding" version = "0.2.0" @@ -5704,10 +5894,10 @@ dependencies = [ "secrecy", "subtle", "tracing", - "zcash_address", - "zcash_encoding", - "zcash_primitives", - "zcash_protocol", + "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_primitives 0.15.1", + "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "zip32", ] @@ -5724,18 +5914,28 @@ dependencies = [ "subtle", ] +[[package]] +name = "zcash_note_encryption" +version = "0.4.0" +source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#b8bd2a186fc04ec4f55b2db44df7374f03ab5725" +dependencies = [ + "chacha20", + "chacha20poly1305", + "cipher", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "zcash_primitives" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ccee58d0f9e8da312a999a4c0cd3d001ff3b37af6fb1318c89e6a3076f4da" +version = "0.15.0" dependencies = [ "aes", "bip0039", "blake2b_simd", "byteorder", "document-features", - "equihash", + "equihash 0.2.0", "ff", "fpe", "group", @@ -5745,7 +5945,7 @@ dependencies = [ "jubjub", "memuse", "nonempty", - "orchard", + "orchard 0.8.0", "rand 0.8.5", "rand_core 0.6.4", "redjubjub", @@ -5755,10 +5955,46 @@ dependencies = [ "sha2", "subtle", "tracing", - "zcash_address", - "zcash_encoding", - "zcash_note_encryption", - "zcash_protocol", + "zcash_address 0.3.2", + "zcash_encoding 0.2.0", + "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_protocol 0.1.1", + "zcash_spec", + "zip32", +] + +[[package]] +name = "zcash_primitives" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ccee58d0f9e8da312a999a4c0cd3d001ff3b37af6fb1318c89e6a3076f4da" +dependencies = [ + "aes", + "bip0039", + "blake2b_simd", + "byteorder", + "document-features", + "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ff", + "fpe", + "group", + "hex", + "incrementalmerkletree", + "jubjub", + "memuse", + "nonempty", + "orchard 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.8.5", + "rand_core 0.6.4", + "redjubjub", + "sapling-crypto", + "sha2", + "subtle", + "tracing", + "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_spec", "zip32", ] @@ -5783,7 +6019,17 @@ dependencies = [ "sapling-crypto", "tracing", "xdg", - "zcash_primitives", + "zcash_primitives 0.15.1", +] + +[[package]] +name = "zcash_protocol" +version = "0.1.1" +dependencies = [ + "document-features", + "incrementalmerkletree", + "memuse", + "proptest", ] [[package]] @@ -5831,10 +6077,10 @@ dependencies = [ "color-eyre", "criterion", "ed25519-zebra", - "equihash", + "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures", "group", - "halo2_proofs", + "halo2_proofs 0.3.0 (git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11)", "hex", "humantime", "incrementalmerkletree", @@ -5842,7 +6088,7 @@ dependencies = [ "jubjub", "lazy_static", "num-integer", - "orchard", + "orchard 0.8.0", "primitive-types", "proptest", "proptest-derive", @@ -5868,13 +6114,13 @@ dependencies = [ "tracing", "uint", "x25519-dalek", - "zcash_address", + "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_client_backend", - "zcash_encoding", + "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_history", - "zcash_note_encryption", - "zcash_primitives", - "zcash_protocol", + "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_primitives 0.15.0", + "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "zebra-test", ] @@ -5889,7 +6135,7 @@ dependencies = [ "color-eyre", "futures", "futures-util", - "halo2_proofs", + "halo2_proofs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex", "howudoin", "jubjub", @@ -5897,7 +6143,7 @@ dependencies = [ "metrics", "num-integer", "once_cell", - "orchard", + "orchard 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "proptest", "proptest-derive", "rand 0.8.5", @@ -5939,7 +6185,7 @@ dependencies = [ "tonic-build 0.11.0", "tonic-reflection", "tower", - "zcash_primitives", + "zcash_primitives 0.15.1", "zebra-chain", "zebra-node-services", "zebra-state", @@ -6021,8 +6267,8 @@ dependencies = [ "tokio", "tower", "tracing", - "zcash_address", - "zcash_primitives", + "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_primitives 0.15.1", "zebra-chain", "zebra-consensus", "zebra-network", @@ -6055,11 +6301,11 @@ dependencies = [ "tokio", "tower", "tracing", - "zcash_address", + "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "zcash_client_backend", "zcash_keys", - "zcash_note_encryption", - "zcash_primitives", + "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_primitives 0.15.1", "zebra-chain", "zebra-grpc", "zebra-node-services", @@ -6089,7 +6335,7 @@ dependencies = [ "dirs", "elasticsearch", "futures", - "halo2_proofs", + "halo2_proofs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex", "hex-literal", "howudoin", @@ -6175,8 +6421,8 @@ dependencies = [ "tracing-error", "tracing-subscriber", "zcash_client_backend", - "zcash_primitives", - "zcash_protocol", + "zcash_primitives 0.15.1", + "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "zebra-chain", "zebra-node-services", "zebra-rpc", diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 9b4160b5c69..bb97fc415f9 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -92,13 +92,18 @@ uint = "0.9.5" x25519-dalek = { version = "2.0.1", features = ["serde"] } # ECC deps -halo2 = { package = "halo2_proofs", version = "0.3.0" } -orchard = "0.8.0" +#halo2 = { package = "halo2_proofs", version = "0.3.0" } +halo2 = { package = "halo2_proofs", git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11", version = "0.3.0" } +#orchard = { version = "0.8.0", default-features = false, git = "https://github.com/QED-it/orchard", branch = "zsa1" } +orchard = { version = "0.8.0", default-features = false, path = "../../orchard", features = ["multicore"] } zcash_encoding = "0.2.0" zcash_history = "0.4.0" zcash_note_encryption = "0.4.0" -zcash_primitives = { version = "0.15.0", features = ["transparent-inputs"] } -sapling = { package = "sapling-crypto", version = "0.1" } +#zcash_primitives = { version = "0.15.0", features = ["transparent-inputs"] } +#zcash_primitives = { version = "0.15", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd1", features = ["transparent-inputs"] } +zcash_primitives = { version = "0.15", path = "../../librustzcash/zcash_primitives", features = ["transparent-inputs"] } +#sapling = { package = "sapling-crypto", version = "0.1" } +sapling = { package = "sapling-crypto", version = "0.1.3" } zcash_protocol = { version = "0.1.1" } zcash_address = { version = "0.3.2" } @@ -176,3 +181,8 @@ required-features = ["bench"] [[bench]] name = "redpallas" harness = false + +[patch.crates-io] +#zcash_primitives = { version = "0.15", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd1" } +zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "fix-sapling-constants" } +sapling = { package = "sapling-crypto", version = "0.1.3", git = "https://github.com/QED-it/sapling-crypto", branch = "orchard-backward-compatibility" } From 95dce56ab33ceabd6960c78acd005d2c34f366f6 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 11 Aug 2024 22:25:01 +0200 Subject: [PATCH 002/157] Switch Zebra to QED-it ZSA-compatible crates but maintain the original Orchard support only, without supporting and enabling ZSA features. --- Cargo.lock | 812 ++++++++---------- Cargo.toml | 12 + zebra-chain/Cargo.toml | 18 +- zebra-chain/src/orchard/note/ciphertexts.rs | 2 + zebra-consensus/src/primitives/halo2.rs | 17 +- zebra-consensus/src/primitives/halo2/tests.rs | 24 +- 6 files changed, 405 insertions(+), 480 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e3ac5e59dc..4ddf06cb4b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,7 +12,7 @@ dependencies = [ "arc-swap", "backtrace", "canonical-path", - "clap 4.5.7", + "clap 4.5.13", "color-eyre", "fs-err", "once_cell", @@ -137,9 +137,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -152,33 +152,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -198,9 +198,9 @@ checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" @@ -210,9 +210,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-compression" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ "flate2", "futures-core", @@ -240,18 +240,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -290,7 +290,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "itoa", "matchit", "memchr", @@ -428,7 +428,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.68", + "syn 2.0.72", "which", ] @@ -560,9 +560,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "serde", @@ -582,9 +582,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.16.1" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" [[package]] name = "byteorder" @@ -594,9 +594,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "bzip2-sys" @@ -664,13 +664,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.100" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" dependencies = [ "jobserver", "libc", - "once_cell", ] [[package]] @@ -728,7 +727,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -797,9 +796,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" dependencies = [ "clap_builder", "clap_derive", @@ -807,9 +806,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" dependencies = [ "anstream", "anstyle", @@ -819,21 +818,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "color-eyre" @@ -865,9 +864,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "console" @@ -974,7 +973,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.7", + "clap 4.5.13", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -1088,7 +1087,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -1103,12 +1102,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.9", - "darling_macro 0.20.9", + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -1127,16 +1126,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -1152,13 +1151,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.9", + "darling_core 0.20.10", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -1226,9 +1225,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" dependencies = [ "litrs", ] @@ -1282,9 +1281,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elasticsearch" @@ -1353,6 +1352,8 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" dependencies = [ "blake2b_simd", "byteorder", @@ -1361,8 +1362,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab579d7cf78477773b03e80bc2f89702ef02d7112c711d54ca93dcdce68533d5" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ "blake2b_simd", "byteorder", @@ -1397,15 +1397,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -dependencies = [ - "blake2b_simd", -] - -[[package]] -name = "f4jumble" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a83e8d7fd0c526af4aad893b7c9fe41e2699ed8a776a6c74aecdeafe05afc75" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ "blake2b_simd", ] @@ -1453,9 +1445,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -1574,7 +1566,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -1650,9 +1642,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "git2" -version = "0.18.3" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" +checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ "bitflags 2.6.0", "libc", @@ -1704,7 +1696,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util 0.7.11", @@ -1723,7 +1715,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util 0.7.11", @@ -1739,24 +1731,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "halo2_gadgets" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126a150072b0c38c7b573fe3eaf0af944a7fed09e154071bf2436d3f016f7230" -dependencies = [ - "arrayvec", - "bitvec", - "ff", - "group", - "halo2_proofs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static", - "pasta_curves", - "rand 0.8.5", - "subtle", - "uint", -] - [[package]] name = "halo2_gadgets" version = "0.3.0" @@ -1766,7 +1740,7 @@ dependencies = [ "bitvec", "ff", "group", - "halo2_proofs 0.3.0 (git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11)", + "halo2_proofs", "lazy_static", "pasta_curves", "rand 0.8.5", @@ -1780,22 +1754,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" -[[package]] -name = "halo2_proofs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b867a8d9bbb85fca76fff60652b5cd19b853a1c4d0665cb89bee68b18d2caf0" -dependencies = [ - "blake2b_simd", - "ff", - "group", - "halo2_legacy_pdqsort", - "maybe-rayon", - "pasta_curves", - "rand_core 0.6.4", - "tracing", -] - [[package]] name = "halo2_proofs" version = "0.3.0" @@ -1973,9 +1931,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.1.0", @@ -1990,7 +1948,7 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -2030,9 +1988,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.29" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -2054,16 +2012,16 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", "h2 0.4.5", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -2081,7 +2039,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.29", + "hyper 0.14.30", "rustls", "tokio", "tokio-rustls", @@ -2093,7 +2051,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.29", + "hyper 0.14.30", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -2101,16 +2059,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", "socket2", "tokio", @@ -2185,9 +2143,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb1872810fb725b06b8c153dde9e86f3ec26747b9b60096da7a869883b549cbe" dependencies = [ "either", - "proptest", - "rand 0.8.5", - "rand_core 0.6.4", ] [[package]] @@ -2209,9 +2164,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -2233,9 +2188,9 @@ dependencies = [ [[package]] name = "inferno" -version = "0.11.19" +version = "0.11.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" dependencies = [ "ahash", "is-terminal", @@ -2301,9 +2256,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -2340,9 +2295,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] @@ -2401,7 +2356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" dependencies = [ "futures", - "hyper 0.14.29", + "hyper 0.14.30", "jsonrpc-core", "jsonrpc-server-utils", "log", @@ -2488,9 +2443,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libgit2-sys" -version = "0.16.2+1.7.2" +version = "0.17.0+1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" +checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" dependencies = [ "cc", "libc", @@ -2500,12 +2455,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2581,15 +2536,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lz4-sys" -version = "1.9.5" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9764018d143cc854c9f17f0b907de70f14393b1f502da6375dce70f00514eb3" +checksum = "109de74d5d2353660401699a4174a4ff23fcc649caf553df71933c7fb45ad868" dependencies = [ "cc", "libc", @@ -2653,9 +2608,9 @@ checksum = "5d58e362dc7206e9456ddbcdbd53c71ba441020e62104703075a69151e38d85f" dependencies = [ "base64 0.22.1", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", - "indexmap 2.2.6", + "indexmap 2.3.0", "ipnet", "metrics", "metrics-util", @@ -2703,13 +2658,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ + "hermit-abi 0.3.9", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2772,9 +2728,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -2857,9 +2813,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "opaque-debug" @@ -2876,6 +2832,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.8.0" +source = "git+https://github.com/QED-it/orchard?branch=zsa1#6e6112c80eb751a93c0fd1d881e9ca69887e1154" dependencies = [ "aes", "bitvec", @@ -2884,8 +2841,8 @@ dependencies = [ "fpe", "group", "half", - "halo2_gadgets 0.3.0 (git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11)", - "halo2_proofs 0.3.0 (git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11)", + "halo2_gadgets", + "halo2_proofs", "hex", "incrementalmerkletree", "k256", @@ -2898,37 +2855,7 @@ dependencies = [ "serde", "subtle", "tracing", - "zcash_note_encryption 0.4.0 (git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1)", - "zcash_spec", - "zip32", -] - -[[package]] -name = "orchard" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0462569fc8b0d1b158e4d640571867a4e4319225ebee2ab6647e60c70af19ae3" -dependencies = [ - "aes", - "bitvec", - "blake2b_simd", - "ff", - "fpe", - "group", - "halo2_gadgets 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "halo2_proofs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hex", - "incrementalmerkletree", - "lazy_static", - "memuse", - "nonempty", - "pasta_curves", - "rand 0.8.5", - "reddsa", - "serde", - "subtle", - "tracing", - "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_note_encryption", "zcash_spec", "zip32", ] @@ -3050,9 +2977,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.5.2", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3099,9 +3026,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -3110,9 +3037,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -3120,22 +3047,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] name = "pest_meta" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -3149,7 +3076,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.6", + "indexmap 2.3.0", ] [[package]] @@ -3169,7 +3096,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -3241,9 +3168,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "powerfmt" @@ -3253,9 +3180,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" @@ -3264,7 +3194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -3387,7 +3317,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.68", + "syn 2.0.72", "tempfile", ] @@ -3401,7 +3331,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -3563,9 +3493,9 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.0.2" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" +checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" dependencies = [ "bitflags 2.6.0", ] @@ -3632,9 +3562,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags 2.6.0", ] @@ -3652,9 +3582,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -3709,7 +3639,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-rustls", "ipnet", "js-sys", @@ -3749,9 +3679,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "e12bc8d2f72df26a5d3178022df33720fbede0d31d82c7291662eff89836994d" dependencies = [ "bytemuck", ] @@ -3941,8 +3871,7 @@ dependencies = [ [[package]] name = "sapling-crypto" version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f4270033afcb0c74c5c7d59c73cfd1040367f67f224fe7ed9a919ae618f1b7" +source = "git+https://github.com/QED-it/sapling-crypto?branch=zsa1#e19f4d916360842becf2842bfd9b27228e66fa81" dependencies = [ "aes", "bellman", @@ -3965,7 +3894,7 @@ dependencies = [ "redjubjub", "subtle", "tracing", - "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_note_encryption", "zcash_spec", "zip32", ] @@ -4141,9 +4070,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -4159,32 +4088,33 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] name = "serde_json" -version = "1.0.118" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -4213,19 +4143,19 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_derive", "serde_json", - "serde_with_macros 3.8.1", + "serde_with_macros 3.9.0", "time", ] @@ -4243,14 +4173,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ - "darling 0.20.9", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -4259,7 +4189,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "itoa", "ryu", "serde", @@ -4325,9 +4255,9 @@ dependencies = [ [[package]] name = "similar" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "sketches-ddsketch" @@ -4480,9 +4410,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -4536,12 +4466,13 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if 1.0.0", "fastrand", + "once_cell", "rustix", "windows-sys 0.52.0", ] @@ -4566,22 +4497,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -4653,9 +4584,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -4668,22 +4599,21 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4698,13 +4628,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -4780,21 +4710,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.14", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -4805,22 +4735,22 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "toml_datetime", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", + "winnow 0.6.18", ] [[package]] @@ -4837,7 +4767,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", @@ -4864,7 +4794,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", @@ -4887,7 +4817,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -4900,7 +4830,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -5030,7 +4960,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -5143,7 +5073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -5302,9 +5232,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "serde", ] @@ -5329,9 +5259,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "8.3.1" +version = "8.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" +checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" dependencies = [ "anyhow", "cargo_metadata", @@ -5345,9 +5275,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "void" @@ -5466,7 +5396,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -5500,7 +5430,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5557,11 +5487,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5577,7 +5507,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -5586,7 +5516,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -5604,7 +5534,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -5624,18 +5563,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -5646,9 +5585,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -5658,9 +5597,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -5670,15 +5609,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -5688,9 +5627,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -5700,9 +5639,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -5712,9 +5651,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -5724,9 +5663,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -5739,9 +5678,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -5786,32 +5725,19 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" version = "0.3.2" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ "bech32", "bs58", - "f4jumble 0.1.0", - "zcash_encoding 0.2.0", - "zcash_protocol 0.1.1", -] - -[[package]] -name = "zcash_address" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "827c17a1f7e3a69f0d44e991ff610c7a842228afdc9dc2325ffdd1a67fee01e9" -dependencies = [ - "bech32", - "bs58", - "f4jumble 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "f4jumble", + "zcash_encoding", + "zcash_protocol", ] [[package]] name = "zcash_client_backend" version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0364e69c446fcf96a1f73f342c6c3fa697ea65ae7eeeae7d76ca847b9c442e40" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ "base64 0.21.7", "bech32", @@ -5837,28 +5763,20 @@ dependencies = [ "tonic-build 0.10.2", "tracing", "which", - "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_keys", - "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_primitives 0.15.1", - "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", + "zcash_encoding", + "zcash_keys 0.2.0 (git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2)", + "zcash_note_encryption", + "zcash_primitives", + "zcash_protocol", "zip32", + "zip321", ] [[package]] name = "zcash_encoding" version = "0.2.0" -dependencies = [ - "byteorder", - "nonempty", -] - -[[package]] -name = "zcash_encoding" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f03391b81727875efa6ac0661a20883022b6fba92365dc121c48fa9b00c5aac0" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ "byteorder", "nonempty", @@ -5867,8 +5785,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fde17bf53792f9c756b313730da14880257d7661b5bfc69d0571c3a7c11a76d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ "blake2b_simd", "byteorder", @@ -5894,30 +5811,42 @@ dependencies = [ "secrecy", "subtle", "tracing", - "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_primitives 0.15.1", - "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", + "zcash_encoding", + "zcash_primitives", + "zcash_protocol", "zip32", ] [[package]] -name = "zcash_note_encryption" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b4580cd6cee12e44421dac43169be8d23791650816bdb34e6ddfa70ac89c1c5" +name = "zcash_keys" +version = "0.2.0" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ - "chacha20", - "chacha20poly1305", - "cipher", + "bech32", + "blake2b_simd", + "bls12_381", + "bs58", + "document-features", + "group", + "memuse", + "nonempty", "rand_core 0.6.4", + "sapling-crypto", + "secrecy", "subtle", + "tracing", + "zcash_address", + "zcash_encoding", + "zcash_primitives", + "zcash_protocol", + "zip32", ] [[package]] name = "zcash_note_encryption" version = "0.4.0" -source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#b8bd2a186fc04ec4f55b2db44df7374f03ab5725" +source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#58384553aab76b2ee6d6eb328cf2187fa824ec9a" dependencies = [ "chacha20", "chacha20poly1305", @@ -5929,13 +5858,14 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.15.0" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ "aes", "bip0039", "blake2b_simd", "byteorder", "document-features", - "equihash 0.2.0", + "equihash 0.2.0 (git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2)", "ff", "fpe", "group", @@ -5945,7 +5875,7 @@ dependencies = [ "jubjub", "memuse", "nonempty", - "orchard 0.8.0", + "orchard", "rand 0.8.5", "rand_core 0.6.4", "redjubjub", @@ -5955,46 +5885,10 @@ dependencies = [ "sha2", "subtle", "tracing", - "zcash_address 0.3.2", - "zcash_encoding 0.2.0", - "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_protocol 0.1.1", - "zcash_spec", - "zip32", -] - -[[package]] -name = "zcash_primitives" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ccee58d0f9e8da312a999a4c0cd3d001ff3b37af6fb1318c89e6a3076f4da" -dependencies = [ - "aes", - "bip0039", - "blake2b_simd", - "byteorder", - "document-features", - "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ff", - "fpe", - "group", - "hex", - "incrementalmerkletree", - "jubjub", - "memuse", - "nonempty", - "orchard 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.8.5", - "rand_core 0.6.4", - "redjubjub", - "sapling-crypto", - "sha2", - "subtle", - "tracing", - "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", + "zcash_encoding", + "zcash_note_encryption", + "zcash_protocol", "zcash_spec", "zip32", ] @@ -6019,24 +5913,13 @@ dependencies = [ "sapling-crypto", "tracing", "xdg", - "zcash_primitives 0.15.1", + "zcash_primitives", ] [[package]] name = "zcash_protocol" version = "0.1.1" -dependencies = [ - "document-features", - "incrementalmerkletree", - "memuse", - "proptest", -] - -[[package]] -name = "zcash_protocol" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f8189d4a304e8aa3aef3b75e89f3874bb0dc84b1cd623316a84e79e06cddabc" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" dependencies = [ "document-features", "memuse", @@ -6080,7 +5963,7 @@ dependencies = [ "equihash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures", "group", - "halo2_proofs 0.3.0 (git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11)", + "halo2_proofs", "hex", "humantime", "incrementalmerkletree", @@ -6088,7 +5971,7 @@ dependencies = [ "jubjub", "lazy_static", "num-integer", - "orchard 0.8.0", + "orchard", "primitive-types", "proptest", "proptest-derive", @@ -6104,7 +5987,7 @@ dependencies = [ "serde", "serde-big-array", "serde_json", - "serde_with 3.8.1", + "serde_with 3.9.0", "sha2", "spandoc", "static_assertions", @@ -6114,13 +5997,13 @@ dependencies = [ "tracing", "uint", "x25519-dalek", - "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", "zcash_client_backend", - "zcash_encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_encoding", "zcash_history", - "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_primitives 0.15.0", - "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_note_encryption", + "zcash_primitives", + "zcash_protocol", "zebra-test", ] @@ -6135,7 +6018,7 @@ dependencies = [ "color-eyre", "futures", "futures-util", - "halo2_proofs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "halo2_proofs", "hex", "howudoin", "jubjub", @@ -6143,7 +6026,7 @@ dependencies = [ "metrics", "num-integer", "once_cell", - "orchard 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "orchard", "proptest", "proptest-derive", "rand 0.8.5", @@ -6185,7 +6068,7 @@ dependencies = [ "tonic-build 0.11.0", "tonic-reflection", "tower", - "zcash_primitives 0.15.1", + "zcash_primitives", "zebra-chain", "zebra-node-services", "zebra-state", @@ -6205,7 +6088,7 @@ dependencies = [ "hex", "howudoin", "humantime-serde", - "indexmap 2.2.6", + "indexmap 2.3.0", "itertools 0.13.0", "lazy_static", "metrics", @@ -6224,7 +6107,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util 0.7.11", - "toml 0.8.14", + "toml 0.8.19", "tower", "tracing", "tracing-error", @@ -6253,8 +6136,8 @@ dependencies = [ "chrono", "futures", "hex", - "hyper 0.14.29", - "indexmap 2.2.6", + "hyper 0.14.30", + "indexmap 2.3.0", "insta", "jsonrpc-core", "jsonrpc-derive", @@ -6267,8 +6150,8 @@ dependencies = [ "tokio", "tower", "tracing", - "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_primitives 0.15.1", + "zcash_address", + "zcash_primitives", "zebra-chain", "zebra-consensus", "zebra-network", @@ -6288,7 +6171,7 @@ dependencies = [ "ff", "futures", "group", - "indexmap 2.2.6", + "indexmap 2.3.0", "insta", "itertools 0.13.0", "jubjub", @@ -6301,11 +6184,11 @@ dependencies = [ "tokio", "tower", "tracing", - "zcash_address 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_address", "zcash_client_backend", - "zcash_keys", - "zcash_note_encryption 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zcash_primitives 0.15.1", + "zcash_keys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_note_encryption", + "zcash_primitives", "zebra-chain", "zebra-grpc", "zebra-node-services", @@ -6335,13 +6218,13 @@ dependencies = [ "dirs", "elasticsearch", "futures", - "halo2_proofs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "halo2_proofs", "hex", "hex-literal", "howudoin", "human_bytes", "humantime-serde", - "indexmap 2.2.6", + "indexmap 2.3.0", "insta", "itertools 0.13.0", "jubjub", @@ -6378,7 +6261,7 @@ dependencies = [ "futures", "hex", "humantime", - "indexmap 2.2.6", + "indexmap 2.3.0", "insta", "itertools 0.13.0", "lazy_static", @@ -6414,15 +6297,15 @@ dependencies = [ "serde_json", "serde_yaml", "structopt", - "syn 2.0.68", + "syn 2.0.72", "thiserror", "tinyvec", "tokio", "tracing-error", "tracing-subscriber", "zcash_client_backend", - "zcash_primitives 0.15.1", - "zcash_protocol 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_primitives", + "zcash_protocol", "zebra-chain", "zebra-node-services", "zebra-rpc", @@ -6436,7 +6319,7 @@ dependencies = [ "abscissa_core", "atty", "chrono", - "clap 4.5.7", + "clap 4.5.13", "color-eyre", "console-subscriber", "dirs", @@ -6445,8 +6328,8 @@ dependencies = [ "hex-literal", "howudoin", "humantime-serde", - "hyper 0.14.29", - "indexmap 2.2.6", + "hyper 0.14.30", + "indexmap 2.3.0", "indicatif", "inferno", "insta", @@ -6474,7 +6357,7 @@ dependencies = [ "tinyvec", "tokio", "tokio-stream", - "toml 0.8.14", + "toml 0.8.19", "tonic 0.11.0", "tonic-build 0.11.0", "tower", @@ -6501,22 +6384,23 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -6536,7 +6420,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.72", ] [[package]] @@ -6549,3 +6433,15 @@ dependencies = [ "memuse", "subtle", ] + +[[package]] +name = "zip321" +version = "0.0.0" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +dependencies = [ + "base64 0.21.7", + "nom", + "percent-encoding", + "zcash_address", + "zcash_protocol", +] diff --git a/Cargo.toml b/Cargo.toml index 591c0d898e1..e6baf5c7db5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,3 +89,15 @@ panic = "abort" # - add "-flto=thin" to all C/C++ code builds # - see https://doc.rust-lang.org/rustc/linker-plugin-lto.html#cc-code-as-a-dependency-in-rust lto = "thin" + +[patch.crates-io] +halo2_proofs = { version = "0.3.0", git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" } +zcash_note_encryption = { version = "0.4.0", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1" } +sapling-crypto = { version = "0.1.3", git = "https://github.com/QED-it/sapling-crypto", branch = "zsa1" } +orchard = { version = "0.8.0", git = "https://github.com/QED-it/orchard", branch = "zsa1" } +zcash_primitives = { version = "0.15.0", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } +zcash_protocol = { version = "0.1.1", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } +zcash_address = { version = "0.3.2", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } +zcash_encoding = { version = "0.2.0", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } +zcash_history = { version = "0.4.0", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } +zcash_client_backend = { version = "0.12.1", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index bb97fc415f9..9b4160b5c69 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -92,18 +92,13 @@ uint = "0.9.5" x25519-dalek = { version = "2.0.1", features = ["serde"] } # ECC deps -#halo2 = { package = "halo2_proofs", version = "0.3.0" } -halo2 = { package = "halo2_proofs", git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11", version = "0.3.0" } -#orchard = { version = "0.8.0", default-features = false, git = "https://github.com/QED-it/orchard", branch = "zsa1" } -orchard = { version = "0.8.0", default-features = false, path = "../../orchard", features = ["multicore"] } +halo2 = { package = "halo2_proofs", version = "0.3.0" } +orchard = "0.8.0" zcash_encoding = "0.2.0" zcash_history = "0.4.0" zcash_note_encryption = "0.4.0" -#zcash_primitives = { version = "0.15.0", features = ["transparent-inputs"] } -#zcash_primitives = { version = "0.15", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd1", features = ["transparent-inputs"] } -zcash_primitives = { version = "0.15", path = "../../librustzcash/zcash_primitives", features = ["transparent-inputs"] } -#sapling = { package = "sapling-crypto", version = "0.1" } -sapling = { package = "sapling-crypto", version = "0.1.3" } +zcash_primitives = { version = "0.15.0", features = ["transparent-inputs"] } +sapling = { package = "sapling-crypto", version = "0.1" } zcash_protocol = { version = "0.1.1" } zcash_address = { version = "0.3.2" } @@ -181,8 +176,3 @@ required-features = ["bench"] [[bench]] name = "redpallas" harness = false - -[patch.crates-io] -#zcash_primitives = { version = "0.15", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd1" } -zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "fix-sapling-constants" } -sapling = { package = "sapling-crypto", version = "0.1.3", git = "https://github.com/QED-it/sapling-crypto", branch = "orchard-backward-compatibility" } diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index 8f857cf1444..b27ffbc53a1 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -1,5 +1,7 @@ //! Encrypted parts of Orchard notes. +// FIXME: make it a generic and add support for OrchardZSA (encrypted tote size ofr it is not 580!) + use std::{fmt, io}; use serde_big_array::BigArray; diff --git a/zebra-consensus/src/primitives/halo2.rs b/zebra-consensus/src/primitives/halo2.rs index ffc58a5feb8..447d9bbd449 100644 --- a/zebra-consensus/src/primitives/halo2.rs +++ b/zebra-consensus/src/primitives/halo2.rs @@ -10,7 +10,7 @@ use std::{ use futures::{future::BoxFuture, FutureExt}; use once_cell::sync::Lazy; -use orchard::circuit::VerifyingKey; +use orchard::{circuit::VerifyingKey, orchard_flavor::OrchardVanilla}; use rand::{thread_rng, CryptoRng, RngCore}; use thiserror::Error; @@ -75,7 +75,8 @@ pub type ItemVerifyingKey = VerifyingKey; lazy_static::lazy_static! { /// The halo2 proof verifying key. - pub static ref VERIFYING_KEY: ItemVerifyingKey = ItemVerifyingKey::build(); + // FIXME: support OrchardZSA? + pub static ref VERIFYING_KEY: ItemVerifyingKey = ItemVerifyingKey::build::(); } // === TEMPORARY BATCH HALO2 SUBSTITUTE === @@ -143,6 +144,15 @@ impl From<&zebra_chain::orchard::ShieldedData> for Item { .flags .contains(zebra_chain::orchard::Flags::ENABLE_OUTPUTS); + // FIXME: simplify the flags creation - make `Flags::from_parts` method pub? + // FIXME: support OrchardZSA? + let flags = match (enable_spend, enable_output) { + (false, false) => orchard::builder::BundleType::DISABLED.flags(), + (false, true) => orchard::bundle::Flags::SPENDS_DISABLED_WITHOUT_ZSA, + (true, false) => orchard::bundle::Flags::OUTPUTS_DISABLED, + (true, true) => orchard::bundle::Flags::ENABLED_WITHOUT_ZSA, + }; + let instances = shielded_data .actions() .map(|action| { @@ -155,8 +165,7 @@ impl From<&zebra_chain::orchard::ShieldedData> for Item { )) .expect("should be a valid redpallas spendauth verification key"), note::ExtractedNoteCommitment::from_bytes(&action.cm_x.into()).unwrap(), - enable_spend, - enable_output, + flags, ) }) .collect(); diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index e654adcc546..9b5c367e640 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -11,6 +11,8 @@ use orchard::{ bundle::Flags, circuit::ProvingKey, keys::{FullViewingKey, Scope, SpendingKey}, + note::AssetBase, + orchard_flavor::OrchardVanilla, value::NoteValue, Anchor, Bundle, }; @@ -23,9 +25,10 @@ use zebra_chain::{ use crate::primitives::halo2::*; +// FIXME: add support for OrchardZSA (see OrchardVanilla and AssetBase::native() usage below) #[allow(dead_code, clippy::print_stdout)] fn generate_test_vectors() { - let proving_key = ProvingKey::build(); + let proving_key = ProvingKey::build::(); let rng = OsRng; @@ -50,11 +53,17 @@ fn generate_test_vectors() { for _ in 0..num_recipients { builder - .add_output(None, recipient, NoteValue::from_raw(note_value), None) + .add_output( + None, + recipient, + NoteValue::from_raw(note_value), + AssetBase::native(), + None, + ) .unwrap(); } - let bundle: Bundle<_, i64> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, OrchardVanilla> = builder.build(rng).unwrap().unwrap().0; let bundle = bundle .create_proof(&proving_key, rng) @@ -79,7 +88,14 @@ fn generate_test_vectors() { rk: <[u8; 32]>::from(a.rk()).into(), cm_x: pallas::Base::from_repr(a.cmx().into()).unwrap(), ephemeral_key: a.encrypted_note().epk_bytes.try_into().unwrap(), - enc_ciphertext: a.encrypted_note().enc_ciphertext.into(), + // FIXME: support OrchardZSA too, 580 works for OrchardVanilla only! + // FIXME: consider more "type safe" way to do the following conversion + // (now it goes through &[u8]) + enc_ciphertext: <[u8; 580]>::try_from( + a.encrypted_note().enc_ciphertext.as_ref(), + ) + .unwrap() + .into(), out_ciphertext: a.encrypted_note().out_ciphertext.into(), }; zebra_chain::orchard::shielded_data::AuthorizedAction { From 50190a3c3f74566ee0602c9454a476491d15b4b3 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 18 Aug 2024 22:34:58 +0200 Subject: [PATCH 003/157] Introduce Nu7 --- zebra-chain/Cargo.toml | 3 ++- zebra-chain/src/block/commitment.rs | 4 ++-- zebra-chain/src/history_tree.rs | 4 ++-- zebra-chain/src/parameters/network.rs | 2 ++ zebra-chain/src/parameters/network/testnet.rs | 9 +++++++- .../src/parameters/network/tests/vectors.rs | 5 ++-- zebra-chain/src/parameters/network_upgrade.rs | 23 ++++++++++++++++--- zebra-chain/src/primitives/zcash_history.rs | 3 ++- zebra-chain/src/transaction/arbitrary.rs | 2 +- 9 files changed, 42 insertions(+), 13 deletions(-) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index badeb6b699f..10c5ed926cd 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -179,4 +179,5 @@ harness = false [lints.rust] # TODO: Remove this once it's no longer needed for NU6. -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } +# FIXME: TODO: What about NU7? +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6", "nu7"))'] } diff --git a/zebra-chain/src/block/commitment.rs b/zebra-chain/src/block/commitment.rs index 2cb09e75b22..ec4ef7d2616 100644 --- a/zebra-chain/src/block/commitment.rs +++ b/zebra-chain/src/block/commitment.rs @@ -125,7 +125,7 @@ impl Commitment { // NetworkUpgrade::current() returns the latest network upgrade that's activated at the provided height, so // on Regtest for heights above height 0, it could return NU6, and it's possible for the current network upgrade // to be NU6 (or Canopy, or any network upgrade above Heartwood) at the Heartwood activation height. - (Canopy | Nu5 | Nu6, activation_height) + (Canopy | Nu5 | Nu6 | Nu7, activation_height) if height == activation_height && Some(height) == Heartwood.activation_height(network) => { @@ -136,7 +136,7 @@ impl Commitment { } } (Heartwood | Canopy, _) => Ok(ChainHistoryRoot(ChainHistoryMmrRootHash(bytes))), - (Nu5 | Nu6, _) => Ok(ChainHistoryBlockTxAuthCommitment( + (Nu5 | Nu6 | Nu7, _) => Ok(ChainHistoryBlockTxAuthCommitment( ChainHistoryBlockTxAuthCommitmentHash(bytes), )), } diff --git a/zebra-chain/src/history_tree.rs b/zebra-chain/src/history_tree.rs index 91fa3a17628..613bf0616d7 100644 --- a/zebra-chain/src/history_tree.rs +++ b/zebra-chain/src/history_tree.rs @@ -102,7 +102,7 @@ impl NonEmptyHistoryTree { )?; InnerHistoryTree::PreOrchard(tree) } - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => { + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => { let tree = Tree::::new_from_cache( network, network_upgrade, @@ -156,7 +156,7 @@ impl NonEmptyHistoryTree { )?; (InnerHistoryTree::PreOrchard(tree), entry) } - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => { + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => { let (tree, entry) = Tree::::new_from_block( network, block, diff --git a/zebra-chain/src/parameters/network.rs b/zebra-chain/src/parameters/network.rs index 8cec6c16c1e..6b793b4f634 100644 --- a/zebra-chain/src/parameters/network.rs +++ b/zebra-chain/src/parameters/network.rs @@ -136,10 +136,12 @@ impl Network { pub fn new_regtest( nu5_activation_height: Option, nu6_activation_height: Option, + nu7_activation_height: Option, ) -> Self { Self::new_configured_testnet(testnet::Parameters::new_regtest( nu5_activation_height, nu6_activation_height, + nu7_activation_height, )) } diff --git a/zebra-chain/src/parameters/network/testnet.rs b/zebra-chain/src/parameters/network/testnet.rs index 80cb8419c77..53ae14711c1 100644 --- a/zebra-chain/src/parameters/network/testnet.rs +++ b/zebra-chain/src/parameters/network/testnet.rs @@ -194,6 +194,9 @@ pub struct ConfiguredActivationHeights { /// Activation height for `NU6` network upgrade. #[serde(rename = "NU6")] pub nu6: Option, + /// Activation height for `NU7` network upgrade. + #[serde(rename = "NU7")] + pub nu7: Option, } /// Builder for the [`Parameters`] struct. @@ -314,6 +317,7 @@ impl ParametersBuilder { canopy, nu5, nu6, + nu7, }: ConfiguredActivationHeights, ) -> Self { use NetworkUpgrade::*; @@ -332,6 +336,7 @@ impl ParametersBuilder { .chain(canopy.into_iter().map(|h| (h, Canopy))) .chain(nu5.into_iter().map(|h| (h, Nu5))) .chain(nu6.into_iter().map(|h| (h, Nu6))) + .chain(nu7.into_iter().map(|h| (h, Nu7))) .map(|(h, nu)| (h.try_into().expect("activation height must be valid"), nu)) .collect(); @@ -519,6 +524,7 @@ impl Parameters { pub fn new_regtest( nu5_activation_height: Option, nu6_activation_height: Option, + nu7_activation_height: Option, ) -> Self { #[cfg(any(test, feature = "proptest-impl"))] let nu5_activation_height = nu5_activation_height.or(Some(100)); @@ -538,6 +544,7 @@ impl Parameters { canopy: Some(1), nu5: nu5_activation_height, nu6: nu6_activation_height, + nu7: nu7_activation_height, ..Default::default() }) .finish() @@ -568,7 +575,7 @@ impl Parameters { post_nu6_funding_streams, target_difficulty_limit, disable_pow, - } = Self::new_regtest(None, None); + } = Self::new_regtest(None, None, None); self.network_name == network_name && self.genesis_hash == genesis_hash diff --git a/zebra-chain/src/parameters/network/tests/vectors.rs b/zebra-chain/src/parameters/network/tests/vectors.rs index c839a26c116..4683a908d2b 100644 --- a/zebra-chain/src/parameters/network/tests/vectors.rs +++ b/zebra-chain/src/parameters/network/tests/vectors.rs @@ -109,6 +109,7 @@ fn activates_network_upgrades_correctly() { let expected_activation_height = 1; let network = testnet::Parameters::build() .with_activation_heights(ConfiguredActivationHeights { + // FIXME: nu7? nu6: Some(expected_activation_height), ..Default::default() }) @@ -147,7 +148,7 @@ fn activates_network_upgrades_correctly() { (Network::Mainnet, MAINNET_ACTIVATION_HEIGHTS), (Network::new_default_testnet(), TESTNET_ACTIVATION_HEIGHTS), ( - Network::new_regtest(None, None), + Network::new_regtest(None, None, None), expected_default_regtest_activation_heights, ), ] { @@ -198,7 +199,7 @@ fn check_configured_network_name() { "Mainnet should be displayed as 'Mainnet'" ); assert_eq!( - Network::new_regtest(None, None).to_string(), + Network::new_regtest(None, None, None).to_string(), "Regtest", "Regtest should be displayed as 'Regtest'" ); diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 121a5bdcf13..74669a9b0fe 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -15,7 +15,7 @@ use hex::{FromHex, ToHex}; use proptest_derive::Arbitrary; /// A list of network upgrades in the order that they must be activated. -pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 9] = [ +pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 10] = [ Genesis, BeforeOverwinter, Overwinter, @@ -25,6 +25,7 @@ pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 9] = [ Canopy, Nu5, Nu6, + Nu7, ]; /// A Zcash network upgrade. @@ -60,6 +61,8 @@ pub enum NetworkUpgrade { Nu5, /// The Zcash protocol after the NU6 upgrade. Nu6, + /// The Zcash protocol after the NU7 upgrade. + Nu7, } impl fmt::Display for NetworkUpgrade { @@ -90,6 +93,8 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_687_104), Nu5), // TODO: Add NU6 // (block::Height(2_726_400), Nu6), + // FIXME: TODO: Add NU7 with a correct value + // (block::Height(2_726_401), Nu7), ]; /// Fake mainnet network upgrade activation heights, used in tests. @@ -104,6 +109,7 @@ const FAKE_MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] = &[ (block::Height(30), Canopy), (block::Height(35), Nu5), (block::Height(40), Nu6), + (block::Height(45), Nu7), ]; /// Testnet network upgrade activation heights. @@ -127,6 +133,8 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_842_420), Nu5), // TODO: Add NU6 // (block::Height(2_942_000), Nu6), + // FIXME: TODO: Add NU7 with a correct value + // (block::Height(2_942_001), Nu7), ]; /// Fake testnet network upgrade activation heights, used in tests. @@ -141,6 +149,7 @@ const FAKE_TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] = &[ (block::Height(30), Canopy), (block::Height(35), Nu5), (block::Height(40), Nu6), + (block::Height(45), Nu7), ]; /// The Consensus Branch Id, used to bind transactions and blocks to a @@ -217,6 +226,8 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Canopy, ConsensusBranchId(0xe9ff75a6)), (Nu5, ConsensusBranchId(0xc2d6d0b4)), (Nu6, ConsensusBranchId(0xc8e71055)), + // FIXME: use a proper value below + (Nu7, ConsensusBranchId(0xc8e71056)), ]; /// The target block spacing before Blossom. @@ -333,7 +344,8 @@ impl NetworkUpgrade { Heartwood => Some(Canopy), Canopy => Some(Nu5), Nu5 => Some(Nu6), - Nu6 => None, + Nu6 => Some(Nu7), + Nu7 => None, } } @@ -410,7 +422,9 @@ impl NetworkUpgrade { pub fn target_spacing(&self) -> Duration { let spacing_seconds = match self { Genesis | BeforeOverwinter | Overwinter | Sapling => PRE_BLOSSOM_POW_TARGET_SPACING, - Blossom | Heartwood | Canopy | Nu5 | Nu6 => POST_BLOSSOM_POW_TARGET_SPACING.into(), + Blossom | Heartwood | Canopy | Nu5 | Nu6 | Nu7 => { + POST_BLOSSOM_POW_TARGET_SPACING.into() + } }; Duration::seconds(spacing_seconds) @@ -533,6 +547,9 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, #[cfg(zcash_unstable = "nu6")] zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, + // FIXME: do we need the following cfg check? + #[cfg(zcash_unstable = "nu7")] + zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu7, } } } diff --git a/zebra-chain/src/primitives/zcash_history.rs b/zebra-chain/src/primitives/zcash_history.rs index e8ca97d63f8..4b52c85d8e8 100644 --- a/zebra-chain/src/primitives/zcash_history.rs +++ b/zebra-chain/src/primitives/zcash_history.rs @@ -276,7 +276,8 @@ impl Version for zcash_history::V1 { NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy | NetworkUpgrade::Nu5 - | NetworkUpgrade::Nu6 => zcash_history::NodeData { + | NetworkUpgrade::Nu6 + | NetworkUpgrade::Nu7 => zcash_history::NodeData { consensus_branch_id: branch_id.into(), subtree_commitment: block_hash, start_time: time, diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index cf4aa7a9552..0541bd7acd3 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -778,7 +778,7 @@ impl Arbitrary for Transaction { NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => { Self::v4_strategy(ledger_state) } - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => prop_oneof![ + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => prop_oneof![ Self::v4_strategy(ledger_state.clone()), Self::v5_strategy(ledger_state) ] From 2d3845dc7230e4e81c5c2ffa42093dfbbf919acb Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 19 Aug 2024 07:51:31 +0200 Subject: [PATCH 004/157] Introduce Nu7 fo other crates of Zebra --- zebra-consensus/src/transaction.rs | 5 +++-- zebra-consensus/src/transaction/tests/prop.rs | 3 ++- zebra-network/src/config.rs | 17 +++++++++++------ zebra-network/src/protocol/external/types.rs | 3 +++ .../types/get_block_template/proposal.rs | 2 +- zebrad/tests/common/configs/v1.9.0.toml | 2 ++ 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 1c303003615..192f1413332 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -678,7 +678,8 @@ where | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy | NetworkUpgrade::Nu5 - | NetworkUpgrade::Nu6 => Ok(()), + | NetworkUpgrade::Nu6 + | NetworkUpgrade::Nu7 => Ok(()), // Does not support V4 transactions NetworkUpgrade::Genesis @@ -766,7 +767,7 @@ where // // Note: Here we verify the transaction version number of the above rule, the group // id is checked in zebra-chain crate, in the transaction serialize. - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => Ok(()), + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => Ok(()), // Does not support V5 transactions NetworkUpgrade::Genesis diff --git a/zebra-consensus/src/transaction/tests/prop.rs b/zebra-consensus/src/transaction/tests/prop.rs index f45b4731de0..3f57bbb74bf 100644 --- a/zebra-consensus/src/transaction/tests/prop.rs +++ b/zebra-consensus/src/transaction/tests/prop.rs @@ -344,7 +344,8 @@ fn sanitize_transaction_version( BeforeOverwinter => 2, Overwinter => 3, Sapling | Blossom | Heartwood | Canopy => 4, - Nu5 | Nu6 => 5, + // FIXME: Use 6 for Nu7 + Nu5 | Nu6 | Nu7 => 5, } }; diff --git a/zebra-network/src/config.rs b/zebra-network/src/config.rs index 00f4f8b4460..236608b11cc 100644 --- a/zebra-network/src/config.rs +++ b/zebra-network/src/config.rs @@ -722,12 +722,17 @@ impl<'de> Deserialize<'de> for Config { (NetworkKind::Mainnet, _) => Network::Mainnet, (NetworkKind::Testnet, None) => Network::new_default_testnet(), (NetworkKind::Regtest, testnet_parameters) => { - let (nu5_activation_height, nu6_activation_height) = testnet_parameters - .and_then(|params| params.activation_heights) - .map(|ConfiguredActivationHeights { nu5, nu6, .. }| (nu5, nu6)) - .unwrap_or_default(); - - Network::new_regtest(nu5_activation_height, nu6_activation_height) + let (nu5_activation_height, nu6_activation_height, nu7_activation_height) = + testnet_parameters + .and_then(|params| params.activation_heights) + .map(|ConfiguredActivationHeights { nu5, nu6, nu7, .. }| (nu5, nu6, nu7)) + .unwrap_or_default(); + + Network::new_regtest( + nu5_activation_height, + nu6_activation_height, + nu7_activation_height, + ) } ( NetworkKind::Testnet, diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 7ac76d7670f..1c8c2fd3b2f 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -95,6 +95,9 @@ impl Version { (Mainnet, Nu5) => 170_100, (Testnet(params), Nu6) if params.is_default_testnet() => 170_050, (Mainnet, Nu6) => 170_100, + // FIXME: use proper values for Nu7 + (Testnet(params), Nu7) if params.is_default_testnet() => 170_051, + (Mainnet, Nu7) => 170_101, // It should be fine to reject peers with earlier network protocol versions on custom testnets for now. (Testnet(_params), _) => CURRENT_NETWORK_PROTOCOL_VERSION.0, diff --git a/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs b/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs index fc0805b533d..373ba2d7c20 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs @@ -217,7 +217,7 @@ pub fn proposal_block_from_template( | NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood => panic!("pre-Canopy block templates not supported"), NetworkUpgrade::Canopy => chain_history_root.bytes_in_serialized_order().into(), - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => { + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => { block_commitments_hash.bytes_in_serialized_order().into() } }; diff --git a/zebrad/tests/common/configs/v1.9.0.toml b/zebrad/tests/common/configs/v1.9.0.toml index 11bcf62107a..93291298f98 100644 --- a/zebrad/tests/common/configs/v1.9.0.toml +++ b/zebrad/tests/common/configs/v1.9.0.toml @@ -73,6 +73,8 @@ Heartwood = 903_800 Canopy = 1_028_500 NU5 = 1_842_420 NU6 = 2_000_000 +# FIXME: Use a proper value for NU7. +NU7 = 2_000_001 [network.testnet_parameters.pre_nu6_funding_streams.height_range] start = 0 From a3a61f5d9401c7ec4d7734b4665fb0887afbb1f8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 28 Aug 2024 15:20:23 +0200 Subject: [PATCH 005/157] Add initial Transaction V6 support in zebra-chain crate. This commit introduces basic support for Transaction version 6 (Tx V6). This initial implementation treats Tx V6 as a simple copy of Tx V5, without yet integrating ZSA-specific features or the new transaction structure. - Added a new V6 variant to the Transaction enum in the zebra-chain crate. - Updated relevant code to handle the new V6 variant. Note: Tests and additional adjustments are still pending, and will be addressed in subsequent commits. --- zebra-chain/src/transaction.rs | 167 +++++++++++++++++++++++++++++---- 1 file changed, 148 insertions(+), 19 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 3df3edc8d53..ada329140f1 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -142,6 +142,28 @@ pub enum Transaction { /// The orchard data for this transaction, if any. orchard_shielded_data: Option, }, + // FIXME: implement V6 properly (now it's just a coipy of V5) + /// A `version = 6` transaction , which supports Orchard ZSA, Orchard Vanille, Sapling and + /// transparent, but not Sprout. + V6 { + /// The Network Upgrade for this transaction. + /// + /// Derived from the ConsensusBranchId field. + network_upgrade: NetworkUpgrade, + /// The earliest time or block height that this transaction can be added to the + /// chain. + lock_time: LockTime, + /// The latest block height that this transaction can be added to the chain. + expiry_height: block::Height, + /// The transparent inputs to the transaction. + inputs: Vec, + /// The transparent outputs from the transaction. + outputs: Vec, + /// The sapling shielded data for this transaction, if any. + sapling_shielded_data: Option>, + /// The orchard data for this transaction, if any. + orchard_shielded_data: Option, + }, } impl fmt::Display for Transaction { @@ -180,7 +202,7 @@ impl Transaction { /// Compute the hash (mined transaction ID) of this transaction. /// - /// The hash uniquely identifies mined v5 transactions, + /// The hash uniquely identifies mined v5/v6 transactions, /// and all v1-v4 transactions, whether mined or unmined. pub fn hash(&self) -> Hash { Hash::from(self) @@ -247,7 +269,7 @@ impl Transaction { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => None, - Transaction::V5 { .. } => Some(AuthDigest::from(self)), + Transaction::V5 { .. } | Transaction::V6 { .. } => Some(AuthDigest::from(self)), } } @@ -320,7 +342,10 @@ impl Transaction { pub fn is_overwintered(&self) -> bool { match self { Transaction::V1 { .. } | Transaction::V2 { .. } => false, - Transaction::V3 { .. } | Transaction::V4 { .. } | Transaction::V5 { .. } => true, + Transaction::V3 { .. } + | Transaction::V4 { .. } + | Transaction::V5 { .. } + | Transaction::V6 { .. } => true, } } @@ -332,6 +357,7 @@ impl Transaction { Transaction::V3 { .. } => 3, Transaction::V4 { .. } => 4, Transaction::V5 { .. } => 5, + Transaction::V6 { .. } => 6, } } @@ -342,7 +368,8 @@ impl Transaction { | Transaction::V2 { lock_time, .. } | Transaction::V3 { lock_time, .. } | Transaction::V4 { lock_time, .. } - | Transaction::V5 { lock_time, .. } => *lock_time, + | Transaction::V5 { lock_time, .. } + | Transaction::V6 { lock_time, .. } => *lock_time, }; // `zcashd` checks that the block height is greater than the lock height. @@ -389,7 +416,8 @@ impl Transaction { | Transaction::V2 { lock_time, .. } | Transaction::V3 { lock_time, .. } | Transaction::V4 { lock_time, .. } - | Transaction::V5 { lock_time, .. } => *lock_time, + | Transaction::V5 { lock_time, .. } + | Transaction::V6 { lock_time, .. } => *lock_time, }; let mut lock_time_bytes = Vec::new(); lock_time @@ -419,7 +447,8 @@ impl Transaction { Transaction::V1 { .. } | Transaction::V2 { .. } => None, Transaction::V3 { expiry_height, .. } | Transaction::V4 { expiry_height, .. } - | Transaction::V5 { expiry_height, .. } => match expiry_height { + | Transaction::V5 { expiry_height, .. } + | Transaction::V6 { expiry_height, .. } => match expiry_height { // Consensus rule: // > No limit: To set no limit on transactions (so that they do not expire), nExpiryHeight should be set to 0. // https://zips.z.cash/zip-0203#specification @@ -451,6 +480,10 @@ impl Transaction { | Transaction::V5 { ref mut expiry_height, .. + } + | Transaction::V6 { + ref mut expiry_height, + .. } => expiry_height, } } @@ -467,6 +500,9 @@ impl Transaction { | Transaction::V4 { .. } => None, Transaction::V5 { network_upgrade, .. + } + | Transaction::V6 { + network_upgrade, .. } => Some(*network_upgrade), } } @@ -481,6 +517,7 @@ impl Transaction { Transaction::V3 { ref inputs, .. } => inputs, Transaction::V4 { ref inputs, .. } => inputs, Transaction::V5 { ref inputs, .. } => inputs, + Transaction::V6 { ref inputs, .. } => inputs, } } @@ -493,6 +530,7 @@ impl Transaction { Transaction::V3 { ref mut inputs, .. } => inputs, Transaction::V4 { ref mut inputs, .. } => inputs, Transaction::V5 { ref mut inputs, .. } => inputs, + Transaction::V6 { ref mut inputs, .. } => inputs, } } @@ -511,6 +549,7 @@ impl Transaction { Transaction::V3 { ref outputs, .. } => outputs, Transaction::V4 { ref outputs, .. } => outputs, Transaction::V5 { ref outputs, .. } => outputs, + Transaction::V6 { ref outputs, .. } => outputs, } } @@ -533,6 +572,9 @@ impl Transaction { Transaction::V5 { ref mut outputs, .. } => outputs, + Transaction::V6 { + ref mut outputs, .. + } => outputs, } } @@ -580,7 +622,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } + | Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -615,7 +658,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => 0, + | Transaction::V5 { .. } + | Transaction::V6 { .. } => 0, } } @@ -654,7 +698,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } + | Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -690,7 +735,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => None, + | Transaction::V5 { .. } + | Transaction::V6 { .. } => None, } } @@ -698,7 +744,7 @@ impl Transaction { pub fn has_sprout_joinsplit_data(&self) -> bool { match self { // No JoinSplits - Transaction::V1 { .. } | Transaction::V5 { .. } => false, + Transaction::V1 { .. } | Transaction::V5 { .. } | Transaction::V6 { .. } => false, // JoinSplits-on-BCTV14 Transaction::V2 { joinsplit_data, .. } | Transaction::V3 { joinsplit_data, .. } => { @@ -745,7 +791,8 @@ impl Transaction { .. } | Transaction::V1 { .. } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } + | Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -767,6 +814,11 @@ impl Transaction { .. } => Box::new(sapling_shielded_data.anchors()), + Transaction::V6 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.anchors()), + // No Spends Transaction::V1 { .. } | Transaction::V2 { .. } @@ -778,6 +830,10 @@ impl Transaction { | Transaction::V5 { sapling_shielded_data: None, .. + } + | Transaction::V6 { + sapling_shielded_data: None, + .. } => Box::new(std::iter::empty()), } } @@ -786,8 +842,8 @@ impl Transaction { /// returning `Spend` regardless of the underlying /// transaction version. /// - /// Shared anchors in V5 transactions are copied into each sapling spend. - /// This allows the same code to validate spends from V4 and V5 transactions. + /// Shared anchors in V5/V6 transactions are copied into each sapling spend. + /// This allows the same code to validate spends from V4 and V5/V6 transactions. /// /// # Correctness /// @@ -804,6 +860,10 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.spends_per_anchor()), + Transaction::V6 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.spends_per_anchor()), // No Spends Transaction::V1 { .. } @@ -816,6 +876,10 @@ impl Transaction { | Transaction::V5 { sapling_shielded_data: None, .. + } + | Transaction::V6 { + sapling_shielded_data: None, + .. } => Box::new(std::iter::empty()), } } @@ -832,6 +896,10 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.outputs()), + Transaction::V6 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.outputs()), // No Outputs Transaction::V1 { .. } @@ -844,6 +912,10 @@ impl Transaction { | Transaction::V5 { sapling_shielded_data: None, .. + } + | Transaction::V6 { + sapling_shielded_data: None, + .. } => Box::new(std::iter::empty()), } } @@ -862,6 +934,10 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.nullifiers()), + Transaction::V6 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.nullifiers()), // No Spends Transaction::V1 { .. } @@ -874,6 +950,10 @@ impl Transaction { | Transaction::V5 { sapling_shielded_data: None, .. + } + | Transaction::V6 { + sapling_shielded_data: None, + .. } => Box::new(std::iter::empty()), } } @@ -892,6 +972,10 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.note_commitments()), + Transaction::V6 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Box::new(sapling_shielded_data.note_commitments()), // No Spends Transaction::V1 { .. } @@ -904,6 +988,10 @@ impl Transaction { | Transaction::V5 { sapling_shielded_data: None, .. + } + | Transaction::V6 { + sapling_shielded_data: None, + .. } => Box::new(std::iter::empty()), } } @@ -920,6 +1008,10 @@ impl Transaction { sapling_shielded_data, .. } => sapling_shielded_data.is_some(), + Transaction::V6 { + sapling_shielded_data, + .. + } => sapling_shielded_data.is_some(), } } @@ -935,6 +1027,12 @@ impl Transaction { .. } => orchard_shielded_data.as_ref(), + // FIXME: Support V6/OrchardZSA propetly. + Transaction::V6 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_ref(), + // No Orchard shielded data Transaction::V1 { .. } | Transaction::V2 { .. } @@ -953,6 +1051,12 @@ impl Transaction { .. } => Some(orchard_shielded_data), + // FIXME: Support V6/OrchardZSA propetly. + Transaction::V6 { + orchard_shielded_data: Some(orchard_shielded_data), + .. + } => Some(orchard_shielded_data), + Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } @@ -960,6 +1064,10 @@ impl Transaction { | Transaction::V5 { orchard_shielded_data: None, .. + } + | Transaction::V6 { + orchard_shielded_data: None, + .. } => None, } } @@ -1086,7 +1194,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } + | Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -1135,7 +1244,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } + | Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -1182,7 +1292,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } + | Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -1231,7 +1342,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => Box::new(std::iter::empty()), + | Transaction::V5 { .. } + | Transaction::V6 { .. } => Box::new(std::iter::empty()), } } @@ -1272,7 +1384,8 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } => Box::new(iter::empty()), + | Transaction::V5 { .. } + | Transaction::V6 { .. } => Box::new(iter::empty()), }; joinsplit_value_balances.map(ValueBalance::from_sprout_amount) @@ -1314,6 +1427,10 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => sapling_shielded_data.value_balance, + Transaction::V6 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => sapling_shielded_data.value_balance, Transaction::V1 { .. } | Transaction::V2 { .. } @@ -1325,6 +1442,10 @@ impl Transaction { | Transaction::V5 { sapling_shielded_data: None, .. + } + | Transaction::V6 { + sapling_shielded_data: None, + .. } => Amount::zero(), }; @@ -1346,6 +1467,10 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Some(&mut sapling_shielded_data.value_balance), + Transaction::V6 { + sapling_shielded_data: Some(sapling_shielded_data), + .. + } => Some(&mut sapling_shielded_data.value_balance), Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } @@ -1356,6 +1481,10 @@ impl Transaction { | Transaction::V5 { sapling_shielded_data: None, .. + } + | Transaction::V6 { + sapling_shielded_data: None, + .. } => None, } } From 83d981b0a1276eda743740740b0adb14d3c9f768 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 28 Aug 2024 21:49:08 +0200 Subject: [PATCH 006/157] Add initial Transaction V6 support in other crates and tests (just copy V5 behaviour for now) --- zebra-chain/src/parameters/transaction.rs | 7 ++ .../src/primitives/zcash_primitives.rs | 5 +- zebra-chain/src/transaction/arbitrary.rs | 16 +++ zebra-chain/src/transaction/serialize.rs | 107 +++++++++++++++++- zebra-chain/src/transaction/tests/vectors.rs | 4 + zebra-chain/src/transaction/txid.rs | 10 +- zebra-chain/src/transaction/unmined.rs | 2 +- zebra-consensus/src/transaction.rs | 8 +- zebra-state/src/service/check/utxo.rs | 1 + .../src/service/non_finalized_state/chain.rs | 28 +++++ 10 files changed, 181 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index bab59e794db..77b88abca44 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -11,3 +11,10 @@ pub const SAPLING_VERSION_GROUP_ID: u32 = 0x892F_2085; /// Orchard transactions must use transaction version 5 and this version /// group ID. Sapling transactions can use v4 or v5 transactions. pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; + +/// The version group ID for version 6 transactions. +/// +/// Orchard transactions must use transaction version 5 and this version +/// group ID. +// FIXME: use a proper value! +pub const TX_V6_VERSION_GROUP_ID: u32 = 0x26A7_270B; diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 227742110ed..6fcaf7c38fe 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -148,13 +148,16 @@ impl TryFrom<&Transaction> for zp_tx::Transaction { /// /// # Panics /// - /// If the transaction is not V5. (Currently there is no need for this + /// If the transaction is not V5/V6. (Currently there is no need for this /// conversion for other versions.) #[allow(clippy::unwrap_in_result)] fn try_from(trans: &Transaction) -> Result { let network_upgrade = match trans { Transaction::V5 { network_upgrade, .. + } + | Transaction::V6 { + network_upgrade, .. } => network_upgrade, Transaction::V1 { .. } | Transaction::V2 { .. } diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index cf4aa7a9552..73aac10a23d 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -918,6 +918,22 @@ pub fn transaction_to_fake_v5( orchard_shielded_data: None, }, v5 @ V5 { .. } => v5.clone(), + V6 { + inputs, + outputs, + lock_time, + sapling_shielded_data, + orchard_shielded_data, + .. + } => V5 { + network_upgrade: block_nu, + inputs: inputs.clone(), + outputs: outputs.clone(), + lock_time: *lock_time, + expiry_height: height, + sapling_shielded_data: sapling_shielded_data.clone(), + orchard_shielded_data: orchard_shielded_data.clone(), + }, } } diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index ba65dd054b3..f37698d6118 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -11,7 +11,10 @@ use reddsa::{orchard::Binding, orchard::SpendAuth, Signature}; use crate::{ amount, block::MAX_BLOCK_BYTES, - parameters::{OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, TX_V5_VERSION_GROUP_ID}, + parameters::{ + OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, TX_V5_VERSION_GROUP_ID, + TX_V6_VERSION_GROUP_ID, + }, primitives::{Halo2Proof, ZkSnarkProof}, serialization::{ zcash_deserialize_external_count, zcash_serialize_empty_list, @@ -673,6 +676,54 @@ impl ZcashSerialize for Transaction { // `proofsOrchard`, `vSpendAuthSigsOrchard`, and `bindingSigOrchard`. orchard_shielded_data.zcash_serialize(&mut writer)?; } + + // FIXME: implement a proper serialization for V6 + Transaction::V6 { + network_upgrade, + lock_time, + expiry_height, + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data, + } => { + // Transaction V6 spec: + // FIXME: specify a proper ref + // https://zips.z.cash/protocol/protocol.pdf#txnencoding + + // Denoted as `nVersionGroupId` in the spec. + writer.write_u32::(TX_V6_VERSION_GROUP_ID)?; + + // Denoted as `nConsensusBranchId` in the spec. + writer.write_u32::(u32::from( + network_upgrade + .branch_id() + .expect("valid transactions must have a network upgrade with a branch id"), + ))?; + + // Denoted as `lock_time` in the spec. + lock_time.zcash_serialize(&mut writer)?; + + // Denoted as `nExpiryHeight` in the spec. + writer.write_u32::(expiry_height.0)?; + + // Denoted as `tx_in_count` and `tx_in` in the spec. + inputs.zcash_serialize(&mut writer)?; + + // Denoted as `tx_out_count` and `tx_out` in the spec. + outputs.zcash_serialize(&mut writer)?; + + // A bundle of fields denoted in the spec as `nSpendsSapling`, `vSpendsSapling`, + // `nOutputsSapling`,`vOutputsSapling`, `valueBalanceSapling`, `anchorSapling`, + // `vSpendProofsSapling`, `vSpendAuthSigsSapling`, `vOutputProofsSapling` and + // `bindingSigSapling`. + sapling_shielded_data.zcash_serialize(&mut writer)?; + + // A bundle of fields denoted in the spec as `nActionsOrchard`, `vActionsOrchard`, + // `flagsOrchard`,`valueBalanceOrchard`, `anchorOrchard`, `sizeProofsOrchard`, + // `proofsOrchard`, `vSpendAuthSigsOrchard`, and `bindingSigOrchard`. + orchard_shielded_data.zcash_serialize(&mut writer)?; + } } Ok(()) } @@ -929,6 +980,60 @@ impl ZcashDeserialize for Transaction { orchard_shielded_data, }) } + // FIXME: implement a proper deserialization for V6 + (6, true) => { + // Transaction V6 spec: + // FIXME: specify a proper ref + // https://zips.z.cash/protocol/protocol.pdf#txnencoding + + // Denoted as `nVersionGroupId` in the spec. + let id = limited_reader.read_u32::()?; + if id != TX_V6_VERSION_GROUP_ID { + return Err(SerializationError::Parse("expected TX_V6_VERSION_GROUP_ID")); + } + // Denoted as `nConsensusBranchId` in the spec. + // Convert it to a NetworkUpgrade + let network_upgrade = + NetworkUpgrade::from_branch_id(limited_reader.read_u32::()?) + .ok_or_else(|| { + SerializationError::Parse( + "expected a valid network upgrade from the consensus branch id", + ) + })?; + + // Denoted as `lock_time` in the spec. + let lock_time = LockTime::zcash_deserialize(&mut limited_reader)?; + + // Denoted as `nExpiryHeight` in the spec. + let expiry_height = block::Height(limited_reader.read_u32::()?); + + // Denoted as `tx_in_count` and `tx_in` in the spec. + let inputs = Vec::zcash_deserialize(&mut limited_reader)?; + + // Denoted as `tx_out_count` and `tx_out` in the spec. + let outputs = Vec::zcash_deserialize(&mut limited_reader)?; + + // A bundle of fields denoted in the spec as `nSpendsSapling`, `vSpendsSapling`, + // `nOutputsSapling`,`vOutputsSapling`, `valueBalanceSapling`, `anchorSapling`, + // `vSpendProofsSapling`, `vSpendAuthSigsSapling`, `vOutputProofsSapling` and + // `bindingSigSapling`. + let sapling_shielded_data = (&mut limited_reader).zcash_deserialize_into()?; + + // A bundle of fields denoted in the spec as `nActionsOrchard`, `vActionsOrchard`, + // `flagsOrchard`,`valueBalanceOrchard`, `anchorOrchard`, `sizeProofsOrchard`, + // `proofsOrchard`, `vSpendAuthSigsOrchard`, and `bindingSigOrchard`. + let orchard_shielded_data = (&mut limited_reader).zcash_deserialize_into()?; + + Ok(Transaction::V6 { + network_upgrade, + lock_time, + expiry_height, + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data, + }) + } (_, _) => Err(SerializationError::Parse("bad tx header")), } } diff --git a/zebra-chain/src/transaction/tests/vectors.rs b/zebra-chain/src/transaction/tests/vectors.rs index 66d5009ed05..f20bfaef455 100644 --- a/zebra-chain/src/transaction/tests/vectors.rs +++ b/zebra-chain/src/transaction/tests/vectors.rs @@ -991,6 +991,10 @@ fn binding_signatures_for_network(network: Network) { Transaction::V5 { sapling_shielded_data, .. + } + | Transaction::V6 { + sapling_shielded_data, + .. } => { if let Some(sapling_shielded_data) = sapling_shielded_data { let shielded_sighash = diff --git a/zebra-chain/src/transaction/txid.rs b/zebra-chain/src/transaction/txid.rs index f67f6dee58d..eb05fd6edb3 100644 --- a/zebra-chain/src/transaction/txid.rs +++ b/zebra-chain/src/transaction/txid.rs @@ -28,7 +28,7 @@ impl<'a> TxIdBuilder<'a> { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => self.txid_v1_to_v4(), - Transaction::V5 { .. } => self.txid_v5(), + Transaction::V5 { .. } | Transaction::V6 { .. } => self.txid_v5_v6(), } } @@ -43,10 +43,14 @@ impl<'a> TxIdBuilder<'a> { Ok(Hash(hash_writer.finish())) } - /// Compute the Transaction ID for a V5 transaction in the given network upgrade. + // FIXME: it looks like the updated zcash_primitives in librustzcash + // auto-detects the transaction version by the first byte, so the same function + // can be used here for both V5 and V6. + // FIXME: fix spec refs below for V6 + /// Compute the Transaction ID for a V5/V6 transaction in the given network upgrade. /// In this case it's the hash of a tree of hashes of specific parts of the /// transaction, as specified in ZIP-244 and ZIP-225. - fn txid_v5(self) -> Result { + fn txid_v5_v6(self) -> Result { // The v5 txid (from ZIP-244) is computed using librustzcash. Convert the zebra // transaction to a librustzcash transaction. let alt_tx: zcash_primitives::transaction::Transaction = self.trans.try_into()?; diff --git a/zebra-chain/src/transaction/unmined.rs b/zebra-chain/src/transaction/unmined.rs index da716573e8b..554e8c3f0e1 100644 --- a/zebra-chain/src/transaction/unmined.rs +++ b/zebra-chain/src/transaction/unmined.rs @@ -140,7 +140,7 @@ impl From<&Transaction> for UnminedTxId { fn from(transaction: &Transaction) -> Self { match transaction { V1 { .. } | V2 { .. } | V3 { .. } | V4 { .. } => Legacy(transaction.into()), - V5 { .. } => Witnessed(transaction.into()), + V5 { .. } | V6 { .. } => Witnessed(transaction.into()), } } } diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 1c303003615..5c21ccd494c 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -405,7 +405,13 @@ where sapling_shielded_data, orchard_shielded_data, .. - } => Self::verify_v5_transaction( + } + // FIXME: implement proper V6 verification + | Transaction::V6 { + sapling_shielded_data, + orchard_shielded_data, + .. + }=> Self::verify_v5_transaction( &req, &network, script_verifier, diff --git a/zebra-state/src/service/check/utxo.rs b/zebra-state/src/service/check/utxo.rs index 324efa3c035..b856a616dd5 100644 --- a/zebra-state/src/service/check/utxo.rs +++ b/zebra-state/src/service/check/utxo.rs @@ -63,6 +63,7 @@ pub fn transparent_spend( finalized_state, )?; + // FIXME: what about v6? // The state service returns UTXOs from pending blocks, // which can be rejected by later contextual checks. // This is a particular issue for v5 transactions, diff --git a/zebra-state/src/service/non_finalized_state/chain.rs b/zebra-state/src/service/non_finalized_state/chain.rs index e25b1fd171b..233a1dbea63 100644 --- a/zebra-state/src/service/non_finalized_state/chain.rs +++ b/zebra-state/src/service/non_finalized_state/chain.rs @@ -1510,6 +1510,20 @@ impl Chain { sapling_shielded_data, orchard_shielded_data, ), + V6 { + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data, + .. + } => ( + inputs, + outputs, + &None, + &None, + sapling_shielded_data, + orchard_shielded_data, + ), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!( "older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint", ), @@ -1671,6 +1685,20 @@ impl UpdateWith for Chain { sapling_shielded_data, orchard_shielded_data, ), + V6 { + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data, + .. + } => ( + inputs, + outputs, + &None, + &None, + sapling_shielded_data, + orchard_shielded_data, + ), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!( "older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint", ), From c8fa7794502191f6980a3f70b85e10d62a1453b5 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 28 Aug 2024 23:07:00 +0200 Subject: [PATCH 007/157] Fix compilation errors in tests --- zebra-state/src/tests.rs | 1 + zebrad/src/components/mempool/storage/tests/prop.rs | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/zebra-state/src/tests.rs b/zebra-state/src/tests.rs index 488ab4227bd..6b955480572 100644 --- a/zebra-state/src/tests.rs +++ b/zebra-state/src/tests.rs @@ -34,6 +34,7 @@ impl FakeChainHelper for Arc { Transaction::V3 { inputs, .. } => &mut inputs[0], Transaction::V4 { inputs, .. } => &mut inputs[0], Transaction::V5 { inputs, .. } => &mut inputs[0], + Transaction::V6 { inputs, .. } => &mut inputs[0], }; match input { diff --git a/zebrad/src/components/mempool/storage/tests/prop.rs b/zebrad/src/components/mempool/storage/tests/prop.rs index eca65935acb..98abdb2b8e8 100644 --- a/zebrad/src/components/mempool/storage/tests/prop.rs +++ b/zebrad/src/components/mempool/storage/tests/prop.rs @@ -446,6 +446,7 @@ enum SpendConflictTestInput { conflict: SpendConflictForTransactionV5, }, + // FIXME: add and use V6? } impl SpendConflictTestInput { @@ -567,7 +568,7 @@ impl SpendConflictTestInput { } // No JoinSplits - Transaction::V1 { .. } | Transaction::V5 { .. } => {} + Transaction::V1 { .. } | Transaction::V5 { .. } | Transaction::V6 { .. } => {} } } } @@ -634,6 +635,10 @@ impl SpendConflictTestInput { Transaction::V5 { sapling_shielded_data, .. + } + | Transaction::V6 { + sapling_shielded_data, + .. } => { Self::remove_sapling_transfers_with_conflicts(sapling_shielded_data, &conflicts) } @@ -707,6 +712,10 @@ impl SpendConflictTestInput { Transaction::V5 { orchard_shielded_data, .. + } + | Transaction::V6 { + orchard_shielded_data, + .. } => Self::remove_orchard_actions_with_conflicts(orchard_shielded_data, &conflicts), // No Spends From 53c65b675b1ce50905f145412b8e18fcc56a98d3 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 2 Sep 2024 10:39:29 +0200 Subject: [PATCH 008/157] Trigger CI From c238847af2f5ad57f537889e87860042af2100bb Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 08:54:05 +0200 Subject: [PATCH 009/157] Add basic CI checks workflow --- .github/workflows/ci-basic.yml | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/ci-basic.yml diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml new file mode 100644 index 00000000000..92dedd60cb0 --- /dev/null +++ b/.github/workflows/ci-basic.yml @@ -0,0 +1,36 @@ +name: Basic checks + +on: [push, pull_request] + +jobs: + test: + name: Test on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + + steps: + - uses: actions/checkout@v4 + - name: Run tests + run: cargo test --verbose + - name: Verify working directory is clean + run: git diff --exit-code + + doc-links: + name: Intra-doc links + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: cargo fetch + # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. + - name: Check intra-doc links + run: cargo doc --all-features --document-private-items + + fmt: + name: Rustfmt + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: cargo fmt -- --check From 2c13ae9ab1ffbc6865867ed7f42a2f5d262a3539 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 10:28:32 +0200 Subject: [PATCH 010/157] Fix ci-basic.yml --- .github/workflows/ci-basic.yml | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 92dedd60cb0..7b50109c04a 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -12,25 +12,13 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install dependencies on Ubuntu + run: sudo apt-get update && sudo apt-get install -y protoc - name: Run tests run: cargo test --verbose - name: Verify working directory is clean run: git diff --exit-code - - doc-links: - name: Intra-doc links - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: cargo fetch - # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. - - name: Check intra-doc links + - name: Run doc check run: cargo doc --all-features --document-private-items - - fmt: - name: Rustfmt - timeout-minutes: 30 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: cargo fmt -- --check + - name: Run format check + run: cargo fmt -- --check From 5a839c6f2b56f3ca73f16a101b7a34551a4816da Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 10:31:29 +0200 Subject: [PATCH 011/157] Fix ci-basic.yml (2) --- .github/workflows/ci-basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 7b50109c04a..522329e2440 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu - run: sudo apt-get update && sudo apt-get install -y protoc + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler - name: Run tests run: cargo test --verbose - name: Verify working directory is clean From 367a14bff6885625577eac433b6b4ccdc5c6600b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 10:52:49 +0200 Subject: [PATCH 012/157] Add installing of build-essential to ci-basic.yml --- .github/workflows/ci-basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 522329e2440..be3d44917eb 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential - name: Run tests run: cargo test --verbose - name: Verify working directory is clean From f425747e759a17c8a102bd30985bddb406d60906 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 20:57:11 +0200 Subject: [PATCH 013/157] Try to use librocksdb-dev in ci-basic.yml --- .github/workflows/ci-basic.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index be3d44917eb..547b64446c3 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -1,6 +1,7 @@ name: Basic checks -on: [push, pull_request] +#on: [push, pull_request] +on: [push] jobs: test: @@ -13,9 +14,9 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev - name: Run tests - run: cargo test --verbose + run: ROCKSDB_LIB_DIR=/usr/lib SNAPPY_LIB_DIR=/usr/lib/x86_64-linux-gnu cargo test --verbose - name: Verify working directory is clean run: git diff --exit-code - name: Run doc check From 831c847d32201ceb7dc0cf6efde9a317a7274d59 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 21:05:06 +0200 Subject: [PATCH 014/157] Run ci-basic.yml on ubuntu-24.04 --- .github/workflows/ci-basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 547b64446c3..840d406b609 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -9,7 +9,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest] + os: [ubuntu-24.04] steps: - uses: actions/checkout@v4 From ecaf98d9a04213b2bc0b6e2fc553880a4849bf5a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 22:32:19 +0200 Subject: [PATCH 015/157] Enable nu6 cfg flag in ci-basic.yml --- .github/workflows/ci-basic.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 840d406b609..4a9bdafa1b5 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -11,12 +11,20 @@ jobs: matrix: os: [ubuntu-24.04] + env: + # Use system-installed RocksDB library instead of building from scratch + ROCKSDB_LIB_DIR: /usr/lib + # Use system-installed Snappy library for compression in RocksDB + SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu + # Enable the `nu6` feature in `zcash_protocol` + RUSTFLAGS: '--cfg zcash_unstable="nu6"' + steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev - name: Run tests - run: ROCKSDB_LIB_DIR=/usr/lib SNAPPY_LIB_DIR=/usr/lib/x86_64-linux-gnu cargo test --verbose + run: cargo test --verbose - name: Verify working directory is clean run: git diff --exit-code - name: Run doc check From 7d1115990ab39f28035f568ad4d69eadbd764147 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 4 Sep 2024 10:51:26 +0200 Subject: [PATCH 016/157] Adjust the code with librustzcash/zcash_protocol nu6 related changes --- zebra-chain/Cargo.toml | 4 +++ zebra-chain/src/parameters/network_upgrade.rs | 7 ++++- .../src/primitives/zcash_primitives.rs | 27 ++++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index bf9479976ee..44954d31af7 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -176,3 +176,7 @@ required-features = ["bench"] [[bench]] name = "redpallas" harness = false + +# FIXME: remove this and all zcash_unstable usage in the code after updating librustzcash +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 551c4a88801..ab66fbc7895 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -530,7 +530,12 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Heartwood => Self::Heartwood, zcash_protocol::consensus::NetworkUpgrade::Canopy => Self::Canopy, zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, - // FIXME: uncomment this! zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, + // FIXME: remove cfg + #[cfg(zcash_unstable = "nu6")] + zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, + // FIXME: remove cfg and process Nu7 properly (uses Self::Nu6 for now) + #[cfg(zcash_unstable = "nu6")] + zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, } } } diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 7ab2f32d751..be90f18ed23 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -137,6 +137,16 @@ impl zp_tx::components::orchard::MapAuth + for IdentityMap +{ + fn map_issue_authorization(&self, s: orchard::issuance::Signed) -> orchard::issuance::Signed { + s + } +} + #[derive(Debug)] struct PrecomputedAuth<'a> { _phantom: std::marker::PhantomData<&'a ()>, @@ -146,6 +156,14 @@ impl<'a> zp_tx::Authorization for PrecomputedAuth<'a> { type TransparentAuth = TransparentAuth<'a>; type SaplingAuth = sapling_crypto::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; + + // FIXME: is this correct? + #[cfg(zcash_unstable = "nu6")] + type OrchardZsaAuth = orchard::bundle::Authorized; + + // FIXME: is this correct? + #[cfg(zcash_unstable = "nu6")] + type IssueAuth = orchard::issuance::Signed; } // End of (mostly) copied code @@ -275,7 +293,14 @@ impl<'a> PrecomputedTxData<'a> { }; let tx_data: zp_tx::TransactionData = alt_tx .into_data() - .map_authorization(f_transparent, IdentityMap, IdentityMap); + // FIXME: do we need to pass another arg values or orchard_zsa and issue instead of IdentityMap? + .map_authorization( + f_transparent, + IdentityMap, + IdentityMap, + IdentityMap, + IdentityMap, + ); PrecomputedTxData { tx_data, From 6a0196e9b791f6873b42bb086bc4bfe18ebeb299 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 4 Sep 2024 11:40:25 +0200 Subject: [PATCH 017/157] Add RUSTDOCFLAGS to ci-basic.yml --- .github/workflows/ci-basic.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 4a9bdafa1b5..c2cde8686bf 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -18,11 +18,13 @@ jobs: SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu # Enable the `nu6` feature in `zcash_protocol` RUSTFLAGS: '--cfg zcash_unstable="nu6"' + RUSTDOCFLAGS: '--cfg zcash_unstable="nu6"' steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev + #run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler librocksdb-dev - name: Run tests run: cargo test --verbose - name: Verify working directory is clean From 23e318c0b0e46a8ff4f7f2498fc20ddd57d4034d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 16 Sep 2024 10:00:59 +0200 Subject: [PATCH 018/157] Add support for Orchard ZSA and updated generic structures for Tx V6 (without unit tests fixing for now). - Refactored `ShieldedData` and `Action` structures to be generics parameterized by Orchard flavor (`OrchardVanilla` or `OrchardZSA`), enabling support for both Orchard protocols in Tx V6. - Introduced a `burn` field in `ShieldedData` to support ZSA, with unit type for Tx V5 and a vector of burn items for Tx V6. - Modified `Transaction` enum methods (orchard_...) to handle generics properly, ensuring compatibility with both Orchard flavors. - Implemented serialization and deserialization for Tx V6 while avoiding code redundancy with Tx V5 wherever possible. --- Cargo.lock | 1 + zebra-chain/Cargo.toml | 11 +- zebra-chain/src/lib.rs | 3 + zebra-chain/src/orchard.rs | 5 + zebra-chain/src/orchard/action.rs | 11 +- zebra-chain/src/orchard/note/ciphertexts.rs | 30 ++-- zebra-chain/src/orchard/shielded_data.rs | 158 +++++++++++++---- zebra-chain/src/transaction.rs | 186 +++++++++++--------- zebra-chain/src/transaction/serialize.rs | 48 +++-- 9 files changed, 303 insertions(+), 150 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d66f5989a5..6d45b80fb3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6000,6 +6000,7 @@ dependencies = [ "itertools 0.13.0", "jubjub", "lazy_static", + "nonempty", "num-integer", "orchard", "primitive-types", diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 44954d31af7..8efebf87be4 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -15,7 +15,8 @@ keywords = ["zebra", "zcash"] categories = ["asynchronous", "cryptography::cryptocurrencies", "encoding"] [features] -default = [] +#default = [] +default = ["tx-v6"] # Production features that activate extra functionality @@ -60,6 +61,11 @@ proptest-impl = [ bench = ["zebra-test"] +# Support for transaction version 6 +tx-v6 = [ + "nonempty" +] + [dependencies] # Cryptography @@ -102,6 +108,9 @@ sapling-crypto.workspace = true zcash_protocol.workspace = true zcash_address.workspace = true +# Used for orchard serialization +nonempty = { version = "0.7", optional = true } + # Time chrono = { version = "0.4.38", default-features = false, features = ["clock", "std", "serde"] } humantime = "2.1.0" diff --git a/zebra-chain/src/lib.rs b/zebra-chain/src/lib.rs index 4faaeab70cc..06b6a0e1e23 100644 --- a/zebra-chain/src/lib.rs +++ b/zebra-chain/src/lib.rs @@ -40,6 +40,9 @@ pub mod transparent; pub mod value_balance; pub mod work; +#[cfg(feature = "tx-v6")] +pub mod orchard_zsa; + #[cfg(any(test, feature = "proptest-impl"))] pub use block::LedgerState; diff --git a/zebra-chain/src/orchard.rs b/zebra-chain/src/orchard.rs index be96644c8c9..55de746336d 100644 --- a/zebra-chain/src/orchard.rs +++ b/zebra-chain/src/orchard.rs @@ -6,6 +6,7 @@ mod action; mod address; mod commitment; mod note; +mod orchard_flavor_ext; mod sinsemilla; #[cfg(any(test, feature = "proptest-impl"))] @@ -23,3 +24,7 @@ pub use commitment::{CommitmentRandomness, NoteCommitment, ValueCommitment}; pub use keys::Diversifier; pub use note::{EncryptedNote, Note, Nullifier, WrappedNoteKey}; pub use shielded_data::{AuthorizedAction, Flags, ShieldedData}; + +pub(crate) use crate::orchard_zsa::issuance::IssueData; +pub(crate) use orchard_flavor_ext::{OrchardFlavorExt, OrchardVanilla, OrchardZSA}; +pub(crate) use shielded_data::ActionCommon; diff --git a/zebra-chain/src/orchard/action.rs b/zebra-chain/src/orchard/action.rs index ae7690def7a..c8161246efb 100644 --- a/zebra-chain/src/orchard/action.rs +++ b/zebra-chain/src/orchard/action.rs @@ -11,6 +11,7 @@ use super::{ commitment::{self, ValueCommitment}, keys, note::{self, Nullifier}, + OrchardFlavorExt, }; /// An Action description, as described in the [Zcash specification §7.3][actiondesc]. @@ -21,7 +22,7 @@ use super::{ /// /// [actiondesc]: https://zips.z.cash/protocol/nu5.pdf#actiondesc #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct Action { +pub struct Action { /// A value commitment to net value of the input note minus the output note pub cv: commitment::ValueCommitment, /// The nullifier of the input note being spent. @@ -35,14 +36,14 @@ pub struct Action { /// encrypted private key in `out_ciphertext`. pub ephemeral_key: keys::EphemeralPublicKey, /// A ciphertext component for the encrypted output note. - pub enc_ciphertext: note::EncryptedNote, + pub enc_ciphertext: V::EncryptedNote, /// A ciphertext component that allows the holder of a full viewing key to /// recover the recipient diversified transmission key and the ephemeral /// private key (and therefore the entire note plaintext). pub out_ciphertext: note::WrappedNoteKey, } -impl ZcashSerialize for Action { +impl ZcashSerialize for Action { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { self.cv.zcash_serialize(&mut writer)?; writer.write_all(&<[u8; 32]>::from(self.nullifier)[..])?; @@ -55,7 +56,7 @@ impl ZcashSerialize for Action { } } -impl ZcashDeserialize for Action { +impl ZcashDeserialize for Action { fn zcash_deserialize(mut reader: R) -> Result { // # Consensus // @@ -93,7 +94,7 @@ impl ZcashDeserialize for Action { // https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to // 580 bytes in https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus // See [`note::EncryptedNote::zcash_deserialize`]. - enc_ciphertext: note::EncryptedNote::zcash_deserialize(&mut reader)?, + enc_ciphertext: V::EncryptedNote::zcash_deserialize(&mut reader)?, // Type is `Sym.C`, i.e. `𝔹^Y^{\[N\]}`, i.e. arbitrary-sized byte arrays // https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to // 80 bytes in https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index b27ffbc53a1..f245e47ca7c 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -1,7 +1,5 @@ //! Encrypted parts of Orchard notes. -// FIXME: make it a generic and add support for OrchardZSA (encrypted tote size ofr it is not 580!) - use std::{fmt, io}; use serde_big_array::BigArray; @@ -12,20 +10,20 @@ use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize} /// /// Corresponds to the Orchard 'encCiphertext's #[derive(Deserialize, Serialize)] -pub struct EncryptedNote(#[serde(with = "BigArray")] pub(crate) [u8; 580]); +pub struct EncryptedNote(#[serde(with = "BigArray")] pub(crate) [u8; N]); // These impls all only exist because of array length restrictions. // TODO: use const generics https://github.com/ZcashFoundation/zebra/issues/2042 -impl Copy for EncryptedNote {} +impl Copy for EncryptedNote {} -impl Clone for EncryptedNote { +impl Clone for EncryptedNote { fn clone(&self) -> Self { *self } } -impl fmt::Debug for EncryptedNote { +impl fmt::Debug for EncryptedNote { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("EncryptedNote") .field(&hex::encode(&self.0[..])) @@ -33,36 +31,36 @@ impl fmt::Debug for EncryptedNote { } } -impl Eq for EncryptedNote {} +impl Eq for EncryptedNote {} -impl From<[u8; 580]> for EncryptedNote { - fn from(bytes: [u8; 580]) -> Self { +impl From<[u8; N]> for EncryptedNote { + fn from(bytes: [u8; N]) -> Self { EncryptedNote(bytes) } } -impl From for [u8; 580] { - fn from(enc_ciphertext: EncryptedNote) -> Self { +impl From> for [u8; N] { + fn from(enc_ciphertext: EncryptedNote) -> Self { enc_ciphertext.0 } } -impl PartialEq for EncryptedNote { +impl PartialEq for EncryptedNote { fn eq(&self, other: &Self) -> bool { self.0[..] == other.0[..] } } -impl ZcashSerialize for EncryptedNote { +impl ZcashSerialize for EncryptedNote { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { writer.write_all(&self.0[..])?; Ok(()) } } -impl ZcashDeserialize for EncryptedNote { +impl ZcashDeserialize for EncryptedNote { fn zcash_deserialize(mut reader: R) -> Result { - let mut bytes = [0; 580]; + let mut bytes = [0; N]; reader.read_exact(&mut bytes[..])?; Ok(Self(bytes)) } @@ -133,7 +131,7 @@ use proptest::prelude::*; proptest! { #[test] - fn encrypted_ciphertext_roundtrip(ec in any::()) { + fn encrypted_ciphertext_roundtrip(ec in any::>()) { let _init_guard = zebra_test::init(); let mut data = Vec::new(); diff --git a/zebra-chain/src/orchard/shielded_data.rs b/zebra-chain/src/orchard/shielded_data.rs index 5347919cd01..df09023fe5a 100644 --- a/zebra-chain/src/orchard/shielded_data.rs +++ b/zebra-chain/src/orchard/shielded_data.rs @@ -20,9 +20,17 @@ use crate::{ }, }; +use super::OrchardFlavorExt; + +#[cfg(not(feature = "tx-v6"))] +use super::OrchardVanilla; + +#[cfg(feature = "tx-v6")] +use super::OrchardZSA; + /// A bundle of [`Action`] descriptions and signature data. #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShieldedData { +pub struct ShieldedData { /// The orchard flags for this transaction. /// Denoted as `flagsOrchard` in the spec. pub flags: Flags, @@ -37,13 +45,18 @@ pub struct ShieldedData { pub proof: Halo2Proof, /// The Orchard Actions, in the order they appear in the transaction. /// Denoted as `vActionsOrchard` and `vSpendAuthSigsOrchard` in the spec. - pub actions: AtLeastOne, + pub actions: AtLeastOne>, /// A signature on the transaction `sighash`. /// Denoted as `bindingSigOrchard` in the spec. pub binding_sig: Signature, + + #[cfg(feature = "tx-v6")] + /// Assets intended for burning + /// Denoted as `vAssetBurn` in the spec (ZIP 230). + pub burn: V::BurnType, } -impl fmt::Display for ShieldedData { +impl fmt::Display for ShieldedData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut fmter = f.debug_struct("orchard::ShieldedData"); @@ -59,13 +72,18 @@ impl fmt::Display for ShieldedData { } } -impl ShieldedData { +impl ShieldedData { /// Iterate over the [`Action`]s for the [`AuthorizedAction`]s in this /// transaction, in the order they appear in it. - pub fn actions(&self) -> impl Iterator { + pub fn actions(&self) -> impl Iterator> { self.actions.actions() } + // FIXME: add a doc comment + pub fn action_commons(&self) -> impl Iterator + '_ { + self.actions.actions().map(|action| action.into()) + } + /// Collect the [`Nullifier`]s for this transaction. pub fn nullifiers(&self) -> impl Iterator { self.actions().map(|action| &action.nullifier) @@ -119,9 +137,9 @@ impl ShieldedData { } } -impl AtLeastOne { +impl AtLeastOne> { /// Iterate over the [`Action`]s of each [`AuthorizedAction`]. - pub fn actions(&self) -> impl Iterator { + pub fn actions(&self) -> impl Iterator> { self.iter() .map(|authorized_action| &authorized_action.action) } @@ -131,23 +149,64 @@ impl AtLeastOne { /// /// Every authorized Orchard `Action` must have a corresponding `SpendAuth` signature. #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -pub struct AuthorizedAction { +pub struct AuthorizedAction { /// The action description of this Action. - pub action: Action, + pub action: Action, /// The spend signature. pub spend_auth_sig: Signature, } -impl AuthorizedAction { +impl AuthorizedAction { + /// The size of a single Action + /// + /// Actions are 5 * 32 + ENCRYPTED_NOTE_SIZE + 80 bytes so the total size of each Action is 820 bytes. + /// [7.5 Action Description Encoding and Consensus][ps] + /// + /// [ps]: + pub const ACTION_SIZE: u64 = 5 * 32 + (V::ENCRYPTED_NOTE_SIZE as u64) + 80; + + /// The size of a single `Signature`. + /// + /// Each Signature is 64 bytes. + /// [7.1 Transaction Encoding and Consensus][ps] + /// + /// [ps]: + pub const SPEND_AUTH_SIG_SIZE: u64 = 64; + + /// The size of a single AuthorizedAction + /// + /// Each serialized `Action` has a corresponding `Signature`. + pub const AUTHORIZED_ACTION_SIZE: u64 = Self::ACTION_SIZE + Self::SPEND_AUTH_SIG_SIZE; + + /// The maximum number of actions in the transaction. + // Since a serialized Vec uses at least one byte for its length, + // and the signature is required, + // a valid max allocation can never exceed this size + pub const ACTION_MAX_ALLOCATION: u64 = (MAX_BLOCK_BYTES - 1) / Self::AUTHORIZED_ACTION_SIZE; + + // To be but we ensure ACTION_MAX_ALLOCATION is less than 2^16 on compile time + // (this is a workaround, as static_assertions::const_assert! doesn't work for generics, + // see TrustedPreallocate for Action) + const _ACTION_MAX_ALLOCATION_OK: u64 = (1 << 16) - Self::ACTION_MAX_ALLOCATION; + /* FIXME: remove this + const ACTION_MAX_ALLOCATION_OK: () = assert!( + Self::ACTION_MAX_ALLOCATION < 1, //(1 << 16), + "must be less than 2^16" + ); + */ + /// Split out the action and the signature for V5 transaction /// serialization. - pub fn into_parts(self) -> (Action, Signature) { + pub fn into_parts(self) -> (Action, Signature) { (self.action, self.spend_auth_sig) } // Combine the action and the spend auth sig from V5 transaction /// deserialization. - pub fn from_parts(action: Action, spend_auth_sig: Signature) -> AuthorizedAction { + pub fn from_parts( + action: Action, + spend_auth_sig: Signature, + ) -> AuthorizedAction { AuthorizedAction { action, spend_auth_sig, @@ -155,38 +214,48 @@ impl AuthorizedAction { } } -/// The size of a single Action -/// -/// Actions are 5 * 32 + 580 + 80 bytes so the total size of each Action is 820 bytes. -/// [7.5 Action Description Encoding and Consensus][ps] -/// -/// [ps]: -pub const ACTION_SIZE: u64 = 5 * 32 + 580 + 80; +// TODO: FIXME: Consider moving it to transaction.rs as it's not used here. Or move its usage here from transaction.rs. +/// A struct that contains values of several fields of an `Action` struct. +/// Those fields are used in other parts of the code that call the `orchard_actions()` method of the `Transaction`. +/// The goal of using `ActionCommon` is that it's not a generic, unlike `Action`, so it can be returned from Transaction methods +/// (the fields of `ActionCommon` do not depend on the generic parameter `Version` of `Action`). +pub struct ActionCommon { + /// A reference to the value commitment to the net value of the input note minus the output note. + pub cv: super::commitment::ValueCommitment, + /// A reference to the nullifier of the input note being spent. + pub nullifier: super::note::Nullifier, + /// A reference to the randomized validating key for `spendAuthSig`. + pub rk: reddsa::VerificationKeyBytes, + /// A reference to the x-coordinate of the note commitment for the output note. + pub cm_x: pallas::Base, +} -/// The size of a single `Signature`. -/// -/// Each Signature is 64 bytes. -/// [7.1 Transaction Encoding and Consensus][ps] -/// -/// [ps]: -pub const SPEND_AUTH_SIG_SIZE: u64 = 64; +impl From<&Action> for ActionCommon { + fn from(action: &Action) -> Self { + Self { + cv: action.cv, + nullifier: action.nullifier, + rk: action.rk, + cm_x: action.cm_x, + } + } +} -/// The size of a single AuthorizedAction -/// -/// Each serialized `Action` has a corresponding `Signature`. -pub const AUTHORIZED_ACTION_SIZE: u64 = ACTION_SIZE + SPEND_AUTH_SIG_SIZE; +/* +struct AssertBlockSizeLimit; + +impl AssertBlockSizeLimit { + const OK: () = assert!(N < (1 << 16), "must be less than 2^16"); +} +*/ /// The maximum number of orchard actions in a valid Zcash on-chain transaction V5. /// /// If a transaction contains more actions than can fit in maximally large block, it might be /// valid on the network and in the mempool, but it can never be mined into a block. So /// rejecting these large edge-case transactions can never break consensus. -impl TrustedPreallocate for Action { +impl TrustedPreallocate for Action { fn max_allocation() -> u64 { - // Since a serialized Vec uses at least one byte for its length, - // and the signature is required, - // a valid max allocation can never exceed this size - const MAX: u64 = (MAX_BLOCK_BYTES - 1) / AUTHORIZED_ACTION_SIZE; // # Consensus // // > [NU5 onward] nSpendsSapling, nOutputsSapling, and nActionsOrchard MUST all be less than 2^16. @@ -196,15 +265,28 @@ impl TrustedPreallocate for Action { // This acts as nActionsOrchard and is therefore subject to the rule. // The maximum value is actually smaller due to the block size limit, // but we ensure the 2^16 limit with a static assertion. - static_assertions::const_assert!(MAX < (1 << 16)); - MAX + // + // TODO: FIXME: find a better way to use static check (see https://github.com/nvzqz/static-assertions/issues/40, + // https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307)? + // The following expression doesn't work for generics, so a workaround with _ACTION_MAX_ALLOCATION_OK in + // AuthorizedAction impl is used instead: + // static_assertions::const_assert!(AuthorizedAction::::ACTION_MAX_ALLOCATION < (1 << 16)); + AuthorizedAction::::ACTION_MAX_ALLOCATION } } impl TrustedPreallocate for Signature { fn max_allocation() -> u64 { // Each signature must have a corresponding action. - Action::max_allocation() + #[cfg(not(feature = "tx-v6"))] + let result = Action::::max_allocation(); + + // TODO: FIXME: Check this: V6 is used as it provides the max size of the action. + // So it's used even for V5 - is this correct? + #[cfg(feature = "tx-v6")] + let result = Action::::max_allocation(); + + result } } diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index ada329140f1..9dbc8a8e39b 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -53,6 +53,56 @@ use crate::{ value_balance::{ValueBalance, ValueBalanceError}, }; +// FIXME: doc this +macro_rules! shielded_data_iter { + ($self:expr, $mapper:expr) => { + match $self { + // Maybe Orchard shielded data + Transaction::V5 { + orchard_shielded_data, + .. + } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), + + // FIXME: process V6 properly? + Transaction::V6 { + orchard_shielded_data, + .. + } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), + + // No Orchard shielded data + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => Box::new(std::iter::empty()), + } + }; +} + +// FIXME: doc this +macro_rules! shielded_data_field { + ($self:expr, $field:ident) => { + match $self { + // Maybe Orchard shielded data + Transaction::V5 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_ref().map(|data| data.$field), + + // FIXME: process V6 properly? + Transaction::V6 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_ref().map(|data| data.$field), + + // No Orchard shielded data + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => None, + } + }; +} + /// A Zcash transaction. /// /// A transaction is an encoded data structure that facilitates the transfer of @@ -140,7 +190,7 @@ pub enum Transaction { /// The sapling shielded data for this transaction, if any. sapling_shielded_data: Option>, /// The orchard data for this transaction, if any. - orchard_shielded_data: Option, + orchard_shielded_data: Option>, }, // FIXME: implement V6 properly (now it's just a coipy of V5) /// A `version = 6` transaction , which supports Orchard ZSA, Orchard Vanille, Sapling and @@ -161,8 +211,10 @@ pub enum Transaction { outputs: Vec, /// The sapling shielded data for this transaction, if any. sapling_shielded_data: Option>, - /// The orchard data for this transaction, if any. - orchard_shielded_data: Option, + /// The ZSA orchard shielded data for this transaction, if any. + orchard_shielded_data: Option>, + /// The ZSA issuance data for this transaction, if any. + orchard_zsa_issue_data: Option, }, } @@ -1017,96 +1069,52 @@ impl Transaction { // orchard - /// Access the [`orchard::ShieldedData`] in this transaction, - /// regardless of version. - pub fn orchard_shielded_data(&self) -> Option<&orchard::ShieldedData> { - match self { - // Maybe Orchard shielded data - Transaction::V5 { - orchard_shielded_data, - .. - } => orchard_shielded_data.as_ref(), - - // FIXME: Support V6/OrchardZSA propetly. - Transaction::V6 { - orchard_shielded_data, - .. - } => orchard_shielded_data.as_ref(), - - // No Orchard shielded data - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { .. } => None, - } - } - - /// Modify the [`orchard::ShieldedData`] in this transaction, - /// regardless of version. - #[cfg(any(test, feature = "proptest-impl"))] - pub fn orchard_shielded_data_mut(&mut self) -> Option<&mut orchard::ShieldedData> { - match self { - Transaction::V5 { - orchard_shielded_data: Some(orchard_shielded_data), - .. - } => Some(orchard_shielded_data), - - // FIXME: Support V6/OrchardZSA propetly. - Transaction::V6 { - orchard_shielded_data: Some(orchard_shielded_data), - .. - } => Some(orchard_shielded_data), - - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { .. } - | Transaction::V5 { - orchard_shielded_data: None, - .. - } - | Transaction::V6 { - orchard_shielded_data: None, - .. - } => None, - } - } - /// Iterate over the [`orchard::Action`]s in this transaction, if there are any, /// regardless of version. - pub fn orchard_actions(&self) -> impl Iterator { - self.orchard_shielded_data() - .into_iter() - .flat_map(orchard::ShieldedData::actions) + pub fn orchard_actions(&self) -> Box + '_> { + shielded_data_iter!(self, orchard::ShieldedData::action_commons) } /// Access the [`orchard::Nullifier`]s in this transaction, if there are any, /// regardless of version. - pub fn orchard_nullifiers(&self) -> impl Iterator { - self.orchard_shielded_data() - .into_iter() - .flat_map(orchard::ShieldedData::nullifiers) + pub fn orchard_nullifiers(&self) -> Box + '_> { + shielded_data_iter!(self, orchard::ShieldedData::nullifiers) } /// Access the note commitments in this transaction, if there are any, /// regardless of version. - pub fn orchard_note_commitments(&self) -> impl Iterator { - self.orchard_shielded_data() - .into_iter() - .flat_map(orchard::ShieldedData::note_commitments) + pub fn orchard_note_commitments(&self) -> Box + '_> { + shielded_data_iter!(self, orchard::ShieldedData::note_commitments) } /// Access the [`orchard::Flags`] in this transaction, if there is any, /// regardless of version. pub fn orchard_flags(&self) -> Option { - self.orchard_shielded_data() - .map(|orchard_shielded_data| orchard_shielded_data.flags) + shielded_data_field!(self, flags) } /// Return if the transaction has any Orchard shielded data, /// regardless of version. pub fn has_orchard_shielded_data(&self) -> bool { - self.orchard_shielded_data().is_some() + match self { + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => false, + Transaction::V5 { + orchard_shielded_data, + .. + } => orchard_shielded_data.is_some(), + Transaction::V6 { + orchard_shielded_data, + .. + } => orchard_shielded_data.is_some(), + } + } + + // FIXME: add doc + pub fn orchard_shared_anchor(&self) -> Option { + shielded_data_field!(self, shared_anchor) } // value balances @@ -1501,10 +1509,8 @@ impl Transaction { /// /// pub fn orchard_value_balance(&self) -> ValueBalance { - let orchard_value_balance = self - .orchard_shielded_data() - .map(|shielded_data| shielded_data.value_balance) - .unwrap_or_else(Amount::zero); + let orchard_value_balance = + shielded_data_field!(self, value_balance).unwrap_or_else(Amount::zero); ValueBalance::from_orchard_amount(orchard_value_balance) } @@ -1515,8 +1521,30 @@ impl Transaction { /// See `orchard_value_balance` for details. #[cfg(any(test, feature = "proptest-impl"))] pub fn orchard_value_balance_mut(&mut self) -> Option<&mut Amount> { - self.orchard_shielded_data_mut() - .map(|shielded_data| &mut shielded_data.value_balance) + match self { + Transaction::V5 { + orchard_shielded_data: Some(orchard_shielded_data), + .. + } => Some(&mut orchard_shielded_data.value_balance), + + Transaction::V6 { + orchard_shielded_data: Some(orchard_shielded_data), + .. + } => Some(&mut orchard_shielded_data.value_balance), + + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } + | Transaction::V5 { + orchard_shielded_data: None, + .. + } + | Transaction::V6 { + orchard_shielded_data: None, + .. + } => None, + } } /// Returns the value balances for this transaction using the provided transparent outputs. diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index f37698d6118..00464e1d320 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -11,6 +11,7 @@ use reddsa::{orchard::Binding, orchard::SpendAuth, Signature}; use crate::{ amount, block::MAX_BLOCK_BYTES, + orchard::OrchardFlavorExt, parameters::{ OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, TX_V5_VERSION_GROUP_ID, TX_V6_VERSION_GROUP_ID, @@ -326,7 +327,7 @@ impl ZcashDeserialize for Option> { } } -impl ZcashSerialize for Option { +impl ZcashSerialize for Option> { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { match self { None => { @@ -342,14 +343,15 @@ impl ZcashSerialize for Option { orchard_shielded_data.zcash_serialize(&mut writer)?; } } + Ok(()) } } -impl ZcashSerialize for orchard::ShieldedData { +impl ZcashSerialize for orchard::ShieldedData { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { // Split the AuthorizedAction - let (actions, sigs): (Vec, Vec>) = self + let (actions, sigs): (Vec>, Vec>) = self .actions .iter() .cloned() @@ -377,16 +379,20 @@ impl ZcashSerialize for orchard::ShieldedData { // Denoted as `bindingSigOrchard` in the spec. self.binding_sig.zcash_serialize(&mut writer)?; + #[cfg(feature = "tx-v6")] + // Denoted as `vAssetBurn` in the spec (ZIP 230). + self.burn.zcash_serialize(&mut writer)?; + Ok(()) } } // we can't split ShieldedData out of Option deserialization, // because the counts are read along with the arrays. -impl ZcashDeserialize for Option { +impl ZcashDeserialize for Option> { fn zcash_deserialize(mut reader: R) -> Result { // Denoted as `nActionsOrchard` and `vActionsOrchard` in the spec. - let actions: Vec = (&mut reader).zcash_deserialize_into()?; + let actions: Vec> = (&mut reader).zcash_deserialize_into()?; // "The fields flagsOrchard, valueBalanceOrchard, anchorOrchard, sizeProofsOrchard, // proofsOrchard , and bindingSigOrchard are present if and only if nActionsOrchard > 0." @@ -432,7 +438,7 @@ impl ZcashDeserialize for Option { let binding_sig: Signature = (&mut reader).zcash_deserialize_into()?; // Create the AuthorizedAction from deserialized parts - let authorized_actions: Vec = actions + let authorized_actions: Vec> = actions .into_iter() .zip(sigs) .map(|(action, spend_auth_sig)| { @@ -440,11 +446,17 @@ impl ZcashDeserialize for Option { }) .collect(); - let actions: AtLeastOne = authorized_actions.try_into()?; + let actions: AtLeastOne> = authorized_actions.try_into()?; - Ok(Some(orchard::ShieldedData { + // TODO: FIXME: add a proper comment + #[cfg(feature = "tx-v6")] + let burn = (&mut reader).zcash_deserialize_into()?; + + Ok(Some(orchard::ShieldedData:: { flags, value_balance, + #[cfg(feature = "tx-v6")] + burn, shared_anchor, proof, actions, @@ -677,7 +689,6 @@ impl ZcashSerialize for Transaction { orchard_shielded_data.zcash_serialize(&mut writer)?; } - // FIXME: implement a proper serialization for V6 Transaction::V6 { network_upgrade, lock_time, @@ -686,9 +697,11 @@ impl ZcashSerialize for Transaction { outputs, sapling_shielded_data, orchard_shielded_data, + orchard_zsa_issue_data, } => { + // FIXME: fix spec or use another link as the current version of the PDF + // doesn't contain V6 description. // Transaction V6 spec: - // FIXME: specify a proper ref // https://zips.z.cash/protocol/protocol.pdf#txnencoding // Denoted as `nVersionGroupId` in the spec. @@ -723,6 +736,9 @@ impl ZcashSerialize for Transaction { // `flagsOrchard`,`valueBalanceOrchard`, `anchorOrchard`, `sizeProofsOrchard`, // `proofsOrchard`, `vSpendAuthSigsOrchard`, and `bindingSigOrchard`. orchard_shielded_data.zcash_serialize(&mut writer)?; + + // TODO: FIXME: add ref to spec + orchard_zsa_issue_data.zcash_serialize(&mut writer)?; } } Ok(()) @@ -982,8 +998,9 @@ impl ZcashDeserialize for Transaction { } // FIXME: implement a proper deserialization for V6 (6, true) => { + // FIXME: fix spec or use another link as the current version of the PDF + // doesn't contain V6 description. // Transaction V6 spec: - // FIXME: specify a proper ref // https://zips.z.cash/protocol/protocol.pdf#txnencoding // Denoted as `nVersionGroupId` in the spec. @@ -1024,6 +1041,9 @@ impl ZcashDeserialize for Transaction { // `proofsOrchard`, `vSpendAuthSigsOrchard`, and `bindingSigOrchard`. let orchard_shielded_data = (&mut limited_reader).zcash_deserialize_into()?; + // TODO: FIXME: add ref to spec + let orchard_zsa_issue_data = (&mut limited_reader).zcash_deserialize_into()?; + Ok(Transaction::V6 { network_upgrade, lock_time, @@ -1032,6 +1052,7 @@ impl ZcashDeserialize for Transaction { outputs, sapling_shielded_data, orchard_shielded_data, + orchard_zsa_issue_data, }) } (_, _) => Err(SerializationError::Parse("bad tx header")), @@ -1081,6 +1102,11 @@ pub const MIN_TRANSPARENT_TX_V4_SIZE: u64 = MIN_TRANSPARENT_TX_SIZE + 4; /// v5 transactions also have an expiry height and a consensus branch ID. pub const MIN_TRANSPARENT_TX_V5_SIZE: u64 = MIN_TRANSPARENT_TX_SIZE + 4 + 4; +/// The minimum transaction size for v6 transactions. +/// +/// FIXME: specify a proper value and description. +pub const MIN_TRANSPARENT_TX_V6_SIZE: u64 = MIN_TRANSPARENT_TX_V5_SIZE; + /// No valid Zcash message contains more transactions than can fit in a single block /// /// `tx` messages contain a single transaction, and `block` messages are limited to the maximum From e98bb67fc2c36d430ed300c7182446c0b93d46a0 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 18 Sep 2024 11:38:19 +0200 Subject: [PATCH 019/157] Fix compilation errors for unit tests --- zebra-chain/src/orchard.rs | 2 +- zebra-chain/src/orchard/arbitrary.rs | 11 +-- zebra-chain/src/orchard/note/arbitrary.rs | 6 +- zebra-chain/src/orchard/note/ciphertexts.rs | 2 +- zebra-chain/src/orchard/shielded_data.rs | 2 +- zebra-chain/src/orchard/tests/preallocate.rs | 21 +++--- zebra-chain/src/transaction.rs | 70 ++++++++----------- zebra-chain/src/transaction/arbitrary.rs | 20 ++++-- zebra-chain/src/transaction/serialize.rs | 4 +- zebra-consensus/src/primitives/halo2.rs | 10 +-- zebra-consensus/src/primitives/halo2/tests.rs | 36 +++++----- zebra-consensus/src/transaction.rs | 18 ++--- zebra-consensus/src/transaction/check.rs | 4 +- zebra-consensus/src/transaction/tests.rs | 6 +- zebra-state/src/service/check/anchors.rs | 16 ++--- .../finalized_state/zebra_db/arbitrary.rs | 4 +- .../src/service/non_finalized_state/chain.rs | 16 +++-- .../components/mempool/storage/tests/prop.rs | 20 ++++-- 18 files changed, 136 insertions(+), 132 deletions(-) diff --git a/zebra-chain/src/orchard.rs b/zebra-chain/src/orchard.rs index 55de746336d..1eff5f2a3c6 100644 --- a/zebra-chain/src/orchard.rs +++ b/zebra-chain/src/orchard.rs @@ -23,8 +23,8 @@ pub use address::Address; pub use commitment::{CommitmentRandomness, NoteCommitment, ValueCommitment}; pub use keys::Diversifier; pub use note::{EncryptedNote, Note, Nullifier, WrappedNoteKey}; +pub use orchard_flavor_ext::{OrchardFlavorExt, OrchardVanilla, OrchardZSA}; pub use shielded_data::{AuthorizedAction, Flags, ShieldedData}; pub(crate) use crate::orchard_zsa::issuance::IssueData; -pub(crate) use orchard_flavor_ext::{OrchardFlavorExt, OrchardVanilla, OrchardZSA}; pub(crate) use shielded_data::ActionCommon; diff --git a/zebra-chain/src/orchard/arbitrary.rs b/zebra-chain/src/orchard/arbitrary.rs index 7a6544606f8..54572085f11 100644 --- a/zebra-chain/src/orchard/arbitrary.rs +++ b/zebra-chain/src/orchard/arbitrary.rs @@ -10,17 +10,18 @@ use reddsa::{orchard::SpendAuth, Signature, SigningKey, VerificationKey, Verific use proptest::{array, collection::vec, prelude::*}; use super::{ - keys::*, note, tree, Action, AuthorizedAction, Flags, NoteCommitment, ValueCommitment, + keys::*, note, tree, Action, AuthorizedAction, Flags, NoteCommitment, OrchardFlavorExt, + OrchardVanilla, ValueCommitment, }; -impl Arbitrary for Action { +impl Arbitrary for Action { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { ( any::(), any::(), - any::(), + any::>(), any::(), ) .prop_map(|(nullifier, rk, enc_ciphertext, out_ciphertext)| Self { @@ -54,11 +55,11 @@ impl Arbitrary for note::Nullifier { type Strategy = BoxedStrategy; } -impl Arbitrary for AuthorizedAction { +impl Arbitrary for AuthorizedAction { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - (any::(), any::()) + (any::>(), any::()) .prop_map(|(action, spend_auth_sig)| Self { action, spend_auth_sig: spend_auth_sig.0, diff --git a/zebra-chain/src/orchard/note/arbitrary.rs b/zebra-chain/src/orchard/note/arbitrary.rs index e9365de80c1..7968877d9bd 100644 --- a/zebra-chain/src/orchard/note/arbitrary.rs +++ b/zebra-chain/src/orchard/note/arbitrary.rs @@ -2,13 +2,13 @@ use proptest::{collection::vec, prelude::*}; use super::*; -impl Arbitrary for EncryptedNote { +impl Arbitrary for EncryptedNote { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - (vec(any::(), 580)) + (vec(any::(), N)) .prop_map(|v| { - let mut bytes = [0; 580]; + let mut bytes = [0; N]; bytes.copy_from_slice(v.as_slice()); Self(bytes) }) diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index f245e47ca7c..3cd1300847c 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -131,7 +131,7 @@ use proptest::prelude::*; proptest! { #[test] - fn encrypted_ciphertext_roundtrip(ec in any::>()) { + fn encrypted_ciphertext_roundtrip(ec in any::>()) { let _init_guard = zebra_test::init(); let mut data = Vec::new(); diff --git a/zebra-chain/src/orchard/shielded_data.rs b/zebra-chain/src/orchard/shielded_data.rs index df09023fe5a..baf98da8c42 100644 --- a/zebra-chain/src/orchard/shielded_data.rs +++ b/zebra-chain/src/orchard/shielded_data.rs @@ -79,7 +79,7 @@ impl ShieldedData { self.actions.actions() } - // FIXME: add a doc comment + /// FIXME: add a doc comment pub fn action_commons(&self) -> impl Iterator + '_ { self.actions.actions().map(|action| action.into()) } diff --git a/zebra-chain/src/orchard/tests/preallocate.rs b/zebra-chain/src/orchard/tests/preallocate.rs index 79f6a16e7d9..6b1fadfce29 100644 --- a/zebra-chain/src/orchard/tests/preallocate.rs +++ b/zebra-chain/src/orchard/tests/preallocate.rs @@ -4,10 +4,7 @@ use reddsa::{orchard::SpendAuth, Signature}; use crate::{ block::MAX_BLOCK_BYTES, - orchard::{ - shielded_data::{ACTION_SIZE, AUTHORIZED_ACTION_SIZE}, - Action, AuthorizedAction, - }, + orchard::{Action, AuthorizedAction, OrchardVanilla}, serialization::{arbitrary::max_allocation_is_big_enough, TrustedPreallocate, ZcashSerialize}, }; @@ -17,16 +14,16 @@ proptest! { /// Confirm that each `AuthorizedAction` takes exactly AUTHORIZED_ACTION_SIZE /// bytes when serialized. #[test] - fn authorized_action_size_is_small_enough(authorized_action in ::arbitrary_with(())) { + fn authorized_action_size_is_small_enough(authorized_action in >::arbitrary_with(())) { let (action, spend_auth_sig) = authorized_action.into_parts(); let mut serialized_len = action.zcash_serialize_to_vec().expect("Serialization to vec must succeed").len(); serialized_len += spend_auth_sig.zcash_serialize_to_vec().expect("Serialization to vec must succeed").len(); - prop_assert!(serialized_len as u64 == AUTHORIZED_ACTION_SIZE) + prop_assert!(serialized_len as u64 == AuthorizedAction::::AUTHORIZED_ACTION_SIZE) } /// Verify trusted preallocation for `AuthorizedAction` and its split fields #[test] - fn authorized_action_max_allocation_is_big_enough(authorized_action in ::arbitrary_with(())) { + fn authorized_action_max_allocation_is_big_enough(authorized_action in >::arbitrary_with(())) { let (action, spend_auth_sig) = authorized_action.into_parts(); let ( @@ -37,12 +34,14 @@ proptest! { ) = max_allocation_is_big_enough(action); // Calculate the actual size of all required Action fields - prop_assert!((smallest_disallowed_serialized_len as u64)/ACTION_SIZE*AUTHORIZED_ACTION_SIZE >= MAX_BLOCK_BYTES); - prop_assert!((largest_allowed_serialized_len as u64)/ACTION_SIZE*AUTHORIZED_ACTION_SIZE <= MAX_BLOCK_BYTES); + prop_assert!((smallest_disallowed_serialized_len as u64)/AuthorizedAction::::ACTION_SIZE* + AuthorizedAction::::AUTHORIZED_ACTION_SIZE >= MAX_BLOCK_BYTES); + prop_assert!((largest_allowed_serialized_len as u64)/AuthorizedAction::::ACTION_SIZE* + AuthorizedAction::::AUTHORIZED_ACTION_SIZE <= MAX_BLOCK_BYTES); // Check the serialization limits for `Action` - prop_assert!(((smallest_disallowed_vec_len - 1) as u64) == Action::max_allocation()); - prop_assert!((largest_allowed_vec_len as u64) == Action::max_allocation()); + prop_assert!(((smallest_disallowed_vec_len - 1) as u64) == Action::::max_allocation()); + prop_assert!((largest_allowed_vec_len as u64) == Action::::max_allocation()); prop_assert!((largest_allowed_serialized_len as u64) <= MAX_BLOCK_BYTES); let ( diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 9dbc8a8e39b..49e8fdbe33c 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -54,51 +54,49 @@ use crate::{ }; // FIXME: doc this -macro_rules! shielded_data_iter { +// Move down +macro_rules! orchard_shielded_data_iter { ($self:expr, $mapper:expr) => { match $self { - // Maybe Orchard shielded data + // No Orchard shielded data + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => Box::new(std::iter::empty()), + Transaction::V5 { orchard_shielded_data, .. } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), - // FIXME: process V6 properly? Transaction::V6 { orchard_shielded_data, .. } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), - - // No Orchard shielded data - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { .. } => Box::new(std::iter::empty()), } }; } // FIXME: doc this -macro_rules! shielded_data_field { +// Move down +macro_rules! orchard_shielded_data_field { ($self:expr, $field:ident) => { match $self { - // Maybe Orchard shielded data + // No Orchard shielded data + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => None, + Transaction::V5 { orchard_shielded_data, .. } => orchard_shielded_data.as_ref().map(|data| data.$field), - // FIXME: process V6 properly? Transaction::V6 { orchard_shielded_data, .. } => orchard_shielded_data.as_ref().map(|data| data.$field), - - // No Orchard shielded data - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { .. } => None, } }; } @@ -1072,49 +1070,37 @@ impl Transaction { /// Iterate over the [`orchard::Action`]s in this transaction, if there are any, /// regardless of version. pub fn orchard_actions(&self) -> Box + '_> { - shielded_data_iter!(self, orchard::ShieldedData::action_commons) + orchard_shielded_data_iter!(self, orchard::ShieldedData::action_commons) } /// Access the [`orchard::Nullifier`]s in this transaction, if there are any, /// regardless of version. pub fn orchard_nullifiers(&self) -> Box + '_> { - shielded_data_iter!(self, orchard::ShieldedData::nullifiers) + orchard_shielded_data_iter!(self, orchard::ShieldedData::nullifiers) } /// Access the note commitments in this transaction, if there are any, /// regardless of version. pub fn orchard_note_commitments(&self) -> Box + '_> { - shielded_data_iter!(self, orchard::ShieldedData::note_commitments) + orchard_shielded_data_iter!(self, orchard::ShieldedData::note_commitments) } /// Access the [`orchard::Flags`] in this transaction, if there is any, /// regardless of version. pub fn orchard_flags(&self) -> Option { - shielded_data_field!(self, flags) + // FIXME: remove this line with_shielded_data!(self, |data: impl orchard::ShieldedDataCommon| data.flags) + orchard_shielded_data_field!(self, flags) + } + + // FIXME: add doc + pub fn orchard_shared_anchor(&self) -> Option { + orchard_shielded_data_field!(self, shared_anchor) } /// Return if the transaction has any Orchard shielded data, /// regardless of version. pub fn has_orchard_shielded_data(&self) -> bool { - match self { - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { .. } => false, - Transaction::V5 { - orchard_shielded_data, - .. - } => orchard_shielded_data.is_some(), - Transaction::V6 { - orchard_shielded_data, - .. - } => orchard_shielded_data.is_some(), - } - } - - // FIXME: add doc - pub fn orchard_shared_anchor(&self) -> Option { - shielded_data_field!(self, shared_anchor) + self.orchard_flags().is_some() } // value balances @@ -1510,7 +1496,7 @@ impl Transaction { /// pub fn orchard_value_balance(&self) -> ValueBalance { let orchard_value_balance = - shielded_data_field!(self, value_balance).unwrap_or_else(Amount::zero); + orchard_shielded_data_field!(self, value_balance).unwrap_or_else(Amount::zero); ValueBalance::from_orchard_amount(orchard_value_balance) } diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 73aac10a23d..753c68d2fe0 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -141,7 +141,7 @@ impl Transaction { transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS), vec(any::(), 0..MAX_ARBITRARY_ITEMS), option::of(any::>()), - option::of(any::()), + option::of(any::>()), ) .prop_map( move |( @@ -697,7 +697,7 @@ impl Arbitrary for sapling::TransferData { type Strategy = BoxedStrategy; } -impl Arbitrary for orchard::ShieldedData { +impl Arbitrary for orchard::ShieldedData { type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { @@ -707,7 +707,7 @@ impl Arbitrary for orchard::ShieldedData { any::(), any::(), vec( - any::(), + any::>(), 1..MAX_ARBITRARY_ITEMS, ), any::(), @@ -722,6 +722,7 @@ impl Arbitrary for orchard::ShieldedData { .try_into() .expect("arbitrary vector size range produces at least one action"), binding_sig: binding_sig.0, + burn: Default::default(), }, ) .boxed() @@ -923,7 +924,7 @@ pub fn transaction_to_fake_v5( outputs, lock_time, sapling_shielded_data, - orchard_shielded_data, + orchard_shielded_data: _, .. } => V5 { network_upgrade: block_nu, @@ -932,7 +933,10 @@ pub fn transaction_to_fake_v5( lock_time: *lock_time, expiry_height: height, sapling_shielded_data: sapling_shielded_data.clone(), - orchard_shielded_data: orchard_shielded_data.clone(), + // FIXME: is it possible to convert V6 shielded data to V5? + // FIXME: add another function for V6, like transaction_to_fake_v6? + //orchard_shielded_data: orchard_shielded_data.clone(), + orchard_shielded_data: None, }, } } @@ -1036,6 +1040,7 @@ pub fn transactions_from_blocks<'a>( }) } +// FIXME: make it a generic to support V6? /// Modify a V5 transaction to insert fake Orchard shielded data. /// /// Creates a fake instance of [`orchard::ShieldedData`] with one fake action. Note that both the @@ -1050,7 +1055,7 @@ pub fn transactions_from_blocks<'a>( /// Panics if the transaction to be modified is not V5. pub fn insert_fake_orchard_shielded_data( transaction: &mut Transaction, -) -> &mut orchard::ShieldedData { +) -> &mut orchard::ShieldedData { // Create a dummy action let mut runner = TestRunner::default(); let dummy_action = orchard::Action::arbitrary() @@ -1065,13 +1070,14 @@ pub fn insert_fake_orchard_shielded_data( }; // Place the dummy action inside the Orchard shielded data - let dummy_shielded_data = orchard::ShieldedData { + let dummy_shielded_data = orchard::ShieldedData:: { flags: orchard::Flags::empty(), value_balance: Amount::try_from(0).expect("invalid transaction amount"), shared_anchor: orchard::tree::Root::default(), proof: Halo2Proof(vec![]), actions: at_least_one![dummy_authorized_action], binding_sig: Signature::from([0u8; 64]), + burn: Default::default(), }; // Replace the shielded data in the transaction diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 00464e1d320..e851bb158cf 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -1104,8 +1104,8 @@ pub const MIN_TRANSPARENT_TX_V5_SIZE: u64 = MIN_TRANSPARENT_TX_SIZE + 4 + 4; /// The minimum transaction size for v6 transactions. /// -/// FIXME: specify a proper value and description. -pub const MIN_TRANSPARENT_TX_V6_SIZE: u64 = MIN_TRANSPARENT_TX_V5_SIZE; +/// FIXME: uncomment this and specify a proper value and description. +//pub const MIN_TRANSPARENT_TX_V6_SIZE: u64 = MIN_TRANSPARENT_TX_V5_SIZE; /// No valid Zcash message contains more transactions than can fit in a single block /// diff --git a/zebra-consensus/src/primitives/halo2.rs b/zebra-consensus/src/primitives/halo2.rs index 447d9bbd449..ab88f6cbde4 100644 --- a/zebra-consensus/src/primitives/halo2.rs +++ b/zebra-consensus/src/primitives/halo2.rs @@ -10,7 +10,7 @@ use std::{ use futures::{future::BoxFuture, FutureExt}; use once_cell::sync::Lazy; -use orchard::{circuit::VerifyingKey, orchard_flavor::OrchardVanilla}; +use orchard::circuit::VerifyingKey; use rand::{thread_rng, CryptoRng, RngCore}; use thiserror::Error; @@ -19,6 +19,8 @@ use tower::{util::ServiceFn, Service}; use tower_batch_control::{Batch, BatchControl}; use tower_fallback::Fallback; +use zebra_chain::orchard::{OrchardFlavorExt, OrchardVanilla}; + use crate::BoxError; use super::{spawn_fifo, spawn_fifo_and_convert}; @@ -76,7 +78,7 @@ pub type ItemVerifyingKey = VerifyingKey; lazy_static::lazy_static! { /// The halo2 proof verifying key. // FIXME: support OrchardZSA? - pub static ref VERIFYING_KEY: ItemVerifyingKey = ItemVerifyingKey::build::(); + pub static ref VERIFYING_KEY: ItemVerifyingKey = ItemVerifyingKey::build::<::Flavor>(); } // === TEMPORARY BATCH HALO2 SUBSTITUTE === @@ -131,8 +133,8 @@ impl BatchVerifier { // === END TEMPORARY BATCH HALO2 SUBSTITUTE === -impl From<&zebra_chain::orchard::ShieldedData> for Item { - fn from(shielded_data: &zebra_chain::orchard::ShieldedData) -> Item { +impl From<&zebra_chain::orchard::ShieldedData> for Item { + fn from(shielded_data: &zebra_chain::orchard::ShieldedData) -> Item { use orchard::{circuit, note, primitives::redpallas, tree, value}; let anchor = tree::Anchor::from_bytes(shielded_data.shared_anchor.into()).unwrap(); diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index 9b5c367e640..12f2635b3b2 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -12,14 +12,13 @@ use orchard::{ circuit::ProvingKey, keys::{FullViewingKey, Scope, SpendingKey}, note::AssetBase, - orchard_flavor::OrchardVanilla, value::NoteValue, Anchor, Bundle, }; use rand::rngs::OsRng; use zebra_chain::{ - orchard::ShieldedData, + orchard::{OrchardFlavorExt, OrchardVanilla, ShieldedData}, serialization::{ZcashDeserializeInto, ZcashSerialize}, }; @@ -28,7 +27,7 @@ use crate::primitives::halo2::*; // FIXME: add support for OrchardZSA (see OrchardVanilla and AssetBase::native() usage below) #[allow(dead_code, clippy::print_stdout)] fn generate_test_vectors() { - let proving_key = ProvingKey::build::(); + let proving_key = ProvingKey::build::<::Flavor>(); let rng = OsRng; @@ -41,7 +40,7 @@ fn generate_test_vectors() { let anchor_bytes = [0; 32]; let note_value = 10; - let shielded_data: Vec = (1..=4) + let shielded_data: Vec> = (1..=4) .map(|num_recipients| { let mut builder = Builder::new( BundleType::Transactional { @@ -63,7 +62,8 @@ fn generate_test_vectors() { .unwrap(); } - let bundle: Bundle<_, i64, OrchardVanilla> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, ::Flavor> = + builder.build(rng).unwrap().unwrap().0; let bundle = bundle .create_proof(&proving_key, rng) @@ -71,7 +71,7 @@ fn generate_test_vectors() { .apply_signatures(rng, [0; 32], &[]) .unwrap(); - zebra_chain::orchard::ShieldedData { + zebra_chain::orchard::ShieldedData:: { flags, value_balance: note_value.try_into().unwrap(), shared_anchor: anchor_bytes.try_into().unwrap(), @@ -82,7 +82,7 @@ fn generate_test_vectors() { .actions() .iter() .map(|a| { - let action = zebra_chain::orchard::Action { + let action = zebra_chain::orchard::Action:: { cv: a.cv_net().to_bytes().try_into().unwrap(), nullifier: a.nullifier().to_bytes().try_into().unwrap(), rk: <[u8; 32]>::from(a.rk()).into(), @@ -91,7 +91,7 @@ fn generate_test_vectors() { // FIXME: support OrchardZSA too, 580 works for OrchardVanilla only! // FIXME: consider more "type safe" way to do the following conversion // (now it goes through &[u8]) - enc_ciphertext: <[u8; 580]>::try_from( + enc_ciphertext: <[u8; OrchardVanilla::ENCRYPTED_NOTE_SIZE]>::try_from( a.encrypted_note().enc_ciphertext.as_ref(), ) .unwrap() @@ -107,6 +107,8 @@ fn generate_test_vectors() { .try_into() .unwrap(), binding_sig: <[u8; 64]>::from(bundle.authorization().binding_signature()).into(), + // FIXME: use a proper value when implementing V6 + burn: Default::default(), } }) .collect(); @@ -121,7 +123,7 @@ fn generate_test_vectors() { async fn verify_orchard_halo2_proofs( verifier: &mut V, - shielded_data: Vec, + shielded_data: Vec>, ) -> Result<(), V::Error> where V: tower::Service, @@ -154,9 +156,10 @@ async fn verify_generated_halo2_proofs() { .clone() .iter() .map(|bytes| { - let maybe_shielded_data: Option = bytes - .zcash_deserialize_into() - .expect("a valid orchard::ShieldedData instance"); + let maybe_shielded_data: Option> = + bytes + .zcash_deserialize_into() + .expect("a valid orchard::ShieldedData instance"); maybe_shielded_data.unwrap() }) .collect(); @@ -183,7 +186,7 @@ async fn verify_generated_halo2_proofs() { async fn verify_invalid_orchard_halo2_proofs( verifier: &mut V, - shielded_data: Vec, + shielded_data: Vec>, ) -> Result<(), V::Error> where V: tower::Service, @@ -221,9 +224,10 @@ async fn correctly_err_on_invalid_halo2_proofs() { .clone() .iter() .map(|bytes| { - let maybe_shielded_data: Option = bytes - .zcash_deserialize_into() - .expect("a valid orchard::ShieldedData instance"); + let maybe_shielded_data: Option> = + bytes + .zcash_deserialize_into() + .expect("a valid orchard::ShieldedData instance"); maybe_shielded_data.unwrap() }) .collect(); diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 5c21ccd494c..0be7fea38f3 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -406,12 +406,7 @@ where orchard_shielded_data, .. } - // FIXME: implement proper V6 verification - | Transaction::V6 { - sapling_shielded_data, - orchard_shielded_data, - .. - }=> Self::verify_v5_transaction( + => Self::verify_v5_transaction( &req, &network, script_verifier, @@ -419,6 +414,13 @@ where sapling_shielded_data, orchard_shielded_data, )?, + // FIXME: implement proper V6 verification + | Transaction::V6 { + .. + } => { + tracing::debug!(?tx, "V6 transaction verification is not supported for now"); + return Err(TransactionError::WrongVersion); + } }; if let Some(unmined_tx) = req.mempool_transaction() { @@ -722,7 +724,7 @@ where script_verifier: script::Verifier, cached_ffi_transaction: Arc, sapling_shielded_data: &Option>, - orchard_shielded_data: &Option, + orchard_shielded_data: &Option>, ) -> Result { let transaction = request.transaction(); let upgrade = request.upgrade(network); @@ -1019,7 +1021,7 @@ where /// Verifies a transaction's Orchard shielded data. fn verify_orchard_shielded_data( - orchard_shielded_data: &Option, + orchard_shielded_data: &Option>, shielded_sighash: &SigHash, ) -> Result { let mut async_checks = AsyncChecks::new(); diff --git a/zebra-consensus/src/transaction/check.rs b/zebra-consensus/src/transaction/check.rs index 66e3d0be595..133c7e80470 100644 --- a/zebra-consensus/src/transaction/check.rs +++ b/zebra-consensus/src/transaction/check.rs @@ -172,8 +172,8 @@ pub fn coinbase_tx_no_prevout_joinsplit_spend(tx: &Transaction) -> Result<(), Tr return Err(TransactionError::CoinbaseHasSpend); } - if let Some(orchard_shielded_data) = tx.orchard_shielded_data() { - if orchard_shielded_data.flags.contains(Flags::ENABLE_SPENDS) { + if let Some(orchard_flags) = tx.orchard_flags() { + if orchard_flags.contains(Flags::ENABLE_SPENDS) { return Err(TransactionError::CoinbaseHasEnableSpendsOrchard); } } diff --git a/zebra-consensus/src/transaction/tests.rs b/zebra-consensus/src/transaction/tests.rs index 0a4c21bb039..5494537edb8 100644 --- a/zebra-consensus/src/transaction/tests.rs +++ b/zebra-consensus/src/transaction/tests.rs @@ -12,7 +12,7 @@ use tower::{service_fn, ServiceExt}; use zebra_chain::{ amount::{Amount, NonNegative}, block::{self, Block, Height}, - orchard::AuthorizedAction, + orchard::{AuthorizedAction, OrchardVanilla}, parameters::{Network, NetworkUpgrade}, primitives::{ed25519, x25519, Groth16Proof}, sapling, @@ -2830,9 +2830,9 @@ fn coinbase_outputs_are_decryptable_for_historical_blocks_for_network( /// Given an Orchard action as a base, fill fields related to note encryption /// from the given test vector and returned the modified action. fn fill_action_with_note_encryption_test_vector( - action: &zebra_chain::orchard::Action, + action: &zebra_chain::orchard::Action, v: &zebra_test::vectors::TestVector, -) -> zebra_chain::orchard::Action { +) -> zebra_chain::orchard::Action { let mut action = action.clone(); action.cv = v.cv_net.try_into().expect("test vector must be valid"); action.cm_x = pallas::Base::from_repr(v.cmx).unwrap(); diff --git a/zebra-state/src/service/check/anchors.rs b/zebra-state/src/service/check/anchors.rs index 5f6ee293e34..b4a53c8f176 100644 --- a/zebra-state/src/service/check/anchors.rs +++ b/zebra-state/src/service/check/anchors.rs @@ -88,25 +88,21 @@ fn sapling_orchard_anchors_refer_to_final_treestates( // > earlier block’s final Orchard treestate. // // - if let Some(orchard_shielded_data) = transaction.orchard_shielded_data() { + if let Some(shared_anchor) = transaction.orchard_shared_anchor() { tracing::debug!( - ?orchard_shielded_data.shared_anchor, + ?shared_anchor, ?tx_index_in_block, ?height, "observed orchard anchor", ); if !parent_chain - .map(|chain| { - chain - .orchard_anchors - .contains(&orchard_shielded_data.shared_anchor) - }) + .map(|chain| chain.orchard_anchors.contains(&shared_anchor)) .unwrap_or(false) - && !finalized_state.contains_orchard_anchor(&orchard_shielded_data.shared_anchor) + && !finalized_state.contains_orchard_anchor(&shared_anchor) { return Err(ValidateContextError::UnknownOrchardAnchor { - anchor: orchard_shielded_data.shared_anchor, + anchor: shared_anchor, height, tx_index_in_block, transaction_hash, @@ -114,7 +110,7 @@ fn sapling_orchard_anchors_refer_to_final_treestates( } tracing::debug!( - ?orchard_shielded_data.shared_anchor, + ?shared_anchor, ?tx_index_in_block, ?height, "validated orchard anchor", diff --git a/zebra-state/src/service/finalized_state/zebra_db/arbitrary.rs b/zebra-state/src/service/finalized_state/zebra_db/arbitrary.rs index bbe0e026d8c..39bf082d43d 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/arbitrary.rs +++ b/zebra-state/src/service/finalized_state/zebra_db/arbitrary.rs @@ -66,8 +66,8 @@ impl ZebraDb { } // Orchard - if let Some(orchard_shielded_data) = transaction.orchard_shielded_data() { - batch.zs_insert(&orchard_anchors, orchard_shielded_data.shared_anchor, ()); + if let Some(shared_anchor) = transaction.orchard_shared_anchor() { + batch.zs_insert(&orchard_anchors, shared_anchor, ()); } } diff --git a/zebra-state/src/service/non_finalized_state/chain.rs b/zebra-state/src/service/non_finalized_state/chain.rs index dce9c783ec8..4539eb6aaa0 100644 --- a/zebra-state/src/service/non_finalized_state/chain.rs +++ b/zebra-state/src/service/non_finalized_state/chain.rs @@ -1525,7 +1525,7 @@ impl Chain { inputs, outputs, sapling_shielded_data, - orchard_shielded_data, + orchard_shielded_data: _, .. } => ( inputs, @@ -1533,7 +1533,8 @@ impl Chain { &None, &None, sapling_shielded_data, - orchard_shielded_data, + // FIXME: support V6 shielded data? + &None, //orchard_shielded_data, ), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!( "older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint", @@ -1700,7 +1701,7 @@ impl UpdateWith for Chain { inputs, outputs, sapling_shielded_data, - orchard_shielded_data, + orchard_shielded_data: _, .. } => ( inputs, @@ -1708,7 +1709,8 @@ impl UpdateWith for Chain { &None, &None, sapling_shielded_data, - orchard_shielded_data, + // FIXME: support V6 shielded data? + &None, //orchard_shielded_data, ), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!( "older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint", @@ -2045,11 +2047,11 @@ where } } -impl UpdateWith> for Chain { +impl UpdateWith>> for Chain { #[instrument(skip(self, orchard_shielded_data))] fn update_chain_tip_with( &mut self, - orchard_shielded_data: &Option, + orchard_shielded_data: &Option>, ) -> Result<(), ValidateContextError> { if let Some(orchard_shielded_data) = orchard_shielded_data { // We do note commitment tree updates in parallel rayon threads. @@ -2070,7 +2072,7 @@ impl UpdateWith> for Chain { #[instrument(skip(self, orchard_shielded_data))] fn revert_chain_with( &mut self, - orchard_shielded_data: &Option, + orchard_shielded_data: &Option>, _position: RevertPosition, ) { if let Some(orchard_shielded_data) = orchard_shielded_data { diff --git a/zebrad/src/components/mempool/storage/tests/prop.rs b/zebrad/src/components/mempool/storage/tests/prop.rs index 98abdb2b8e8..2dde9d1d470 100644 --- a/zebrad/src/components/mempool/storage/tests/prop.rs +++ b/zebrad/src/components/mempool/storage/tests/prop.rs @@ -712,12 +712,14 @@ impl SpendConflictTestInput { Transaction::V5 { orchard_shielded_data, .. - } - | Transaction::V6 { - orchard_shielded_data, - .. } => Self::remove_orchard_actions_with_conflicts(orchard_shielded_data, &conflicts), + // FIXME: implement for V6 + Transaction::V6 { + orchard_shielded_data: _, + .. + } => {} + // No Spends Transaction::V1 { .. } | Transaction::V2 { .. } @@ -732,7 +734,7 @@ impl SpendConflictTestInput { /// /// This may clear the entire shielded data. fn remove_orchard_actions_with_conflicts( - maybe_shielded_data: &mut Option, + maybe_shielded_data: &mut Option>, conflicts: &HashSet, ) { if let Some(shielded_data) = maybe_shielded_data.take() { @@ -789,10 +791,11 @@ struct SaplingSpendConflict { fallback_shielded_data: DisplayToDebug>, } +// FIXME: make it a generic to support V6 /// A conflict caused by revealing the same Orchard nullifier. #[derive(Arbitrary, Clone, Debug)] struct OrchardSpendConflict { - new_shielded_data: DisplayToDebug, + new_shielded_data: DisplayToDebug>, } impl SpendConflictForTransactionV4 { @@ -938,7 +941,10 @@ impl OrchardSpendConflict { /// the new action is inserted in the transaction. /// /// The transaction will then conflict with any other transaction with the same new nullifier. - pub fn apply_to(self, orchard_shielded_data: &mut Option) { + pub fn apply_to( + self, + orchard_shielded_data: &mut Option>, + ) { if let Some(shielded_data) = orchard_shielded_data.as_mut() { shielded_data.actions.first_mut().action.nullifier = self.new_shielded_data.actions.first().action.nullifier; From dd741e943c26f444c73d014015c7a1840b288654 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 18 Sep 2024 11:48:29 +0200 Subject: [PATCH 020/157] Add missed files --- zebra-chain/src/orchard/orchard_flavor_ext.rs | 84 ++++++ zebra-chain/src/orchard_zsa.rs | 7 + zebra-chain/src/orchard_zsa/burn.rs | 80 ++++++ zebra-chain/src/orchard_zsa/issuance.rs | 260 ++++++++++++++++++ zebra-chain/src/orchard_zsa/serialize.rs | 23 ++ 5 files changed, 454 insertions(+) create mode 100644 zebra-chain/src/orchard/orchard_flavor_ext.rs create mode 100644 zebra-chain/src/orchard_zsa.rs create mode 100644 zebra-chain/src/orchard_zsa/burn.rs create mode 100644 zebra-chain/src/orchard_zsa/issuance.rs create mode 100644 zebra-chain/src/orchard_zsa/serialize.rs diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs new file mode 100644 index 00000000000..f8ce25d0ed5 --- /dev/null +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -0,0 +1,84 @@ +//! This module defines traits and structures for supporting the Orchard Shielded Protocol +//! for `V5` and `V6` versions of the transaction. +use std::{fmt::Debug, io}; + +use serde::{de::DeserializeOwned, Serialize}; + +#[cfg(any(test, feature = "proptest-impl"))] +use proptest_derive::Arbitrary; + +use orchard::{note_encryption::OrchardDomainCommon, orchard_flavor}; + +use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; + +use super::note; + +#[cfg(feature = "tx-v6")] +use crate::orchard_zsa::burn::BurnItem; + +/// A trait representing compile-time settings of Orchard Shielded Protocol used in +/// the transactions `V5` and `V6`. +pub trait OrchardFlavorExt: Clone + Debug { + /// A type representing an encrypted note for this protocol version. + /// A type representing an encrypted note for this protocol version. + type EncryptedNote: Clone + + Debug + + PartialEq + + Eq + + DeserializeOwned + + Serialize + + ZcashDeserialize + + ZcashSerialize; + + /// FIXME: add doc + type Flavor: orchard_flavor::OrchardFlavor; + + /// The size of the encrypted note for this protocol version. + const ENCRYPTED_NOTE_SIZE: usize = Self::Flavor::ENC_CIPHERTEXT_SIZE; + + /// A type representing a burn field for this protocol version. + type BurnType: Clone + Debug + Default + ZcashDeserialize + ZcashSerialize; +} + +/// A structure representing a tag for Orchard protocol variant used for the transaction version `V5`. +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] +pub struct OrchardVanilla; + +/// A structure representing a tag for Orchard protocol variant used for the transaction version `V6` +/// (which ZSA features support). +#[cfg(feature = "tx-v6")] +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] +#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] +pub struct OrchardZSA; + +/// A special marker type indicating the absence of a burn field in Orchard ShieldedData for `V5` transactions. +/// Useful for unifying ShieldedData serialization and deserialization implementations across various +/// Orchard protocol variants (i.e. various transaction versions). +#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize)] +pub struct NoBurn; + +impl ZcashSerialize for NoBurn { + fn zcash_serialize(&self, mut _writer: W) -> Result<(), io::Error> { + Ok(()) + } +} + +impl ZcashDeserialize for NoBurn { + fn zcash_deserialize(mut _reader: R) -> Result { + Ok(Self) + } +} + +impl OrchardFlavorExt for OrchardVanilla { + type Flavor = orchard_flavor::OrchardVanilla; + type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; + type BurnType = NoBurn; +} + +#[cfg(feature = "tx-v6")] +impl OrchardFlavorExt for OrchardZSA { + type Flavor = orchard_flavor::OrchardZSA; + type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; + type BurnType = Vec; +} diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs new file mode 100644 index 00000000000..9806850daf9 --- /dev/null +++ b/zebra-chain/src/orchard_zsa.rs @@ -0,0 +1,7 @@ +//! Orchard ZSA related functionality. + +pub mod burn; +pub mod issuance; +pub mod serialize; + +pub use burn::BurnItem; diff --git a/zebra-chain/src/orchard_zsa/burn.rs b/zebra-chain/src/orchard_zsa/burn.rs new file mode 100644 index 00000000000..04c878feb49 --- /dev/null +++ b/zebra-chain/src/orchard_zsa/burn.rs @@ -0,0 +1,80 @@ +//! Orchard ZSA burn related functionality. + +use std::io; + +use crate::{ + amount::Amount, + block::MAX_BLOCK_BYTES, + serialization::{SerializationError, TrustedPreallocate, ZcashDeserialize, ZcashSerialize}, +}; + +use orchard::note::AssetBase; + +use super::serialize::ASSET_BASE_SIZE; + +// Sizes of the serialized values for types in bytes (used for TrustedPreallocate impls) +const AMOUNT_SIZE: u64 = 8; +// FIXME: is this a correct way to calculate (simple sum of sizes of components)? +const BURN_ITEM_SIZE: u64 = ASSET_BASE_SIZE + AMOUNT_SIZE; + +/// Represents an Orchard ZSA burn item. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct BurnItem(AssetBase, Amount); + +impl ZcashSerialize for BurnItem { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + let BurnItem(asset_base, amount) = self; + + asset_base.zcash_serialize(&mut writer)?; + amount.zcash_serialize(&mut writer)?; + + Ok(()) + } +} + +impl ZcashDeserialize for BurnItem { + fn zcash_deserialize(mut reader: R) -> Result { + Ok(Self( + AssetBase::zcash_deserialize(&mut reader)?, + Amount::zcash_deserialize(&mut reader)?, + )) + } +} + +impl TrustedPreallocate for BurnItem { + fn max_allocation() -> u64 { + // FIXME: is this a correct calculation way? + // The longest Vec we receive from an honest peer must fit inside a valid block. + // Since encoding the length of the vec takes at least one byte, we use MAX_BLOCK_BYTES - 1 + (MAX_BLOCK_BYTES - 1) / BURN_ITEM_SIZE + } +} + +#[cfg(any(test, feature = "proptest-impl"))] +impl serde::Serialize for BurnItem { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + // FIXME: return custom error with a meaningful description? + (self.0.to_bytes(), &self.1).serialize(serializer) + } +} + +#[cfg(any(test, feature = "proptest-impl"))] +impl<'de> serde::Deserialize<'de> for BurnItem { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + // FIXME: consider another implementation (explicit specifying of [u8; 32] may not look perfect) + let (asset_base_bytes, amount) = <([u8; 32], Amount)>::deserialize(deserializer)?; + // FIXME: return custom error with a meaningful description? + Ok(BurnItem( + // FIXME: duplicates the body of AssetBase::zcash_deserialize? + Option::from(AssetBase::from_bytes(&asset_base_bytes)) + .ok_or_else(|| serde::de::Error::custom("Invalid orchard_zsa AssetBase"))?, + amount, + )) + } +} diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs new file mode 100644 index 00000000000..3e55edcf14d --- /dev/null +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -0,0 +1,260 @@ +//! Orchard ZSA issuance related functionality. + +use std::{fmt::Debug, io}; + +use crate::{ + block::MAX_BLOCK_BYTES, + serialization::{ + zcash_serialize_empty_list, ReadZcashExt, SerializationError, TrustedPreallocate, + ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize, + }, +}; + +use nonempty::NonEmpty; + +// FIXME: needed for "as_bool" only - consider to implement as_bool locally +use bitvec::macros::internal::funty::Fundamental; + +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; + +use orchard::{ + issuance::{IssueAction, IssueBundle, Signed}, + keys::IssuanceValidatingKey, + note::{RandomSeed, Rho}, + primitives::redpallas::{SigType, Signature, SpendAuth}, + value::NoteValue, + Address, Note, +}; + +use super::serialize::ASSET_BASE_SIZE; + +/// Wrapper for `IssueBundle` used in the context of Transaction V6. This allows the implementation of +/// a Serde serializer for unit tests within this crate. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct IssueData(IssueBundle); + +// Sizes of the serialized values for types in bytes (used for TrustedPreallocate impls) +// FIXME: are those values correct (43, 32 etc.)? +//const ISSUANCE_VALIDATING_KEY_SIZE: u64 = 32; +const ADDRESS_SIZE: u64 = 43; +const NULLIFIER_SIZE: u64 = 32; +const NOTE_VALUE_SIZE: u64 = 4; +const RANDOM_SEED_SIZE: u64 = 32; +// FIXME: is this a correct way to calculate (simple sum of sizes of components)? +const NOTE_SIZE: u64 = + ADDRESS_SIZE + NOTE_VALUE_SIZE + ASSET_BASE_SIZE + NULLIFIER_SIZE + RANDOM_SEED_SIZE; + +// FIXME: duplicates ZcashSerialize for reddsa::Signature in transaction/serialize.rs +// (as Signature from oechard_zsa is formally a different type) +impl ZcashSerialize for Signature { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&<[u8; 64]>::from(self))?; + Ok(()) + } +} + +// FIXME: duplicates ZcashDeserialize for reddsa::Signature in transaction/serialize.rs +// (as Signature from oechard_zsa is formally a different type) +impl ZcashDeserialize for Signature { + fn zcash_deserialize(mut reader: R) -> Result { + Ok(reader.read_64_bytes()?.into()) + } +} + +impl ZcashDeserialize for Signed { + fn zcash_deserialize(mut reader: R) -> Result { + let signature = Signature::::zcash_deserialize(&mut reader)?; + Ok(Signed::from_data((&signature).into())) + } +} + +impl ZcashSerialize for IssuanceValidatingKey { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&self.to_bytes()) + } +} + +impl ZcashDeserialize for IssuanceValidatingKey { + fn zcash_deserialize(mut reader: R) -> Result { + IssuanceValidatingKey::from_bytes(&reader.read_32_bytes()?) + .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa IssuanceValidatingKey!")) + } +} + +impl ZcashSerialize for Address { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&self.to_raw_address_bytes()) + } +} + +impl ZcashDeserialize for Address { + fn zcash_deserialize(mut reader: R) -> Result { + let mut bytes = [0u8; ADDRESS_SIZE as usize]; + reader.read_exact(&mut bytes)?; + Option::from(Address::from_raw_address_bytes(&bytes)) + .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa Address!")) + } +} + +impl ZcashSerialize for Rho { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&self.to_bytes()) + } +} + +impl ZcashDeserialize for Rho { + fn zcash_deserialize(mut reader: R) -> Result { + Option::from(Rho::from_bytes(&reader.read_32_bytes()?)) + .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa Rho!")) + } +} + +impl ZcashSerialize for RandomSeed { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(self.as_bytes()) + } +} + +// RandomSeed::zcash_deserialize can't be implemented and used as it requires Nullifier parameter. +// That's why we need to have this function. +fn zcash_deserialize_random_seed( + mut reader: R, + rho: &Rho, +) -> Result { + Option::from(RandomSeed::from_bytes(reader.read_32_bytes()?, rho)) + .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa RandomSeed!")) +} + +impl ZcashSerialize for NoteValue { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + // FIXME: use Amount serializer/deserializer? + writer.write_u64::(self.inner())?; + Ok(()) + } +} + +impl ZcashDeserialize for NoteValue { + fn zcash_deserialize(mut reader: R) -> Result { + Ok(NoteValue::from_raw(reader.read_u64::()?)) + } +} + +impl ZcashSerialize for Note { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + self.recipient().zcash_serialize(&mut writer)?; + self.value().zcash_serialize(&mut writer)?; + self.asset().zcash_serialize(&mut writer)?; + self.rho().zcash_serialize(&mut writer)?; + self.rseed().zcash_serialize(&mut writer)?; + + Ok(()) + } +} + +impl ZcashDeserialize for Note { + fn zcash_deserialize(mut reader: R) -> Result { + let recipient = (&mut reader).zcash_deserialize_into()?; + let value = (&mut reader).zcash_deserialize_into()?; + let asset = (&mut reader).zcash_deserialize_into()?; + let rho = (&mut reader).zcash_deserialize_into()?; + let rseed = zcash_deserialize_random_seed(&mut reader, &rho)?; + + Option::from(Note::from_parts(recipient, value, asset, rho, rseed)) + .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa Note components!")) + } +} + +impl TrustedPreallocate for Note { + fn max_allocation() -> u64 { + // FIXME: is this a correct calculation way? + // The longest Vec we receive from an honest peer must fit inside a valid block. + // Since encoding the length of the vec takes at least one byte, we use MAX_BLOCK_BYTES - 1 + (MAX_BLOCK_BYTES - 1) / NOTE_SIZE + } +} + +impl ZcashSerialize for IssueAction { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_u8(self.is_finalized().as_u8())?; + self.notes().zcash_serialize(&mut writer)?; + self.asset_desc().zcash_serialize(&mut writer)?; + Ok(()) + } +} + +impl ZcashDeserialize for IssueAction { + fn zcash_deserialize(mut reader: R) -> Result { + let finalize = reader.read_u8()?.as_bool(); + let notes = (&mut reader).zcash_deserialize_into()?; + let asset_descr = (&mut reader).zcash_deserialize_into()?; + Ok(IssueAction::from_parts(asset_descr, notes, finalize)) + } +} + +impl TrustedPreallocate for IssueAction { + fn max_allocation() -> u64 { + // FIXME: impl correct calculation + 10 + } +} + +impl ZcashSerialize for IssueBundle { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + // FIXME: try to avoid transforming to Vec (consider implementation of ZcashSerialize for IntoIter generic, + // or use AtLeastOne). + // This is how does it work in librustzcash: + // Vector::write_nonempty(&mut writer, bundle.actions(), |w, action| write_action(action, w))?; + let actions: Vec<_> = self.actions().clone().into(); + + actions.zcash_serialize(&mut writer)?; + self.ik().zcash_serialize(&mut writer)?; + writer.write_all(&<[u8; 64]>::from(self.authorization().signature()))?; + Ok(()) + } +} + +impl ZcashSerialize for Option { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + match self { + None => { + // Denoted as `&Option` in the spec (ZIP 230). + zcash_serialize_empty_list(writer)?; + } + Some(issue_data) => { + issue_data.0.zcash_serialize(&mut writer)?; + } + } + Ok(()) + } +} + +// FIXME: We can't split IssueData out of Option deserialization, +// because the counts are read along with the arrays. +impl ZcashDeserialize for Option { + fn zcash_deserialize(mut reader: R) -> Result { + let actions: Vec<_> = (&mut reader).zcash_deserialize_into()?; + + if actions.is_empty() { + Ok(None) + } else { + let ik = (&mut reader).zcash_deserialize_into()?; + let authorization = (&mut reader).zcash_deserialize_into()?; + + Ok(Some(IssueData(IssueBundle::from_parts( + ik, + NonEmpty::from_vec(actions).ok_or_else(|| { + SerializationError::Parse("Invalid orchard_zsa IssueData - no actions!") + })?, + authorization, + )))) + } + } +} + +#[cfg(any(test, feature = "proptest-impl"))] +impl serde::Serialize for IssueData { + fn serialize(&self, serializer: S) -> Result { + // TODO: FIXME: implement Serde serialization here + "(IssueData)".serialize(serializer) + } +} diff --git a/zebra-chain/src/orchard_zsa/serialize.rs b/zebra-chain/src/orchard_zsa/serialize.rs new file mode 100644 index 00000000000..6afc51e1887 --- /dev/null +++ b/zebra-chain/src/orchard_zsa/serialize.rs @@ -0,0 +1,23 @@ +//! Serialization implementation for selected types from the 'orchard_zsa' crate used in this module. + +use std::io; + +use crate::serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize}; + +use orchard::note::AssetBase; + +// The size of the serialized AssetBase in bytes (used for TrustedPreallocate impls) +pub(crate) const ASSET_BASE_SIZE: u64 = 32; + +impl ZcashSerialize for AssetBase { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&self.to_bytes()) + } +} + +impl ZcashDeserialize for AssetBase { + fn zcash_deserialize(mut reader: R) -> Result { + Option::from(AssetBase::from_bytes(&reader.read_32_bytes()?)) + .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa AssetBase!")) + } +} From c218fc5e6abb4795830484c0c820059b8b5381bd Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 18 Sep 2024 11:58:44 +0200 Subject: [PATCH 021/157] Fix ciphertexts.rs tests compilation error --- zebra-chain/src/orchard/note/ciphertexts.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index 3cd1300847c..369260a197f 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -125,6 +125,9 @@ impl ZcashDeserialize for WrappedNoteKey { } } +#[cfg(test)] +use crate::orchard::orchard_flavor_ext::OrchardFlavorExt; + #[cfg(test)] use proptest::prelude::*; #[cfg(test)] From 4807dd67000b5bae351e1db1687d25b8365f0496 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 18 Sep 2024 11:58:44 +0200 Subject: [PATCH 022/157] Simplify the previous fix for ciphertexts.rs test --- zebra-chain/src/orchard/note/ciphertexts.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index 3cd1300847c..68f92dc667d 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -125,6 +125,9 @@ impl ZcashDeserialize for WrappedNoteKey { } } +#[cfg(test)] +use crate::orchard::OrchardFlavorExt; + #[cfg(test)] use proptest::prelude::*; #[cfg(test)] From 0f9c164f988ef1a23586b241a92124d43b701348 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 18 Sep 2024 12:20:15 +0200 Subject: [PATCH 023/157] Fix tests compilation errors for nullifiers --- .../src/service/check/tests/nullifier.rs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/zebra-state/src/service/check/tests/nullifier.rs b/zebra-state/src/service/check/tests/nullifier.rs index 0392f1c8e79..8a8b17e4fd0 100644 --- a/zebra-state/src/service/check/tests/nullifier.rs +++ b/zebra-state/src/service/check/tests/nullifier.rs @@ -700,8 +700,8 @@ proptest! { /// (And that the test infrastructure generally works.) #[test] fn accept_distinct_arbitrary_orchard_nullifiers_in_one_block( - authorized_action in TypeNameToDebug::::arbitrary(), - orchard_shielded_data in TypeNameToDebug::::arbitrary(), + authorized_action in TypeNameToDebug::>::arbitrary(), + orchard_shielded_data in TypeNameToDebug::>::arbitrary(), use_finalized_state in any::(), ) { let _init_guard = zebra_test::init(); @@ -759,9 +759,9 @@ proptest! { /// if they come from different AuthorizedActions in the same orchard::ShieldedData/Transaction. #[test] fn reject_duplicate_orchard_nullifiers_in_transaction( - authorized_action1 in TypeNameToDebug::::arbitrary(), - mut authorized_action2 in TypeNameToDebug::::arbitrary(), - orchard_shielded_data in TypeNameToDebug::::arbitrary(), + authorized_action1 in TypeNameToDebug::>::arbitrary(), + mut authorized_action2 in TypeNameToDebug::>::arbitrary(), + orchard_shielded_data in TypeNameToDebug::>::arbitrary(), ) { let _init_guard = zebra_test::init(); @@ -812,10 +812,10 @@ proptest! { /// if they come from different transactions in the same block. #[test] fn reject_duplicate_orchard_nullifiers_in_block( - authorized_action1 in TypeNameToDebug::::arbitrary(), - mut authorized_action2 in TypeNameToDebug::::arbitrary(), - orchard_shielded_data1 in TypeNameToDebug::::arbitrary(), - orchard_shielded_data2 in TypeNameToDebug::::arbitrary(), + authorized_action1 in TypeNameToDebug::>::arbitrary(), + mut authorized_action2 in TypeNameToDebug::>::arbitrary(), + orchard_shielded_data1 in TypeNameToDebug::>::arbitrary(), + orchard_shielded_data2 in TypeNameToDebug::>::arbitrary(), ) { let _init_guard = zebra_test::init(); @@ -872,10 +872,10 @@ proptest! { /// if they come from different blocks in the same chain. #[test] fn reject_duplicate_orchard_nullifiers_in_chain( - authorized_action1 in TypeNameToDebug::::arbitrary(), - mut authorized_action2 in TypeNameToDebug::::arbitrary(), - orchard_shielded_data1 in TypeNameToDebug::::arbitrary(), - orchard_shielded_data2 in TypeNameToDebug::::arbitrary(), + authorized_action1 in TypeNameToDebug::>::arbitrary(), + mut authorized_action2 in TypeNameToDebug::>::arbitrary(), + orchard_shielded_data1 in TypeNameToDebug::>::arbitrary(), + orchard_shielded_data2 in TypeNameToDebug::>::arbitrary(), duplicate_in_finalized_state in any::(), ) { let _init_guard = zebra_test::init(); @@ -1126,8 +1126,8 @@ fn transaction_v4_with_sapling_shielded_data( /// /// If there are no `AuthorizedAction`s in `authorized_actions`. fn transaction_v5_with_orchard_shielded_data( - orchard_shielded_data: impl Into>, - authorized_actions: impl IntoIterator, + orchard_shielded_data: impl Into>>, + authorized_actions: impl IntoIterator>, ) -> Transaction { let mut orchard_shielded_data = orchard_shielded_data.into(); let authorized_actions: Vec<_> = authorized_actions.into_iter().collect(); From 4d8cdefe20d1fbb8b73795318fb732415964c72b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 24 Sep 2024 07:30:06 +0200 Subject: [PATCH 024/157] Add several FIXME comments --- zebra-chain/src/orchard/action.rs | 1 + zebra-rpc/qa/rpc-tests/test_framework/mininode.py | 3 ++- zebra-test/src/vectors/orchard_note_encryption.rs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/orchard/action.rs b/zebra-chain/src/orchard/action.rs index c8161246efb..4f256408f11 100644 --- a/zebra-chain/src/orchard/action.rs +++ b/zebra-chain/src/orchard/action.rs @@ -94,6 +94,7 @@ impl ZcashDeserialize for Action { // https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to // 580 bytes in https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus // See [`note::EncryptedNote::zcash_deserialize`]. + // FIXME: don't mention about 580 here as this should work for OrchardZSA too? enc_ciphertext: V::EncryptedNote::zcash_deserialize(&mut reader)?, // Type is `Sym.C`, i.e. `𝔹^Y^{\[N\]}`, i.e. arbitrary-sized byte arrays // https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to diff --git a/zebra-rpc/qa/rpc-tests/test_framework/mininode.py b/zebra-rpc/qa/rpc-tests/test_framework/mininode.py index d56fb8bf79c..2fbe6faca89 100755 --- a/zebra-rpc/qa/rpc-tests/test_framework/mininode.py +++ b/zebra-rpc/qa/rpc-tests/test_framework/mininode.py @@ -425,6 +425,7 @@ def __repr__(self): return "RedPallasSignature(%s)" % bytes_to_hex_str(self.data) +# FIXME: add support of OrchardZSA class OrchardAction(object): def __init__(self): self.cv = None @@ -441,7 +442,7 @@ def deserialize(self, f): self.rk = deser_uint256(f) self.cmx = deser_uint256(f) self.ephemeralKey = deser_uint256(f) - self.encCiphertext = f.read(580) + self.encCiphertext = f.read(580) # FIXME: works for OrchardVanilla only self.outCiphertext = f.read(80) def serialize(self): diff --git a/zebra-test/src/vectors/orchard_note_encryption.rs b/zebra-test/src/vectors/orchard_note_encryption.rs index ff52b661b53..84b576df5c3 100644 --- a/zebra-test/src/vectors/orchard_note_encryption.rs +++ b/zebra-test/src/vectors/orchard_note_encryption.rs @@ -1,6 +1,7 @@ //! Contains test vectors for Orchard note encryptions. use lazy_static::lazy_static; +// FIXME: add tests for OrchardZSA #[allow(missing_docs)] pub struct TestVector { pub incoming_viewing_key: [u8; 64], @@ -18,7 +19,7 @@ pub struct TestVector { pub shared_secret: [u8; 32], pub k_enc: [u8; 32], pub p_enc: [u8; 564], - pub c_enc: [u8; 580], + pub c_enc: [u8; 580], // FIXME: works for OrchardVanilla only! pub ock: [u8; 32], pub op: [u8; 64], pub c_out: [u8; 80], From 1adadb14dab94c5a31cee16bde69868a7efb7ad9 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 24 Sep 2024 16:01:24 +0200 Subject: [PATCH 025/157] Remove (comment out) zcash_unstable=nu6 Rust flag and sync Cargo.lock with the upstream halo2/librustcash/orchard/sapling versions --- .github/workflows/ci-basic.yml | 5 ++-- Cargo.lock | 30 +++++++++---------- Cargo.toml | 2 +- zebra-chain/Cargo.toml | 4 +-- zebra-chain/src/parameters/network_upgrade.rs | 8 ++--- .../src/primitives/zcash_primitives.rs | 9 ++++-- zebra-chain/src/transaction.rs | 2 +- 7 files changed, 32 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index c2cde8686bf..226f1528046 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -16,9 +16,10 @@ jobs: ROCKSDB_LIB_DIR: /usr/lib # Use system-installed Snappy library for compression in RocksDB SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu + # FIXME: remove the following commented lines # Enable the `nu6` feature in `zcash_protocol` - RUSTFLAGS: '--cfg zcash_unstable="nu6"' - RUSTDOCFLAGS: '--cfg zcash_unstable="nu6"' + #RUSTFLAGS: '--cfg zcash_unstable="nu6"' + #RUSTDOCFLAGS: '--cfg zcash_unstable="nu6"' steps: - uses: actions/checkout@v4 diff --git a/Cargo.lock b/Cargo.lock index 0465c10f426..d1e183bc90b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1372,7 +1372,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "blake2b_simd", "byteorder", @@ -1407,7 +1407,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "blake2b_simd", ] @@ -1744,7 +1744,7 @@ dependencies = [ [[package]] name = "halo2_gadgets" version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11#7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#1195c9af90205829ba20662bdfaf20dcc878807d" dependencies = [ "arrayvec", "bitvec", @@ -1767,7 +1767,7 @@ checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" [[package]] name = "halo2_proofs" version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11#7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#1195c9af90205829ba20662bdfaf20dcc878807d" dependencies = [ "blake2b_simd", "ff", @@ -2865,7 +2865,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.8.0" -source = "git+https://github.com/QED-it/orchard?branch=zsa1#6e6112c80eb751a93c0fd1d881e9ca69887e1154" +source = "git+https://github.com/QED-it/orchard?branch=zsa1#3ba9e5b8d208bb44222cb2fe8bcd603c71abf444" dependencies = [ "aes", "bitvec", @@ -3957,7 +3957,7 @@ dependencies = [ [[package]] name = "sapling-crypto" version = "0.1.3" -source = "git+https://github.com/QED-it/sapling-crypto?branch=zsa1#e19f4d916360842becf2842bfd9b27228e66fa81" +source = "git+https://github.com/QED-it/sapling-crypto?branch=zsa1#99ad0a5f0bdef332bdc91d577086abd3aca59553" dependencies = [ "aes", "bellman", @@ -5779,7 +5779,7 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" version = "0.3.2" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "bech32", "bs58", @@ -5791,7 +5791,7 @@ dependencies = [ [[package]] name = "zcash_client_backend" version = "0.12.1" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "base64 0.21.7", "bech32", @@ -5830,7 +5830,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "byteorder", "nonempty", @@ -5839,7 +5839,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "blake2b_simd", "byteorder", @@ -5875,7 +5875,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "bech32", "blake2b_simd", @@ -5900,7 +5900,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.4.0" -source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#58384553aab76b2ee6d6eb328cf2187fa824ec9a" +source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#76745f00551d4442dee11ad64a8400b75132d18f" dependencies = [ "chacha20", "chacha20poly1305", @@ -5912,7 +5912,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.15.0" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "aes", "bip0039", @@ -5973,7 +5973,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.1.1" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "document-features", "memuse", @@ -6512,7 +6512,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.0.0" -source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#04ebee7fb22303c1e1dc6428def3dd3cecc4715d" +source = "git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2#8149034c53c9a33b5ca417689c42ec4d47d0eff5" dependencies = [ "base64 0.21.7", "nom", diff --git a/Cargo.toml b/Cargo.toml index e8b55f1ba8f..8e67fb8e048 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,7 +104,7 @@ panic = "abort" lto = "thin" [patch.crates-io] -halo2_proofs = { version = "0.3.0", git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" } +halo2_proofs = { version = "0.3.0", git = "https://github.com/QED-it/halo2", branch = "zsa1" } zcash_note_encryption = { version = "0.4.0", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1" } sapling-crypto = { version = "0.1.3", git = "https://github.com/QED-it/sapling-crypto", branch = "zsa1" } orchard = { version = "0.8.0", git = "https://github.com/QED-it/orchard", branch = "zsa1" } diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 641ea6a25a2..e98b38ff56d 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -189,5 +189,5 @@ name = "redpallas" harness = false # FIXME: remove this and all zcash_unstable usage in the code after updating librustzcash -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } +#[lints.rust] +#unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index ab66fbc7895..79cf18a6291 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -530,11 +530,11 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Heartwood => Self::Heartwood, zcash_protocol::consensus::NetworkUpgrade::Canopy => Self::Canopy, zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, - // FIXME: remove cfg - #[cfg(zcash_unstable = "nu6")] + // FIXME: remove this cfg + //#[cfg(zcash_unstable = "nu6")] zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, - // FIXME: remove cfg and process Nu7 properly (uses Self::Nu6 for now) - #[cfg(zcash_unstable = "nu6")] + // FIXME: remove this cfg and process Nu7 properly (uses Self::Nu6 for now) + //#[cfg(zcash_unstable = "nu6")] zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, } } diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 4cf445854d2..f69f4081446 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -138,7 +138,8 @@ impl zp_tx::components::orchard::MapAuth for IdentityMap { @@ -158,11 +159,13 @@ impl<'a> zp_tx::Authorization for PrecomputedAuth<'a> { type OrchardAuth = orchard::bundle::Authorized; // FIXME: is this correct? - #[cfg(zcash_unstable = "nu6")] + // FIXME: remove this cfg + //#[cfg(zcash_unstable = "nu6")] type OrchardZsaAuth = orchard::bundle::Authorized; // FIXME: is this correct? - #[cfg(zcash_unstable = "nu6")] + // FIXME: remove this cfg + //#[cfg(zcash_unstable = "nu6")] type IssueAuth = orchard::issuance::Signed; } diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 49e8fdbe33c..db5613eab24 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -1092,7 +1092,7 @@ impl Transaction { orchard_shielded_data_field!(self, flags) } - // FIXME: add doc + /// FIXME: add doc pub fn orchard_shared_anchor(&self) -> Option { orchard_shielded_data_field!(self, shared_anchor) } From e2e160cc60bbc08486ed1f3291b3fdc0b589de80 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 30 Sep 2024 10:49:34 +0200 Subject: [PATCH 026/157] Attempt to make the code compilable when tx-v6 feature is disabled --- zebra-chain/Cargo.toml | 4 ++-- zebra-chain/src/orchard.rs | 9 ++++++-- zebra-chain/src/transaction.rs | 42 ++++++++++++++++++++++++++-------- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index e98b38ff56d..f2997f2f950 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -15,8 +15,8 @@ keywords = ["zebra", "zcash"] categories = ["asynchronous", "cryptography::cryptocurrencies", "encoding"] [features] -#default = [] -default = ["tx-v6"] +default = [] +#default = ["tx-v6"] # Production features that activate extra functionality diff --git a/zebra-chain/src/orchard.rs b/zebra-chain/src/orchard.rs index 1eff5f2a3c6..3141b6a1154 100644 --- a/zebra-chain/src/orchard.rs +++ b/zebra-chain/src/orchard.rs @@ -23,8 +23,13 @@ pub use address::Address; pub use commitment::{CommitmentRandomness, NoteCommitment, ValueCommitment}; pub use keys::Diversifier; pub use note::{EncryptedNote, Note, Nullifier, WrappedNoteKey}; -pub use orchard_flavor_ext::{OrchardFlavorExt, OrchardVanilla, OrchardZSA}; +pub use orchard_flavor_ext::{OrchardFlavorExt, OrchardVanilla}; pub use shielded_data::{AuthorizedAction, Flags, ShieldedData}; -pub(crate) use crate::orchard_zsa::issuance::IssueData; pub(crate) use shielded_data::ActionCommon; + +#[cfg(feature = "tx-v6")] +pub use orchard_flavor_ext::OrchardZSA; + +#[cfg(feature = "tx-v6")] +pub(crate) use crate::orchard_zsa::issuance::IssueData; diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index db5613eab24..4ed61e2dfd1 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -69,6 +69,7 @@ macro_rules! orchard_shielded_data_iter { .. } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), + #[cfg(feature = "tx-v6")] Transaction::V6 { orchard_shielded_data, .. @@ -93,6 +94,7 @@ macro_rules! orchard_shielded_data_field { .. } => orchard_shielded_data.as_ref().map(|data| data.$field), + #[cfg(feature = "tx-v6")] Transaction::V6 { orchard_shielded_data, .. @@ -101,6 +103,21 @@ macro_rules! orchard_shielded_data_field { }; } +// FIXME: +// Define the macro for including the V6 pattern +//#[cfg(feature = "tx-v6")] +macro_rules! with_v6 { + () => { + | Transaction::V6 { expiry_height, .. } + }; +} + +// FIXME: +//#[cfg(not(feature = "tx-v6"))] +//macro_rules! with_v6 { +// () => {}; +//} + /// A Zcash transaction. /// /// A transaction is an encoded data structure that facilitates the transfer of @@ -193,6 +210,7 @@ pub enum Transaction { // FIXME: implement V6 properly (now it's just a coipy of V5) /// A `version = 6` transaction , which supports Orchard ZSA, Orchard Vanille, Sapling and /// transparent, but not Sprout. + #[cfg(feature = "tx-v6")] V6 { /// The Network Upgrade for this transaction. /// @@ -210,8 +228,10 @@ pub enum Transaction { /// The sapling shielded data for this transaction, if any. sapling_shielded_data: Option>, /// The ZSA orchard shielded data for this transaction, if any. + #[cfg(feature = "tx-v6")] orchard_shielded_data: Option>, /// The ZSA issuance data for this transaction, if any. + #[cfg(feature = "tx-v6")] orchard_zsa_issue_data: Option, }, } @@ -319,7 +339,9 @@ impl Transaction { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => None, - Transaction::V5 { .. } | Transaction::V6 { .. } => Some(AuthDigest::from(self)), + Transaction::V5 { .. } => Some(AuthDigest::from(self)), + #[cfg(feature = "tx-v6")] + Transaction::V6 { .. } => Some(AuthDigest::from(self)), } } @@ -392,10 +414,9 @@ impl Transaction { pub fn is_overwintered(&self) -> bool { match self { Transaction::V1 { .. } | Transaction::V2 { .. } => false, - Transaction::V3 { .. } - | Transaction::V4 { .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => true, + Transaction::V3 { .. } | Transaction::V4 { .. } | Transaction::V5 { .. } => true, + #[cfg(feature = "tx-v6")] + Transaction::V6 { .. } => true, } } @@ -407,6 +428,7 @@ impl Transaction { Transaction::V3 { .. } => 3, Transaction::V4 { .. } => 4, Transaction::V5 { .. } => 5, + #[cfg(feature = "tx-v6")] Transaction::V6 { .. } => 6, } } @@ -418,8 +440,9 @@ impl Transaction { | Transaction::V2 { lock_time, .. } | Transaction::V3 { lock_time, .. } | Transaction::V4 { lock_time, .. } - | Transaction::V5 { lock_time, .. } - | Transaction::V6 { lock_time, .. } => *lock_time, + | Transaction::V5 { lock_time, .. } => *lock_time, + #[cfg(feature = "tx-v6")] + Transaction::V6 { lock_time, .. } => *lock_time, }; // `zcashd` checks that the block height is greater than the lock height. @@ -466,8 +489,9 @@ impl Transaction { | Transaction::V2 { lock_time, .. } | Transaction::V3 { lock_time, .. } | Transaction::V4 { lock_time, .. } - | Transaction::V5 { lock_time, .. } - | Transaction::V6 { lock_time, .. } => *lock_time, + | Transaction::V5 { lock_time, .. } => *lock_time, + #[cfg(feature = "tx-v6")] + Transaction::V6 { lock_time, .. } => *lock_time, }; let mut lock_time_bytes = Vec::new(); lock_time From 763cded7ed0b2c2aeeceabe0a7e9f680d5a4ece5 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 2 Oct 2024 10:37:23 +0200 Subject: [PATCH 027/157] Use tx-v6 feature across all crates --- zebra-chain/Cargo.toml | 2 +- zebra-chain/src/parameters/transaction.rs | 1 + .../src/primitives/zcash_primitives.rs | 7 +- zebra-chain/src/transaction.rs | 195 +++++------------- zebra-chain/src/transaction/arbitrary.rs | 3 + zebra-chain/src/transaction/serialize.rs | 10 +- zebra-chain/src/transaction/tests/vectors.rs | 6 +- zebra-chain/src/transaction/txid.rs | 4 +- zebra-chain/src/transaction/unmined.rs | 4 +- zebra-consensus/Cargo.toml | 7 + zebra-consensus/src/primitives/halo2/tests.rs | 1 + zebra-consensus/src/transaction.rs | 3 +- zebra-state/Cargo.toml | 7 + .../src/service/non_finalized_state/chain.rs | 2 + zebra-state/src/tests.rs | 1 + zebrad/Cargo.toml | 10 +- .../components/mempool/storage/tests/prop.rs | 13 +- 17 files changed, 112 insertions(+), 164 deletions(-) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index f2997f2f950..5e539fddba5 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -63,7 +63,7 @@ bench = ["zebra-test"] # Support for transaction version 6 tx-v6 = [ - "nonempty" + "nonempty" ] [dependencies] diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index 77b88abca44..d7391bdf184 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -17,4 +17,5 @@ pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; /// Orchard transactions must use transaction version 5 and this version /// group ID. // FIXME: use a proper value! +#[cfg(feature = "tx-v6")] pub const TX_V6_VERSION_GROUP_ID: u32 = 0x26A7_270B; diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index f69f4081446..0d10f8546af 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -10,7 +10,7 @@ use crate::{ amount::{Amount, NonNegative}, parameters::{ConsensusBranchId, Network}, serialization::ZcashSerialize, - transaction::{AuthDigest, HashType, SigHash, Transaction}, + transaction::{tx_v5_and_v6, AuthDigest, HashType, SigHash, Transaction}, transparent::{self, Script}, }; @@ -183,10 +183,7 @@ impl TryFrom<&Transaction> for zp_tx::Transaction { #[allow(clippy::unwrap_in_result)] fn try_from(trans: &Transaction) -> Result { let network_upgrade = match trans { - Transaction::V5 { - network_upgrade, .. - } - | Transaction::V6 { + tx_v5_and_v6! { network_upgrade, .. } => network_upgrade, Transaction::V1 { .. } diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 4ed61e2dfd1..e60f13b57a1 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -105,18 +105,21 @@ macro_rules! orchard_shielded_data_field { // FIXME: // Define the macro for including the V6 pattern -//#[cfg(feature = "tx-v6")] -macro_rules! with_v6 { - () => { - | Transaction::V6 { expiry_height, .. } +#[cfg(feature = "tx-v6")] +macro_rules! tx_v5_and_v6 { + { $($fields:tt)* } => { + Transaction::V5 { $($fields)* } | Transaction::V6 { $($fields)* } }; } -// FIXME: -//#[cfg(not(feature = "tx-v6"))] -//macro_rules! with_v6 { -// () => {}; -//} +#[cfg(not(feature = "tx-v6"))] +macro_rules! tx_v5_and_v6 { + { $($fields:tt)* } => { + Transaction::V5 { $($fields)* } + }; +} + +pub(crate) use tx_v5_and_v6; /// A Zcash transaction. /// @@ -339,9 +342,7 @@ impl Transaction { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => None, - Transaction::V5 { .. } => Some(AuthDigest::from(self)), - #[cfg(feature = "tx-v6")] - Transaction::V6 { .. } => Some(AuthDigest::from(self)), + tx_v5_and_v6! { .. } => Some(AuthDigest::from(self)), } } @@ -414,9 +415,7 @@ impl Transaction { pub fn is_overwintered(&self) -> bool { match self { Transaction::V1 { .. } | Transaction::V2 { .. } => false, - Transaction::V3 { .. } | Transaction::V4 { .. } | Transaction::V5 { .. } => true, - #[cfg(feature = "tx-v6")] - Transaction::V6 { .. } => true, + Transaction::V3 { .. } | Transaction::V4 { .. } | tx_v5_and_v6! { .. } => true, } } @@ -440,9 +439,7 @@ impl Transaction { | Transaction::V2 { lock_time, .. } | Transaction::V3 { lock_time, .. } | Transaction::V4 { lock_time, .. } - | Transaction::V5 { lock_time, .. } => *lock_time, - #[cfg(feature = "tx-v6")] - Transaction::V6 { lock_time, .. } => *lock_time, + | tx_v5_and_v6! { lock_time, .. } => *lock_time, }; // `zcashd` checks that the block height is greater than the lock height. @@ -489,9 +486,7 @@ impl Transaction { | Transaction::V2 { lock_time, .. } | Transaction::V3 { lock_time, .. } | Transaction::V4 { lock_time, .. } - | Transaction::V5 { lock_time, .. } => *lock_time, - #[cfg(feature = "tx-v6")] - Transaction::V6 { lock_time, .. } => *lock_time, + | tx_v5_and_v6! { lock_time, .. } => *lock_time, }; let mut lock_time_bytes = Vec::new(); lock_time @@ -521,8 +516,7 @@ impl Transaction { Transaction::V1 { .. } | Transaction::V2 { .. } => None, Transaction::V3 { expiry_height, .. } | Transaction::V4 { expiry_height, .. } - | Transaction::V5 { expiry_height, .. } - | Transaction::V6 { expiry_height, .. } => match expiry_height { + | tx_v5_and_v6! { expiry_height, .. } => match expiry_height { // Consensus rule: // > No limit: To set no limit on transactions (so that they do not expire), nExpiryHeight should be set to 0. // https://zips.z.cash/zip-0203#specification @@ -551,11 +545,7 @@ impl Transaction { ref mut expiry_height, .. } - | Transaction::V5 { - ref mut expiry_height, - .. - } - | Transaction::V6 { + | tx_v5_and_v6! { ref mut expiry_height, .. } => expiry_height, @@ -572,10 +562,7 @@ impl Transaction { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => None, - Transaction::V5 { - network_upgrade, .. - } - | Transaction::V6 { + tx_v5_and_v6! { network_upgrade, .. } => Some(*network_upgrade), } @@ -590,8 +577,7 @@ impl Transaction { Transaction::V2 { ref inputs, .. } => inputs, Transaction::V3 { ref inputs, .. } => inputs, Transaction::V4 { ref inputs, .. } => inputs, - Transaction::V5 { ref inputs, .. } => inputs, - Transaction::V6 { ref inputs, .. } => inputs, + tx_v5_and_v6! { ref inputs, .. } => inputs, } } @@ -603,8 +589,7 @@ impl Transaction { Transaction::V2 { ref mut inputs, .. } => inputs, Transaction::V3 { ref mut inputs, .. } => inputs, Transaction::V4 { ref mut inputs, .. } => inputs, - Transaction::V5 { ref mut inputs, .. } => inputs, - Transaction::V6 { ref mut inputs, .. } => inputs, + tx_v5_and_v6! { ref mut inputs, .. } => inputs, } } @@ -622,8 +607,7 @@ impl Transaction { Transaction::V2 { ref outputs, .. } => outputs, Transaction::V3 { ref outputs, .. } => outputs, Transaction::V4 { ref outputs, .. } => outputs, - Transaction::V5 { ref outputs, .. } => outputs, - Transaction::V6 { ref outputs, .. } => outputs, + tx_v5_and_v6! { ref outputs, .. } => outputs, } } @@ -643,10 +627,7 @@ impl Transaction { Transaction::V4 { ref mut outputs, .. } => outputs, - Transaction::V5 { - ref mut outputs, .. - } => outputs, - Transaction::V6 { + tx_v5_and_v6! { ref mut outputs, .. } => outputs, } @@ -696,8 +677,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => Box::new(std::iter::empty()), + | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), } } @@ -732,8 +712,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => 0, + | tx_v5_and_v6! { .. } => 0, } } @@ -772,8 +751,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => Box::new(std::iter::empty()), + | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), } } @@ -809,8 +787,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => None, + | tx_v5_and_v6! { .. } => None, } } @@ -818,7 +795,7 @@ impl Transaction { pub fn has_sprout_joinsplit_data(&self) -> bool { match self { // No JoinSplits - Transaction::V1 { .. } | Transaction::V5 { .. } | Transaction::V6 { .. } => false, + Transaction::V1 { .. } | tx_v5_and_v6! { .. } => false, // JoinSplits-on-BCTV14 Transaction::V2 { joinsplit_data, .. } | Transaction::V3 { joinsplit_data, .. } => { @@ -865,8 +842,7 @@ impl Transaction { .. } | Transaction::V1 { .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => Box::new(std::iter::empty()), + | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), } } @@ -883,12 +859,7 @@ impl Transaction { .. } => Box::new(sapling_shielded_data.anchors()), - Transaction::V5 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Box::new(sapling_shielded_data.anchors()), - - Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.anchors()), @@ -901,11 +872,7 @@ impl Transaction { sapling_shielded_data: None, .. } - | Transaction::V5 { - sapling_shielded_data: None, - .. - } - | Transaction::V6 { + | tx_v5_and_v6! { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -930,11 +897,7 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.spends_per_anchor()), - Transaction::V5 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Box::new(sapling_shielded_data.spends_per_anchor()), - Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.spends_per_anchor()), @@ -947,11 +910,7 @@ impl Transaction { sapling_shielded_data: None, .. } - | Transaction::V5 { - sapling_shielded_data: None, - .. - } - | Transaction::V6 { + | tx_v5_and_v6! { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -966,11 +925,7 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.outputs()), - Transaction::V5 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Box::new(sapling_shielded_data.outputs()), - Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.outputs()), @@ -983,11 +938,7 @@ impl Transaction { sapling_shielded_data: None, .. } - | Transaction::V5 { - sapling_shielded_data: None, - .. - } - | Transaction::V6 { + | tx_v5_and_v6! { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -1004,11 +955,7 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.nullifiers()), - Transaction::V5 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Box::new(sapling_shielded_data.nullifiers()), - Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.nullifiers()), @@ -1021,11 +968,7 @@ impl Transaction { sapling_shielded_data: None, .. } - | Transaction::V5 { - sapling_shielded_data: None, - .. - } - | Transaction::V6 { + | tx_v5_and_v6! { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -1042,11 +985,7 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.note_commitments()), - Transaction::V5 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Box::new(sapling_shielded_data.note_commitments()), - Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data: Some(sapling_shielded_data), .. } => Box::new(sapling_shielded_data.note_commitments()), @@ -1059,11 +998,7 @@ impl Transaction { sapling_shielded_data: None, .. } - | Transaction::V5 { - sapling_shielded_data: None, - .. - } - | Transaction::V6 { + | tx_v5_and_v6! { sapling_shielded_data: None, .. } => Box::new(std::iter::empty()), @@ -1078,11 +1013,7 @@ impl Transaction { sapling_shielded_data, .. } => sapling_shielded_data.is_some(), - Transaction::V5 { - sapling_shielded_data, - .. - } => sapling_shielded_data.is_some(), - Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data, .. } => sapling_shielded_data.is_some(), @@ -1212,8 +1143,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => Box::new(std::iter::empty()), + | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), } } @@ -1262,8 +1192,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => Box::new(std::iter::empty()), + | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), } } @@ -1310,8 +1239,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => Box::new(std::iter::empty()), + | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), } } @@ -1360,8 +1288,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => Box::new(std::iter::empty()), + | tx_v5_and_v6! { .. } => Box::new(std::iter::empty()), } } @@ -1402,8 +1329,7 @@ impl Transaction { joinsplit_data: None, .. } - | Transaction::V5 { .. } - | Transaction::V6 { .. } => Box::new(iter::empty()), + | tx_v5_and_v6! { .. } => Box::new(iter::empty()), }; joinsplit_value_balances.map(ValueBalance::from_sprout_amount) @@ -1441,11 +1367,7 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => sapling_shielded_data.value_balance, - Transaction::V5 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => sapling_shielded_data.value_balance, - Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data: Some(sapling_shielded_data), .. } => sapling_shielded_data.value_balance, @@ -1457,11 +1379,7 @@ impl Transaction { sapling_shielded_data: None, .. } - | Transaction::V5 { - sapling_shielded_data: None, - .. - } - | Transaction::V6 { + | tx_v5_and_v6! { sapling_shielded_data: None, .. } => Amount::zero(), @@ -1481,11 +1399,7 @@ impl Transaction { sapling_shielded_data: Some(sapling_shielded_data), .. } => Some(&mut sapling_shielded_data.value_balance), - Transaction::V5 { - sapling_shielded_data: Some(sapling_shielded_data), - .. - } => Some(&mut sapling_shielded_data.value_balance), - Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data: Some(sapling_shielded_data), .. } => Some(&mut sapling_shielded_data.value_balance), @@ -1496,11 +1410,7 @@ impl Transaction { sapling_shielded_data: None, .. } - | Transaction::V5 { - sapling_shielded_data: None, - .. - } - | Transaction::V6 { + | tx_v5_and_v6! { sapling_shielded_data: None, .. } => None, @@ -1537,6 +1447,7 @@ impl Transaction { .. } => Some(&mut orchard_shielded_data.value_balance), + #[cfg(feature = "tx-v6")] Transaction::V6 { orchard_shielded_data: Some(orchard_shielded_data), .. @@ -1549,8 +1460,10 @@ impl Transaction { | Transaction::V5 { orchard_shielded_data: None, .. - } - | Transaction::V6 { + } => None, + + #[cfg(feature = "tx-v6")] + Transaction::V6 { orchard_shielded_data: None, .. } => None, diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 753c68d2fe0..ffd169f651f 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -722,6 +722,7 @@ impl Arbitrary for orchard::ShieldedData { .try_into() .expect("arbitrary vector size range produces at least one action"), binding_sig: binding_sig.0, + #[cfg(feature = "tx-v6")] burn: Default::default(), }, ) @@ -919,6 +920,7 @@ pub fn transaction_to_fake_v5( orchard_shielded_data: None, }, v5 @ V5 { .. } => v5.clone(), + #[cfg(feature = "tx-v6")] V6 { inputs, outputs, @@ -1077,6 +1079,7 @@ pub fn insert_fake_orchard_shielded_data( proof: Halo2Proof(vec![]), actions: at_least_one![dummy_authorized_action], binding_sig: Signature::from([0u8; 64]), + #[cfg(feature = "tx-v6")] burn: Default::default(), }; diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index e851bb158cf..f5fd254773d 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -12,10 +12,7 @@ use crate::{ amount, block::MAX_BLOCK_BYTES, orchard::OrchardFlavorExt, - parameters::{ - OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, TX_V5_VERSION_GROUP_ID, - TX_V6_VERSION_GROUP_ID, - }, + parameters::{OVERWINTER_VERSION_GROUP_ID, SAPLING_VERSION_GROUP_ID, TX_V5_VERSION_GROUP_ID}, primitives::{Halo2Proof, ZkSnarkProof}, serialization::{ zcash_deserialize_external_count, zcash_serialize_empty_list, @@ -24,6 +21,9 @@ use crate::{ }, }; +#[cfg(feature = "tx-v6")] +use crate::parameters::TX_V6_VERSION_GROUP_ID; + use super::*; use crate::sapling; @@ -689,6 +689,7 @@ impl ZcashSerialize for Transaction { orchard_shielded_data.zcash_serialize(&mut writer)?; } + #[cfg(feature = "tx-v6")] Transaction::V6 { network_upgrade, lock_time, @@ -997,6 +998,7 @@ impl ZcashDeserialize for Transaction { }) } // FIXME: implement a proper deserialization for V6 + #[cfg(feature = "tx-v6")] (6, true) => { // FIXME: fix spec or use another link as the current version of the PDF // doesn't contain V6 description. diff --git a/zebra-chain/src/transaction/tests/vectors.rs b/zebra-chain/src/transaction/tests/vectors.rs index f20bfaef455..9e0af8adf63 100644 --- a/zebra-chain/src/transaction/tests/vectors.rs +++ b/zebra-chain/src/transaction/tests/vectors.rs @@ -988,11 +988,7 @@ fn binding_signatures_for_network(network: Network) { .expect("must pass verification"); } } - Transaction::V5 { - sapling_shielded_data, - .. - } - | Transaction::V6 { + tx_v5_and_v6! { sapling_shielded_data, .. } => { diff --git a/zebra-chain/src/transaction/txid.rs b/zebra-chain/src/transaction/txid.rs index eb05fd6edb3..08172459ade 100644 --- a/zebra-chain/src/transaction/txid.rs +++ b/zebra-chain/src/transaction/txid.rs @@ -2,7 +2,7 @@ //! from the transaction. use std::io; -use super::{Hash, Transaction}; +use super::{tx_v5_and_v6, Hash, Transaction}; use crate::serialization::{sha256d, ZcashSerialize}; /// A Transaction ID builder. It computes the transaction ID by hashing @@ -28,7 +28,7 @@ impl<'a> TxIdBuilder<'a> { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => self.txid_v1_to_v4(), - Transaction::V5 { .. } | Transaction::V6 { .. } => self.txid_v5_v6(), + tx_v5_and_v6! { .. } => self.txid_v5_v6(), } } diff --git a/zebra-chain/src/transaction/unmined.rs b/zebra-chain/src/transaction/unmined.rs index 554e8c3f0e1..ce327ae9f76 100644 --- a/zebra-chain/src/transaction/unmined.rs +++ b/zebra-chain/src/transaction/unmined.rs @@ -21,7 +21,7 @@ use crate::{ amount::{Amount, NonNegative}, serialization::ZcashSerialize, transaction::{ - AuthDigest, Hash, + tx_v5_and_v6, AuthDigest, Hash, Transaction::{self, *}, WtxId, }, @@ -140,7 +140,7 @@ impl From<&Transaction> for UnminedTxId { fn from(transaction: &Transaction) -> Self { match transaction { V1 { .. } | V2 { .. } | V3 { .. } | V4 { .. } => Legacy(transaction.into()), - V5 { .. } | V6 { .. } => Witnessed(transaction.into()), + tx_v5_and_v6! { .. } => Witnessed(transaction.into()), } } } diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index f49041d0ba1..66ebb405492 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -16,6 +16,7 @@ categories = ["asynchronous", "cryptography::cryptocurrencies"] [features] default = [] +#default = ["tx-v6"] # Production features that activate extra dependencies, or extra features in dependencies @@ -34,6 +35,12 @@ getblocktemplate-rpcs = [ # Test-only features proptest-impl = ["proptest", "proptest-derive", "zebra-chain/proptest-impl", "zebra-state/proptest-impl"] +# Support for transaction version 6 +tx-v6 = [ + "zebra-state/tx-v6", + "zebra-chain/tx-v6" +] + [dependencies] blake2b_simd = "1.0.2" bellman = "0.14.0" diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index 12f2635b3b2..8af73f182e1 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -108,6 +108,7 @@ fn generate_test_vectors() { .unwrap(), binding_sig: <[u8; 64]>::from(bundle.authorization().binding_signature()).into(), // FIXME: use a proper value when implementing V6 + #[cfg(feature = "tx-v6")] burn: Default::default(), } }) diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 0be7fea38f3..e91f576f2a5 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -415,7 +415,8 @@ where orchard_shielded_data, )?, // FIXME: implement proper V6 verification - | Transaction::V6 { + #[cfg(feature = "tx-v6")] + Transaction::V6 { .. } => { tracing::debug!(?tx, "V6 transaction verification is not supported for now"); diff --git a/zebra-state/Cargo.toml b/zebra-state/Cargo.toml index db14f448c4b..1cabe066258 100644 --- a/zebra-state/Cargo.toml +++ b/zebra-state/Cargo.toml @@ -15,6 +15,8 @@ keywords = ["zebra", "zcash"] categories = ["asynchronous", "caching", "cryptography::cryptocurrencies"] [features] +default = [] +#default = ["tx-v6"] # Production features that activate extra dependencies, or extra features in dependencies @@ -45,6 +47,11 @@ elasticsearch = [ "zebra-chain/elasticsearch", ] +# Support for transaction version 6 +tx-v6 = [ + "zebra-chain/tx-v6" +] + [dependencies] bincode = "1.3.3" chrono = { version = "0.4.38", default-features = false, features = ["clock", "std"] } diff --git a/zebra-state/src/service/non_finalized_state/chain.rs b/zebra-state/src/service/non_finalized_state/chain.rs index 4539eb6aaa0..190f8b1a930 100644 --- a/zebra-state/src/service/non_finalized_state/chain.rs +++ b/zebra-state/src/service/non_finalized_state/chain.rs @@ -1521,6 +1521,7 @@ impl Chain { sapling_shielded_data, orchard_shielded_data, ), + #[cfg(feature ="tx-v6")] V6 { inputs, outputs, @@ -1697,6 +1698,7 @@ impl UpdateWith for Chain { sapling_shielded_data, orchard_shielded_data, ), + #[cfg(feature = "tx-v6")] V6 { inputs, outputs, diff --git a/zebra-state/src/tests.rs b/zebra-state/src/tests.rs index 6b955480572..d01a871f142 100644 --- a/zebra-state/src/tests.rs +++ b/zebra-state/src/tests.rs @@ -34,6 +34,7 @@ impl FakeChainHelper for Arc { Transaction::V3 { inputs, .. } => &mut inputs[0], Transaction::V4 { inputs, .. } => &mut inputs[0], Transaction::V5 { inputs, .. } => &mut inputs[0], + #[cfg(feature = "tx-v6")] Transaction::V6 { inputs, .. } => &mut inputs[0], }; diff --git a/zebrad/Cargo.toml b/zebrad/Cargo.toml index 6b4f2cfec8d..2df700dfc57 100644 --- a/zebrad/Cargo.toml +++ b/zebrad/Cargo.toml @@ -52,7 +52,8 @@ features = [ [features] # In release builds, don't compile debug logging code, to improve performance. -default = ["release_max_level_info", "progress-bar", "getblocktemplate-rpcs"] +#default = ["release_max_level_info", "progress-bar", "getblocktemplate-rpcs"] +default = ["release_max_level_info", "progress-bar", "getblocktemplate-rpcs", "tx-v6"] # Default features for official ZF binary release builds default-release-binaries = ["default", "sentry"] @@ -156,6 +157,13 @@ test_sync_to_mandatory_checkpoint_testnet = [] test_sync_past_mandatory_checkpoint_mainnet = [] test_sync_past_mandatory_checkpoint_testnet = [] +# Support for transaction version 6 +tx-v6 = [ + "zebra-consensus/tx-v6", + "zebra-state/tx-v6", + "zebra-chain/tx-v6" +] + [dependencies] zebra-chain = { path = "../zebra-chain", version = "1.0.0-beta.39" } zebra-consensus = { path = "../zebra-consensus", version = "1.0.0-beta.39" } diff --git a/zebrad/src/components/mempool/storage/tests/prop.rs b/zebrad/src/components/mempool/storage/tests/prop.rs index 2dde9d1d470..d3ef954063d 100644 --- a/zebrad/src/components/mempool/storage/tests/prop.rs +++ b/zebrad/src/components/mempool/storage/tests/prop.rs @@ -568,7 +568,11 @@ impl SpendConflictTestInput { } // No JoinSplits - Transaction::V1 { .. } | Transaction::V5 { .. } | Transaction::V6 { .. } => {} + Transaction::V1 { .. } | Transaction::V5 { .. } => {} + + // No JoinSplits + #[cfg(feature = "tx-v6")] + Transaction::V6 { .. } => {} } } } @@ -635,8 +639,12 @@ impl SpendConflictTestInput { Transaction::V5 { sapling_shielded_data, .. + } => { + Self::remove_sapling_transfers_with_conflicts(sapling_shielded_data, &conflicts) } - | Transaction::V6 { + + #[cfg(feature = "tx-v6")] + Transaction::V6 { sapling_shielded_data, .. } => { @@ -715,6 +723,7 @@ impl SpendConflictTestInput { } => Self::remove_orchard_actions_with_conflicts(orchard_shielded_data, &conflicts), // FIXME: implement for V6 + #[cfg(feature = "tx-v6")] Transaction::V6 { orchard_shielded_data: _, .. From c979861c296f073d9a4d9fa814b9bd9a76ea1d41 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 2 Oct 2024 12:52:16 +0200 Subject: [PATCH 028/157] Patch path for zcash_keys in Cargo.toml to avoid crate duplication in the crate tree --- Cargo.lock | 30 ++---------------------------- Cargo.toml | 1 + 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1e183bc90b..ae2e712bd81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5819,7 +5819,7 @@ dependencies = [ "which", "zcash_address", "zcash_encoding", - "zcash_keys 0.2.0 (git+https://github.com/QED-it/librustzcash?branch=txv6-separate-bundles-rebased-dd2)", + "zcash_keys", "zcash_note_encryption", "zcash_primitives", "zcash_protocol", @@ -5846,32 +5846,6 @@ dependencies = [ "primitive-types", ] -[[package]] -name = "zcash_keys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "663489ffb4e51bc4436ff8796832612a9ff3c6516f1c620b5a840cb5dcd7b866" -dependencies = [ - "bech32", - "blake2b_simd", - "bls12_381", - "bs58", - "document-features", - "group", - "memuse", - "nonempty", - "rand_core 0.6.4", - "sapling-crypto", - "secrecy", - "subtle", - "tracing", - "zcash_address", - "zcash_encoding", - "zcash_primitives", - "zcash_protocol", - "zip32", -] - [[package]] name = "zcash_keys" version = "0.2.0" @@ -6257,7 +6231,7 @@ dependencies = [ "tracing-subscriber", "zcash_address", "zcash_client_backend", - "zcash_keys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_keys", "zcash_note_encryption", "zcash_primitives", "zebra-chain", diff --git a/Cargo.toml b/Cargo.toml index 8e67fb8e048..ea9d38d197f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -114,3 +114,4 @@ zcash_address = { version = "0.3.2", git = "https://github.com/QED-it/librustzca zcash_encoding = { version = "0.2.0", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } zcash_history = { version = "0.4.0", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } zcash_client_backend = { version = "0.12.1", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } +zcash_keys = { version = "0.2.0", git = "https://github.com/QED-it/librustzcash", branch = "txv6-separate-bundles-rebased-dd2" } From 342202623a979ba21ad71792d25db115803e320c Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 8 Oct 2024 14:28:16 +0200 Subject: [PATCH 029/157] Add Burn and Issuance ZSA structs to Orchard proptests --- Cargo.lock | 1 + zebra-chain/Cargo.toml | 6 +- zebra-chain/src/orchard/arbitrary.rs | 18 ++- zebra-chain/src/orchard/orchard_flavor_ext.rs | 17 +- zebra-chain/src/orchard_zsa.rs | 4 + zebra-chain/src/orchard_zsa/burn.rs | 11 +- zebra-chain/src/orchard_zsa/issuance.rs | 6 + zebra-chain/src/transaction/arbitrary.rs | 146 ++++++++++++++---- zebra-consensus/Cargo.toml | 4 +- 9 files changed, 172 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae2e712bd81..562242cdc4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2883,6 +2883,7 @@ dependencies = [ "memuse", "nonempty", "pasta_curves", + "proptest", "rand 0.8.5", "reddsa", "serde", diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 5e539fddba5..abd1b542e25 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -15,8 +15,8 @@ keywords = ["zebra", "zcash"] categories = ["asynchronous", "cryptography::cryptocurrencies", "encoding"] [features] -default = [] -#default = ["tx-v6"] +#default = [] +default = ["tx-v6"] # Production features that activate extra functionality @@ -179,6 +179,8 @@ tokio = { version = "1.39.2", features = ["full", "tracing", "test-util"] } zebra-test = { path = "../zebra-test/", version = "1.0.0-beta.39" } +orchard = { workspace = true, features = ["test-dependencies"] } + [[bench]] name = "block" harness = false diff --git a/zebra-chain/src/orchard/arbitrary.rs b/zebra-chain/src/orchard/arbitrary.rs index 54572085f11..89618e451ad 100644 --- a/zebra-chain/src/orchard/arbitrary.rs +++ b/zebra-chain/src/orchard/arbitrary.rs @@ -11,17 +11,21 @@ use proptest::{array, collection::vec, prelude::*}; use super::{ keys::*, note, tree, Action, AuthorizedAction, Flags, NoteCommitment, OrchardFlavorExt, - OrchardVanilla, ValueCommitment, + ValueCommitment, }; -impl Arbitrary for Action { +impl Arbitrary for Action +// FIXME: define the constraint in OrchardFlavorExt? +where + ::Strategy: 'static, +{ type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { ( any::(), any::(), - any::>(), + any::(), any::(), ) .prop_map(|(nullifier, rk, enc_ciphertext, out_ciphertext)| Self { @@ -55,11 +59,15 @@ impl Arbitrary for note::Nullifier { type Strategy = BoxedStrategy; } -impl Arbitrary for AuthorizedAction { +impl Arbitrary for AuthorizedAction +// FIXME: define the constraint in OrchardFlavorExt? +where + ::Strategy: 'static, +{ type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - (any::>(), any::()) + (any::>(), any::()) .prop_map(|(action, spend_auth_sig)| Self { action, spend_auth_sig: spend_auth_sig.0, diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index f8ce25d0ed5..de99cd6f375 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -16,10 +16,21 @@ use super::note; #[cfg(feature = "tx-v6")] use crate::orchard_zsa::burn::BurnItem; +#[cfg(not(any(test, feature = "proptest-impl")))] +pub trait EncryptedNoteTest {} + +#[cfg(not(any(test, feature = "proptest-impl")))] +impl EncryptedNoteTest for T {} + +#[cfg(any(test, feature = "proptest-impl"))] +pub trait EncryptedNoteTest: proptest::prelude::Arbitrary {} + +#[cfg(any(test, feature = "proptest-impl"))] +impl EncryptedNoteTest for T {} + /// A trait representing compile-time settings of Orchard Shielded Protocol used in /// the transactions `V5` and `V6`. pub trait OrchardFlavorExt: Clone + Debug { - /// A type representing an encrypted note for this protocol version. /// A type representing an encrypted note for this protocol version. type EncryptedNote: Clone + Debug @@ -28,7 +39,8 @@ pub trait OrchardFlavorExt: Clone + Debug { + DeserializeOwned + Serialize + ZcashDeserialize - + ZcashSerialize; + + ZcashSerialize + + EncryptedNoteTest; /// FIXME: add doc type Flavor: orchard_flavor::OrchardFlavor; @@ -37,6 +49,7 @@ pub trait OrchardFlavorExt: Clone + Debug { const ENCRYPTED_NOTE_SIZE: usize = Self::Flavor::ENC_CIPHERTEXT_SIZE; /// A type representing a burn field for this protocol version. + // FIXME: add cfg tx-v6 here? type BurnType: Clone + Debug + Default + ZcashDeserialize + ZcashSerialize; } diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index 9806850daf9..651a146e796 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -1,5 +1,9 @@ //! Orchard ZSA related functionality. +// FIXME: remove pub(crate) later if possible +#[cfg(any(test, feature = "proptest-impl"))] +pub(crate) mod arbitrary; + pub mod burn; pub mod issuance; pub mod serialize; diff --git a/zebra-chain/src/orchard_zsa/burn.rs b/zebra-chain/src/orchard_zsa/burn.rs index 04c878feb49..85b235258e8 100644 --- a/zebra-chain/src/orchard_zsa/burn.rs +++ b/zebra-chain/src/orchard_zsa/burn.rs @@ -8,7 +8,7 @@ use crate::{ serialization::{SerializationError, TrustedPreallocate, ZcashDeserialize, ZcashSerialize}, }; -use orchard::note::AssetBase; +use orchard::{note::AssetBase, value::NoteValue}; use super::serialize::ASSET_BASE_SIZE; @@ -21,6 +21,15 @@ const BURN_ITEM_SIZE: u64 = ASSET_BASE_SIZE + AMOUNT_SIZE; #[derive(Clone, Debug, PartialEq, Eq)] pub struct BurnItem(AssetBase, Amount); +// Convert from burn item type used in `orchard` crate +impl TryFrom<(AssetBase, NoteValue)> for BurnItem { + type Error = crate::amount::Error; + + fn try_from(item: (AssetBase, NoteValue)) -> Result { + Ok(Self(item.0, item.1.inner().try_into()?)) + } +} + impl ZcashSerialize for BurnItem { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { let BurnItem(asset_base, amount) = self; diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index 3e55edcf14d..be4451d7e82 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -33,6 +33,12 @@ use super::serialize::ASSET_BASE_SIZE; #[derive(Clone, Debug, PartialEq, Eq)] pub struct IssueData(IssueBundle); +impl From> for IssueData { + fn from(inner: IssueBundle) -> Self { + Self(inner) + } +} + // Sizes of the serialized values for types in bytes (used for TrustedPreallocate impls) // FIXME: are those values correct (43, 32 etc.)? //const ISSUANCE_VALIDATING_KEY_SIZE: u64 = 32; diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index ffd169f651f..25c669a16a3 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -11,6 +11,7 @@ use crate::{ at_least_one, block::{self, arbitrary::MAX_PARTIAL_CHAIN_BLOCKS}, orchard, + orchard_zsa::arbitrary::ArbitraryBurn, parameters::{Network, NetworkUpgrade}, primitives::{Bctv14Proof, Groth16Proof, Halo2Proof, ZkSnarkProof}, sapling::{self, AnchorVariant, PerSpendAnchor, SharedAnchor}, @@ -132,8 +133,23 @@ impl Transaction { .boxed() } - /// Generate a proptest strategy for V5 Transactions - pub fn v5_strategy(ledger_state: LedgerState) -> BoxedStrategy { + fn v5_v6_strategy( + ledger_state: LedgerState, + construct_transaction: F, + ) -> BoxedStrategy + where + F: Fn( + NetworkUpgrade, + LockTime, + block::Height, + Vec, + Vec, + Option>, + Option>, + ) -> Transaction + + 'static, + V: Clone + 'static, + { ( NetworkUpgrade::branch_id_strategy(), any::(), @@ -141,7 +157,7 @@ impl Transaction { transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS), vec(any::(), 0..MAX_ARBITRARY_ITEMS), option::of(any::>()), - option::of(any::>()), + any::>>(), ) .prop_map( move |( @@ -153,34 +169,89 @@ impl Transaction { sapling_shielded_data, orchard_shielded_data, )| { - Transaction::V5 { - network_upgrade: if ledger_state.transaction_has_valid_network_upgrade() { - ledger_state.network_upgrade() - } else { - network_upgrade - }, + let network_upgrade = if ledger_state.transaction_has_valid_network_upgrade() { + ledger_state.network_upgrade() + } else { + network_upgrade + }; + + let sapling_shielded_data = if ledger_state.height.is_min() { + None + } else { + sapling_shielded_data + }; + + let orchard_shielded_data = if ledger_state.height.is_min() { + None + } else { + orchard_shielded_data + }; + + construct_transaction( + network_upgrade, lock_time, expiry_height, inputs, outputs, - sapling_shielded_data: if ledger_state.height.is_min() { - // The genesis block should not contain any shielded data. - None - } else { - sapling_shielded_data - }, - orchard_shielded_data: if ledger_state.height.is_min() { - // The genesis block should not contain any shielded data. - None - } else { - orchard_shielded_data - }, - } + sapling_shielded_data, + orchard_shielded_data, + ) }, ) .boxed() } + /// Generate a proptest strategy for V5 Transactions + pub fn v5_strategy(ledger_state: LedgerState) -> BoxedStrategy { + Self::v5_v6_strategy( + ledger_state, + |network_upgrade, + lock_time, + expiry_height, + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data| { + Transaction::V5 { + network_upgrade, + lock_time, + expiry_height, + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data, + } + }, + ) + } + + /// Generate a proptest strategy for V6 Transactions + #[cfg(feature = "tx-v6")] + pub fn v6_strategy(ledger_state: LedgerState) -> BoxedStrategy { + Self::v5_v6_strategy( + ledger_state, + |network_upgrade, + lock_time, + expiry_height, + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data| { + Transaction::V6 { + network_upgrade, + lock_time, + expiry_height, + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data, + // FIXME: generate a real arbitrary orchard_zsa_issue_data + orchard_zsa_issue_data: Default::default(), + } + }, + ) + } + /// Proptest Strategy for creating a Vector of transactions where the first /// transaction is always the only coinbase transaction pub fn vec_strategy( @@ -697,7 +768,11 @@ impl Arbitrary for sapling::TransferData { type Strategy = BoxedStrategy; } -impl Arbitrary for orchard::ShieldedData { +impl Arbitrary for orchard::ShieldedData +// FIXME: define the constraint in OrchardFlavorExt? +where + ::Strategy: 'static, +{ type Parameters = (); fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { @@ -707,13 +782,22 @@ impl Arbitrary for orchard::ShieldedData { any::(), any::(), vec( - any::>(), + any::>(), 1..MAX_ARBITRARY_ITEMS, ), any::(), + #[cfg(feature = "tx-v6")] + V::arbitrary_burn(), ) - .prop_map( - |(flags, value_balance, shared_anchor, proof, actions, binding_sig)| Self { + .prop_map(|props| { + #[cfg(not(feature = "tx-v6"))] + let (flags, value_balance, shared_anchor, proof, actions, binding_sig) = props; + + #[cfg(feature = "tx-v6")] + let (flags, value_balance, shared_anchor, proof, actions, binding_sig, burn) = + props; + + Self { flags, value_balance, shared_anchor, @@ -723,9 +807,9 @@ impl Arbitrary for orchard::ShieldedData { .expect("arbitrary vector size range produces at least one action"), binding_sig: binding_sig.0, #[cfg(feature = "tx-v6")] - burn: Default::default(), - }, - ) + burn, + } + }) .boxed() } @@ -767,6 +851,8 @@ impl Arbitrary for Transaction { Some(3) => return Self::v3_strategy(ledger_state), Some(4) => return Self::v4_strategy(ledger_state), Some(5) => return Self::v5_strategy(ledger_state), + #[cfg(feature = "tx-v6")] + Some(6) => return Self::v6_strategy(ledger_state), Some(_) => unreachable!("invalid transaction version in override"), None => {} } @@ -780,11 +866,13 @@ impl Arbitrary for Transaction { NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => { Self::v4_strategy(ledger_state) } + // FIXME: should v6_strategy be included here? NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => prop_oneof![ Self::v4_strategy(ledger_state.clone()), Self::v5_strategy(ledger_state) ] .boxed(), + // FIXME: process NetworkUpgrade::Nu7 properly, with v6 strategy } } diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index 66ebb405492..c2cc663105f 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -15,8 +15,8 @@ keywords = ["zebra", "zcash"] categories = ["asynchronous", "cryptography::cryptocurrencies"] [features] -default = [] -#default = ["tx-v6"] +#default = [] +default = ["tx-v6"] # Production features that activate extra dependencies, or extra features in dependencies From 4eb472be2ab9be0911197046f0905ebccbaf0652 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 8 Oct 2024 14:46:48 +0200 Subject: [PATCH 030/157] Add missed new file orchard_zsa/arbitrary.rs --- zebra-chain/src/orchard_zsa/arbitrary.rs | 64 ++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 zebra-chain/src/orchard_zsa/arbitrary.rs diff --git a/zebra-chain/src/orchard_zsa/arbitrary.rs b/zebra-chain/src/orchard_zsa/arbitrary.rs new file mode 100644 index 00000000000..011395568aa --- /dev/null +++ b/zebra-chain/src/orchard_zsa/arbitrary.rs @@ -0,0 +1,64 @@ +//! Randomised data generation for Orchard ZSA types. + +use proptest::prelude::*; + +use orchard::{bundle::testing::BundleArb, issuance::testing::arb_signed_issue_bundle}; + +// FIXME: consider using another value, i.e. define MAX_BURN_ITEMS constant for that +use crate::{ + orchard::{OrchardFlavorExt, OrchardVanilla, OrchardZSA}, + transaction::arbitrary::MAX_ARBITRARY_ITEMS, +}; + +use super::{burn::BurnItem, issuance::IssueData}; + +pub(crate) trait ArbitraryBurn: OrchardFlavorExt { + fn arbitrary_burn() -> BoxedStrategy; + // FIXME: remove the following lines + // where + // Self: Sized +} + +impl ArbitraryBurn for OrchardVanilla { + fn arbitrary_burn() -> BoxedStrategy { + Just(Default::default()).boxed() + } +} + +impl ArbitraryBurn for OrchardZSA { + fn arbitrary_burn() -> BoxedStrategy { + prop::collection::vec(any::(), 0..MAX_ARBITRARY_ITEMS).boxed() + } +} + +impl Arbitrary for BurnItem { + type Parameters = (); + + fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { + // FIXME: move arb_asset_to_burn out of BundleArb in orchard + // as it does not depend on flavor (we pinned it here OrchardVanilla + // just for certainty, as there's no difference, which flavor to use) + // FIXME: consider to use BurnItem(asset_base, value.try_into().expect("Invalid value for Amount")) + // instead of filtering non-convertable values + // FIXME: should we filter/protect from including native assets into burn here? + BundleArb::::arb_asset_to_burn() + .prop_filter_map("Conversion to Amount failed", |(asset_base, value)| { + BurnItem::try_from((asset_base, value)).ok() + }) + .boxed() + } + + type Strategy = BoxedStrategy; +} + +impl Arbitrary for IssueData { + type Parameters = (); + + fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { + arb_signed_issue_bundle(MAX_ARBITRARY_ITEMS) + .prop_map(|bundle| bundle.into()) + .boxed() + } + + type Strategy = BoxedStrategy; +} From 6372de86e34f445b94132940bcc66c02df774a34 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 9 Oct 2024 12:34:47 +0200 Subject: [PATCH 031/157] Refactor burn types and proptest implementations for Orchard types 1. Introduced new type `Burn` that wraps `Vec`, implemented serialization/deserialization for it - put it into `orchard_zsa/burn.rs`, also moved `NoBurn` there from `orchard_flavor_ext.rs` for better code structuring. 2. Renamed the `EncryptedNoteTest` trait to `TestArbitrary` in `orchard_flavor_ext.rs` and used it to constrain `BurnType` as well. 3. Renamed `serialize.rs` to `common.rs` in the `orchard_zsa` folder. 4. Refactored transaction generation strategies for V5 and V6 in `transaction/arbitrary.rs` and `orchard_zsa/arbitrary.rs` to incorporate the new burn handling and proper issuance handling. --- zebra-chain/src/orchard/orchard_flavor_ext.rs | 50 +++----- zebra-chain/src/orchard_zsa.rs | 3 +- zebra-chain/src/orchard_zsa/arbitrary.rs | 52 ++++---- zebra-chain/src/orchard_zsa/burn.rs | 49 +++++++- .../orchard_zsa/{serialize.rs => common.rs} | 2 +- zebra-chain/src/orchard_zsa/issuance.rs | 2 +- zebra-chain/src/transaction/arbitrary.rs | 118 ++++++++++-------- 7 files changed, 160 insertions(+), 116 deletions(-) rename zebra-chain/src/orchard_zsa/{serialize.rs => common.rs} (94%) diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index de99cd6f375..119646ae7b9 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -1,6 +1,6 @@ //! This module defines traits and structures for supporting the Orchard Shielded Protocol //! for `V5` and `V6` versions of the transaction. -use std::{fmt::Debug, io}; +use std::fmt::Debug; use serde::{de::DeserializeOwned, Serialize}; @@ -9,24 +9,24 @@ use proptest_derive::Arbitrary; use orchard::{note_encryption::OrchardDomainCommon, orchard_flavor}; -use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; - -use super::note; +use crate::serialization::{ZcashDeserialize, ZcashSerialize}; #[cfg(feature = "tx-v6")] -use crate::orchard_zsa::burn::BurnItem; +use crate::orchard_zsa::burn::{Burn, NoBurn}; + +use super::note; #[cfg(not(any(test, feature = "proptest-impl")))] -pub trait EncryptedNoteTest {} +pub trait TestArbitrary {} #[cfg(not(any(test, feature = "proptest-impl")))] -impl EncryptedNoteTest for T {} +impl TestArbitrary for T {} #[cfg(any(test, feature = "proptest-impl"))] -pub trait EncryptedNoteTest: proptest::prelude::Arbitrary {} +pub trait TestArbitrary: proptest::prelude::Arbitrary {} #[cfg(any(test, feature = "proptest-impl"))] -impl EncryptedNoteTest for T {} +impl TestArbitrary for T {} /// A trait representing compile-time settings of Orchard Shielded Protocol used in /// the transactions `V5` and `V6`. @@ -40,17 +40,17 @@ pub trait OrchardFlavorExt: Clone + Debug { + Serialize + ZcashDeserialize + ZcashSerialize - + EncryptedNoteTest; + + TestArbitrary; - /// FIXME: add doc + /// Specifies the Orchard protocol flavor from `orchard` crate used by this implementation. type Flavor: orchard_flavor::OrchardFlavor; /// The size of the encrypted note for this protocol version. const ENCRYPTED_NOTE_SIZE: usize = Self::Flavor::ENC_CIPHERTEXT_SIZE; /// A type representing a burn field for this protocol version. - // FIXME: add cfg tx-v6 here? - type BurnType: Clone + Debug + Default + ZcashDeserialize + ZcashSerialize; + #[cfg(feature = "tx-v6")] + type BurnType: Clone + Debug + Default + ZcashDeserialize + ZcashSerialize + TestArbitrary; } /// A structure representing a tag for Orchard protocol variant used for the transaction version `V5`. @@ -65,27 +65,11 @@ pub struct OrchardVanilla; #[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] pub struct OrchardZSA; -/// A special marker type indicating the absence of a burn field in Orchard ShieldedData for `V5` transactions. -/// Useful for unifying ShieldedData serialization and deserialization implementations across various -/// Orchard protocol variants (i.e. various transaction versions). -#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize)] -pub struct NoBurn; - -impl ZcashSerialize for NoBurn { - fn zcash_serialize(&self, mut _writer: W) -> Result<(), io::Error> { - Ok(()) - } -} - -impl ZcashDeserialize for NoBurn { - fn zcash_deserialize(mut _reader: R) -> Result { - Ok(Self) - } -} - impl OrchardFlavorExt for OrchardVanilla { type Flavor = orchard_flavor::OrchardVanilla; type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; + + #[cfg(feature = "tx-v6")] type BurnType = NoBurn; } @@ -93,5 +77,7 @@ impl OrchardFlavorExt for OrchardVanilla { impl OrchardFlavorExt for OrchardZSA { type Flavor = orchard_flavor::OrchardZSA; type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; - type BurnType = Vec; + + #[cfg(feature = "tx-v6")] + type BurnType = Burn; } diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index 651a146e796..d1dae03d792 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -4,8 +4,9 @@ #[cfg(any(test, feature = "proptest-impl"))] pub(crate) mod arbitrary; +mod common; + pub mod burn; pub mod issuance; -pub mod serialize; pub use burn::BurnItem; diff --git a/zebra-chain/src/orchard_zsa/arbitrary.rs b/zebra-chain/src/orchard_zsa/arbitrary.rs index 011395568aa..0dc89ce7080 100644 --- a/zebra-chain/src/orchard_zsa/arbitrary.rs +++ b/zebra-chain/src/orchard_zsa/arbitrary.rs @@ -5,31 +5,12 @@ use proptest::prelude::*; use orchard::{bundle::testing::BundleArb, issuance::testing::arb_signed_issue_bundle}; // FIXME: consider using another value, i.e. define MAX_BURN_ITEMS constant for that -use crate::{ - orchard::{OrchardFlavorExt, OrchardVanilla, OrchardZSA}, - transaction::arbitrary::MAX_ARBITRARY_ITEMS, -}; - -use super::{burn::BurnItem, issuance::IssueData}; - -pub(crate) trait ArbitraryBurn: OrchardFlavorExt { - fn arbitrary_burn() -> BoxedStrategy; - // FIXME: remove the following lines - // where - // Self: Sized -} - -impl ArbitraryBurn for OrchardVanilla { - fn arbitrary_burn() -> BoxedStrategy { - Just(Default::default()).boxed() - } -} +use crate::transaction::arbitrary::MAX_ARBITRARY_ITEMS; -impl ArbitraryBurn for OrchardZSA { - fn arbitrary_burn() -> BoxedStrategy { - prop::collection::vec(any::(), 0..MAX_ARBITRARY_ITEMS).boxed() - } -} +use super::{ + burn::{Burn, BurnItem, NoBurn}, + issuance::IssueData, +}; impl Arbitrary for BurnItem { type Parameters = (); @@ -51,6 +32,29 @@ impl Arbitrary for BurnItem { type Strategy = BoxedStrategy; } +impl Arbitrary for NoBurn { + type Parameters = (); + + fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { + // FIXME: consider using this instead, for clarity: any::<()>().prop_map(|_| NoBurn).boxed() + Just(Self).boxed() + } + + type Strategy = BoxedStrategy; +} + +impl Arbitrary for Burn { + type Parameters = (); + + fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { + prop::collection::vec(any::(), 0..MAX_ARBITRARY_ITEMS) + .prop_map(|inner| inner.into()) + .boxed() + } + + type Strategy = BoxedStrategy; +} + impl Arbitrary for IssueData { type Parameters = (); diff --git a/zebra-chain/src/orchard_zsa/burn.rs b/zebra-chain/src/orchard_zsa/burn.rs index 85b235258e8..812728b9380 100644 --- a/zebra-chain/src/orchard_zsa/burn.rs +++ b/zebra-chain/src/orchard_zsa/burn.rs @@ -10,14 +10,15 @@ use crate::{ use orchard::{note::AssetBase, value::NoteValue}; -use super::serialize::ASSET_BASE_SIZE; +use super::common::ASSET_BASE_SIZE; // Sizes of the serialized values for types in bytes (used for TrustedPreallocate impls) const AMOUNT_SIZE: u64 = 8; + // FIXME: is this a correct way to calculate (simple sum of sizes of components)? const BURN_ITEM_SIZE: u64 = ASSET_BASE_SIZE + AMOUNT_SIZE; -/// Represents an Orchard ZSA burn item. +/// Orchard ZSA burn item. #[derive(Clone, Debug, PartialEq, Eq)] pub struct BurnItem(AssetBase, Amount); @@ -59,18 +60,16 @@ impl TrustedPreallocate for BurnItem { } } -#[cfg(any(test, feature = "proptest-impl"))] impl serde::Serialize for BurnItem { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { - // FIXME: return custom error with a meaningful description? + // FIXME: return a custom error with a meaningful description? (self.0.to_bytes(), &self.1).serialize(serializer) } } -#[cfg(any(test, feature = "proptest-impl"))] impl<'de> serde::Deserialize<'de> for BurnItem { fn deserialize(deserializer: D) -> Result where @@ -87,3 +86,43 @@ impl<'de> serde::Deserialize<'de> for BurnItem { )) } } + +/// A special marker type indicating the absence of a burn field in Orchard ShieldedData for `V5` transactions. +/// Useful for unifying ShieldedData serialization and deserialization implementations across various +/// Orchard protocol variants (i.e. various transaction versions). +#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize)] +pub struct NoBurn; + +impl ZcashSerialize for NoBurn { + fn zcash_serialize(&self, mut _writer: W) -> Result<(), io::Error> { + Ok(()) + } +} + +impl ZcashDeserialize for NoBurn { + fn zcash_deserialize(mut _reader: R) -> Result { + Ok(Self) + } +} + +/// Orchard ZSA burn items (assets intended for burning) +#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize)] +pub struct Burn(Vec); + +impl From> for Burn { + fn from(inner: Vec) -> Self { + Self(inner) + } +} + +impl ZcashSerialize for Burn { + fn zcash_serialize(&self, writer: W) -> Result<(), io::Error> { + self.0.zcash_serialize(writer) + } +} + +impl ZcashDeserialize for Burn { + fn zcash_deserialize(reader: R) -> Result { + Ok(Burn(Vec::::zcash_deserialize(reader)?)) + } +} diff --git a/zebra-chain/src/orchard_zsa/serialize.rs b/zebra-chain/src/orchard_zsa/common.rs similarity index 94% rename from zebra-chain/src/orchard_zsa/serialize.rs rename to zebra-chain/src/orchard_zsa/common.rs index 6afc51e1887..deb3969ced7 100644 --- a/zebra-chain/src/orchard_zsa/serialize.rs +++ b/zebra-chain/src/orchard_zsa/common.rs @@ -7,7 +7,7 @@ use crate::serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, Z use orchard::note::AssetBase; // The size of the serialized AssetBase in bytes (used for TrustedPreallocate impls) -pub(crate) const ASSET_BASE_SIZE: u64 = 32; +pub(super) const ASSET_BASE_SIZE: u64 = 32; impl ZcashSerialize for AssetBase { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index be4451d7e82..edd85cf88d7 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -26,7 +26,7 @@ use orchard::{ Address, Note, }; -use super::serialize::ASSET_BASE_SIZE; +use super::common::ASSET_BASE_SIZE; /// Wrapper for `IssueBundle` used in the context of Transaction V6. This allows the implementation of /// a Serde serializer for unit tests within this crate. diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 25c669a16a3..eb8c7c56ed6 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -11,7 +11,6 @@ use crate::{ at_least_one, block::{self, arbitrary::MAX_PARTIAL_CHAIN_BLOCKS}, orchard, - orchard_zsa::arbitrary::ArbitraryBurn, parameters::{Network, NetworkUpgrade}, primitives::{Bctv14Proof, Groth16Proof, Halo2Proof, ZkSnarkProof}, sapling::{self, AnchorVariant, PerSpendAnchor, SharedAnchor}, @@ -21,6 +20,9 @@ use crate::{ LedgerState, }; +#[cfg(feature = "tx-v6")] +use crate::orchard_zsa::issuance::IssueData; + use itertools::Itertools; use super::{ @@ -133,23 +135,21 @@ impl Transaction { .boxed() } - fn v5_v6_strategy( + /// Helper function to generate the common transaction fields. + /// This function is generic over the Orchard shielded data type. + fn v5_v6_strategy_common( ledger_state: LedgerState, - construct_transaction: F, - ) -> BoxedStrategy - where - F: Fn( - NetworkUpgrade, - LockTime, - block::Height, - Vec, - Vec, - Option>, - Option>, - ) -> Transaction - + 'static, - V: Clone + 'static, - { + ) -> impl Strategy< + Value = ( + NetworkUpgrade, + LockTime, + block::Height, + Vec, + Vec, + Option>, + Option>, + ), + > + 'static { ( NetworkUpgrade::branch_id_strategy(), any::(), @@ -157,7 +157,7 @@ impl Transaction { transparent::Input::vec_strategy(&ledger_state, MAX_ARBITRARY_ITEMS), vec(any::(), 0..MAX_ARBITRARY_ITEMS), option::of(any::>()), - any::>>(), + option::of(any::>()), ) .prop_map( move |( @@ -169,6 +169,7 @@ impl Transaction { sapling_shielded_data, orchard_shielded_data, )| { + // Apply conditional logic based on ledger_state let network_upgrade = if ledger_state.transaction_has_valid_network_upgrade() { ledger_state.network_upgrade() } else { @@ -176,18 +177,20 @@ impl Transaction { }; let sapling_shielded_data = if ledger_state.height.is_min() { + // The genesis block should not contain any shielded data. None } else { sapling_shielded_data }; let orchard_shielded_data = if ledger_state.height.is_min() { + // The genesis block should not contain any shielded data. None } else { orchard_shielded_data }; - construct_transaction( + ( network_upgrade, lock_time, expiry_height, @@ -198,21 +201,13 @@ impl Transaction { ) }, ) - .boxed() } /// Generate a proptest strategy for V5 Transactions pub fn v5_strategy(ledger_state: LedgerState) -> BoxedStrategy { - Self::v5_v6_strategy( - ledger_state, - |network_upgrade, - lock_time, - expiry_height, - inputs, - outputs, - sapling_shielded_data, - orchard_shielded_data| { - Transaction::V5 { + Self::v5_v6_strategy_common::(ledger_state) + .prop_map( + move |( network_upgrade, lock_time, expiry_height, @@ -220,24 +215,43 @@ impl Transaction { outputs, sapling_shielded_data, orchard_shielded_data, - } - }, - ) + )| Transaction::V5 { + network_upgrade, + lock_time, + expiry_height, + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data, + }, + ) + .boxed() } /// Generate a proptest strategy for V6 Transactions #[cfg(feature = "tx-v6")] pub fn v6_strategy(ledger_state: LedgerState) -> BoxedStrategy { - Self::v5_v6_strategy( - ledger_state, - |network_upgrade, - lock_time, - expiry_height, - inputs, - outputs, - sapling_shielded_data, - orchard_shielded_data| { - Transaction::V6 { + Self::v5_v6_strategy_common::(ledger_state) + .prop_flat_map(|common_fields| { + // FIXME: Can IssueData present in V6 transaction without orchard::ShieldedData? + // If no, we possibly need to use something like prop_filter_map to filter wrong + // combnations (orchard_shielded_data: None, orchard_zsa_issue_data: Some) + option::of(any::()) + .prop_map(move |issue_data| (common_fields.clone(), issue_data)) + }) + .prop_map( + |( + ( + network_upgrade, + lock_time, + expiry_height, + inputs, + outputs, + sapling_shielded_data, + orchard_shielded_data, + ), + orchard_zsa_issue_data, + )| Transaction::V6 { network_upgrade, lock_time, expiry_height, @@ -245,11 +259,10 @@ impl Transaction { outputs, sapling_shielded_data, orchard_shielded_data, - // FIXME: generate a real arbitrary orchard_zsa_issue_data - orchard_zsa_issue_data: Default::default(), - } - }, - ) + orchard_zsa_issue_data, + }, + ) + .boxed() } /// Proptest Strategy for creating a Vector of transactions where the first @@ -768,10 +781,11 @@ impl Arbitrary for sapling::TransferData { type Strategy = BoxedStrategy; } -impl Arbitrary for orchard::ShieldedData +impl Arbitrary for orchard::ShieldedData +// FIXME: remove the following lines // FIXME: define the constraint in OrchardFlavorExt? -where - ::Strategy: 'static, +//where +// ::Strategy: 'static, { type Parameters = (); @@ -787,7 +801,7 @@ where ), any::(), #[cfg(feature = "tx-v6")] - V::arbitrary_burn(), + any::(), ) .prop_map(|props| { #[cfg(not(feature = "tx-v6"))] From d8964e714e6527ba6632b0b6451eab934baa8040 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 11:05:59 +0200 Subject: [PATCH 032/157] Fix of new_regtest call (as it additionally needs Nu7 arg now) --- zebrad/tests/common/regtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebrad/tests/common/regtest.rs b/zebrad/tests/common/regtest.rs index bf1cba697de..f7b571e5a09 100644 --- a/zebrad/tests/common/regtest.rs +++ b/zebrad/tests/common/regtest.rs @@ -43,7 +43,7 @@ pub(crate) async fn submit_blocks_test() -> Result<()> { let _init_guard = zebra_test::init(); info!("starting regtest submit_blocks test"); - let network = Network::new_regtest(None, None); + let network = Network::new_regtest(None, None, None); let mut config = os_assigned_rpc_port_config(false, &network)?; config.mempool.debug_enable_at_height = Some(0); From e8abddd11e856fe0d972b1bbf2c93949e2040e34 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 13:15:21 +0200 Subject: [PATCH 033/157] Fix of new_regtest call (as it additionally needs Nu7 arg now) (2) --- zebra-consensus/src/checkpoint/list/tests.rs | 2 +- zebrad/tests/acceptance.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zebra-consensus/src/checkpoint/list/tests.rs b/zebra-consensus/src/checkpoint/list/tests.rs index 5a2fe803f3d..698eaf36082 100644 --- a/zebra-consensus/src/checkpoint/list/tests.rs +++ b/zebra-consensus/src/checkpoint/list/tests.rs @@ -237,7 +237,7 @@ fn checkpoint_list_load_hard_coded() -> Result<(), BoxError> { let _ = Mainnet.checkpoint_list(); let _ = Network::new_default_testnet().checkpoint_list(); - let _ = Network::new_regtest(None, None).checkpoint_list(); + let _ = Network::new_regtest(None, None, None).checkpoint_list(); Ok(()) } diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index cd3572ce3f2..c71cede4c3b 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -2907,7 +2907,7 @@ async fn fully_synced_rpc_z_getsubtreesbyindex_snapshot_test() -> Result<()> { async fn validate_regtest_genesis_block() { let _init_guard = zebra_test::init(); - let network = Network::new_regtest(None, None); + let network = Network::new_regtest(None, None, None); let state = zebra_state::init_test(&network); let ( block_verifier_router, @@ -2982,7 +2982,7 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { use zebra_state::{ReadResponse, Response}; let _init_guard = zebra_test::init(); - let mut config = os_assigned_rpc_port_config(false, &Network::new_regtest(None, None))?; + let mut config = os_assigned_rpc_port_config(false, &Network::new_regtest(None, None, None))?; config.state.ephemeral = false; let network = config.network.network.clone(); From 23d9e7754ae959f5f6d8174ad0f3d7bce927545d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 14:46:17 +0200 Subject: [PATCH 034/157] Set Nu7 as a network update for testnet in zebra-chain network tests --- zebra-chain/src/parameters/network/tests/vectors.rs | 3 +-- zebra-chain/src/parameters/network_upgrade.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/zebra-chain/src/parameters/network/tests/vectors.rs b/zebra-chain/src/parameters/network/tests/vectors.rs index ca341184b8c..6c1426e4e0e 100644 --- a/zebra-chain/src/parameters/network/tests/vectors.rs +++ b/zebra-chain/src/parameters/network/tests/vectors.rs @@ -109,8 +109,7 @@ fn activates_network_upgrades_correctly() { let expected_activation_height = 1; let network = testnet::Parameters::build() .with_activation_heights(ConfiguredActivationHeights { - // FIXME: nu7? - nu6: Some(expected_activation_height), + nu7: Some(expected_activation_height), ..Default::default() }) .to_network(); diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 845bbec981e..4ca8c6a8777 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -133,8 +133,8 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_028_500), Canopy), (block::Height(1_842_420), Nu5), (block::Height(2_976_000), Nu6), - // FIXME: TODO: Add NU7 with a correct value - // (block::Height(2_942_001), Nu7), + // FIXME: TODO: Set a correct value for NU7 + (block::Height(2_942_001), Nu7), ]; /// Fake testnet network upgrade activation heights, used in tests. From d2313fbdac09803a829a3bae2531d8065a8dc1b8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 15:05:57 +0200 Subject: [PATCH 035/157] Fix Orchard ZSA issuance serialization (use to_vec for notes and asset_desc to convert slice to vec, as slices require implementation of the serialization from scratch --- zebra-chain/src/orchard_zsa/issuance.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index 3e55edcf14d..9d31276072c 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -5,8 +5,8 @@ use std::{fmt::Debug, io}; use crate::{ block::MAX_BLOCK_BYTES, serialization::{ - zcash_serialize_empty_list, ReadZcashExt, SerializationError, TrustedPreallocate, - ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize, + zcash_serialize_bytes, zcash_serialize_empty_list, ReadZcashExt, SerializationError, + TrustedPreallocate, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize, }, }; @@ -176,8 +176,8 @@ impl TrustedPreallocate for Note { impl ZcashSerialize for IssueAction { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { writer.write_u8(self.is_finalized().as_u8())?; - self.notes().zcash_serialize(&mut writer)?; - self.asset_desc().zcash_serialize(&mut writer)?; + self.notes().to_vec().zcash_serialize(&mut writer)?; + zcash_serialize_bytes(&self.asset_desc().to_vec(), &mut writer)?; Ok(()) } } From e0adb4ca39ea389589a729c1fc294b6658b7fd79 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 15:14:51 +0200 Subject: [PATCH 036/157] Fix serde names for NU7 --- zebra-chain/src/parameters/network_upgrade.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 4ca8c6a8777..325f2558b17 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -63,6 +63,7 @@ pub enum NetworkUpgrade { #[serde(rename = "NU6")] Nu6, /// The Zcash protocol after the NU7 upgrade. + #[serde(rename = "NU7")] Nu7, } From 0daf0ce05a5a9bdef648860862b35b0c001350e8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 15:19:20 +0200 Subject: [PATCH 037/157] Update test snapshot in zebra-rpc to use NU7 --- .../tests/snapshots/get_blockchain_info@testnet_10.snap | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap index 3bea6c01509..9d7ea3f5176 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap @@ -1,5 +1,6 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs +assertion_line: 562 expression: info --- { @@ -69,6 +70,11 @@ expression: info "name": "NU6", "activationheight": 2976000, "status": "pending" + }, + "c8e71056": { + "name": "NU7", + "activationheight": 2942001, + "status": "pending" } }, "consensus": { From 6a9334aa2a24f08f084f38db3c61f877a074f319 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 18 Oct 2024 09:55:02 +0200 Subject: [PATCH 038/157] Enable test-dependencies feaure flag for orchard if proptest-impl is enabled for zebra-chain --- zebra-chain/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index cede4329aed..8e1f043629e 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -57,6 +57,7 @@ proptest-impl = [ "rand_chacha", "tokio/tracing", "zebra-test", + "orchard/test-dependencies" ] bench = ["zebra-test"] From 2fabac727ea30c921c3635a1d23b610c24e87f9d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 29 Jul 2024 10:13:56 +0200 Subject: [PATCH 039/157] Prepare to use Orchard ZSA --- zebra-chain/Cargo.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 3f932ea298a..cb30fb1873d 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -68,7 +68,7 @@ bitflags = "2.5.0" bitflags-serde-legacy = "0.1.1" blake2b_simd = "1.0.2" blake2s_simd = "1.0.2" -bridgetree = "0.6.0" +bridgetree = "0.4.0" bs58 = { version = "0.5.1", features = ["check"] } byteorder = "1.5.0" @@ -178,3 +178,7 @@ required-features = ["bench"] [[bench]] name = "redpallas" harness = false + +# FIXME: remove this and all zcash_unstable usage in the code after updating librustzcash +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } From 836516d84d099322d7add5c38a2afa6f7c1ef88b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 08:54:05 +0200 Subject: [PATCH 040/157] Add basic CI checks workflow --- .github/workflows/ci-basic.yml | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/ci-basic.yml diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml new file mode 100644 index 00000000000..92dedd60cb0 --- /dev/null +++ b/.github/workflows/ci-basic.yml @@ -0,0 +1,36 @@ +name: Basic checks + +on: [push, pull_request] + +jobs: + test: + name: Test on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + + steps: + - uses: actions/checkout@v4 + - name: Run tests + run: cargo test --verbose + - name: Verify working directory is clean + run: git diff --exit-code + + doc-links: + name: Intra-doc links + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: cargo fetch + # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. + - name: Check intra-doc links + run: cargo doc --all-features --document-private-items + + fmt: + name: Rustfmt + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: cargo fmt -- --check From e29a64cde48f50037e4305ea176a42a2d95e7e14 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 10:28:32 +0200 Subject: [PATCH 041/157] Fix ci-basic.yml --- .github/workflows/ci-basic.yml | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 92dedd60cb0..7b50109c04a 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -12,25 +12,13 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install dependencies on Ubuntu + run: sudo apt-get update && sudo apt-get install -y protoc - name: Run tests run: cargo test --verbose - name: Verify working directory is clean run: git diff --exit-code - - doc-links: - name: Intra-doc links - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: cargo fetch - # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. - - name: Check intra-doc links + - name: Run doc check run: cargo doc --all-features --document-private-items - - fmt: - name: Rustfmt - timeout-minutes: 30 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: cargo fmt -- --check + - name: Run format check + run: cargo fmt -- --check From 790072d9115c146ef3229e3ab5bc328001b7cb58 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 10:31:29 +0200 Subject: [PATCH 042/157] Fix ci-basic.yml (2) --- .github/workflows/ci-basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 7b50109c04a..522329e2440 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu - run: sudo apt-get update && sudo apt-get install -y protoc + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler - name: Run tests run: cargo test --verbose - name: Verify working directory is clean From 769588293ac04c8520e3604026f8873fd73247d6 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 10:52:49 +0200 Subject: [PATCH 043/157] Add installing of build-essential to ci-basic.yml --- .github/workflows/ci-basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 522329e2440..be3d44917eb 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential - name: Run tests run: cargo test --verbose - name: Verify working directory is clean From 9a8d37eb0b452840eee56f7c906f8ab5118555da Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 20:57:11 +0200 Subject: [PATCH 044/157] Try to use librocksdb-dev in ci-basic.yml --- .github/workflows/ci-basic.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index be3d44917eb..547b64446c3 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -1,6 +1,7 @@ name: Basic checks -on: [push, pull_request] +#on: [push, pull_request] +on: [push] jobs: test: @@ -13,9 +14,9 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev - name: Run tests - run: cargo test --verbose + run: ROCKSDB_LIB_DIR=/usr/lib SNAPPY_LIB_DIR=/usr/lib/x86_64-linux-gnu cargo test --verbose - name: Verify working directory is clean run: git diff --exit-code - name: Run doc check From 925e81a79d1c4883da54df0078082c09685007c9 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 21:05:06 +0200 Subject: [PATCH 045/157] Run ci-basic.yml on ubuntu-24.04 --- .github/workflows/ci-basic.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 547b64446c3..840d406b609 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -9,7 +9,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest] + os: [ubuntu-24.04] steps: - uses: actions/checkout@v4 From 61f9f95899156712a688c574e3f03a59656fffad Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 3 Sep 2024 22:32:19 +0200 Subject: [PATCH 046/157] Enable nu6 cfg flag in ci-basic.yml --- .github/workflows/ci-basic.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 840d406b609..4a9bdafa1b5 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -11,12 +11,20 @@ jobs: matrix: os: [ubuntu-24.04] + env: + # Use system-installed RocksDB library instead of building from scratch + ROCKSDB_LIB_DIR: /usr/lib + # Use system-installed Snappy library for compression in RocksDB + SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu + # Enable the `nu6` feature in `zcash_protocol` + RUSTFLAGS: '--cfg zcash_unstable="nu6"' + steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev - name: Run tests - run: ROCKSDB_LIB_DIR=/usr/lib SNAPPY_LIB_DIR=/usr/lib/x86_64-linux-gnu cargo test --verbose + run: cargo test --verbose - name: Verify working directory is clean run: git diff --exit-code - name: Run doc check From 2e9c089b10b6b35170a6cbfe6a6e16852c6b42f0 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 4 Sep 2024 10:51:26 +0200 Subject: [PATCH 047/157] Adjust the code with librustzcash/zcash_protocol nu6 related changes --- zebra-chain/src/parameters/network_upgrade.rs | 5 ++++ .../src/primitives/zcash_primitives.rs | 27 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 957b96de944..40007293ab9 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -531,7 +531,12 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Heartwood => Self::Heartwood, zcash_protocol::consensus::NetworkUpgrade::Canopy => Self::Canopy, zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, + // FIXME: remove cfg + #[cfg(zcash_unstable = "nu6")] zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, + // FIXME: remove cfg and process Nu7 properly (uses Self::Nu6 for now) + #[cfg(zcash_unstable = "nu6")] + zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, } } } diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 7ab2f32d751..be90f18ed23 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -137,6 +137,16 @@ impl zp_tx::components::orchard::MapAuth + for IdentityMap +{ + fn map_issue_authorization(&self, s: orchard::issuance::Signed) -> orchard::issuance::Signed { + s + } +} + #[derive(Debug)] struct PrecomputedAuth<'a> { _phantom: std::marker::PhantomData<&'a ()>, @@ -146,6 +156,14 @@ impl<'a> zp_tx::Authorization for PrecomputedAuth<'a> { type TransparentAuth = TransparentAuth<'a>; type SaplingAuth = sapling_crypto::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; + + // FIXME: is this correct? + #[cfg(zcash_unstable = "nu6")] + type OrchardZsaAuth = orchard::bundle::Authorized; + + // FIXME: is this correct? + #[cfg(zcash_unstable = "nu6")] + type IssueAuth = orchard::issuance::Signed; } // End of (mostly) copied code @@ -275,7 +293,14 @@ impl<'a> PrecomputedTxData<'a> { }; let tx_data: zp_tx::TransactionData = alt_tx .into_data() - .map_authorization(f_transparent, IdentityMap, IdentityMap); + // FIXME: do we need to pass another arg values or orchard_zsa and issue instead of IdentityMap? + .map_authorization( + f_transparent, + IdentityMap, + IdentityMap, + IdentityMap, + IdentityMap, + ); PrecomputedTxData { tx_data, From 0dce1a4441c4e2c73a5693e70488e856de58c45a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 4 Sep 2024 11:40:25 +0200 Subject: [PATCH 048/157] Add RUSTDOCFLAGS to ci-basic.yml --- .github/workflows/ci-basic.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 4a9bdafa1b5..c2cde8686bf 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -18,11 +18,13 @@ jobs: SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu # Enable the `nu6` feature in `zcash_protocol` RUSTFLAGS: '--cfg zcash_unstable="nu6"' + RUSTDOCFLAGS: '--cfg zcash_unstable="nu6"' steps: - uses: actions/checkout@v4 - name: Install dependencies on Ubuntu - run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev + #run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev + run: sudo apt-get update && sudo apt-get install -y protobuf-compiler librocksdb-dev - name: Run tests run: cargo test --verbose - name: Verify working directory is clean From e294837071ef3bf3d282a513da18b0fdf9491540 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 29 Oct 2024 14:52:10 +0100 Subject: [PATCH 049/157] Set Rust cfg zcash_unstable to nu6 in .cargo/config.toml --- .cargo/config.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 1368e393fe4..ab7095e21bd 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,6 +3,9 @@ # Flags that apply to all Zebra crates and configurations [target.'cfg(all())'] rustflags = [ + # FIXME: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) + "--cfg", "zcash_unstable=\"nu6\"", + # Zebra standard lints for Rust 1.65+ # High-risk code From 9f55f355ca27b2db7947a51886a27a2453fbc27c Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 29 Oct 2024 14:55:15 +0100 Subject: [PATCH 050/157] Disable GCP/Firebase/Docker/deploy related workflows (add .disabled suffix to their .yml files) --- ...ternal.yml => cd-deploy-nodes-gcp.patch-external.yml.disabled} | 0 ...nodes-gcp.patch.yml => cd-deploy-nodes-gcp.patch.yml.disabled} | 0 .../{cd-deploy-nodes-gcp.yml => cd-deploy-nodes-gcp.yml.disabled} | 0 ...-gcp-resources.yml => chore-delete-gcp-resources.yml.disabled} | 0 .github/workflows/{ci-basic.yml => ci-basic.yml.disabled} | 0 ...-build-crates.patch.yml => ci-build-crates.patch.yml.disabled} | 0 .../{ci-build-crates.yml => ci-build-crates.yml.disabled} | 0 .../{ci-coverage.patch.yml => ci-coverage.patch.yml.disabled} | 0 .github/workflows/{ci-coverage.yml => ci-coverage.yml.disabled} | 0 .../workflows/{ci-lint.patch.yml => ci-lint.patch.yml.disabled} | 0 .github/workflows/{ci-lint.yml => ci-lint.yml.disabled} | 0 ...ts.patch-external.yml => ci-tests.patch-external.yml.disabled} | 0 .../workflows/{ci-tests.patch.yml => ci-tests.patch.yml.disabled} | 0 .github/workflows/{ci-tests.yml => ci-tests.yml.disabled} | 0 ...nit-tests-os.patch.yml => ci-unit-tests-os.patch.yml.disabled} | 0 .../{ci-unit-tests-os.yml => ci-unit-tests-os.yml.disabled} | 0 ...ernal.yml => docs-deploy-firebase.patch-external.yml.disabled} | 0 ...firebase.patch.yml => docs-deploy-firebase.patch.yml.disabled} | 0 ...docs-deploy-firebase.yml => docs-deploy-firebase.yml.disabled} | 0 ...ub-description.yml => docs-dockerhub-description.yml.disabled} | 0 ...manual-zcashd-deploy.yml => manual-zcashd-deploy.yml.disabled} | 0 .../{release-binaries.yml => release-binaries.yml.disabled} | 0 ...e-crates-io.patch.yml => release-crates-io.patch.yml.disabled} | 0 .../{release-crates-io.yml => release-crates-io.yml.disabled} | 0 .../{release-drafter.yml => release-drafter.yml.disabled} | 0 ...build-docker-image.yml => sub-build-docker-image.yml.disabled} | 0 ...on-tests-gcp.yml => sub-ci-integration-tests-gcp.yml.disabled} | 0 ...nit-tests-docker.yml => sub-ci-unit-tests-docker.yml.disabled} | 0 ...ests-gcp.yml => sub-deploy-integration-tests-gcp.yml.disabled} | 0 ...b-find-cached-disks.yml => sub-find-cached-disks.yml.disabled} | 0 ...b-test-zebra-config.yml => sub-test-zebra-config.yml.disabled} | 0 31 files changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{cd-deploy-nodes-gcp.patch-external.yml => cd-deploy-nodes-gcp.patch-external.yml.disabled} (100%) rename .github/workflows/{cd-deploy-nodes-gcp.patch.yml => cd-deploy-nodes-gcp.patch.yml.disabled} (100%) rename .github/workflows/{cd-deploy-nodes-gcp.yml => cd-deploy-nodes-gcp.yml.disabled} (100%) rename .github/workflows/{chore-delete-gcp-resources.yml => chore-delete-gcp-resources.yml.disabled} (100%) rename .github/workflows/{ci-basic.yml => ci-basic.yml.disabled} (100%) rename .github/workflows/{ci-build-crates.patch.yml => ci-build-crates.patch.yml.disabled} (100%) rename .github/workflows/{ci-build-crates.yml => ci-build-crates.yml.disabled} (100%) rename .github/workflows/{ci-coverage.patch.yml => ci-coverage.patch.yml.disabled} (100%) rename .github/workflows/{ci-coverage.yml => ci-coverage.yml.disabled} (100%) rename .github/workflows/{ci-lint.patch.yml => ci-lint.patch.yml.disabled} (100%) rename .github/workflows/{ci-lint.yml => ci-lint.yml.disabled} (100%) rename .github/workflows/{ci-tests.patch-external.yml => ci-tests.patch-external.yml.disabled} (100%) rename .github/workflows/{ci-tests.patch.yml => ci-tests.patch.yml.disabled} (100%) rename .github/workflows/{ci-tests.yml => ci-tests.yml.disabled} (100%) rename .github/workflows/{ci-unit-tests-os.patch.yml => ci-unit-tests-os.patch.yml.disabled} (100%) rename .github/workflows/{ci-unit-tests-os.yml => ci-unit-tests-os.yml.disabled} (100%) rename .github/workflows/{docs-deploy-firebase.patch-external.yml => docs-deploy-firebase.patch-external.yml.disabled} (100%) rename .github/workflows/{docs-deploy-firebase.patch.yml => docs-deploy-firebase.patch.yml.disabled} (100%) rename .github/workflows/{docs-deploy-firebase.yml => docs-deploy-firebase.yml.disabled} (100%) rename .github/workflows/{docs-dockerhub-description.yml => docs-dockerhub-description.yml.disabled} (100%) rename .github/workflows/{manual-zcashd-deploy.yml => manual-zcashd-deploy.yml.disabled} (100%) rename .github/workflows/{release-binaries.yml => release-binaries.yml.disabled} (100%) rename .github/workflows/{release-crates-io.patch.yml => release-crates-io.patch.yml.disabled} (100%) rename .github/workflows/{release-crates-io.yml => release-crates-io.yml.disabled} (100%) rename .github/workflows/{release-drafter.yml => release-drafter.yml.disabled} (100%) rename .github/workflows/{sub-build-docker-image.yml => sub-build-docker-image.yml.disabled} (100%) rename .github/workflows/{sub-ci-integration-tests-gcp.yml => sub-ci-integration-tests-gcp.yml.disabled} (100%) rename .github/workflows/{sub-ci-unit-tests-docker.yml => sub-ci-unit-tests-docker.yml.disabled} (100%) rename .github/workflows/{sub-deploy-integration-tests-gcp.yml => sub-deploy-integration-tests-gcp.yml.disabled} (100%) rename .github/workflows/{sub-find-cached-disks.yml => sub-find-cached-disks.yml.disabled} (100%) rename .github/workflows/{sub-test-zebra-config.yml => sub-test-zebra-config.yml.disabled} (100%) diff --git a/.github/workflows/cd-deploy-nodes-gcp.patch-external.yml b/.github/workflows/cd-deploy-nodes-gcp.patch-external.yml.disabled similarity index 100% rename from .github/workflows/cd-deploy-nodes-gcp.patch-external.yml rename to .github/workflows/cd-deploy-nodes-gcp.patch-external.yml.disabled diff --git a/.github/workflows/cd-deploy-nodes-gcp.patch.yml b/.github/workflows/cd-deploy-nodes-gcp.patch.yml.disabled similarity index 100% rename from .github/workflows/cd-deploy-nodes-gcp.patch.yml rename to .github/workflows/cd-deploy-nodes-gcp.patch.yml.disabled diff --git a/.github/workflows/cd-deploy-nodes-gcp.yml b/.github/workflows/cd-deploy-nodes-gcp.yml.disabled similarity index 100% rename from .github/workflows/cd-deploy-nodes-gcp.yml rename to .github/workflows/cd-deploy-nodes-gcp.yml.disabled diff --git a/.github/workflows/chore-delete-gcp-resources.yml b/.github/workflows/chore-delete-gcp-resources.yml.disabled similarity index 100% rename from .github/workflows/chore-delete-gcp-resources.yml rename to .github/workflows/chore-delete-gcp-resources.yml.disabled diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml.disabled similarity index 100% rename from .github/workflows/ci-basic.yml rename to .github/workflows/ci-basic.yml.disabled diff --git a/.github/workflows/ci-build-crates.patch.yml b/.github/workflows/ci-build-crates.patch.yml.disabled similarity index 100% rename from .github/workflows/ci-build-crates.patch.yml rename to .github/workflows/ci-build-crates.patch.yml.disabled diff --git a/.github/workflows/ci-build-crates.yml b/.github/workflows/ci-build-crates.yml.disabled similarity index 100% rename from .github/workflows/ci-build-crates.yml rename to .github/workflows/ci-build-crates.yml.disabled diff --git a/.github/workflows/ci-coverage.patch.yml b/.github/workflows/ci-coverage.patch.yml.disabled similarity index 100% rename from .github/workflows/ci-coverage.patch.yml rename to .github/workflows/ci-coverage.patch.yml.disabled diff --git a/.github/workflows/ci-coverage.yml b/.github/workflows/ci-coverage.yml.disabled similarity index 100% rename from .github/workflows/ci-coverage.yml rename to .github/workflows/ci-coverage.yml.disabled diff --git a/.github/workflows/ci-lint.patch.yml b/.github/workflows/ci-lint.patch.yml.disabled similarity index 100% rename from .github/workflows/ci-lint.patch.yml rename to .github/workflows/ci-lint.patch.yml.disabled diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml.disabled similarity index 100% rename from .github/workflows/ci-lint.yml rename to .github/workflows/ci-lint.yml.disabled diff --git a/.github/workflows/ci-tests.patch-external.yml b/.github/workflows/ci-tests.patch-external.yml.disabled similarity index 100% rename from .github/workflows/ci-tests.patch-external.yml rename to .github/workflows/ci-tests.patch-external.yml.disabled diff --git a/.github/workflows/ci-tests.patch.yml b/.github/workflows/ci-tests.patch.yml.disabled similarity index 100% rename from .github/workflows/ci-tests.patch.yml rename to .github/workflows/ci-tests.patch.yml.disabled diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml.disabled similarity index 100% rename from .github/workflows/ci-tests.yml rename to .github/workflows/ci-tests.yml.disabled diff --git a/.github/workflows/ci-unit-tests-os.patch.yml b/.github/workflows/ci-unit-tests-os.patch.yml.disabled similarity index 100% rename from .github/workflows/ci-unit-tests-os.patch.yml rename to .github/workflows/ci-unit-tests-os.patch.yml.disabled diff --git a/.github/workflows/ci-unit-tests-os.yml b/.github/workflows/ci-unit-tests-os.yml.disabled similarity index 100% rename from .github/workflows/ci-unit-tests-os.yml rename to .github/workflows/ci-unit-tests-os.yml.disabled diff --git a/.github/workflows/docs-deploy-firebase.patch-external.yml b/.github/workflows/docs-deploy-firebase.patch-external.yml.disabled similarity index 100% rename from .github/workflows/docs-deploy-firebase.patch-external.yml rename to .github/workflows/docs-deploy-firebase.patch-external.yml.disabled diff --git a/.github/workflows/docs-deploy-firebase.patch.yml b/.github/workflows/docs-deploy-firebase.patch.yml.disabled similarity index 100% rename from .github/workflows/docs-deploy-firebase.patch.yml rename to .github/workflows/docs-deploy-firebase.patch.yml.disabled diff --git a/.github/workflows/docs-deploy-firebase.yml b/.github/workflows/docs-deploy-firebase.yml.disabled similarity index 100% rename from .github/workflows/docs-deploy-firebase.yml rename to .github/workflows/docs-deploy-firebase.yml.disabled diff --git a/.github/workflows/docs-dockerhub-description.yml b/.github/workflows/docs-dockerhub-description.yml.disabled similarity index 100% rename from .github/workflows/docs-dockerhub-description.yml rename to .github/workflows/docs-dockerhub-description.yml.disabled diff --git a/.github/workflows/manual-zcashd-deploy.yml b/.github/workflows/manual-zcashd-deploy.yml.disabled similarity index 100% rename from .github/workflows/manual-zcashd-deploy.yml rename to .github/workflows/manual-zcashd-deploy.yml.disabled diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml.disabled similarity index 100% rename from .github/workflows/release-binaries.yml rename to .github/workflows/release-binaries.yml.disabled diff --git a/.github/workflows/release-crates-io.patch.yml b/.github/workflows/release-crates-io.patch.yml.disabled similarity index 100% rename from .github/workflows/release-crates-io.patch.yml rename to .github/workflows/release-crates-io.patch.yml.disabled diff --git a/.github/workflows/release-crates-io.yml b/.github/workflows/release-crates-io.yml.disabled similarity index 100% rename from .github/workflows/release-crates-io.yml rename to .github/workflows/release-crates-io.yml.disabled diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml.disabled similarity index 100% rename from .github/workflows/release-drafter.yml rename to .github/workflows/release-drafter.yml.disabled diff --git a/.github/workflows/sub-build-docker-image.yml b/.github/workflows/sub-build-docker-image.yml.disabled similarity index 100% rename from .github/workflows/sub-build-docker-image.yml rename to .github/workflows/sub-build-docker-image.yml.disabled diff --git a/.github/workflows/sub-ci-integration-tests-gcp.yml b/.github/workflows/sub-ci-integration-tests-gcp.yml.disabled similarity index 100% rename from .github/workflows/sub-ci-integration-tests-gcp.yml rename to .github/workflows/sub-ci-integration-tests-gcp.yml.disabled diff --git a/.github/workflows/sub-ci-unit-tests-docker.yml b/.github/workflows/sub-ci-unit-tests-docker.yml.disabled similarity index 100% rename from .github/workflows/sub-ci-unit-tests-docker.yml rename to .github/workflows/sub-ci-unit-tests-docker.yml.disabled diff --git a/.github/workflows/sub-deploy-integration-tests-gcp.yml b/.github/workflows/sub-deploy-integration-tests-gcp.yml.disabled similarity index 100% rename from .github/workflows/sub-deploy-integration-tests-gcp.yml rename to .github/workflows/sub-deploy-integration-tests-gcp.yml.disabled diff --git a/.github/workflows/sub-find-cached-disks.yml b/.github/workflows/sub-find-cached-disks.yml.disabled similarity index 100% rename from .github/workflows/sub-find-cached-disks.yml rename to .github/workflows/sub-find-cached-disks.yml.disabled diff --git a/.github/workflows/sub-test-zebra-config.yml b/.github/workflows/sub-test-zebra-config.yml.disabled similarity index 100% rename from .github/workflows/sub-test-zebra-config.yml rename to .github/workflows/sub-test-zebra-config.yml.disabled From 6b43dd19508e87a897f40f3ec4bcd7340366a7ab Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 29 Oct 2024 15:02:32 +0100 Subject: [PATCH 051/157] Trigger CI From c6f8913c0a410578645cd29be9204152cdb21097 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 29 Oct 2024 15:07:21 +0100 Subject: [PATCH 052/157] Restore the names of ci-*.yml files )i.e. non GCP/Firebase/Docker/deploy related workflows (add .disabled suffix to their .yml files) --- .github/workflows/{ci-basic.yml.disabled => ci-basic.yml} | 0 ...-build-crates.patch.yml.disabled => ci-build-crates.patch.yml} | 0 .../{ci-build-crates.yml.disabled => ci-build-crates.yml} | 0 .../{ci-coverage.patch.yml.disabled => ci-coverage.patch.yml} | 0 .github/workflows/{ci-coverage.yml.disabled => ci-coverage.yml} | 0 .../workflows/{ci-lint.patch.yml.disabled => ci-lint.patch.yml} | 0 .github/workflows/{ci-lint.yml.disabled => ci-lint.yml} | 0 ...ts.patch-external.yml.disabled => ci-tests.patch-external.yml} | 0 .../workflows/{ci-tests.patch.yml.disabled => ci-tests.patch.yml} | 0 .github/workflows/{ci-tests.yml.disabled => ci-tests.yml} | 0 ...nit-tests-os.patch.yml.disabled => ci-unit-tests-os.patch.yml} | 0 .../{ci-unit-tests-os.yml.disabled => ci-unit-tests-os.yml} | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{ci-basic.yml.disabled => ci-basic.yml} (100%) rename .github/workflows/{ci-build-crates.patch.yml.disabled => ci-build-crates.patch.yml} (100%) rename .github/workflows/{ci-build-crates.yml.disabled => ci-build-crates.yml} (100%) rename .github/workflows/{ci-coverage.patch.yml.disabled => ci-coverage.patch.yml} (100%) rename .github/workflows/{ci-coverage.yml.disabled => ci-coverage.yml} (100%) rename .github/workflows/{ci-lint.patch.yml.disabled => ci-lint.patch.yml} (100%) rename .github/workflows/{ci-lint.yml.disabled => ci-lint.yml} (100%) rename .github/workflows/{ci-tests.patch-external.yml.disabled => ci-tests.patch-external.yml} (100%) rename .github/workflows/{ci-tests.patch.yml.disabled => ci-tests.patch.yml} (100%) rename .github/workflows/{ci-tests.yml.disabled => ci-tests.yml} (100%) rename .github/workflows/{ci-unit-tests-os.patch.yml.disabled => ci-unit-tests-os.patch.yml} (100%) rename .github/workflows/{ci-unit-tests-os.yml.disabled => ci-unit-tests-os.yml} (100%) diff --git a/.github/workflows/ci-basic.yml.disabled b/.github/workflows/ci-basic.yml similarity index 100% rename from .github/workflows/ci-basic.yml.disabled rename to .github/workflows/ci-basic.yml diff --git a/.github/workflows/ci-build-crates.patch.yml.disabled b/.github/workflows/ci-build-crates.patch.yml similarity index 100% rename from .github/workflows/ci-build-crates.patch.yml.disabled rename to .github/workflows/ci-build-crates.patch.yml diff --git a/.github/workflows/ci-build-crates.yml.disabled b/.github/workflows/ci-build-crates.yml similarity index 100% rename from .github/workflows/ci-build-crates.yml.disabled rename to .github/workflows/ci-build-crates.yml diff --git a/.github/workflows/ci-coverage.patch.yml.disabled b/.github/workflows/ci-coverage.patch.yml similarity index 100% rename from .github/workflows/ci-coverage.patch.yml.disabled rename to .github/workflows/ci-coverage.patch.yml diff --git a/.github/workflows/ci-coverage.yml.disabled b/.github/workflows/ci-coverage.yml similarity index 100% rename from .github/workflows/ci-coverage.yml.disabled rename to .github/workflows/ci-coverage.yml diff --git a/.github/workflows/ci-lint.patch.yml.disabled b/.github/workflows/ci-lint.patch.yml similarity index 100% rename from .github/workflows/ci-lint.patch.yml.disabled rename to .github/workflows/ci-lint.patch.yml diff --git a/.github/workflows/ci-lint.yml.disabled b/.github/workflows/ci-lint.yml similarity index 100% rename from .github/workflows/ci-lint.yml.disabled rename to .github/workflows/ci-lint.yml diff --git a/.github/workflows/ci-tests.patch-external.yml.disabled b/.github/workflows/ci-tests.patch-external.yml similarity index 100% rename from .github/workflows/ci-tests.patch-external.yml.disabled rename to .github/workflows/ci-tests.patch-external.yml diff --git a/.github/workflows/ci-tests.patch.yml.disabled b/.github/workflows/ci-tests.patch.yml similarity index 100% rename from .github/workflows/ci-tests.patch.yml.disabled rename to .github/workflows/ci-tests.patch.yml diff --git a/.github/workflows/ci-tests.yml.disabled b/.github/workflows/ci-tests.yml similarity index 100% rename from .github/workflows/ci-tests.yml.disabled rename to .github/workflows/ci-tests.yml diff --git a/.github/workflows/ci-unit-tests-os.patch.yml.disabled b/.github/workflows/ci-unit-tests-os.patch.yml similarity index 100% rename from .github/workflows/ci-unit-tests-os.patch.yml.disabled rename to .github/workflows/ci-unit-tests-os.patch.yml diff --git a/.github/workflows/ci-unit-tests-os.yml.disabled b/.github/workflows/ci-unit-tests-os.yml similarity index 100% rename from .github/workflows/ci-unit-tests-os.yml.disabled rename to .github/workflows/ci-unit-tests-os.yml From 1c061e9a95419b44dc85f3740b2fe010a5f195e7 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 29 Oct 2024 16:07:05 +0100 Subject: [PATCH 053/157] Update Cargo.lock --- Cargo.lock | 216 ++++++++++++++++++++++++++++------------------------- 1 file changed, 113 insertions(+), 103 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1df18e16559..b399cef361e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,7 +240,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -251,7 +251,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -430,7 +430,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.79", + "syn 2.0.85", "which", ] @@ -596,9 +596,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bzip2-sys" @@ -833,7 +833,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1097,7 +1097,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1145,7 +1145,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1167,7 +1167,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -1482,6 +1482,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1522,9 +1528,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1537,9 +1543,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1547,15 +1553,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1564,38 +1570,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1744,7 +1750,7 @@ dependencies = [ [[package]] name = "halo2_gadgets" version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?branch=zsa1#1195c9af90205829ba20662bdfaf20dcc878807d" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#90bc56539022c7b47d3da6201958ae2d5a694207" dependencies = [ "arrayvec", "bitvec", @@ -1800,6 +1806,9 @@ name = "hashbrown" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "foldhash", +] [[package]] name = "hdrhistogram" @@ -2028,9 +2037,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -2067,7 +2076,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "pin-project-lite", "tokio", @@ -2085,7 +2094,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.0", "pin-project-lite", "socket2", "tokio", @@ -2618,9 +2627,9 @@ dependencies = [ [[package]] name = "metrics" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884adb57038347dfbaf2d5065887b6cf4312330dc8e94bc30a1a839bd79d3261" +checksum = "8ae428771d17306715c5091d446327d1cfdedc82185c65ba8423ab404e45bf10" dependencies = [ "ahash", "portable-atomic", @@ -2628,13 +2637,13 @@ dependencies = [ [[package]] name = "metrics-exporter-prometheus" -version = "0.15.3" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f0c8427b39666bf970460908b213ec09b3b350f20c0c2eabcbba51704a08e6" +checksum = "85b6f8152da6d7892ff1b7a1c0fa3f435e92b5918ad67035c3bb432111d9a29b" dependencies = [ "base64 0.22.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "indexmap 2.6.0", "ipnet", @@ -2648,15 +2657,14 @@ dependencies = [ [[package]] name = "metrics-util" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4259040465c955f9f2f1a4a8a16dc46726169bca0f88e8fb2dbeced487c3e828" +checksum = "15b482df36c13dd1869d73d14d28cd4855fbd6cfc32294bee109908a9f4a4ed7" dependencies = [ "crossbeam-epoch", "crossbeam-utils", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "metrics", - "num_cpus", "quanta", "sketches-ddsketch", ] @@ -2845,9 +2853,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" @@ -3093,7 +3101,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -3119,22 +3127,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -3232,7 +3240,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -3325,7 +3333,7 @@ checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -3365,7 +3373,7 @@ dependencies = [ "prost 0.12.6", "prost-types 0.12.6", "regex", - "syn 2.0.79", + "syn 2.0.85", "tempfile", ] @@ -3386,7 +3394,7 @@ dependencies = [ "prost 0.13.3", "prost-types 0.13.1", "regex", - "syn 2.0.79", + "syn 2.0.85", "tempfile", ] @@ -3400,7 +3408,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -3413,7 +3421,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -4170,9 +4178,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] @@ -4188,20 +4196,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "indexmap 2.6.0", "itoa", @@ -4243,9 +4251,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64 0.22.1", "chrono", @@ -4255,7 +4263,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serde_with_macros 3.9.0", + "serde_with_macros 3.11.0", "time", ] @@ -4273,14 +4281,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.9.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -4363,9 +4371,9 @@ checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "sketches-ddsketch" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85636c14b73d81f541e525f585c0a2109e6744e1565b5c1668e31c70c10ed65c" +checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" [[package]] name = "slab" @@ -4512,9 +4520,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -4620,7 +4628,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -4707,9 +4715,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", @@ -4732,7 +4740,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -4866,7 +4874,7 @@ dependencies = [ "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-timeout", "hyper-util", "percent-encoding", @@ -4891,7 +4899,7 @@ dependencies = [ "proc-macro2", "prost-build 0.12.6", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -4905,7 +4913,7 @@ dependencies = [ "prost-build 0.13.1", "prost-types 0.13.1", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -4944,7 +4952,7 @@ dependencies = [ [[package]] name = "tower-batch-control" -version = "0.2.41-beta.16" +version = "0.2.41-beta.17" dependencies = [ "color-eyre", "ed25519-zebra", @@ -4967,7 +4975,7 @@ dependencies = [ [[package]] name = "tower-fallback" -version = "0.2.41-beta.16" +version = "0.2.41-beta.17" dependencies = [ "futures-core", "pin-project", @@ -5035,7 +5043,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -5148,7 +5156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -5477,7 +5485,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", "wasm-bindgen-shared", ] @@ -5511,7 +5519,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6027,7 +6035,7 @@ dependencies = [ [[package]] name = "zebra-chain" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ "bitflags 2.6.0", "bitflags-serde-legacy", @@ -6069,7 +6077,7 @@ dependencies = [ "serde", "serde-big-array", "serde_json", - "serde_with 3.9.0", + "serde_with 3.11.0", "sha2", "spandoc", "static_assertions", @@ -6092,7 +6100,7 @@ dependencies = [ [[package]] name = "zebra-consensus" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ "bellman", "blake2b_simd", @@ -6138,7 +6146,7 @@ dependencies = [ [[package]] name = "zebra-grpc" -version = "0.1.0-alpha.7" +version = "0.1.0-alpha.8" dependencies = [ "color-eyre", "futures-util", @@ -6160,7 +6168,7 @@ dependencies = [ [[package]] name = "zebra-network" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ "bitflags 2.6.0", "byteorder", @@ -6201,7 +6209,7 @@ dependencies = [ [[package]] name = "zebra-node-services" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ "color-eyre", "jsonrpc-core", @@ -6214,9 +6222,11 @@ dependencies = [ [[package]] name = "zebra-rpc" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ + "base64 0.22.1", "chrono", + "color-eyre", "futures", "hex", "indexmap 2.6.0", @@ -6251,7 +6261,7 @@ dependencies = [ [[package]] name = "zebra-scan" -version = "0.1.0-alpha.9" +version = "0.1.0-alpha.10" dependencies = [ "bls12_381", "chrono", @@ -6297,7 +6307,7 @@ dependencies = [ [[package]] name = "zebra-script" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ "hex", "lazy_static", @@ -6309,7 +6319,7 @@ dependencies = [ [[package]] name = "zebra-state" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ "bincode", "chrono", @@ -6354,7 +6364,7 @@ dependencies = [ [[package]] name = "zebra-test" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ "color-eyre", "futures", @@ -6382,7 +6392,7 @@ dependencies = [ [[package]] name = "zebra-utils" -version = "1.0.0-beta.40" +version = "1.0.0-beta.41" dependencies = [ "color-eyre", "hex", @@ -6397,7 +6407,7 @@ dependencies = [ "serde_json", "serde_yml", "structopt", - "syn 2.0.79", + "syn 2.0.85", "thiserror", "tinyvec", "tokio", @@ -6413,7 +6423,7 @@ dependencies = [ [[package]] name = "zebrad" -version = "2.0.0-rc.0" +version = "2.0.0" dependencies = [ "abscissa_core", "atty", @@ -6429,7 +6439,7 @@ dependencies = [ "howudoin", "http-body-util", "humantime-serde", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "indexmap 2.6.0", "indicatif", @@ -6501,7 +6511,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] @@ -6521,7 +6531,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.85", ] [[package]] From 8c76592fa08d41f4cd4eb21e7a8c23251b22402e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 29 Oct 2024 16:21:32 +0100 Subject: [PATCH 054/157] Use zsa1 branch for librustzcash crates --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 16 ++++++---------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b399cef361e..6690a968028 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1372,7 +1372,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "blake2b_simd", "byteorder", @@ -1407,7 +1407,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "blake2b_simd", ] @@ -5814,7 +5814,7 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" version = "0.3.2" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "bech32", "bs58", @@ -5826,7 +5826,7 @@ dependencies = [ [[package]] name = "zcash_client_backend" version = "0.12.1" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "base64 0.21.7", "bech32", @@ -5854,7 +5854,7 @@ dependencies = [ "which", "zcash_address", "zcash_encoding", - "zcash_keys 0.2.0 (git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend)", + "zcash_keys 0.2.0 (git+https://github.com/QED-it/librustzcash?branch=zsa1)", "zcash_note_encryption", "zcash_primitives", "zcash_protocol", @@ -5865,7 +5865,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "byteorder", "nonempty", @@ -5874,7 +5874,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "blake2b_simd", "byteorder", @@ -5910,7 +5910,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "bech32", "blake2b_simd", @@ -5947,14 +5947,14 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.15.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "aes", "bip0039", "blake2b_simd", "byteorder", "document-features", - "equihash 0.2.0 (git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend)", + "equihash 0.2.0 (git+https://github.com/QED-it/librustzcash?branch=zsa1)", "ff", "fpe", "group", @@ -6008,7 +6008,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.1.1" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "document-features", "memuse", @@ -6548,7 +6548,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.0.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zebra-compat-enable-backend#7191c6aacad337ca2aad86b46d992688ab1593af" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" dependencies = [ "base64 0.21.7", "nom", diff --git a/Cargo.toml b/Cargo.toml index c2792f9ff9c..dda73229b91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,18 +104,14 @@ panic = "abort" lto = "thin" [patch.crates-io] -#halo2_proofs = { version = "0.3.0", git = "https://github.com/QED-it/halo2", rev = "1195c9af90205829ba20662bdfaf20dcc878807d" } -#halo2_gadgets = { version = "0.3.0", git = "https://github.com/QED-it/halo2", rev = "1195c9af90205829ba20662bdfaf20dcc878807d" } halo2_proofs = { version = "0.3.0", git = "https://github.com/QED-it/halo2", branch = "zsa1" } halo2_gadgets = { version = "0.3.0", git = "https://github.com/QED-it/halo2", branch = "zsa1" } zcash_note_encryption = { version = "0.4.0", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1" } sapling-crypto = { version = "0.1.3", git = "https://github.com/QED-it/sapling-crypto", branch = "zsa1" } orchard = { version = "0.8.0", git = "https://github.com/QED-it/orchard", branch = "zsa1" } -zcash_primitives = { version = "0.15.0", git = "https://github.com/QED-it/librustzcash", branch = "zebra-compat-enable-backend" } -zcash_protocol = { version = "0.1.1", git = "https://github.com/QED-it/librustzcash", branch = "zebra-compat-enable-backend" } -zcash_address = { version = "0.3.2", git = "https://github.com/QED-it/librustzcash", branch = "zebra-compat-enable-backend" } -zcash_encoding = { version = "0.2.0", git = "https://github.com/QED-it/librustzcash", branch = "zebra-compat-enable-backend" } -zcash_history = { version = "0.4.0", git = "https://github.com/QED-it/librustzcash", branch = "zebra-compat-enable-backend" } -zcash_client_backend = { version = "0.12.1", git = "https://github.com/QED-it/librustzcash", branch = "zebra-compat-enable-backend" } -#incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" } -#shardtree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "ffe4234788fd22662b937ba7c6ea01535fcc1293" } +zcash_primitives = { version = "0.15.0", git = "https://github.com/QED-it/librustzcash", branch = "zsa1" } +zcash_protocol = { version = "0.1.1", git = "https://github.com/QED-it/librustzcash", branch = "zsa1" } +zcash_address = { version = "0.3.2", git = "https://github.com/QED-it/librustzcash", branch = "zsa1" } +zcash_encoding = { version = "0.2.0", git = "https://github.com/QED-it/librustzcash", branch = "zsa1" } +zcash_history = { version = "0.4.0", git = "https://github.com/QED-it/librustzcash", branch = "zsa1" } +zcash_client_backend = { version = "0.12.1", git = "https://github.com/QED-it/librustzcash", branch = "zsa1" } From ab9a2b54606c762b1a127659245579bee8110339 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 30 Oct 2024 10:14:48 +0100 Subject: [PATCH 055/157] Add support for processing ZSA orchard_shielded_data in zebra_state --- .../src/service/non_finalized_state/chain.rs | 59 ++++++++++++++----- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/zebra-state/src/service/non_finalized_state/chain.rs b/zebra-state/src/service/non_finalized_state/chain.rs index 190f8b1a930..d0ce3eee904 100644 --- a/zebra-state/src/service/non_finalized_state/chain.rs +++ b/zebra-state/src/service/non_finalized_state/chain.rs @@ -1492,21 +1492,23 @@ impl Chain { .zip(transaction_hashes.iter().cloned()) .enumerate() { - let ( - inputs, - outputs, - joinsplit_data, - sapling_shielded_data_per_spend_anchor, - sapling_shielded_data_shared_anchor, - orchard_shielded_data, - ) = match transaction.deref() { + let transaction_data = match transaction.deref() { V4 { inputs, outputs, joinsplit_data, sapling_shielded_data, .. - } => (inputs, outputs, joinsplit_data, sapling_shielded_data, &None, &None), + } => ( + inputs, + outputs, + joinsplit_data, + sapling_shielded_data, + &None, + &None, + #[cfg(feature ="tx-v6")] + &None + ), V5 { inputs, outputs, @@ -1520,13 +1522,15 @@ impl Chain { &None, sapling_shielded_data, orchard_shielded_data, + #[cfg(feature ="tx-v6")] + &None, ), #[cfg(feature ="tx-v6")] V6 { inputs, outputs, sapling_shielded_data, - orchard_shielded_data: _, + orchard_shielded_data, .. } => ( inputs, @@ -1534,14 +1538,35 @@ impl Chain { &None, &None, sapling_shielded_data, - // FIXME: support V6 shielded data? - &None, //orchard_shielded_data, + &None, + orchard_shielded_data, ), V1 { .. } | V2 { .. } | V3 { .. } => unreachable!( "older transaction versions only exist in finalized blocks, because of the mandatory canopy checkpoint", ), }; + #[cfg(not(feature = "tx-v6"))] + let ( + inputs, + outputs, + joinsplit_data, + sapling_shielded_data_per_spend_anchor, + sapling_shielded_data_shared_anchor, + orchard_shielded_data_vanilla, + ) = transaction_data; + + #[cfg(feature = "tx-v6")] + let ( + inputs, + outputs, + joinsplit_data, + sapling_shielded_data_per_spend_anchor, + sapling_shielded_data_shared_anchor, + orchard_shielded_data_vanilla, + orchard_shielded_data_zsa, + ) = transaction_data; + // add key `transaction.hash` and value `(height, tx_index)` to `tx_loc_by_hash` let transaction_location = TransactionLocation::from_usize(height, transaction_index); let prior_pair = self @@ -1561,7 +1586,9 @@ impl Chain { self.update_chain_tip_with(joinsplit_data)?; self.update_chain_tip_with(sapling_shielded_data_per_spend_anchor)?; self.update_chain_tip_with(sapling_shielded_data_shared_anchor)?; - self.update_chain_tip_with(orchard_shielded_data)?; + self.update_chain_tip_with(orchard_shielded_data_vanilla)?; + #[cfg(feature = "tx-v6")] + self.update_chain_tip_with(orchard_shielded_data_zsa)?; } // update the chain value pool balances @@ -2049,11 +2076,11 @@ where } } -impl UpdateWith>> for Chain { +impl UpdateWith>> for Chain { #[instrument(skip(self, orchard_shielded_data))] fn update_chain_tip_with( &mut self, - orchard_shielded_data: &Option>, + orchard_shielded_data: &Option>, ) -> Result<(), ValidateContextError> { if let Some(orchard_shielded_data) = orchard_shielded_data { // We do note commitment tree updates in parallel rayon threads. @@ -2074,7 +2101,7 @@ impl UpdateWith>> for Chai #[instrument(skip(self, orchard_shielded_data))] fn revert_chain_with( &mut self, - orchard_shielded_data: &Option>, + orchard_shielded_data: &Option>, _position: RevertPosition, ) { if let Some(orchard_shielded_data) = orchard_shielded_data { From 2587b043ebb3eb3e203772aef4c1a94936bd0fc5 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 3 Nov 2024 18:59:03 +0100 Subject: [PATCH 056/157] Introduce match_orchard_shielded_data macro in transaction.rs and refactor orchard_shielded_data_iter and orchard_shielded_data_field macros to use it --- zebra-chain/src/transaction.rs | 117 +++++++++++++++------------------ 1 file changed, 54 insertions(+), 63 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index e60f13b57a1..cd6c635a11f 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -53,58 +53,67 @@ use crate::{ value_balance::{ValueBalance, ValueBalanceError}, }; -// FIXME: doc this -// Move down -macro_rules! orchard_shielded_data_iter { - ($self:expr, $mapper:expr) => { +/// Applies expression to different versions of `Transaction` to handle Orchard shielded data. +macro_rules! match_orchard_shielded_data { + // Separate field sets and expressions for V5 and V6 + ($self:expr, $pre_v5_expr:expr, { $( $v5_field:ident ),+ }, $v5_expr:expr, { $( $v6_field:ident ),+ }, $v6_expr:expr) => { match $self { - // No Orchard shielded data Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } - | Transaction::V4 { .. } => Box::new(std::iter::empty()), + | Transaction::V4 { .. } => $pre_v5_expr, - Transaction::V5 { - orchard_shielded_data, - .. - } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), + Transaction::V5 { $( $v5_field ),+, .. } => $v5_expr, #[cfg(feature = "tx-v6")] - Transaction::V6 { - orchard_shielded_data, - .. - } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), + Transaction::V6 { $( $v6_field ),+, .. } => $v6_expr, } }; + + // Single field set and expression used for both V5 and V6 + ($self:expr, $pre_v5_expr:expr, { $( $v5_v6_field:ident ),+ }, $v5_v6_expr:expr) => { + match_orchard_shielded_data!( + $self, + $pre_v5_expr, + { $( $v5_v6_field ),+ }, + $v5_v6_expr, + { $( $v5_v6_field ),+ }, + $v5_v6_expr + ) + }; +} + +/// Creates an iterator over Orchard shielded data. +/// +/// - `$self`: The `Transaction` instance. +/// - `$mapper`: Function to apply to each data item. +macro_rules! orchard_shielded_data_iter { + ($self:expr, $mapper:expr) => { + match_orchard_shielded_data!( + $self, + Box::new(std::iter::empty()), + { orchard_shielded_data }, + Box::new(orchard_shielded_data.into_iter().flat_map($mapper)) + ) + }; } -// FIXME: doc this -// Move down +/// Retrieves a specific field from Orchard shielded data. +/// +/// - `$self`: The `Transaction` instance. +/// - `$field`: The field to access macro_rules! orchard_shielded_data_field { ($self:expr, $field:ident) => { - match $self { - // No Orchard shielded data - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { .. } => None, - - Transaction::V5 { - orchard_shielded_data, - .. - } => orchard_shielded_data.as_ref().map(|data| data.$field), - - #[cfg(feature = "tx-v6")] - Transaction::V6 { - orchard_shielded_data, - .. - } => orchard_shielded_data.as_ref().map(|data| data.$field), - } + match_orchard_shielded_data!( + $self, + None, + { orchard_shielded_data }, + orchard_shielded_data.as_ref().map(|d| d.$field) + ) }; } -// FIXME: -// Define the macro for including the V6 pattern +/// Generates match patterns for `Transaction::V5` and `Transaction::V6` #[cfg(feature = "tx-v6")] macro_rules! tx_v5_and_v6 { { $($fields:tt)* } => { @@ -112,6 +121,7 @@ macro_rules! tx_v5_and_v6 { }; } +/// Generates a match pattern for `Transaction::V5` only #[cfg(not(feature = "tx-v6"))] macro_rules! tx_v5_and_v6 { { $($fields:tt)* } => { @@ -1441,33 +1451,14 @@ impl Transaction { /// See `orchard_value_balance` for details. #[cfg(any(test, feature = "proptest-impl"))] pub fn orchard_value_balance_mut(&mut self) -> Option<&mut Amount> { - match self { - Transaction::V5 { - orchard_shielded_data: Some(orchard_shielded_data), - .. - } => Some(&mut orchard_shielded_data.value_balance), - - #[cfg(feature = "tx-v6")] - Transaction::V6 { - orchard_shielded_data: Some(orchard_shielded_data), - .. - } => Some(&mut orchard_shielded_data.value_balance), - - Transaction::V1 { .. } - | Transaction::V2 { .. } - | Transaction::V3 { .. } - | Transaction::V4 { .. } - | Transaction::V5 { - orchard_shielded_data: None, - .. - } => None, - - #[cfg(feature = "tx-v6")] - Transaction::V6 { - orchard_shielded_data: None, - .. - } => None, - } + match_orchard_shielded_data!( + self, + None, + { orchard_shielded_data }, + orchard_shielded_data + .as_mut() + .map(|shielded_data| &mut shielded_data.value_balance) + ) } /// Returns the value balances for this transaction using the provided transparent outputs. From 7447d452e17376b5499a9ff1213e42dd5639dc21 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 3 Nov 2024 19:20:39 +0100 Subject: [PATCH 057/157] Expose Burn, NoBurn, and IssueData from orchard_zsa module directly --- zebra-chain/src/orchard.rs | 3 --- zebra-chain/src/orchard/orchard_flavor_ext.rs | 2 +- zebra-chain/src/orchard_zsa.rs | 7 ++++--- zebra-chain/src/transaction.rs | 4 ++-- zebra-chain/src/transaction/arbitrary.rs | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/zebra-chain/src/orchard.rs b/zebra-chain/src/orchard.rs index 3141b6a1154..a44aa4ae2ec 100644 --- a/zebra-chain/src/orchard.rs +++ b/zebra-chain/src/orchard.rs @@ -30,6 +30,3 @@ pub(crate) use shielded_data::ActionCommon; #[cfg(feature = "tx-v6")] pub use orchard_flavor_ext::OrchardZSA; - -#[cfg(feature = "tx-v6")] -pub(crate) use crate::orchard_zsa::issuance::IssueData; diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index 119646ae7b9..6ad05abd889 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -12,7 +12,7 @@ use orchard::{note_encryption::OrchardDomainCommon, orchard_flavor}; use crate::serialization::{ZcashDeserialize, ZcashSerialize}; #[cfg(feature = "tx-v6")] -use crate::orchard_zsa::burn::{Burn, NoBurn}; +use crate::orchard_zsa::{Burn, NoBurn}; use super::note; diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index d1dae03d792..be3e29ec0e4 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -6,7 +6,8 @@ pub(crate) mod arbitrary; mod common; -pub mod burn; -pub mod issuance; +mod burn; +mod issuance; -pub use burn::BurnItem; +pub(crate) use burn::{Burn, NoBurn}; +pub(crate) use issuance::IssueData; diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index cd6c635a11f..09c15090814 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -40,7 +40,7 @@ pub use unmined::{ use crate::{ amount::{Amount, Error as AmountError, NegativeAllowed, NonNegative}, - block, orchard, + block, orchard, orchard_zsa, parameters::{ConsensusBranchId, NetworkUpgrade}, primitives::{ed25519, Bctv14Proof, Groth16Proof}, sapling, @@ -245,7 +245,7 @@ pub enum Transaction { orchard_shielded_data: Option>, /// The ZSA issuance data for this transaction, if any. #[cfg(feature = "tx-v6")] - orchard_zsa_issue_data: Option, + orchard_zsa_issue_data: Option, }, } diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index eb8c7c56ed6..cc06655c2ed 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -21,7 +21,7 @@ use crate::{ }; #[cfg(feature = "tx-v6")] -use crate::orchard_zsa::issuance::IssueData; +use crate::orchard_zsa::IssueData; use itertools::Itertools; From 714e6314f6efc011b23fb3be82280ff85cf40ca2 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 3 Nov 2024 19:29:59 +0100 Subject: [PATCH 058/157] Add IssueData::note_commitments and use it in Transaction::orchard_note_commitments to merge Orchard ZSA issuance note commitments for V6 transactions --- zebra-chain/src/block.rs | 2 +- zebra-chain/src/block/arbitrary.rs | 2 +- zebra-chain/src/orchard_zsa/issuance.rs | 38 ++++++++++++++----- zebra-chain/src/parallel/tree.rs | 2 +- zebra-chain/src/transaction.rs | 28 +++++++++++++- .../disk_format/upgrade/add_subtrees.rs | 1 - 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/zebra-chain/src/block.rs b/zebra-chain/src/block.rs index 5bbc774d35c..998fd11b860 100644 --- a/zebra-chain/src/block.rs +++ b/zebra-chain/src/block.rs @@ -175,7 +175,7 @@ impl Block { } /// Access the [orchard note commitments](pallas::Base) from all transactions in this block. - pub fn orchard_note_commitments(&self) -> impl Iterator { + pub fn orchard_note_commitments(&self) -> impl Iterator + '_ { self.transactions .iter() .flat_map(|transaction| transaction.orchard_note_commitments()) diff --git a/zebra-chain/src/block/arbitrary.rs b/zebra-chain/src/block/arbitrary.rs index 5a39afa2ee4..cf8ce64c9b8 100644 --- a/zebra-chain/src/block/arbitrary.rs +++ b/zebra-chain/src/block/arbitrary.rs @@ -452,7 +452,7 @@ impl Block { sapling_tree.append(*sapling_note_commitment).unwrap(); } for orchard_note_commitment in transaction.orchard_note_commitments() { - orchard_tree.append(*orchard_note_commitment).unwrap(); + orchard_tree.append(orchard_note_commitment).unwrap(); } } new_transactions.push(Arc::new(transaction)); diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index 8a1dde30ca5..9f7b4e9faaf 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -2,14 +2,6 @@ use std::{fmt::Debug, io}; -use crate::{ - block::MAX_BLOCK_BYTES, - serialization::{ - zcash_serialize_bytes, zcash_serialize_empty_list, ReadZcashExt, SerializationError, - TrustedPreallocate, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize, - }, -}; - use nonempty::NonEmpty; // FIXME: needed for "as_bool" only - consider to implement as_bool locally @@ -17,15 +9,28 @@ use bitvec::macros::internal::funty::Fundamental; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use halo2::pasta::pallas; + +// For pallas::Base::from_repr only +use group::ff::PrimeField; + use orchard::{ issuance::{IssueAction, IssueBundle, Signed}, keys::IssuanceValidatingKey, - note::{RandomSeed, Rho}, + note::{ExtractedNoteCommitment, RandomSeed, Rho}, primitives::redpallas::{SigType, Signature, SpendAuth}, value::NoteValue, Address, Note, }; +use crate::{ + block::MAX_BLOCK_BYTES, + serialization::{ + zcash_serialize_bytes, zcash_serialize_empty_list, ReadZcashExt, SerializationError, + TrustedPreallocate, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize, + }, +}; + use super::common::ASSET_BASE_SIZE; /// Wrapper for `IssueBundle` used in the context of Transaction V6. This allows the implementation of @@ -39,6 +44,21 @@ impl From> for IssueData { } } +impl IssueData { + pub(crate) fn note_commitments(&self) -> impl Iterator + '_ { + self.0.actions().iter().flat_map(|action| { + action.notes().iter().map(|note| { + // FIXME: Make `ExtractedNoteCommitment::inner` public in `orchard` (this would + // eliminate the need for the workaround of converting `pallas::Base` from bytes + // here), or introduce a new public method in `orchard::issuance::IssueBundle` to + // retrieve note commitments directly from `orchard`. + pallas::Base::from_repr(ExtractedNoteCommitment::from(note.commitment()).to_bytes()) + .unwrap() + }) + }) + } +} + // Sizes of the serialized values for types in bytes (used for TrustedPreallocate impls) // FIXME: are those values correct (43, 32 etc.)? //const ISSUANCE_VALIDATING_KEY_SIZE: u64 = 32; diff --git a/zebra-chain/src/parallel/tree.rs b/zebra-chain/src/parallel/tree.rs index 4f35dd44617..4f18d2359b3 100644 --- a/zebra-chain/src/parallel/tree.rs +++ b/zebra-chain/src/parallel/tree.rs @@ -73,7 +73,7 @@ impl NoteCommitmentTrees { let sprout_note_commitments: Vec<_> = block.sprout_note_commitments().cloned().collect(); let sapling_note_commitments: Vec<_> = block.sapling_note_commitments().cloned().collect(); - let orchard_note_commitments: Vec<_> = block.orchard_note_commitments().cloned().collect(); + let orchard_note_commitments: Vec<_> = block.orchard_note_commitments().collect(); let mut sprout_result = None; let mut sapling_result = None; diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 09c15090814..ea160c59e88 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -1046,8 +1046,32 @@ impl Transaction { /// Access the note commitments in this transaction, if there are any, /// regardless of version. - pub fn orchard_note_commitments(&self) -> Box + '_> { - orchard_shielded_data_iter!(self, orchard::ShieldedData::note_commitments) + pub fn orchard_note_commitments(&self) -> Box + '_> { + match_orchard_shielded_data!( + self, + Box::new(std::iter::empty()), + { orchard_shielded_data }, + Box::new( + orchard_shielded_data + .iter() + .flat_map(orchard::ShieldedData::note_commitments) + .cloned() + ), + { orchard_shielded_data, orchard_zsa_issue_data }, + { + Box::new( + orchard_shielded_data + .iter() + .flat_map(orchard::ShieldedData::note_commitments) + .cloned() + .chain( + orchard_zsa_issue_data + .iter() + .flat_map(orchard_zsa::IssueData::note_commitments) + ) + ) + } + ) } /// Access the [`orchard::Flags`] in this transaction, if there is any, diff --git a/zebra-state/src/service/finalized_state/disk_format/upgrade/add_subtrees.rs b/zebra-state/src/service/finalized_state/disk_format/upgrade/add_subtrees.rs index d84392ebf84..636301d041f 100644 --- a/zebra-state/src/service/finalized_state/disk_format/upgrade/add_subtrees.rs +++ b/zebra-state/src/service/finalized_state/disk_format/upgrade/add_subtrees.rs @@ -800,7 +800,6 @@ fn calculate_orchard_subtree( let orchard_note_commitments = block .orchard_note_commitments() .take(prev_remaining_notes) - .cloned() .collect(); // This takes less than 1 second per tree, so we don't need to make it cancellable. From c9c79e63d541f2a7a175d4c9b0f3120f42ed6b76 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 4 Nov 2024 12:50:49 +0100 Subject: [PATCH 059/157] Revert "Introduce match_orchard_shielded_data macro in transaction.rs and refactor orchard_shielded_data_iter and orchard_shielded_data_field macros to use it" This reverts commit 2587b043ebb3eb3e203772aef4c1a94936bd0fc5. --- zebra-chain/src/transaction.rs | 117 ++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index ea160c59e88..1155c148516 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -53,67 +53,58 @@ use crate::{ value_balance::{ValueBalance, ValueBalanceError}, }; -/// Applies expression to different versions of `Transaction` to handle Orchard shielded data. -macro_rules! match_orchard_shielded_data { - // Separate field sets and expressions for V5 and V6 - ($self:expr, $pre_v5_expr:expr, { $( $v5_field:ident ),+ }, $v5_expr:expr, { $( $v6_field:ident ),+ }, $v6_expr:expr) => { +// FIXME: doc this +// Move down +macro_rules! orchard_shielded_data_iter { + ($self:expr, $mapper:expr) => { match $self { + // No Orchard shielded data Transaction::V1 { .. } | Transaction::V2 { .. } | Transaction::V3 { .. } - | Transaction::V4 { .. } => $pre_v5_expr, + | Transaction::V4 { .. } => Box::new(std::iter::empty()), - Transaction::V5 { $( $v5_field ),+, .. } => $v5_expr, + Transaction::V5 { + orchard_shielded_data, + .. + } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), #[cfg(feature = "tx-v6")] - Transaction::V6 { $( $v6_field ),+, .. } => $v6_expr, + Transaction::V6 { + orchard_shielded_data, + .. + } => Box::new(orchard_shielded_data.into_iter().flat_map($mapper)), } }; - - // Single field set and expression used for both V5 and V6 - ($self:expr, $pre_v5_expr:expr, { $( $v5_v6_field:ident ),+ }, $v5_v6_expr:expr) => { - match_orchard_shielded_data!( - $self, - $pre_v5_expr, - { $( $v5_v6_field ),+ }, - $v5_v6_expr, - { $( $v5_v6_field ),+ }, - $v5_v6_expr - ) - }; } -/// Creates an iterator over Orchard shielded data. -/// -/// - `$self`: The `Transaction` instance. -/// - `$mapper`: Function to apply to each data item. -macro_rules! orchard_shielded_data_iter { - ($self:expr, $mapper:expr) => { - match_orchard_shielded_data!( - $self, - Box::new(std::iter::empty()), - { orchard_shielded_data }, - Box::new(orchard_shielded_data.into_iter().flat_map($mapper)) - ) - }; -} - -/// Retrieves a specific field from Orchard shielded data. -/// -/// - `$self`: The `Transaction` instance. -/// - `$field`: The field to access +// FIXME: doc this +// Move down macro_rules! orchard_shielded_data_field { ($self:expr, $field:ident) => { - match_orchard_shielded_data!( - $self, - None, - { orchard_shielded_data }, - orchard_shielded_data.as_ref().map(|d| d.$field) - ) + match $self { + // No Orchard shielded data + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => None, + + Transaction::V5 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_ref().map(|data| data.$field), + + #[cfg(feature = "tx-v6")] + Transaction::V6 { + orchard_shielded_data, + .. + } => orchard_shielded_data.as_ref().map(|data| data.$field), + } }; } -/// Generates match patterns for `Transaction::V5` and `Transaction::V6` +// FIXME: +// Define the macro for including the V6 pattern #[cfg(feature = "tx-v6")] macro_rules! tx_v5_and_v6 { { $($fields:tt)* } => { @@ -121,7 +112,6 @@ macro_rules! tx_v5_and_v6 { }; } -/// Generates a match pattern for `Transaction::V5` only #[cfg(not(feature = "tx-v6"))] macro_rules! tx_v5_and_v6 { { $($fields:tt)* } => { @@ -1475,14 +1465,33 @@ impl Transaction { /// See `orchard_value_balance` for details. #[cfg(any(test, feature = "proptest-impl"))] pub fn orchard_value_balance_mut(&mut self) -> Option<&mut Amount> { - match_orchard_shielded_data!( - self, - None, - { orchard_shielded_data }, - orchard_shielded_data - .as_mut() - .map(|shielded_data| &mut shielded_data.value_balance) - ) + match self { + Transaction::V5 { + orchard_shielded_data: Some(orchard_shielded_data), + .. + } => Some(&mut orchard_shielded_data.value_balance), + + #[cfg(feature = "tx-v6")] + Transaction::V6 { + orchard_shielded_data: Some(orchard_shielded_data), + .. + } => Some(&mut orchard_shielded_data.value_balance), + + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } + | Transaction::V5 { + orchard_shielded_data: None, + .. + } => None, + + #[cfg(feature = "tx-v6")] + Transaction::V6 { + orchard_shielded_data: None, + .. + } => None, + } } /// Returns the value balances for this transaction using the provided transparent outputs. From 9ad18a458241870ae53b8b4e8227bd8adca3a58b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 4 Nov 2024 13:56:23 +0100 Subject: [PATCH 060/157] Modify Transaction::orchard_note_commitments method to not use match_orchard_shielded_data macro from the reverted commit --- zebra-chain/src/transaction.rs | 47 +++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 1155c148516..737253d6eab 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -1037,31 +1037,38 @@ impl Transaction { /// Access the note commitments in this transaction, if there are any, /// regardless of version. pub fn orchard_note_commitments(&self) -> Box + '_> { - match_orchard_shielded_data!( - self, - Box::new(std::iter::empty()), - { orchard_shielded_data }, - Box::new( + match self { + Transaction::V1 { .. } + | Transaction::V2 { .. } + | Transaction::V3 { .. } + | Transaction::V4 { .. } => Box::new(std::iter::empty()), + + Transaction::V5 { + orchard_shielded_data, + .. + } => Box::new( + orchard_shielded_data + .iter() + .flat_map(orchard::ShieldedData::note_commitments) + .cloned(), + ), + #[cfg(feature = "tx-v6")] + Transaction::V6 { + orchard_shielded_data, + orchard_zsa_issue_data, + .. + } => Box::new( orchard_shielded_data .iter() .flat_map(orchard::ShieldedData::note_commitments) .cloned() + .chain( + orchard_zsa_issue_data + .iter() + .flat_map(orchard_zsa::IssueData::note_commitments), + ), ), - { orchard_shielded_data, orchard_zsa_issue_data }, - { - Box::new( - orchard_shielded_data - .iter() - .flat_map(orchard::ShieldedData::note_commitments) - .cloned() - .chain( - orchard_zsa_issue_data - .iter() - .flat_map(orchard_zsa::IssueData::note_commitments) - ) - ) - } - ) + } } /// Access the [`orchard::Flags`] in this transaction, if there is any, From 3cce4894d078252d1ec7d1a600d3e1297bc5b1a8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 11 Nov 2024 21:23:31 +0100 Subject: [PATCH 061/157] Refactor orchard_zsa modules to use IssueBundle serialization functions from librustzcash/zcash_primitives instead of reimplementing them --- zebra-chain/src/orchard_zsa.rs | 2 - zebra-chain/src/orchard_zsa/burn.rs | 20 ++- zebra-chain/src/orchard_zsa/common.rs | 23 --- zebra-chain/src/orchard_zsa/issuance.rs | 208 ++---------------------- 4 files changed, 28 insertions(+), 225 deletions(-) delete mode 100644 zebra-chain/src/orchard_zsa/common.rs diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index be3e29ec0e4..1fc878dbc34 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -4,8 +4,6 @@ #[cfg(any(test, feature = "proptest-impl"))] pub(crate) mod arbitrary; -mod common; - mod burn; mod issuance; diff --git a/zebra-chain/src/orchard_zsa/burn.rs b/zebra-chain/src/orchard_zsa/burn.rs index 812728b9380..0e0c007709b 100644 --- a/zebra-chain/src/orchard_zsa/burn.rs +++ b/zebra-chain/src/orchard_zsa/burn.rs @@ -5,12 +5,28 @@ use std::io; use crate::{ amount::Amount, block::MAX_BLOCK_BYTES, - serialization::{SerializationError, TrustedPreallocate, ZcashDeserialize, ZcashSerialize}, + serialization::{ + ReadZcashExt, SerializationError, TrustedPreallocate, ZcashDeserialize, ZcashSerialize, + }, }; use orchard::{note::AssetBase, value::NoteValue}; -use super::common::ASSET_BASE_SIZE; +// The size of the serialized AssetBase in bytes (used for TrustedPreallocate impls) +pub(super) const ASSET_BASE_SIZE: u64 = 32; + +impl ZcashSerialize for AssetBase { + fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { + writer.write_all(&self.to_bytes()) + } +} + +impl ZcashDeserialize for AssetBase { + fn zcash_deserialize(mut reader: R) -> Result { + Option::from(AssetBase::from_bytes(&reader.read_32_bytes()?)) + .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa AssetBase!")) + } +} // Sizes of the serialized values for types in bytes (used for TrustedPreallocate impls) const AMOUNT_SIZE: u64 = 8; diff --git a/zebra-chain/src/orchard_zsa/common.rs b/zebra-chain/src/orchard_zsa/common.rs deleted file mode 100644 index deb3969ced7..00000000000 --- a/zebra-chain/src/orchard_zsa/common.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Serialization implementation for selected types from the 'orchard_zsa' crate used in this module. - -use std::io; - -use crate::serialization::{ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize}; - -use orchard::note::AssetBase; - -// The size of the serialized AssetBase in bytes (used for TrustedPreallocate impls) -pub(super) const ASSET_BASE_SIZE: u64 = 32; - -impl ZcashSerialize for AssetBase { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_all(&self.to_bytes()) - } -} - -impl ZcashDeserialize for AssetBase { - fn zcash_deserialize(mut reader: R) -> Result { - Option::from(AssetBase::from_bytes(&reader.read_32_bytes()?)) - .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa AssetBase!")) - } -} diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index 9f7b4e9faaf..d45f10253cd 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -2,36 +2,25 @@ use std::{fmt::Debug, io}; -use nonempty::NonEmpty; - -// FIXME: needed for "as_bool" only - consider to implement as_bool locally -use bitvec::macros::internal::funty::Fundamental; - -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; - use halo2::pasta::pallas; // For pallas::Base::from_repr only use group::ff::PrimeField; +use zcash_primitives::transaction::components::issuance::{read_v6_bundle, write_v6_bundle}; + use orchard::{ issuance::{IssueAction, IssueBundle, Signed}, - keys::IssuanceValidatingKey, - note::{ExtractedNoteCommitment, RandomSeed, Rho}, - primitives::redpallas::{SigType, Signature, SpendAuth}, - value::NoteValue, - Address, Note, + note::ExtractedNoteCommitment, + Note, }; use crate::{ block::MAX_BLOCK_BYTES, - serialization::{ - zcash_serialize_bytes, zcash_serialize_empty_list, ReadZcashExt, SerializationError, - TrustedPreallocate, ZcashDeserialize, ZcashDeserializeInto, ZcashSerialize, - }, + serialization::{SerializationError, TrustedPreallocate, ZcashDeserialize, ZcashSerialize}, }; -use super::common::ASSET_BASE_SIZE; +use super::burn::ASSET_BASE_SIZE; /// Wrapper for `IssueBundle` used in the context of Transaction V6. This allows the implementation of /// a Serde serializer for unit tests within this crate. @@ -70,126 +59,6 @@ const RANDOM_SEED_SIZE: u64 = 32; const NOTE_SIZE: u64 = ADDRESS_SIZE + NOTE_VALUE_SIZE + ASSET_BASE_SIZE + NULLIFIER_SIZE + RANDOM_SEED_SIZE; -// FIXME: duplicates ZcashSerialize for reddsa::Signature in transaction/serialize.rs -// (as Signature from oechard_zsa is formally a different type) -impl ZcashSerialize for Signature { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_all(&<[u8; 64]>::from(self))?; - Ok(()) - } -} - -// FIXME: duplicates ZcashDeserialize for reddsa::Signature in transaction/serialize.rs -// (as Signature from oechard_zsa is formally a different type) -impl ZcashDeserialize for Signature { - fn zcash_deserialize(mut reader: R) -> Result { - Ok(reader.read_64_bytes()?.into()) - } -} - -impl ZcashDeserialize for Signed { - fn zcash_deserialize(mut reader: R) -> Result { - let signature = Signature::::zcash_deserialize(&mut reader)?; - Ok(Signed::from_data((&signature).into())) - } -} - -impl ZcashSerialize for IssuanceValidatingKey { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_all(&self.to_bytes()) - } -} - -impl ZcashDeserialize for IssuanceValidatingKey { - fn zcash_deserialize(mut reader: R) -> Result { - IssuanceValidatingKey::from_bytes(&reader.read_32_bytes()?) - .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa IssuanceValidatingKey!")) - } -} - -impl ZcashSerialize for Address { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_all(&self.to_raw_address_bytes()) - } -} - -impl ZcashDeserialize for Address { - fn zcash_deserialize(mut reader: R) -> Result { - let mut bytes = [0u8; ADDRESS_SIZE as usize]; - reader.read_exact(&mut bytes)?; - Option::from(Address::from_raw_address_bytes(&bytes)) - .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa Address!")) - } -} - -impl ZcashSerialize for Rho { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_all(&self.to_bytes()) - } -} - -impl ZcashDeserialize for Rho { - fn zcash_deserialize(mut reader: R) -> Result { - Option::from(Rho::from_bytes(&reader.read_32_bytes()?)) - .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa Rho!")) - } -} - -impl ZcashSerialize for RandomSeed { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_all(self.as_bytes()) - } -} - -// RandomSeed::zcash_deserialize can't be implemented and used as it requires Nullifier parameter. -// That's why we need to have this function. -fn zcash_deserialize_random_seed( - mut reader: R, - rho: &Rho, -) -> Result { - Option::from(RandomSeed::from_bytes(reader.read_32_bytes()?, rho)) - .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa RandomSeed!")) -} - -impl ZcashSerialize for NoteValue { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - // FIXME: use Amount serializer/deserializer? - writer.write_u64::(self.inner())?; - Ok(()) - } -} - -impl ZcashDeserialize for NoteValue { - fn zcash_deserialize(mut reader: R) -> Result { - Ok(NoteValue::from_raw(reader.read_u64::()?)) - } -} - -impl ZcashSerialize for Note { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - self.recipient().zcash_serialize(&mut writer)?; - self.value().zcash_serialize(&mut writer)?; - self.asset().zcash_serialize(&mut writer)?; - self.rho().zcash_serialize(&mut writer)?; - self.rseed().zcash_serialize(&mut writer)?; - - Ok(()) - } -} - -impl ZcashDeserialize for Note { - fn zcash_deserialize(mut reader: R) -> Result { - let recipient = (&mut reader).zcash_deserialize_into()?; - let value = (&mut reader).zcash_deserialize_into()?; - let asset = (&mut reader).zcash_deserialize_into()?; - let rho = (&mut reader).zcash_deserialize_into()?; - let rseed = zcash_deserialize_random_seed(&mut reader, &rho)?; - - Option::from(Note::from_parts(recipient, value, asset, rho, rseed)) - .ok_or_else(|| SerializationError::Parse("Invalid orchard_zsa Note components!")) - } -} - impl TrustedPreallocate for Note { fn max_allocation() -> u64 { // FIXME: is this a correct calculation way? @@ -199,24 +68,6 @@ impl TrustedPreallocate for Note { } } -impl ZcashSerialize for IssueAction { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - writer.write_u8(self.is_finalized().as_u8())?; - self.notes().to_vec().zcash_serialize(&mut writer)?; - zcash_serialize_bytes(&self.asset_desc().to_vec(), &mut writer)?; - Ok(()) - } -} - -impl ZcashDeserialize for IssueAction { - fn zcash_deserialize(mut reader: R) -> Result { - let finalize = reader.read_u8()?.as_bool(); - let notes = (&mut reader).zcash_deserialize_into()?; - let asset_descr = (&mut reader).zcash_deserialize_into()?; - Ok(IssueAction::from_parts(asset_descr, notes, finalize)) - } -} - impl TrustedPreallocate for IssueAction { fn max_allocation() -> u64 { // FIXME: impl correct calculation @@ -224,56 +75,17 @@ impl TrustedPreallocate for IssueAction { } } -impl ZcashSerialize for IssueBundle { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - // FIXME: try to avoid transforming to Vec (consider implementation of ZcashSerialize for IntoIter generic, - // or use AtLeastOne). - // This is how does it work in librustzcash: - // Vector::write_nonempty(&mut writer, bundle.actions(), |w, action| write_action(action, w))?; - let actions: Vec<_> = self.actions().clone().into(); - - actions.zcash_serialize(&mut writer)?; - self.ik().zcash_serialize(&mut writer)?; - writer.write_all(&<[u8; 64]>::from(self.authorization().signature()))?; - Ok(()) - } -} - impl ZcashSerialize for Option { - fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { - match self { - None => { - // Denoted as `&Option` in the spec (ZIP 230). - zcash_serialize_empty_list(writer)?; - } - Some(issue_data) => { - issue_data.0.zcash_serialize(&mut writer)?; - } - } - Ok(()) + fn zcash_serialize(&self, writer: W) -> Result<(), io::Error> { + write_v6_bundle(self.as_ref().map(|issue_data| &issue_data.0), writer) } } // FIXME: We can't split IssueData out of Option deserialization, // because the counts are read along with the arrays. impl ZcashDeserialize for Option { - fn zcash_deserialize(mut reader: R) -> Result { - let actions: Vec<_> = (&mut reader).zcash_deserialize_into()?; - - if actions.is_empty() { - Ok(None) - } else { - let ik = (&mut reader).zcash_deserialize_into()?; - let authorization = (&mut reader).zcash_deserialize_into()?; - - Ok(Some(IssueData(IssueBundle::from_parts( - ik, - NonEmpty::from_vec(actions).ok_or_else(|| { - SerializationError::Parse("Invalid orchard_zsa IssueData - no actions!") - })?, - authorization, - )))) - } + fn zcash_deserialize(reader: R) -> Result { + Ok(read_v6_bundle(reader)?.map(IssueData)) } } From ce6c5c36ff6d799a449d8f4ac27e4482a8182ee7 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 11 Nov 2024 21:27:27 +0100 Subject: [PATCH 062/157] Fix the orchard::ShieldedData serialization/deserialization functions to use the correct order of the asset burn field in V6 transaction as it's defined in ZIP 230 --- zebra-chain/src/transaction/serialize.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/transaction/serialize.rs b/zebra-chain/src/transaction/serialize.rs index 42743881bd5..b3ed12ebd7d 100644 --- a/zebra-chain/src/transaction/serialize.rs +++ b/zebra-chain/src/transaction/serialize.rs @@ -376,13 +376,13 @@ impl ZcashSerialize for orchard::ShieldedData { // Denoted as `vSpendAuthSigsOrchard` in the spec. zcash_serialize_external_count(&sigs, &mut writer)?; - // Denoted as `bindingSigOrchard` in the spec. - self.binding_sig.zcash_serialize(&mut writer)?; - #[cfg(feature = "tx-v6")] // Denoted as `vAssetBurn` in the spec (ZIP 230). self.burn.zcash_serialize(&mut writer)?; + // Denoted as `bindingSigOrchard` in the spec. + self.binding_sig.zcash_serialize(&mut writer)?; + Ok(()) } } @@ -434,6 +434,10 @@ impl ZcashDeserialize for Option> let sigs: Vec> = zcash_deserialize_external_count(actions.len(), &mut reader)?; + // TODO: FIXME: add a proper comment + #[cfg(feature = "tx-v6")] + let burn = (&mut reader).zcash_deserialize_into()?; + // Denoted as `bindingSigOrchard` in the spec. let binding_sig: Signature = (&mut reader).zcash_deserialize_into()?; @@ -448,10 +452,6 @@ impl ZcashDeserialize for Option> let actions: AtLeastOne> = authorized_actions.try_into()?; - // TODO: FIXME: add a proper comment - #[cfg(feature = "tx-v6")] - let burn = (&mut reader).zcash_deserialize_into()?; - Ok(Some(orchard::ShieldedData:: { flags, value_balance, From 22349e59c4905fb14d4974f8b4d57396b4925f34 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 11 Nov 2024 21:28:36 +0100 Subject: [PATCH 063/157] Add ENABLE_ZSA flag to Flags for the orchard ShieldedData --- zebra-chain/src/orchard/shielded_data.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zebra-chain/src/orchard/shielded_data.rs b/zebra-chain/src/orchard/shielded_data.rs index baf98da8c42..844c1ff3994 100644 --- a/zebra-chain/src/orchard/shielded_data.rs +++ b/zebra-chain/src/orchard/shielded_data.rs @@ -313,6 +313,9 @@ bitflags! { const ENABLE_SPENDS = 0b00000001; /// Enable creating new non-zero valued Orchard notes. const ENABLE_OUTPUTS = 0b00000010; + /// Enable ZSA transaction (otherwise all notes within actions must use native asset). + // FIXME: Should we use this flag explicitly anywhere in Zebra? + const ENABLE_ZSA = 0b00000100; } } From 46f81bcf4713902a38b5e497bf88fc7637a6ece3 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 11 Nov 2024 21:30:12 +0100 Subject: [PATCH 064/157] Fix TX_V6_VERSION_GROUP_ID constant value to adjust it with the value used in librustzcash --- zebra-chain/src/parameters/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index d7391bdf184..bfb3c8ca7c7 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -18,4 +18,4 @@ pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; /// group ID. // FIXME: use a proper value! #[cfg(feature = "tx-v6")] -pub const TX_V6_VERSION_GROUP_ID: u32 = 0x26A7_270B; +pub const TX_V6_VERSION_GROUP_ID: u32 = 0x124A_69F8; From 408c15531ee57192e64aed79039b212bda8a419a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 11 Nov 2024 21:32:03 +0100 Subject: [PATCH 065/157] Add a value for Nu7 to CONSENSUS_BRANCH_IDS (a placeholder values for now - the same as used in librustzcash to make it possible to run tests) --- zebra-chain/src/parameters/network_upgrade.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index aad1d19e2a5..1eade62208c 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -227,7 +227,7 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Nu5, ConsensusBranchId(0xc2d6d0b4)), (Nu6, ConsensusBranchId(0xc8e71055)), // FIXME: use a proper value below - (Nu7, ConsensusBranchId(0xc8e71056)), + (Nu7, ConsensusBranchId(0x77777777)), ]; /// The target block spacing before Blossom. From c6a3dd48d21cfb9cb7c8a681308ccb60e0d1f11e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 11 Nov 2024 21:34:43 +0100 Subject: [PATCH 066/157] Add a test vector with an issuance block to orchard_zsa module, also add issuance_block test function there (now it simply deserialized issuance block from the test vector to check if deserialization functions work properly) --- zebra-chain/src/orchard_zsa.rs | 3 + zebra-chain/src/orchard_zsa/tests.rs | 2 + zebra-chain/src/orchard_zsa/tests/issuance.rs | 9 + zebra-chain/src/orchard_zsa/tests/vectors.rs | 3 + .../src/orchard_zsa/tests/vectors/blocks.rs | 703 ++++++++++++++++++ 5 files changed, 720 insertions(+) create mode 100644 zebra-chain/src/orchard_zsa/tests.rs create mode 100644 zebra-chain/src/orchard_zsa/tests/issuance.rs create mode 100644 zebra-chain/src/orchard_zsa/tests/vectors.rs create mode 100644 zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index 1fc878dbc34..91445ebf949 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -4,6 +4,9 @@ #[cfg(any(test, feature = "proptest-impl"))] pub(crate) mod arbitrary; +#[cfg(test)] +mod tests; + mod burn; mod issuance; diff --git a/zebra-chain/src/orchard_zsa/tests.rs b/zebra-chain/src/orchard_zsa/tests.rs new file mode 100644 index 00000000000..a9301a7461e --- /dev/null +++ b/zebra-chain/src/orchard_zsa/tests.rs @@ -0,0 +1,2 @@ +mod issuance; +mod vectors; diff --git a/zebra-chain/src/orchard_zsa/tests/issuance.rs b/zebra-chain/src/orchard_zsa/tests/issuance.rs new file mode 100644 index 00000000000..902af757adf --- /dev/null +++ b/zebra-chain/src/orchard_zsa/tests/issuance.rs @@ -0,0 +1,9 @@ +use crate::{block::Block, serialization::ZcashDeserialize}; + +use super::vectors::BLOCKS; + +#[test] +fn issuance_block() { + let issuance_block = + Block::zcash_deserialize(BLOCKS[0].as_ref()).expect("issuance block should deserialize"); +} diff --git a/zebra-chain/src/orchard_zsa/tests/vectors.rs b/zebra-chain/src/orchard_zsa/tests/vectors.rs new file mode 100644 index 00000000000..d5664e50b19 --- /dev/null +++ b/zebra-chain/src/orchard_zsa/tests/vectors.rs @@ -0,0 +1,3 @@ +mod blocks; + +pub(crate) use blocks::BLOCKS; diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs new file mode 100644 index 00000000000..222f1e3c201 --- /dev/null +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -0,0 +1,703 @@ +pub(crate) const BLOCKS: [&[u8]; 1] = [&[ + 0x04, 0x00, 0x00, 0x00, 0x27, 0xe3, 0x01, 0x34, 0xd6, 0x20, 0xe9, 0xfe, 0x61, 0xf7, 0x19, 0x93, + 0xb2, 0xc2, 0x72, 0x75, 0x6a, 0xce, 0xec, 0xdc, 0xbf, 0xd3, 0xe5, 0x43, 0xf7, 0x30, 0xbc, 0x65, + 0x83, 0x20, 0xba, 0xb6, 0x3e, 0x7e, 0x72, 0xc9, 0x1b, 0x5e, 0x23, 0x02, 0x56, 0x76, 0xf9, 0x0e, + 0xd8, 0x11, 0x9f, 0x02, 0x77, 0x8a, 0xa0, 0x8d, 0x1a, 0x56, 0x79, 0x47, 0x66, 0x88, 0xbf, 0x6e, + 0x8e, 0x5a, 0x4f, 0x57, 0x00, 0x23, 0xde, 0x3e, 0xf1, 0x3a, 0x05, 0xe5, 0x9d, 0x2e, 0x94, 0x76, + 0x6a, 0x3c, 0x7a, 0x94, 0x88, 0x5d, 0x72, 0x57, 0x04, 0x56, 0x3c, 0x74, 0xd1, 0x7a, 0xbd, 0xf7, + 0x53, 0x53, 0xdb, 0x1a, 0xf2, 0xfa, 0x49, 0x4d, 0x3f, 0xa6, 0x0c, 0x20, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0xfd, 0x40, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x04, 0x00, 0x00, 0x80, 0x85, 0x20, 0x2f, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x02, 0x51, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x40, 0xbe, 0x40, 0x25, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, + 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, + 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, + 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x64, 0x40, 0xa8, 0x86, 0x5d, 0x61, 0x39, 0xb3, 0x39, 0x62, 0x94, 0xee, 0x42, + 0xc5, 0xa6, 0x0b, 0x63, 0x57, 0xca, 0x65, 0x8b, 0xa6, 0x76, 0xf2, 0xd6, 0xda, 0x8e, 0x00, 0xcf, + 0x60, 0xe8, 0x33, 0xa4, 0x55, 0xec, 0x7c, 0x99, 0x0f, 0xda, 0xd2, 0x46, 0xc0, 0x5b, 0x4a, 0x8f, + 0xe5, 0x2c, 0x6a, 0xb7, 0x00, 0xca, 0x49, 0xb4, 0xda, 0x80, 0xd3, 0x3d, 0x4d, 0x83, 0x7a, 0xd1, + 0x3a, 0x21, 0x3f, 0xfe, 0x71, 0xf5, 0x04, 0xd3, 0xaf, 0xeb, 0x10, 0x9d, 0xc2, 0x0d, 0xbd, 0x3a, + 0x9b, 0x2d, 0xf7, 0x7c, 0xd3, 0x2c, 0x7e, 0x7b, 0xeb, 0xb7, 0xaf, 0x60, 0xe4, 0xd3, 0x41, 0x96, + 0xe7, 0x2c, 0x0a, 0xf8, 0x99, 0x89, 0xbd, 0x70, 0x79, 0x54, 0x3b, 0xc7, 0x66, 0x29, 0x91, 0x31, + 0x97, 0xa6, 0x53, 0xfe, 0x24, 0x70, 0xf9, 0xf2, 0x41, 0x81, 0xac, 0x79, 0x60, 0x43, 0x79, 0xed, + 0x42, 0xba, 0x25, 0xdd, 0xf0, 0x05, 0xe8, 0xff, 0x14, 0x9e, 0xe8, 0x34, 0x91, 0x5d, 0xc6, 0x9d, + 0x6a, 0x2f, 0xc5, 0x70, 0x55, 0x65, 0x01, 0xf3, 0x74, 0x6f, 0xe7, 0x37, 0x4a, 0x8f, 0x5d, 0x4d, + 0xb6, 0x4e, 0x3b, 0xab, 0xc5, 0xc9, 0xa2, 0x86, 0x28, 0x0e, 0xa6, 0x2d, 0xc0, 0xc4, 0x12, 0x74, + 0xe9, 0x39, 0x34, 0xa6, 0xd8, 0xbc, 0x24, 0xdf, 0x5a, 0x2b, 0x2d, 0xd3, 0xae, 0x62, 0x2f, 0x37, + 0x38, 0xcb, 0x41, 0x26, 0xa5, 0xae, 0xed, 0x94, 0x84, 0x51, 0xc2, 0xe7, 0xff, 0xbe, 0x27, 0x7b, + 0x37, 0x94, 0xc0, 0xb5, 0x17, 0x08, 0x0a, 0x00, 0xd4, 0x69, 0x74, 0x8f, 0x4e, 0x2c, 0xeb, 0x06, + 0x2f, 0x1d, 0x61, 0xdc, 0x70, 0xab, 0x97, 0xc9, 0xbd, 0x02, 0x68, 0xf0, 0xe1, 0x5e, 0xcb, 0x76, + 0x25, 0x2c, 0x2c, 0xd2, 0xf1, 0x8a, 0x03, 0xb3, 0x2f, 0x0b, 0x40, 0xa2, 0x56, 0xc4, 0x3a, 0xd0, + 0xf7, 0xc4, 0xef, 0x98, 0x52, 0x87, 0x54, 0x5b, 0x8e, 0xf8, 0xb3, 0x6e, 0x3d, 0x9e, 0xd6, 0x05, + 0xb9, 0x49, 0x54, 0x1b, 0xe0, 0xbc, 0xe7, 0x52, 0x71, 0x6c, 0x70, 0xdb, 0x0c, 0xf2, 0x06, 0x9e, + 0x80, 0x90, 0xde, 0x83, 0x0e, 0x8c, 0xee, 0xa3, 0x36, 0x99, 0xf0, 0xa8, 0x29, 0x58, 0x9e, 0xa8, + 0x4c, 0x90, 0x0d, 0x66, 0x06, 0xf9, 0x95, 0x21, 0x65, 0xa4, 0x90, 0x58, 0x9f, 0x61, 0x66, 0x25, + 0x8b, 0x7b, 0x13, 0xa1, 0x6b, 0x9c, 0xf4, 0x80, 0xfb, 0x34, 0xd1, 0x0f, 0x52, 0x2d, 0xbd, 0x2a, + 0xcd, 0x16, 0x7b, 0x7d, 0xd0, 0x6c, 0x4d, 0x2d, 0xbb, 0x51, 0x90, 0x7d, 0x4d, 0x38, 0xbe, 0x06, + 0x95, 0x18, 0xd4, 0x31, 0x6d, 0xa4, 0x67, 0xca, 0xe5, 0x35, 0x51, 0xaa, 0xb4, 0x33, 0x46, 0x67, + 0xc0, 0xa5, 0xb7, 0x07, 0x63, 0x64, 0xe8, 0x42, 0x8e, 0x81, 0xf4, 0xc4, 0xcb, 0xde, 0x44, 0xe8, + 0xf1, 0x80, 0xca, 0x7a, 0x70, 0x33, 0x64, 0xaa, 0x4d, 0x50, 0xaf, 0xf3, 0x24, 0x27, 0xc4, 0x23, + 0xfb, 0xf8, 0x47, 0x61, 0x83, 0x5c, 0x31, 0xeb, 0x69, 0x73, 0x64, 0x4c, 0xe3, 0x8e, 0x24, 0x40, + 0xd9, 0xe0, 0x46, 0x17, 0xbc, 0x0b, 0xa0, 0xcd, 0x8d, 0x14, 0x96, 0x57, 0x21, 0x71, 0x97, 0x9c, + 0xa7, 0x5b, 0x28, 0xb7, 0x5b, 0x71, 0xd2, 0x7b, 0x77, 0x83, 0x09, 0x3a, 0xc4, 0x9c, 0x37, 0x38, + 0xfb, 0xdf, 0xe1, 0xf9, 0xc7, 0x29, 0xe0, 0x50, 0xbb, 0xfd, 0x7b, 0xa1, 0x53, 0xe5, 0x3b, 0x85, + 0x61, 0x21, 0x66, 0xf0, 0xa2, 0xb7, 0x65, 0x77, 0xd4, 0x5f, 0x0f, 0xf8, 0x5f, 0x4c, 0x6a, 0x90, + 0x03, 0xc1, 0x2f, 0x8c, 0x95, 0xa4, 0x36, 0x88, 0x51, 0x43, 0xd9, 0xa8, 0x78, 0x7f, 0x36, 0xb2, + 0x27, 0x2f, 0x2c, 0xd0, 0x21, 0xdc, 0x6a, 0x3f, 0x34, 0xdf, 0xac, 0x94, 0xf2, 0x8f, 0x13, 0x2e, + 0x3d, 0x2a, 0x4a, 0xf0, 0xdc, 0xa4, 0x1c, 0xc8, 0x59, 0x7e, 0xa0, 0x88, 0x7c, 0x02, 0x06, 0xf1, + 0xbe, 0x5a, 0xae, 0xc4, 0xf7, 0x72, 0x46, 0x97, 0xd9, 0x4b, 0x47, 0x9f, 0x9b, 0x93, 0x93, 0x71, + 0x8d, 0x80, 0xf7, 0xaf, 0xc7, 0xf9, 0xc9, 0x84, 0xd5, 0x9e, 0x87, 0x0f, 0x64, 0x33, 0x1f, 0xd6, + 0xf5, 0x90, 0x2d, 0x3a, 0xc3, 0x59, 0xf5, 0x25, 0xe6, 0xa5, 0xda, 0xf4, 0x21, 0x24, 0x9d, 0xdb, + 0x69, 0x86, 0x93, 0xec, 0x7d, 0x9b, 0xfd, 0x71, 0x19, 0xab, 0x05, 0xb6, 0xfd, 0x5c, 0x6b, 0x17, + 0x7e, 0xe5, 0xc4, 0x10, 0x38, 0xd7, 0x9b, 0x84, 0x94, 0x0d, 0xf1, 0xf5, 0xe6, 0x79, 0x84, 0x3c, + 0x04, 0x84, 0x2c, 0x6a, 0x62, 0xcf, 0xd6, 0x2f, 0xd0, 0x1b, 0xcc, 0xc2, 0xc8, 0x2a, 0x67, 0x34, + 0x52, 0xae, 0x88, 0x48, 0x47, 0x5f, 0x61, 0x4d, 0xba, 0x6c, 0x53, 0xf1, 0x8b, 0x12, 0x54, 0xcc, + 0xf0, 0x77, 0x89, 0x72, 0x98, 0x97, 0xed, 0x2e, 0xfa, 0xef, 0x0b, 0x54, 0x69, 0x02, 0x69, 0x15, + 0xa6, 0x5f, 0x11, 0xed, 0x04, 0x58, 0x02, 0x46, 0xc4, 0xdc, 0x9c, 0xb6, 0xe1, 0xc8, 0xd8, 0xdc, + 0xa3, 0x99, 0xea, 0x17, 0x96, 0x74, 0x7b, 0x5f, 0xeb, 0x00, 0x02, 0x91, 0x04, 0x9e, 0xf4, 0xff, + 0x6d, 0x0b, 0x29, 0x82, 0x37, 0x1a, 0x4c, 0xa0, 0x71, 0x71, 0x20, 0xaf, 0xe4, 0x3b, 0x6e, 0x26, + 0xb1, 0x89, 0x56, 0xb3, 0xb6, 0x44, 0x2d, 0x2b, 0xb4, 0x6f, 0x22, 0xe4, 0x5d, 0xd8, 0x7d, 0x25, + 0x60, 0xe7, 0xf4, 0xab, 0x87, 0x0b, 0x97, 0x0a, 0xd4, 0x82, 0x48, 0x93, 0x0f, 0x1d, 0xcc, 0xc7, + 0x69, 0xee, 0xc7, 0xcf, 0x5d, 0x9b, 0xbe, 0x9f, 0x23, 0x4b, 0x06, 0x49, 0x88, 0xf5, 0xbd, 0xb5, + 0xc3, 0xed, 0x46, 0x2a, 0x17, 0xc8, 0x5c, 0x4e, 0xa4, 0x56, 0xf3, 0x62, 0x28, 0xe7, 0xd1, 0x66, + 0x15, 0x1c, 0xeb, 0x62, 0xc1, 0x64, 0xee, 0xb6, 0x98, 0x7a, 0x9e, 0x40, 0xaa, 0xa2, 0x7d, 0xca, + 0xb6, 0xf3, 0x82, 0x6d, 0x65, 0xfb, 0x82, 0x57, 0xd2, 0x64, 0xc8, 0xb8, 0x15, 0x1b, 0x68, 0x94, + 0x90, 0x7a, 0xd5, 0xd7, 0xe6, 0x42, 0x99, 0x6f, 0x46, 0xc8, 0x3d, 0x9e, 0x5d, 0x85, 0x00, 0x7b, + 0xed, 0x53, 0xde, 0x27, 0xa4, 0x66, 0x3f, 0xa3, 0xc2, 0xf8, 0x89, 0x69, 0x8a, 0xac, 0xcc, 0x15, + 0x5e, 0xdd, 0x63, 0xda, 0xe3, 0x5a, 0x1f, 0xe9, 0x81, 0x60, 0x20, 0x60, 0xc1, 0xf9, 0xbb, 0x71, + 0x87, 0x77, 0x79, 0xe0, 0x90, 0x3d, 0xef, 0x49, 0xa9, 0xf7, 0x66, 0x70, 0x6f, 0x80, 0x88, 0xbe, + 0x89, 0x73, 0x99, 0x3e, 0xb1, 0xf9, 0xd6, 0xe7, 0xb1, 0x9f, 0x3e, 0xfe, 0x39, 0xed, 0x36, 0x18, + 0xee, 0xc3, 0x41, 0xbb, 0x69, 0x9a, 0x8b, 0xb1, 0x13, 0x2d, 0xd5, 0xab, 0xb7, 0xb6, 0x3b, 0xed, + 0xdf, 0x5b, 0x08, 0xde, 0x7d, 0xe5, 0x5d, 0xfa, 0x32, 0x91, 0x78, 0x03, 0x87, 0x77, 0x85, 0xc2, + 0x92, 0x66, 0x51, 0x83, 0xdb, 0xa8, 0x3f, 0xce, 0x17, 0xaa, 0xf5, 0xbb, 0x1e, 0x5c, 0x5f, 0x2e, + 0xb6, 0x6c, 0x6d, 0x1a, 0x98, 0x84, 0xe4, 0x69, 0x44, 0x9a, 0xf5, 0x6e, 0xd8, 0xd4, 0xc9, 0xd3, + 0x42, 0x18, 0xca, 0x80, 0x1c, 0x71, 0x8c, 0x62, 0x79, 0x59, 0xd9, 0x3b, 0xf3, 0xba, 0x90, 0x6b, + 0x36, 0x2a, 0x7c, 0xf8, 0xd3, 0xf4, 0xaa, 0xd9, 0x17, 0x59, 0xb1, 0xe6, 0x5a, 0x50, 0xcb, 0x0b, + 0x6b, 0x19, 0x0c, 0xe0, 0x5e, 0x67, 0x09, 0x42, 0x53, 0x71, 0x8b, 0xc2, 0x4e, 0x46, 0xc3, 0xff, + 0xf1, 0x45, 0x2b, 0x81, 0x52, 0x3b, 0xb4, 0x59, 0x20, 0xdc, 0x24, 0xea, 0xa5, 0xe7, 0xfc, 0x19, + 0xc2, 0xeb, 0x8c, 0x91, 0x99, 0x0a, 0x87, 0x43, 0xa7, 0x4c, 0x3e, 0x5a, 0xd7, 0x71, 0x5e, 0x3f, + 0x7c, 0xd0, 0x2f, 0x1a, 0xc0, 0xac, 0x73, 0xcf, 0xfc, 0x0a, 0x85, 0xe8, 0xd6, 0xb1, 0xa2, 0xe0, + 0x2e, 0x7a, 0xa8, 0x68, 0x68, 0x0a, 0x7d, 0x73, 0xd0, 0xc7, 0x6a, 0x3e, 0x7b, 0x6b, 0x6a, 0x28, + 0x59, 0x7a, 0x29, 0x85, 0x84, 0x04, 0xbb, 0x7c, 0x5b, 0x8f, 0x68, 0x6f, 0xb7, 0x3e, 0xbf, 0xca, + 0x97, 0x62, 0x7a, 0x73, 0xf3, 0xe3, 0x23, 0x39, 0xa6, 0xb1, 0x71, 0xd0, 0x4e, 0xb5, 0x7a, 0x29, + 0x51, 0xc9, 0x40, 0x45, 0x2f, 0x25, 0x58, 0x0c, 0x71, 0x61, 0x9c, 0x73, 0x99, 0xc8, 0xab, 0xee, + 0x67, 0x0d, 0x97, 0xd3, 0xdc, 0xa0, 0x90, 0x3b, 0xc2, 0x91, 0x07, 0x1f, 0xf0, 0xe9, 0x97, 0xa9, + 0xb5, 0x46, 0xdc, 0x63, 0xfc, 0xa3, 0x24, 0x1f, 0xeb, 0xa8, 0x85, 0x66, 0x9a, 0xaf, 0x0f, 0x37, + 0xe0, 0x8e, 0x01, 0x32, 0x35, 0xdb, 0xbe, 0xa3, 0xbe, 0xf6, 0x2f, 0x1a, 0xd8, 0x1e, 0xc6, 0x40, + 0xb9, 0x69, 0xea, 0x02, 0x95, 0x14, 0x9b, 0xe9, 0x7d, 0x0c, 0xb7, 0x55, 0xf8, 0x87, 0xd9, 0x76, + 0x3e, 0x15, 0xae, 0x83, 0xba, 0xe7, 0x60, 0xc4, 0x0d, 0x32, 0x8a, 0x46, 0x9a, 0x56, 0xdc, 0xc1, + 0x62, 0x9e, 0x76, 0xf6, 0x34, 0xfb, 0xb9, 0xca, 0x32, 0xaa, 0xdd, 0x2b, 0x4e, 0xd2, 0xbc, 0x1a, + 0xe4, 0x5d, 0x8c, 0x79, 0xb1, 0x84, 0xd3, 0xfc, 0xd5, 0x40, 0xa9, 0x00, 0x97, 0x18, 0x39, 0xf7, + 0x78, 0xa7, 0xfd, 0x60, 0xb4, 0xfa, 0x3f, 0x8b, 0x74, 0x23, 0xb6, 0x90, 0x07, 0x32, 0xea, 0xde, + 0x4d, 0xe9, 0xbf, 0xe3, 0x78, 0x0a, 0xe0, 0x86, 0x21, 0x02, 0x2d, 0x45, 0xe0, 0x74, 0x20, 0xb7, + 0x63, 0x17, 0x2f, 0x09, 0xd3, 0xbe, 0x24, 0x6e, 0xef, 0x62, 0x06, 0x35, 0x1d, 0x0d, 0xe0, 0xb8, + 0xc4, 0xff, 0xc5, 0x3e, 0x4a, 0xf3, 0x04, 0x2b, 0x4f, 0xea, 0xf6, 0xfd, 0x8d, 0x28, 0x5e, 0xdc, + 0xe8, 0x1d, 0x39, 0x20, 0x43, 0x89, 0x5c, 0x37, 0x50, 0x38, 0x92, 0x00, 0x69, 0x46, 0xc8, 0x55, + 0x16, 0x70, 0x90, 0x73, 0x9e, 0xd8, 0x08, 0xdb, 0x3a, 0xcf, 0x5c, 0xc8, 0xdb, 0x2b, 0xae, 0x8e, + 0x7c, 0x51, 0xa9, 0x0c, 0x54, 0xc8, 0x15, 0x21, 0x26, 0x29, 0x92, 0x25, 0x19, 0xa8, 0x31, 0x7c, + 0x7d, 0x41, 0x32, 0x69, 0xe4, 0xfd, 0xf0, 0x0f, 0x12, 0x2e, 0x35, 0x0d, 0x22, 0x04, 0xf5, 0x7e, + 0x5c, 0xa7, 0x2e, 0xe1, 0xda, 0x11, 0xd2, 0xbf, 0x98, 0xe1, 0x33, 0xf7, 0x3c, 0xb2, 0x4a, 0x1c, + 0x01, 0x3e, 0xf7, 0xcc, 0x14, 0x2a, 0x51, 0xe6, 0x4f, 0x43, 0xba, 0xd4, 0xad, 0xb7, 0x8c, 0x5c, + 0x4a, 0x44, 0x03, 0x7f, 0x80, 0x0f, 0xe5, 0x58, 0x35, 0x44, 0x11, 0x13, 0x63, 0xd6, 0x62, 0x48, + 0x15, 0xa9, 0xb9, 0xdf, 0xf9, 0xc1, 0x70, 0x80, 0xdf, 0x76, 0xda, 0x93, 0x50, 0xc3, 0x17, 0x5b, + 0xb7, 0xdd, 0xfa, 0x14, 0x5a, 0xfa, 0x2f, 0xd6, 0x4b, 0x54, 0xd8, 0x41, 0xab, 0x82, 0xc9, 0x12, + 0xd8, 0x65, 0x71, 0x99, 0xff, 0x07, 0x3b, 0x46, 0x84, 0xeb, 0x89, 0x04, 0x10, 0x6d, 0x5c, 0x1e, + 0xe4, 0xcb, 0x13, 0xcd, 0x37, 0x3b, 0xde, 0x78, 0xfc, 0x48, 0xbd, 0xb2, 0x85, 0x89, 0x45, 0x72, + 0x96, 0x2a, 0x7d, 0x69, 0x1a, 0x59, 0x6d, 0x03, 0x30, 0xb9, 0xce, 0x98, 0xb3, 0xc2, 0x23, 0xb4, + 0x86, 0x2a, 0x1e, 0x76, 0x49, 0xc0, 0x7b, 0xd6, 0x3c, 0x54, 0x76, 0x22, 0x1c, 0x8e, 0x86, 0x56, + 0xeb, 0xa3, 0x00, 0x73, 0x3c, 0xeb, 0x64, 0xa1, 0xd7, 0x4a, 0xeb, 0x4d, 0x98, 0x49, 0xcf, 0x93, + 0x72, 0xec, 0x35, 0x33, 0x8b, 0x97, 0xf4, 0xd0, 0xb7, 0x80, 0xf8, 0xc4, 0x85, 0x27, 0x1f, 0x5e, + 0x3c, 0xe9, 0x83, 0x3d, 0xbc, 0x99, 0x96, 0x3d, 0x63, 0xaa, 0x99, 0x7c, 0x83, 0x07, 0x55, 0x78, + 0x94, 0x7f, 0xa4, 0x48, 0x77, 0x38, 0xa3, 0xb8, 0xb7, 0x02, 0xee, 0x82, 0xac, 0x27, 0x1e, 0xb4, + 0x2a, 0xa9, 0x27, 0x98, 0xcf, 0x58, 0x80, 0xa6, 0x58, 0x15, 0xce, 0x17, 0x87, 0xb4, 0xff, 0xaf, + 0x22, 0xa8, 0xf3, 0x83, 0xf6, 0xd9, 0x04, 0xb3, 0xbb, 0xf1, 0x1a, 0xa7, 0x00, 0x5c, 0x64, 0xfb, + 0x99, 0x6f, 0x54, 0xda, 0x29, 0x1e, 0x4f, 0xae, 0x22, 0x24, 0xce, 0xc8, 0x77, 0xc8, 0x7e, 0xe6, + 0xfd, 0xce, 0x07, 0x7d, 0x0d, 0x93, 0xde, 0x13, 0xd3, 0x08, 0xdb, 0xc1, 0xd5, 0xbb, 0x5a, 0x69, + 0x34, 0xa5, 0x90, 0x44, 0x5b, 0xd2, 0x50, 0x4c, 0x03, 0xb4, 0x35, 0x33, 0x4d, 0x63, 0xdb, 0xfb, + 0xe7, 0xed, 0x07, 0x91, 0x1f, 0x7e, 0xa5, 0x68, 0xa0, 0xe7, 0x80, 0x65, 0xf8, 0x79, 0xc7, 0xca, + 0x80, 0x27, 0x41, 0x59, 0xa3, 0x38, 0xc3, 0xae, 0xa5, 0x8c, 0x1d, 0x00, 0xb5, 0xbc, 0x6d, 0x16, + 0xdf, 0x8e, 0x36, 0xa6, 0x24, 0x8e, 0x1d, 0xca, 0x0c, 0x13, 0xed, 0x3d, 0xe1, 0x68, 0xc9, 0x0b, + 0x8b, 0xd4, 0x17, 0xf2, 0xb3, 0xec, 0x78, 0xa0, 0x7d, 0x35, 0x71, 0xe4, 0x24, 0xd1, 0xe5, 0xc1, + 0x13, 0x2c, 0x7e, 0xab, 0x86, 0x19, 0xfe, 0xbe, 0x22, 0xcf, 0xb7, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xae, 0x29, 0x35, 0xf1, 0xdf, 0xd8, 0xa2, 0x4a, 0xed, 0x7c, 0x70, 0xdf, + 0x7d, 0xe3, 0xa6, 0x68, 0xeb, 0x7a, 0x49, 0xb1, 0x31, 0x98, 0x80, 0xdd, 0xe2, 0xbb, 0xd9, 0x03, + 0x1a, 0xe5, 0xd8, 0x2f, 0xfd, 0xe0, 0x1c, 0x85, 0xa0, 0x45, 0xcc, 0x0e, 0xf3, 0x67, 0x88, 0xe9, + 0x1e, 0xdf, 0x18, 0xe6, 0x3a, 0x44, 0x94, 0x53, 0x74, 0x09, 0x4e, 0x08, 0x3c, 0x33, 0xd3, 0x07, + 0xd1, 0x72, 0xaf, 0x7f, 0x82, 0xec, 0x14, 0x05, 0x87, 0x12, 0x50, 0xc0, 0xc4, 0x4f, 0x7c, 0x67, + 0xdf, 0xd2, 0xe2, 0xc7, 0x38, 0x0d, 0x7c, 0x30, 0xf6, 0x80, 0x39, 0xe2, 0x7d, 0x77, 0xb4, 0x42, + 0xcb, 0x01, 0x63, 0xca, 0x95, 0x32, 0xa4, 0x18, 0x2c, 0x2b, 0xef, 0xa0, 0x26, 0x88, 0xc6, 0x01, + 0x97, 0x10, 0xba, 0xba, 0x3d, 0x80, 0xf2, 0xb8, 0x94, 0xfd, 0x91, 0x75, 0xf2, 0x2c, 0x7f, 0xf6, + 0xdf, 0x41, 0x2c, 0x8c, 0x41, 0xde, 0xb3, 0x94, 0xb9, 0x89, 0xc2, 0x27, 0xf5, 0xc2, 0x03, 0x32, + 0xb7, 0xa0, 0x30, 0x36, 0x98, 0x23, 0xc6, 0xac, 0x19, 0xee, 0xa1, 0xe6, 0xe2, 0x68, 0xee, 0xaa, + 0x70, 0x0c, 0x81, 0xe8, 0x87, 0x31, 0xbf, 0x74, 0xaa, 0xd7, 0x37, 0xab, 0xf9, 0x15, 0x8c, 0x3e, + 0xfc, 0x59, 0x16, 0x20, 0x4e, 0xe3, 0xd4, 0x5e, 0x57, 0x28, 0xcf, 0x42, 0x7f, 0x1a, 0x86, 0x9d, + 0x1c, 0x5d, 0x4a, 0xf1, 0x7a, 0x17, 0x9e, 0xd1, 0x6f, 0xfd, 0xcd, 0xb4, 0xe9, 0x05, 0xdb, 0x8e, + 0x10, 0x99, 0x25, 0x41, 0x2c, 0xa6, 0xf6, 0x65, 0xd3, 0x4f, 0x3c, 0x3d, 0xc9, 0x2c, 0xf5, 0x40, + 0xea, 0x6d, 0x7a, 0x07, 0xdf, 0x9c, 0x3b, 0x3f, 0xe7, 0x45, 0xd8, 0xcf, 0x95, 0x33, 0x57, 0x39, + 0x37, 0x61, 0x36, 0x7c, 0xf7, 0xee, 0xb5, 0xc0, 0x75, 0x0b, 0xe3, 0x08, 0x02, 0xfe, 0x8f, 0x52, + 0x14, 0xa4, 0x1f, 0x99, 0xbe, 0x8d, 0xb8, 0x1f, 0x35, 0xf1, 0x96, 0x61, 0x31, 0x19, 0x20, 0xd8, + 0x1c, 0xdb, 0x99, 0x9f, 0x34, 0x68, 0xf0, 0x16, 0x05, 0x5d, 0x33, 0xbc, 0x8e, 0xa9, 0x50, 0xda, + 0x3f, 0x07, 0xc0, 0xf1, 0x02, 0x61, 0x88, 0xe2, 0x8b, 0x50, 0xc9, 0xad, 0x30, 0xab, 0x00, 0x05, + 0xea, 0x60, 0x4c, 0xcf, 0x86, 0xb0, 0x32, 0x40, 0x1a, 0x6b, 0x84, 0xf9, 0xee, 0xee, 0x1c, 0x82, + 0xf6, 0xbc, 0xd3, 0x88, 0x7c, 0xb9, 0x87, 0x88, 0x8c, 0x1e, 0xc2, 0x55, 0x37, 0xc6, 0x60, 0xdc, + 0xf8, 0x1d, 0xbc, 0x80, 0x06, 0x33, 0x33, 0x61, 0x99, 0xce, 0x7c, 0x41, 0xea, 0xf2, 0xc8, 0x92, + 0x0c, 0xd3, 0xd6, 0xf4, 0x1b, 0xa7, 0x8d, 0x97, 0xb9, 0x84, 0x51, 0x65, 0x6e, 0xcb, 0x7a, 0x73, + 0x97, 0x0a, 0xfd, 0xaa, 0x36, 0xb9, 0xb1, 0x5e, 0x8d, 0xe1, 0xcf, 0x85, 0x2c, 0x5c, 0x41, 0xee, + 0x6c, 0xbc, 0x0e, 0x76, 0x80, 0x5a, 0xa9, 0x3c, 0x3f, 0xa9, 0x33, 0xc4, 0x3d, 0x12, 0x5d, 0x0b, + 0x00, 0x68, 0x7d, 0x15, 0x30, 0x37, 0xe2, 0x4d, 0x4f, 0x49, 0x30, 0x0c, 0x93, 0x2c, 0x18, 0xdd, + 0x1f, 0x92, 0xab, 0xef, 0x0a, 0x2c, 0x12, 0x4c, 0x4e, 0x99, 0xee, 0xcb, 0x95, 0x68, 0xf1, 0xf8, + 0x88, 0x8c, 0xe1, 0x16, 0x2d, 0x08, 0x6a, 0x5a, 0xb1, 0x87, 0xb4, 0x9f, 0x6b, 0x16, 0xb6, 0x69, + 0xb0, 0x40, 0xbc, 0x9c, 0x54, 0x61, 0xa2, 0x65, 0x97, 0x29, 0xa0, 0xfa, 0x12, 0x7b, 0xc5, 0xdb, + 0xcf, 0x6a, 0x54, 0xfc, 0xc8, 0x93, 0xd0, 0xdf, 0x06, 0x7a, 0xd7, 0x44, 0x0c, 0x80, 0x35, 0xe1, + 0xcf, 0x18, 0xc5, 0xb4, 0x19, 0xf3, 0x9c, 0x97, 0x3b, 0x1a, 0x91, 0xbd, 0x54, 0x0c, 0x37, 0x6b, + 0x14, 0x1d, 0xfe, 0x5c, 0xea, 0xb4, 0x3c, 0x71, 0x16, 0x21, 0x1e, 0xa0, 0x14, 0x13, 0x8d, 0xaf, + 0xbd, 0x24, 0xb2, 0x9a, 0xf4, 0x82, 0xab, 0x03, 0xb7, 0x77, 0x00, 0x6f, 0x99, 0x6f, 0xa4, 0x89, + 0xe7, 0x6f, 0xf9, 0xc2, 0x30, 0x3c, 0x1f, 0xe4, 0x69, 0x27, 0x53, 0x40, 0x16, 0xf1, 0x9e, 0xae, + 0xe7, 0xd1, 0xaf, 0x02, 0xf7, 0xb1, 0x13, 0x1a, 0x3e, 0x16, 0x1b, 0x2d, 0x18, 0xfd, 0xbf, 0xb8, + 0x61, 0xeb, 0xf7, 0x8d, 0xe8, 0x5b, 0xa0, 0xee, 0x0e, 0x56, 0xe6, 0xe1, 0x5c, 0x4a, 0x09, 0x51, + 0x41, 0xfa, 0x0c, 0xa8, 0xfc, 0x1a, 0x8d, 0x00, 0x14, 0x4d, 0x82, 0x85, 0x9e, 0x62, 0x7b, 0x70, + 0x06, 0x0b, 0x6a, 0xd7, 0xb1, 0x82, 0x46, 0x49, 0xcf, 0x3b, 0x76, 0x57, 0xd0, 0x27, 0x44, 0xac, + 0xb8, 0xb3, 0x74, 0x6b, 0x3a, 0x1c, 0x2b, 0xdb, 0x5c, 0x9a, 0x57, 0x1c, 0x79, 0xee, 0x80, 0x1d, + 0x6a, 0x8d, 0xbb, 0xfd, 0xc1, 0x70, 0x4e, 0x9b, 0xa0, 0xd3, 0x29, 0x3e, 0xe1, 0x61, 0xe5, 0xe9, + 0x69, 0x59, 0xf6, 0x3f, 0x55, 0x5e, 0x0f, 0x8a, 0x4a, 0x99, 0x95, 0xa4, 0x97, 0x71, 0xd0, 0x72, + 0x36, 0xb4, 0x20, 0x0a, 0xce, 0x69, 0xab, 0xdc, 0xf9, 0xa4, 0x66, 0xd3, 0x0e, 0x81, 0xca, 0x93, + 0xa9, 0xb9, 0xd1, 0x92, 0x41, 0xa3, 0x09, 0x57, 0xcb, 0x05, 0x28, 0xaf, 0xea, 0x86, 0xe1, 0xf1, + 0x9c, 0x7d, 0x38, 0x58, 0x97, 0x6d, 0x50, 0xa6, 0xef, 0xf6, 0xbf, 0x8b, 0x29, 0x8d, 0xbb, 0x86, + 0x48, 0x52, 0x58, 0x8f, 0x88, 0x55, 0x8a, 0x05, 0x40, 0xa0, 0x7c, 0x72, 0xb6, 0xdd, 0xa9, 0x48, + 0x77, 0xdc, 0xee, 0xbc, 0xd3, 0x6f, 0x95, 0x9f, 0x51, 0xa8, 0x5d, 0x7a, 0x61, 0x06, 0x6a, 0x78, + 0x1c, 0xb9, 0xcf, 0xa9, 0xf7, 0x88, 0x81, 0x97, 0x53, 0x5f, 0x62, 0x58, 0xb2, 0x8d, 0x71, 0xce, + 0xf4, 0x05, 0x16, 0x8b, 0x4a, 0xa3, 0xdd, 0x35, 0xfa, 0xdd, 0xd9, 0x95, 0xde, 0xb5, 0x26, 0x0d, + 0xf8, 0x73, 0x26, 0xb6, 0x5c, 0x09, 0x2b, 0x49, 0xac, 0x66, 0x91, 0x33, 0x5f, 0x44, 0xbe, 0x13, + 0xd1, 0x64, 0x44, 0xe4, 0x86, 0x4a, 0xdd, 0xde, 0x2e, 0x2c, 0xe1, 0x89, 0x32, 0x66, 0x14, 0x2e, + 0x75, 0x74, 0xe6, 0x47, 0xf9, 0x74, 0x11, 0xe3, 0x00, 0x3f, 0x13, 0x07, 0xbc, 0x09, 0x88, 0x4b, + 0x51, 0xf6, 0x91, 0xb7, 0x45, 0xaf, 0xaf, 0x69, 0x7b, 0x4f, 0x77, 0x7d, 0x2e, 0xc7, 0x5c, 0x2c, + 0x4f, 0xae, 0x5a, 0x80, 0x6a, 0xef, 0xba, 0x3e, 0x2c, 0x93, 0x63, 0x3a, 0xe4, 0xce, 0x75, 0xe1, + 0xce, 0x38, 0xf7, 0x84, 0xe1, 0xfa, 0x6f, 0x3e, 0x20, 0x17, 0x3a, 0xe7, 0x99, 0x24, 0xc1, 0x2f, + 0x98, 0x32, 0xe4, 0xca, 0x89, 0x80, 0x9c, 0x68, 0x50, 0xb1, 0x56, 0x7e, 0x5f, 0x51, 0x2c, 0x79, + 0x05, 0x16, 0x10, 0xf0, 0x7e, 0x8b, 0x09, 0xaa, 0xb1, 0xf5, 0xcf, 0xb9, 0x18, 0x14, 0x5e, 0xfd, + 0xc0, 0x08, 0xbd, 0x65, 0x1f, 0x7c, 0x1b, 0x2e, 0x0b, 0x7e, 0xc8, 0xbb, 0x32, 0x71, 0x83, 0x2c, + 0x67, 0x82, 0x32, 0xfb, 0xcb, 0x22, 0xe0, 0xff, 0x9b, 0xc1, 0x0a, 0x54, 0xe7, 0xdb, 0x86, 0x23, + 0x00, 0x04, 0x08, 0x06, 0xd1, 0x5a, 0x8f, 0xc9, 0xe3, 0x3a, 0x9b, 0x51, 0xeb, 0xfd, 0xb2, 0xf3, + 0x27, 0x45, 0xa1, 0xeb, 0xdc, 0xd0, 0xf9, 0xa7, 0x70, 0x23, 0xec, 0xc4, 0x29, 0xf1, 0xce, 0x52, + 0x89, 0xa2, 0xcb, 0xa0, 0x45, 0x6d, 0xa5, 0xa7, 0x73, 0xf4, 0xd7, 0x4c, 0x48, 0xd9, 0x15, 0xb9, + 0xe9, 0x87, 0x84, 0x30, 0xfe, 0x0d, 0xf6, 0x45, 0x88, 0xa4, 0x29, 0x26, 0x5d, 0xde, 0xc9, 0x0f, + 0xea, 0x4c, 0xb3, 0xe1, 0x48, 0x9f, 0x03, 0x99, 0x8f, 0xb6, 0x78, 0xa1, 0xaa, 0x7a, 0xa3, 0x99, + 0xb9, 0x0c, 0xcf, 0x22, 0xc5, 0x6e, 0x51, 0x82, 0xcb, 0x14, 0xbd, 0x5e, 0x03, 0xc1, 0xe1, 0xc2, + 0xec, 0x68, 0x09, 0xb0, 0x20, 0x06, 0xa9, 0x1c, 0x64, 0xdc, 0x8d, 0xac, 0x8c, 0xbb, 0x1c, 0xb7, + 0x6b, 0x80, 0x58, 0x92, 0x85, 0xe4, 0x2c, 0x98, 0xfa, 0x44, 0xd9, 0xe0, 0xfd, 0x67, 0xb4, 0xa1, + 0xfc, 0x02, 0xfd, 0x82, 0x0c, 0xac, 0xa3, 0x6f, 0x20, 0x54, 0x5e, 0x22, 0xfe, 0xb1, 0x2d, 0xad, + 0x46, 0x72, 0x5d, 0x78, 0xea, 0xb3, 0xd4, 0x65, 0xa5, 0xd2, 0x85, 0xa2, 0xe9, 0xb2, 0xbc, 0xf6, + 0xdf, 0x32, 0xa3, 0x2a, 0x91, 0x26, 0x1b, 0x18, 0x05, 0x23, 0x19, 0xb5, 0x1e, 0x3c, 0x6a, 0x29, + 0x7d, 0xc3, 0x6e, 0x52, 0xc7, 0xf2, 0x50, 0x29, 0x67, 0xfb, 0xeb, 0x0a, 0xd0, 0xdb, 0xf7, 0x0c, + 0x8a, 0x25, 0x70, 0xb8, 0xf7, 0x15, 0x88, 0xfb, 0x28, 0x91, 0xef, 0xf0, 0xa2, 0x3c, 0x28, 0xdd, + 0x2f, 0x4f, 0xd0, 0xf6, 0x26, 0xa4, 0xdb, 0x65, 0x3b, 0x39, 0x61, 0x43, 0xc6, 0xf8, 0x68, 0xd6, + 0x55, 0xe2, 0xd5, 0x85, 0x03, 0x9c, 0x89, 0x1a, 0x11, 0xff, 0xf1, 0x37, 0x76, 0x8d, 0x05, 0xf7, + 0x5c, 0x27, 0xb8, 0xd3, 0x79, 0xad, 0x02, 0xca, 0xb0, 0x52, 0xec, 0x67, 0x89, 0xfb, 0xb1, 0x28, + 0x72, 0xae, 0x32, 0x2f, 0xde, 0x58, 0x2c, 0x8e, 0x6d, 0x87, 0xb3, 0x3f, 0xb8, 0x44, 0x7e, 0x81, + 0x76, 0x29, 0x4b, 0xe9, 0xdf, 0x99, 0xc7, 0x43, 0xde, 0xb2, 0xe3, 0xf9, 0xf9, 0x1c, 0x8a, 0x3b, + 0x58, 0x88, 0xf6, 0x0e, 0x1e, 0x7f, 0x9f, 0x49, 0xb0, 0x49, 0xba, 0xdb, 0x6d, 0x59, 0xdf, 0x42, + 0x8e, 0xa4, 0x13, 0x80, 0xb5, 0x01, 0x90, 0xd9, 0x6f, 0xf7, 0x2e, 0xba, 0x28, 0x7c, 0xa5, 0x5f, + 0x32, 0x43, 0x99, 0x64, 0xa9, 0xa5, 0x9b, 0xa8, 0xc0, 0x99, 0x03, 0x08, 0x02, 0x10, 0xde, 0xa1, + 0x75, 0xc9, 0x72, 0xa7, 0x66, 0x7a, 0x66, 0xca, 0xb9, 0x36, 0xd0, 0x98, 0xaf, 0xdf, 0x2d, 0xc3, + 0xac, 0x5c, 0xda, 0x1c, 0x66, 0xea, 0xb7, 0x3e, 0x89, 0x32, 0x54, 0xb3, 0x57, 0xa5, 0x4f, 0x9a, + 0xda, 0x6b, 0x11, 0x21, 0x79, 0x15, 0x7e, 0xb1, 0x92, 0x64, 0x07, 0xe8, 0x8f, 0x40, 0x19, 0xbf, + 0x7b, 0x34, 0x1d, 0xd5, 0xbb, 0x0e, 0xbc, 0xd3, 0xd9, 0x88, 0x59, 0xe1, 0xd2, 0xe2, 0x8a, 0x25, + 0xd8, 0x6c, 0x34, 0x8c, 0xab, 0xca, 0x24, 0x51, 0xbf, 0xcd, 0x7d, 0x1a, 0x88, 0x0e, 0x41, 0x0f, + 0xcf, 0x10, 0x62, 0x40, 0xf1, 0xef, 0x38, 0xf9, 0x14, 0x52, 0x9a, 0x6f, 0xd3, 0xf9, 0x6b, 0x98, + 0x4f, 0x19, 0x6c, 0x07, 0xec, 0xcf, 0x36, 0x53, 0x77, 0x58, 0x23, 0x56, 0x08, 0x65, 0xdb, 0x24, + 0x1c, 0xd2, 0xdb, 0x62, 0x5f, 0xdc, 0x1c, 0x01, 0x49, 0xf6, 0x8c, 0x21, 0x6f, 0x71, 0x22, 0x5f, + 0x02, 0xb5, 0x00, 0x49, 0x28, 0x11, 0xc1, 0x3c, 0xba, 0x69, 0xdc, 0x7f, 0xcb, 0xc7, 0xa8, 0x8d, + 0xf5, 0xee, 0xe4, 0x4b, 0x53, 0x8d, 0x01, 0xa3, 0xd1, 0x82, 0x88, 0x28, 0x03, 0x42, 0xed, 0x20, + 0x4b, 0xca, 0xb0, 0x3a, 0x4e, 0x05, 0xee, 0x42, 0xc1, 0xd8, 0xd6, 0x2c, 0x64, 0xd6, 0x83, 0x03, + 0xc1, 0x21, 0x75, 0xd4, 0xce, 0x5d, 0x83, 0x9b, 0x74, 0x88, 0x51, 0x14, 0x9c, 0x5e, 0x73, 0xe5, + 0xaf, 0x1e, 0x12, 0xae, 0xb9, 0xc3, 0x2d, 0xd7, 0x09, 0xf8, 0x4b, 0x2e, 0x14, 0xcf, 0x94, 0x17, + 0xf6, 0xc8, 0x28, 0xbf, 0x6b, 0xd9, 0x33, 0x4c, 0x4c, 0xab, 0x2e, 0xa4, 0x3a, 0xe7, 0x6b, 0x3d, + 0xe0, 0xc4, 0x35, 0xc1, 0xb3, 0x7f, 0x9e, 0xcc, 0x65, 0xeb, 0xed, 0xd8, 0x15, 0x27, 0x11, 0x66, + 0x20, 0x68, 0xaa, 0xf3, 0xa0, 0xf3, 0xa8, 0x6f, 0x51, 0x63, 0x42, 0xcf, 0xba, 0x10, 0x4f, 0x04, + 0xdf, 0x64, 0x87, 0x88, 0xda, 0x49, 0x3e, 0xbf, 0xa2, 0x21, 0xd6, 0x31, 0xac, 0x9f, 0xf2, 0xf8, + 0xd1, 0x5c, 0xf8, 0x89, 0x72, 0x0c, 0x9e, 0x24, 0x30, 0xc1, 0x9f, 0xd9, 0x36, 0xae, 0xcc, 0xcc, + 0xbb, 0x09, 0xf2, 0xc3, 0x5c, 0xf9, 0x33, 0x87, 0x58, 0xb5, 0x47, 0x69, 0x26, 0x23, 0x57, 0x98, + 0xa4, 0x62, 0xa9, 0x0d, 0x70, 0xa7, 0x2d, 0xce, 0x6f, 0x55, 0x05, 0x8f, 0x8b, 0x51, 0x5b, 0x18, + 0xcd, 0x65, 0x9b, 0x47, 0xb6, 0xee, 0xd4, 0xfd, 0x72, 0x28, 0xa0, 0x94, 0xa2, 0xd7, 0xd2, 0xef, + 0x5a, 0xae, 0xc1, 0xf3, 0x6b, 0x5c, 0xa4, 0x54, 0xdb, 0x48, 0xec, 0xfd, 0xe1, 0xe9, 0x5e, 0x8c, + 0x62, 0x4c, 0xf7, 0x7a, 0x50, 0x62, 0xeb, 0xdf, 0x54, 0x6a, 0x49, 0x6f, 0xdb, 0x5a, 0x02, 0x96, + 0xf9, 0x1d, 0x57, 0x8e, 0xa1, 0x61, 0xaa, 0xc7, 0xc7, 0xa8, 0x1b, 0xf5, 0x33, 0x3d, 0x65, 0x12, + 0x45, 0x54, 0xfc, 0x9d, 0x40, 0x17, 0x7c, 0xff, 0xf4, 0x2e, 0x0b, 0xbd, 0x56, 0x80, 0x5c, 0x83, + 0x7f, 0xe6, 0x20, 0x3f, 0x6e, 0x91, 0xa2, 0x2c, 0x58, 0x33, 0x69, 0xbc, 0x15, 0x10, 0xdc, 0x2d, + 0xa3, 0xd6, 0x06, 0xa9, 0xce, 0xa7, 0xec, 0xa8, 0x28, 0x14, 0xbe, 0xbe, 0x80, 0x82, 0x8f, 0x1d, + 0x4c, 0x24, 0x40, 0x26, 0x68, 0xdd, 0xa9, 0xaa, 0x4c, 0xd6, 0x87, 0x7e, 0x46, 0x7a, 0xaa, 0x43, + 0x56, 0x2e, 0xd9, 0x24, 0xda, 0x6f, 0xdd, 0x21, 0x10, 0x39, 0x48, 0xd5, 0x08, 0xec, 0x5d, 0x1f, + 0xe4, 0xdb, 0x64, 0xa1, 0x99, 0x8b, 0x11, 0x60, 0x2f, 0x4b, 0x44, 0x84, 0xd2, 0x69, 0x52, 0xfd, + 0xee, 0xe9, 0x5b, 0xb0, 0xa8, 0xc5, 0x07, 0x77, 0x15, 0xfe, 0x58, 0xf5, 0x62, 0xfb, 0x60, 0x4c, + 0x43, 0xe0, 0x17, 0x54, 0x42, 0x9f, 0x07, 0x7c, 0x2d, 0xc0, 0xa2, 0x6a, 0x3e, 0x13, 0x0b, 0x78, + 0x5c, 0x62, 0x98, 0x7f, 0x55, 0xe2, 0xc7, 0xb2, 0x58, 0xe1, 0x9d, 0x53, 0xb5, 0xd9, 0xaf, 0x0c, + 0x11, 0x70, 0x85, 0xca, 0x21, 0x87, 0x1a, 0x39, 0x5e, 0x67, 0xd4, 0x51, 0x75, 0x2e, 0xa8, 0xea, + 0x0d, 0x30, 0xc0, 0x93, 0x60, 0x18, 0x7f, 0xdf, 0x4a, 0x41, 0xa0, 0x80, 0x1c, 0xed, 0x5c, 0xaa, + 0x84, 0x4f, 0x2d, 0xec, 0x8c, 0xad, 0x24, 0xa1, 0x4b, 0xa9, 0x52, 0x27, 0x8e, 0x70, 0xf6, 0xff, + 0xc0, 0xb4, 0x13, 0x39, 0x75, 0xd4, 0xfc, 0x9a, 0xbf, 0xff, 0x53, 0x3f, 0x44, 0x19, 0xd9, 0xa5, + 0x28, 0x18, 0x5c, 0x38, 0xfb, 0x4c, 0x3e, 0x5b, 0x40, 0xf2, 0xf4, 0xc2, 0x2c, 0x95, 0xdb, 0xd2, + 0xe5, 0x5f, 0x87, 0x56, 0x63, 0x28, 0xda, 0x07, 0xa9, 0x90, 0x83, 0x94, 0xdb, 0x56, 0x2c, 0xa3, + 0xd0, 0xc4, 0x52, 0x6d, 0x1f, 0xfa, 0x35, 0x4f, 0xba, 0xcf, 0x12, 0xf4, 0xf0, 0x46, 0xb5, 0x1e, + 0x67, 0xba, 0x10, 0xc9, 0xc3, 0x0a, 0x30, 0xed, 0xcd, 0xc4, 0x3a, 0x87, 0x08, 0x2c, 0xd9, 0x21, + 0x5f, 0x68, 0x0f, 0xf8, 0x2f, 0x6f, 0x2a, 0x27, 0x47, 0x79, 0x16, 0x52, 0x7a, 0xfd, 0x9d, 0x65, + 0xec, 0x53, 0x90, 0xaf, 0xf0, 0x45, 0x24, 0x08, 0x5a, 0x9f, 0xfd, 0xec, 0xd9, 0x9a, 0x4c, 0x0a, + 0xd4, 0x09, 0x58, 0xdd, 0x29, 0xe4, 0x1a, 0x8e, 0xe9, 0xa3, 0x60, 0x85, 0xd8, 0xd5, 0x9c, 0xb7, + 0x33, 0x2c, 0x3a, 0xfe, 0xd7, 0x09, 0x5a, 0x7a, 0x19, 0x3b, 0x67, 0xc2, 0xc9, 0xf1, 0x41, 0xa4, + 0xc6, 0x7f, 0x1e, 0x7d, 0x6a, 0x75, 0x24, 0xce, 0xef, 0x30, 0xdc, 0x74, 0x8f, 0x2d, 0x8c, 0xf0, + 0x5d, 0x2d, 0x4b, 0x0d, 0x0d, 0x1a, 0xda, 0x8b, 0xdb, 0xc9, 0xac, 0xeb, 0x51, 0x5e, 0xaa, 0xde, + 0x05, 0x3c, 0x8c, 0x87, 0x09, 0x08, 0x2d, 0xd2, 0xca, 0xe6, 0x66, 0x97, 0x70, 0x38, 0x0e, 0x28, + 0x53, 0x4b, 0x59, 0x85, 0x6a, 0x59, 0xe2, 0xd2, 0x6f, 0x87, 0x4f, 0x4b, 0xf5, 0xe1, 0x4d, 0xc9, + 0x23, 0xdd, 0xfe, 0x77, 0x44, 0x92, 0x3f, 0xf6, 0x78, 0x93, 0x18, 0x38, 0x02, 0x24, 0x22, 0x89, + 0xb7, 0x59, 0x84, 0x7d, 0xe4, 0xf7, 0x67, 0xaa, 0xb8, 0xd4, 0x03, 0x92, 0x97, 0xfd, 0xaa, 0xb0, + 0x5d, 0xee, 0x1a, 0x48, 0xb1, 0xfb, 0x1c, 0x9d, 0xaf, 0x64, 0xc3, 0xd6, 0x3e, 0xb7, 0x62, 0xf5, + 0xdb, 0xea, 0x61, 0x1d, 0xde, 0xc6, 0xee, 0x6e, 0x90, 0xfd, 0x0b, 0x74, 0xd2, 0xc2, 0xf7, 0x35, + 0x98, 0x78, 0x74, 0x3e, 0xb4, 0xac, 0x29, 0x4f, 0xcd, 0x95, 0x6f, 0x0a, 0x6b, 0x20, 0xee, 0xd6, + 0xd8, 0x6b, 0x34, 0x51, 0xc0, 0x6f, 0x52, 0x9c, 0x4d, 0xac, 0x9a, 0x11, 0xb8, 0xb8, 0x29, 0x37, + 0x8a, 0x1b, 0x8f, 0x0c, 0x3a, 0x7a, 0x24, 0xfa, 0xc9, 0x5b, 0xef, 0x94, 0x9d, 0x36, 0xf9, 0x1a, + 0x5b, 0x97, 0xab, 0x0d, 0x3e, 0xc4, 0x7c, 0x9a, 0x83, 0xb7, 0x36, 0x1b, 0x2c, 0x93, 0xd2, 0x66, + 0x6e, 0x6f, 0x32, 0x11, 0x2f, 0x21, 0x19, 0x96, 0x3d, 0x7c, 0x5f, 0x2e, 0x6c, 0x05, 0x34, 0x95, + 0x7c, 0x1b, 0x9b, 0x33, 0xa4, 0xb2, 0x6d, 0x5f, 0xda, 0x45, 0x69, 0x0e, 0x5c, 0x1e, 0x5e, 0xa9, + 0x1a, 0x31, 0xc8, 0x23, 0x78, 0x98, 0x34, 0x4b, 0xe9, 0x37, 0xd5, 0x87, 0x46, 0xec, 0x9b, 0x20, + 0x50, 0x35, 0xb9, 0x95, 0xe5, 0x06, 0x50, 0xa6, 0xe1, 0xdd, 0x19, 0xf5, 0xc6, 0x96, 0xec, 0xb3, + 0x08, 0x1c, 0x25, 0xad, 0x3b, 0xfc, 0x11, 0x6c, 0x9a, 0x7d, 0xd8, 0x31, 0x03, 0x24, 0xb5, 0xcb, + 0x90, 0xed, 0xfc, 0x98, 0xb1, 0x46, 0xec, 0xd0, 0xa9, 0x3c, 0x1f, 0x66, 0xb5, 0xba, 0x5e, 0xf2, + 0x5a, 0xd5, 0xf3, 0xdf, 0x54, 0xe7, 0x11, 0x89, 0xdc, 0xf0, 0xea, 0x09, 0x5d, 0x7a, 0x7a, 0xf6, + 0x5f, 0x5d, 0x69, 0xc0, 0xbc, 0xf3, 0x73, 0x73, 0x9a, 0xd5, 0x78, 0x40, 0xe3, 0x54, 0x31, 0x45, + 0xd1, 0xc0, 0x2f, 0x93, 0xbc, 0x1e, 0x2f, 0x39, 0x4e, 0xb4, 0xf0, 0x3e, 0x57, 0x7a, 0x64, 0x8d, + 0x98, 0x66, 0x5d, 0x83, 0x5a, 0x6f, 0x8b, 0x5f, 0xf2, 0x7e, 0xd1, 0xc9, 0xcc, 0xbb, 0xf7, 0xaa, + 0x95, 0x2e, 0x7a, 0x7d, 0x8d, 0xec, 0x37, 0x7a, 0xb5, 0xbc, 0x8d, 0x62, 0xd2, 0x32, 0x1e, 0xd7, + 0x8b, 0x15, 0x06, 0x75, 0xde, 0x81, 0xab, 0xb0, 0xd4, 0x59, 0xa2, 0x25, 0x34, 0xca, 0x6d, 0xce, + 0x3f, 0xa3, 0xae, 0xe6, 0x09, 0xb3, 0x33, 0xe1, 0x25, 0x56, 0x77, 0x30, 0x8b, 0xf7, 0x30, 0x0f, + 0x74, 0x72, 0x36, 0x8c, 0x4b, 0x5d, 0x94, 0xbc, 0x4f, 0x5e, 0x1d, 0x8a, 0x75, 0xec, 0xd4, 0x21, + 0x21, 0xa9, 0x54, 0x9c, 0xc8, 0x37, 0x28, 0x06, 0xae, 0x5c, 0x72, 0x3b, 0xa0, 0x80, 0x0d, 0x17, + 0xbb, 0x22, 0xe8, 0xf7, 0xa9, 0x31, 0x7d, 0x2c, 0x13, 0x74, 0xbc, 0xa0, 0x09, 0xba, 0x5b, 0x05, + 0xa4, 0xf9, 0xab, 0xb5, 0xd5, 0xd7, 0x11, 0x3f, 0xa3, 0xb4, 0x89, 0x79, 0x1c, 0x4a, 0xd8, 0xfb, + 0xc6, 0x54, 0x41, 0xaf, 0x32, 0xc9, 0x71, 0xaa, 0x5a, 0xb1, 0xb5, 0xe0, 0xa0, 0x73, 0x45, 0x18, + 0x73, 0x17, 0xd2, 0xcb, 0xb8, 0x70, 0x30, 0xbb, 0xce, 0x25, 0xad, 0x9e, 0x8d, 0xf3, 0x0d, 0xec, + 0x26, 0x3f, 0x2c, 0x16, 0x49, 0x45, 0x68, 0xbe, 0x04, 0x3e, 0x67, 0x1a, 0xa6, 0x7e, 0xe9, 0x44, + 0x63, 0x43, 0x91, 0x92, 0x25, 0x84, 0x04, 0xe6, 0xa8, 0xb7, 0xf2, 0x70, 0x86, 0xba, 0x2e, 0x34, + 0x4c, 0x0f, 0x45, 0xac, 0x39, 0x8d, 0x0c, 0x59, 0x60, 0x08, 0xb2, 0x07, 0x79, 0xfd, 0xd0, 0x60, + 0xad, 0x0d, 0x53, 0xa6, 0x9b, 0x02, 0x22, 0xf2, 0xbc, 0xb4, 0xbd, 0x9e, 0x8a, 0xe8, 0x3b, 0xa7, + 0x76, 0x21, 0x8e, 0x59, 0x5f, 0x08, 0xb6, 0xf9, 0x4f, 0x18, 0x09, 0x8b, 0x8a, 0x94, 0x59, 0x93, + 0xa3, 0x23, 0xf1, 0xdb, 0x62, 0x88, 0x30, 0xe5, 0xea, 0xf1, 0x79, 0x3a, 0xf4, 0x3a, 0x57, 0xee, + 0xab, 0xa0, 0x82, 0x39, 0x44, 0xd9, 0x13, 0xb9, 0x32, 0xb4, 0x97, 0xb9, 0xa9, 0xb3, 0x23, 0x81, + 0x61, 0xed, 0x96, 0x51, 0xd9, 0xc5, 0x1c, 0x1b, 0xe7, 0x2a, 0x18, 0x83, 0xdb, 0xf5, 0xf2, 0x93, + 0x98, 0xd8, 0x79, 0xc3, 0x38, 0x6d, 0x86, 0x83, 0x9a, 0x80, 0x0d, 0x21, 0x5e, 0xbd, 0x7c, 0x7a, + 0x32, 0xd0, 0x75, 0xea, 0xe4, 0x95, 0x01, 0xcc, 0xa3, 0x2c, 0x74, 0x97, 0x1a, 0x25, 0xc7, 0x1a, + 0x38, 0xe6, 0x92, 0x8b, 0x89, 0xff, 0x56, 0xcd, 0x8d, 0x9f, 0xa0, 0x18, 0x9b, 0x00, 0xc4, 0x58, + 0x38, 0x49, 0x6a, 0x87, 0x59, 0xcc, 0x3b, 0xde, 0xb1, 0x6a, 0x86, 0x12, 0x74, 0x03, 0xd7, 0x04, + 0xc4, 0x63, 0xab, 0x1f, 0x5f, 0xf8, 0x4b, 0xba, 0x1d, 0x27, 0x06, 0xba, 0x68, 0xee, 0xe2, 0xd3, + 0x59, 0xb1, 0xc1, 0x7b, 0x97, 0x4e, 0x36, 0x9e, 0x13, 0x62, 0x9a, 0xad, 0x75, 0xe5, 0x44, 0xaa, + 0x9c, 0x5e, 0xdd, 0x05, 0x24, 0x6f, 0x44, 0x54, 0xc2, 0x5a, 0xfd, 0x4e, 0x97, 0x49, 0xfc, 0xf8, + 0xe9, 0x87, 0x42, 0x7d, 0xc5, 0xd6, 0x36, 0x21, 0x20, 0x6c, 0x2c, 0x32, 0xf9, 0xca, 0x49, 0x2f, + 0x7c, 0x3c, 0x24, 0x39, 0xd6, 0x91, 0xd3, 0x69, 0xf1, 0x8b, 0x91, 0x54, 0xfd, 0xa0, 0x7a, 0x01, + 0x52, 0x4a, 0xee, 0xf7, 0xea, 0xac, 0x19, 0xe8, 0x26, 0x8c, 0x5b, 0x23, 0xd3, 0xa3, 0xa6, 0x44, + 0xdf, 0x9c, 0x90, 0xd8, 0x09, 0x68, 0xda, 0x44, 0x50, 0x2c, 0x55, 0x44, 0xd5, 0xc2, 0x7d, 0xab, + 0xb0, 0x44, 0x81, 0xe5, 0xd9, 0x89, 0x0b, 0x08, 0x7e, 0xe0, 0x15, 0x0f, 0xef, 0x80, 0xd9, 0x46, + 0xef, 0x0d, 0x58, 0x9b, 0xa2, 0x5f, 0x74, 0xb4, 0x5c, 0x66, 0x84, 0x5b, 0x5d, 0x5e, 0x08, 0xd1, + 0xfc, 0x8e, 0x7b, 0xb4, 0x51, 0x59, 0x17, 0xb3, 0x32, 0xdb, 0x86, 0x6a, 0x7a, 0x11, 0x74, 0x78, + 0xda, 0x6b, 0x50, 0x10, 0x16, 0x04, 0x48, 0x1f, 0xc8, 0x24, 0x9f, 0x77, 0xb7, 0x39, 0x0f, 0xd4, + 0xde, 0x34, 0x50, 0x3a, 0xb7, 0x2d, 0x0e, 0x6e, 0x9e, 0x15, 0x9a, 0x8e, 0x90, 0x1e, 0x93, 0xbf, + 0x6b, 0xb8, 0xeb, 0x10, 0x52, 0xe4, 0x0d, 0x7f, 0x05, 0x0e, 0x5d, 0x87, 0x25, 0x8f, 0xbc, 0x7f, + 0x25, 0xfa, 0xce, 0x37, 0x03, 0xac, 0x15, 0xfa, 0x46, 0x3d, 0xd5, 0x48, 0xfb, 0xf2, 0x63, 0x7b, + 0xda, 0x6f, 0x37, 0xdb, 0xbe, 0xc0, 0xad, 0xac, 0xb3, 0x36, 0xe4, 0xe6, 0x15, 0xd7, 0xd4, 0xc8, + 0x4e, 0xe0, 0x74, 0x3d, 0xe7, 0x31, 0x05, 0xf3, 0x42, 0x79, 0x12, 0x91, 0x56, 0x8e, 0xf7, 0xd1, + 0x60, 0xd4, 0x7d, 0x28, 0x53, 0x5b, 0xe9, 0x16, 0x25, 0x17, 0x32, 0x6c, 0x3a, 0x80, 0xc8, 0x23, + 0xe3, 0x54, 0xef, 0xc4, 0xfe, 0xd7, 0x21, 0xa1, 0xc1, 0x01, 0xfc, 0xad, 0x4e, 0x3d, 0x14, 0xb5, + 0xd4, 0x08, 0x9d, 0xdd, 0x98, 0x6c, 0xd6, 0x26, 0x4d, 0xad, 0x83, 0x50, 0x45, 0x82, 0x0e, 0x8d, + 0x1e, 0x4c, 0x7a, 0xea, 0x65, 0xb2, 0x1c, 0x75, 0x2d, 0xe3, 0x57, 0xd2, 0x26, 0x56, 0x8c, 0x46, + 0xb7, 0x83, 0x61, 0x4b, 0x1d, 0xe0, 0x42, 0xa1, 0x3f, 0x9d, 0xe5, 0x37, 0xdd, 0xfa, 0x21, 0xd8, + 0x45, 0x2a, 0xa5, 0xc8, 0x4f, 0x8a, 0x38, 0x0c, 0xc0, 0x7f, 0x43, 0xac, 0xfa, 0xaf, 0x8b, 0x84, + 0xdf, 0x70, 0xc3, 0xf7, 0x1b, 0xff, 0x1c, 0x82, 0x66, 0xdb, 0x04, 0x27, 0xa8, 0x60, 0x38, 0xd9, + 0x6a, 0x76, 0xbc, 0xd2, 0xac, 0xa7, 0x2c, 0xa7, 0x25, 0xde, 0xe2, 0xff, 0xc0, 0x30, 0xbb, 0x45, + 0x3c, 0x11, 0xea, 0x3b, 0x33, 0xfb, 0x40, 0x71, 0xbe, 0xfe, 0xa6, 0x0b, 0xb9, 0xac, 0xff, 0xa9, + 0xe4, 0xc6, 0x5d, 0x9a, 0x9b, 0xea, 0x10, 0x53, 0x95, 0xa3, 0x4f, 0x9b, 0xc7, 0x8c, 0x4c, 0x5e, + 0x92, 0x95, 0xc1, 0x52, 0xd2, 0xe1, 0x45, 0x4a, 0x53, 0x14, 0xc1, 0xed, 0x1f, 0xba, 0x8a, 0x47, + 0xc3, 0x64, 0x1e, 0x7b, 0xf6, 0x61, 0x39, 0xb8, 0x1c, 0x83, 0x59, 0x2d, 0x1e, 0xf6, 0xb4, 0x81, + 0x32, 0xee, 0xe0, 0x97, 0xd2, 0x25, 0xdb, 0xa6, 0x44, 0xf0, 0xe9, 0x73, 0xa1, 0xb5, 0xfc, 0x1b, + 0x04, 0xe5, 0x5d, 0x35, 0x3c, 0xe3, 0x1b, 0x4a, 0x30, 0x02, 0x29, 0x00, 0xe9, 0xda, 0xc5, 0x74, + 0x6f, 0x7e, 0xb4, 0xa1, 0x4f, 0xbb, 0xfe, 0x8b, 0x36, 0x74, 0x2a, 0x4e, 0xee, 0xc6, 0x85, 0x38, + 0x05, 0x74, 0xfe, 0x5c, 0xf2, 0xca, 0x39, 0xdd, 0xab, 0xca, 0xa4, 0x30, 0xf9, 0xee, 0xf1, 0x3b, + 0xdd, 0x2c, 0xe0, 0x64, 0x73, 0x88, 0x9e, 0x80, 0x0f, 0xbf, 0xf8, 0x5e, 0x1a, 0x8b, 0x05, 0xea, + 0x9a, 0x9a, 0xae, 0x82, 0xeb, 0x6d, 0x04, 0xbf, 0xa8, 0x25, 0xdf, 0x54, 0x17, 0x92, 0x3d, 0x52, + 0x4e, 0x3c, 0x93, 0xc6, 0x5a, 0xd8, 0x50, 0xf8, 0x57, 0x42, 0xf2, 0x02, 0x9e, 0xbb, 0xf6, 0x44, + 0xd7, 0x0d, 0x59, 0xdf, 0x77, 0x3b, 0x23, 0x54, 0x7b, 0xa7, 0x67, 0x75, 0xf3, 0xe5, 0x75, 0x3e, + 0x9d, 0xdc, 0xe0, 0xdc, 0x75, 0xb8, 0x93, 0xf0, 0xd2, 0x5b, 0x03, 0x9c, 0x56, 0x4d, 0x22, 0xd9, + 0xfd, 0x42, 0xb2, 0xcf, 0xc9, 0xb4, 0x3f, 0xe5, 0x32, 0x01, 0x75, 0x54, 0xa4, 0xdf, 0xa3, 0x43, + 0xcd, 0x77, 0x25, 0x87, 0xb9, 0x74, 0x07, 0x71, 0xe8, 0xa6, 0x82, 0x82, 0x14, 0x16, 0x94, 0x45, + 0x6a, 0xb1, 0x42, 0xfe, 0x7b, 0xbf, 0x08, 0xa2, 0x1d, 0x42, 0xc2, 0x79, 0x6e, 0xec, 0x50, 0x71, + 0x57, 0xa5, 0x81, 0xbf, 0xe4, 0x52, 0x68, 0xf1, 0xd4, 0xc9, 0xdb, 0x34, 0x2d, 0x9e, 0xda, 0x2f, + 0x29, 0xda, 0x43, 0x6a, 0xc6, 0x13, 0x09, 0x9e, 0xf1, 0xfb, 0xe1, 0x6b, 0x9b, 0x48, 0x5d, 0x8e, + 0xcb, 0xc0, 0xb3, 0x0f, 0x48, 0x67, 0x8e, 0x53, 0xd7, 0x51, 0x8e, 0xf4, 0x44, 0x1d, 0xcf, 0xc4, + 0x03, 0x0d, 0x64, 0x68, 0xb9, 0x62, 0x2b, 0x0b, 0x31, 0xf1, 0xc8, 0x22, 0xce, 0xbe, 0xc5, 0xa6, + 0x06, 0x4f, 0x43, 0x9a, 0x1b, 0xa5, 0xfc, 0xa6, 0xac, 0xe4, 0x94, 0x5e, 0x4b, 0x80, 0x65, 0xfe, + 0xb4, 0xeb, 0xd4, 0x4d, 0x0e, 0x66, 0x01, 0x1d, 0x2b, 0x31, 0x7d, 0xfc, 0x3a, 0xb2, 0x63, 0x45, + 0x5b, 0x3a, 0x64, 0xd1, 0xc8, 0x25, 0x1a, 0xa6, 0x6c, 0x96, 0xa5, 0x9c, 0x20, 0xfc, 0xf8, 0x8a, + 0x0d, 0x5b, 0x83, 0x19, 0xd4, 0xde, 0x01, 0xc3, 0x22, 0x06, 0x6c, 0x0b, 0x0a, 0x17, 0x9c, 0x77, + 0x1f, 0xc0, 0x53, 0x07, 0xc7, 0x6f, 0xe3, 0xdf, 0x61, 0x6e, 0x21, 0x0e, 0x8f, 0x26, 0x3b, 0x89, + 0x3b, 0x7b, 0x11, 0x7a, 0xf2, 0x88, 0x29, 0x98, 0xff, 0xec, 0x4b, 0x95, 0xee, 0x8b, 0xc7, 0xde, + 0x60, 0x0a, 0x49, 0x0e, 0x4f, 0xa3, 0x91, 0xa9, 0xfc, 0x97, 0x4a, 0x34, 0xe8, 0x00, 0x8f, 0x38, + 0xa6, 0x91, 0xe5, 0xde, 0xfe, 0x2d, 0x20, 0xde, 0xd8, 0x9b, 0x6a, 0x97, 0x14, 0x3a, 0xaf, 0x2f, + 0x47, 0x8a, 0x66, 0x22, 0x03, 0x68, 0x4b, 0x9b, 0xe4, 0xbd, 0x98, 0x2e, 0x5f, 0x21, 0x63, 0x5a, + 0x9a, 0x70, 0x27, 0x41, 0x46, 0x51, 0x27, 0xbb, 0xa1, 0xb6, 0xd5, 0x2d, 0xdf, 0x09, 0x64, 0xd5, + 0xdb, 0x0c, 0x2f, 0x4c, 0x00, 0x55, 0x45, 0xd1, 0x12, 0xd7, 0xdb, 0x81, 0x09, 0x40, 0x59, 0xba, + 0x93, 0xe8, 0xfc, 0x0c, 0x1a, 0x9e, 0x00, 0xd9, 0xf7, 0xc5, 0x68, 0x23, 0x16, 0x10, 0x51, 0xba, + 0xb0, 0x0c, 0x67, 0x56, 0x6d, 0xd4, 0x81, 0x88, 0xa1, 0x6f, 0xcc, 0x9c, 0x54, 0x3b, 0x5a, 0xc0, + 0x27, 0x90, 0xaa, 0xf1, 0x10, 0xf7, 0x28, 0x56, 0xec, 0x49, 0x05, 0x41, 0x88, 0x24, 0x9a, 0x8b, + 0x62, 0x5f, 0xe1, 0x9c, 0xa6, 0xd7, 0x23, 0x08, 0x80, 0xf5, 0x85, 0x4d, 0xce, 0xa4, 0xf5, 0x11, + 0xc0, 0x4b, 0xd3, 0x64, 0xe4, 0x2e, 0x08, 0x3b, 0xea, 0x33, 0x46, 0xaf, 0x92, 0xec, 0x61, 0xc8, + 0x14, 0xee, 0x6f, 0x90, 0x5a, 0xe8, 0x3e, 0xcb, 0xe1, 0x41, 0xd8, 0x5f, 0xab, 0xac, 0x5b, 0xe7, + 0x61, 0x09, 0x92, 0x62, 0xc8, 0x42, 0x12, 0x3f, 0x9d, 0x17, 0x11, 0x17, 0x1d, 0x89, 0x1c, 0x59, + 0x55, 0x42, 0xec, 0x37, 0x7b, 0xdc, 0x30, 0xe7, 0x01, 0x8f, 0x76, 0x6c, 0xda, 0xb0, 0x45, 0x50, + 0x02, 0x8d, 0x27, 0xea, 0x55, 0x04, 0x11, 0xf6, 0xf3, 0x3f, 0xca, 0xed, 0xef, 0x8c, 0xf6, 0xb6, + 0xd5, 0x83, 0x46, 0xa1, 0x56, 0xd9, 0xc5, 0xa5, 0x65, 0x45, 0x9c, 0x50, 0x3e, 0x9e, 0xc6, 0xd0, + 0x83, 0x8d, 0x13, 0xd0, 0x6a, 0x21, 0x30, 0x44, 0x70, 0x6a, 0x95, 0xf2, 0x48, 0x18, 0x84, 0xe5, + 0x60, 0xa4, 0xb3, 0xe5, 0x74, 0xe0, 0x8a, 0x47, 0x58, 0x82, 0x89, 0xb7, 0x16, 0xc0, 0x1a, 0x0f, + 0x0f, 0x35, 0x56, 0xa3, 0x0c, 0xdb, 0x12, 0xc0, 0x02, 0x8f, 0x1a, 0x72, 0xd1, 0x73, 0xbf, 0xf0, + 0x67, 0x94, 0xaa, 0xc8, 0x73, 0x5b, 0x95, 0x61, 0x5a, 0xca, 0x41, 0xf5, 0xe9, 0xc6, 0x38, 0x21, + 0x67, 0x1b, 0xe7, 0xc5, 0x7b, 0x0d, 0x06, 0x60, 0x6d, 0x31, 0x40, 0x6e, 0xa5, 0xd6, 0xfa, 0xe1, + 0xd1, 0x85, 0x8e, 0x52, 0x2d, 0xf5, 0x06, 0x90, 0xf8, 0x55, 0xf9, 0x1e, 0x8e, 0x7f, 0xd5, 0xc7, + 0x32, 0x0a, 0x93, 0xb8, 0xe0, 0xe3, 0x1c, 0xe1, 0xa0, 0xfe, 0xa6, 0x11, 0x4b, 0x08, 0x14, 0x47, + 0x10, 0x56, 0xc5, 0x62, 0x38, 0x22, 0x12, 0xfc, 0x2b, 0x9a, 0x9e, 0xf2, 0x19, 0xe7, 0xa4, 0xa2, + 0x0f, 0xb8, 0x32, 0xeb, 0x42, 0x77, 0x3c, 0xb2, 0x41, 0xbf, 0x3c, 0x05, 0x19, 0xf3, 0x6a, 0x50, + 0x74, 0x41, 0x0e, 0x02, 0xab, 0x1a, 0xc7, 0x69, 0x04, 0x76, 0xb4, 0xb2, 0x45, 0x6f, 0x05, 0x92, + 0x77, 0x83, 0x9b, 0xc2, 0x4b, 0xeb, 0x30, 0xf1, 0x8e, 0xf0, 0x2c, 0xa8, 0x52, 0xdf, 0xcf, 0x0f, + 0xd4, 0x63, 0xb7, 0x55, 0x9e, 0x8d, 0xd9, 0xc0, 0xef, 0x02, 0xaa, 0x74, 0x76, 0x43, 0x4b, 0x60, + 0x53, 0x04, 0xce, 0x21, 0xa5, 0xa0, 0x1c, 0x48, 0xca, 0x64, 0xe3, 0xc7, 0x18, 0xc2, 0x67, 0x95, + 0xba, 0x85, 0xe9, 0x87, 0xee, 0xd8, 0x03, 0x07, 0xc4, 0xe7, 0x6a, 0xf8, 0x83, 0xb4, 0xbc, 0xb6, + 0x82, 0x9e, 0xc9, 0x1e, 0xe3, 0xa9, 0x36, 0x22, 0x77, 0xc4, 0x98, 0x3c, 0x50, 0xfb, 0x6e, 0xd9, + 0x42, 0x2a, 0x48, 0xb6, 0xe8, 0x33, 0x7c, 0xc4, 0x30, 0xd7, 0xc0, 0x59, 0x6d, 0x5c, 0x74, 0x93, + 0x8b, 0x70, 0x28, 0x25, 0xcc, 0x52, 0x3d, 0xb1, 0xa8, 0xa6, 0x60, 0x39, 0x3a, 0x2d, 0xf6, 0x53, + 0x0e, 0x34, 0x28, 0xe1, 0x2b, 0x89, 0x08, 0x27, 0x3a, 0x28, 0x51, 0xef, 0x20, 0xf9, 0x9c, 0x36, + 0xb1, 0x2c, 0xeb, 0x6a, 0xeb, 0x60, 0x08, 0x0b, 0x25, 0xac, 0x34, 0x4d, 0x21, 0xea, 0x2d, 0x27, + 0x98, 0x62, 0x14, 0x68, 0x41, 0x94, 0x66, 0x20, 0x0d, 0x52, 0x32, 0x0d, 0x71, 0x68, 0x1a, 0x44, + 0x13, 0x47, 0xda, 0x22, 0xd6, 0xf5, 0x3a, 0x3a, 0x05, 0x9f, 0xfc, 0x62, 0xbc, 0x76, 0xd9, 0x37, + 0x7f, 0x73, 0x2b, 0x8d, 0x83, 0xa5, 0x81, 0xf3, 0x98, 0x95, 0x56, 0x99, 0x19, 0x73, 0xd7, 0x24, + 0xf7, 0x62, 0x79, 0xf5, 0x7b, 0x2e, 0x05, 0x41, 0x65, 0x72, 0xfb, 0x6a, 0xd1, 0xd2, 0xe9, 0x9c, + 0x08, 0x53, 0x8d, 0x08, 0x84, 0x27, 0xe7, 0x6a, 0xda, 0x99, 0xf2, 0xbf, 0x13, 0xb4, 0x1f, 0xa8, + 0x5f, 0x21, 0x40, 0xc0, 0x64, 0xb4, 0x0a, 0x6a, 0x2f, 0x88, 0x09, 0xff, 0x82, 0x19, 0x9b, 0xec, + 0x4f, 0xa0, 0xdf, 0x73, 0xb2, 0x41, 0x00, 0x09, 0xa6, 0xff, 0x38, 0x58, 0x68, 0x44, 0xe0, 0x67, + 0xda, 0xd7, 0x57, 0xd9, 0x9c, 0xf6, 0x0a, 0xd6, 0x9f, 0x6a, 0x3b, 0x98, 0x59, 0xdd, 0xdf, 0xe2, + 0x10, 0x56, 0xd5, 0xf3, 0x51, 0x20, 0x7e, 0xc5, 0x78, 0x0d, 0x18, 0xcf, 0x8f, 0x0c, 0x01, 0xf2, + 0xaa, 0xa2, 0x05, 0x9c, 0x65, 0x8e, 0x10, 0x86, 0x0a, 0x2c, 0x6c, 0x45, 0x7b, 0x6d, 0x03, 0xdf, + 0x57, 0xd3, 0x36, 0x21, 0xee, 0xd1, 0xd1, 0x81, 0x5e, 0x27, 0x86, 0xbc, 0x76, 0x70, 0x85, 0xe0, + 0x95, 0x46, 0xc7, 0xc8, 0x8b, 0x95, 0x28, 0x39, 0xc8, 0x55, 0xf9, 0x61, 0x7c, 0xd5, 0x37, 0x48, + 0xad, 0x68, 0x1c, 0x4e, 0x84, 0x38, 0x48, 0x34, 0xad, 0x24, 0xab, 0xfa, 0x1d, 0x6f, 0xda, 0x2e, + 0x41, 0xc4, 0xcc, 0x5c, 0x3b, 0xaf, 0x32, 0xb7, 0x13, 0x3d, 0x0a, 0x44, 0x83, 0x01, 0x78, 0x07, + 0xfe, 0x6f, 0xae, 0xfe, 0x11, 0xa4, 0x29, 0x54, 0x7d, 0x83, 0x8a, 0xd4, 0xed, 0xba, 0x93, 0x13, + 0x60, 0x3a, 0xd4, 0xa9, 0xa4, 0x63, 0x3e, 0x06, 0x81, 0xa0, 0x31, 0x8b, 0xc2, 0x25, 0x70, 0xaa, + 0xc8, 0x41, 0xcd, 0xce, 0x55, 0x9b, 0x6a, 0x6f, 0x75, 0x01, 0xcb, 0xd4, 0xde, 0x6b, 0xcc, 0x38, + 0xe5, 0x14, 0x18, 0xe4, 0x53, 0xac, 0x26, 0x08, 0x1e, 0x07, 0x78, 0x3c, 0xd4, 0x17, 0xdd, 0x40, + 0x50, 0x3c, 0x94, 0x46, 0x6b, 0xc4, 0xf3, 0x7b, 0xdd, 0x2d, 0xe3, 0xe9, 0x0e, 0x23, 0x44, 0x39, + 0xbc, 0x97, 0xa4, 0xa0, 0xda, 0x84, 0x20, 0xec, 0x94, 0xce, 0x0e, 0x04, 0xd4, 0xb0, 0x61, 0xb4, + 0x4f, 0xa7, 0x08, 0x71, 0xd6, 0x8e, 0x48, 0x6f, 0x88, 0xd4, 0x19, 0x60, 0x0a, 0x91, 0x77, 0x99, + 0xbb, 0xce, 0x30, 0xb8, 0x36, 0x1b, 0x0c, 0x13, 0x0e, 0x2d, 0x79, 0xc6, 0xe6, 0x79, 0xa4, 0xd7, + 0x4d, 0xea, 0x8e, 0xa2, 0xc1, 0x40, 0xbd, 0x2b, 0xde, 0x04, 0x78, 0xa6, 0x59, 0x8a, 0x10, 0xac, + 0xc3, 0xf6, 0x53, 0x71, 0xfe, 0x79, 0x0f, 0x79, 0x37, 0xd5, 0xbf, 0xdd, 0xab, 0xad, 0xac, 0x9e, + 0x12, 0xac, 0xbd, 0xd5, 0x06, 0x26, 0x35, 0xab, 0xb1, 0x0d, 0x26, 0x5e, 0x87, 0x3a, 0xa0, 0x07, + 0xb0, 0xb5, 0x72, 0xc8, 0xad, 0x43, 0x2b, 0x87, 0xb1, 0x91, 0xf4, 0x1c, 0x42, 0xd8, 0x51, 0xa6, + 0x6e, 0xf6, 0xa7, 0xff, 0x53, 0xd8, 0xa5, 0x11, 0xce, 0x2c, 0x01, 0xf4, 0x1d, 0x22, 0x23, 0x4d, + 0xcb, 0x27, 0x61, 0x06, 0xdb, 0x9d, 0x3c, 0x99, 0x0c, 0x5e, 0x1f, 0xca, 0x13, 0xde, 0x97, 0xdf, + 0xbd, 0x28, 0x72, 0xdc, 0x2d, 0x69, 0x9c, 0x3b, 0x6a, 0xa2, 0x0c, 0x5c, 0xf6, 0xfa, 0x2f, 0xc5, + 0xe6, 0xd6, 0x6c, 0xcd, 0x1a, 0xfe, 0x39, 0xed, 0x31, 0x72, 0x26, 0xbb, 0xa5, 0xfd, 0x2a, 0x97, + 0x0a, 0xdb, 0xa5, 0x54, 0xb1, 0x44, 0x00, 0x3f, 0x9b, 0x79, 0xa2, 0xda, 0xc3, 0xc1, 0x4d, 0xdf, + 0x70, 0x43, 0xc9, 0x0b, 0xdb, 0x4a, 0x24, 0xf7, 0xba, 0x4b, 0xac, 0x46, 0x78, 0x42, 0x3b, 0x66, + 0xe3, 0x2d, 0x3a, 0x42, 0x9a, 0x84, 0x3c, 0x5b, 0x36, 0x6f, 0x66, 0x14, 0x58, 0xec, 0x60, 0x4b, + 0x67, 0xfb, 0x6a, 0x34, 0x2c, 0x6a, 0x15, 0xb7, 0xc6, 0x7b, 0x0a, 0xe3, 0x5b, 0x9a, 0xcd, 0x84, + 0x2e, 0xab, 0x18, 0x8f, 0x08, 0x07, 0xe2, 0x25, 0xb6, 0x3d, 0x21, 0x0f, 0x59, 0xb7, 0x92, 0xaa, + 0x4f, 0x79, 0xcd, 0x60, 0x7e, 0x0a, 0x0a, 0x85, 0xff, 0x4d, 0x0d, 0x01, 0x0f, 0xe2, 0xcf, 0x97, + 0xee, 0x13, 0x75, 0xfc, 0x91, 0x80, 0x0a, 0x96, 0x86, 0x6c, 0x88, 0x09, 0xeb, 0x5c, 0x71, 0x6b, + 0x24, 0x51, 0xec, 0xd3, 0xa4, 0x83, 0x14, 0x47, 0x8b, 0xa0, 0x21, 0x95, 0x38, 0xf3, 0x0f, 0x56, + 0x81, 0xb5, 0x93, 0xfe, 0xe1, 0x63, 0x8f, 0x88, 0x6b, 0x85, 0x38, 0xce, 0x3c, 0x5c, 0xea, 0x46, + 0x73, 0xb8, 0x00, 0xd9, 0x5d, 0xa8, 0x3f, 0x76, 0xfd, 0xdc, 0x9e, 0x78, 0x90, 0x83, 0xd2, 0x29, + 0xb2, 0xbd, 0x86, 0x85, 0x58, 0x65, 0x33, 0xb7, 0x01, 0xab, 0x68, 0x84, 0xc5, 0xab, 0x7a, 0x77, + 0x8e, 0x4b, 0xf2, 0x27, 0x3d, 0x44, 0x3e, 0xa4, 0x4e, 0x19, 0x20, 0xde, 0xaa, 0xe2, 0x28, 0xf2, + 0x85, 0x86, 0xa6, 0x92, 0x2a, 0xce, 0x88, 0xae, 0x9f, 0xfe, 0xff, 0xac, 0x1a, 0xbf, 0x78, 0x69, + 0xe4, 0x98, 0xb5, 0xa1, 0x54, 0x97, 0x05, 0x25, 0x70, 0x3e, 0x67, 0x00, 0x96, 0xc5, 0xe0, 0x39, + 0x9c, 0x95, 0x92, 0x7d, 0xd7, 0x23, 0x83, 0xb9, 0xe2, 0xf3, 0xbb, 0x65, 0x98, 0xcc, 0xda, 0x47, + 0xf2, 0xd3, 0x59, 0x43, 0x34, 0x92, 0x32, 0x03, 0x70, 0x5f, 0x5f, 0xcd, 0x8c, 0xba, 0xc6, 0x97, + 0x48, 0x20, 0x18, 0x8e, 0xe2, 0xfc, 0x96, 0xc9, 0x6a, 0x4a, 0xcf, 0x4c, 0xf8, 0x68, 0x55, 0x3c, + 0x80, 0x8f, 0x69, 0x41, 0xe2, 0xf1, 0x08, 0x90, 0xe4, 0xa0, 0xf4, 0x63, 0x04, 0x4f, 0x64, 0x16, + 0xfc, 0xd5, 0x32, 0xf0, 0x87, 0x57, 0x60, 0x28, 0x85, 0xfc, 0x1f, 0x8c, 0x42, 0xec, 0xc1, 0x41, + 0x93, 0x32, 0x0b, 0x4b, 0x8e, 0xbc, 0x18, 0xc7, 0x15, 0xd4, 0xe1, 0x99, 0x3f, 0x69, 0x74, 0x05, + 0x44, 0xd1, 0xd7, 0x83, 0xc0, 0x01, 0x00, 0x34, 0x0e, 0x44, 0x56, 0xf5, 0xe2, 0x6c, 0xfe, 0x26, + 0xfb, 0x10, 0x2a, 0xfc, 0xea, 0xb6, 0x1f, 0xef, 0x62, 0xbe, 0x39, 0x0d, 0xa2, 0xfc, 0xea, 0x72, + 0x2d, 0xa6, 0x1e, 0x5c, 0x25, 0x0f, 0xcc, 0xe6, 0xad, 0xc5, 0xe6, 0x53, 0xc9, 0x1c, 0x46, 0x4a, + 0x89, 0xaf, 0x58, 0xf9, 0xa3, 0x09, 0x0b, 0x6e, 0xdf, 0x29, 0xcd, 0xfc, 0x4c, 0xb8, 0x9b, 0x3e, + 0x0e, 0x5b, 0xdb, 0x4e, 0x4b, 0x82, 0x36, 0x7b, 0x01, 0xe9, 0x83, 0x75, 0x5a, 0xfc, 0xe5, 0x90, + 0xc3, 0xe9, 0xc2, 0x6f, 0x15, 0x8f, 0x01, 0xc5, 0x8a, 0x0a, 0xea, 0x73, 0x02, 0xc0, 0xa4, 0x7a, + 0x18, 0x32, 0x30, 0xb9, 0x05, 0xb7, 0x03, 0x02, 0xef, 0xac, 0x2f, 0xdc, 0x5c, 0x40, 0x2a, 0x56, + 0x0b, 0xe5, 0xe3, 0x70, 0x85, 0x88, 0x1d, 0xd9, 0x7d, 0xa0, 0x40, 0x8d, 0x37, 0x85, 0xdf, 0xd0, + 0xca, 0xd6, 0x1f, 0xe7, 0x67, 0xfa, 0xc5, 0xb8, 0x92, 0xdd, 0x4f, 0x26, 0x4d, 0x77, 0xbe, 0x51, + 0xa8, 0x0b, 0x1d, 0x2c, 0xb4, 0x52, 0x33, 0x8d, 0x95, 0xaf, 0xf1, 0xbd, 0x6e, 0x91, 0xde, 0xac, + 0xf6, 0xba, 0x0a, 0x5c, 0x9b, 0x67, 0x20, 0x21, 0xd1, 0x33, 0xf7, 0x0f, 0xf4, 0xb1, 0x2a, 0x6b, + 0x5b, 0x30, 0x31, 0x01, 0x1d, 0xb3, 0x10, 0xec, 0xef, 0x05, 0x24, 0x72, 0xd6, 0xb5, 0x14, 0x48, + 0xef, 0xc7, 0x93, 0xf8, 0xf4, 0x76, 0x9a, 0x24, 0x01, 0xe3, 0x26, 0xca, 0x30, 0xa0, 0xc5, 0x1c, + 0x7e, 0xc2, 0x19, 0x7a, 0x87, 0xf9, 0x1d, 0xd3, 0xa4, 0xae, 0x81, 0xb3, 0x06, 0x2f, 0xbd, 0xc3, + 0xd5, 0xb6, 0xd7, 0xa7, 0x82, 0x8d, 0xab, 0x0e, 0x34, 0x9e, 0xe2, 0x37, 0x2b, 0x0b, 0x49, 0x94, + 0x1f, 0x25, 0x33, 0x27, 0xdf, 0x15, 0x3e, 0x2c, 0x90, 0x60, 0x19, 0x28, 0xcc, 0xd1, 0x0f, 0xc8, + 0x67, 0x5e, 0x5c, 0x63, 0x42, 0x14, 0x7c, 0xfb, 0x22, 0x21, 0x43, 0x7f, 0x31, 0x3a, 0xa5, 0xe4, + 0x87, 0x75, 0xfe, 0x08, 0x45, 0xa7, 0x32, 0xd9, 0x5f, 0x54, 0x93, 0x64, 0xce, 0xaf, 0xca, 0x4a, + 0x1e, 0xd9, 0xde, 0x5a, 0x64, 0x9f, 0x77, 0x93, 0x49, 0x54, 0x7a, 0xa9, 0x96, 0xc0, 0x0e, 0xf4, + 0x0c, 0xc2, 0x43, 0x33, 0x42, 0x92, 0x3f, 0x11, 0x96, 0x8b, 0x50, 0x11, 0xa6, 0x9c, 0xe7, 0x38, + 0x40, 0xaa, 0x19, 0x56, 0x6e, 0x6e, 0x6a, 0xe6, 0x9f, 0xa4, 0xbe, 0x10, 0xc5, 0xf8, 0x72, 0xe0, + 0xaf, 0xec, 0x51, 0xa0, 0xd9, 0x28, 0x08, 0xe9, 0x16, 0x1c, 0x50, 0x97, 0xe7, 0x18, 0x38, 0xd0, + 0x05, 0x35, 0x49, 0x72, 0xfa, 0xe4, 0x7b, 0x6e, 0x52, 0x92, 0x41, 0x1d, 0xcd, 0x08, 0x79, 0xd7, + 0x75, 0xd8, 0x9e, 0x02, 0x70, 0xaf, 0x09, 0x6c, 0xac, 0x1c, 0x33, 0xa1, 0x7e, 0x56, 0xcd, 0xad, + 0x4e, 0x4d, 0xc8, 0xae, 0xa4, 0xac, 0xbf, 0x29, 0x52, 0xa0, 0x1e, 0x29, 0x76, 0x08, 0xc1, 0x2d, + 0x7f, 0xcf, 0x2a, 0x63, 0xde, 0xd0, 0x38, 0xa0, 0xf8, 0xf5, 0xc0, 0x0e, 0x1b, 0xce, 0x32, 0xe4, + 0x67, 0xa6, 0x9d, 0xf1, 0xb5, 0x02, 0x91, 0xb0, 0x4c, 0xbf, 0xf9, 0x38, 0x33, 0x47, 0xf8, 0x82, + 0x8f, 0x17, 0xc0, 0xd8, 0xa6, 0xe4, 0x0c, 0x85, 0xa7, 0xc2, 0x81, 0xf3, 0x99, 0x6e, 0x8c, 0x4b, + 0x40, 0x9e, 0x7c, 0x31, 0x13, 0x03, 0x36, 0x33, 0x0c, 0x95, 0xcd, 0xe3, 0x35, 0x4c, 0x73, 0x83, + 0x3d, 0x80, 0xaa, 0xa7, 0xbb, 0x15, 0x1b, 0x7e, 0xbd, 0x23, 0x31, 0xe7, 0x50, 0x51, 0xe0, 0x51, + 0xaf, 0xf1, 0x74, 0x2d, 0x4f, 0xa7, 0x6b, 0x81, 0x5a, 0x07, 0xd6, 0x0f, 0xb4, 0xdf, 0x95, 0x5d, + 0xf8, 0x7c, 0x47, 0xea, 0x0c, 0x90, 0x3d, 0x73, 0x2d, 0x05, 0x07, 0x50, 0xc9, 0x92, 0x6c, 0xdf, + 0xd3, 0xbc, 0xcc, 0xb0, 0x60, 0xfe, 0xf4, 0x6b, 0xc9, 0x9c, 0x1d, 0x99, 0x1f, 0x45, 0x66, 0xe9, + 0x66, 0xb3, 0xd8, 0x3f, 0x87, 0x32, 0x09, 0x0d, 0x8e, 0xe4, 0xb6, 0x68, 0xd8, 0x5c, 0x13, 0x58, + 0x16, 0x27, 0xa3, 0x9a, 0x51, 0x3a, 0x8a, 0xac, 0x03, 0x7e, 0x65, 0x32, 0x0e, 0xff, 0xb6, 0x2b, + 0x8f, 0xe1, 0x65, 0x03, 0x1d, 0x84, 0x31, 0x7b, 0x08, 0x29, 0x55, 0xa7, 0x1f, 0x1b, 0x95, 0x1d, + 0x5e, 0x68, 0x8f, 0x6f, 0xc7, 0x52, 0x55, 0x09, 0x8a, 0x8e, 0xff, 0xd3, 0x5b, 0x41, 0x60, 0xb8, + 0x3a, 0x05, 0x5b, 0xb9, 0xe0, 0xbe, 0x0f, 0xd8, 0xf7, 0x01, 0xb5, 0xeb, 0xc9, 0xed, 0x8e, 0xe4, + 0x85, 0x69, 0x18, 0xdd, 0xa1, 0x27, 0xf0, 0x9a, 0x13, 0x51, 0xe7, 0x22, 0xdf, 0x04, 0xcd, 0xc3, + 0xd9, 0xa8, 0x73, 0xdb, 0xe8, 0xb7, 0x39, 0x66, 0x9b, 0x36, 0x15, 0xad, 0x14, 0xad, 0x9d, 0xf0, + 0x64, 0x69, 0xa3, 0x6a, 0xbb, 0x59, 0xfb, 0xce, 0x00, 0xac, 0x23, 0xb4, 0x7f, 0x3a, 0xa2, 0xf9, + 0x55, 0x4b, 0x7b, 0x0f, 0x9d, 0x5a, 0x2b, 0xc7, 0x5e, 0xb7, 0xfb, 0x21, 0x10, 0xf4, 0x0d, 0x2e, + 0x62, 0xca, 0x7b, 0x30, 0x0f, 0xdf, 0xa7, 0xf3, 0xd2, 0xf4, 0x6c, 0xd8, 0x14, 0x76, 0x02, 0x3b, + 0x43, 0x59, 0xd7, 0xa9, 0x19, 0x81, 0x1d, 0x65, 0xe8, 0xc3, 0x9b, 0x69, 0xf2, 0xd4, 0x73, 0xf3, + 0xf8, 0x84, 0xaa, 0xf9, 0x1e, 0xa9, 0x1e, 0xcd, 0x84, 0xc4, 0x45, 0xa6, 0x34, 0xf2, 0x8a, 0x93, + 0x3b, 0xb6, 0x2b, 0xc8, 0x49, 0x48, 0x1c, 0xd9, 0x70, 0x8e, 0xf2, 0x07, 0x2b, 0xf5, 0x22, 0x63, + 0x3f, 0x0c, 0x2b, 0xb7, 0xd6, 0x8a, 0x6f, 0x64, 0x41, 0x33, 0x7a, 0xd7, 0x02, 0x13, 0x50, 0xec, + 0x36, 0xa9, 0x6a, 0x31, 0x26, 0xe3, 0x00, 0xa7, 0x67, 0xbb, 0xac, 0x22, 0xee, 0xbc, 0x33, 0xb0, + 0x4f, 0xdf, 0x2b, 0x36, 0xdf, 0x8f, 0x1a, 0x6a, 0xc5, 0x21, 0x78, 0xd0, 0x8c, 0x5c, 0x71, 0xe5, + 0xde, 0xa3, 0x85, 0x39, 0x5b, 0x62, 0x3f, 0xea, 0xae, 0x03, 0x14, 0x67, 0x4e, 0xc7, 0x9b, 0x4a, + 0x5d, 0x26, 0xca, 0x1f, 0xdf, 0xa0, 0x8f, 0x18, 0x2b, 0xf4, 0x2d, 0x4a, 0xd3, 0x9c, 0x07, 0x7c, + 0xb7, 0xa6, 0x1e, 0xcb, 0xb6, 0x48, 0x02, 0x79, 0x6a, 0xf3, 0x67, 0xf4, 0xe2, 0xe7, 0x5f, 0x0e, + 0x3a, 0x27, 0xb5, 0xff, 0xc4, 0xef, 0x5b, 0xf6, 0x02, 0x64, 0x73, 0x94, 0x8c, 0x50, 0x29, 0x86, + 0xcc, 0x02, 0x6e, 0xc4, 0x70, 0xa8, 0x36, 0xc9, 0x3f, 0x32, 0xc3, 0x1d, 0x21, 0x54, 0x64, 0x9d, + 0xdc, 0x71, 0x30, 0xd3, 0x97, 0x4c, 0x4c, 0xd2, 0xfa, 0xb9, 0x80, 0x11, 0x12, 0x47, 0xa3, 0x5d, + 0x85, 0x61, 0xbe, 0x6c, 0x8c, 0xdc, 0x12, 0x59, 0x1d, 0xbb, 0x81, 0xe6, 0x5e, 0x99, 0xf9, 0x78, + 0xce, 0xe1, 0x8b, 0x4f, 0x6a, 0x01, 0xce, 0xb4, 0xc1, 0xb0, 0xf8, 0x50, 0x4c, 0x4d, 0x48, 0x1e, + 0xea, 0x94, 0x6f, 0xab, 0x26, 0xf8, 0x0c, 0x74, 0xd2, 0xd3, 0x75, 0x6a, 0x83, 0x96, 0xfd, 0xb4, + 0x5e, 0xfb, 0x06, 0x63, 0xf7, 0x1c, 0xa9, 0x15, 0xc9, 0x72, 0xc2, 0xf7, 0x36, 0x03, 0x66, 0xca, + 0x66, 0x3b, 0x8e, 0x39, 0x59, 0x51, 0x27, 0x87, 0xe7, 0xbb, 0x98, 0xc2, 0xb0, 0xe6, 0x1c, 0xb9, + 0x05, 0xb6, 0xde, 0x55, 0xbb, 0xb8, 0xff, 0x42, 0x79, 0xf1, 0xa3, 0x09, 0xa6, 0xe2, 0xc9, 0xa5, + 0x58, 0x42, 0x9a, 0xdb, 0x08, 0xd3, 0x29, 0x17, 0xc2, 0x91, 0x10, 0xdf, 0x3a, 0xb3, 0x41, 0x3a, + 0x27, 0x73, 0xf7, 0xc7, 0xd9, 0xa4, 0x58, 0xef, 0xd2, 0xcd, 0x2e, 0xe1, 0x42, 0xd4, 0x05, 0x7e, + 0x96, 0x8b, 0x26, 0x99, 0x7c, 0xfc, 0x34, 0x33, 0x18, 0x3b, 0x29, 0x71, 0x3f, 0x39, 0x7a, 0x4c, + 0xf0, 0x01, 0x20, 0xe0, 0x44, 0x5a, 0x88, 0xb6, 0xcc, 0xb6, 0xcd, 0x96, 0x8a, 0x1f, 0x9e, 0xcb, + 0x3c, 0x7f, 0x7e, 0x1a, 0x2c, 0xbf, 0x2a, 0xda, 0xd1, 0x91, 0x53, 0x20, 0x00, 0x10, 0xb4, 0x83, + 0x78, 0x8f, 0xeb, 0xc1, 0x0f, 0xe2, 0x10, 0x14, 0x5d, 0x27, 0x3a, 0x3d, 0x5e, 0x3e, 0x3d, 0xe5, + 0x7c, 0x84, 0xaa, 0x7c, 0x6a, 0xa8, 0x3d, 0x86, 0x0a, 0x79, 0xcc, 0xa1, 0x09, 0x2e, 0x96, 0x41, + 0x41, 0xc5, 0xce, 0x3e, 0x9d, 0x93, 0x20, 0xb0, 0x7a, 0x53, 0xfd, 0x10, 0xba, 0x2f, 0xe4, 0x0f, + 0xfd, 0xbf, 0x55, 0x23, 0x2b, 0x3a, 0x2d, 0xaa, 0x7e, 0xf1, 0xbc, 0x6d, 0x93, 0x57, 0xc7, 0x1b, + 0xd4, 0x28, 0x03, 0x8f, 0xae, 0x3c, 0x90, 0xb2, 0xb1, 0xff, 0x2c, 0x40, 0xa2, 0xd4, 0x0a, 0x55, + 0xde, 0xeb, 0xf7, 0x85, 0xad, 0x6e, 0x13, 0x6e, 0x55, 0x53, 0x06, 0xf1, 0x37, 0x2e, 0x50, 0x78, + 0xe0, 0x6f, 0x27, 0xc1, 0xbe, 0xc5, 0x81, 0xb3, 0x52, 0xd5, 0xc0, 0xe9, 0x98, 0xf5, 0x74, 0x5b, + 0x17, 0xdd, 0x84, 0xbc, 0xed, 0x06, 0x2c, 0xa3, 0xa4, 0x48, 0xc9, 0xf1, 0xa1, 0x9d, 0xf2, 0x48, + 0x23, 0x59, 0x09, 0xd5, 0x88, 0xf1, 0x79, 0xa2, 0x03, 0xe6, 0x8d, 0xe6, 0x3a, 0xb9, 0xd3, 0xeb, + 0xcb, 0xa6, 0x13, 0xd0, 0xef, 0xe3, 0x11, 0x71, 0x0e, 0x1b, 0xf3, 0xd3, 0xa9, 0xc3, 0xfb, 0xc6, + 0xbd, 0xf8, 0xd8, 0x99, 0x41, 0x81, 0x6f, 0xe8, 0x09, 0x7d, 0x0a, 0xcd, 0x91, 0xc0, 0xa2, 0x38, + 0x42, 0x5c, 0x53, 0x19, 0x02, 0x5e, 0x21, 0xab, 0xa1, 0xf1, 0xe8, 0x0d, 0xf0, 0x6d, 0x65, 0xab, + 0x4d, 0x39, 0xa4, 0x05, 0xda, 0x30, 0xc4, 0x4c, 0x94, 0x3a, 0xd8, 0x49, 0x00, 0x39, 0x85, 0xe4, + 0x91, 0x55, 0xf9, 0x40, 0x08, 0x22, 0x04, 0x1a, 0xa5, 0xe2, 0x48, 0x3d, 0x10, 0x76, 0xb4, 0x25, + 0x7f, 0x12, 0xb2, 0xfb, 0xda, 0xa5, 0xa9, 0x18, 0x28, 0x91, 0x1d, 0x86, 0x0f, 0xda, 0x10, 0x53, + 0xa9, 0x99, 0xc1, 0xc8, 0x02, 0x41, 0x3a, 0x42, 0xdc, 0x55, 0x21, 0xca, 0x6e, 0x8a, 0x75, 0x5b, + 0xe1, 0x26, 0xdf, 0x16, 0x48, 0x14, 0xc7, 0x01, 0xad, 0x2f, 0x75, 0x49, 0x64, 0x44, 0xff, 0x5a, + 0xc6, 0x70, 0x89, 0x10, 0x79, 0xac, 0x0e, 0x2f, 0xaf, 0x6d, 0x57, 0xf5, 0x59, 0x6c, 0x79, 0x1b, + 0x9d, 0x4c, 0x39, 0xb3, 0xa5, 0xbf, 0xb6, 0xe0, 0x78, 0x76, 0x81, 0x4f, 0xde, 0xea, 0xa0, 0xdd, + 0x63, 0x25, 0x7c, 0x4f, 0x1d, 0x53, 0x2d, 0x2d, 0x4d, 0x61, 0x72, 0x86, 0x07, 0x6e, 0xd3, 0x23, + 0xe3, 0x79, 0xc4, 0x27, 0xc5, 0xfe, 0x5d, 0x05, 0xb1, 0xe3, 0x45, 0x1b, 0x6c, 0xd7, 0x1e, 0x8f, + 0x62, 0xc2, 0x85, 0x0d, 0x2c, 0xbe, 0x25, 0xc5, 0x38, 0xe9, 0xa2, 0x80, 0x34, 0x4f, 0x4e, 0x30, + 0xff, 0xaf, 0x16, 0x4c, 0x8b, 0xd0, 0xb1, 0x0e, 0x3f, 0x4e, 0xf9, 0x0d, 0x4e, 0x1d, 0x95, 0x49, + 0x66, 0xcf, 0xa0, 0x8f, 0xa3, 0xf6, 0x35, 0xfa, 0x88, 0xa1, 0xf9, 0xfc, 0x34, 0x71, 0xd6, 0xfe, + 0xbc, 0x21, 0x6f, 0xbe, 0xc4, 0xca, 0xd7, 0x85, 0xa3, 0x65, 0x10, 0x5c, 0x46, 0xc9, 0xbd, 0xce, + 0xbf, 0xcc, 0x4c, 0x3c, 0x7e, 0x2a, 0x28, 0x09, 0x6a, 0x73, 0x16, 0x35, 0xf7, 0xe3, 0x4e, 0x8a, + 0xbb, 0x7a, 0x54, 0x2c, 0xe1, 0x18, 0x1c, 0x90, 0x14, 0xe7, 0x5a, 0xe8, 0xd9, 0xc9, 0x29, 0x20, + 0x12, 0x5e, 0x0a, 0xcf, 0xdc, 0xcd, 0x16, 0x86, 0xde, 0x72, 0x0e, 0x41, 0x52, 0x91, 0x74, 0x4c, + 0x68, 0x50, 0xc1, 0x91, 0xcc, 0x92, 0xca, 0x42, 0x8a, 0x6a, 0x1a, 0xfd, 0x37, 0x70, 0x61, 0xab, + 0x18, 0x21, 0x07, 0x0e, 0xc5, 0x62, 0x02, 0xc8, 0xf8, 0xe5, 0xa3, 0x94, 0x38, 0xff, 0x40, 0xbf, + 0xee, 0x77, 0xa1, 0x5f, 0x19, 0x91, 0x26, 0x72, 0xc0, 0x32, 0x1b, 0x8a, 0xab, 0xc3, 0x2a, 0x00, + 0x50, 0xee, 0xd9, 0xc9, 0xa4, 0x07, 0x04, 0x7c, 0xa1, 0xd7, 0xbb, 0xba, 0x46, 0x64, 0xbc, 0x07, + 0x00, 0x30, 0x02, 0x1d, 0xe4, 0x64, 0xc9, 0x0d, 0x2a, 0xfc, 0x3a, 0xdb, 0xeb, 0x73, 0x54, 0x2a, + 0x97, 0x48, 0xa3, 0x06, 0xe7, 0x36, 0x1c, 0xae, 0xbb, 0xe2, 0x3a, 0xa7, 0x4f, 0xa4, 0x39, 0x67, + 0xc3, 0xab, 0x1f, 0x13, 0x30, 0xa2, 0x5c, 0x49, 0x52, 0x04, 0xf5, 0x46, 0x74, 0x50, 0xae, 0xa8, + 0xd3, 0xae, 0x33, 0x84, 0x9f, 0x8c, 0x27, 0xfc, 0x42, 0xa4, 0x44, 0x4f, 0x2d, 0xa2, 0xb9, 0x84, + 0x43, 0x46, 0x87, 0x6b, 0x4e, 0xb3, 0xa4, 0x47, 0x5c, 0xd1, 0xc2, 0xac, 0x0f, 0x34, 0x99, 0x00, + 0xfc, 0xc9, 0xab, 0x85, 0x0e, 0x49, 0x9f, 0xf4, 0x95, 0x7f, 0xc3, 0x8f, 0x35, 0xd0, 0x3c, 0xbe, + 0x7c, 0xbc, 0x2d, 0xe4, 0xd7, 0x03, 0x62, 0x86, 0xd8, 0x4d, 0x3d, 0x65, 0xc0, 0xa3, 0x7d, 0xc1, + 0x83, 0x70, 0xd0, 0x3a, 0x1b, 0xd6, 0x32, 0x46, 0xf4, 0xb6, 0x95, 0x09, 0xf7, 0xca, 0x71, 0xa8, + 0x05, 0x7b, 0xbb, 0xcb, 0x8e, 0x8f, 0x11, 0x79, 0x1a, 0xd1, 0xdd, 0x41, 0x3f, 0x95, 0x2b, 0xdf, + 0x31, 0x11, 0xa2, 0xe4, 0x56, 0x04, 0x11, 0x40, 0x68, 0x6b, 0xa7, 0x22, 0xa3, 0xb7, 0x7a, 0x95, + 0x2d, 0xa7, 0xd3, 0x61, 0x68, 0xb5, 0x26, 0x82, 0x8f, 0xb6, 0x21, 0xb3, 0xae, 0x12, 0x1c, 0xa6, + 0x22, 0x2f, 0xd2, 0x5e, 0x28, 0x14, 0x01, 0x94, 0xb9, 0x56, 0x88, 0x9f, 0x56, 0xd0, 0xee, 0x02, + 0xd3, 0x58, 0x6c, 0x9d, 0xc0, 0x0a, 0xf8, 0x0b, 0xdf, 0xea, 0xf0, 0xf9, 0xe5, 0xbb, 0x64, 0x46, + 0x29, 0x67, 0xa8, 0xaa, 0xb0, 0xb4, 0x24, 0xb2, 0x85, 0x20, 0x14, 0x42, 0x73, 0xe0, 0x53, 0xed, + 0xa0, 0x0f, 0x23, 0x7f, 0xd0, 0x9e, 0x98, 0xd2, 0x69, 0x64, 0x9b, 0xb1, 0x9c, 0xcd, 0x06, 0x8f, + 0x64, 0x52, 0x45, 0x24, 0x13, 0x35, 0x34, 0xbf, 0x52, 0xff, 0x4a, 0x1f, 0x96, 0x6a, 0xc5, 0x38, + 0xb3, 0x50, 0xf6, 0xe3, 0xb0, 0x7b, 0x3f, 0x3e, 0x67, 0xa7, 0x5b, 0x4e, 0x91, 0x27, 0xb5, 0x46, + 0x71, 0x0c, 0x50, 0xb1, 0xfb, 0xb5, 0x90, 0x9a, 0x8d, 0xa5, 0x7b, 0x36, 0x11, 0x97, 0x56, 0xd8, + 0x31, 0x2c, 0x54, 0xe0, 0x12, 0x68, 0x1e, 0x86, 0x8c, 0x10, 0x36, 0xce, 0x12, 0x3b, 0xad, 0x8b, + 0xf1, 0x45, 0x97, 0xb8, 0x76, 0x19, 0x38, 0x99, 0x72, 0x87, 0x78, 0x1d, 0x6e, 0xe6, 0x75, 0x70, + 0x05, 0x3b, 0x1e, 0xfb, 0xe8, 0xba, 0x94, 0x67, 0x6e, 0x3e, 0x32, 0x86, 0xa3, 0x77, 0x07, 0xfc, + 0xa1, 0x05, 0x03, 0x97, 0x72, 0x7b, 0x9b, 0x8e, 0xd0, 0x63, 0x5a, 0xc4, 0x58, 0x1b, 0x5d, 0x95, + 0xe9, 0x49, 0x80, 0x7a, 0xfc, 0xcb, 0x08, 0xa4, 0x4d, 0xf6, 0x5d, 0x73, 0x77, 0xe1, 0x19, 0x1d, + 0xaf, 0x67, 0xa8, 0x6e, 0x37, 0xa9, 0x19, 0xe7, 0xa0, 0x17, 0x86, 0x62, 0x13, 0xde, 0x48, 0x81, + 0x72, 0x3b, 0xc2, 0xba, 0xdb, 0x4c, 0x9b, 0x0b, 0xab, 0x10, 0x2c, 0xf9, 0xc1, 0x0e, 0xc4, 0x2f, + 0x16, 0x35, 0x26, 0x91, 0xf2, 0xf8, 0x33, 0xc4, 0x01, 0x46, 0x3e, 0xb3, 0x21, 0x66, 0x62, 0xf7, + 0x5e, 0xae, 0x53, 0x7e, 0xdf, 0x62, 0xad, 0x96, 0x58, 0xc5, 0x52, 0x46, 0xb4, 0x13, 0x6a, 0x9f, + 0x69, 0x32, 0x55, 0xc8, 0xd4, 0xcd, 0x12, 0xa4, 0x6a, 0x7d, 0x31, 0x6a, 0x6e, 0x13, 0x56, 0xfc, + 0x8d, 0x2c, 0xe8, 0xf4, 0x54, 0x83, 0xaa, 0x2a, 0x00, 0xfd, 0xdd, 0xee, 0x95, 0x27, 0xbe, 0xcf, + 0x58, 0xb1, 0xa5, 0xdf, 0x1e, 0x2b, 0x18, 0x98, 0x3c, 0x6e, 0x1f, 0x5e, 0x93, 0xdf, 0x90, 0x2c, + 0x7d, 0xae, 0x89, 0xa7, 0x56, 0x59, 0x27, 0x5c, 0x15, 0x22, 0xf9, 0xf4, 0xdc, 0x71, 0x00, 0xfe, + 0x69, 0x9c, 0x34, 0x56, 0x07, 0x10, 0x1c, 0x47, 0x47, 0x6c, 0xa0, 0x43, 0x74, 0x68, 0x89, 0x8c, + 0x31, 0xd2, 0x69, 0x11, 0x94, 0x7f, 0x45, 0x01, 0x5a, 0x0e, 0x50, 0x75, 0xf6, 0x70, 0xa5, 0x5f, + 0xc1, 0x78, 0x45, 0xd8, 0x1d, 0x2b, 0xb6, 0xbc, 0x0f, 0xb8, 0xab, 0x13, 0x40, 0xf6, 0xb5, 0x43, + 0x82, 0x7d, 0xe5, 0x53, 0x63, 0x6a, 0xf7, 0xed, 0xf4, 0xf0, 0x56, 0x75, 0xdd, 0xc0, 0x8e, 0xa0, + 0x68, 0x66, 0xf1, 0xce, 0x08, 0x73, 0xbb, 0xd4, 0xff, 0x3e, 0x10, 0xbb, 0xca, 0x51, 0x48, 0x44, + 0xe7, 0x76, 0x37, 0x98, 0x0e, 0x80, 0xa5, 0x00, 0x46, 0xb3, 0x22, 0x02, 0x62, 0xe7, 0xef, 0x24, + 0x3a, 0xeb, 0x9c, 0x53, 0x30, 0x4f, 0x39, 0x38, 0x0b, 0xc0, 0x4c, 0x7b, 0xbf, 0xbf, 0xb4, 0xc8, + 0xf6, 0x5e, 0x69, 0x26, 0xfb, 0xdb, 0x0d, 0x80, 0x94, 0xd3, 0x4e, 0xa0, 0x51, 0x5b, 0xb2, 0x8d, + 0x5c, 0x31, 0xc9, 0x0f, 0x8c, 0xf5, 0xa9, 0x7f, 0x1b, 0xe8, 0x78, 0x51, 0x41, 0xdb, 0xf6, 0x40, + 0x62, 0x5d, 0x9b, 0x49, 0xbe, 0x09, 0x03, 0xc4, 0x43, 0xcc, 0xb1, 0xc5, 0xf8, 0x14, 0x9f, 0x05, + 0xa0, 0x4c, 0x93, 0x49, 0x3c, 0x7a, 0x05, 0xee, 0x35, 0x91, 0x38, 0xc7, 0xb0, 0x8a, 0xea, 0x1b, + 0x01, 0xcc, 0xc7, 0xb5, 0x0e, 0x02, 0xa8, 0xe2, 0xa3, 0x01, 0x81, 0x6c, 0x0a, 0x6a, 0xc3, 0x0d, + 0x0d, 0x4d, 0x58, 0x41, 0xcb, 0xfc, 0x36, 0x1e, 0x15, 0xf4, 0x89, 0xca, 0x1c, 0xbc, 0xd4, 0xd8, + 0x70, 0x36, 0x1d, 0x6d, 0x30, 0x7b, 0x28, 0x8d, 0x94, 0x4d, 0x8e, 0x02, 0xf3, 0x06, 0x44, 0x39, + 0xf4, 0xfe, 0xde, 0x2a, 0x45, 0xf2, 0xb5, 0xcb, 0x44, 0xe2, 0xd7, 0x41, 0x4f, 0xfb, 0x0a, 0x86, + 0xbf, 0x47, 0x21, 0x70, 0x17, 0x4d, 0x33, 0x5e, 0xd7, 0x00, 0x13, 0x47, 0xa3, 0x56, 0x90, 0x04, + 0x43, 0x5c, 0xf8, 0x61, 0x2b, 0xf8, 0x83, 0xe5, 0x5b, 0x48, 0x82, 0x0c, 0xbb, 0x92, 0xf5, 0xdc, + 0x03, 0xd3, 0x9b, 0xc6, 0x12, 0xb7, 0x34, 0x65, 0x28, 0xac, 0x45, 0x11, 0x61, 0x73, 0x58, 0x87, + 0xb2, 0xc7, 0x2c, 0xd8, 0x79, 0x28, 0xa5, 0x1f, 0xd3, 0x0b, 0xb6, 0x7a, 0x30, 0xa1, 0x9c, 0x25, + 0x23, 0x7b, 0x74, 0x17, 0xc4, 0xc6, 0x7c, 0xa9, 0x66, 0xeb, 0xe1, 0x2d, 0x74, 0x82, 0xc7, 0xe8, + 0xb3, 0xa6, 0xcd, 0x92, 0x15, 0x87, 0x0c, 0x2a, 0x0b, 0x04, 0x64, 0xf9, 0x3f, 0x81, 0x95, 0x5c, + 0xb2, 0x1c, 0x6d, 0xf7, 0xa4, 0x0b, 0xb9, 0xcd, 0xfe, 0x05, 0x9c, 0x4a, 0x66, 0xc3, 0xef, 0x0e, + 0x6b, 0xb9, 0xb2, 0x56, 0x1b, 0x82, 0x2f, 0xc1, 0x46, 0xbe, 0x31, 0xcb, 0x50, 0xdf, 0xa6, 0xe5, + 0xa8, 0x97, 0x2e, 0x13, 0xe2, 0xe3, 0x1d, 0x84, 0xa7, 0x4b, 0x45, 0x35, 0xb9, 0x6c, 0xa8, 0x1f, + 0x56, 0x3f, 0x30, 0xa8, 0x6c, 0x32, 0xb8, 0xae, 0xd0, 0x95, 0xd0, 0x5b, 0x8d, 0xec, 0x37, 0xb7, + 0xa7, 0x9f, 0xe6, 0x4f, 0xdc, 0xd1, 0x4a, 0xf9, 0xf0, 0x04, 0x6e, 0x93, 0x57, 0xbb, 0xbe, 0xf9, + 0xd2, 0x37, 0x2e, 0x14, 0x14, 0x54, 0xbe, 0xad, 0x9f, 0xad, 0xdd, 0x1c, 0x8e, 0x07, 0x6f, 0xb7, + 0x28, 0xc7, 0xe7, 0x5a, 0x5d, 0x70, 0x52, 0x96, 0x14, 0x5f, 0x44, 0xcc, 0xa0, 0xac, 0x0b, 0x2c, + 0xac, 0xe6, 0xe8, 0xba, 0x7a, 0x50, 0x29, 0x86, 0x88, 0xe7, 0x0d, 0x5c, 0xef, 0xa4, 0x87, 0x1b, + 0x71, 0xfd, 0xe9, 0x68, 0xb1, 0xae, 0xf6, 0xcd, 0xd7, 0xdf, 0x2a, 0xbf, 0x46, 0x45, 0xf0, 0x45, + 0xae, 0x1a, 0xef, 0x89, 0x31, 0x17, 0x1d, 0x37, 0xba, 0xed, 0x0a, 0x0c, 0xf5, 0x9f, 0x40, 0x4f, + 0x33, 0x80, 0x3a, 0xb4, 0x88, 0xa4, 0x30, 0x25, 0xe8, 0x4f, 0x03, 0xb4, 0x37, 0x12, 0x9d, 0x52, + 0x3e, 0xd5, 0xb8, 0x24, 0xdc, 0xd1, 0x35, 0xe6, 0xda, 0xa1, 0xd2, 0x02, 0x04, 0x58, 0x07, 0xdd, + 0xd0, 0x6a, 0x7b, 0xd6, 0x47, 0x0c, 0xaa, 0xcc, 0xe9, 0xf6, 0x11, 0xd3, 0xbd, 0xf7, 0x09, 0xab, + 0xd2, 0xf3, 0xd1, 0xda, 0x9c, 0xf0, 0x2f, 0x20, 0x14, 0x14, 0x78, 0xf5, 0x31, 0x7b, 0x19, 0x64, + 0x13, 0x1e, 0xbb, 0x18, 0x60, 0x1d, 0xcd, 0xa2, 0x52, 0x2e, 0x64, 0x79, 0xd2, 0xca, 0x81, 0xe5, + 0x6d, 0x4c, 0xe5, 0x52, 0xb5, 0x96, 0x0f, 0xc8, 0x80, 0x1a, 0x27, 0x69, 0x22, 0xef, 0x67, 0xde, + 0x7b, 0xf9, 0xaf, 0xfe, 0x34, 0x88, 0x1e, 0x2a, 0xb8, 0xbe, 0x10, 0xb7, 0x6e, 0xec, 0x73, 0x80, + 0x9d, 0xca, 0x48, 0xbd, 0xd3, 0xf7, 0x3d, 0xbb, 0xa8, 0x7c, 0x73, 0xbb, 0x1f, 0x2d, 0x1b, 0xd9, + 0x85, 0xf6, 0x16, 0x7e, 0xdd, 0x48, 0x87, 0x23, 0x95, 0xe3, 0x79, 0x07, 0xb9, 0xd9, 0x9f, 0xca, + 0x59, 0x2b, 0x7b, 0x82, 0x3e, 0x45, 0x00, 0x1f, 0xff, 0x01, 0x98, 0x56, 0x06, 0x0b, 0xc4, 0xe9, + 0x65, 0xf7, 0xac, 0x2a, 0x5d, 0x48, 0x9e, 0x6b, 0x02, 0x6a, 0x2d, 0xdf, 0x50, 0x87, 0x4b, 0x21, + 0x16, 0x74, 0x24, 0x99, 0xac, 0x2e, 0x11, 0x00, 0x44, 0xbb, 0x2e, 0x45, 0x65, 0xf7, 0x11, 0xd5, + 0xdb, 0xfc, 0x66, 0xed, 0xd9, 0x14, 0x54, 0x52, 0xc7, 0x44, 0xbb, 0x9b, 0x9b, 0x5d, 0x60, 0x69, + 0xbc, 0x43, 0xc3, 0x59, 0xdc, 0x99, 0xf5, 0x18, 0xdd, 0x92, 0x03, 0x24, 0xa8, 0xda, 0x5b, 0x91, + 0xc0, 0xf5, 0x51, 0x24, 0x8a, 0x75, 0x1b, 0x50, 0x86, 0x2d, 0x3a, 0xf7, 0x37, 0x36, 0x13, 0x1c, + 0x8c, 0x29, 0xae, 0xa1, 0x38, 0x5a, 0x89, 0x01, 0x01, 0x04, 0x57, 0x45, 0x54, 0x48, 0x01, 0x51, + 0x23, 0x84, 0x58, 0xb0, 0xd0, 0xdd, 0x6d, 0x49, 0x3e, 0xc9, 0x64, 0xa7, 0x46, 0x21, 0x17, 0x23, + 0x7e, 0xa2, 0x14, 0xab, 0x8b, 0xb5, 0x4b, 0x5a, 0x7d, 0x9e, 0x00, 0x5f, 0x56, 0x06, 0x86, 0x5f, + 0x5c, 0x7c, 0x04, 0xad, 0xb7, 0x14, 0x97, 0x25, 0xe0, 0x2a, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc9, 0xcd, 0x43, 0x2e, 0xde, 0xa8, 0x73, 0x19, 0xb8, 0xbd, 0xf5, 0xb4, 0x00, 0xd1, + 0x7c, 0xb0, 0xd4, 0x74, 0x3f, 0x21, 0x74, 0xc1, 0x50, 0x37, 0xc7, 0xfd, 0x9e, 0x5c, 0xdc, 0xe9, + 0x45, 0x86, 0x4c, 0x29, 0xe3, 0x15, 0x3f, 0x0c, 0x0f, 0x8d, 0xf0, 0x15, 0xdd, 0xa9, 0x02, 0x16, + 0x6c, 0xda, 0x01, 0x5a, 0xf9, 0x06, 0x33, 0x78, 0xfa, 0xdc, 0xc3, 0xcc, 0x19, 0xad, 0x25, 0xff, + 0x82, 0x25, 0x47, 0xea, 0x17, 0x04, 0x55, 0x5d, 0x56, 0x53, 0x69, 0x74, 0xd6, 0x2e, 0x91, 0xfc, + 0x3d, 0x6d, 0xcb, 0x39, 0x76, 0xf1, 0x08, 0x26, 0xba, 0xd9, 0x72, 0x21, 0xf4, 0x2d, 0x60, 0x2c, + 0x4f, 0x8e, 0x00, 0x3c, 0x99, 0x76, 0x4d, 0x0d, 0xda, 0x13, 0x9b, 0x31, 0x65, 0xda, 0x5d, 0xc4, + 0xbf, 0x97, 0x00, 0xc6, 0xa5, 0x63, 0xfc, 0xd0, 0x54, 0x3f, 0x54, 0x9e, 0x7b, 0x19, 0xd4, 0xcc, + 0x4c, 0xaf, 0x77, 0x33, 0xbb, 0x23, 0xe1, 0x95, 0x16, 0x4d, 0xde, 0xb6, 0xbf, 0xd4, 0x57, 0x8a, + 0x5d, 0x48, 0x12, 0x41, 0x31, 0xd3, 0x18, 0xc0, 0xdc, 0x23, 0xe2, 0xe6, 0xd5, 0x99, 0x50, 0xbe, + 0xa6, 0xe5, 0x9f, 0xe4, 0x90, 0xba, 0x1e, 0x9e, 0x26, 0xbd, 0x63, 0xcc, 0xb6, 0x4b, 0x36, 0x4d, + 0x91, 0x8c, 0x15, 0x65, 0x4b, 0x72, 0xa6, 0xda, 0xb9, 0x56, 0x7e, 0xf2, 0x57, 0xf2, 0x50, 0x2f, + 0xc2, 0xca, 0x84, +]]; From c3a8583903235196df21f3c03ff17ed1d20265cb Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 11 Nov 2024 21:59:31 +0100 Subject: [PATCH 067/157] Add a method to return the inner value (IssueBundle) of IssueData wrapper --- zebra-chain/src/orchard_zsa/issuance.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index d45f10253cd..4a3cb968926 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -27,6 +27,13 @@ use super::burn::ASSET_BASE_SIZE; #[derive(Clone, Debug, PartialEq, Eq)] pub struct IssueData(IssueBundle); +impl IssueData { + /// Returns a reference to the inner `IssueBundle`. + pub fn inner(&self) -> &IssueBundle { + &self.0 + } +} + impl From> for IssueData { fn from(inner: IssueBundle) -> Self { Self(inner) From 4855c25724fd15d8809304a933000766c90835dc Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 11 Nov 2024 22:02:36 +0100 Subject: [PATCH 068/157] Add more checks after deserializing issuance block in issuance_block test --- zebra-chain/src/orchard_zsa/tests/issuance.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/zebra-chain/src/orchard_zsa/tests/issuance.rs b/zebra-chain/src/orchard_zsa/tests/issuance.rs index 902af757adf..9dc90d881c7 100644 --- a/zebra-chain/src/orchard_zsa/tests/issuance.rs +++ b/zebra-chain/src/orchard_zsa/tests/issuance.rs @@ -1,4 +1,4 @@ -use crate::{block::Block, serialization::ZcashDeserialize}; +use crate::{block::Block, serialization::ZcashDeserialize, transaction::Transaction}; use super::vectors::BLOCKS; @@ -6,4 +6,20 @@ use super::vectors::BLOCKS; fn issuance_block() { let issuance_block = Block::zcash_deserialize(BLOCKS[0].as_ref()).expect("issuance block should deserialize"); + + for transaction in issuance_block.transactions { + if let Transaction::V6 { + orchard_zsa_issue_data, + .. + } = transaction.as_ref() + { + let issue_bundle = orchard_zsa_issue_data + .as_ref() + .expect("V6 transaction in the issuance test block has orchard_zsa_issue_data") + .inner(); + + assert_eq!(issue_bundle.actions().len(), 1); + assert_eq!(issue_bundle.actions()[0].notes().len(), 1); + } + } } From 87e4a637fac115f3f6315f5f3ee3d6a1b05ebaf8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 17 Nov 2024 19:24:04 +0100 Subject: [PATCH 069/157] Rename orchard_zsa::tests::issuance_block to deserialize_blocks and add checks of deserialization of transfer and burn blocks --- zebra-chain/src/orchard_zsa/tests.rs | 2 +- .../tests/{issuance.rs => blocks.rs} | 8 +- .../src/orchard_zsa/tests/vectors/blocks.rs | 3554 +++++++++++++---- 3 files changed, 2858 insertions(+), 706 deletions(-) rename zebra-chain/src/orchard_zsa/tests/{issuance.rs => blocks.rs} (68%) diff --git a/zebra-chain/src/orchard_zsa/tests.rs b/zebra-chain/src/orchard_zsa/tests.rs index a9301a7461e..1c895a420d9 100644 --- a/zebra-chain/src/orchard_zsa/tests.rs +++ b/zebra-chain/src/orchard_zsa/tests.rs @@ -1,2 +1,2 @@ -mod issuance; +mod blocks; mod vectors; diff --git a/zebra-chain/src/orchard_zsa/tests/issuance.rs b/zebra-chain/src/orchard_zsa/tests/blocks.rs similarity index 68% rename from zebra-chain/src/orchard_zsa/tests/issuance.rs rename to zebra-chain/src/orchard_zsa/tests/blocks.rs index 9dc90d881c7..2828acb311c 100644 --- a/zebra-chain/src/orchard_zsa/tests/issuance.rs +++ b/zebra-chain/src/orchard_zsa/tests/blocks.rs @@ -3,9 +3,13 @@ use crate::{block::Block, serialization::ZcashDeserialize, transaction::Transact use super::vectors::BLOCKS; #[test] -fn issuance_block() { +fn deserialize_blocks() { let issuance_block = - Block::zcash_deserialize(BLOCKS[0].as_ref()).expect("issuance block should deserialize"); + Block::zcash_deserialize(BLOCKS[1].as_ref()).expect("issuance block should deserialize"); + let transfer_block = + Block::zcash_deserialize(BLOCKS[2].as_ref()).expect("transfer block should deserialize"); + let burn_block = + Block::zcash_deserialize(BLOCKS[3].as_ref()).expect("burn block should deserialize"); for transaction in issuance_block.transactions { if let Transaction::V6 { diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs index 222f1e3c201..db0eca9fb0b 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -1,703 +1,2851 @@ -pub(crate) const BLOCKS: [&[u8]; 1] = [&[ - 0x04, 0x00, 0x00, 0x00, 0x27, 0xe3, 0x01, 0x34, 0xd6, 0x20, 0xe9, 0xfe, 0x61, 0xf7, 0x19, 0x93, - 0xb2, 0xc2, 0x72, 0x75, 0x6a, 0xce, 0xec, 0xdc, 0xbf, 0xd3, 0xe5, 0x43, 0xf7, 0x30, 0xbc, 0x65, - 0x83, 0x20, 0xba, 0xb6, 0x3e, 0x7e, 0x72, 0xc9, 0x1b, 0x5e, 0x23, 0x02, 0x56, 0x76, 0xf9, 0x0e, - 0xd8, 0x11, 0x9f, 0x02, 0x77, 0x8a, 0xa0, 0x8d, 0x1a, 0x56, 0x79, 0x47, 0x66, 0x88, 0xbf, 0x6e, - 0x8e, 0x5a, 0x4f, 0x57, 0x00, 0x23, 0xde, 0x3e, 0xf1, 0x3a, 0x05, 0xe5, 0x9d, 0x2e, 0x94, 0x76, - 0x6a, 0x3c, 0x7a, 0x94, 0x88, 0x5d, 0x72, 0x57, 0x04, 0x56, 0x3c, 0x74, 0xd1, 0x7a, 0xbd, 0xf7, - 0x53, 0x53, 0xdb, 0x1a, 0xf2, 0xfa, 0x49, 0x4d, 0x3f, 0xa6, 0x0c, 0x20, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0xfd, 0x40, 0x05, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x04, 0x00, 0x00, 0x80, 0x85, 0x20, 0x2f, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x02, 0x51, 0x00, - 0xff, 0xff, 0xff, 0xff, 0x01, 0x40, 0xbe, 0x40, 0x25, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, - 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, - 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, - 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x64, 0x40, 0xa8, 0x86, 0x5d, 0x61, 0x39, 0xb3, 0x39, 0x62, 0x94, 0xee, 0x42, - 0xc5, 0xa6, 0x0b, 0x63, 0x57, 0xca, 0x65, 0x8b, 0xa6, 0x76, 0xf2, 0xd6, 0xda, 0x8e, 0x00, 0xcf, - 0x60, 0xe8, 0x33, 0xa4, 0x55, 0xec, 0x7c, 0x99, 0x0f, 0xda, 0xd2, 0x46, 0xc0, 0x5b, 0x4a, 0x8f, - 0xe5, 0x2c, 0x6a, 0xb7, 0x00, 0xca, 0x49, 0xb4, 0xda, 0x80, 0xd3, 0x3d, 0x4d, 0x83, 0x7a, 0xd1, - 0x3a, 0x21, 0x3f, 0xfe, 0x71, 0xf5, 0x04, 0xd3, 0xaf, 0xeb, 0x10, 0x9d, 0xc2, 0x0d, 0xbd, 0x3a, - 0x9b, 0x2d, 0xf7, 0x7c, 0xd3, 0x2c, 0x7e, 0x7b, 0xeb, 0xb7, 0xaf, 0x60, 0xe4, 0xd3, 0x41, 0x96, - 0xe7, 0x2c, 0x0a, 0xf8, 0x99, 0x89, 0xbd, 0x70, 0x79, 0x54, 0x3b, 0xc7, 0x66, 0x29, 0x91, 0x31, - 0x97, 0xa6, 0x53, 0xfe, 0x24, 0x70, 0xf9, 0xf2, 0x41, 0x81, 0xac, 0x79, 0x60, 0x43, 0x79, 0xed, - 0x42, 0xba, 0x25, 0xdd, 0xf0, 0x05, 0xe8, 0xff, 0x14, 0x9e, 0xe8, 0x34, 0x91, 0x5d, 0xc6, 0x9d, - 0x6a, 0x2f, 0xc5, 0x70, 0x55, 0x65, 0x01, 0xf3, 0x74, 0x6f, 0xe7, 0x37, 0x4a, 0x8f, 0x5d, 0x4d, - 0xb6, 0x4e, 0x3b, 0xab, 0xc5, 0xc9, 0xa2, 0x86, 0x28, 0x0e, 0xa6, 0x2d, 0xc0, 0xc4, 0x12, 0x74, - 0xe9, 0x39, 0x34, 0xa6, 0xd8, 0xbc, 0x24, 0xdf, 0x5a, 0x2b, 0x2d, 0xd3, 0xae, 0x62, 0x2f, 0x37, - 0x38, 0xcb, 0x41, 0x26, 0xa5, 0xae, 0xed, 0x94, 0x84, 0x51, 0xc2, 0xe7, 0xff, 0xbe, 0x27, 0x7b, - 0x37, 0x94, 0xc0, 0xb5, 0x17, 0x08, 0x0a, 0x00, 0xd4, 0x69, 0x74, 0x8f, 0x4e, 0x2c, 0xeb, 0x06, - 0x2f, 0x1d, 0x61, 0xdc, 0x70, 0xab, 0x97, 0xc9, 0xbd, 0x02, 0x68, 0xf0, 0xe1, 0x5e, 0xcb, 0x76, - 0x25, 0x2c, 0x2c, 0xd2, 0xf1, 0x8a, 0x03, 0xb3, 0x2f, 0x0b, 0x40, 0xa2, 0x56, 0xc4, 0x3a, 0xd0, - 0xf7, 0xc4, 0xef, 0x98, 0x52, 0x87, 0x54, 0x5b, 0x8e, 0xf8, 0xb3, 0x6e, 0x3d, 0x9e, 0xd6, 0x05, - 0xb9, 0x49, 0x54, 0x1b, 0xe0, 0xbc, 0xe7, 0x52, 0x71, 0x6c, 0x70, 0xdb, 0x0c, 0xf2, 0x06, 0x9e, - 0x80, 0x90, 0xde, 0x83, 0x0e, 0x8c, 0xee, 0xa3, 0x36, 0x99, 0xf0, 0xa8, 0x29, 0x58, 0x9e, 0xa8, - 0x4c, 0x90, 0x0d, 0x66, 0x06, 0xf9, 0x95, 0x21, 0x65, 0xa4, 0x90, 0x58, 0x9f, 0x61, 0x66, 0x25, - 0x8b, 0x7b, 0x13, 0xa1, 0x6b, 0x9c, 0xf4, 0x80, 0xfb, 0x34, 0xd1, 0x0f, 0x52, 0x2d, 0xbd, 0x2a, - 0xcd, 0x16, 0x7b, 0x7d, 0xd0, 0x6c, 0x4d, 0x2d, 0xbb, 0x51, 0x90, 0x7d, 0x4d, 0x38, 0xbe, 0x06, - 0x95, 0x18, 0xd4, 0x31, 0x6d, 0xa4, 0x67, 0xca, 0xe5, 0x35, 0x51, 0xaa, 0xb4, 0x33, 0x46, 0x67, - 0xc0, 0xa5, 0xb7, 0x07, 0x63, 0x64, 0xe8, 0x42, 0x8e, 0x81, 0xf4, 0xc4, 0xcb, 0xde, 0x44, 0xe8, - 0xf1, 0x80, 0xca, 0x7a, 0x70, 0x33, 0x64, 0xaa, 0x4d, 0x50, 0xaf, 0xf3, 0x24, 0x27, 0xc4, 0x23, - 0xfb, 0xf8, 0x47, 0x61, 0x83, 0x5c, 0x31, 0xeb, 0x69, 0x73, 0x64, 0x4c, 0xe3, 0x8e, 0x24, 0x40, - 0xd9, 0xe0, 0x46, 0x17, 0xbc, 0x0b, 0xa0, 0xcd, 0x8d, 0x14, 0x96, 0x57, 0x21, 0x71, 0x97, 0x9c, - 0xa7, 0x5b, 0x28, 0xb7, 0x5b, 0x71, 0xd2, 0x7b, 0x77, 0x83, 0x09, 0x3a, 0xc4, 0x9c, 0x37, 0x38, - 0xfb, 0xdf, 0xe1, 0xf9, 0xc7, 0x29, 0xe0, 0x50, 0xbb, 0xfd, 0x7b, 0xa1, 0x53, 0xe5, 0x3b, 0x85, - 0x61, 0x21, 0x66, 0xf0, 0xa2, 0xb7, 0x65, 0x77, 0xd4, 0x5f, 0x0f, 0xf8, 0x5f, 0x4c, 0x6a, 0x90, - 0x03, 0xc1, 0x2f, 0x8c, 0x95, 0xa4, 0x36, 0x88, 0x51, 0x43, 0xd9, 0xa8, 0x78, 0x7f, 0x36, 0xb2, - 0x27, 0x2f, 0x2c, 0xd0, 0x21, 0xdc, 0x6a, 0x3f, 0x34, 0xdf, 0xac, 0x94, 0xf2, 0x8f, 0x13, 0x2e, - 0x3d, 0x2a, 0x4a, 0xf0, 0xdc, 0xa4, 0x1c, 0xc8, 0x59, 0x7e, 0xa0, 0x88, 0x7c, 0x02, 0x06, 0xf1, - 0xbe, 0x5a, 0xae, 0xc4, 0xf7, 0x72, 0x46, 0x97, 0xd9, 0x4b, 0x47, 0x9f, 0x9b, 0x93, 0x93, 0x71, - 0x8d, 0x80, 0xf7, 0xaf, 0xc7, 0xf9, 0xc9, 0x84, 0xd5, 0x9e, 0x87, 0x0f, 0x64, 0x33, 0x1f, 0xd6, - 0xf5, 0x90, 0x2d, 0x3a, 0xc3, 0x59, 0xf5, 0x25, 0xe6, 0xa5, 0xda, 0xf4, 0x21, 0x24, 0x9d, 0xdb, - 0x69, 0x86, 0x93, 0xec, 0x7d, 0x9b, 0xfd, 0x71, 0x19, 0xab, 0x05, 0xb6, 0xfd, 0x5c, 0x6b, 0x17, - 0x7e, 0xe5, 0xc4, 0x10, 0x38, 0xd7, 0x9b, 0x84, 0x94, 0x0d, 0xf1, 0xf5, 0xe6, 0x79, 0x84, 0x3c, - 0x04, 0x84, 0x2c, 0x6a, 0x62, 0xcf, 0xd6, 0x2f, 0xd0, 0x1b, 0xcc, 0xc2, 0xc8, 0x2a, 0x67, 0x34, - 0x52, 0xae, 0x88, 0x48, 0x47, 0x5f, 0x61, 0x4d, 0xba, 0x6c, 0x53, 0xf1, 0x8b, 0x12, 0x54, 0xcc, - 0xf0, 0x77, 0x89, 0x72, 0x98, 0x97, 0xed, 0x2e, 0xfa, 0xef, 0x0b, 0x54, 0x69, 0x02, 0x69, 0x15, - 0xa6, 0x5f, 0x11, 0xed, 0x04, 0x58, 0x02, 0x46, 0xc4, 0xdc, 0x9c, 0xb6, 0xe1, 0xc8, 0xd8, 0xdc, - 0xa3, 0x99, 0xea, 0x17, 0x96, 0x74, 0x7b, 0x5f, 0xeb, 0x00, 0x02, 0x91, 0x04, 0x9e, 0xf4, 0xff, - 0x6d, 0x0b, 0x29, 0x82, 0x37, 0x1a, 0x4c, 0xa0, 0x71, 0x71, 0x20, 0xaf, 0xe4, 0x3b, 0x6e, 0x26, - 0xb1, 0x89, 0x56, 0xb3, 0xb6, 0x44, 0x2d, 0x2b, 0xb4, 0x6f, 0x22, 0xe4, 0x5d, 0xd8, 0x7d, 0x25, - 0x60, 0xe7, 0xf4, 0xab, 0x87, 0x0b, 0x97, 0x0a, 0xd4, 0x82, 0x48, 0x93, 0x0f, 0x1d, 0xcc, 0xc7, - 0x69, 0xee, 0xc7, 0xcf, 0x5d, 0x9b, 0xbe, 0x9f, 0x23, 0x4b, 0x06, 0x49, 0x88, 0xf5, 0xbd, 0xb5, - 0xc3, 0xed, 0x46, 0x2a, 0x17, 0xc8, 0x5c, 0x4e, 0xa4, 0x56, 0xf3, 0x62, 0x28, 0xe7, 0xd1, 0x66, - 0x15, 0x1c, 0xeb, 0x62, 0xc1, 0x64, 0xee, 0xb6, 0x98, 0x7a, 0x9e, 0x40, 0xaa, 0xa2, 0x7d, 0xca, - 0xb6, 0xf3, 0x82, 0x6d, 0x65, 0xfb, 0x82, 0x57, 0xd2, 0x64, 0xc8, 0xb8, 0x15, 0x1b, 0x68, 0x94, - 0x90, 0x7a, 0xd5, 0xd7, 0xe6, 0x42, 0x99, 0x6f, 0x46, 0xc8, 0x3d, 0x9e, 0x5d, 0x85, 0x00, 0x7b, - 0xed, 0x53, 0xde, 0x27, 0xa4, 0x66, 0x3f, 0xa3, 0xc2, 0xf8, 0x89, 0x69, 0x8a, 0xac, 0xcc, 0x15, - 0x5e, 0xdd, 0x63, 0xda, 0xe3, 0x5a, 0x1f, 0xe9, 0x81, 0x60, 0x20, 0x60, 0xc1, 0xf9, 0xbb, 0x71, - 0x87, 0x77, 0x79, 0xe0, 0x90, 0x3d, 0xef, 0x49, 0xa9, 0xf7, 0x66, 0x70, 0x6f, 0x80, 0x88, 0xbe, - 0x89, 0x73, 0x99, 0x3e, 0xb1, 0xf9, 0xd6, 0xe7, 0xb1, 0x9f, 0x3e, 0xfe, 0x39, 0xed, 0x36, 0x18, - 0xee, 0xc3, 0x41, 0xbb, 0x69, 0x9a, 0x8b, 0xb1, 0x13, 0x2d, 0xd5, 0xab, 0xb7, 0xb6, 0x3b, 0xed, - 0xdf, 0x5b, 0x08, 0xde, 0x7d, 0xe5, 0x5d, 0xfa, 0x32, 0x91, 0x78, 0x03, 0x87, 0x77, 0x85, 0xc2, - 0x92, 0x66, 0x51, 0x83, 0xdb, 0xa8, 0x3f, 0xce, 0x17, 0xaa, 0xf5, 0xbb, 0x1e, 0x5c, 0x5f, 0x2e, - 0xb6, 0x6c, 0x6d, 0x1a, 0x98, 0x84, 0xe4, 0x69, 0x44, 0x9a, 0xf5, 0x6e, 0xd8, 0xd4, 0xc9, 0xd3, - 0x42, 0x18, 0xca, 0x80, 0x1c, 0x71, 0x8c, 0x62, 0x79, 0x59, 0xd9, 0x3b, 0xf3, 0xba, 0x90, 0x6b, - 0x36, 0x2a, 0x7c, 0xf8, 0xd3, 0xf4, 0xaa, 0xd9, 0x17, 0x59, 0xb1, 0xe6, 0x5a, 0x50, 0xcb, 0x0b, - 0x6b, 0x19, 0x0c, 0xe0, 0x5e, 0x67, 0x09, 0x42, 0x53, 0x71, 0x8b, 0xc2, 0x4e, 0x46, 0xc3, 0xff, - 0xf1, 0x45, 0x2b, 0x81, 0x52, 0x3b, 0xb4, 0x59, 0x20, 0xdc, 0x24, 0xea, 0xa5, 0xe7, 0xfc, 0x19, - 0xc2, 0xeb, 0x8c, 0x91, 0x99, 0x0a, 0x87, 0x43, 0xa7, 0x4c, 0x3e, 0x5a, 0xd7, 0x71, 0x5e, 0x3f, - 0x7c, 0xd0, 0x2f, 0x1a, 0xc0, 0xac, 0x73, 0xcf, 0xfc, 0x0a, 0x85, 0xe8, 0xd6, 0xb1, 0xa2, 0xe0, - 0x2e, 0x7a, 0xa8, 0x68, 0x68, 0x0a, 0x7d, 0x73, 0xd0, 0xc7, 0x6a, 0x3e, 0x7b, 0x6b, 0x6a, 0x28, - 0x59, 0x7a, 0x29, 0x85, 0x84, 0x04, 0xbb, 0x7c, 0x5b, 0x8f, 0x68, 0x6f, 0xb7, 0x3e, 0xbf, 0xca, - 0x97, 0x62, 0x7a, 0x73, 0xf3, 0xe3, 0x23, 0x39, 0xa6, 0xb1, 0x71, 0xd0, 0x4e, 0xb5, 0x7a, 0x29, - 0x51, 0xc9, 0x40, 0x45, 0x2f, 0x25, 0x58, 0x0c, 0x71, 0x61, 0x9c, 0x73, 0x99, 0xc8, 0xab, 0xee, - 0x67, 0x0d, 0x97, 0xd3, 0xdc, 0xa0, 0x90, 0x3b, 0xc2, 0x91, 0x07, 0x1f, 0xf0, 0xe9, 0x97, 0xa9, - 0xb5, 0x46, 0xdc, 0x63, 0xfc, 0xa3, 0x24, 0x1f, 0xeb, 0xa8, 0x85, 0x66, 0x9a, 0xaf, 0x0f, 0x37, - 0xe0, 0x8e, 0x01, 0x32, 0x35, 0xdb, 0xbe, 0xa3, 0xbe, 0xf6, 0x2f, 0x1a, 0xd8, 0x1e, 0xc6, 0x40, - 0xb9, 0x69, 0xea, 0x02, 0x95, 0x14, 0x9b, 0xe9, 0x7d, 0x0c, 0xb7, 0x55, 0xf8, 0x87, 0xd9, 0x76, - 0x3e, 0x15, 0xae, 0x83, 0xba, 0xe7, 0x60, 0xc4, 0x0d, 0x32, 0x8a, 0x46, 0x9a, 0x56, 0xdc, 0xc1, - 0x62, 0x9e, 0x76, 0xf6, 0x34, 0xfb, 0xb9, 0xca, 0x32, 0xaa, 0xdd, 0x2b, 0x4e, 0xd2, 0xbc, 0x1a, - 0xe4, 0x5d, 0x8c, 0x79, 0xb1, 0x84, 0xd3, 0xfc, 0xd5, 0x40, 0xa9, 0x00, 0x97, 0x18, 0x39, 0xf7, - 0x78, 0xa7, 0xfd, 0x60, 0xb4, 0xfa, 0x3f, 0x8b, 0x74, 0x23, 0xb6, 0x90, 0x07, 0x32, 0xea, 0xde, - 0x4d, 0xe9, 0xbf, 0xe3, 0x78, 0x0a, 0xe0, 0x86, 0x21, 0x02, 0x2d, 0x45, 0xe0, 0x74, 0x20, 0xb7, - 0x63, 0x17, 0x2f, 0x09, 0xd3, 0xbe, 0x24, 0x6e, 0xef, 0x62, 0x06, 0x35, 0x1d, 0x0d, 0xe0, 0xb8, - 0xc4, 0xff, 0xc5, 0x3e, 0x4a, 0xf3, 0x04, 0x2b, 0x4f, 0xea, 0xf6, 0xfd, 0x8d, 0x28, 0x5e, 0xdc, - 0xe8, 0x1d, 0x39, 0x20, 0x43, 0x89, 0x5c, 0x37, 0x50, 0x38, 0x92, 0x00, 0x69, 0x46, 0xc8, 0x55, - 0x16, 0x70, 0x90, 0x73, 0x9e, 0xd8, 0x08, 0xdb, 0x3a, 0xcf, 0x5c, 0xc8, 0xdb, 0x2b, 0xae, 0x8e, - 0x7c, 0x51, 0xa9, 0x0c, 0x54, 0xc8, 0x15, 0x21, 0x26, 0x29, 0x92, 0x25, 0x19, 0xa8, 0x31, 0x7c, - 0x7d, 0x41, 0x32, 0x69, 0xe4, 0xfd, 0xf0, 0x0f, 0x12, 0x2e, 0x35, 0x0d, 0x22, 0x04, 0xf5, 0x7e, - 0x5c, 0xa7, 0x2e, 0xe1, 0xda, 0x11, 0xd2, 0xbf, 0x98, 0xe1, 0x33, 0xf7, 0x3c, 0xb2, 0x4a, 0x1c, - 0x01, 0x3e, 0xf7, 0xcc, 0x14, 0x2a, 0x51, 0xe6, 0x4f, 0x43, 0xba, 0xd4, 0xad, 0xb7, 0x8c, 0x5c, - 0x4a, 0x44, 0x03, 0x7f, 0x80, 0x0f, 0xe5, 0x58, 0x35, 0x44, 0x11, 0x13, 0x63, 0xd6, 0x62, 0x48, - 0x15, 0xa9, 0xb9, 0xdf, 0xf9, 0xc1, 0x70, 0x80, 0xdf, 0x76, 0xda, 0x93, 0x50, 0xc3, 0x17, 0x5b, - 0xb7, 0xdd, 0xfa, 0x14, 0x5a, 0xfa, 0x2f, 0xd6, 0x4b, 0x54, 0xd8, 0x41, 0xab, 0x82, 0xc9, 0x12, - 0xd8, 0x65, 0x71, 0x99, 0xff, 0x07, 0x3b, 0x46, 0x84, 0xeb, 0x89, 0x04, 0x10, 0x6d, 0x5c, 0x1e, - 0xe4, 0xcb, 0x13, 0xcd, 0x37, 0x3b, 0xde, 0x78, 0xfc, 0x48, 0xbd, 0xb2, 0x85, 0x89, 0x45, 0x72, - 0x96, 0x2a, 0x7d, 0x69, 0x1a, 0x59, 0x6d, 0x03, 0x30, 0xb9, 0xce, 0x98, 0xb3, 0xc2, 0x23, 0xb4, - 0x86, 0x2a, 0x1e, 0x76, 0x49, 0xc0, 0x7b, 0xd6, 0x3c, 0x54, 0x76, 0x22, 0x1c, 0x8e, 0x86, 0x56, - 0xeb, 0xa3, 0x00, 0x73, 0x3c, 0xeb, 0x64, 0xa1, 0xd7, 0x4a, 0xeb, 0x4d, 0x98, 0x49, 0xcf, 0x93, - 0x72, 0xec, 0x35, 0x33, 0x8b, 0x97, 0xf4, 0xd0, 0xb7, 0x80, 0xf8, 0xc4, 0x85, 0x27, 0x1f, 0x5e, - 0x3c, 0xe9, 0x83, 0x3d, 0xbc, 0x99, 0x96, 0x3d, 0x63, 0xaa, 0x99, 0x7c, 0x83, 0x07, 0x55, 0x78, - 0x94, 0x7f, 0xa4, 0x48, 0x77, 0x38, 0xa3, 0xb8, 0xb7, 0x02, 0xee, 0x82, 0xac, 0x27, 0x1e, 0xb4, - 0x2a, 0xa9, 0x27, 0x98, 0xcf, 0x58, 0x80, 0xa6, 0x58, 0x15, 0xce, 0x17, 0x87, 0xb4, 0xff, 0xaf, - 0x22, 0xa8, 0xf3, 0x83, 0xf6, 0xd9, 0x04, 0xb3, 0xbb, 0xf1, 0x1a, 0xa7, 0x00, 0x5c, 0x64, 0xfb, - 0x99, 0x6f, 0x54, 0xda, 0x29, 0x1e, 0x4f, 0xae, 0x22, 0x24, 0xce, 0xc8, 0x77, 0xc8, 0x7e, 0xe6, - 0xfd, 0xce, 0x07, 0x7d, 0x0d, 0x93, 0xde, 0x13, 0xd3, 0x08, 0xdb, 0xc1, 0xd5, 0xbb, 0x5a, 0x69, - 0x34, 0xa5, 0x90, 0x44, 0x5b, 0xd2, 0x50, 0x4c, 0x03, 0xb4, 0x35, 0x33, 0x4d, 0x63, 0xdb, 0xfb, - 0xe7, 0xed, 0x07, 0x91, 0x1f, 0x7e, 0xa5, 0x68, 0xa0, 0xe7, 0x80, 0x65, 0xf8, 0x79, 0xc7, 0xca, - 0x80, 0x27, 0x41, 0x59, 0xa3, 0x38, 0xc3, 0xae, 0xa5, 0x8c, 0x1d, 0x00, 0xb5, 0xbc, 0x6d, 0x16, - 0xdf, 0x8e, 0x36, 0xa6, 0x24, 0x8e, 0x1d, 0xca, 0x0c, 0x13, 0xed, 0x3d, 0xe1, 0x68, 0xc9, 0x0b, - 0x8b, 0xd4, 0x17, 0xf2, 0xb3, 0xec, 0x78, 0xa0, 0x7d, 0x35, 0x71, 0xe4, 0x24, 0xd1, 0xe5, 0xc1, - 0x13, 0x2c, 0x7e, 0xab, 0x86, 0x19, 0xfe, 0xbe, 0x22, 0xcf, 0xb7, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xae, 0x29, 0x35, 0xf1, 0xdf, 0xd8, 0xa2, 0x4a, 0xed, 0x7c, 0x70, 0xdf, - 0x7d, 0xe3, 0xa6, 0x68, 0xeb, 0x7a, 0x49, 0xb1, 0x31, 0x98, 0x80, 0xdd, 0xe2, 0xbb, 0xd9, 0x03, - 0x1a, 0xe5, 0xd8, 0x2f, 0xfd, 0xe0, 0x1c, 0x85, 0xa0, 0x45, 0xcc, 0x0e, 0xf3, 0x67, 0x88, 0xe9, - 0x1e, 0xdf, 0x18, 0xe6, 0x3a, 0x44, 0x94, 0x53, 0x74, 0x09, 0x4e, 0x08, 0x3c, 0x33, 0xd3, 0x07, - 0xd1, 0x72, 0xaf, 0x7f, 0x82, 0xec, 0x14, 0x05, 0x87, 0x12, 0x50, 0xc0, 0xc4, 0x4f, 0x7c, 0x67, - 0xdf, 0xd2, 0xe2, 0xc7, 0x38, 0x0d, 0x7c, 0x30, 0xf6, 0x80, 0x39, 0xe2, 0x7d, 0x77, 0xb4, 0x42, - 0xcb, 0x01, 0x63, 0xca, 0x95, 0x32, 0xa4, 0x18, 0x2c, 0x2b, 0xef, 0xa0, 0x26, 0x88, 0xc6, 0x01, - 0x97, 0x10, 0xba, 0xba, 0x3d, 0x80, 0xf2, 0xb8, 0x94, 0xfd, 0x91, 0x75, 0xf2, 0x2c, 0x7f, 0xf6, - 0xdf, 0x41, 0x2c, 0x8c, 0x41, 0xde, 0xb3, 0x94, 0xb9, 0x89, 0xc2, 0x27, 0xf5, 0xc2, 0x03, 0x32, - 0xb7, 0xa0, 0x30, 0x36, 0x98, 0x23, 0xc6, 0xac, 0x19, 0xee, 0xa1, 0xe6, 0xe2, 0x68, 0xee, 0xaa, - 0x70, 0x0c, 0x81, 0xe8, 0x87, 0x31, 0xbf, 0x74, 0xaa, 0xd7, 0x37, 0xab, 0xf9, 0x15, 0x8c, 0x3e, - 0xfc, 0x59, 0x16, 0x20, 0x4e, 0xe3, 0xd4, 0x5e, 0x57, 0x28, 0xcf, 0x42, 0x7f, 0x1a, 0x86, 0x9d, - 0x1c, 0x5d, 0x4a, 0xf1, 0x7a, 0x17, 0x9e, 0xd1, 0x6f, 0xfd, 0xcd, 0xb4, 0xe9, 0x05, 0xdb, 0x8e, - 0x10, 0x99, 0x25, 0x41, 0x2c, 0xa6, 0xf6, 0x65, 0xd3, 0x4f, 0x3c, 0x3d, 0xc9, 0x2c, 0xf5, 0x40, - 0xea, 0x6d, 0x7a, 0x07, 0xdf, 0x9c, 0x3b, 0x3f, 0xe7, 0x45, 0xd8, 0xcf, 0x95, 0x33, 0x57, 0x39, - 0x37, 0x61, 0x36, 0x7c, 0xf7, 0xee, 0xb5, 0xc0, 0x75, 0x0b, 0xe3, 0x08, 0x02, 0xfe, 0x8f, 0x52, - 0x14, 0xa4, 0x1f, 0x99, 0xbe, 0x8d, 0xb8, 0x1f, 0x35, 0xf1, 0x96, 0x61, 0x31, 0x19, 0x20, 0xd8, - 0x1c, 0xdb, 0x99, 0x9f, 0x34, 0x68, 0xf0, 0x16, 0x05, 0x5d, 0x33, 0xbc, 0x8e, 0xa9, 0x50, 0xda, - 0x3f, 0x07, 0xc0, 0xf1, 0x02, 0x61, 0x88, 0xe2, 0x8b, 0x50, 0xc9, 0xad, 0x30, 0xab, 0x00, 0x05, - 0xea, 0x60, 0x4c, 0xcf, 0x86, 0xb0, 0x32, 0x40, 0x1a, 0x6b, 0x84, 0xf9, 0xee, 0xee, 0x1c, 0x82, - 0xf6, 0xbc, 0xd3, 0x88, 0x7c, 0xb9, 0x87, 0x88, 0x8c, 0x1e, 0xc2, 0x55, 0x37, 0xc6, 0x60, 0xdc, - 0xf8, 0x1d, 0xbc, 0x80, 0x06, 0x33, 0x33, 0x61, 0x99, 0xce, 0x7c, 0x41, 0xea, 0xf2, 0xc8, 0x92, - 0x0c, 0xd3, 0xd6, 0xf4, 0x1b, 0xa7, 0x8d, 0x97, 0xb9, 0x84, 0x51, 0x65, 0x6e, 0xcb, 0x7a, 0x73, - 0x97, 0x0a, 0xfd, 0xaa, 0x36, 0xb9, 0xb1, 0x5e, 0x8d, 0xe1, 0xcf, 0x85, 0x2c, 0x5c, 0x41, 0xee, - 0x6c, 0xbc, 0x0e, 0x76, 0x80, 0x5a, 0xa9, 0x3c, 0x3f, 0xa9, 0x33, 0xc4, 0x3d, 0x12, 0x5d, 0x0b, - 0x00, 0x68, 0x7d, 0x15, 0x30, 0x37, 0xe2, 0x4d, 0x4f, 0x49, 0x30, 0x0c, 0x93, 0x2c, 0x18, 0xdd, - 0x1f, 0x92, 0xab, 0xef, 0x0a, 0x2c, 0x12, 0x4c, 0x4e, 0x99, 0xee, 0xcb, 0x95, 0x68, 0xf1, 0xf8, - 0x88, 0x8c, 0xe1, 0x16, 0x2d, 0x08, 0x6a, 0x5a, 0xb1, 0x87, 0xb4, 0x9f, 0x6b, 0x16, 0xb6, 0x69, - 0xb0, 0x40, 0xbc, 0x9c, 0x54, 0x61, 0xa2, 0x65, 0x97, 0x29, 0xa0, 0xfa, 0x12, 0x7b, 0xc5, 0xdb, - 0xcf, 0x6a, 0x54, 0xfc, 0xc8, 0x93, 0xd0, 0xdf, 0x06, 0x7a, 0xd7, 0x44, 0x0c, 0x80, 0x35, 0xe1, - 0xcf, 0x18, 0xc5, 0xb4, 0x19, 0xf3, 0x9c, 0x97, 0x3b, 0x1a, 0x91, 0xbd, 0x54, 0x0c, 0x37, 0x6b, - 0x14, 0x1d, 0xfe, 0x5c, 0xea, 0xb4, 0x3c, 0x71, 0x16, 0x21, 0x1e, 0xa0, 0x14, 0x13, 0x8d, 0xaf, - 0xbd, 0x24, 0xb2, 0x9a, 0xf4, 0x82, 0xab, 0x03, 0xb7, 0x77, 0x00, 0x6f, 0x99, 0x6f, 0xa4, 0x89, - 0xe7, 0x6f, 0xf9, 0xc2, 0x30, 0x3c, 0x1f, 0xe4, 0x69, 0x27, 0x53, 0x40, 0x16, 0xf1, 0x9e, 0xae, - 0xe7, 0xd1, 0xaf, 0x02, 0xf7, 0xb1, 0x13, 0x1a, 0x3e, 0x16, 0x1b, 0x2d, 0x18, 0xfd, 0xbf, 0xb8, - 0x61, 0xeb, 0xf7, 0x8d, 0xe8, 0x5b, 0xa0, 0xee, 0x0e, 0x56, 0xe6, 0xe1, 0x5c, 0x4a, 0x09, 0x51, - 0x41, 0xfa, 0x0c, 0xa8, 0xfc, 0x1a, 0x8d, 0x00, 0x14, 0x4d, 0x82, 0x85, 0x9e, 0x62, 0x7b, 0x70, - 0x06, 0x0b, 0x6a, 0xd7, 0xb1, 0x82, 0x46, 0x49, 0xcf, 0x3b, 0x76, 0x57, 0xd0, 0x27, 0x44, 0xac, - 0xb8, 0xb3, 0x74, 0x6b, 0x3a, 0x1c, 0x2b, 0xdb, 0x5c, 0x9a, 0x57, 0x1c, 0x79, 0xee, 0x80, 0x1d, - 0x6a, 0x8d, 0xbb, 0xfd, 0xc1, 0x70, 0x4e, 0x9b, 0xa0, 0xd3, 0x29, 0x3e, 0xe1, 0x61, 0xe5, 0xe9, - 0x69, 0x59, 0xf6, 0x3f, 0x55, 0x5e, 0x0f, 0x8a, 0x4a, 0x99, 0x95, 0xa4, 0x97, 0x71, 0xd0, 0x72, - 0x36, 0xb4, 0x20, 0x0a, 0xce, 0x69, 0xab, 0xdc, 0xf9, 0xa4, 0x66, 0xd3, 0x0e, 0x81, 0xca, 0x93, - 0xa9, 0xb9, 0xd1, 0x92, 0x41, 0xa3, 0x09, 0x57, 0xcb, 0x05, 0x28, 0xaf, 0xea, 0x86, 0xe1, 0xf1, - 0x9c, 0x7d, 0x38, 0x58, 0x97, 0x6d, 0x50, 0xa6, 0xef, 0xf6, 0xbf, 0x8b, 0x29, 0x8d, 0xbb, 0x86, - 0x48, 0x52, 0x58, 0x8f, 0x88, 0x55, 0x8a, 0x05, 0x40, 0xa0, 0x7c, 0x72, 0xb6, 0xdd, 0xa9, 0x48, - 0x77, 0xdc, 0xee, 0xbc, 0xd3, 0x6f, 0x95, 0x9f, 0x51, 0xa8, 0x5d, 0x7a, 0x61, 0x06, 0x6a, 0x78, - 0x1c, 0xb9, 0xcf, 0xa9, 0xf7, 0x88, 0x81, 0x97, 0x53, 0x5f, 0x62, 0x58, 0xb2, 0x8d, 0x71, 0xce, - 0xf4, 0x05, 0x16, 0x8b, 0x4a, 0xa3, 0xdd, 0x35, 0xfa, 0xdd, 0xd9, 0x95, 0xde, 0xb5, 0x26, 0x0d, - 0xf8, 0x73, 0x26, 0xb6, 0x5c, 0x09, 0x2b, 0x49, 0xac, 0x66, 0x91, 0x33, 0x5f, 0x44, 0xbe, 0x13, - 0xd1, 0x64, 0x44, 0xe4, 0x86, 0x4a, 0xdd, 0xde, 0x2e, 0x2c, 0xe1, 0x89, 0x32, 0x66, 0x14, 0x2e, - 0x75, 0x74, 0xe6, 0x47, 0xf9, 0x74, 0x11, 0xe3, 0x00, 0x3f, 0x13, 0x07, 0xbc, 0x09, 0x88, 0x4b, - 0x51, 0xf6, 0x91, 0xb7, 0x45, 0xaf, 0xaf, 0x69, 0x7b, 0x4f, 0x77, 0x7d, 0x2e, 0xc7, 0x5c, 0x2c, - 0x4f, 0xae, 0x5a, 0x80, 0x6a, 0xef, 0xba, 0x3e, 0x2c, 0x93, 0x63, 0x3a, 0xe4, 0xce, 0x75, 0xe1, - 0xce, 0x38, 0xf7, 0x84, 0xe1, 0xfa, 0x6f, 0x3e, 0x20, 0x17, 0x3a, 0xe7, 0x99, 0x24, 0xc1, 0x2f, - 0x98, 0x32, 0xe4, 0xca, 0x89, 0x80, 0x9c, 0x68, 0x50, 0xb1, 0x56, 0x7e, 0x5f, 0x51, 0x2c, 0x79, - 0x05, 0x16, 0x10, 0xf0, 0x7e, 0x8b, 0x09, 0xaa, 0xb1, 0xf5, 0xcf, 0xb9, 0x18, 0x14, 0x5e, 0xfd, - 0xc0, 0x08, 0xbd, 0x65, 0x1f, 0x7c, 0x1b, 0x2e, 0x0b, 0x7e, 0xc8, 0xbb, 0x32, 0x71, 0x83, 0x2c, - 0x67, 0x82, 0x32, 0xfb, 0xcb, 0x22, 0xe0, 0xff, 0x9b, 0xc1, 0x0a, 0x54, 0xe7, 0xdb, 0x86, 0x23, - 0x00, 0x04, 0x08, 0x06, 0xd1, 0x5a, 0x8f, 0xc9, 0xe3, 0x3a, 0x9b, 0x51, 0xeb, 0xfd, 0xb2, 0xf3, - 0x27, 0x45, 0xa1, 0xeb, 0xdc, 0xd0, 0xf9, 0xa7, 0x70, 0x23, 0xec, 0xc4, 0x29, 0xf1, 0xce, 0x52, - 0x89, 0xa2, 0xcb, 0xa0, 0x45, 0x6d, 0xa5, 0xa7, 0x73, 0xf4, 0xd7, 0x4c, 0x48, 0xd9, 0x15, 0xb9, - 0xe9, 0x87, 0x84, 0x30, 0xfe, 0x0d, 0xf6, 0x45, 0x88, 0xa4, 0x29, 0x26, 0x5d, 0xde, 0xc9, 0x0f, - 0xea, 0x4c, 0xb3, 0xe1, 0x48, 0x9f, 0x03, 0x99, 0x8f, 0xb6, 0x78, 0xa1, 0xaa, 0x7a, 0xa3, 0x99, - 0xb9, 0x0c, 0xcf, 0x22, 0xc5, 0x6e, 0x51, 0x82, 0xcb, 0x14, 0xbd, 0x5e, 0x03, 0xc1, 0xe1, 0xc2, - 0xec, 0x68, 0x09, 0xb0, 0x20, 0x06, 0xa9, 0x1c, 0x64, 0xdc, 0x8d, 0xac, 0x8c, 0xbb, 0x1c, 0xb7, - 0x6b, 0x80, 0x58, 0x92, 0x85, 0xe4, 0x2c, 0x98, 0xfa, 0x44, 0xd9, 0xe0, 0xfd, 0x67, 0xb4, 0xa1, - 0xfc, 0x02, 0xfd, 0x82, 0x0c, 0xac, 0xa3, 0x6f, 0x20, 0x54, 0x5e, 0x22, 0xfe, 0xb1, 0x2d, 0xad, - 0x46, 0x72, 0x5d, 0x78, 0xea, 0xb3, 0xd4, 0x65, 0xa5, 0xd2, 0x85, 0xa2, 0xe9, 0xb2, 0xbc, 0xf6, - 0xdf, 0x32, 0xa3, 0x2a, 0x91, 0x26, 0x1b, 0x18, 0x05, 0x23, 0x19, 0xb5, 0x1e, 0x3c, 0x6a, 0x29, - 0x7d, 0xc3, 0x6e, 0x52, 0xc7, 0xf2, 0x50, 0x29, 0x67, 0xfb, 0xeb, 0x0a, 0xd0, 0xdb, 0xf7, 0x0c, - 0x8a, 0x25, 0x70, 0xb8, 0xf7, 0x15, 0x88, 0xfb, 0x28, 0x91, 0xef, 0xf0, 0xa2, 0x3c, 0x28, 0xdd, - 0x2f, 0x4f, 0xd0, 0xf6, 0x26, 0xa4, 0xdb, 0x65, 0x3b, 0x39, 0x61, 0x43, 0xc6, 0xf8, 0x68, 0xd6, - 0x55, 0xe2, 0xd5, 0x85, 0x03, 0x9c, 0x89, 0x1a, 0x11, 0xff, 0xf1, 0x37, 0x76, 0x8d, 0x05, 0xf7, - 0x5c, 0x27, 0xb8, 0xd3, 0x79, 0xad, 0x02, 0xca, 0xb0, 0x52, 0xec, 0x67, 0x89, 0xfb, 0xb1, 0x28, - 0x72, 0xae, 0x32, 0x2f, 0xde, 0x58, 0x2c, 0x8e, 0x6d, 0x87, 0xb3, 0x3f, 0xb8, 0x44, 0x7e, 0x81, - 0x76, 0x29, 0x4b, 0xe9, 0xdf, 0x99, 0xc7, 0x43, 0xde, 0xb2, 0xe3, 0xf9, 0xf9, 0x1c, 0x8a, 0x3b, - 0x58, 0x88, 0xf6, 0x0e, 0x1e, 0x7f, 0x9f, 0x49, 0xb0, 0x49, 0xba, 0xdb, 0x6d, 0x59, 0xdf, 0x42, - 0x8e, 0xa4, 0x13, 0x80, 0xb5, 0x01, 0x90, 0xd9, 0x6f, 0xf7, 0x2e, 0xba, 0x28, 0x7c, 0xa5, 0x5f, - 0x32, 0x43, 0x99, 0x64, 0xa9, 0xa5, 0x9b, 0xa8, 0xc0, 0x99, 0x03, 0x08, 0x02, 0x10, 0xde, 0xa1, - 0x75, 0xc9, 0x72, 0xa7, 0x66, 0x7a, 0x66, 0xca, 0xb9, 0x36, 0xd0, 0x98, 0xaf, 0xdf, 0x2d, 0xc3, - 0xac, 0x5c, 0xda, 0x1c, 0x66, 0xea, 0xb7, 0x3e, 0x89, 0x32, 0x54, 0xb3, 0x57, 0xa5, 0x4f, 0x9a, - 0xda, 0x6b, 0x11, 0x21, 0x79, 0x15, 0x7e, 0xb1, 0x92, 0x64, 0x07, 0xe8, 0x8f, 0x40, 0x19, 0xbf, - 0x7b, 0x34, 0x1d, 0xd5, 0xbb, 0x0e, 0xbc, 0xd3, 0xd9, 0x88, 0x59, 0xe1, 0xd2, 0xe2, 0x8a, 0x25, - 0xd8, 0x6c, 0x34, 0x8c, 0xab, 0xca, 0x24, 0x51, 0xbf, 0xcd, 0x7d, 0x1a, 0x88, 0x0e, 0x41, 0x0f, - 0xcf, 0x10, 0x62, 0x40, 0xf1, 0xef, 0x38, 0xf9, 0x14, 0x52, 0x9a, 0x6f, 0xd3, 0xf9, 0x6b, 0x98, - 0x4f, 0x19, 0x6c, 0x07, 0xec, 0xcf, 0x36, 0x53, 0x77, 0x58, 0x23, 0x56, 0x08, 0x65, 0xdb, 0x24, - 0x1c, 0xd2, 0xdb, 0x62, 0x5f, 0xdc, 0x1c, 0x01, 0x49, 0xf6, 0x8c, 0x21, 0x6f, 0x71, 0x22, 0x5f, - 0x02, 0xb5, 0x00, 0x49, 0x28, 0x11, 0xc1, 0x3c, 0xba, 0x69, 0xdc, 0x7f, 0xcb, 0xc7, 0xa8, 0x8d, - 0xf5, 0xee, 0xe4, 0x4b, 0x53, 0x8d, 0x01, 0xa3, 0xd1, 0x82, 0x88, 0x28, 0x03, 0x42, 0xed, 0x20, - 0x4b, 0xca, 0xb0, 0x3a, 0x4e, 0x05, 0xee, 0x42, 0xc1, 0xd8, 0xd6, 0x2c, 0x64, 0xd6, 0x83, 0x03, - 0xc1, 0x21, 0x75, 0xd4, 0xce, 0x5d, 0x83, 0x9b, 0x74, 0x88, 0x51, 0x14, 0x9c, 0x5e, 0x73, 0xe5, - 0xaf, 0x1e, 0x12, 0xae, 0xb9, 0xc3, 0x2d, 0xd7, 0x09, 0xf8, 0x4b, 0x2e, 0x14, 0xcf, 0x94, 0x17, - 0xf6, 0xc8, 0x28, 0xbf, 0x6b, 0xd9, 0x33, 0x4c, 0x4c, 0xab, 0x2e, 0xa4, 0x3a, 0xe7, 0x6b, 0x3d, - 0xe0, 0xc4, 0x35, 0xc1, 0xb3, 0x7f, 0x9e, 0xcc, 0x65, 0xeb, 0xed, 0xd8, 0x15, 0x27, 0x11, 0x66, - 0x20, 0x68, 0xaa, 0xf3, 0xa0, 0xf3, 0xa8, 0x6f, 0x51, 0x63, 0x42, 0xcf, 0xba, 0x10, 0x4f, 0x04, - 0xdf, 0x64, 0x87, 0x88, 0xda, 0x49, 0x3e, 0xbf, 0xa2, 0x21, 0xd6, 0x31, 0xac, 0x9f, 0xf2, 0xf8, - 0xd1, 0x5c, 0xf8, 0x89, 0x72, 0x0c, 0x9e, 0x24, 0x30, 0xc1, 0x9f, 0xd9, 0x36, 0xae, 0xcc, 0xcc, - 0xbb, 0x09, 0xf2, 0xc3, 0x5c, 0xf9, 0x33, 0x87, 0x58, 0xb5, 0x47, 0x69, 0x26, 0x23, 0x57, 0x98, - 0xa4, 0x62, 0xa9, 0x0d, 0x70, 0xa7, 0x2d, 0xce, 0x6f, 0x55, 0x05, 0x8f, 0x8b, 0x51, 0x5b, 0x18, - 0xcd, 0x65, 0x9b, 0x47, 0xb6, 0xee, 0xd4, 0xfd, 0x72, 0x28, 0xa0, 0x94, 0xa2, 0xd7, 0xd2, 0xef, - 0x5a, 0xae, 0xc1, 0xf3, 0x6b, 0x5c, 0xa4, 0x54, 0xdb, 0x48, 0xec, 0xfd, 0xe1, 0xe9, 0x5e, 0x8c, - 0x62, 0x4c, 0xf7, 0x7a, 0x50, 0x62, 0xeb, 0xdf, 0x54, 0x6a, 0x49, 0x6f, 0xdb, 0x5a, 0x02, 0x96, - 0xf9, 0x1d, 0x57, 0x8e, 0xa1, 0x61, 0xaa, 0xc7, 0xc7, 0xa8, 0x1b, 0xf5, 0x33, 0x3d, 0x65, 0x12, - 0x45, 0x54, 0xfc, 0x9d, 0x40, 0x17, 0x7c, 0xff, 0xf4, 0x2e, 0x0b, 0xbd, 0x56, 0x80, 0x5c, 0x83, - 0x7f, 0xe6, 0x20, 0x3f, 0x6e, 0x91, 0xa2, 0x2c, 0x58, 0x33, 0x69, 0xbc, 0x15, 0x10, 0xdc, 0x2d, - 0xa3, 0xd6, 0x06, 0xa9, 0xce, 0xa7, 0xec, 0xa8, 0x28, 0x14, 0xbe, 0xbe, 0x80, 0x82, 0x8f, 0x1d, - 0x4c, 0x24, 0x40, 0x26, 0x68, 0xdd, 0xa9, 0xaa, 0x4c, 0xd6, 0x87, 0x7e, 0x46, 0x7a, 0xaa, 0x43, - 0x56, 0x2e, 0xd9, 0x24, 0xda, 0x6f, 0xdd, 0x21, 0x10, 0x39, 0x48, 0xd5, 0x08, 0xec, 0x5d, 0x1f, - 0xe4, 0xdb, 0x64, 0xa1, 0x99, 0x8b, 0x11, 0x60, 0x2f, 0x4b, 0x44, 0x84, 0xd2, 0x69, 0x52, 0xfd, - 0xee, 0xe9, 0x5b, 0xb0, 0xa8, 0xc5, 0x07, 0x77, 0x15, 0xfe, 0x58, 0xf5, 0x62, 0xfb, 0x60, 0x4c, - 0x43, 0xe0, 0x17, 0x54, 0x42, 0x9f, 0x07, 0x7c, 0x2d, 0xc0, 0xa2, 0x6a, 0x3e, 0x13, 0x0b, 0x78, - 0x5c, 0x62, 0x98, 0x7f, 0x55, 0xe2, 0xc7, 0xb2, 0x58, 0xe1, 0x9d, 0x53, 0xb5, 0xd9, 0xaf, 0x0c, - 0x11, 0x70, 0x85, 0xca, 0x21, 0x87, 0x1a, 0x39, 0x5e, 0x67, 0xd4, 0x51, 0x75, 0x2e, 0xa8, 0xea, - 0x0d, 0x30, 0xc0, 0x93, 0x60, 0x18, 0x7f, 0xdf, 0x4a, 0x41, 0xa0, 0x80, 0x1c, 0xed, 0x5c, 0xaa, - 0x84, 0x4f, 0x2d, 0xec, 0x8c, 0xad, 0x24, 0xa1, 0x4b, 0xa9, 0x52, 0x27, 0x8e, 0x70, 0xf6, 0xff, - 0xc0, 0xb4, 0x13, 0x39, 0x75, 0xd4, 0xfc, 0x9a, 0xbf, 0xff, 0x53, 0x3f, 0x44, 0x19, 0xd9, 0xa5, - 0x28, 0x18, 0x5c, 0x38, 0xfb, 0x4c, 0x3e, 0x5b, 0x40, 0xf2, 0xf4, 0xc2, 0x2c, 0x95, 0xdb, 0xd2, - 0xe5, 0x5f, 0x87, 0x56, 0x63, 0x28, 0xda, 0x07, 0xa9, 0x90, 0x83, 0x94, 0xdb, 0x56, 0x2c, 0xa3, - 0xd0, 0xc4, 0x52, 0x6d, 0x1f, 0xfa, 0x35, 0x4f, 0xba, 0xcf, 0x12, 0xf4, 0xf0, 0x46, 0xb5, 0x1e, - 0x67, 0xba, 0x10, 0xc9, 0xc3, 0x0a, 0x30, 0xed, 0xcd, 0xc4, 0x3a, 0x87, 0x08, 0x2c, 0xd9, 0x21, - 0x5f, 0x68, 0x0f, 0xf8, 0x2f, 0x6f, 0x2a, 0x27, 0x47, 0x79, 0x16, 0x52, 0x7a, 0xfd, 0x9d, 0x65, - 0xec, 0x53, 0x90, 0xaf, 0xf0, 0x45, 0x24, 0x08, 0x5a, 0x9f, 0xfd, 0xec, 0xd9, 0x9a, 0x4c, 0x0a, - 0xd4, 0x09, 0x58, 0xdd, 0x29, 0xe4, 0x1a, 0x8e, 0xe9, 0xa3, 0x60, 0x85, 0xd8, 0xd5, 0x9c, 0xb7, - 0x33, 0x2c, 0x3a, 0xfe, 0xd7, 0x09, 0x5a, 0x7a, 0x19, 0x3b, 0x67, 0xc2, 0xc9, 0xf1, 0x41, 0xa4, - 0xc6, 0x7f, 0x1e, 0x7d, 0x6a, 0x75, 0x24, 0xce, 0xef, 0x30, 0xdc, 0x74, 0x8f, 0x2d, 0x8c, 0xf0, - 0x5d, 0x2d, 0x4b, 0x0d, 0x0d, 0x1a, 0xda, 0x8b, 0xdb, 0xc9, 0xac, 0xeb, 0x51, 0x5e, 0xaa, 0xde, - 0x05, 0x3c, 0x8c, 0x87, 0x09, 0x08, 0x2d, 0xd2, 0xca, 0xe6, 0x66, 0x97, 0x70, 0x38, 0x0e, 0x28, - 0x53, 0x4b, 0x59, 0x85, 0x6a, 0x59, 0xe2, 0xd2, 0x6f, 0x87, 0x4f, 0x4b, 0xf5, 0xe1, 0x4d, 0xc9, - 0x23, 0xdd, 0xfe, 0x77, 0x44, 0x92, 0x3f, 0xf6, 0x78, 0x93, 0x18, 0x38, 0x02, 0x24, 0x22, 0x89, - 0xb7, 0x59, 0x84, 0x7d, 0xe4, 0xf7, 0x67, 0xaa, 0xb8, 0xd4, 0x03, 0x92, 0x97, 0xfd, 0xaa, 0xb0, - 0x5d, 0xee, 0x1a, 0x48, 0xb1, 0xfb, 0x1c, 0x9d, 0xaf, 0x64, 0xc3, 0xd6, 0x3e, 0xb7, 0x62, 0xf5, - 0xdb, 0xea, 0x61, 0x1d, 0xde, 0xc6, 0xee, 0x6e, 0x90, 0xfd, 0x0b, 0x74, 0xd2, 0xc2, 0xf7, 0x35, - 0x98, 0x78, 0x74, 0x3e, 0xb4, 0xac, 0x29, 0x4f, 0xcd, 0x95, 0x6f, 0x0a, 0x6b, 0x20, 0xee, 0xd6, - 0xd8, 0x6b, 0x34, 0x51, 0xc0, 0x6f, 0x52, 0x9c, 0x4d, 0xac, 0x9a, 0x11, 0xb8, 0xb8, 0x29, 0x37, - 0x8a, 0x1b, 0x8f, 0x0c, 0x3a, 0x7a, 0x24, 0xfa, 0xc9, 0x5b, 0xef, 0x94, 0x9d, 0x36, 0xf9, 0x1a, - 0x5b, 0x97, 0xab, 0x0d, 0x3e, 0xc4, 0x7c, 0x9a, 0x83, 0xb7, 0x36, 0x1b, 0x2c, 0x93, 0xd2, 0x66, - 0x6e, 0x6f, 0x32, 0x11, 0x2f, 0x21, 0x19, 0x96, 0x3d, 0x7c, 0x5f, 0x2e, 0x6c, 0x05, 0x34, 0x95, - 0x7c, 0x1b, 0x9b, 0x33, 0xa4, 0xb2, 0x6d, 0x5f, 0xda, 0x45, 0x69, 0x0e, 0x5c, 0x1e, 0x5e, 0xa9, - 0x1a, 0x31, 0xc8, 0x23, 0x78, 0x98, 0x34, 0x4b, 0xe9, 0x37, 0xd5, 0x87, 0x46, 0xec, 0x9b, 0x20, - 0x50, 0x35, 0xb9, 0x95, 0xe5, 0x06, 0x50, 0xa6, 0xe1, 0xdd, 0x19, 0xf5, 0xc6, 0x96, 0xec, 0xb3, - 0x08, 0x1c, 0x25, 0xad, 0x3b, 0xfc, 0x11, 0x6c, 0x9a, 0x7d, 0xd8, 0x31, 0x03, 0x24, 0xb5, 0xcb, - 0x90, 0xed, 0xfc, 0x98, 0xb1, 0x46, 0xec, 0xd0, 0xa9, 0x3c, 0x1f, 0x66, 0xb5, 0xba, 0x5e, 0xf2, - 0x5a, 0xd5, 0xf3, 0xdf, 0x54, 0xe7, 0x11, 0x89, 0xdc, 0xf0, 0xea, 0x09, 0x5d, 0x7a, 0x7a, 0xf6, - 0x5f, 0x5d, 0x69, 0xc0, 0xbc, 0xf3, 0x73, 0x73, 0x9a, 0xd5, 0x78, 0x40, 0xe3, 0x54, 0x31, 0x45, - 0xd1, 0xc0, 0x2f, 0x93, 0xbc, 0x1e, 0x2f, 0x39, 0x4e, 0xb4, 0xf0, 0x3e, 0x57, 0x7a, 0x64, 0x8d, - 0x98, 0x66, 0x5d, 0x83, 0x5a, 0x6f, 0x8b, 0x5f, 0xf2, 0x7e, 0xd1, 0xc9, 0xcc, 0xbb, 0xf7, 0xaa, - 0x95, 0x2e, 0x7a, 0x7d, 0x8d, 0xec, 0x37, 0x7a, 0xb5, 0xbc, 0x8d, 0x62, 0xd2, 0x32, 0x1e, 0xd7, - 0x8b, 0x15, 0x06, 0x75, 0xde, 0x81, 0xab, 0xb0, 0xd4, 0x59, 0xa2, 0x25, 0x34, 0xca, 0x6d, 0xce, - 0x3f, 0xa3, 0xae, 0xe6, 0x09, 0xb3, 0x33, 0xe1, 0x25, 0x56, 0x77, 0x30, 0x8b, 0xf7, 0x30, 0x0f, - 0x74, 0x72, 0x36, 0x8c, 0x4b, 0x5d, 0x94, 0xbc, 0x4f, 0x5e, 0x1d, 0x8a, 0x75, 0xec, 0xd4, 0x21, - 0x21, 0xa9, 0x54, 0x9c, 0xc8, 0x37, 0x28, 0x06, 0xae, 0x5c, 0x72, 0x3b, 0xa0, 0x80, 0x0d, 0x17, - 0xbb, 0x22, 0xe8, 0xf7, 0xa9, 0x31, 0x7d, 0x2c, 0x13, 0x74, 0xbc, 0xa0, 0x09, 0xba, 0x5b, 0x05, - 0xa4, 0xf9, 0xab, 0xb5, 0xd5, 0xd7, 0x11, 0x3f, 0xa3, 0xb4, 0x89, 0x79, 0x1c, 0x4a, 0xd8, 0xfb, - 0xc6, 0x54, 0x41, 0xaf, 0x32, 0xc9, 0x71, 0xaa, 0x5a, 0xb1, 0xb5, 0xe0, 0xa0, 0x73, 0x45, 0x18, - 0x73, 0x17, 0xd2, 0xcb, 0xb8, 0x70, 0x30, 0xbb, 0xce, 0x25, 0xad, 0x9e, 0x8d, 0xf3, 0x0d, 0xec, - 0x26, 0x3f, 0x2c, 0x16, 0x49, 0x45, 0x68, 0xbe, 0x04, 0x3e, 0x67, 0x1a, 0xa6, 0x7e, 0xe9, 0x44, - 0x63, 0x43, 0x91, 0x92, 0x25, 0x84, 0x04, 0xe6, 0xa8, 0xb7, 0xf2, 0x70, 0x86, 0xba, 0x2e, 0x34, - 0x4c, 0x0f, 0x45, 0xac, 0x39, 0x8d, 0x0c, 0x59, 0x60, 0x08, 0xb2, 0x07, 0x79, 0xfd, 0xd0, 0x60, - 0xad, 0x0d, 0x53, 0xa6, 0x9b, 0x02, 0x22, 0xf2, 0xbc, 0xb4, 0xbd, 0x9e, 0x8a, 0xe8, 0x3b, 0xa7, - 0x76, 0x21, 0x8e, 0x59, 0x5f, 0x08, 0xb6, 0xf9, 0x4f, 0x18, 0x09, 0x8b, 0x8a, 0x94, 0x59, 0x93, - 0xa3, 0x23, 0xf1, 0xdb, 0x62, 0x88, 0x30, 0xe5, 0xea, 0xf1, 0x79, 0x3a, 0xf4, 0x3a, 0x57, 0xee, - 0xab, 0xa0, 0x82, 0x39, 0x44, 0xd9, 0x13, 0xb9, 0x32, 0xb4, 0x97, 0xb9, 0xa9, 0xb3, 0x23, 0x81, - 0x61, 0xed, 0x96, 0x51, 0xd9, 0xc5, 0x1c, 0x1b, 0xe7, 0x2a, 0x18, 0x83, 0xdb, 0xf5, 0xf2, 0x93, - 0x98, 0xd8, 0x79, 0xc3, 0x38, 0x6d, 0x86, 0x83, 0x9a, 0x80, 0x0d, 0x21, 0x5e, 0xbd, 0x7c, 0x7a, - 0x32, 0xd0, 0x75, 0xea, 0xe4, 0x95, 0x01, 0xcc, 0xa3, 0x2c, 0x74, 0x97, 0x1a, 0x25, 0xc7, 0x1a, - 0x38, 0xe6, 0x92, 0x8b, 0x89, 0xff, 0x56, 0xcd, 0x8d, 0x9f, 0xa0, 0x18, 0x9b, 0x00, 0xc4, 0x58, - 0x38, 0x49, 0x6a, 0x87, 0x59, 0xcc, 0x3b, 0xde, 0xb1, 0x6a, 0x86, 0x12, 0x74, 0x03, 0xd7, 0x04, - 0xc4, 0x63, 0xab, 0x1f, 0x5f, 0xf8, 0x4b, 0xba, 0x1d, 0x27, 0x06, 0xba, 0x68, 0xee, 0xe2, 0xd3, - 0x59, 0xb1, 0xc1, 0x7b, 0x97, 0x4e, 0x36, 0x9e, 0x13, 0x62, 0x9a, 0xad, 0x75, 0xe5, 0x44, 0xaa, - 0x9c, 0x5e, 0xdd, 0x05, 0x24, 0x6f, 0x44, 0x54, 0xc2, 0x5a, 0xfd, 0x4e, 0x97, 0x49, 0xfc, 0xf8, - 0xe9, 0x87, 0x42, 0x7d, 0xc5, 0xd6, 0x36, 0x21, 0x20, 0x6c, 0x2c, 0x32, 0xf9, 0xca, 0x49, 0x2f, - 0x7c, 0x3c, 0x24, 0x39, 0xd6, 0x91, 0xd3, 0x69, 0xf1, 0x8b, 0x91, 0x54, 0xfd, 0xa0, 0x7a, 0x01, - 0x52, 0x4a, 0xee, 0xf7, 0xea, 0xac, 0x19, 0xe8, 0x26, 0x8c, 0x5b, 0x23, 0xd3, 0xa3, 0xa6, 0x44, - 0xdf, 0x9c, 0x90, 0xd8, 0x09, 0x68, 0xda, 0x44, 0x50, 0x2c, 0x55, 0x44, 0xd5, 0xc2, 0x7d, 0xab, - 0xb0, 0x44, 0x81, 0xe5, 0xd9, 0x89, 0x0b, 0x08, 0x7e, 0xe0, 0x15, 0x0f, 0xef, 0x80, 0xd9, 0x46, - 0xef, 0x0d, 0x58, 0x9b, 0xa2, 0x5f, 0x74, 0xb4, 0x5c, 0x66, 0x84, 0x5b, 0x5d, 0x5e, 0x08, 0xd1, - 0xfc, 0x8e, 0x7b, 0xb4, 0x51, 0x59, 0x17, 0xb3, 0x32, 0xdb, 0x86, 0x6a, 0x7a, 0x11, 0x74, 0x78, - 0xda, 0x6b, 0x50, 0x10, 0x16, 0x04, 0x48, 0x1f, 0xc8, 0x24, 0x9f, 0x77, 0xb7, 0x39, 0x0f, 0xd4, - 0xde, 0x34, 0x50, 0x3a, 0xb7, 0x2d, 0x0e, 0x6e, 0x9e, 0x15, 0x9a, 0x8e, 0x90, 0x1e, 0x93, 0xbf, - 0x6b, 0xb8, 0xeb, 0x10, 0x52, 0xe4, 0x0d, 0x7f, 0x05, 0x0e, 0x5d, 0x87, 0x25, 0x8f, 0xbc, 0x7f, - 0x25, 0xfa, 0xce, 0x37, 0x03, 0xac, 0x15, 0xfa, 0x46, 0x3d, 0xd5, 0x48, 0xfb, 0xf2, 0x63, 0x7b, - 0xda, 0x6f, 0x37, 0xdb, 0xbe, 0xc0, 0xad, 0xac, 0xb3, 0x36, 0xe4, 0xe6, 0x15, 0xd7, 0xd4, 0xc8, - 0x4e, 0xe0, 0x74, 0x3d, 0xe7, 0x31, 0x05, 0xf3, 0x42, 0x79, 0x12, 0x91, 0x56, 0x8e, 0xf7, 0xd1, - 0x60, 0xd4, 0x7d, 0x28, 0x53, 0x5b, 0xe9, 0x16, 0x25, 0x17, 0x32, 0x6c, 0x3a, 0x80, 0xc8, 0x23, - 0xe3, 0x54, 0xef, 0xc4, 0xfe, 0xd7, 0x21, 0xa1, 0xc1, 0x01, 0xfc, 0xad, 0x4e, 0x3d, 0x14, 0xb5, - 0xd4, 0x08, 0x9d, 0xdd, 0x98, 0x6c, 0xd6, 0x26, 0x4d, 0xad, 0x83, 0x50, 0x45, 0x82, 0x0e, 0x8d, - 0x1e, 0x4c, 0x7a, 0xea, 0x65, 0xb2, 0x1c, 0x75, 0x2d, 0xe3, 0x57, 0xd2, 0x26, 0x56, 0x8c, 0x46, - 0xb7, 0x83, 0x61, 0x4b, 0x1d, 0xe0, 0x42, 0xa1, 0x3f, 0x9d, 0xe5, 0x37, 0xdd, 0xfa, 0x21, 0xd8, - 0x45, 0x2a, 0xa5, 0xc8, 0x4f, 0x8a, 0x38, 0x0c, 0xc0, 0x7f, 0x43, 0xac, 0xfa, 0xaf, 0x8b, 0x84, - 0xdf, 0x70, 0xc3, 0xf7, 0x1b, 0xff, 0x1c, 0x82, 0x66, 0xdb, 0x04, 0x27, 0xa8, 0x60, 0x38, 0xd9, - 0x6a, 0x76, 0xbc, 0xd2, 0xac, 0xa7, 0x2c, 0xa7, 0x25, 0xde, 0xe2, 0xff, 0xc0, 0x30, 0xbb, 0x45, - 0x3c, 0x11, 0xea, 0x3b, 0x33, 0xfb, 0x40, 0x71, 0xbe, 0xfe, 0xa6, 0x0b, 0xb9, 0xac, 0xff, 0xa9, - 0xe4, 0xc6, 0x5d, 0x9a, 0x9b, 0xea, 0x10, 0x53, 0x95, 0xa3, 0x4f, 0x9b, 0xc7, 0x8c, 0x4c, 0x5e, - 0x92, 0x95, 0xc1, 0x52, 0xd2, 0xe1, 0x45, 0x4a, 0x53, 0x14, 0xc1, 0xed, 0x1f, 0xba, 0x8a, 0x47, - 0xc3, 0x64, 0x1e, 0x7b, 0xf6, 0x61, 0x39, 0xb8, 0x1c, 0x83, 0x59, 0x2d, 0x1e, 0xf6, 0xb4, 0x81, - 0x32, 0xee, 0xe0, 0x97, 0xd2, 0x25, 0xdb, 0xa6, 0x44, 0xf0, 0xe9, 0x73, 0xa1, 0xb5, 0xfc, 0x1b, - 0x04, 0xe5, 0x5d, 0x35, 0x3c, 0xe3, 0x1b, 0x4a, 0x30, 0x02, 0x29, 0x00, 0xe9, 0xda, 0xc5, 0x74, - 0x6f, 0x7e, 0xb4, 0xa1, 0x4f, 0xbb, 0xfe, 0x8b, 0x36, 0x74, 0x2a, 0x4e, 0xee, 0xc6, 0x85, 0x38, - 0x05, 0x74, 0xfe, 0x5c, 0xf2, 0xca, 0x39, 0xdd, 0xab, 0xca, 0xa4, 0x30, 0xf9, 0xee, 0xf1, 0x3b, - 0xdd, 0x2c, 0xe0, 0x64, 0x73, 0x88, 0x9e, 0x80, 0x0f, 0xbf, 0xf8, 0x5e, 0x1a, 0x8b, 0x05, 0xea, - 0x9a, 0x9a, 0xae, 0x82, 0xeb, 0x6d, 0x04, 0xbf, 0xa8, 0x25, 0xdf, 0x54, 0x17, 0x92, 0x3d, 0x52, - 0x4e, 0x3c, 0x93, 0xc6, 0x5a, 0xd8, 0x50, 0xf8, 0x57, 0x42, 0xf2, 0x02, 0x9e, 0xbb, 0xf6, 0x44, - 0xd7, 0x0d, 0x59, 0xdf, 0x77, 0x3b, 0x23, 0x54, 0x7b, 0xa7, 0x67, 0x75, 0xf3, 0xe5, 0x75, 0x3e, - 0x9d, 0xdc, 0xe0, 0xdc, 0x75, 0xb8, 0x93, 0xf0, 0xd2, 0x5b, 0x03, 0x9c, 0x56, 0x4d, 0x22, 0xd9, - 0xfd, 0x42, 0xb2, 0xcf, 0xc9, 0xb4, 0x3f, 0xe5, 0x32, 0x01, 0x75, 0x54, 0xa4, 0xdf, 0xa3, 0x43, - 0xcd, 0x77, 0x25, 0x87, 0xb9, 0x74, 0x07, 0x71, 0xe8, 0xa6, 0x82, 0x82, 0x14, 0x16, 0x94, 0x45, - 0x6a, 0xb1, 0x42, 0xfe, 0x7b, 0xbf, 0x08, 0xa2, 0x1d, 0x42, 0xc2, 0x79, 0x6e, 0xec, 0x50, 0x71, - 0x57, 0xa5, 0x81, 0xbf, 0xe4, 0x52, 0x68, 0xf1, 0xd4, 0xc9, 0xdb, 0x34, 0x2d, 0x9e, 0xda, 0x2f, - 0x29, 0xda, 0x43, 0x6a, 0xc6, 0x13, 0x09, 0x9e, 0xf1, 0xfb, 0xe1, 0x6b, 0x9b, 0x48, 0x5d, 0x8e, - 0xcb, 0xc0, 0xb3, 0x0f, 0x48, 0x67, 0x8e, 0x53, 0xd7, 0x51, 0x8e, 0xf4, 0x44, 0x1d, 0xcf, 0xc4, - 0x03, 0x0d, 0x64, 0x68, 0xb9, 0x62, 0x2b, 0x0b, 0x31, 0xf1, 0xc8, 0x22, 0xce, 0xbe, 0xc5, 0xa6, - 0x06, 0x4f, 0x43, 0x9a, 0x1b, 0xa5, 0xfc, 0xa6, 0xac, 0xe4, 0x94, 0x5e, 0x4b, 0x80, 0x65, 0xfe, - 0xb4, 0xeb, 0xd4, 0x4d, 0x0e, 0x66, 0x01, 0x1d, 0x2b, 0x31, 0x7d, 0xfc, 0x3a, 0xb2, 0x63, 0x45, - 0x5b, 0x3a, 0x64, 0xd1, 0xc8, 0x25, 0x1a, 0xa6, 0x6c, 0x96, 0xa5, 0x9c, 0x20, 0xfc, 0xf8, 0x8a, - 0x0d, 0x5b, 0x83, 0x19, 0xd4, 0xde, 0x01, 0xc3, 0x22, 0x06, 0x6c, 0x0b, 0x0a, 0x17, 0x9c, 0x77, - 0x1f, 0xc0, 0x53, 0x07, 0xc7, 0x6f, 0xe3, 0xdf, 0x61, 0x6e, 0x21, 0x0e, 0x8f, 0x26, 0x3b, 0x89, - 0x3b, 0x7b, 0x11, 0x7a, 0xf2, 0x88, 0x29, 0x98, 0xff, 0xec, 0x4b, 0x95, 0xee, 0x8b, 0xc7, 0xde, - 0x60, 0x0a, 0x49, 0x0e, 0x4f, 0xa3, 0x91, 0xa9, 0xfc, 0x97, 0x4a, 0x34, 0xe8, 0x00, 0x8f, 0x38, - 0xa6, 0x91, 0xe5, 0xde, 0xfe, 0x2d, 0x20, 0xde, 0xd8, 0x9b, 0x6a, 0x97, 0x14, 0x3a, 0xaf, 0x2f, - 0x47, 0x8a, 0x66, 0x22, 0x03, 0x68, 0x4b, 0x9b, 0xe4, 0xbd, 0x98, 0x2e, 0x5f, 0x21, 0x63, 0x5a, - 0x9a, 0x70, 0x27, 0x41, 0x46, 0x51, 0x27, 0xbb, 0xa1, 0xb6, 0xd5, 0x2d, 0xdf, 0x09, 0x64, 0xd5, - 0xdb, 0x0c, 0x2f, 0x4c, 0x00, 0x55, 0x45, 0xd1, 0x12, 0xd7, 0xdb, 0x81, 0x09, 0x40, 0x59, 0xba, - 0x93, 0xe8, 0xfc, 0x0c, 0x1a, 0x9e, 0x00, 0xd9, 0xf7, 0xc5, 0x68, 0x23, 0x16, 0x10, 0x51, 0xba, - 0xb0, 0x0c, 0x67, 0x56, 0x6d, 0xd4, 0x81, 0x88, 0xa1, 0x6f, 0xcc, 0x9c, 0x54, 0x3b, 0x5a, 0xc0, - 0x27, 0x90, 0xaa, 0xf1, 0x10, 0xf7, 0x28, 0x56, 0xec, 0x49, 0x05, 0x41, 0x88, 0x24, 0x9a, 0x8b, - 0x62, 0x5f, 0xe1, 0x9c, 0xa6, 0xd7, 0x23, 0x08, 0x80, 0xf5, 0x85, 0x4d, 0xce, 0xa4, 0xf5, 0x11, - 0xc0, 0x4b, 0xd3, 0x64, 0xe4, 0x2e, 0x08, 0x3b, 0xea, 0x33, 0x46, 0xaf, 0x92, 0xec, 0x61, 0xc8, - 0x14, 0xee, 0x6f, 0x90, 0x5a, 0xe8, 0x3e, 0xcb, 0xe1, 0x41, 0xd8, 0x5f, 0xab, 0xac, 0x5b, 0xe7, - 0x61, 0x09, 0x92, 0x62, 0xc8, 0x42, 0x12, 0x3f, 0x9d, 0x17, 0x11, 0x17, 0x1d, 0x89, 0x1c, 0x59, - 0x55, 0x42, 0xec, 0x37, 0x7b, 0xdc, 0x30, 0xe7, 0x01, 0x8f, 0x76, 0x6c, 0xda, 0xb0, 0x45, 0x50, - 0x02, 0x8d, 0x27, 0xea, 0x55, 0x04, 0x11, 0xf6, 0xf3, 0x3f, 0xca, 0xed, 0xef, 0x8c, 0xf6, 0xb6, - 0xd5, 0x83, 0x46, 0xa1, 0x56, 0xd9, 0xc5, 0xa5, 0x65, 0x45, 0x9c, 0x50, 0x3e, 0x9e, 0xc6, 0xd0, - 0x83, 0x8d, 0x13, 0xd0, 0x6a, 0x21, 0x30, 0x44, 0x70, 0x6a, 0x95, 0xf2, 0x48, 0x18, 0x84, 0xe5, - 0x60, 0xa4, 0xb3, 0xe5, 0x74, 0xe0, 0x8a, 0x47, 0x58, 0x82, 0x89, 0xb7, 0x16, 0xc0, 0x1a, 0x0f, - 0x0f, 0x35, 0x56, 0xa3, 0x0c, 0xdb, 0x12, 0xc0, 0x02, 0x8f, 0x1a, 0x72, 0xd1, 0x73, 0xbf, 0xf0, - 0x67, 0x94, 0xaa, 0xc8, 0x73, 0x5b, 0x95, 0x61, 0x5a, 0xca, 0x41, 0xf5, 0xe9, 0xc6, 0x38, 0x21, - 0x67, 0x1b, 0xe7, 0xc5, 0x7b, 0x0d, 0x06, 0x60, 0x6d, 0x31, 0x40, 0x6e, 0xa5, 0xd6, 0xfa, 0xe1, - 0xd1, 0x85, 0x8e, 0x52, 0x2d, 0xf5, 0x06, 0x90, 0xf8, 0x55, 0xf9, 0x1e, 0x8e, 0x7f, 0xd5, 0xc7, - 0x32, 0x0a, 0x93, 0xb8, 0xe0, 0xe3, 0x1c, 0xe1, 0xa0, 0xfe, 0xa6, 0x11, 0x4b, 0x08, 0x14, 0x47, - 0x10, 0x56, 0xc5, 0x62, 0x38, 0x22, 0x12, 0xfc, 0x2b, 0x9a, 0x9e, 0xf2, 0x19, 0xe7, 0xa4, 0xa2, - 0x0f, 0xb8, 0x32, 0xeb, 0x42, 0x77, 0x3c, 0xb2, 0x41, 0xbf, 0x3c, 0x05, 0x19, 0xf3, 0x6a, 0x50, - 0x74, 0x41, 0x0e, 0x02, 0xab, 0x1a, 0xc7, 0x69, 0x04, 0x76, 0xb4, 0xb2, 0x45, 0x6f, 0x05, 0x92, - 0x77, 0x83, 0x9b, 0xc2, 0x4b, 0xeb, 0x30, 0xf1, 0x8e, 0xf0, 0x2c, 0xa8, 0x52, 0xdf, 0xcf, 0x0f, - 0xd4, 0x63, 0xb7, 0x55, 0x9e, 0x8d, 0xd9, 0xc0, 0xef, 0x02, 0xaa, 0x74, 0x76, 0x43, 0x4b, 0x60, - 0x53, 0x04, 0xce, 0x21, 0xa5, 0xa0, 0x1c, 0x48, 0xca, 0x64, 0xe3, 0xc7, 0x18, 0xc2, 0x67, 0x95, - 0xba, 0x85, 0xe9, 0x87, 0xee, 0xd8, 0x03, 0x07, 0xc4, 0xe7, 0x6a, 0xf8, 0x83, 0xb4, 0xbc, 0xb6, - 0x82, 0x9e, 0xc9, 0x1e, 0xe3, 0xa9, 0x36, 0x22, 0x77, 0xc4, 0x98, 0x3c, 0x50, 0xfb, 0x6e, 0xd9, - 0x42, 0x2a, 0x48, 0xb6, 0xe8, 0x33, 0x7c, 0xc4, 0x30, 0xd7, 0xc0, 0x59, 0x6d, 0x5c, 0x74, 0x93, - 0x8b, 0x70, 0x28, 0x25, 0xcc, 0x52, 0x3d, 0xb1, 0xa8, 0xa6, 0x60, 0x39, 0x3a, 0x2d, 0xf6, 0x53, - 0x0e, 0x34, 0x28, 0xe1, 0x2b, 0x89, 0x08, 0x27, 0x3a, 0x28, 0x51, 0xef, 0x20, 0xf9, 0x9c, 0x36, - 0xb1, 0x2c, 0xeb, 0x6a, 0xeb, 0x60, 0x08, 0x0b, 0x25, 0xac, 0x34, 0x4d, 0x21, 0xea, 0x2d, 0x27, - 0x98, 0x62, 0x14, 0x68, 0x41, 0x94, 0x66, 0x20, 0x0d, 0x52, 0x32, 0x0d, 0x71, 0x68, 0x1a, 0x44, - 0x13, 0x47, 0xda, 0x22, 0xd6, 0xf5, 0x3a, 0x3a, 0x05, 0x9f, 0xfc, 0x62, 0xbc, 0x76, 0xd9, 0x37, - 0x7f, 0x73, 0x2b, 0x8d, 0x83, 0xa5, 0x81, 0xf3, 0x98, 0x95, 0x56, 0x99, 0x19, 0x73, 0xd7, 0x24, - 0xf7, 0x62, 0x79, 0xf5, 0x7b, 0x2e, 0x05, 0x41, 0x65, 0x72, 0xfb, 0x6a, 0xd1, 0xd2, 0xe9, 0x9c, - 0x08, 0x53, 0x8d, 0x08, 0x84, 0x27, 0xe7, 0x6a, 0xda, 0x99, 0xf2, 0xbf, 0x13, 0xb4, 0x1f, 0xa8, - 0x5f, 0x21, 0x40, 0xc0, 0x64, 0xb4, 0x0a, 0x6a, 0x2f, 0x88, 0x09, 0xff, 0x82, 0x19, 0x9b, 0xec, - 0x4f, 0xa0, 0xdf, 0x73, 0xb2, 0x41, 0x00, 0x09, 0xa6, 0xff, 0x38, 0x58, 0x68, 0x44, 0xe0, 0x67, - 0xda, 0xd7, 0x57, 0xd9, 0x9c, 0xf6, 0x0a, 0xd6, 0x9f, 0x6a, 0x3b, 0x98, 0x59, 0xdd, 0xdf, 0xe2, - 0x10, 0x56, 0xd5, 0xf3, 0x51, 0x20, 0x7e, 0xc5, 0x78, 0x0d, 0x18, 0xcf, 0x8f, 0x0c, 0x01, 0xf2, - 0xaa, 0xa2, 0x05, 0x9c, 0x65, 0x8e, 0x10, 0x86, 0x0a, 0x2c, 0x6c, 0x45, 0x7b, 0x6d, 0x03, 0xdf, - 0x57, 0xd3, 0x36, 0x21, 0xee, 0xd1, 0xd1, 0x81, 0x5e, 0x27, 0x86, 0xbc, 0x76, 0x70, 0x85, 0xe0, - 0x95, 0x46, 0xc7, 0xc8, 0x8b, 0x95, 0x28, 0x39, 0xc8, 0x55, 0xf9, 0x61, 0x7c, 0xd5, 0x37, 0x48, - 0xad, 0x68, 0x1c, 0x4e, 0x84, 0x38, 0x48, 0x34, 0xad, 0x24, 0xab, 0xfa, 0x1d, 0x6f, 0xda, 0x2e, - 0x41, 0xc4, 0xcc, 0x5c, 0x3b, 0xaf, 0x32, 0xb7, 0x13, 0x3d, 0x0a, 0x44, 0x83, 0x01, 0x78, 0x07, - 0xfe, 0x6f, 0xae, 0xfe, 0x11, 0xa4, 0x29, 0x54, 0x7d, 0x83, 0x8a, 0xd4, 0xed, 0xba, 0x93, 0x13, - 0x60, 0x3a, 0xd4, 0xa9, 0xa4, 0x63, 0x3e, 0x06, 0x81, 0xa0, 0x31, 0x8b, 0xc2, 0x25, 0x70, 0xaa, - 0xc8, 0x41, 0xcd, 0xce, 0x55, 0x9b, 0x6a, 0x6f, 0x75, 0x01, 0xcb, 0xd4, 0xde, 0x6b, 0xcc, 0x38, - 0xe5, 0x14, 0x18, 0xe4, 0x53, 0xac, 0x26, 0x08, 0x1e, 0x07, 0x78, 0x3c, 0xd4, 0x17, 0xdd, 0x40, - 0x50, 0x3c, 0x94, 0x46, 0x6b, 0xc4, 0xf3, 0x7b, 0xdd, 0x2d, 0xe3, 0xe9, 0x0e, 0x23, 0x44, 0x39, - 0xbc, 0x97, 0xa4, 0xa0, 0xda, 0x84, 0x20, 0xec, 0x94, 0xce, 0x0e, 0x04, 0xd4, 0xb0, 0x61, 0xb4, - 0x4f, 0xa7, 0x08, 0x71, 0xd6, 0x8e, 0x48, 0x6f, 0x88, 0xd4, 0x19, 0x60, 0x0a, 0x91, 0x77, 0x99, - 0xbb, 0xce, 0x30, 0xb8, 0x36, 0x1b, 0x0c, 0x13, 0x0e, 0x2d, 0x79, 0xc6, 0xe6, 0x79, 0xa4, 0xd7, - 0x4d, 0xea, 0x8e, 0xa2, 0xc1, 0x40, 0xbd, 0x2b, 0xde, 0x04, 0x78, 0xa6, 0x59, 0x8a, 0x10, 0xac, - 0xc3, 0xf6, 0x53, 0x71, 0xfe, 0x79, 0x0f, 0x79, 0x37, 0xd5, 0xbf, 0xdd, 0xab, 0xad, 0xac, 0x9e, - 0x12, 0xac, 0xbd, 0xd5, 0x06, 0x26, 0x35, 0xab, 0xb1, 0x0d, 0x26, 0x5e, 0x87, 0x3a, 0xa0, 0x07, - 0xb0, 0xb5, 0x72, 0xc8, 0xad, 0x43, 0x2b, 0x87, 0xb1, 0x91, 0xf4, 0x1c, 0x42, 0xd8, 0x51, 0xa6, - 0x6e, 0xf6, 0xa7, 0xff, 0x53, 0xd8, 0xa5, 0x11, 0xce, 0x2c, 0x01, 0xf4, 0x1d, 0x22, 0x23, 0x4d, - 0xcb, 0x27, 0x61, 0x06, 0xdb, 0x9d, 0x3c, 0x99, 0x0c, 0x5e, 0x1f, 0xca, 0x13, 0xde, 0x97, 0xdf, - 0xbd, 0x28, 0x72, 0xdc, 0x2d, 0x69, 0x9c, 0x3b, 0x6a, 0xa2, 0x0c, 0x5c, 0xf6, 0xfa, 0x2f, 0xc5, - 0xe6, 0xd6, 0x6c, 0xcd, 0x1a, 0xfe, 0x39, 0xed, 0x31, 0x72, 0x26, 0xbb, 0xa5, 0xfd, 0x2a, 0x97, - 0x0a, 0xdb, 0xa5, 0x54, 0xb1, 0x44, 0x00, 0x3f, 0x9b, 0x79, 0xa2, 0xda, 0xc3, 0xc1, 0x4d, 0xdf, - 0x70, 0x43, 0xc9, 0x0b, 0xdb, 0x4a, 0x24, 0xf7, 0xba, 0x4b, 0xac, 0x46, 0x78, 0x42, 0x3b, 0x66, - 0xe3, 0x2d, 0x3a, 0x42, 0x9a, 0x84, 0x3c, 0x5b, 0x36, 0x6f, 0x66, 0x14, 0x58, 0xec, 0x60, 0x4b, - 0x67, 0xfb, 0x6a, 0x34, 0x2c, 0x6a, 0x15, 0xb7, 0xc6, 0x7b, 0x0a, 0xe3, 0x5b, 0x9a, 0xcd, 0x84, - 0x2e, 0xab, 0x18, 0x8f, 0x08, 0x07, 0xe2, 0x25, 0xb6, 0x3d, 0x21, 0x0f, 0x59, 0xb7, 0x92, 0xaa, - 0x4f, 0x79, 0xcd, 0x60, 0x7e, 0x0a, 0x0a, 0x85, 0xff, 0x4d, 0x0d, 0x01, 0x0f, 0xe2, 0xcf, 0x97, - 0xee, 0x13, 0x75, 0xfc, 0x91, 0x80, 0x0a, 0x96, 0x86, 0x6c, 0x88, 0x09, 0xeb, 0x5c, 0x71, 0x6b, - 0x24, 0x51, 0xec, 0xd3, 0xa4, 0x83, 0x14, 0x47, 0x8b, 0xa0, 0x21, 0x95, 0x38, 0xf3, 0x0f, 0x56, - 0x81, 0xb5, 0x93, 0xfe, 0xe1, 0x63, 0x8f, 0x88, 0x6b, 0x85, 0x38, 0xce, 0x3c, 0x5c, 0xea, 0x46, - 0x73, 0xb8, 0x00, 0xd9, 0x5d, 0xa8, 0x3f, 0x76, 0xfd, 0xdc, 0x9e, 0x78, 0x90, 0x83, 0xd2, 0x29, - 0xb2, 0xbd, 0x86, 0x85, 0x58, 0x65, 0x33, 0xb7, 0x01, 0xab, 0x68, 0x84, 0xc5, 0xab, 0x7a, 0x77, - 0x8e, 0x4b, 0xf2, 0x27, 0x3d, 0x44, 0x3e, 0xa4, 0x4e, 0x19, 0x20, 0xde, 0xaa, 0xe2, 0x28, 0xf2, - 0x85, 0x86, 0xa6, 0x92, 0x2a, 0xce, 0x88, 0xae, 0x9f, 0xfe, 0xff, 0xac, 0x1a, 0xbf, 0x78, 0x69, - 0xe4, 0x98, 0xb5, 0xa1, 0x54, 0x97, 0x05, 0x25, 0x70, 0x3e, 0x67, 0x00, 0x96, 0xc5, 0xe0, 0x39, - 0x9c, 0x95, 0x92, 0x7d, 0xd7, 0x23, 0x83, 0xb9, 0xe2, 0xf3, 0xbb, 0x65, 0x98, 0xcc, 0xda, 0x47, - 0xf2, 0xd3, 0x59, 0x43, 0x34, 0x92, 0x32, 0x03, 0x70, 0x5f, 0x5f, 0xcd, 0x8c, 0xba, 0xc6, 0x97, - 0x48, 0x20, 0x18, 0x8e, 0xe2, 0xfc, 0x96, 0xc9, 0x6a, 0x4a, 0xcf, 0x4c, 0xf8, 0x68, 0x55, 0x3c, - 0x80, 0x8f, 0x69, 0x41, 0xe2, 0xf1, 0x08, 0x90, 0xe4, 0xa0, 0xf4, 0x63, 0x04, 0x4f, 0x64, 0x16, - 0xfc, 0xd5, 0x32, 0xf0, 0x87, 0x57, 0x60, 0x28, 0x85, 0xfc, 0x1f, 0x8c, 0x42, 0xec, 0xc1, 0x41, - 0x93, 0x32, 0x0b, 0x4b, 0x8e, 0xbc, 0x18, 0xc7, 0x15, 0xd4, 0xe1, 0x99, 0x3f, 0x69, 0x74, 0x05, - 0x44, 0xd1, 0xd7, 0x83, 0xc0, 0x01, 0x00, 0x34, 0x0e, 0x44, 0x56, 0xf5, 0xe2, 0x6c, 0xfe, 0x26, - 0xfb, 0x10, 0x2a, 0xfc, 0xea, 0xb6, 0x1f, 0xef, 0x62, 0xbe, 0x39, 0x0d, 0xa2, 0xfc, 0xea, 0x72, - 0x2d, 0xa6, 0x1e, 0x5c, 0x25, 0x0f, 0xcc, 0xe6, 0xad, 0xc5, 0xe6, 0x53, 0xc9, 0x1c, 0x46, 0x4a, - 0x89, 0xaf, 0x58, 0xf9, 0xa3, 0x09, 0x0b, 0x6e, 0xdf, 0x29, 0xcd, 0xfc, 0x4c, 0xb8, 0x9b, 0x3e, - 0x0e, 0x5b, 0xdb, 0x4e, 0x4b, 0x82, 0x36, 0x7b, 0x01, 0xe9, 0x83, 0x75, 0x5a, 0xfc, 0xe5, 0x90, - 0xc3, 0xe9, 0xc2, 0x6f, 0x15, 0x8f, 0x01, 0xc5, 0x8a, 0x0a, 0xea, 0x73, 0x02, 0xc0, 0xa4, 0x7a, - 0x18, 0x32, 0x30, 0xb9, 0x05, 0xb7, 0x03, 0x02, 0xef, 0xac, 0x2f, 0xdc, 0x5c, 0x40, 0x2a, 0x56, - 0x0b, 0xe5, 0xe3, 0x70, 0x85, 0x88, 0x1d, 0xd9, 0x7d, 0xa0, 0x40, 0x8d, 0x37, 0x85, 0xdf, 0xd0, - 0xca, 0xd6, 0x1f, 0xe7, 0x67, 0xfa, 0xc5, 0xb8, 0x92, 0xdd, 0x4f, 0x26, 0x4d, 0x77, 0xbe, 0x51, - 0xa8, 0x0b, 0x1d, 0x2c, 0xb4, 0x52, 0x33, 0x8d, 0x95, 0xaf, 0xf1, 0xbd, 0x6e, 0x91, 0xde, 0xac, - 0xf6, 0xba, 0x0a, 0x5c, 0x9b, 0x67, 0x20, 0x21, 0xd1, 0x33, 0xf7, 0x0f, 0xf4, 0xb1, 0x2a, 0x6b, - 0x5b, 0x30, 0x31, 0x01, 0x1d, 0xb3, 0x10, 0xec, 0xef, 0x05, 0x24, 0x72, 0xd6, 0xb5, 0x14, 0x48, - 0xef, 0xc7, 0x93, 0xf8, 0xf4, 0x76, 0x9a, 0x24, 0x01, 0xe3, 0x26, 0xca, 0x30, 0xa0, 0xc5, 0x1c, - 0x7e, 0xc2, 0x19, 0x7a, 0x87, 0xf9, 0x1d, 0xd3, 0xa4, 0xae, 0x81, 0xb3, 0x06, 0x2f, 0xbd, 0xc3, - 0xd5, 0xb6, 0xd7, 0xa7, 0x82, 0x8d, 0xab, 0x0e, 0x34, 0x9e, 0xe2, 0x37, 0x2b, 0x0b, 0x49, 0x94, - 0x1f, 0x25, 0x33, 0x27, 0xdf, 0x15, 0x3e, 0x2c, 0x90, 0x60, 0x19, 0x28, 0xcc, 0xd1, 0x0f, 0xc8, - 0x67, 0x5e, 0x5c, 0x63, 0x42, 0x14, 0x7c, 0xfb, 0x22, 0x21, 0x43, 0x7f, 0x31, 0x3a, 0xa5, 0xe4, - 0x87, 0x75, 0xfe, 0x08, 0x45, 0xa7, 0x32, 0xd9, 0x5f, 0x54, 0x93, 0x64, 0xce, 0xaf, 0xca, 0x4a, - 0x1e, 0xd9, 0xde, 0x5a, 0x64, 0x9f, 0x77, 0x93, 0x49, 0x54, 0x7a, 0xa9, 0x96, 0xc0, 0x0e, 0xf4, - 0x0c, 0xc2, 0x43, 0x33, 0x42, 0x92, 0x3f, 0x11, 0x96, 0x8b, 0x50, 0x11, 0xa6, 0x9c, 0xe7, 0x38, - 0x40, 0xaa, 0x19, 0x56, 0x6e, 0x6e, 0x6a, 0xe6, 0x9f, 0xa4, 0xbe, 0x10, 0xc5, 0xf8, 0x72, 0xe0, - 0xaf, 0xec, 0x51, 0xa0, 0xd9, 0x28, 0x08, 0xe9, 0x16, 0x1c, 0x50, 0x97, 0xe7, 0x18, 0x38, 0xd0, - 0x05, 0x35, 0x49, 0x72, 0xfa, 0xe4, 0x7b, 0x6e, 0x52, 0x92, 0x41, 0x1d, 0xcd, 0x08, 0x79, 0xd7, - 0x75, 0xd8, 0x9e, 0x02, 0x70, 0xaf, 0x09, 0x6c, 0xac, 0x1c, 0x33, 0xa1, 0x7e, 0x56, 0xcd, 0xad, - 0x4e, 0x4d, 0xc8, 0xae, 0xa4, 0xac, 0xbf, 0x29, 0x52, 0xa0, 0x1e, 0x29, 0x76, 0x08, 0xc1, 0x2d, - 0x7f, 0xcf, 0x2a, 0x63, 0xde, 0xd0, 0x38, 0xa0, 0xf8, 0xf5, 0xc0, 0x0e, 0x1b, 0xce, 0x32, 0xe4, - 0x67, 0xa6, 0x9d, 0xf1, 0xb5, 0x02, 0x91, 0xb0, 0x4c, 0xbf, 0xf9, 0x38, 0x33, 0x47, 0xf8, 0x82, - 0x8f, 0x17, 0xc0, 0xd8, 0xa6, 0xe4, 0x0c, 0x85, 0xa7, 0xc2, 0x81, 0xf3, 0x99, 0x6e, 0x8c, 0x4b, - 0x40, 0x9e, 0x7c, 0x31, 0x13, 0x03, 0x36, 0x33, 0x0c, 0x95, 0xcd, 0xe3, 0x35, 0x4c, 0x73, 0x83, - 0x3d, 0x80, 0xaa, 0xa7, 0xbb, 0x15, 0x1b, 0x7e, 0xbd, 0x23, 0x31, 0xe7, 0x50, 0x51, 0xe0, 0x51, - 0xaf, 0xf1, 0x74, 0x2d, 0x4f, 0xa7, 0x6b, 0x81, 0x5a, 0x07, 0xd6, 0x0f, 0xb4, 0xdf, 0x95, 0x5d, - 0xf8, 0x7c, 0x47, 0xea, 0x0c, 0x90, 0x3d, 0x73, 0x2d, 0x05, 0x07, 0x50, 0xc9, 0x92, 0x6c, 0xdf, - 0xd3, 0xbc, 0xcc, 0xb0, 0x60, 0xfe, 0xf4, 0x6b, 0xc9, 0x9c, 0x1d, 0x99, 0x1f, 0x45, 0x66, 0xe9, - 0x66, 0xb3, 0xd8, 0x3f, 0x87, 0x32, 0x09, 0x0d, 0x8e, 0xe4, 0xb6, 0x68, 0xd8, 0x5c, 0x13, 0x58, - 0x16, 0x27, 0xa3, 0x9a, 0x51, 0x3a, 0x8a, 0xac, 0x03, 0x7e, 0x65, 0x32, 0x0e, 0xff, 0xb6, 0x2b, - 0x8f, 0xe1, 0x65, 0x03, 0x1d, 0x84, 0x31, 0x7b, 0x08, 0x29, 0x55, 0xa7, 0x1f, 0x1b, 0x95, 0x1d, - 0x5e, 0x68, 0x8f, 0x6f, 0xc7, 0x52, 0x55, 0x09, 0x8a, 0x8e, 0xff, 0xd3, 0x5b, 0x41, 0x60, 0xb8, - 0x3a, 0x05, 0x5b, 0xb9, 0xe0, 0xbe, 0x0f, 0xd8, 0xf7, 0x01, 0xb5, 0xeb, 0xc9, 0xed, 0x8e, 0xe4, - 0x85, 0x69, 0x18, 0xdd, 0xa1, 0x27, 0xf0, 0x9a, 0x13, 0x51, 0xe7, 0x22, 0xdf, 0x04, 0xcd, 0xc3, - 0xd9, 0xa8, 0x73, 0xdb, 0xe8, 0xb7, 0x39, 0x66, 0x9b, 0x36, 0x15, 0xad, 0x14, 0xad, 0x9d, 0xf0, - 0x64, 0x69, 0xa3, 0x6a, 0xbb, 0x59, 0xfb, 0xce, 0x00, 0xac, 0x23, 0xb4, 0x7f, 0x3a, 0xa2, 0xf9, - 0x55, 0x4b, 0x7b, 0x0f, 0x9d, 0x5a, 0x2b, 0xc7, 0x5e, 0xb7, 0xfb, 0x21, 0x10, 0xf4, 0x0d, 0x2e, - 0x62, 0xca, 0x7b, 0x30, 0x0f, 0xdf, 0xa7, 0xf3, 0xd2, 0xf4, 0x6c, 0xd8, 0x14, 0x76, 0x02, 0x3b, - 0x43, 0x59, 0xd7, 0xa9, 0x19, 0x81, 0x1d, 0x65, 0xe8, 0xc3, 0x9b, 0x69, 0xf2, 0xd4, 0x73, 0xf3, - 0xf8, 0x84, 0xaa, 0xf9, 0x1e, 0xa9, 0x1e, 0xcd, 0x84, 0xc4, 0x45, 0xa6, 0x34, 0xf2, 0x8a, 0x93, - 0x3b, 0xb6, 0x2b, 0xc8, 0x49, 0x48, 0x1c, 0xd9, 0x70, 0x8e, 0xf2, 0x07, 0x2b, 0xf5, 0x22, 0x63, - 0x3f, 0x0c, 0x2b, 0xb7, 0xd6, 0x8a, 0x6f, 0x64, 0x41, 0x33, 0x7a, 0xd7, 0x02, 0x13, 0x50, 0xec, - 0x36, 0xa9, 0x6a, 0x31, 0x26, 0xe3, 0x00, 0xa7, 0x67, 0xbb, 0xac, 0x22, 0xee, 0xbc, 0x33, 0xb0, - 0x4f, 0xdf, 0x2b, 0x36, 0xdf, 0x8f, 0x1a, 0x6a, 0xc5, 0x21, 0x78, 0xd0, 0x8c, 0x5c, 0x71, 0xe5, - 0xde, 0xa3, 0x85, 0x39, 0x5b, 0x62, 0x3f, 0xea, 0xae, 0x03, 0x14, 0x67, 0x4e, 0xc7, 0x9b, 0x4a, - 0x5d, 0x26, 0xca, 0x1f, 0xdf, 0xa0, 0x8f, 0x18, 0x2b, 0xf4, 0x2d, 0x4a, 0xd3, 0x9c, 0x07, 0x7c, - 0xb7, 0xa6, 0x1e, 0xcb, 0xb6, 0x48, 0x02, 0x79, 0x6a, 0xf3, 0x67, 0xf4, 0xe2, 0xe7, 0x5f, 0x0e, - 0x3a, 0x27, 0xb5, 0xff, 0xc4, 0xef, 0x5b, 0xf6, 0x02, 0x64, 0x73, 0x94, 0x8c, 0x50, 0x29, 0x86, - 0xcc, 0x02, 0x6e, 0xc4, 0x70, 0xa8, 0x36, 0xc9, 0x3f, 0x32, 0xc3, 0x1d, 0x21, 0x54, 0x64, 0x9d, - 0xdc, 0x71, 0x30, 0xd3, 0x97, 0x4c, 0x4c, 0xd2, 0xfa, 0xb9, 0x80, 0x11, 0x12, 0x47, 0xa3, 0x5d, - 0x85, 0x61, 0xbe, 0x6c, 0x8c, 0xdc, 0x12, 0x59, 0x1d, 0xbb, 0x81, 0xe6, 0x5e, 0x99, 0xf9, 0x78, - 0xce, 0xe1, 0x8b, 0x4f, 0x6a, 0x01, 0xce, 0xb4, 0xc1, 0xb0, 0xf8, 0x50, 0x4c, 0x4d, 0x48, 0x1e, - 0xea, 0x94, 0x6f, 0xab, 0x26, 0xf8, 0x0c, 0x74, 0xd2, 0xd3, 0x75, 0x6a, 0x83, 0x96, 0xfd, 0xb4, - 0x5e, 0xfb, 0x06, 0x63, 0xf7, 0x1c, 0xa9, 0x15, 0xc9, 0x72, 0xc2, 0xf7, 0x36, 0x03, 0x66, 0xca, - 0x66, 0x3b, 0x8e, 0x39, 0x59, 0x51, 0x27, 0x87, 0xe7, 0xbb, 0x98, 0xc2, 0xb0, 0xe6, 0x1c, 0xb9, - 0x05, 0xb6, 0xde, 0x55, 0xbb, 0xb8, 0xff, 0x42, 0x79, 0xf1, 0xa3, 0x09, 0xa6, 0xe2, 0xc9, 0xa5, - 0x58, 0x42, 0x9a, 0xdb, 0x08, 0xd3, 0x29, 0x17, 0xc2, 0x91, 0x10, 0xdf, 0x3a, 0xb3, 0x41, 0x3a, - 0x27, 0x73, 0xf7, 0xc7, 0xd9, 0xa4, 0x58, 0xef, 0xd2, 0xcd, 0x2e, 0xe1, 0x42, 0xd4, 0x05, 0x7e, - 0x96, 0x8b, 0x26, 0x99, 0x7c, 0xfc, 0x34, 0x33, 0x18, 0x3b, 0x29, 0x71, 0x3f, 0x39, 0x7a, 0x4c, - 0xf0, 0x01, 0x20, 0xe0, 0x44, 0x5a, 0x88, 0xb6, 0xcc, 0xb6, 0xcd, 0x96, 0x8a, 0x1f, 0x9e, 0xcb, - 0x3c, 0x7f, 0x7e, 0x1a, 0x2c, 0xbf, 0x2a, 0xda, 0xd1, 0x91, 0x53, 0x20, 0x00, 0x10, 0xb4, 0x83, - 0x78, 0x8f, 0xeb, 0xc1, 0x0f, 0xe2, 0x10, 0x14, 0x5d, 0x27, 0x3a, 0x3d, 0x5e, 0x3e, 0x3d, 0xe5, - 0x7c, 0x84, 0xaa, 0x7c, 0x6a, 0xa8, 0x3d, 0x86, 0x0a, 0x79, 0xcc, 0xa1, 0x09, 0x2e, 0x96, 0x41, - 0x41, 0xc5, 0xce, 0x3e, 0x9d, 0x93, 0x20, 0xb0, 0x7a, 0x53, 0xfd, 0x10, 0xba, 0x2f, 0xe4, 0x0f, - 0xfd, 0xbf, 0x55, 0x23, 0x2b, 0x3a, 0x2d, 0xaa, 0x7e, 0xf1, 0xbc, 0x6d, 0x93, 0x57, 0xc7, 0x1b, - 0xd4, 0x28, 0x03, 0x8f, 0xae, 0x3c, 0x90, 0xb2, 0xb1, 0xff, 0x2c, 0x40, 0xa2, 0xd4, 0x0a, 0x55, - 0xde, 0xeb, 0xf7, 0x85, 0xad, 0x6e, 0x13, 0x6e, 0x55, 0x53, 0x06, 0xf1, 0x37, 0x2e, 0x50, 0x78, - 0xe0, 0x6f, 0x27, 0xc1, 0xbe, 0xc5, 0x81, 0xb3, 0x52, 0xd5, 0xc0, 0xe9, 0x98, 0xf5, 0x74, 0x5b, - 0x17, 0xdd, 0x84, 0xbc, 0xed, 0x06, 0x2c, 0xa3, 0xa4, 0x48, 0xc9, 0xf1, 0xa1, 0x9d, 0xf2, 0x48, - 0x23, 0x59, 0x09, 0xd5, 0x88, 0xf1, 0x79, 0xa2, 0x03, 0xe6, 0x8d, 0xe6, 0x3a, 0xb9, 0xd3, 0xeb, - 0xcb, 0xa6, 0x13, 0xd0, 0xef, 0xe3, 0x11, 0x71, 0x0e, 0x1b, 0xf3, 0xd3, 0xa9, 0xc3, 0xfb, 0xc6, - 0xbd, 0xf8, 0xd8, 0x99, 0x41, 0x81, 0x6f, 0xe8, 0x09, 0x7d, 0x0a, 0xcd, 0x91, 0xc0, 0xa2, 0x38, - 0x42, 0x5c, 0x53, 0x19, 0x02, 0x5e, 0x21, 0xab, 0xa1, 0xf1, 0xe8, 0x0d, 0xf0, 0x6d, 0x65, 0xab, - 0x4d, 0x39, 0xa4, 0x05, 0xda, 0x30, 0xc4, 0x4c, 0x94, 0x3a, 0xd8, 0x49, 0x00, 0x39, 0x85, 0xe4, - 0x91, 0x55, 0xf9, 0x40, 0x08, 0x22, 0x04, 0x1a, 0xa5, 0xe2, 0x48, 0x3d, 0x10, 0x76, 0xb4, 0x25, - 0x7f, 0x12, 0xb2, 0xfb, 0xda, 0xa5, 0xa9, 0x18, 0x28, 0x91, 0x1d, 0x86, 0x0f, 0xda, 0x10, 0x53, - 0xa9, 0x99, 0xc1, 0xc8, 0x02, 0x41, 0x3a, 0x42, 0xdc, 0x55, 0x21, 0xca, 0x6e, 0x8a, 0x75, 0x5b, - 0xe1, 0x26, 0xdf, 0x16, 0x48, 0x14, 0xc7, 0x01, 0xad, 0x2f, 0x75, 0x49, 0x64, 0x44, 0xff, 0x5a, - 0xc6, 0x70, 0x89, 0x10, 0x79, 0xac, 0x0e, 0x2f, 0xaf, 0x6d, 0x57, 0xf5, 0x59, 0x6c, 0x79, 0x1b, - 0x9d, 0x4c, 0x39, 0xb3, 0xa5, 0xbf, 0xb6, 0xe0, 0x78, 0x76, 0x81, 0x4f, 0xde, 0xea, 0xa0, 0xdd, - 0x63, 0x25, 0x7c, 0x4f, 0x1d, 0x53, 0x2d, 0x2d, 0x4d, 0x61, 0x72, 0x86, 0x07, 0x6e, 0xd3, 0x23, - 0xe3, 0x79, 0xc4, 0x27, 0xc5, 0xfe, 0x5d, 0x05, 0xb1, 0xe3, 0x45, 0x1b, 0x6c, 0xd7, 0x1e, 0x8f, - 0x62, 0xc2, 0x85, 0x0d, 0x2c, 0xbe, 0x25, 0xc5, 0x38, 0xe9, 0xa2, 0x80, 0x34, 0x4f, 0x4e, 0x30, - 0xff, 0xaf, 0x16, 0x4c, 0x8b, 0xd0, 0xb1, 0x0e, 0x3f, 0x4e, 0xf9, 0x0d, 0x4e, 0x1d, 0x95, 0x49, - 0x66, 0xcf, 0xa0, 0x8f, 0xa3, 0xf6, 0x35, 0xfa, 0x88, 0xa1, 0xf9, 0xfc, 0x34, 0x71, 0xd6, 0xfe, - 0xbc, 0x21, 0x6f, 0xbe, 0xc4, 0xca, 0xd7, 0x85, 0xa3, 0x65, 0x10, 0x5c, 0x46, 0xc9, 0xbd, 0xce, - 0xbf, 0xcc, 0x4c, 0x3c, 0x7e, 0x2a, 0x28, 0x09, 0x6a, 0x73, 0x16, 0x35, 0xf7, 0xe3, 0x4e, 0x8a, - 0xbb, 0x7a, 0x54, 0x2c, 0xe1, 0x18, 0x1c, 0x90, 0x14, 0xe7, 0x5a, 0xe8, 0xd9, 0xc9, 0x29, 0x20, - 0x12, 0x5e, 0x0a, 0xcf, 0xdc, 0xcd, 0x16, 0x86, 0xde, 0x72, 0x0e, 0x41, 0x52, 0x91, 0x74, 0x4c, - 0x68, 0x50, 0xc1, 0x91, 0xcc, 0x92, 0xca, 0x42, 0x8a, 0x6a, 0x1a, 0xfd, 0x37, 0x70, 0x61, 0xab, - 0x18, 0x21, 0x07, 0x0e, 0xc5, 0x62, 0x02, 0xc8, 0xf8, 0xe5, 0xa3, 0x94, 0x38, 0xff, 0x40, 0xbf, - 0xee, 0x77, 0xa1, 0x5f, 0x19, 0x91, 0x26, 0x72, 0xc0, 0x32, 0x1b, 0x8a, 0xab, 0xc3, 0x2a, 0x00, - 0x50, 0xee, 0xd9, 0xc9, 0xa4, 0x07, 0x04, 0x7c, 0xa1, 0xd7, 0xbb, 0xba, 0x46, 0x64, 0xbc, 0x07, - 0x00, 0x30, 0x02, 0x1d, 0xe4, 0x64, 0xc9, 0x0d, 0x2a, 0xfc, 0x3a, 0xdb, 0xeb, 0x73, 0x54, 0x2a, - 0x97, 0x48, 0xa3, 0x06, 0xe7, 0x36, 0x1c, 0xae, 0xbb, 0xe2, 0x3a, 0xa7, 0x4f, 0xa4, 0x39, 0x67, - 0xc3, 0xab, 0x1f, 0x13, 0x30, 0xa2, 0x5c, 0x49, 0x52, 0x04, 0xf5, 0x46, 0x74, 0x50, 0xae, 0xa8, - 0xd3, 0xae, 0x33, 0x84, 0x9f, 0x8c, 0x27, 0xfc, 0x42, 0xa4, 0x44, 0x4f, 0x2d, 0xa2, 0xb9, 0x84, - 0x43, 0x46, 0x87, 0x6b, 0x4e, 0xb3, 0xa4, 0x47, 0x5c, 0xd1, 0xc2, 0xac, 0x0f, 0x34, 0x99, 0x00, - 0xfc, 0xc9, 0xab, 0x85, 0x0e, 0x49, 0x9f, 0xf4, 0x95, 0x7f, 0xc3, 0x8f, 0x35, 0xd0, 0x3c, 0xbe, - 0x7c, 0xbc, 0x2d, 0xe4, 0xd7, 0x03, 0x62, 0x86, 0xd8, 0x4d, 0x3d, 0x65, 0xc0, 0xa3, 0x7d, 0xc1, - 0x83, 0x70, 0xd0, 0x3a, 0x1b, 0xd6, 0x32, 0x46, 0xf4, 0xb6, 0x95, 0x09, 0xf7, 0xca, 0x71, 0xa8, - 0x05, 0x7b, 0xbb, 0xcb, 0x8e, 0x8f, 0x11, 0x79, 0x1a, 0xd1, 0xdd, 0x41, 0x3f, 0x95, 0x2b, 0xdf, - 0x31, 0x11, 0xa2, 0xe4, 0x56, 0x04, 0x11, 0x40, 0x68, 0x6b, 0xa7, 0x22, 0xa3, 0xb7, 0x7a, 0x95, - 0x2d, 0xa7, 0xd3, 0x61, 0x68, 0xb5, 0x26, 0x82, 0x8f, 0xb6, 0x21, 0xb3, 0xae, 0x12, 0x1c, 0xa6, - 0x22, 0x2f, 0xd2, 0x5e, 0x28, 0x14, 0x01, 0x94, 0xb9, 0x56, 0x88, 0x9f, 0x56, 0xd0, 0xee, 0x02, - 0xd3, 0x58, 0x6c, 0x9d, 0xc0, 0x0a, 0xf8, 0x0b, 0xdf, 0xea, 0xf0, 0xf9, 0xe5, 0xbb, 0x64, 0x46, - 0x29, 0x67, 0xa8, 0xaa, 0xb0, 0xb4, 0x24, 0xb2, 0x85, 0x20, 0x14, 0x42, 0x73, 0xe0, 0x53, 0xed, - 0xa0, 0x0f, 0x23, 0x7f, 0xd0, 0x9e, 0x98, 0xd2, 0x69, 0x64, 0x9b, 0xb1, 0x9c, 0xcd, 0x06, 0x8f, - 0x64, 0x52, 0x45, 0x24, 0x13, 0x35, 0x34, 0xbf, 0x52, 0xff, 0x4a, 0x1f, 0x96, 0x6a, 0xc5, 0x38, - 0xb3, 0x50, 0xf6, 0xe3, 0xb0, 0x7b, 0x3f, 0x3e, 0x67, 0xa7, 0x5b, 0x4e, 0x91, 0x27, 0xb5, 0x46, - 0x71, 0x0c, 0x50, 0xb1, 0xfb, 0xb5, 0x90, 0x9a, 0x8d, 0xa5, 0x7b, 0x36, 0x11, 0x97, 0x56, 0xd8, - 0x31, 0x2c, 0x54, 0xe0, 0x12, 0x68, 0x1e, 0x86, 0x8c, 0x10, 0x36, 0xce, 0x12, 0x3b, 0xad, 0x8b, - 0xf1, 0x45, 0x97, 0xb8, 0x76, 0x19, 0x38, 0x99, 0x72, 0x87, 0x78, 0x1d, 0x6e, 0xe6, 0x75, 0x70, - 0x05, 0x3b, 0x1e, 0xfb, 0xe8, 0xba, 0x94, 0x67, 0x6e, 0x3e, 0x32, 0x86, 0xa3, 0x77, 0x07, 0xfc, - 0xa1, 0x05, 0x03, 0x97, 0x72, 0x7b, 0x9b, 0x8e, 0xd0, 0x63, 0x5a, 0xc4, 0x58, 0x1b, 0x5d, 0x95, - 0xe9, 0x49, 0x80, 0x7a, 0xfc, 0xcb, 0x08, 0xa4, 0x4d, 0xf6, 0x5d, 0x73, 0x77, 0xe1, 0x19, 0x1d, - 0xaf, 0x67, 0xa8, 0x6e, 0x37, 0xa9, 0x19, 0xe7, 0xa0, 0x17, 0x86, 0x62, 0x13, 0xde, 0x48, 0x81, - 0x72, 0x3b, 0xc2, 0xba, 0xdb, 0x4c, 0x9b, 0x0b, 0xab, 0x10, 0x2c, 0xf9, 0xc1, 0x0e, 0xc4, 0x2f, - 0x16, 0x35, 0x26, 0x91, 0xf2, 0xf8, 0x33, 0xc4, 0x01, 0x46, 0x3e, 0xb3, 0x21, 0x66, 0x62, 0xf7, - 0x5e, 0xae, 0x53, 0x7e, 0xdf, 0x62, 0xad, 0x96, 0x58, 0xc5, 0x52, 0x46, 0xb4, 0x13, 0x6a, 0x9f, - 0x69, 0x32, 0x55, 0xc8, 0xd4, 0xcd, 0x12, 0xa4, 0x6a, 0x7d, 0x31, 0x6a, 0x6e, 0x13, 0x56, 0xfc, - 0x8d, 0x2c, 0xe8, 0xf4, 0x54, 0x83, 0xaa, 0x2a, 0x00, 0xfd, 0xdd, 0xee, 0x95, 0x27, 0xbe, 0xcf, - 0x58, 0xb1, 0xa5, 0xdf, 0x1e, 0x2b, 0x18, 0x98, 0x3c, 0x6e, 0x1f, 0x5e, 0x93, 0xdf, 0x90, 0x2c, - 0x7d, 0xae, 0x89, 0xa7, 0x56, 0x59, 0x27, 0x5c, 0x15, 0x22, 0xf9, 0xf4, 0xdc, 0x71, 0x00, 0xfe, - 0x69, 0x9c, 0x34, 0x56, 0x07, 0x10, 0x1c, 0x47, 0x47, 0x6c, 0xa0, 0x43, 0x74, 0x68, 0x89, 0x8c, - 0x31, 0xd2, 0x69, 0x11, 0x94, 0x7f, 0x45, 0x01, 0x5a, 0x0e, 0x50, 0x75, 0xf6, 0x70, 0xa5, 0x5f, - 0xc1, 0x78, 0x45, 0xd8, 0x1d, 0x2b, 0xb6, 0xbc, 0x0f, 0xb8, 0xab, 0x13, 0x40, 0xf6, 0xb5, 0x43, - 0x82, 0x7d, 0xe5, 0x53, 0x63, 0x6a, 0xf7, 0xed, 0xf4, 0xf0, 0x56, 0x75, 0xdd, 0xc0, 0x8e, 0xa0, - 0x68, 0x66, 0xf1, 0xce, 0x08, 0x73, 0xbb, 0xd4, 0xff, 0x3e, 0x10, 0xbb, 0xca, 0x51, 0x48, 0x44, - 0xe7, 0x76, 0x37, 0x98, 0x0e, 0x80, 0xa5, 0x00, 0x46, 0xb3, 0x22, 0x02, 0x62, 0xe7, 0xef, 0x24, - 0x3a, 0xeb, 0x9c, 0x53, 0x30, 0x4f, 0x39, 0x38, 0x0b, 0xc0, 0x4c, 0x7b, 0xbf, 0xbf, 0xb4, 0xc8, - 0xf6, 0x5e, 0x69, 0x26, 0xfb, 0xdb, 0x0d, 0x80, 0x94, 0xd3, 0x4e, 0xa0, 0x51, 0x5b, 0xb2, 0x8d, - 0x5c, 0x31, 0xc9, 0x0f, 0x8c, 0xf5, 0xa9, 0x7f, 0x1b, 0xe8, 0x78, 0x51, 0x41, 0xdb, 0xf6, 0x40, - 0x62, 0x5d, 0x9b, 0x49, 0xbe, 0x09, 0x03, 0xc4, 0x43, 0xcc, 0xb1, 0xc5, 0xf8, 0x14, 0x9f, 0x05, - 0xa0, 0x4c, 0x93, 0x49, 0x3c, 0x7a, 0x05, 0xee, 0x35, 0x91, 0x38, 0xc7, 0xb0, 0x8a, 0xea, 0x1b, - 0x01, 0xcc, 0xc7, 0xb5, 0x0e, 0x02, 0xa8, 0xe2, 0xa3, 0x01, 0x81, 0x6c, 0x0a, 0x6a, 0xc3, 0x0d, - 0x0d, 0x4d, 0x58, 0x41, 0xcb, 0xfc, 0x36, 0x1e, 0x15, 0xf4, 0x89, 0xca, 0x1c, 0xbc, 0xd4, 0xd8, - 0x70, 0x36, 0x1d, 0x6d, 0x30, 0x7b, 0x28, 0x8d, 0x94, 0x4d, 0x8e, 0x02, 0xf3, 0x06, 0x44, 0x39, - 0xf4, 0xfe, 0xde, 0x2a, 0x45, 0xf2, 0xb5, 0xcb, 0x44, 0xe2, 0xd7, 0x41, 0x4f, 0xfb, 0x0a, 0x86, - 0xbf, 0x47, 0x21, 0x70, 0x17, 0x4d, 0x33, 0x5e, 0xd7, 0x00, 0x13, 0x47, 0xa3, 0x56, 0x90, 0x04, - 0x43, 0x5c, 0xf8, 0x61, 0x2b, 0xf8, 0x83, 0xe5, 0x5b, 0x48, 0x82, 0x0c, 0xbb, 0x92, 0xf5, 0xdc, - 0x03, 0xd3, 0x9b, 0xc6, 0x12, 0xb7, 0x34, 0x65, 0x28, 0xac, 0x45, 0x11, 0x61, 0x73, 0x58, 0x87, - 0xb2, 0xc7, 0x2c, 0xd8, 0x79, 0x28, 0xa5, 0x1f, 0xd3, 0x0b, 0xb6, 0x7a, 0x30, 0xa1, 0x9c, 0x25, - 0x23, 0x7b, 0x74, 0x17, 0xc4, 0xc6, 0x7c, 0xa9, 0x66, 0xeb, 0xe1, 0x2d, 0x74, 0x82, 0xc7, 0xe8, - 0xb3, 0xa6, 0xcd, 0x92, 0x15, 0x87, 0x0c, 0x2a, 0x0b, 0x04, 0x64, 0xf9, 0x3f, 0x81, 0x95, 0x5c, - 0xb2, 0x1c, 0x6d, 0xf7, 0xa4, 0x0b, 0xb9, 0xcd, 0xfe, 0x05, 0x9c, 0x4a, 0x66, 0xc3, 0xef, 0x0e, - 0x6b, 0xb9, 0xb2, 0x56, 0x1b, 0x82, 0x2f, 0xc1, 0x46, 0xbe, 0x31, 0xcb, 0x50, 0xdf, 0xa6, 0xe5, - 0xa8, 0x97, 0x2e, 0x13, 0xe2, 0xe3, 0x1d, 0x84, 0xa7, 0x4b, 0x45, 0x35, 0xb9, 0x6c, 0xa8, 0x1f, - 0x56, 0x3f, 0x30, 0xa8, 0x6c, 0x32, 0xb8, 0xae, 0xd0, 0x95, 0xd0, 0x5b, 0x8d, 0xec, 0x37, 0xb7, - 0xa7, 0x9f, 0xe6, 0x4f, 0xdc, 0xd1, 0x4a, 0xf9, 0xf0, 0x04, 0x6e, 0x93, 0x57, 0xbb, 0xbe, 0xf9, - 0xd2, 0x37, 0x2e, 0x14, 0x14, 0x54, 0xbe, 0xad, 0x9f, 0xad, 0xdd, 0x1c, 0x8e, 0x07, 0x6f, 0xb7, - 0x28, 0xc7, 0xe7, 0x5a, 0x5d, 0x70, 0x52, 0x96, 0x14, 0x5f, 0x44, 0xcc, 0xa0, 0xac, 0x0b, 0x2c, - 0xac, 0xe6, 0xe8, 0xba, 0x7a, 0x50, 0x29, 0x86, 0x88, 0xe7, 0x0d, 0x5c, 0xef, 0xa4, 0x87, 0x1b, - 0x71, 0xfd, 0xe9, 0x68, 0xb1, 0xae, 0xf6, 0xcd, 0xd7, 0xdf, 0x2a, 0xbf, 0x46, 0x45, 0xf0, 0x45, - 0xae, 0x1a, 0xef, 0x89, 0x31, 0x17, 0x1d, 0x37, 0xba, 0xed, 0x0a, 0x0c, 0xf5, 0x9f, 0x40, 0x4f, - 0x33, 0x80, 0x3a, 0xb4, 0x88, 0xa4, 0x30, 0x25, 0xe8, 0x4f, 0x03, 0xb4, 0x37, 0x12, 0x9d, 0x52, - 0x3e, 0xd5, 0xb8, 0x24, 0xdc, 0xd1, 0x35, 0xe6, 0xda, 0xa1, 0xd2, 0x02, 0x04, 0x58, 0x07, 0xdd, - 0xd0, 0x6a, 0x7b, 0xd6, 0x47, 0x0c, 0xaa, 0xcc, 0xe9, 0xf6, 0x11, 0xd3, 0xbd, 0xf7, 0x09, 0xab, - 0xd2, 0xf3, 0xd1, 0xda, 0x9c, 0xf0, 0x2f, 0x20, 0x14, 0x14, 0x78, 0xf5, 0x31, 0x7b, 0x19, 0x64, - 0x13, 0x1e, 0xbb, 0x18, 0x60, 0x1d, 0xcd, 0xa2, 0x52, 0x2e, 0x64, 0x79, 0xd2, 0xca, 0x81, 0xe5, - 0x6d, 0x4c, 0xe5, 0x52, 0xb5, 0x96, 0x0f, 0xc8, 0x80, 0x1a, 0x27, 0x69, 0x22, 0xef, 0x67, 0xde, - 0x7b, 0xf9, 0xaf, 0xfe, 0x34, 0x88, 0x1e, 0x2a, 0xb8, 0xbe, 0x10, 0xb7, 0x6e, 0xec, 0x73, 0x80, - 0x9d, 0xca, 0x48, 0xbd, 0xd3, 0xf7, 0x3d, 0xbb, 0xa8, 0x7c, 0x73, 0xbb, 0x1f, 0x2d, 0x1b, 0xd9, - 0x85, 0xf6, 0x16, 0x7e, 0xdd, 0x48, 0x87, 0x23, 0x95, 0xe3, 0x79, 0x07, 0xb9, 0xd9, 0x9f, 0xca, - 0x59, 0x2b, 0x7b, 0x82, 0x3e, 0x45, 0x00, 0x1f, 0xff, 0x01, 0x98, 0x56, 0x06, 0x0b, 0xc4, 0xe9, - 0x65, 0xf7, 0xac, 0x2a, 0x5d, 0x48, 0x9e, 0x6b, 0x02, 0x6a, 0x2d, 0xdf, 0x50, 0x87, 0x4b, 0x21, - 0x16, 0x74, 0x24, 0x99, 0xac, 0x2e, 0x11, 0x00, 0x44, 0xbb, 0x2e, 0x45, 0x65, 0xf7, 0x11, 0xd5, - 0xdb, 0xfc, 0x66, 0xed, 0xd9, 0x14, 0x54, 0x52, 0xc7, 0x44, 0xbb, 0x9b, 0x9b, 0x5d, 0x60, 0x69, - 0xbc, 0x43, 0xc3, 0x59, 0xdc, 0x99, 0xf5, 0x18, 0xdd, 0x92, 0x03, 0x24, 0xa8, 0xda, 0x5b, 0x91, - 0xc0, 0xf5, 0x51, 0x24, 0x8a, 0x75, 0x1b, 0x50, 0x86, 0x2d, 0x3a, 0xf7, 0x37, 0x36, 0x13, 0x1c, - 0x8c, 0x29, 0xae, 0xa1, 0x38, 0x5a, 0x89, 0x01, 0x01, 0x04, 0x57, 0x45, 0x54, 0x48, 0x01, 0x51, - 0x23, 0x84, 0x58, 0xb0, 0xd0, 0xdd, 0x6d, 0x49, 0x3e, 0xc9, 0x64, 0xa7, 0x46, 0x21, 0x17, 0x23, - 0x7e, 0xa2, 0x14, 0xab, 0x8b, 0xb5, 0x4b, 0x5a, 0x7d, 0x9e, 0x00, 0x5f, 0x56, 0x06, 0x86, 0x5f, - 0x5c, 0x7c, 0x04, 0xad, 0xb7, 0x14, 0x97, 0x25, 0xe0, 0x2a, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc9, 0xcd, 0x43, 0x2e, 0xde, 0xa8, 0x73, 0x19, 0xb8, 0xbd, 0xf5, 0xb4, 0x00, 0xd1, - 0x7c, 0xb0, 0xd4, 0x74, 0x3f, 0x21, 0x74, 0xc1, 0x50, 0x37, 0xc7, 0xfd, 0x9e, 0x5c, 0xdc, 0xe9, - 0x45, 0x86, 0x4c, 0x29, 0xe3, 0x15, 0x3f, 0x0c, 0x0f, 0x8d, 0xf0, 0x15, 0xdd, 0xa9, 0x02, 0x16, - 0x6c, 0xda, 0x01, 0x5a, 0xf9, 0x06, 0x33, 0x78, 0xfa, 0xdc, 0xc3, 0xcc, 0x19, 0xad, 0x25, 0xff, - 0x82, 0x25, 0x47, 0xea, 0x17, 0x04, 0x55, 0x5d, 0x56, 0x53, 0x69, 0x74, 0xd6, 0x2e, 0x91, 0xfc, - 0x3d, 0x6d, 0xcb, 0x39, 0x76, 0xf1, 0x08, 0x26, 0xba, 0xd9, 0x72, 0x21, 0xf4, 0x2d, 0x60, 0x2c, - 0x4f, 0x8e, 0x00, 0x3c, 0x99, 0x76, 0x4d, 0x0d, 0xda, 0x13, 0x9b, 0x31, 0x65, 0xda, 0x5d, 0xc4, - 0xbf, 0x97, 0x00, 0xc6, 0xa5, 0x63, 0xfc, 0xd0, 0x54, 0x3f, 0x54, 0x9e, 0x7b, 0x19, 0xd4, 0xcc, - 0x4c, 0xaf, 0x77, 0x33, 0xbb, 0x23, 0xe1, 0x95, 0x16, 0x4d, 0xde, 0xb6, 0xbf, 0xd4, 0x57, 0x8a, - 0x5d, 0x48, 0x12, 0x41, 0x31, 0xd3, 0x18, 0xc0, 0xdc, 0x23, 0xe2, 0xe6, 0xd5, 0x99, 0x50, 0xbe, - 0xa6, 0xe5, 0x9f, 0xe4, 0x90, 0xba, 0x1e, 0x9e, 0x26, 0xbd, 0x63, 0xcc, 0xb6, 0x4b, 0x36, 0x4d, - 0x91, 0x8c, 0x15, 0x65, 0x4b, 0x72, 0xa6, 0xda, 0xb9, 0x56, 0x7e, 0xf2, 0x57, 0xf2, 0x50, 0x2f, - 0xc2, 0xca, 0x84, -]]; +pub(crate) const BLOCKS: [&[u8]; 4] = [ + // Genesis block + &[], + // Issuance block + &[ + 0x04, 0x00, 0x00, 0x00, 0x27, 0xe3, 0x01, 0x34, 0xd6, 0x20, 0xe9, 0xfe, 0x61, 0xf7, 0x19, + 0x93, 0xb2, 0xc2, 0x72, 0x75, 0x6a, 0xce, 0xec, 0xdc, 0xbf, 0xd3, 0xe5, 0x43, 0xf7, 0x30, + 0xbc, 0x65, 0x83, 0x20, 0xba, 0xb6, 0x3e, 0x7e, 0x72, 0xc9, 0x1b, 0x5e, 0x23, 0x02, 0x56, + 0x76, 0xf9, 0x0e, 0xd8, 0x11, 0x9f, 0x02, 0x77, 0x8a, 0xa0, 0x8d, 0x1a, 0x56, 0x79, 0x47, + 0x66, 0x88, 0xbf, 0x6e, 0x8e, 0x5a, 0x4f, 0x57, 0x00, 0x23, 0xde, 0x3e, 0xf1, 0x3a, 0x05, + 0xe5, 0x9d, 0x2e, 0x94, 0x76, 0x6a, 0x3c, 0x7a, 0x94, 0x88, 0x5d, 0x72, 0x57, 0x04, 0x56, + 0x3c, 0x74, 0xd1, 0x7a, 0xbd, 0xf7, 0x53, 0x53, 0xdb, 0x1a, 0xf2, 0xfa, 0x49, 0x4d, 0x3f, + 0xa6, 0x0c, 0x20, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0xfd, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x80, 0x85, 0x20, 0x2f, 0x89, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x02, 0x51, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x40, 0xbe, 0x40, 0x25, + 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, + 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, + 0x40, 0xa8, 0x86, 0x5d, 0x61, 0x39, 0xb3, 0x39, 0x62, 0x94, 0xee, 0x42, 0xc5, 0xa6, 0x0b, + 0x63, 0x57, 0xca, 0x65, 0x8b, 0xa6, 0x76, 0xf2, 0xd6, 0xda, 0x8e, 0x00, 0xcf, 0x60, 0xe8, + 0x33, 0xa4, 0x55, 0xec, 0x7c, 0x99, 0x0f, 0xda, 0xd2, 0x46, 0xc0, 0x5b, 0x4a, 0x8f, 0xe5, + 0x2c, 0x6a, 0xb7, 0x00, 0xca, 0x49, 0xb4, 0xda, 0x80, 0xd3, 0x3d, 0x4d, 0x83, 0x7a, 0xd1, + 0x3a, 0x21, 0x3f, 0xfe, 0x71, 0xf5, 0x04, 0xd3, 0xaf, 0xeb, 0x10, 0x9d, 0xc2, 0x0d, 0xbd, + 0x3a, 0x9b, 0x2d, 0xf7, 0x7c, 0xd3, 0x2c, 0x7e, 0x7b, 0xeb, 0xb7, 0xaf, 0x60, 0xe4, 0xd3, + 0x41, 0x96, 0xe7, 0x2c, 0x0a, 0xf8, 0x99, 0x89, 0xbd, 0x70, 0x79, 0x54, 0x3b, 0xc7, 0x66, + 0x29, 0x91, 0x31, 0x97, 0xa6, 0x53, 0xfe, 0x24, 0x70, 0xf9, 0xf2, 0x41, 0x81, 0xac, 0x79, + 0x60, 0x43, 0x79, 0xed, 0x42, 0xba, 0x25, 0xdd, 0xf0, 0x05, 0xe8, 0xff, 0x14, 0x9e, 0xe8, + 0x34, 0x91, 0x5d, 0xc6, 0x9d, 0x6a, 0x2f, 0xc5, 0x70, 0x55, 0x65, 0x01, 0xf3, 0x74, 0x6f, + 0xe7, 0x37, 0x4a, 0x8f, 0x5d, 0x4d, 0xb6, 0x4e, 0x3b, 0xab, 0xc5, 0xc9, 0xa2, 0x86, 0x28, + 0x0e, 0xa6, 0x2d, 0xc0, 0xc4, 0x12, 0x74, 0xe9, 0x39, 0x34, 0xa6, 0xd8, 0xbc, 0x24, 0xdf, + 0x5a, 0x2b, 0x2d, 0xd3, 0xae, 0x62, 0x2f, 0x37, 0x38, 0xcb, 0x41, 0x26, 0xa5, 0xae, 0xed, + 0x94, 0x84, 0x51, 0xc2, 0xe7, 0xff, 0xbe, 0x27, 0x7b, 0x37, 0x94, 0xc0, 0xb5, 0x17, 0x08, + 0x0a, 0x00, 0xd4, 0x69, 0x74, 0x8f, 0x4e, 0x2c, 0xeb, 0x06, 0x2f, 0x1d, 0x61, 0xdc, 0x70, + 0xab, 0x97, 0xc9, 0xbd, 0x02, 0x68, 0xf0, 0xe1, 0x5e, 0xcb, 0x76, 0x25, 0x2c, 0x2c, 0xd2, + 0xf1, 0x8a, 0x03, 0xb3, 0x2f, 0x0b, 0x40, 0xa2, 0x56, 0xc4, 0x3a, 0xd0, 0xf7, 0xc4, 0xef, + 0x98, 0x52, 0x87, 0x54, 0x5b, 0x8e, 0xf8, 0xb3, 0x6e, 0x3d, 0x9e, 0xd6, 0x05, 0xb9, 0x49, + 0x54, 0x1b, 0xe0, 0xbc, 0xe7, 0x52, 0x71, 0x6c, 0x70, 0xdb, 0x0c, 0xf2, 0x06, 0x9e, 0x80, + 0x90, 0xde, 0x83, 0x0e, 0x8c, 0xee, 0xa3, 0x36, 0x99, 0xf0, 0xa8, 0x29, 0x58, 0x9e, 0xa8, + 0x4c, 0x90, 0x0d, 0x66, 0x06, 0xf9, 0x95, 0x21, 0x65, 0xa4, 0x90, 0x58, 0x9f, 0x61, 0x66, + 0x25, 0x8b, 0x7b, 0x13, 0xa1, 0x6b, 0x9c, 0xf4, 0x80, 0xfb, 0x34, 0xd1, 0x0f, 0x52, 0x2d, + 0xbd, 0x2a, 0xcd, 0x16, 0x7b, 0x7d, 0xd0, 0x6c, 0x4d, 0x2d, 0xbb, 0x51, 0x90, 0x7d, 0x4d, + 0x38, 0xbe, 0x06, 0x95, 0x18, 0xd4, 0x31, 0x6d, 0xa4, 0x67, 0xca, 0xe5, 0x35, 0x51, 0xaa, + 0xb4, 0x33, 0x46, 0x67, 0xc0, 0xa5, 0xb7, 0x07, 0x63, 0x64, 0xe8, 0x42, 0x8e, 0x81, 0xf4, + 0xc4, 0xcb, 0xde, 0x44, 0xe8, 0xf1, 0x80, 0xca, 0x7a, 0x70, 0x33, 0x64, 0xaa, 0x4d, 0x50, + 0xaf, 0xf3, 0x24, 0x27, 0xc4, 0x23, 0xfb, 0xf8, 0x47, 0x61, 0x83, 0x5c, 0x31, 0xeb, 0x69, + 0x73, 0x64, 0x4c, 0xe3, 0x8e, 0x24, 0x40, 0xd9, 0xe0, 0x46, 0x17, 0xbc, 0x0b, 0xa0, 0xcd, + 0x8d, 0x14, 0x96, 0x57, 0x21, 0x71, 0x97, 0x9c, 0xa7, 0x5b, 0x28, 0xb7, 0x5b, 0x71, 0xd2, + 0x7b, 0x77, 0x83, 0x09, 0x3a, 0xc4, 0x9c, 0x37, 0x38, 0xfb, 0xdf, 0xe1, 0xf9, 0xc7, 0x29, + 0xe0, 0x50, 0xbb, 0xfd, 0x7b, 0xa1, 0x53, 0xe5, 0x3b, 0x85, 0x61, 0x21, 0x66, 0xf0, 0xa2, + 0xb7, 0x65, 0x77, 0xd4, 0x5f, 0x0f, 0xf8, 0x5f, 0x4c, 0x6a, 0x90, 0x03, 0xc1, 0x2f, 0x8c, + 0x95, 0xa4, 0x36, 0x88, 0x51, 0x43, 0xd9, 0xa8, 0x78, 0x7f, 0x36, 0xb2, 0x27, 0x2f, 0x2c, + 0xd0, 0x21, 0xdc, 0x6a, 0x3f, 0x34, 0xdf, 0xac, 0x94, 0xf2, 0x8f, 0x13, 0x2e, 0x3d, 0x2a, + 0x4a, 0xf0, 0xdc, 0xa4, 0x1c, 0xc8, 0x59, 0x7e, 0xa0, 0x88, 0x7c, 0x02, 0x06, 0xf1, 0xbe, + 0x5a, 0xae, 0xc4, 0xf7, 0x72, 0x46, 0x97, 0xd9, 0x4b, 0x47, 0x9f, 0x9b, 0x93, 0x93, 0x71, + 0x8d, 0x80, 0xf7, 0xaf, 0xc7, 0xf9, 0xc9, 0x84, 0xd5, 0x9e, 0x87, 0x0f, 0x64, 0x33, 0x1f, + 0xd6, 0xf5, 0x90, 0x2d, 0x3a, 0xc3, 0x59, 0xf5, 0x25, 0xe6, 0xa5, 0xda, 0xf4, 0x21, 0x24, + 0x9d, 0xdb, 0x69, 0x86, 0x93, 0xec, 0x7d, 0x9b, 0xfd, 0x71, 0x19, 0xab, 0x05, 0xb6, 0xfd, + 0x5c, 0x6b, 0x17, 0x7e, 0xe5, 0xc4, 0x10, 0x38, 0xd7, 0x9b, 0x84, 0x94, 0x0d, 0xf1, 0xf5, + 0xe6, 0x79, 0x84, 0x3c, 0x04, 0x84, 0x2c, 0x6a, 0x62, 0xcf, 0xd6, 0x2f, 0xd0, 0x1b, 0xcc, + 0xc2, 0xc8, 0x2a, 0x67, 0x34, 0x52, 0xae, 0x88, 0x48, 0x47, 0x5f, 0x61, 0x4d, 0xba, 0x6c, + 0x53, 0xf1, 0x8b, 0x12, 0x54, 0xcc, 0xf0, 0x77, 0x89, 0x72, 0x98, 0x97, 0xed, 0x2e, 0xfa, + 0xef, 0x0b, 0x54, 0x69, 0x02, 0x69, 0x15, 0xa6, 0x5f, 0x11, 0xed, 0x04, 0x58, 0x02, 0x46, + 0xc4, 0xdc, 0x9c, 0xb6, 0xe1, 0xc8, 0xd8, 0xdc, 0xa3, 0x99, 0xea, 0x17, 0x96, 0x74, 0x7b, + 0x5f, 0xeb, 0x00, 0x02, 0x91, 0x04, 0x9e, 0xf4, 0xff, 0x6d, 0x0b, 0x29, 0x82, 0x37, 0x1a, + 0x4c, 0xa0, 0x71, 0x71, 0x20, 0xaf, 0xe4, 0x3b, 0x6e, 0x26, 0xb1, 0x89, 0x56, 0xb3, 0xb6, + 0x44, 0x2d, 0x2b, 0xb4, 0x6f, 0x22, 0xe4, 0x5d, 0xd8, 0x7d, 0x25, 0x60, 0xe7, 0xf4, 0xab, + 0x87, 0x0b, 0x97, 0x0a, 0xd4, 0x82, 0x48, 0x93, 0x0f, 0x1d, 0xcc, 0xc7, 0x69, 0xee, 0xc7, + 0xcf, 0x5d, 0x9b, 0xbe, 0x9f, 0x23, 0x4b, 0x06, 0x49, 0x88, 0xf5, 0xbd, 0xb5, 0xc3, 0xed, + 0x46, 0x2a, 0x17, 0xc8, 0x5c, 0x4e, 0xa4, 0x56, 0xf3, 0x62, 0x28, 0xe7, 0xd1, 0x66, 0x15, + 0x1c, 0xeb, 0x62, 0xc1, 0x64, 0xee, 0xb6, 0x98, 0x7a, 0x9e, 0x40, 0xaa, 0xa2, 0x7d, 0xca, + 0xb6, 0xf3, 0x82, 0x6d, 0x65, 0xfb, 0x82, 0x57, 0xd2, 0x64, 0xc8, 0xb8, 0x15, 0x1b, 0x68, + 0x94, 0x90, 0x7a, 0xd5, 0xd7, 0xe6, 0x42, 0x99, 0x6f, 0x46, 0xc8, 0x3d, 0x9e, 0x5d, 0x85, + 0x00, 0x7b, 0xed, 0x53, 0xde, 0x27, 0xa4, 0x66, 0x3f, 0xa3, 0xc2, 0xf8, 0x89, 0x69, 0x8a, + 0xac, 0xcc, 0x15, 0x5e, 0xdd, 0x63, 0xda, 0xe3, 0x5a, 0x1f, 0xe9, 0x81, 0x60, 0x20, 0x60, + 0xc1, 0xf9, 0xbb, 0x71, 0x87, 0x77, 0x79, 0xe0, 0x90, 0x3d, 0xef, 0x49, 0xa9, 0xf7, 0x66, + 0x70, 0x6f, 0x80, 0x88, 0xbe, 0x89, 0x73, 0x99, 0x3e, 0xb1, 0xf9, 0xd6, 0xe7, 0xb1, 0x9f, + 0x3e, 0xfe, 0x39, 0xed, 0x36, 0x18, 0xee, 0xc3, 0x41, 0xbb, 0x69, 0x9a, 0x8b, 0xb1, 0x13, + 0x2d, 0xd5, 0xab, 0xb7, 0xb6, 0x3b, 0xed, 0xdf, 0x5b, 0x08, 0xde, 0x7d, 0xe5, 0x5d, 0xfa, + 0x32, 0x91, 0x78, 0x03, 0x87, 0x77, 0x85, 0xc2, 0x92, 0x66, 0x51, 0x83, 0xdb, 0xa8, 0x3f, + 0xce, 0x17, 0xaa, 0xf5, 0xbb, 0x1e, 0x5c, 0x5f, 0x2e, 0xb6, 0x6c, 0x6d, 0x1a, 0x98, 0x84, + 0xe4, 0x69, 0x44, 0x9a, 0xf5, 0x6e, 0xd8, 0xd4, 0xc9, 0xd3, 0x42, 0x18, 0xca, 0x80, 0x1c, + 0x71, 0x8c, 0x62, 0x79, 0x59, 0xd9, 0x3b, 0xf3, 0xba, 0x90, 0x6b, 0x36, 0x2a, 0x7c, 0xf8, + 0xd3, 0xf4, 0xaa, 0xd9, 0x17, 0x59, 0xb1, 0xe6, 0x5a, 0x50, 0xcb, 0x0b, 0x6b, 0x19, 0x0c, + 0xe0, 0x5e, 0x67, 0x09, 0x42, 0x53, 0x71, 0x8b, 0xc2, 0x4e, 0x46, 0xc3, 0xff, 0xf1, 0x45, + 0x2b, 0x81, 0x52, 0x3b, 0xb4, 0x59, 0x20, 0xdc, 0x24, 0xea, 0xa5, 0xe7, 0xfc, 0x19, 0xc2, + 0xeb, 0x8c, 0x91, 0x99, 0x0a, 0x87, 0x43, 0xa7, 0x4c, 0x3e, 0x5a, 0xd7, 0x71, 0x5e, 0x3f, + 0x7c, 0xd0, 0x2f, 0x1a, 0xc0, 0xac, 0x73, 0xcf, 0xfc, 0x0a, 0x85, 0xe8, 0xd6, 0xb1, 0xa2, + 0xe0, 0x2e, 0x7a, 0xa8, 0x68, 0x68, 0x0a, 0x7d, 0x73, 0xd0, 0xc7, 0x6a, 0x3e, 0x7b, 0x6b, + 0x6a, 0x28, 0x59, 0x7a, 0x29, 0x85, 0x84, 0x04, 0xbb, 0x7c, 0x5b, 0x8f, 0x68, 0x6f, 0xb7, + 0x3e, 0xbf, 0xca, 0x97, 0x62, 0x7a, 0x73, 0xf3, 0xe3, 0x23, 0x39, 0xa6, 0xb1, 0x71, 0xd0, + 0x4e, 0xb5, 0x7a, 0x29, 0x51, 0xc9, 0x40, 0x45, 0x2f, 0x25, 0x58, 0x0c, 0x71, 0x61, 0x9c, + 0x73, 0x99, 0xc8, 0xab, 0xee, 0x67, 0x0d, 0x97, 0xd3, 0xdc, 0xa0, 0x90, 0x3b, 0xc2, 0x91, + 0x07, 0x1f, 0xf0, 0xe9, 0x97, 0xa9, 0xb5, 0x46, 0xdc, 0x63, 0xfc, 0xa3, 0x24, 0x1f, 0xeb, + 0xa8, 0x85, 0x66, 0x9a, 0xaf, 0x0f, 0x37, 0xe0, 0x8e, 0x01, 0x32, 0x35, 0xdb, 0xbe, 0xa3, + 0xbe, 0xf6, 0x2f, 0x1a, 0xd8, 0x1e, 0xc6, 0x40, 0xb9, 0x69, 0xea, 0x02, 0x95, 0x14, 0x9b, + 0xe9, 0x7d, 0x0c, 0xb7, 0x55, 0xf8, 0x87, 0xd9, 0x76, 0x3e, 0x15, 0xae, 0x83, 0xba, 0xe7, + 0x60, 0xc4, 0x0d, 0x32, 0x8a, 0x46, 0x9a, 0x56, 0xdc, 0xc1, 0x62, 0x9e, 0x76, 0xf6, 0x34, + 0xfb, 0xb9, 0xca, 0x32, 0xaa, 0xdd, 0x2b, 0x4e, 0xd2, 0xbc, 0x1a, 0xe4, 0x5d, 0x8c, 0x79, + 0xb1, 0x84, 0xd3, 0xfc, 0xd5, 0x40, 0xa9, 0x00, 0x97, 0x18, 0x39, 0xf7, 0x78, 0xa7, 0xfd, + 0x60, 0xb4, 0xfa, 0x3f, 0x8b, 0x74, 0x23, 0xb6, 0x90, 0x07, 0x32, 0xea, 0xde, 0x4d, 0xe9, + 0xbf, 0xe3, 0x78, 0x0a, 0xe0, 0x86, 0x21, 0x02, 0x2d, 0x45, 0xe0, 0x74, 0x20, 0xb7, 0x63, + 0x17, 0x2f, 0x09, 0xd3, 0xbe, 0x24, 0x6e, 0xef, 0x62, 0x06, 0x35, 0x1d, 0x0d, 0xe0, 0xb8, + 0xc4, 0xff, 0xc5, 0x3e, 0x4a, 0xf3, 0x04, 0x2b, 0x4f, 0xea, 0xf6, 0xfd, 0x8d, 0x28, 0x5e, + 0xdc, 0xe8, 0x1d, 0x39, 0x20, 0x43, 0x89, 0x5c, 0x37, 0x50, 0x38, 0x92, 0x00, 0x69, 0x46, + 0xc8, 0x55, 0x16, 0x70, 0x90, 0x73, 0x9e, 0xd8, 0x08, 0xdb, 0x3a, 0xcf, 0x5c, 0xc8, 0xdb, + 0x2b, 0xae, 0x8e, 0x7c, 0x51, 0xa9, 0x0c, 0x54, 0xc8, 0x15, 0x21, 0x26, 0x29, 0x92, 0x25, + 0x19, 0xa8, 0x31, 0x7c, 0x7d, 0x41, 0x32, 0x69, 0xe4, 0xfd, 0xf0, 0x0f, 0x12, 0x2e, 0x35, + 0x0d, 0x22, 0x04, 0xf5, 0x7e, 0x5c, 0xa7, 0x2e, 0xe1, 0xda, 0x11, 0xd2, 0xbf, 0x98, 0xe1, + 0x33, 0xf7, 0x3c, 0xb2, 0x4a, 0x1c, 0x01, 0x3e, 0xf7, 0xcc, 0x14, 0x2a, 0x51, 0xe6, 0x4f, + 0x43, 0xba, 0xd4, 0xad, 0xb7, 0x8c, 0x5c, 0x4a, 0x44, 0x03, 0x7f, 0x80, 0x0f, 0xe5, 0x58, + 0x35, 0x44, 0x11, 0x13, 0x63, 0xd6, 0x62, 0x48, 0x15, 0xa9, 0xb9, 0xdf, 0xf9, 0xc1, 0x70, + 0x80, 0xdf, 0x76, 0xda, 0x93, 0x50, 0xc3, 0x17, 0x5b, 0xb7, 0xdd, 0xfa, 0x14, 0x5a, 0xfa, + 0x2f, 0xd6, 0x4b, 0x54, 0xd8, 0x41, 0xab, 0x82, 0xc9, 0x12, 0xd8, 0x65, 0x71, 0x99, 0xff, + 0x07, 0x3b, 0x46, 0x84, 0xeb, 0x89, 0x04, 0x10, 0x6d, 0x5c, 0x1e, 0xe4, 0xcb, 0x13, 0xcd, + 0x37, 0x3b, 0xde, 0x78, 0xfc, 0x48, 0xbd, 0xb2, 0x85, 0x89, 0x45, 0x72, 0x96, 0x2a, 0x7d, + 0x69, 0x1a, 0x59, 0x6d, 0x03, 0x30, 0xb9, 0xce, 0x98, 0xb3, 0xc2, 0x23, 0xb4, 0x86, 0x2a, + 0x1e, 0x76, 0x49, 0xc0, 0x7b, 0xd6, 0x3c, 0x54, 0x76, 0x22, 0x1c, 0x8e, 0x86, 0x56, 0xeb, + 0xa3, 0x00, 0x73, 0x3c, 0xeb, 0x64, 0xa1, 0xd7, 0x4a, 0xeb, 0x4d, 0x98, 0x49, 0xcf, 0x93, + 0x72, 0xec, 0x35, 0x33, 0x8b, 0x97, 0xf4, 0xd0, 0xb7, 0x80, 0xf8, 0xc4, 0x85, 0x27, 0x1f, + 0x5e, 0x3c, 0xe9, 0x83, 0x3d, 0xbc, 0x99, 0x96, 0x3d, 0x63, 0xaa, 0x99, 0x7c, 0x83, 0x07, + 0x55, 0x78, 0x94, 0x7f, 0xa4, 0x48, 0x77, 0x38, 0xa3, 0xb8, 0xb7, 0x02, 0xee, 0x82, 0xac, + 0x27, 0x1e, 0xb4, 0x2a, 0xa9, 0x27, 0x98, 0xcf, 0x58, 0x80, 0xa6, 0x58, 0x15, 0xce, 0x17, + 0x87, 0xb4, 0xff, 0xaf, 0x22, 0xa8, 0xf3, 0x83, 0xf6, 0xd9, 0x04, 0xb3, 0xbb, 0xf1, 0x1a, + 0xa7, 0x00, 0x5c, 0x64, 0xfb, 0x99, 0x6f, 0x54, 0xda, 0x29, 0x1e, 0x4f, 0xae, 0x22, 0x24, + 0xce, 0xc8, 0x77, 0xc8, 0x7e, 0xe6, 0xfd, 0xce, 0x07, 0x7d, 0x0d, 0x93, 0xde, 0x13, 0xd3, + 0x08, 0xdb, 0xc1, 0xd5, 0xbb, 0x5a, 0x69, 0x34, 0xa5, 0x90, 0x44, 0x5b, 0xd2, 0x50, 0x4c, + 0x03, 0xb4, 0x35, 0x33, 0x4d, 0x63, 0xdb, 0xfb, 0xe7, 0xed, 0x07, 0x91, 0x1f, 0x7e, 0xa5, + 0x68, 0xa0, 0xe7, 0x80, 0x65, 0xf8, 0x79, 0xc7, 0xca, 0x80, 0x27, 0x41, 0x59, 0xa3, 0x38, + 0xc3, 0xae, 0xa5, 0x8c, 0x1d, 0x00, 0xb5, 0xbc, 0x6d, 0x16, 0xdf, 0x8e, 0x36, 0xa6, 0x24, + 0x8e, 0x1d, 0xca, 0x0c, 0x13, 0xed, 0x3d, 0xe1, 0x68, 0xc9, 0x0b, 0x8b, 0xd4, 0x17, 0xf2, + 0xb3, 0xec, 0x78, 0xa0, 0x7d, 0x35, 0x71, 0xe4, 0x24, 0xd1, 0xe5, 0xc1, 0x13, 0x2c, 0x7e, + 0xab, 0x86, 0x19, 0xfe, 0xbe, 0x22, 0xcf, 0xb7, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xae, 0x29, 0x35, 0xf1, 0xdf, 0xd8, 0xa2, 0x4a, 0xed, 0x7c, 0x70, 0xdf, 0x7d, + 0xe3, 0xa6, 0x68, 0xeb, 0x7a, 0x49, 0xb1, 0x31, 0x98, 0x80, 0xdd, 0xe2, 0xbb, 0xd9, 0x03, + 0x1a, 0xe5, 0xd8, 0x2f, 0xfd, 0xe0, 0x1c, 0x85, 0xa0, 0x45, 0xcc, 0x0e, 0xf3, 0x67, 0x88, + 0xe9, 0x1e, 0xdf, 0x18, 0xe6, 0x3a, 0x44, 0x94, 0x53, 0x74, 0x09, 0x4e, 0x08, 0x3c, 0x33, + 0xd3, 0x07, 0xd1, 0x72, 0xaf, 0x7f, 0x82, 0xec, 0x14, 0x05, 0x87, 0x12, 0x50, 0xc0, 0xc4, + 0x4f, 0x7c, 0x67, 0xdf, 0xd2, 0xe2, 0xc7, 0x38, 0x0d, 0x7c, 0x30, 0xf6, 0x80, 0x39, 0xe2, + 0x7d, 0x77, 0xb4, 0x42, 0xcb, 0x01, 0x63, 0xca, 0x95, 0x32, 0xa4, 0x18, 0x2c, 0x2b, 0xef, + 0xa0, 0x26, 0x88, 0xc6, 0x01, 0x97, 0x10, 0xba, 0xba, 0x3d, 0x80, 0xf2, 0xb8, 0x94, 0xfd, + 0x91, 0x75, 0xf2, 0x2c, 0x7f, 0xf6, 0xdf, 0x41, 0x2c, 0x8c, 0x41, 0xde, 0xb3, 0x94, 0xb9, + 0x89, 0xc2, 0x27, 0xf5, 0xc2, 0x03, 0x32, 0xb7, 0xa0, 0x30, 0x36, 0x98, 0x23, 0xc6, 0xac, + 0x19, 0xee, 0xa1, 0xe6, 0xe2, 0x68, 0xee, 0xaa, 0x70, 0x0c, 0x81, 0xe8, 0x87, 0x31, 0xbf, + 0x74, 0xaa, 0xd7, 0x37, 0xab, 0xf9, 0x15, 0x8c, 0x3e, 0xfc, 0x59, 0x16, 0x20, 0x4e, 0xe3, + 0xd4, 0x5e, 0x57, 0x28, 0xcf, 0x42, 0x7f, 0x1a, 0x86, 0x9d, 0x1c, 0x5d, 0x4a, 0xf1, 0x7a, + 0x17, 0x9e, 0xd1, 0x6f, 0xfd, 0xcd, 0xb4, 0xe9, 0x05, 0xdb, 0x8e, 0x10, 0x99, 0x25, 0x41, + 0x2c, 0xa6, 0xf6, 0x65, 0xd3, 0x4f, 0x3c, 0x3d, 0xc9, 0x2c, 0xf5, 0x40, 0xea, 0x6d, 0x7a, + 0x07, 0xdf, 0x9c, 0x3b, 0x3f, 0xe7, 0x45, 0xd8, 0xcf, 0x95, 0x33, 0x57, 0x39, 0x37, 0x61, + 0x36, 0x7c, 0xf7, 0xee, 0xb5, 0xc0, 0x75, 0x0b, 0xe3, 0x08, 0x02, 0xfe, 0x8f, 0x52, 0x14, + 0xa4, 0x1f, 0x99, 0xbe, 0x8d, 0xb8, 0x1f, 0x35, 0xf1, 0x96, 0x61, 0x31, 0x19, 0x20, 0xd8, + 0x1c, 0xdb, 0x99, 0x9f, 0x34, 0x68, 0xf0, 0x16, 0x05, 0x5d, 0x33, 0xbc, 0x8e, 0xa9, 0x50, + 0xda, 0x3f, 0x07, 0xc0, 0xf1, 0x02, 0x61, 0x88, 0xe2, 0x8b, 0x50, 0xc9, 0xad, 0x30, 0xab, + 0x00, 0x05, 0xea, 0x60, 0x4c, 0xcf, 0x86, 0xb0, 0x32, 0x40, 0x1a, 0x6b, 0x84, 0xf9, 0xee, + 0xee, 0x1c, 0x82, 0xf6, 0xbc, 0xd3, 0x88, 0x7c, 0xb9, 0x87, 0x88, 0x8c, 0x1e, 0xc2, 0x55, + 0x37, 0xc6, 0x60, 0xdc, 0xf8, 0x1d, 0xbc, 0x80, 0x06, 0x33, 0x33, 0x61, 0x99, 0xce, 0x7c, + 0x41, 0xea, 0xf2, 0xc8, 0x92, 0x0c, 0xd3, 0xd6, 0xf4, 0x1b, 0xa7, 0x8d, 0x97, 0xb9, 0x84, + 0x51, 0x65, 0x6e, 0xcb, 0x7a, 0x73, 0x97, 0x0a, 0xfd, 0xaa, 0x36, 0xb9, 0xb1, 0x5e, 0x8d, + 0xe1, 0xcf, 0x85, 0x2c, 0x5c, 0x41, 0xee, 0x6c, 0xbc, 0x0e, 0x76, 0x80, 0x5a, 0xa9, 0x3c, + 0x3f, 0xa9, 0x33, 0xc4, 0x3d, 0x12, 0x5d, 0x0b, 0x00, 0x68, 0x7d, 0x15, 0x30, 0x37, 0xe2, + 0x4d, 0x4f, 0x49, 0x30, 0x0c, 0x93, 0x2c, 0x18, 0xdd, 0x1f, 0x92, 0xab, 0xef, 0x0a, 0x2c, + 0x12, 0x4c, 0x4e, 0x99, 0xee, 0xcb, 0x95, 0x68, 0xf1, 0xf8, 0x88, 0x8c, 0xe1, 0x16, 0x2d, + 0x08, 0x6a, 0x5a, 0xb1, 0x87, 0xb4, 0x9f, 0x6b, 0x16, 0xb6, 0x69, 0xb0, 0x40, 0xbc, 0x9c, + 0x54, 0x61, 0xa2, 0x65, 0x97, 0x29, 0xa0, 0xfa, 0x12, 0x7b, 0xc5, 0xdb, 0xcf, 0x6a, 0x54, + 0xfc, 0xc8, 0x93, 0xd0, 0xdf, 0x06, 0x7a, 0xd7, 0x44, 0x0c, 0x80, 0x35, 0xe1, 0xcf, 0x18, + 0xc5, 0xb4, 0x19, 0xf3, 0x9c, 0x97, 0x3b, 0x1a, 0x91, 0xbd, 0x54, 0x0c, 0x37, 0x6b, 0x14, + 0x1d, 0xfe, 0x5c, 0xea, 0xb4, 0x3c, 0x71, 0x16, 0x21, 0x1e, 0xa0, 0x14, 0x13, 0x8d, 0xaf, + 0xbd, 0x24, 0xb2, 0x9a, 0xf4, 0x82, 0xab, 0x03, 0xb7, 0x77, 0x00, 0x6f, 0x99, 0x6f, 0xa4, + 0x89, 0xe7, 0x6f, 0xf9, 0xc2, 0x30, 0x3c, 0x1f, 0xe4, 0x69, 0x27, 0x53, 0x40, 0x16, 0xf1, + 0x9e, 0xae, 0xe7, 0xd1, 0xaf, 0x02, 0xf7, 0xb1, 0x13, 0x1a, 0x3e, 0x16, 0x1b, 0x2d, 0x18, + 0xfd, 0xbf, 0xb8, 0x61, 0xeb, 0xf7, 0x8d, 0xe8, 0x5b, 0xa0, 0xee, 0x0e, 0x56, 0xe6, 0xe1, + 0x5c, 0x4a, 0x09, 0x51, 0x41, 0xfa, 0x0c, 0xa8, 0xfc, 0x1a, 0x8d, 0x00, 0x14, 0x4d, 0x82, + 0x85, 0x9e, 0x62, 0x7b, 0x70, 0x06, 0x0b, 0x6a, 0xd7, 0xb1, 0x82, 0x46, 0x49, 0xcf, 0x3b, + 0x76, 0x57, 0xd0, 0x27, 0x44, 0xac, 0xb8, 0xb3, 0x74, 0x6b, 0x3a, 0x1c, 0x2b, 0xdb, 0x5c, + 0x9a, 0x57, 0x1c, 0x79, 0xee, 0x80, 0x1d, 0x6a, 0x8d, 0xbb, 0xfd, 0xc1, 0x70, 0x4e, 0x9b, + 0xa0, 0xd3, 0x29, 0x3e, 0xe1, 0x61, 0xe5, 0xe9, 0x69, 0x59, 0xf6, 0x3f, 0x55, 0x5e, 0x0f, + 0x8a, 0x4a, 0x99, 0x95, 0xa4, 0x97, 0x71, 0xd0, 0x72, 0x36, 0xb4, 0x20, 0x0a, 0xce, 0x69, + 0xab, 0xdc, 0xf9, 0xa4, 0x66, 0xd3, 0x0e, 0x81, 0xca, 0x93, 0xa9, 0xb9, 0xd1, 0x92, 0x41, + 0xa3, 0x09, 0x57, 0xcb, 0x05, 0x28, 0xaf, 0xea, 0x86, 0xe1, 0xf1, 0x9c, 0x7d, 0x38, 0x58, + 0x97, 0x6d, 0x50, 0xa6, 0xef, 0xf6, 0xbf, 0x8b, 0x29, 0x8d, 0xbb, 0x86, 0x48, 0x52, 0x58, + 0x8f, 0x88, 0x55, 0x8a, 0x05, 0x40, 0xa0, 0x7c, 0x72, 0xb6, 0xdd, 0xa9, 0x48, 0x77, 0xdc, + 0xee, 0xbc, 0xd3, 0x6f, 0x95, 0x9f, 0x51, 0xa8, 0x5d, 0x7a, 0x61, 0x06, 0x6a, 0x78, 0x1c, + 0xb9, 0xcf, 0xa9, 0xf7, 0x88, 0x81, 0x97, 0x53, 0x5f, 0x62, 0x58, 0xb2, 0x8d, 0x71, 0xce, + 0xf4, 0x05, 0x16, 0x8b, 0x4a, 0xa3, 0xdd, 0x35, 0xfa, 0xdd, 0xd9, 0x95, 0xde, 0xb5, 0x26, + 0x0d, 0xf8, 0x73, 0x26, 0xb6, 0x5c, 0x09, 0x2b, 0x49, 0xac, 0x66, 0x91, 0x33, 0x5f, 0x44, + 0xbe, 0x13, 0xd1, 0x64, 0x44, 0xe4, 0x86, 0x4a, 0xdd, 0xde, 0x2e, 0x2c, 0xe1, 0x89, 0x32, + 0x66, 0x14, 0x2e, 0x75, 0x74, 0xe6, 0x47, 0xf9, 0x74, 0x11, 0xe3, 0x00, 0x3f, 0x13, 0x07, + 0xbc, 0x09, 0x88, 0x4b, 0x51, 0xf6, 0x91, 0xb7, 0x45, 0xaf, 0xaf, 0x69, 0x7b, 0x4f, 0x77, + 0x7d, 0x2e, 0xc7, 0x5c, 0x2c, 0x4f, 0xae, 0x5a, 0x80, 0x6a, 0xef, 0xba, 0x3e, 0x2c, 0x93, + 0x63, 0x3a, 0xe4, 0xce, 0x75, 0xe1, 0xce, 0x38, 0xf7, 0x84, 0xe1, 0xfa, 0x6f, 0x3e, 0x20, + 0x17, 0x3a, 0xe7, 0x99, 0x24, 0xc1, 0x2f, 0x98, 0x32, 0xe4, 0xca, 0x89, 0x80, 0x9c, 0x68, + 0x50, 0xb1, 0x56, 0x7e, 0x5f, 0x51, 0x2c, 0x79, 0x05, 0x16, 0x10, 0xf0, 0x7e, 0x8b, 0x09, + 0xaa, 0xb1, 0xf5, 0xcf, 0xb9, 0x18, 0x14, 0x5e, 0xfd, 0xc0, 0x08, 0xbd, 0x65, 0x1f, 0x7c, + 0x1b, 0x2e, 0x0b, 0x7e, 0xc8, 0xbb, 0x32, 0x71, 0x83, 0x2c, 0x67, 0x82, 0x32, 0xfb, 0xcb, + 0x22, 0xe0, 0xff, 0x9b, 0xc1, 0x0a, 0x54, 0xe7, 0xdb, 0x86, 0x23, 0x00, 0x04, 0x08, 0x06, + 0xd1, 0x5a, 0x8f, 0xc9, 0xe3, 0x3a, 0x9b, 0x51, 0xeb, 0xfd, 0xb2, 0xf3, 0x27, 0x45, 0xa1, + 0xeb, 0xdc, 0xd0, 0xf9, 0xa7, 0x70, 0x23, 0xec, 0xc4, 0x29, 0xf1, 0xce, 0x52, 0x89, 0xa2, + 0xcb, 0xa0, 0x45, 0x6d, 0xa5, 0xa7, 0x73, 0xf4, 0xd7, 0x4c, 0x48, 0xd9, 0x15, 0xb9, 0xe9, + 0x87, 0x84, 0x30, 0xfe, 0x0d, 0xf6, 0x45, 0x88, 0xa4, 0x29, 0x26, 0x5d, 0xde, 0xc9, 0x0f, + 0xea, 0x4c, 0xb3, 0xe1, 0x48, 0x9f, 0x03, 0x99, 0x8f, 0xb6, 0x78, 0xa1, 0xaa, 0x7a, 0xa3, + 0x99, 0xb9, 0x0c, 0xcf, 0x22, 0xc5, 0x6e, 0x51, 0x82, 0xcb, 0x14, 0xbd, 0x5e, 0x03, 0xc1, + 0xe1, 0xc2, 0xec, 0x68, 0x09, 0xb0, 0x20, 0x06, 0xa9, 0x1c, 0x64, 0xdc, 0x8d, 0xac, 0x8c, + 0xbb, 0x1c, 0xb7, 0x6b, 0x80, 0x58, 0x92, 0x85, 0xe4, 0x2c, 0x98, 0xfa, 0x44, 0xd9, 0xe0, + 0xfd, 0x67, 0xb4, 0xa1, 0xfc, 0x02, 0xfd, 0x82, 0x0c, 0xac, 0xa3, 0x6f, 0x20, 0x54, 0x5e, + 0x22, 0xfe, 0xb1, 0x2d, 0xad, 0x46, 0x72, 0x5d, 0x78, 0xea, 0xb3, 0xd4, 0x65, 0xa5, 0xd2, + 0x85, 0xa2, 0xe9, 0xb2, 0xbc, 0xf6, 0xdf, 0x32, 0xa3, 0x2a, 0x91, 0x26, 0x1b, 0x18, 0x05, + 0x23, 0x19, 0xb5, 0x1e, 0x3c, 0x6a, 0x29, 0x7d, 0xc3, 0x6e, 0x52, 0xc7, 0xf2, 0x50, 0x29, + 0x67, 0xfb, 0xeb, 0x0a, 0xd0, 0xdb, 0xf7, 0x0c, 0x8a, 0x25, 0x70, 0xb8, 0xf7, 0x15, 0x88, + 0xfb, 0x28, 0x91, 0xef, 0xf0, 0xa2, 0x3c, 0x28, 0xdd, 0x2f, 0x4f, 0xd0, 0xf6, 0x26, 0xa4, + 0xdb, 0x65, 0x3b, 0x39, 0x61, 0x43, 0xc6, 0xf8, 0x68, 0xd6, 0x55, 0xe2, 0xd5, 0x85, 0x03, + 0x9c, 0x89, 0x1a, 0x11, 0xff, 0xf1, 0x37, 0x76, 0x8d, 0x05, 0xf7, 0x5c, 0x27, 0xb8, 0xd3, + 0x79, 0xad, 0x02, 0xca, 0xb0, 0x52, 0xec, 0x67, 0x89, 0xfb, 0xb1, 0x28, 0x72, 0xae, 0x32, + 0x2f, 0xde, 0x58, 0x2c, 0x8e, 0x6d, 0x87, 0xb3, 0x3f, 0xb8, 0x44, 0x7e, 0x81, 0x76, 0x29, + 0x4b, 0xe9, 0xdf, 0x99, 0xc7, 0x43, 0xde, 0xb2, 0xe3, 0xf9, 0xf9, 0x1c, 0x8a, 0x3b, 0x58, + 0x88, 0xf6, 0x0e, 0x1e, 0x7f, 0x9f, 0x49, 0xb0, 0x49, 0xba, 0xdb, 0x6d, 0x59, 0xdf, 0x42, + 0x8e, 0xa4, 0x13, 0x80, 0xb5, 0x01, 0x90, 0xd9, 0x6f, 0xf7, 0x2e, 0xba, 0x28, 0x7c, 0xa5, + 0x5f, 0x32, 0x43, 0x99, 0x64, 0xa9, 0xa5, 0x9b, 0xa8, 0xc0, 0x99, 0x03, 0x08, 0x02, 0x10, + 0xde, 0xa1, 0x75, 0xc9, 0x72, 0xa7, 0x66, 0x7a, 0x66, 0xca, 0xb9, 0x36, 0xd0, 0x98, 0xaf, + 0xdf, 0x2d, 0xc3, 0xac, 0x5c, 0xda, 0x1c, 0x66, 0xea, 0xb7, 0x3e, 0x89, 0x32, 0x54, 0xb3, + 0x57, 0xa5, 0x4f, 0x9a, 0xda, 0x6b, 0x11, 0x21, 0x79, 0x15, 0x7e, 0xb1, 0x92, 0x64, 0x07, + 0xe8, 0x8f, 0x40, 0x19, 0xbf, 0x7b, 0x34, 0x1d, 0xd5, 0xbb, 0x0e, 0xbc, 0xd3, 0xd9, 0x88, + 0x59, 0xe1, 0xd2, 0xe2, 0x8a, 0x25, 0xd8, 0x6c, 0x34, 0x8c, 0xab, 0xca, 0x24, 0x51, 0xbf, + 0xcd, 0x7d, 0x1a, 0x88, 0x0e, 0x41, 0x0f, 0xcf, 0x10, 0x62, 0x40, 0xf1, 0xef, 0x38, 0xf9, + 0x14, 0x52, 0x9a, 0x6f, 0xd3, 0xf9, 0x6b, 0x98, 0x4f, 0x19, 0x6c, 0x07, 0xec, 0xcf, 0x36, + 0x53, 0x77, 0x58, 0x23, 0x56, 0x08, 0x65, 0xdb, 0x24, 0x1c, 0xd2, 0xdb, 0x62, 0x5f, 0xdc, + 0x1c, 0x01, 0x49, 0xf6, 0x8c, 0x21, 0x6f, 0x71, 0x22, 0x5f, 0x02, 0xb5, 0x00, 0x49, 0x28, + 0x11, 0xc1, 0x3c, 0xba, 0x69, 0xdc, 0x7f, 0xcb, 0xc7, 0xa8, 0x8d, 0xf5, 0xee, 0xe4, 0x4b, + 0x53, 0x8d, 0x01, 0xa3, 0xd1, 0x82, 0x88, 0x28, 0x03, 0x42, 0xed, 0x20, 0x4b, 0xca, 0xb0, + 0x3a, 0x4e, 0x05, 0xee, 0x42, 0xc1, 0xd8, 0xd6, 0x2c, 0x64, 0xd6, 0x83, 0x03, 0xc1, 0x21, + 0x75, 0xd4, 0xce, 0x5d, 0x83, 0x9b, 0x74, 0x88, 0x51, 0x14, 0x9c, 0x5e, 0x73, 0xe5, 0xaf, + 0x1e, 0x12, 0xae, 0xb9, 0xc3, 0x2d, 0xd7, 0x09, 0xf8, 0x4b, 0x2e, 0x14, 0xcf, 0x94, 0x17, + 0xf6, 0xc8, 0x28, 0xbf, 0x6b, 0xd9, 0x33, 0x4c, 0x4c, 0xab, 0x2e, 0xa4, 0x3a, 0xe7, 0x6b, + 0x3d, 0xe0, 0xc4, 0x35, 0xc1, 0xb3, 0x7f, 0x9e, 0xcc, 0x65, 0xeb, 0xed, 0xd8, 0x15, 0x27, + 0x11, 0x66, 0x20, 0x68, 0xaa, 0xf3, 0xa0, 0xf3, 0xa8, 0x6f, 0x51, 0x63, 0x42, 0xcf, 0xba, + 0x10, 0x4f, 0x04, 0xdf, 0x64, 0x87, 0x88, 0xda, 0x49, 0x3e, 0xbf, 0xa2, 0x21, 0xd6, 0x31, + 0xac, 0x9f, 0xf2, 0xf8, 0xd1, 0x5c, 0xf8, 0x89, 0x72, 0x0c, 0x9e, 0x24, 0x30, 0xc1, 0x9f, + 0xd9, 0x36, 0xae, 0xcc, 0xcc, 0xbb, 0x09, 0xf2, 0xc3, 0x5c, 0xf9, 0x33, 0x87, 0x58, 0xb5, + 0x47, 0x69, 0x26, 0x23, 0x57, 0x98, 0xa4, 0x62, 0xa9, 0x0d, 0x70, 0xa7, 0x2d, 0xce, 0x6f, + 0x55, 0x05, 0x8f, 0x8b, 0x51, 0x5b, 0x18, 0xcd, 0x65, 0x9b, 0x47, 0xb6, 0xee, 0xd4, 0xfd, + 0x72, 0x28, 0xa0, 0x94, 0xa2, 0xd7, 0xd2, 0xef, 0x5a, 0xae, 0xc1, 0xf3, 0x6b, 0x5c, 0xa4, + 0x54, 0xdb, 0x48, 0xec, 0xfd, 0xe1, 0xe9, 0x5e, 0x8c, 0x62, 0x4c, 0xf7, 0x7a, 0x50, 0x62, + 0xeb, 0xdf, 0x54, 0x6a, 0x49, 0x6f, 0xdb, 0x5a, 0x02, 0x96, 0xf9, 0x1d, 0x57, 0x8e, 0xa1, + 0x61, 0xaa, 0xc7, 0xc7, 0xa8, 0x1b, 0xf5, 0x33, 0x3d, 0x65, 0x12, 0x45, 0x54, 0xfc, 0x9d, + 0x40, 0x17, 0x7c, 0xff, 0xf4, 0x2e, 0x0b, 0xbd, 0x56, 0x80, 0x5c, 0x83, 0x7f, 0xe6, 0x20, + 0x3f, 0x6e, 0x91, 0xa2, 0x2c, 0x58, 0x33, 0x69, 0xbc, 0x15, 0x10, 0xdc, 0x2d, 0xa3, 0xd6, + 0x06, 0xa9, 0xce, 0xa7, 0xec, 0xa8, 0x28, 0x14, 0xbe, 0xbe, 0x80, 0x82, 0x8f, 0x1d, 0x4c, + 0x24, 0x40, 0x26, 0x68, 0xdd, 0xa9, 0xaa, 0x4c, 0xd6, 0x87, 0x7e, 0x46, 0x7a, 0xaa, 0x43, + 0x56, 0x2e, 0xd9, 0x24, 0xda, 0x6f, 0xdd, 0x21, 0x10, 0x39, 0x48, 0xd5, 0x08, 0xec, 0x5d, + 0x1f, 0xe4, 0xdb, 0x64, 0xa1, 0x99, 0x8b, 0x11, 0x60, 0x2f, 0x4b, 0x44, 0x84, 0xd2, 0x69, + 0x52, 0xfd, 0xee, 0xe9, 0x5b, 0xb0, 0xa8, 0xc5, 0x07, 0x77, 0x15, 0xfe, 0x58, 0xf5, 0x62, + 0xfb, 0x60, 0x4c, 0x43, 0xe0, 0x17, 0x54, 0x42, 0x9f, 0x07, 0x7c, 0x2d, 0xc0, 0xa2, 0x6a, + 0x3e, 0x13, 0x0b, 0x78, 0x5c, 0x62, 0x98, 0x7f, 0x55, 0xe2, 0xc7, 0xb2, 0x58, 0xe1, 0x9d, + 0x53, 0xb5, 0xd9, 0xaf, 0x0c, 0x11, 0x70, 0x85, 0xca, 0x21, 0x87, 0x1a, 0x39, 0x5e, 0x67, + 0xd4, 0x51, 0x75, 0x2e, 0xa8, 0xea, 0x0d, 0x30, 0xc0, 0x93, 0x60, 0x18, 0x7f, 0xdf, 0x4a, + 0x41, 0xa0, 0x80, 0x1c, 0xed, 0x5c, 0xaa, 0x84, 0x4f, 0x2d, 0xec, 0x8c, 0xad, 0x24, 0xa1, + 0x4b, 0xa9, 0x52, 0x27, 0x8e, 0x70, 0xf6, 0xff, 0xc0, 0xb4, 0x13, 0x39, 0x75, 0xd4, 0xfc, + 0x9a, 0xbf, 0xff, 0x53, 0x3f, 0x44, 0x19, 0xd9, 0xa5, 0x28, 0x18, 0x5c, 0x38, 0xfb, 0x4c, + 0x3e, 0x5b, 0x40, 0xf2, 0xf4, 0xc2, 0x2c, 0x95, 0xdb, 0xd2, 0xe5, 0x5f, 0x87, 0x56, 0x63, + 0x28, 0xda, 0x07, 0xa9, 0x90, 0x83, 0x94, 0xdb, 0x56, 0x2c, 0xa3, 0xd0, 0xc4, 0x52, 0x6d, + 0x1f, 0xfa, 0x35, 0x4f, 0xba, 0xcf, 0x12, 0xf4, 0xf0, 0x46, 0xb5, 0x1e, 0x67, 0xba, 0x10, + 0xc9, 0xc3, 0x0a, 0x30, 0xed, 0xcd, 0xc4, 0x3a, 0x87, 0x08, 0x2c, 0xd9, 0x21, 0x5f, 0x68, + 0x0f, 0xf8, 0x2f, 0x6f, 0x2a, 0x27, 0x47, 0x79, 0x16, 0x52, 0x7a, 0xfd, 0x9d, 0x65, 0xec, + 0x53, 0x90, 0xaf, 0xf0, 0x45, 0x24, 0x08, 0x5a, 0x9f, 0xfd, 0xec, 0xd9, 0x9a, 0x4c, 0x0a, + 0xd4, 0x09, 0x58, 0xdd, 0x29, 0xe4, 0x1a, 0x8e, 0xe9, 0xa3, 0x60, 0x85, 0xd8, 0xd5, 0x9c, + 0xb7, 0x33, 0x2c, 0x3a, 0xfe, 0xd7, 0x09, 0x5a, 0x7a, 0x19, 0x3b, 0x67, 0xc2, 0xc9, 0xf1, + 0x41, 0xa4, 0xc6, 0x7f, 0x1e, 0x7d, 0x6a, 0x75, 0x24, 0xce, 0xef, 0x30, 0xdc, 0x74, 0x8f, + 0x2d, 0x8c, 0xf0, 0x5d, 0x2d, 0x4b, 0x0d, 0x0d, 0x1a, 0xda, 0x8b, 0xdb, 0xc9, 0xac, 0xeb, + 0x51, 0x5e, 0xaa, 0xde, 0x05, 0x3c, 0x8c, 0x87, 0x09, 0x08, 0x2d, 0xd2, 0xca, 0xe6, 0x66, + 0x97, 0x70, 0x38, 0x0e, 0x28, 0x53, 0x4b, 0x59, 0x85, 0x6a, 0x59, 0xe2, 0xd2, 0x6f, 0x87, + 0x4f, 0x4b, 0xf5, 0xe1, 0x4d, 0xc9, 0x23, 0xdd, 0xfe, 0x77, 0x44, 0x92, 0x3f, 0xf6, 0x78, + 0x93, 0x18, 0x38, 0x02, 0x24, 0x22, 0x89, 0xb7, 0x59, 0x84, 0x7d, 0xe4, 0xf7, 0x67, 0xaa, + 0xb8, 0xd4, 0x03, 0x92, 0x97, 0xfd, 0xaa, 0xb0, 0x5d, 0xee, 0x1a, 0x48, 0xb1, 0xfb, 0x1c, + 0x9d, 0xaf, 0x64, 0xc3, 0xd6, 0x3e, 0xb7, 0x62, 0xf5, 0xdb, 0xea, 0x61, 0x1d, 0xde, 0xc6, + 0xee, 0x6e, 0x90, 0xfd, 0x0b, 0x74, 0xd2, 0xc2, 0xf7, 0x35, 0x98, 0x78, 0x74, 0x3e, 0xb4, + 0xac, 0x29, 0x4f, 0xcd, 0x95, 0x6f, 0x0a, 0x6b, 0x20, 0xee, 0xd6, 0xd8, 0x6b, 0x34, 0x51, + 0xc0, 0x6f, 0x52, 0x9c, 0x4d, 0xac, 0x9a, 0x11, 0xb8, 0xb8, 0x29, 0x37, 0x8a, 0x1b, 0x8f, + 0x0c, 0x3a, 0x7a, 0x24, 0xfa, 0xc9, 0x5b, 0xef, 0x94, 0x9d, 0x36, 0xf9, 0x1a, 0x5b, 0x97, + 0xab, 0x0d, 0x3e, 0xc4, 0x7c, 0x9a, 0x83, 0xb7, 0x36, 0x1b, 0x2c, 0x93, 0xd2, 0x66, 0x6e, + 0x6f, 0x32, 0x11, 0x2f, 0x21, 0x19, 0x96, 0x3d, 0x7c, 0x5f, 0x2e, 0x6c, 0x05, 0x34, 0x95, + 0x7c, 0x1b, 0x9b, 0x33, 0xa4, 0xb2, 0x6d, 0x5f, 0xda, 0x45, 0x69, 0x0e, 0x5c, 0x1e, 0x5e, + 0xa9, 0x1a, 0x31, 0xc8, 0x23, 0x78, 0x98, 0x34, 0x4b, 0xe9, 0x37, 0xd5, 0x87, 0x46, 0xec, + 0x9b, 0x20, 0x50, 0x35, 0xb9, 0x95, 0xe5, 0x06, 0x50, 0xa6, 0xe1, 0xdd, 0x19, 0xf5, 0xc6, + 0x96, 0xec, 0xb3, 0x08, 0x1c, 0x25, 0xad, 0x3b, 0xfc, 0x11, 0x6c, 0x9a, 0x7d, 0xd8, 0x31, + 0x03, 0x24, 0xb5, 0xcb, 0x90, 0xed, 0xfc, 0x98, 0xb1, 0x46, 0xec, 0xd0, 0xa9, 0x3c, 0x1f, + 0x66, 0xb5, 0xba, 0x5e, 0xf2, 0x5a, 0xd5, 0xf3, 0xdf, 0x54, 0xe7, 0x11, 0x89, 0xdc, 0xf0, + 0xea, 0x09, 0x5d, 0x7a, 0x7a, 0xf6, 0x5f, 0x5d, 0x69, 0xc0, 0xbc, 0xf3, 0x73, 0x73, 0x9a, + 0xd5, 0x78, 0x40, 0xe3, 0x54, 0x31, 0x45, 0xd1, 0xc0, 0x2f, 0x93, 0xbc, 0x1e, 0x2f, 0x39, + 0x4e, 0xb4, 0xf0, 0x3e, 0x57, 0x7a, 0x64, 0x8d, 0x98, 0x66, 0x5d, 0x83, 0x5a, 0x6f, 0x8b, + 0x5f, 0xf2, 0x7e, 0xd1, 0xc9, 0xcc, 0xbb, 0xf7, 0xaa, 0x95, 0x2e, 0x7a, 0x7d, 0x8d, 0xec, + 0x37, 0x7a, 0xb5, 0xbc, 0x8d, 0x62, 0xd2, 0x32, 0x1e, 0xd7, 0x8b, 0x15, 0x06, 0x75, 0xde, + 0x81, 0xab, 0xb0, 0xd4, 0x59, 0xa2, 0x25, 0x34, 0xca, 0x6d, 0xce, 0x3f, 0xa3, 0xae, 0xe6, + 0x09, 0xb3, 0x33, 0xe1, 0x25, 0x56, 0x77, 0x30, 0x8b, 0xf7, 0x30, 0x0f, 0x74, 0x72, 0x36, + 0x8c, 0x4b, 0x5d, 0x94, 0xbc, 0x4f, 0x5e, 0x1d, 0x8a, 0x75, 0xec, 0xd4, 0x21, 0x21, 0xa9, + 0x54, 0x9c, 0xc8, 0x37, 0x28, 0x06, 0xae, 0x5c, 0x72, 0x3b, 0xa0, 0x80, 0x0d, 0x17, 0xbb, + 0x22, 0xe8, 0xf7, 0xa9, 0x31, 0x7d, 0x2c, 0x13, 0x74, 0xbc, 0xa0, 0x09, 0xba, 0x5b, 0x05, + 0xa4, 0xf9, 0xab, 0xb5, 0xd5, 0xd7, 0x11, 0x3f, 0xa3, 0xb4, 0x89, 0x79, 0x1c, 0x4a, 0xd8, + 0xfb, 0xc6, 0x54, 0x41, 0xaf, 0x32, 0xc9, 0x71, 0xaa, 0x5a, 0xb1, 0xb5, 0xe0, 0xa0, 0x73, + 0x45, 0x18, 0x73, 0x17, 0xd2, 0xcb, 0xb8, 0x70, 0x30, 0xbb, 0xce, 0x25, 0xad, 0x9e, 0x8d, + 0xf3, 0x0d, 0xec, 0x26, 0x3f, 0x2c, 0x16, 0x49, 0x45, 0x68, 0xbe, 0x04, 0x3e, 0x67, 0x1a, + 0xa6, 0x7e, 0xe9, 0x44, 0x63, 0x43, 0x91, 0x92, 0x25, 0x84, 0x04, 0xe6, 0xa8, 0xb7, 0xf2, + 0x70, 0x86, 0xba, 0x2e, 0x34, 0x4c, 0x0f, 0x45, 0xac, 0x39, 0x8d, 0x0c, 0x59, 0x60, 0x08, + 0xb2, 0x07, 0x79, 0xfd, 0xd0, 0x60, 0xad, 0x0d, 0x53, 0xa6, 0x9b, 0x02, 0x22, 0xf2, 0xbc, + 0xb4, 0xbd, 0x9e, 0x8a, 0xe8, 0x3b, 0xa7, 0x76, 0x21, 0x8e, 0x59, 0x5f, 0x08, 0xb6, 0xf9, + 0x4f, 0x18, 0x09, 0x8b, 0x8a, 0x94, 0x59, 0x93, 0xa3, 0x23, 0xf1, 0xdb, 0x62, 0x88, 0x30, + 0xe5, 0xea, 0xf1, 0x79, 0x3a, 0xf4, 0x3a, 0x57, 0xee, 0xab, 0xa0, 0x82, 0x39, 0x44, 0xd9, + 0x13, 0xb9, 0x32, 0xb4, 0x97, 0xb9, 0xa9, 0xb3, 0x23, 0x81, 0x61, 0xed, 0x96, 0x51, 0xd9, + 0xc5, 0x1c, 0x1b, 0xe7, 0x2a, 0x18, 0x83, 0xdb, 0xf5, 0xf2, 0x93, 0x98, 0xd8, 0x79, 0xc3, + 0x38, 0x6d, 0x86, 0x83, 0x9a, 0x80, 0x0d, 0x21, 0x5e, 0xbd, 0x7c, 0x7a, 0x32, 0xd0, 0x75, + 0xea, 0xe4, 0x95, 0x01, 0xcc, 0xa3, 0x2c, 0x74, 0x97, 0x1a, 0x25, 0xc7, 0x1a, 0x38, 0xe6, + 0x92, 0x8b, 0x89, 0xff, 0x56, 0xcd, 0x8d, 0x9f, 0xa0, 0x18, 0x9b, 0x00, 0xc4, 0x58, 0x38, + 0x49, 0x6a, 0x87, 0x59, 0xcc, 0x3b, 0xde, 0xb1, 0x6a, 0x86, 0x12, 0x74, 0x03, 0xd7, 0x04, + 0xc4, 0x63, 0xab, 0x1f, 0x5f, 0xf8, 0x4b, 0xba, 0x1d, 0x27, 0x06, 0xba, 0x68, 0xee, 0xe2, + 0xd3, 0x59, 0xb1, 0xc1, 0x7b, 0x97, 0x4e, 0x36, 0x9e, 0x13, 0x62, 0x9a, 0xad, 0x75, 0xe5, + 0x44, 0xaa, 0x9c, 0x5e, 0xdd, 0x05, 0x24, 0x6f, 0x44, 0x54, 0xc2, 0x5a, 0xfd, 0x4e, 0x97, + 0x49, 0xfc, 0xf8, 0xe9, 0x87, 0x42, 0x7d, 0xc5, 0xd6, 0x36, 0x21, 0x20, 0x6c, 0x2c, 0x32, + 0xf9, 0xca, 0x49, 0x2f, 0x7c, 0x3c, 0x24, 0x39, 0xd6, 0x91, 0xd3, 0x69, 0xf1, 0x8b, 0x91, + 0x54, 0xfd, 0xa0, 0x7a, 0x01, 0x52, 0x4a, 0xee, 0xf7, 0xea, 0xac, 0x19, 0xe8, 0x26, 0x8c, + 0x5b, 0x23, 0xd3, 0xa3, 0xa6, 0x44, 0xdf, 0x9c, 0x90, 0xd8, 0x09, 0x68, 0xda, 0x44, 0x50, + 0x2c, 0x55, 0x44, 0xd5, 0xc2, 0x7d, 0xab, 0xb0, 0x44, 0x81, 0xe5, 0xd9, 0x89, 0x0b, 0x08, + 0x7e, 0xe0, 0x15, 0x0f, 0xef, 0x80, 0xd9, 0x46, 0xef, 0x0d, 0x58, 0x9b, 0xa2, 0x5f, 0x74, + 0xb4, 0x5c, 0x66, 0x84, 0x5b, 0x5d, 0x5e, 0x08, 0xd1, 0xfc, 0x8e, 0x7b, 0xb4, 0x51, 0x59, + 0x17, 0xb3, 0x32, 0xdb, 0x86, 0x6a, 0x7a, 0x11, 0x74, 0x78, 0xda, 0x6b, 0x50, 0x10, 0x16, + 0x04, 0x48, 0x1f, 0xc8, 0x24, 0x9f, 0x77, 0xb7, 0x39, 0x0f, 0xd4, 0xde, 0x34, 0x50, 0x3a, + 0xb7, 0x2d, 0x0e, 0x6e, 0x9e, 0x15, 0x9a, 0x8e, 0x90, 0x1e, 0x93, 0xbf, 0x6b, 0xb8, 0xeb, + 0x10, 0x52, 0xe4, 0x0d, 0x7f, 0x05, 0x0e, 0x5d, 0x87, 0x25, 0x8f, 0xbc, 0x7f, 0x25, 0xfa, + 0xce, 0x37, 0x03, 0xac, 0x15, 0xfa, 0x46, 0x3d, 0xd5, 0x48, 0xfb, 0xf2, 0x63, 0x7b, 0xda, + 0x6f, 0x37, 0xdb, 0xbe, 0xc0, 0xad, 0xac, 0xb3, 0x36, 0xe4, 0xe6, 0x15, 0xd7, 0xd4, 0xc8, + 0x4e, 0xe0, 0x74, 0x3d, 0xe7, 0x31, 0x05, 0xf3, 0x42, 0x79, 0x12, 0x91, 0x56, 0x8e, 0xf7, + 0xd1, 0x60, 0xd4, 0x7d, 0x28, 0x53, 0x5b, 0xe9, 0x16, 0x25, 0x17, 0x32, 0x6c, 0x3a, 0x80, + 0xc8, 0x23, 0xe3, 0x54, 0xef, 0xc4, 0xfe, 0xd7, 0x21, 0xa1, 0xc1, 0x01, 0xfc, 0xad, 0x4e, + 0x3d, 0x14, 0xb5, 0xd4, 0x08, 0x9d, 0xdd, 0x98, 0x6c, 0xd6, 0x26, 0x4d, 0xad, 0x83, 0x50, + 0x45, 0x82, 0x0e, 0x8d, 0x1e, 0x4c, 0x7a, 0xea, 0x65, 0xb2, 0x1c, 0x75, 0x2d, 0xe3, 0x57, + 0xd2, 0x26, 0x56, 0x8c, 0x46, 0xb7, 0x83, 0x61, 0x4b, 0x1d, 0xe0, 0x42, 0xa1, 0x3f, 0x9d, + 0xe5, 0x37, 0xdd, 0xfa, 0x21, 0xd8, 0x45, 0x2a, 0xa5, 0xc8, 0x4f, 0x8a, 0x38, 0x0c, 0xc0, + 0x7f, 0x43, 0xac, 0xfa, 0xaf, 0x8b, 0x84, 0xdf, 0x70, 0xc3, 0xf7, 0x1b, 0xff, 0x1c, 0x82, + 0x66, 0xdb, 0x04, 0x27, 0xa8, 0x60, 0x38, 0xd9, 0x6a, 0x76, 0xbc, 0xd2, 0xac, 0xa7, 0x2c, + 0xa7, 0x25, 0xde, 0xe2, 0xff, 0xc0, 0x30, 0xbb, 0x45, 0x3c, 0x11, 0xea, 0x3b, 0x33, 0xfb, + 0x40, 0x71, 0xbe, 0xfe, 0xa6, 0x0b, 0xb9, 0xac, 0xff, 0xa9, 0xe4, 0xc6, 0x5d, 0x9a, 0x9b, + 0xea, 0x10, 0x53, 0x95, 0xa3, 0x4f, 0x9b, 0xc7, 0x8c, 0x4c, 0x5e, 0x92, 0x95, 0xc1, 0x52, + 0xd2, 0xe1, 0x45, 0x4a, 0x53, 0x14, 0xc1, 0xed, 0x1f, 0xba, 0x8a, 0x47, 0xc3, 0x64, 0x1e, + 0x7b, 0xf6, 0x61, 0x39, 0xb8, 0x1c, 0x83, 0x59, 0x2d, 0x1e, 0xf6, 0xb4, 0x81, 0x32, 0xee, + 0xe0, 0x97, 0xd2, 0x25, 0xdb, 0xa6, 0x44, 0xf0, 0xe9, 0x73, 0xa1, 0xb5, 0xfc, 0x1b, 0x04, + 0xe5, 0x5d, 0x35, 0x3c, 0xe3, 0x1b, 0x4a, 0x30, 0x02, 0x29, 0x00, 0xe9, 0xda, 0xc5, 0x74, + 0x6f, 0x7e, 0xb4, 0xa1, 0x4f, 0xbb, 0xfe, 0x8b, 0x36, 0x74, 0x2a, 0x4e, 0xee, 0xc6, 0x85, + 0x38, 0x05, 0x74, 0xfe, 0x5c, 0xf2, 0xca, 0x39, 0xdd, 0xab, 0xca, 0xa4, 0x30, 0xf9, 0xee, + 0xf1, 0x3b, 0xdd, 0x2c, 0xe0, 0x64, 0x73, 0x88, 0x9e, 0x80, 0x0f, 0xbf, 0xf8, 0x5e, 0x1a, + 0x8b, 0x05, 0xea, 0x9a, 0x9a, 0xae, 0x82, 0xeb, 0x6d, 0x04, 0xbf, 0xa8, 0x25, 0xdf, 0x54, + 0x17, 0x92, 0x3d, 0x52, 0x4e, 0x3c, 0x93, 0xc6, 0x5a, 0xd8, 0x50, 0xf8, 0x57, 0x42, 0xf2, + 0x02, 0x9e, 0xbb, 0xf6, 0x44, 0xd7, 0x0d, 0x59, 0xdf, 0x77, 0x3b, 0x23, 0x54, 0x7b, 0xa7, + 0x67, 0x75, 0xf3, 0xe5, 0x75, 0x3e, 0x9d, 0xdc, 0xe0, 0xdc, 0x75, 0xb8, 0x93, 0xf0, 0xd2, + 0x5b, 0x03, 0x9c, 0x56, 0x4d, 0x22, 0xd9, 0xfd, 0x42, 0xb2, 0xcf, 0xc9, 0xb4, 0x3f, 0xe5, + 0x32, 0x01, 0x75, 0x54, 0xa4, 0xdf, 0xa3, 0x43, 0xcd, 0x77, 0x25, 0x87, 0xb9, 0x74, 0x07, + 0x71, 0xe8, 0xa6, 0x82, 0x82, 0x14, 0x16, 0x94, 0x45, 0x6a, 0xb1, 0x42, 0xfe, 0x7b, 0xbf, + 0x08, 0xa2, 0x1d, 0x42, 0xc2, 0x79, 0x6e, 0xec, 0x50, 0x71, 0x57, 0xa5, 0x81, 0xbf, 0xe4, + 0x52, 0x68, 0xf1, 0xd4, 0xc9, 0xdb, 0x34, 0x2d, 0x9e, 0xda, 0x2f, 0x29, 0xda, 0x43, 0x6a, + 0xc6, 0x13, 0x09, 0x9e, 0xf1, 0xfb, 0xe1, 0x6b, 0x9b, 0x48, 0x5d, 0x8e, 0xcb, 0xc0, 0xb3, + 0x0f, 0x48, 0x67, 0x8e, 0x53, 0xd7, 0x51, 0x8e, 0xf4, 0x44, 0x1d, 0xcf, 0xc4, 0x03, 0x0d, + 0x64, 0x68, 0xb9, 0x62, 0x2b, 0x0b, 0x31, 0xf1, 0xc8, 0x22, 0xce, 0xbe, 0xc5, 0xa6, 0x06, + 0x4f, 0x43, 0x9a, 0x1b, 0xa5, 0xfc, 0xa6, 0xac, 0xe4, 0x94, 0x5e, 0x4b, 0x80, 0x65, 0xfe, + 0xb4, 0xeb, 0xd4, 0x4d, 0x0e, 0x66, 0x01, 0x1d, 0x2b, 0x31, 0x7d, 0xfc, 0x3a, 0xb2, 0x63, + 0x45, 0x5b, 0x3a, 0x64, 0xd1, 0xc8, 0x25, 0x1a, 0xa6, 0x6c, 0x96, 0xa5, 0x9c, 0x20, 0xfc, + 0xf8, 0x8a, 0x0d, 0x5b, 0x83, 0x19, 0xd4, 0xde, 0x01, 0xc3, 0x22, 0x06, 0x6c, 0x0b, 0x0a, + 0x17, 0x9c, 0x77, 0x1f, 0xc0, 0x53, 0x07, 0xc7, 0x6f, 0xe3, 0xdf, 0x61, 0x6e, 0x21, 0x0e, + 0x8f, 0x26, 0x3b, 0x89, 0x3b, 0x7b, 0x11, 0x7a, 0xf2, 0x88, 0x29, 0x98, 0xff, 0xec, 0x4b, + 0x95, 0xee, 0x8b, 0xc7, 0xde, 0x60, 0x0a, 0x49, 0x0e, 0x4f, 0xa3, 0x91, 0xa9, 0xfc, 0x97, + 0x4a, 0x34, 0xe8, 0x00, 0x8f, 0x38, 0xa6, 0x91, 0xe5, 0xde, 0xfe, 0x2d, 0x20, 0xde, 0xd8, + 0x9b, 0x6a, 0x97, 0x14, 0x3a, 0xaf, 0x2f, 0x47, 0x8a, 0x66, 0x22, 0x03, 0x68, 0x4b, 0x9b, + 0xe4, 0xbd, 0x98, 0x2e, 0x5f, 0x21, 0x63, 0x5a, 0x9a, 0x70, 0x27, 0x41, 0x46, 0x51, 0x27, + 0xbb, 0xa1, 0xb6, 0xd5, 0x2d, 0xdf, 0x09, 0x64, 0xd5, 0xdb, 0x0c, 0x2f, 0x4c, 0x00, 0x55, + 0x45, 0xd1, 0x12, 0xd7, 0xdb, 0x81, 0x09, 0x40, 0x59, 0xba, 0x93, 0xe8, 0xfc, 0x0c, 0x1a, + 0x9e, 0x00, 0xd9, 0xf7, 0xc5, 0x68, 0x23, 0x16, 0x10, 0x51, 0xba, 0xb0, 0x0c, 0x67, 0x56, + 0x6d, 0xd4, 0x81, 0x88, 0xa1, 0x6f, 0xcc, 0x9c, 0x54, 0x3b, 0x5a, 0xc0, 0x27, 0x90, 0xaa, + 0xf1, 0x10, 0xf7, 0x28, 0x56, 0xec, 0x49, 0x05, 0x41, 0x88, 0x24, 0x9a, 0x8b, 0x62, 0x5f, + 0xe1, 0x9c, 0xa6, 0xd7, 0x23, 0x08, 0x80, 0xf5, 0x85, 0x4d, 0xce, 0xa4, 0xf5, 0x11, 0xc0, + 0x4b, 0xd3, 0x64, 0xe4, 0x2e, 0x08, 0x3b, 0xea, 0x33, 0x46, 0xaf, 0x92, 0xec, 0x61, 0xc8, + 0x14, 0xee, 0x6f, 0x90, 0x5a, 0xe8, 0x3e, 0xcb, 0xe1, 0x41, 0xd8, 0x5f, 0xab, 0xac, 0x5b, + 0xe7, 0x61, 0x09, 0x92, 0x62, 0xc8, 0x42, 0x12, 0x3f, 0x9d, 0x17, 0x11, 0x17, 0x1d, 0x89, + 0x1c, 0x59, 0x55, 0x42, 0xec, 0x37, 0x7b, 0xdc, 0x30, 0xe7, 0x01, 0x8f, 0x76, 0x6c, 0xda, + 0xb0, 0x45, 0x50, 0x02, 0x8d, 0x27, 0xea, 0x55, 0x04, 0x11, 0xf6, 0xf3, 0x3f, 0xca, 0xed, + 0xef, 0x8c, 0xf6, 0xb6, 0xd5, 0x83, 0x46, 0xa1, 0x56, 0xd9, 0xc5, 0xa5, 0x65, 0x45, 0x9c, + 0x50, 0x3e, 0x9e, 0xc6, 0xd0, 0x83, 0x8d, 0x13, 0xd0, 0x6a, 0x21, 0x30, 0x44, 0x70, 0x6a, + 0x95, 0xf2, 0x48, 0x18, 0x84, 0xe5, 0x60, 0xa4, 0xb3, 0xe5, 0x74, 0xe0, 0x8a, 0x47, 0x58, + 0x82, 0x89, 0xb7, 0x16, 0xc0, 0x1a, 0x0f, 0x0f, 0x35, 0x56, 0xa3, 0x0c, 0xdb, 0x12, 0xc0, + 0x02, 0x8f, 0x1a, 0x72, 0xd1, 0x73, 0xbf, 0xf0, 0x67, 0x94, 0xaa, 0xc8, 0x73, 0x5b, 0x95, + 0x61, 0x5a, 0xca, 0x41, 0xf5, 0xe9, 0xc6, 0x38, 0x21, 0x67, 0x1b, 0xe7, 0xc5, 0x7b, 0x0d, + 0x06, 0x60, 0x6d, 0x31, 0x40, 0x6e, 0xa5, 0xd6, 0xfa, 0xe1, 0xd1, 0x85, 0x8e, 0x52, 0x2d, + 0xf5, 0x06, 0x90, 0xf8, 0x55, 0xf9, 0x1e, 0x8e, 0x7f, 0xd5, 0xc7, 0x32, 0x0a, 0x93, 0xb8, + 0xe0, 0xe3, 0x1c, 0xe1, 0xa0, 0xfe, 0xa6, 0x11, 0x4b, 0x08, 0x14, 0x47, 0x10, 0x56, 0xc5, + 0x62, 0x38, 0x22, 0x12, 0xfc, 0x2b, 0x9a, 0x9e, 0xf2, 0x19, 0xe7, 0xa4, 0xa2, 0x0f, 0xb8, + 0x32, 0xeb, 0x42, 0x77, 0x3c, 0xb2, 0x41, 0xbf, 0x3c, 0x05, 0x19, 0xf3, 0x6a, 0x50, 0x74, + 0x41, 0x0e, 0x02, 0xab, 0x1a, 0xc7, 0x69, 0x04, 0x76, 0xb4, 0xb2, 0x45, 0x6f, 0x05, 0x92, + 0x77, 0x83, 0x9b, 0xc2, 0x4b, 0xeb, 0x30, 0xf1, 0x8e, 0xf0, 0x2c, 0xa8, 0x52, 0xdf, 0xcf, + 0x0f, 0xd4, 0x63, 0xb7, 0x55, 0x9e, 0x8d, 0xd9, 0xc0, 0xef, 0x02, 0xaa, 0x74, 0x76, 0x43, + 0x4b, 0x60, 0x53, 0x04, 0xce, 0x21, 0xa5, 0xa0, 0x1c, 0x48, 0xca, 0x64, 0xe3, 0xc7, 0x18, + 0xc2, 0x67, 0x95, 0xba, 0x85, 0xe9, 0x87, 0xee, 0xd8, 0x03, 0x07, 0xc4, 0xe7, 0x6a, 0xf8, + 0x83, 0xb4, 0xbc, 0xb6, 0x82, 0x9e, 0xc9, 0x1e, 0xe3, 0xa9, 0x36, 0x22, 0x77, 0xc4, 0x98, + 0x3c, 0x50, 0xfb, 0x6e, 0xd9, 0x42, 0x2a, 0x48, 0xb6, 0xe8, 0x33, 0x7c, 0xc4, 0x30, 0xd7, + 0xc0, 0x59, 0x6d, 0x5c, 0x74, 0x93, 0x8b, 0x70, 0x28, 0x25, 0xcc, 0x52, 0x3d, 0xb1, 0xa8, + 0xa6, 0x60, 0x39, 0x3a, 0x2d, 0xf6, 0x53, 0x0e, 0x34, 0x28, 0xe1, 0x2b, 0x89, 0x08, 0x27, + 0x3a, 0x28, 0x51, 0xef, 0x20, 0xf9, 0x9c, 0x36, 0xb1, 0x2c, 0xeb, 0x6a, 0xeb, 0x60, 0x08, + 0x0b, 0x25, 0xac, 0x34, 0x4d, 0x21, 0xea, 0x2d, 0x27, 0x98, 0x62, 0x14, 0x68, 0x41, 0x94, + 0x66, 0x20, 0x0d, 0x52, 0x32, 0x0d, 0x71, 0x68, 0x1a, 0x44, 0x13, 0x47, 0xda, 0x22, 0xd6, + 0xf5, 0x3a, 0x3a, 0x05, 0x9f, 0xfc, 0x62, 0xbc, 0x76, 0xd9, 0x37, 0x7f, 0x73, 0x2b, 0x8d, + 0x83, 0xa5, 0x81, 0xf3, 0x98, 0x95, 0x56, 0x99, 0x19, 0x73, 0xd7, 0x24, 0xf7, 0x62, 0x79, + 0xf5, 0x7b, 0x2e, 0x05, 0x41, 0x65, 0x72, 0xfb, 0x6a, 0xd1, 0xd2, 0xe9, 0x9c, 0x08, 0x53, + 0x8d, 0x08, 0x84, 0x27, 0xe7, 0x6a, 0xda, 0x99, 0xf2, 0xbf, 0x13, 0xb4, 0x1f, 0xa8, 0x5f, + 0x21, 0x40, 0xc0, 0x64, 0xb4, 0x0a, 0x6a, 0x2f, 0x88, 0x09, 0xff, 0x82, 0x19, 0x9b, 0xec, + 0x4f, 0xa0, 0xdf, 0x73, 0xb2, 0x41, 0x00, 0x09, 0xa6, 0xff, 0x38, 0x58, 0x68, 0x44, 0xe0, + 0x67, 0xda, 0xd7, 0x57, 0xd9, 0x9c, 0xf6, 0x0a, 0xd6, 0x9f, 0x6a, 0x3b, 0x98, 0x59, 0xdd, + 0xdf, 0xe2, 0x10, 0x56, 0xd5, 0xf3, 0x51, 0x20, 0x7e, 0xc5, 0x78, 0x0d, 0x18, 0xcf, 0x8f, + 0x0c, 0x01, 0xf2, 0xaa, 0xa2, 0x05, 0x9c, 0x65, 0x8e, 0x10, 0x86, 0x0a, 0x2c, 0x6c, 0x45, + 0x7b, 0x6d, 0x03, 0xdf, 0x57, 0xd3, 0x36, 0x21, 0xee, 0xd1, 0xd1, 0x81, 0x5e, 0x27, 0x86, + 0xbc, 0x76, 0x70, 0x85, 0xe0, 0x95, 0x46, 0xc7, 0xc8, 0x8b, 0x95, 0x28, 0x39, 0xc8, 0x55, + 0xf9, 0x61, 0x7c, 0xd5, 0x37, 0x48, 0xad, 0x68, 0x1c, 0x4e, 0x84, 0x38, 0x48, 0x34, 0xad, + 0x24, 0xab, 0xfa, 0x1d, 0x6f, 0xda, 0x2e, 0x41, 0xc4, 0xcc, 0x5c, 0x3b, 0xaf, 0x32, 0xb7, + 0x13, 0x3d, 0x0a, 0x44, 0x83, 0x01, 0x78, 0x07, 0xfe, 0x6f, 0xae, 0xfe, 0x11, 0xa4, 0x29, + 0x54, 0x7d, 0x83, 0x8a, 0xd4, 0xed, 0xba, 0x93, 0x13, 0x60, 0x3a, 0xd4, 0xa9, 0xa4, 0x63, + 0x3e, 0x06, 0x81, 0xa0, 0x31, 0x8b, 0xc2, 0x25, 0x70, 0xaa, 0xc8, 0x41, 0xcd, 0xce, 0x55, + 0x9b, 0x6a, 0x6f, 0x75, 0x01, 0xcb, 0xd4, 0xde, 0x6b, 0xcc, 0x38, 0xe5, 0x14, 0x18, 0xe4, + 0x53, 0xac, 0x26, 0x08, 0x1e, 0x07, 0x78, 0x3c, 0xd4, 0x17, 0xdd, 0x40, 0x50, 0x3c, 0x94, + 0x46, 0x6b, 0xc4, 0xf3, 0x7b, 0xdd, 0x2d, 0xe3, 0xe9, 0x0e, 0x23, 0x44, 0x39, 0xbc, 0x97, + 0xa4, 0xa0, 0xda, 0x84, 0x20, 0xec, 0x94, 0xce, 0x0e, 0x04, 0xd4, 0xb0, 0x61, 0xb4, 0x4f, + 0xa7, 0x08, 0x71, 0xd6, 0x8e, 0x48, 0x6f, 0x88, 0xd4, 0x19, 0x60, 0x0a, 0x91, 0x77, 0x99, + 0xbb, 0xce, 0x30, 0xb8, 0x36, 0x1b, 0x0c, 0x13, 0x0e, 0x2d, 0x79, 0xc6, 0xe6, 0x79, 0xa4, + 0xd7, 0x4d, 0xea, 0x8e, 0xa2, 0xc1, 0x40, 0xbd, 0x2b, 0xde, 0x04, 0x78, 0xa6, 0x59, 0x8a, + 0x10, 0xac, 0xc3, 0xf6, 0x53, 0x71, 0xfe, 0x79, 0x0f, 0x79, 0x37, 0xd5, 0xbf, 0xdd, 0xab, + 0xad, 0xac, 0x9e, 0x12, 0xac, 0xbd, 0xd5, 0x06, 0x26, 0x35, 0xab, 0xb1, 0x0d, 0x26, 0x5e, + 0x87, 0x3a, 0xa0, 0x07, 0xb0, 0xb5, 0x72, 0xc8, 0xad, 0x43, 0x2b, 0x87, 0xb1, 0x91, 0xf4, + 0x1c, 0x42, 0xd8, 0x51, 0xa6, 0x6e, 0xf6, 0xa7, 0xff, 0x53, 0xd8, 0xa5, 0x11, 0xce, 0x2c, + 0x01, 0xf4, 0x1d, 0x22, 0x23, 0x4d, 0xcb, 0x27, 0x61, 0x06, 0xdb, 0x9d, 0x3c, 0x99, 0x0c, + 0x5e, 0x1f, 0xca, 0x13, 0xde, 0x97, 0xdf, 0xbd, 0x28, 0x72, 0xdc, 0x2d, 0x69, 0x9c, 0x3b, + 0x6a, 0xa2, 0x0c, 0x5c, 0xf6, 0xfa, 0x2f, 0xc5, 0xe6, 0xd6, 0x6c, 0xcd, 0x1a, 0xfe, 0x39, + 0xed, 0x31, 0x72, 0x26, 0xbb, 0xa5, 0xfd, 0x2a, 0x97, 0x0a, 0xdb, 0xa5, 0x54, 0xb1, 0x44, + 0x00, 0x3f, 0x9b, 0x79, 0xa2, 0xda, 0xc3, 0xc1, 0x4d, 0xdf, 0x70, 0x43, 0xc9, 0x0b, 0xdb, + 0x4a, 0x24, 0xf7, 0xba, 0x4b, 0xac, 0x46, 0x78, 0x42, 0x3b, 0x66, 0xe3, 0x2d, 0x3a, 0x42, + 0x9a, 0x84, 0x3c, 0x5b, 0x36, 0x6f, 0x66, 0x14, 0x58, 0xec, 0x60, 0x4b, 0x67, 0xfb, 0x6a, + 0x34, 0x2c, 0x6a, 0x15, 0xb7, 0xc6, 0x7b, 0x0a, 0xe3, 0x5b, 0x9a, 0xcd, 0x84, 0x2e, 0xab, + 0x18, 0x8f, 0x08, 0x07, 0xe2, 0x25, 0xb6, 0x3d, 0x21, 0x0f, 0x59, 0xb7, 0x92, 0xaa, 0x4f, + 0x79, 0xcd, 0x60, 0x7e, 0x0a, 0x0a, 0x85, 0xff, 0x4d, 0x0d, 0x01, 0x0f, 0xe2, 0xcf, 0x97, + 0xee, 0x13, 0x75, 0xfc, 0x91, 0x80, 0x0a, 0x96, 0x86, 0x6c, 0x88, 0x09, 0xeb, 0x5c, 0x71, + 0x6b, 0x24, 0x51, 0xec, 0xd3, 0xa4, 0x83, 0x14, 0x47, 0x8b, 0xa0, 0x21, 0x95, 0x38, 0xf3, + 0x0f, 0x56, 0x81, 0xb5, 0x93, 0xfe, 0xe1, 0x63, 0x8f, 0x88, 0x6b, 0x85, 0x38, 0xce, 0x3c, + 0x5c, 0xea, 0x46, 0x73, 0xb8, 0x00, 0xd9, 0x5d, 0xa8, 0x3f, 0x76, 0xfd, 0xdc, 0x9e, 0x78, + 0x90, 0x83, 0xd2, 0x29, 0xb2, 0xbd, 0x86, 0x85, 0x58, 0x65, 0x33, 0xb7, 0x01, 0xab, 0x68, + 0x84, 0xc5, 0xab, 0x7a, 0x77, 0x8e, 0x4b, 0xf2, 0x27, 0x3d, 0x44, 0x3e, 0xa4, 0x4e, 0x19, + 0x20, 0xde, 0xaa, 0xe2, 0x28, 0xf2, 0x85, 0x86, 0xa6, 0x92, 0x2a, 0xce, 0x88, 0xae, 0x9f, + 0xfe, 0xff, 0xac, 0x1a, 0xbf, 0x78, 0x69, 0xe4, 0x98, 0xb5, 0xa1, 0x54, 0x97, 0x05, 0x25, + 0x70, 0x3e, 0x67, 0x00, 0x96, 0xc5, 0xe0, 0x39, 0x9c, 0x95, 0x92, 0x7d, 0xd7, 0x23, 0x83, + 0xb9, 0xe2, 0xf3, 0xbb, 0x65, 0x98, 0xcc, 0xda, 0x47, 0xf2, 0xd3, 0x59, 0x43, 0x34, 0x92, + 0x32, 0x03, 0x70, 0x5f, 0x5f, 0xcd, 0x8c, 0xba, 0xc6, 0x97, 0x48, 0x20, 0x18, 0x8e, 0xe2, + 0xfc, 0x96, 0xc9, 0x6a, 0x4a, 0xcf, 0x4c, 0xf8, 0x68, 0x55, 0x3c, 0x80, 0x8f, 0x69, 0x41, + 0xe2, 0xf1, 0x08, 0x90, 0xe4, 0xa0, 0xf4, 0x63, 0x04, 0x4f, 0x64, 0x16, 0xfc, 0xd5, 0x32, + 0xf0, 0x87, 0x57, 0x60, 0x28, 0x85, 0xfc, 0x1f, 0x8c, 0x42, 0xec, 0xc1, 0x41, 0x93, 0x32, + 0x0b, 0x4b, 0x8e, 0xbc, 0x18, 0xc7, 0x15, 0xd4, 0xe1, 0x99, 0x3f, 0x69, 0x74, 0x05, 0x44, + 0xd1, 0xd7, 0x83, 0xc0, 0x01, 0x00, 0x34, 0x0e, 0x44, 0x56, 0xf5, 0xe2, 0x6c, 0xfe, 0x26, + 0xfb, 0x10, 0x2a, 0xfc, 0xea, 0xb6, 0x1f, 0xef, 0x62, 0xbe, 0x39, 0x0d, 0xa2, 0xfc, 0xea, + 0x72, 0x2d, 0xa6, 0x1e, 0x5c, 0x25, 0x0f, 0xcc, 0xe6, 0xad, 0xc5, 0xe6, 0x53, 0xc9, 0x1c, + 0x46, 0x4a, 0x89, 0xaf, 0x58, 0xf9, 0xa3, 0x09, 0x0b, 0x6e, 0xdf, 0x29, 0xcd, 0xfc, 0x4c, + 0xb8, 0x9b, 0x3e, 0x0e, 0x5b, 0xdb, 0x4e, 0x4b, 0x82, 0x36, 0x7b, 0x01, 0xe9, 0x83, 0x75, + 0x5a, 0xfc, 0xe5, 0x90, 0xc3, 0xe9, 0xc2, 0x6f, 0x15, 0x8f, 0x01, 0xc5, 0x8a, 0x0a, 0xea, + 0x73, 0x02, 0xc0, 0xa4, 0x7a, 0x18, 0x32, 0x30, 0xb9, 0x05, 0xb7, 0x03, 0x02, 0xef, 0xac, + 0x2f, 0xdc, 0x5c, 0x40, 0x2a, 0x56, 0x0b, 0xe5, 0xe3, 0x70, 0x85, 0x88, 0x1d, 0xd9, 0x7d, + 0xa0, 0x40, 0x8d, 0x37, 0x85, 0xdf, 0xd0, 0xca, 0xd6, 0x1f, 0xe7, 0x67, 0xfa, 0xc5, 0xb8, + 0x92, 0xdd, 0x4f, 0x26, 0x4d, 0x77, 0xbe, 0x51, 0xa8, 0x0b, 0x1d, 0x2c, 0xb4, 0x52, 0x33, + 0x8d, 0x95, 0xaf, 0xf1, 0xbd, 0x6e, 0x91, 0xde, 0xac, 0xf6, 0xba, 0x0a, 0x5c, 0x9b, 0x67, + 0x20, 0x21, 0xd1, 0x33, 0xf7, 0x0f, 0xf4, 0xb1, 0x2a, 0x6b, 0x5b, 0x30, 0x31, 0x01, 0x1d, + 0xb3, 0x10, 0xec, 0xef, 0x05, 0x24, 0x72, 0xd6, 0xb5, 0x14, 0x48, 0xef, 0xc7, 0x93, 0xf8, + 0xf4, 0x76, 0x9a, 0x24, 0x01, 0xe3, 0x26, 0xca, 0x30, 0xa0, 0xc5, 0x1c, 0x7e, 0xc2, 0x19, + 0x7a, 0x87, 0xf9, 0x1d, 0xd3, 0xa4, 0xae, 0x81, 0xb3, 0x06, 0x2f, 0xbd, 0xc3, 0xd5, 0xb6, + 0xd7, 0xa7, 0x82, 0x8d, 0xab, 0x0e, 0x34, 0x9e, 0xe2, 0x37, 0x2b, 0x0b, 0x49, 0x94, 0x1f, + 0x25, 0x33, 0x27, 0xdf, 0x15, 0x3e, 0x2c, 0x90, 0x60, 0x19, 0x28, 0xcc, 0xd1, 0x0f, 0xc8, + 0x67, 0x5e, 0x5c, 0x63, 0x42, 0x14, 0x7c, 0xfb, 0x22, 0x21, 0x43, 0x7f, 0x31, 0x3a, 0xa5, + 0xe4, 0x87, 0x75, 0xfe, 0x08, 0x45, 0xa7, 0x32, 0xd9, 0x5f, 0x54, 0x93, 0x64, 0xce, 0xaf, + 0xca, 0x4a, 0x1e, 0xd9, 0xde, 0x5a, 0x64, 0x9f, 0x77, 0x93, 0x49, 0x54, 0x7a, 0xa9, 0x96, + 0xc0, 0x0e, 0xf4, 0x0c, 0xc2, 0x43, 0x33, 0x42, 0x92, 0x3f, 0x11, 0x96, 0x8b, 0x50, 0x11, + 0xa6, 0x9c, 0xe7, 0x38, 0x40, 0xaa, 0x19, 0x56, 0x6e, 0x6e, 0x6a, 0xe6, 0x9f, 0xa4, 0xbe, + 0x10, 0xc5, 0xf8, 0x72, 0xe0, 0xaf, 0xec, 0x51, 0xa0, 0xd9, 0x28, 0x08, 0xe9, 0x16, 0x1c, + 0x50, 0x97, 0xe7, 0x18, 0x38, 0xd0, 0x05, 0x35, 0x49, 0x72, 0xfa, 0xe4, 0x7b, 0x6e, 0x52, + 0x92, 0x41, 0x1d, 0xcd, 0x08, 0x79, 0xd7, 0x75, 0xd8, 0x9e, 0x02, 0x70, 0xaf, 0x09, 0x6c, + 0xac, 0x1c, 0x33, 0xa1, 0x7e, 0x56, 0xcd, 0xad, 0x4e, 0x4d, 0xc8, 0xae, 0xa4, 0xac, 0xbf, + 0x29, 0x52, 0xa0, 0x1e, 0x29, 0x76, 0x08, 0xc1, 0x2d, 0x7f, 0xcf, 0x2a, 0x63, 0xde, 0xd0, + 0x38, 0xa0, 0xf8, 0xf5, 0xc0, 0x0e, 0x1b, 0xce, 0x32, 0xe4, 0x67, 0xa6, 0x9d, 0xf1, 0xb5, + 0x02, 0x91, 0xb0, 0x4c, 0xbf, 0xf9, 0x38, 0x33, 0x47, 0xf8, 0x82, 0x8f, 0x17, 0xc0, 0xd8, + 0xa6, 0xe4, 0x0c, 0x85, 0xa7, 0xc2, 0x81, 0xf3, 0x99, 0x6e, 0x8c, 0x4b, 0x40, 0x9e, 0x7c, + 0x31, 0x13, 0x03, 0x36, 0x33, 0x0c, 0x95, 0xcd, 0xe3, 0x35, 0x4c, 0x73, 0x83, 0x3d, 0x80, + 0xaa, 0xa7, 0xbb, 0x15, 0x1b, 0x7e, 0xbd, 0x23, 0x31, 0xe7, 0x50, 0x51, 0xe0, 0x51, 0xaf, + 0xf1, 0x74, 0x2d, 0x4f, 0xa7, 0x6b, 0x81, 0x5a, 0x07, 0xd6, 0x0f, 0xb4, 0xdf, 0x95, 0x5d, + 0xf8, 0x7c, 0x47, 0xea, 0x0c, 0x90, 0x3d, 0x73, 0x2d, 0x05, 0x07, 0x50, 0xc9, 0x92, 0x6c, + 0xdf, 0xd3, 0xbc, 0xcc, 0xb0, 0x60, 0xfe, 0xf4, 0x6b, 0xc9, 0x9c, 0x1d, 0x99, 0x1f, 0x45, + 0x66, 0xe9, 0x66, 0xb3, 0xd8, 0x3f, 0x87, 0x32, 0x09, 0x0d, 0x8e, 0xe4, 0xb6, 0x68, 0xd8, + 0x5c, 0x13, 0x58, 0x16, 0x27, 0xa3, 0x9a, 0x51, 0x3a, 0x8a, 0xac, 0x03, 0x7e, 0x65, 0x32, + 0x0e, 0xff, 0xb6, 0x2b, 0x8f, 0xe1, 0x65, 0x03, 0x1d, 0x84, 0x31, 0x7b, 0x08, 0x29, 0x55, + 0xa7, 0x1f, 0x1b, 0x95, 0x1d, 0x5e, 0x68, 0x8f, 0x6f, 0xc7, 0x52, 0x55, 0x09, 0x8a, 0x8e, + 0xff, 0xd3, 0x5b, 0x41, 0x60, 0xb8, 0x3a, 0x05, 0x5b, 0xb9, 0xe0, 0xbe, 0x0f, 0xd8, 0xf7, + 0x01, 0xb5, 0xeb, 0xc9, 0xed, 0x8e, 0xe4, 0x85, 0x69, 0x18, 0xdd, 0xa1, 0x27, 0xf0, 0x9a, + 0x13, 0x51, 0xe7, 0x22, 0xdf, 0x04, 0xcd, 0xc3, 0xd9, 0xa8, 0x73, 0xdb, 0xe8, 0xb7, 0x39, + 0x66, 0x9b, 0x36, 0x15, 0xad, 0x14, 0xad, 0x9d, 0xf0, 0x64, 0x69, 0xa3, 0x6a, 0xbb, 0x59, + 0xfb, 0xce, 0x00, 0xac, 0x23, 0xb4, 0x7f, 0x3a, 0xa2, 0xf9, 0x55, 0x4b, 0x7b, 0x0f, 0x9d, + 0x5a, 0x2b, 0xc7, 0x5e, 0xb7, 0xfb, 0x21, 0x10, 0xf4, 0x0d, 0x2e, 0x62, 0xca, 0x7b, 0x30, + 0x0f, 0xdf, 0xa7, 0xf3, 0xd2, 0xf4, 0x6c, 0xd8, 0x14, 0x76, 0x02, 0x3b, 0x43, 0x59, 0xd7, + 0xa9, 0x19, 0x81, 0x1d, 0x65, 0xe8, 0xc3, 0x9b, 0x69, 0xf2, 0xd4, 0x73, 0xf3, 0xf8, 0x84, + 0xaa, 0xf9, 0x1e, 0xa9, 0x1e, 0xcd, 0x84, 0xc4, 0x45, 0xa6, 0x34, 0xf2, 0x8a, 0x93, 0x3b, + 0xb6, 0x2b, 0xc8, 0x49, 0x48, 0x1c, 0xd9, 0x70, 0x8e, 0xf2, 0x07, 0x2b, 0xf5, 0x22, 0x63, + 0x3f, 0x0c, 0x2b, 0xb7, 0xd6, 0x8a, 0x6f, 0x64, 0x41, 0x33, 0x7a, 0xd7, 0x02, 0x13, 0x50, + 0xec, 0x36, 0xa9, 0x6a, 0x31, 0x26, 0xe3, 0x00, 0xa7, 0x67, 0xbb, 0xac, 0x22, 0xee, 0xbc, + 0x33, 0xb0, 0x4f, 0xdf, 0x2b, 0x36, 0xdf, 0x8f, 0x1a, 0x6a, 0xc5, 0x21, 0x78, 0xd0, 0x8c, + 0x5c, 0x71, 0xe5, 0xde, 0xa3, 0x85, 0x39, 0x5b, 0x62, 0x3f, 0xea, 0xae, 0x03, 0x14, 0x67, + 0x4e, 0xc7, 0x9b, 0x4a, 0x5d, 0x26, 0xca, 0x1f, 0xdf, 0xa0, 0x8f, 0x18, 0x2b, 0xf4, 0x2d, + 0x4a, 0xd3, 0x9c, 0x07, 0x7c, 0xb7, 0xa6, 0x1e, 0xcb, 0xb6, 0x48, 0x02, 0x79, 0x6a, 0xf3, + 0x67, 0xf4, 0xe2, 0xe7, 0x5f, 0x0e, 0x3a, 0x27, 0xb5, 0xff, 0xc4, 0xef, 0x5b, 0xf6, 0x02, + 0x64, 0x73, 0x94, 0x8c, 0x50, 0x29, 0x86, 0xcc, 0x02, 0x6e, 0xc4, 0x70, 0xa8, 0x36, 0xc9, + 0x3f, 0x32, 0xc3, 0x1d, 0x21, 0x54, 0x64, 0x9d, 0xdc, 0x71, 0x30, 0xd3, 0x97, 0x4c, 0x4c, + 0xd2, 0xfa, 0xb9, 0x80, 0x11, 0x12, 0x47, 0xa3, 0x5d, 0x85, 0x61, 0xbe, 0x6c, 0x8c, 0xdc, + 0x12, 0x59, 0x1d, 0xbb, 0x81, 0xe6, 0x5e, 0x99, 0xf9, 0x78, 0xce, 0xe1, 0x8b, 0x4f, 0x6a, + 0x01, 0xce, 0xb4, 0xc1, 0xb0, 0xf8, 0x50, 0x4c, 0x4d, 0x48, 0x1e, 0xea, 0x94, 0x6f, 0xab, + 0x26, 0xf8, 0x0c, 0x74, 0xd2, 0xd3, 0x75, 0x6a, 0x83, 0x96, 0xfd, 0xb4, 0x5e, 0xfb, 0x06, + 0x63, 0xf7, 0x1c, 0xa9, 0x15, 0xc9, 0x72, 0xc2, 0xf7, 0x36, 0x03, 0x66, 0xca, 0x66, 0x3b, + 0x8e, 0x39, 0x59, 0x51, 0x27, 0x87, 0xe7, 0xbb, 0x98, 0xc2, 0xb0, 0xe6, 0x1c, 0xb9, 0x05, + 0xb6, 0xde, 0x55, 0xbb, 0xb8, 0xff, 0x42, 0x79, 0xf1, 0xa3, 0x09, 0xa6, 0xe2, 0xc9, 0xa5, + 0x58, 0x42, 0x9a, 0xdb, 0x08, 0xd3, 0x29, 0x17, 0xc2, 0x91, 0x10, 0xdf, 0x3a, 0xb3, 0x41, + 0x3a, 0x27, 0x73, 0xf7, 0xc7, 0xd9, 0xa4, 0x58, 0xef, 0xd2, 0xcd, 0x2e, 0xe1, 0x42, 0xd4, + 0x05, 0x7e, 0x96, 0x8b, 0x26, 0x99, 0x7c, 0xfc, 0x34, 0x33, 0x18, 0x3b, 0x29, 0x71, 0x3f, + 0x39, 0x7a, 0x4c, 0xf0, 0x01, 0x20, 0xe0, 0x44, 0x5a, 0x88, 0xb6, 0xcc, 0xb6, 0xcd, 0x96, + 0x8a, 0x1f, 0x9e, 0xcb, 0x3c, 0x7f, 0x7e, 0x1a, 0x2c, 0xbf, 0x2a, 0xda, 0xd1, 0x91, 0x53, + 0x20, 0x00, 0x10, 0xb4, 0x83, 0x78, 0x8f, 0xeb, 0xc1, 0x0f, 0xe2, 0x10, 0x14, 0x5d, 0x27, + 0x3a, 0x3d, 0x5e, 0x3e, 0x3d, 0xe5, 0x7c, 0x84, 0xaa, 0x7c, 0x6a, 0xa8, 0x3d, 0x86, 0x0a, + 0x79, 0xcc, 0xa1, 0x09, 0x2e, 0x96, 0x41, 0x41, 0xc5, 0xce, 0x3e, 0x9d, 0x93, 0x20, 0xb0, + 0x7a, 0x53, 0xfd, 0x10, 0xba, 0x2f, 0xe4, 0x0f, 0xfd, 0xbf, 0x55, 0x23, 0x2b, 0x3a, 0x2d, + 0xaa, 0x7e, 0xf1, 0xbc, 0x6d, 0x93, 0x57, 0xc7, 0x1b, 0xd4, 0x28, 0x03, 0x8f, 0xae, 0x3c, + 0x90, 0xb2, 0xb1, 0xff, 0x2c, 0x40, 0xa2, 0xd4, 0x0a, 0x55, 0xde, 0xeb, 0xf7, 0x85, 0xad, + 0x6e, 0x13, 0x6e, 0x55, 0x53, 0x06, 0xf1, 0x37, 0x2e, 0x50, 0x78, 0xe0, 0x6f, 0x27, 0xc1, + 0xbe, 0xc5, 0x81, 0xb3, 0x52, 0xd5, 0xc0, 0xe9, 0x98, 0xf5, 0x74, 0x5b, 0x17, 0xdd, 0x84, + 0xbc, 0xed, 0x06, 0x2c, 0xa3, 0xa4, 0x48, 0xc9, 0xf1, 0xa1, 0x9d, 0xf2, 0x48, 0x23, 0x59, + 0x09, 0xd5, 0x88, 0xf1, 0x79, 0xa2, 0x03, 0xe6, 0x8d, 0xe6, 0x3a, 0xb9, 0xd3, 0xeb, 0xcb, + 0xa6, 0x13, 0xd0, 0xef, 0xe3, 0x11, 0x71, 0x0e, 0x1b, 0xf3, 0xd3, 0xa9, 0xc3, 0xfb, 0xc6, + 0xbd, 0xf8, 0xd8, 0x99, 0x41, 0x81, 0x6f, 0xe8, 0x09, 0x7d, 0x0a, 0xcd, 0x91, 0xc0, 0xa2, + 0x38, 0x42, 0x5c, 0x53, 0x19, 0x02, 0x5e, 0x21, 0xab, 0xa1, 0xf1, 0xe8, 0x0d, 0xf0, 0x6d, + 0x65, 0xab, 0x4d, 0x39, 0xa4, 0x05, 0xda, 0x30, 0xc4, 0x4c, 0x94, 0x3a, 0xd8, 0x49, 0x00, + 0x39, 0x85, 0xe4, 0x91, 0x55, 0xf9, 0x40, 0x08, 0x22, 0x04, 0x1a, 0xa5, 0xe2, 0x48, 0x3d, + 0x10, 0x76, 0xb4, 0x25, 0x7f, 0x12, 0xb2, 0xfb, 0xda, 0xa5, 0xa9, 0x18, 0x28, 0x91, 0x1d, + 0x86, 0x0f, 0xda, 0x10, 0x53, 0xa9, 0x99, 0xc1, 0xc8, 0x02, 0x41, 0x3a, 0x42, 0xdc, 0x55, + 0x21, 0xca, 0x6e, 0x8a, 0x75, 0x5b, 0xe1, 0x26, 0xdf, 0x16, 0x48, 0x14, 0xc7, 0x01, 0xad, + 0x2f, 0x75, 0x49, 0x64, 0x44, 0xff, 0x5a, 0xc6, 0x70, 0x89, 0x10, 0x79, 0xac, 0x0e, 0x2f, + 0xaf, 0x6d, 0x57, 0xf5, 0x59, 0x6c, 0x79, 0x1b, 0x9d, 0x4c, 0x39, 0xb3, 0xa5, 0xbf, 0xb6, + 0xe0, 0x78, 0x76, 0x81, 0x4f, 0xde, 0xea, 0xa0, 0xdd, 0x63, 0x25, 0x7c, 0x4f, 0x1d, 0x53, + 0x2d, 0x2d, 0x4d, 0x61, 0x72, 0x86, 0x07, 0x6e, 0xd3, 0x23, 0xe3, 0x79, 0xc4, 0x27, 0xc5, + 0xfe, 0x5d, 0x05, 0xb1, 0xe3, 0x45, 0x1b, 0x6c, 0xd7, 0x1e, 0x8f, 0x62, 0xc2, 0x85, 0x0d, + 0x2c, 0xbe, 0x25, 0xc5, 0x38, 0xe9, 0xa2, 0x80, 0x34, 0x4f, 0x4e, 0x30, 0xff, 0xaf, 0x16, + 0x4c, 0x8b, 0xd0, 0xb1, 0x0e, 0x3f, 0x4e, 0xf9, 0x0d, 0x4e, 0x1d, 0x95, 0x49, 0x66, 0xcf, + 0xa0, 0x8f, 0xa3, 0xf6, 0x35, 0xfa, 0x88, 0xa1, 0xf9, 0xfc, 0x34, 0x71, 0xd6, 0xfe, 0xbc, + 0x21, 0x6f, 0xbe, 0xc4, 0xca, 0xd7, 0x85, 0xa3, 0x65, 0x10, 0x5c, 0x46, 0xc9, 0xbd, 0xce, + 0xbf, 0xcc, 0x4c, 0x3c, 0x7e, 0x2a, 0x28, 0x09, 0x6a, 0x73, 0x16, 0x35, 0xf7, 0xe3, 0x4e, + 0x8a, 0xbb, 0x7a, 0x54, 0x2c, 0xe1, 0x18, 0x1c, 0x90, 0x14, 0xe7, 0x5a, 0xe8, 0xd9, 0xc9, + 0x29, 0x20, 0x12, 0x5e, 0x0a, 0xcf, 0xdc, 0xcd, 0x16, 0x86, 0xde, 0x72, 0x0e, 0x41, 0x52, + 0x91, 0x74, 0x4c, 0x68, 0x50, 0xc1, 0x91, 0xcc, 0x92, 0xca, 0x42, 0x8a, 0x6a, 0x1a, 0xfd, + 0x37, 0x70, 0x61, 0xab, 0x18, 0x21, 0x07, 0x0e, 0xc5, 0x62, 0x02, 0xc8, 0xf8, 0xe5, 0xa3, + 0x94, 0x38, 0xff, 0x40, 0xbf, 0xee, 0x77, 0xa1, 0x5f, 0x19, 0x91, 0x26, 0x72, 0xc0, 0x32, + 0x1b, 0x8a, 0xab, 0xc3, 0x2a, 0x00, 0x50, 0xee, 0xd9, 0xc9, 0xa4, 0x07, 0x04, 0x7c, 0xa1, + 0xd7, 0xbb, 0xba, 0x46, 0x64, 0xbc, 0x07, 0x00, 0x30, 0x02, 0x1d, 0xe4, 0x64, 0xc9, 0x0d, + 0x2a, 0xfc, 0x3a, 0xdb, 0xeb, 0x73, 0x54, 0x2a, 0x97, 0x48, 0xa3, 0x06, 0xe7, 0x36, 0x1c, + 0xae, 0xbb, 0xe2, 0x3a, 0xa7, 0x4f, 0xa4, 0x39, 0x67, 0xc3, 0xab, 0x1f, 0x13, 0x30, 0xa2, + 0x5c, 0x49, 0x52, 0x04, 0xf5, 0x46, 0x74, 0x50, 0xae, 0xa8, 0xd3, 0xae, 0x33, 0x84, 0x9f, + 0x8c, 0x27, 0xfc, 0x42, 0xa4, 0x44, 0x4f, 0x2d, 0xa2, 0xb9, 0x84, 0x43, 0x46, 0x87, 0x6b, + 0x4e, 0xb3, 0xa4, 0x47, 0x5c, 0xd1, 0xc2, 0xac, 0x0f, 0x34, 0x99, 0x00, 0xfc, 0xc9, 0xab, + 0x85, 0x0e, 0x49, 0x9f, 0xf4, 0x95, 0x7f, 0xc3, 0x8f, 0x35, 0xd0, 0x3c, 0xbe, 0x7c, 0xbc, + 0x2d, 0xe4, 0xd7, 0x03, 0x62, 0x86, 0xd8, 0x4d, 0x3d, 0x65, 0xc0, 0xa3, 0x7d, 0xc1, 0x83, + 0x70, 0xd0, 0x3a, 0x1b, 0xd6, 0x32, 0x46, 0xf4, 0xb6, 0x95, 0x09, 0xf7, 0xca, 0x71, 0xa8, + 0x05, 0x7b, 0xbb, 0xcb, 0x8e, 0x8f, 0x11, 0x79, 0x1a, 0xd1, 0xdd, 0x41, 0x3f, 0x95, 0x2b, + 0xdf, 0x31, 0x11, 0xa2, 0xe4, 0x56, 0x04, 0x11, 0x40, 0x68, 0x6b, 0xa7, 0x22, 0xa3, 0xb7, + 0x7a, 0x95, 0x2d, 0xa7, 0xd3, 0x61, 0x68, 0xb5, 0x26, 0x82, 0x8f, 0xb6, 0x21, 0xb3, 0xae, + 0x12, 0x1c, 0xa6, 0x22, 0x2f, 0xd2, 0x5e, 0x28, 0x14, 0x01, 0x94, 0xb9, 0x56, 0x88, 0x9f, + 0x56, 0xd0, 0xee, 0x02, 0xd3, 0x58, 0x6c, 0x9d, 0xc0, 0x0a, 0xf8, 0x0b, 0xdf, 0xea, 0xf0, + 0xf9, 0xe5, 0xbb, 0x64, 0x46, 0x29, 0x67, 0xa8, 0xaa, 0xb0, 0xb4, 0x24, 0xb2, 0x85, 0x20, + 0x14, 0x42, 0x73, 0xe0, 0x53, 0xed, 0xa0, 0x0f, 0x23, 0x7f, 0xd0, 0x9e, 0x98, 0xd2, 0x69, + 0x64, 0x9b, 0xb1, 0x9c, 0xcd, 0x06, 0x8f, 0x64, 0x52, 0x45, 0x24, 0x13, 0x35, 0x34, 0xbf, + 0x52, 0xff, 0x4a, 0x1f, 0x96, 0x6a, 0xc5, 0x38, 0xb3, 0x50, 0xf6, 0xe3, 0xb0, 0x7b, 0x3f, + 0x3e, 0x67, 0xa7, 0x5b, 0x4e, 0x91, 0x27, 0xb5, 0x46, 0x71, 0x0c, 0x50, 0xb1, 0xfb, 0xb5, + 0x90, 0x9a, 0x8d, 0xa5, 0x7b, 0x36, 0x11, 0x97, 0x56, 0xd8, 0x31, 0x2c, 0x54, 0xe0, 0x12, + 0x68, 0x1e, 0x86, 0x8c, 0x10, 0x36, 0xce, 0x12, 0x3b, 0xad, 0x8b, 0xf1, 0x45, 0x97, 0xb8, + 0x76, 0x19, 0x38, 0x99, 0x72, 0x87, 0x78, 0x1d, 0x6e, 0xe6, 0x75, 0x70, 0x05, 0x3b, 0x1e, + 0xfb, 0xe8, 0xba, 0x94, 0x67, 0x6e, 0x3e, 0x32, 0x86, 0xa3, 0x77, 0x07, 0xfc, 0xa1, 0x05, + 0x03, 0x97, 0x72, 0x7b, 0x9b, 0x8e, 0xd0, 0x63, 0x5a, 0xc4, 0x58, 0x1b, 0x5d, 0x95, 0xe9, + 0x49, 0x80, 0x7a, 0xfc, 0xcb, 0x08, 0xa4, 0x4d, 0xf6, 0x5d, 0x73, 0x77, 0xe1, 0x19, 0x1d, + 0xaf, 0x67, 0xa8, 0x6e, 0x37, 0xa9, 0x19, 0xe7, 0xa0, 0x17, 0x86, 0x62, 0x13, 0xde, 0x48, + 0x81, 0x72, 0x3b, 0xc2, 0xba, 0xdb, 0x4c, 0x9b, 0x0b, 0xab, 0x10, 0x2c, 0xf9, 0xc1, 0x0e, + 0xc4, 0x2f, 0x16, 0x35, 0x26, 0x91, 0xf2, 0xf8, 0x33, 0xc4, 0x01, 0x46, 0x3e, 0xb3, 0x21, + 0x66, 0x62, 0xf7, 0x5e, 0xae, 0x53, 0x7e, 0xdf, 0x62, 0xad, 0x96, 0x58, 0xc5, 0x52, 0x46, + 0xb4, 0x13, 0x6a, 0x9f, 0x69, 0x32, 0x55, 0xc8, 0xd4, 0xcd, 0x12, 0xa4, 0x6a, 0x7d, 0x31, + 0x6a, 0x6e, 0x13, 0x56, 0xfc, 0x8d, 0x2c, 0xe8, 0xf4, 0x54, 0x83, 0xaa, 0x2a, 0x00, 0xfd, + 0xdd, 0xee, 0x95, 0x27, 0xbe, 0xcf, 0x58, 0xb1, 0xa5, 0xdf, 0x1e, 0x2b, 0x18, 0x98, 0x3c, + 0x6e, 0x1f, 0x5e, 0x93, 0xdf, 0x90, 0x2c, 0x7d, 0xae, 0x89, 0xa7, 0x56, 0x59, 0x27, 0x5c, + 0x15, 0x22, 0xf9, 0xf4, 0xdc, 0x71, 0x00, 0xfe, 0x69, 0x9c, 0x34, 0x56, 0x07, 0x10, 0x1c, + 0x47, 0x47, 0x6c, 0xa0, 0x43, 0x74, 0x68, 0x89, 0x8c, 0x31, 0xd2, 0x69, 0x11, 0x94, 0x7f, + 0x45, 0x01, 0x5a, 0x0e, 0x50, 0x75, 0xf6, 0x70, 0xa5, 0x5f, 0xc1, 0x78, 0x45, 0xd8, 0x1d, + 0x2b, 0xb6, 0xbc, 0x0f, 0xb8, 0xab, 0x13, 0x40, 0xf6, 0xb5, 0x43, 0x82, 0x7d, 0xe5, 0x53, + 0x63, 0x6a, 0xf7, 0xed, 0xf4, 0xf0, 0x56, 0x75, 0xdd, 0xc0, 0x8e, 0xa0, 0x68, 0x66, 0xf1, + 0xce, 0x08, 0x73, 0xbb, 0xd4, 0xff, 0x3e, 0x10, 0xbb, 0xca, 0x51, 0x48, 0x44, 0xe7, 0x76, + 0x37, 0x98, 0x0e, 0x80, 0xa5, 0x00, 0x46, 0xb3, 0x22, 0x02, 0x62, 0xe7, 0xef, 0x24, 0x3a, + 0xeb, 0x9c, 0x53, 0x30, 0x4f, 0x39, 0x38, 0x0b, 0xc0, 0x4c, 0x7b, 0xbf, 0xbf, 0xb4, 0xc8, + 0xf6, 0x5e, 0x69, 0x26, 0xfb, 0xdb, 0x0d, 0x80, 0x94, 0xd3, 0x4e, 0xa0, 0x51, 0x5b, 0xb2, + 0x8d, 0x5c, 0x31, 0xc9, 0x0f, 0x8c, 0xf5, 0xa9, 0x7f, 0x1b, 0xe8, 0x78, 0x51, 0x41, 0xdb, + 0xf6, 0x40, 0x62, 0x5d, 0x9b, 0x49, 0xbe, 0x09, 0x03, 0xc4, 0x43, 0xcc, 0xb1, 0xc5, 0xf8, + 0x14, 0x9f, 0x05, 0xa0, 0x4c, 0x93, 0x49, 0x3c, 0x7a, 0x05, 0xee, 0x35, 0x91, 0x38, 0xc7, + 0xb0, 0x8a, 0xea, 0x1b, 0x01, 0xcc, 0xc7, 0xb5, 0x0e, 0x02, 0xa8, 0xe2, 0xa3, 0x01, 0x81, + 0x6c, 0x0a, 0x6a, 0xc3, 0x0d, 0x0d, 0x4d, 0x58, 0x41, 0xcb, 0xfc, 0x36, 0x1e, 0x15, 0xf4, + 0x89, 0xca, 0x1c, 0xbc, 0xd4, 0xd8, 0x70, 0x36, 0x1d, 0x6d, 0x30, 0x7b, 0x28, 0x8d, 0x94, + 0x4d, 0x8e, 0x02, 0xf3, 0x06, 0x44, 0x39, 0xf4, 0xfe, 0xde, 0x2a, 0x45, 0xf2, 0xb5, 0xcb, + 0x44, 0xe2, 0xd7, 0x41, 0x4f, 0xfb, 0x0a, 0x86, 0xbf, 0x47, 0x21, 0x70, 0x17, 0x4d, 0x33, + 0x5e, 0xd7, 0x00, 0x13, 0x47, 0xa3, 0x56, 0x90, 0x04, 0x43, 0x5c, 0xf8, 0x61, 0x2b, 0xf8, + 0x83, 0xe5, 0x5b, 0x48, 0x82, 0x0c, 0xbb, 0x92, 0xf5, 0xdc, 0x03, 0xd3, 0x9b, 0xc6, 0x12, + 0xb7, 0x34, 0x65, 0x28, 0xac, 0x45, 0x11, 0x61, 0x73, 0x58, 0x87, 0xb2, 0xc7, 0x2c, 0xd8, + 0x79, 0x28, 0xa5, 0x1f, 0xd3, 0x0b, 0xb6, 0x7a, 0x30, 0xa1, 0x9c, 0x25, 0x23, 0x7b, 0x74, + 0x17, 0xc4, 0xc6, 0x7c, 0xa9, 0x66, 0xeb, 0xe1, 0x2d, 0x74, 0x82, 0xc7, 0xe8, 0xb3, 0xa6, + 0xcd, 0x92, 0x15, 0x87, 0x0c, 0x2a, 0x0b, 0x04, 0x64, 0xf9, 0x3f, 0x81, 0x95, 0x5c, 0xb2, + 0x1c, 0x6d, 0xf7, 0xa4, 0x0b, 0xb9, 0xcd, 0xfe, 0x05, 0x9c, 0x4a, 0x66, 0xc3, 0xef, 0x0e, + 0x6b, 0xb9, 0xb2, 0x56, 0x1b, 0x82, 0x2f, 0xc1, 0x46, 0xbe, 0x31, 0xcb, 0x50, 0xdf, 0xa6, + 0xe5, 0xa8, 0x97, 0x2e, 0x13, 0xe2, 0xe3, 0x1d, 0x84, 0xa7, 0x4b, 0x45, 0x35, 0xb9, 0x6c, + 0xa8, 0x1f, 0x56, 0x3f, 0x30, 0xa8, 0x6c, 0x32, 0xb8, 0xae, 0xd0, 0x95, 0xd0, 0x5b, 0x8d, + 0xec, 0x37, 0xb7, 0xa7, 0x9f, 0xe6, 0x4f, 0xdc, 0xd1, 0x4a, 0xf9, 0xf0, 0x04, 0x6e, 0x93, + 0x57, 0xbb, 0xbe, 0xf9, 0xd2, 0x37, 0x2e, 0x14, 0x14, 0x54, 0xbe, 0xad, 0x9f, 0xad, 0xdd, + 0x1c, 0x8e, 0x07, 0x6f, 0xb7, 0x28, 0xc7, 0xe7, 0x5a, 0x5d, 0x70, 0x52, 0x96, 0x14, 0x5f, + 0x44, 0xcc, 0xa0, 0xac, 0x0b, 0x2c, 0xac, 0xe6, 0xe8, 0xba, 0x7a, 0x50, 0x29, 0x86, 0x88, + 0xe7, 0x0d, 0x5c, 0xef, 0xa4, 0x87, 0x1b, 0x71, 0xfd, 0xe9, 0x68, 0xb1, 0xae, 0xf6, 0xcd, + 0xd7, 0xdf, 0x2a, 0xbf, 0x46, 0x45, 0xf0, 0x45, 0xae, 0x1a, 0xef, 0x89, 0x31, 0x17, 0x1d, + 0x37, 0xba, 0xed, 0x0a, 0x0c, 0xf5, 0x9f, 0x40, 0x4f, 0x33, 0x80, 0x3a, 0xb4, 0x88, 0xa4, + 0x30, 0x25, 0xe8, 0x4f, 0x03, 0xb4, 0x37, 0x12, 0x9d, 0x52, 0x3e, 0xd5, 0xb8, 0x24, 0xdc, + 0xd1, 0x35, 0xe6, 0xda, 0xa1, 0xd2, 0x02, 0x04, 0x58, 0x07, 0xdd, 0xd0, 0x6a, 0x7b, 0xd6, + 0x47, 0x0c, 0xaa, 0xcc, 0xe9, 0xf6, 0x11, 0xd3, 0xbd, 0xf7, 0x09, 0xab, 0xd2, 0xf3, 0xd1, + 0xda, 0x9c, 0xf0, 0x2f, 0x20, 0x14, 0x14, 0x78, 0xf5, 0x31, 0x7b, 0x19, 0x64, 0x13, 0x1e, + 0xbb, 0x18, 0x60, 0x1d, 0xcd, 0xa2, 0x52, 0x2e, 0x64, 0x79, 0xd2, 0xca, 0x81, 0xe5, 0x6d, + 0x4c, 0xe5, 0x52, 0xb5, 0x96, 0x0f, 0xc8, 0x80, 0x1a, 0x27, 0x69, 0x22, 0xef, 0x67, 0xde, + 0x7b, 0xf9, 0xaf, 0xfe, 0x34, 0x88, 0x1e, 0x2a, 0xb8, 0xbe, 0x10, 0xb7, 0x6e, 0xec, 0x73, + 0x80, 0x9d, 0xca, 0x48, 0xbd, 0xd3, 0xf7, 0x3d, 0xbb, 0xa8, 0x7c, 0x73, 0xbb, 0x1f, 0x2d, + 0x1b, 0xd9, 0x85, 0xf6, 0x16, 0x7e, 0xdd, 0x48, 0x87, 0x23, 0x95, 0xe3, 0x79, 0x07, 0xb9, + 0xd9, 0x9f, 0xca, 0x59, 0x2b, 0x7b, 0x82, 0x3e, 0x45, 0x00, 0x1f, 0xff, 0x01, 0x98, 0x56, + 0x06, 0x0b, 0xc4, 0xe9, 0x65, 0xf7, 0xac, 0x2a, 0x5d, 0x48, 0x9e, 0x6b, 0x02, 0x6a, 0x2d, + 0xdf, 0x50, 0x87, 0x4b, 0x21, 0x16, 0x74, 0x24, 0x99, 0xac, 0x2e, 0x11, 0x00, 0x44, 0xbb, + 0x2e, 0x45, 0x65, 0xf7, 0x11, 0xd5, 0xdb, 0xfc, 0x66, 0xed, 0xd9, 0x14, 0x54, 0x52, 0xc7, + 0x44, 0xbb, 0x9b, 0x9b, 0x5d, 0x60, 0x69, 0xbc, 0x43, 0xc3, 0x59, 0xdc, 0x99, 0xf5, 0x18, + 0xdd, 0x92, 0x03, 0x24, 0xa8, 0xda, 0x5b, 0x91, 0xc0, 0xf5, 0x51, 0x24, 0x8a, 0x75, 0x1b, + 0x50, 0x86, 0x2d, 0x3a, 0xf7, 0x37, 0x36, 0x13, 0x1c, 0x8c, 0x29, 0xae, 0xa1, 0x38, 0x5a, + 0x89, 0x01, 0x01, 0x04, 0x57, 0x45, 0x54, 0x48, 0x01, 0x51, 0x23, 0x84, 0x58, 0xb0, 0xd0, + 0xdd, 0x6d, 0x49, 0x3e, 0xc9, 0x64, 0xa7, 0x46, 0x21, 0x17, 0x23, 0x7e, 0xa2, 0x14, 0xab, + 0x8b, 0xb5, 0x4b, 0x5a, 0x7d, 0x9e, 0x00, 0x5f, 0x56, 0x06, 0x86, 0x5f, 0x5c, 0x7c, 0x04, + 0xad, 0xb7, 0x14, 0x97, 0x25, 0xe0, 0x2a, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc9, 0xcd, 0x43, 0x2e, 0xde, 0xa8, 0x73, 0x19, 0xb8, 0xbd, 0xf5, 0xb4, 0x00, 0xd1, 0x7c, + 0xb0, 0xd4, 0x74, 0x3f, 0x21, 0x74, 0xc1, 0x50, 0x37, 0xc7, 0xfd, 0x9e, 0x5c, 0xdc, 0xe9, + 0x45, 0x86, 0x4c, 0x29, 0xe3, 0x15, 0x3f, 0x0c, 0x0f, 0x8d, 0xf0, 0x15, 0xdd, 0xa9, 0x02, + 0x16, 0x6c, 0xda, 0x01, 0x5a, 0xf9, 0x06, 0x33, 0x78, 0xfa, 0xdc, 0xc3, 0xcc, 0x19, 0xad, + 0x25, 0xff, 0x82, 0x25, 0x47, 0xea, 0x17, 0x04, 0x55, 0x5d, 0x56, 0x53, 0x69, 0x74, 0xd6, + 0x2e, 0x91, 0xfc, 0x3d, 0x6d, 0xcb, 0x39, 0x76, 0xf1, 0x08, 0x26, 0xba, 0xd9, 0x72, 0x21, + 0xf4, 0x2d, 0x60, 0x2c, 0x4f, 0x8e, 0x00, 0x3c, 0x99, 0x76, 0x4d, 0x0d, 0xda, 0x13, 0x9b, + 0x31, 0x65, 0xda, 0x5d, 0xc4, 0xbf, 0x97, 0x00, 0xc6, 0xa5, 0x63, 0xfc, 0xd0, 0x54, 0x3f, + 0x54, 0x9e, 0x7b, 0x19, 0xd4, 0xcc, 0x4c, 0xaf, 0x77, 0x33, 0xbb, 0x23, 0xe1, 0x95, 0x16, + 0x4d, 0xde, 0xb6, 0xbf, 0xd4, 0x57, 0x8a, 0x5d, 0x48, 0x12, 0x41, 0x31, 0xd3, 0x18, 0xc0, + 0xdc, 0x23, 0xe2, 0xe6, 0xd5, 0x99, 0x50, 0xbe, 0xa6, 0xe5, 0x9f, 0xe4, 0x90, 0xba, 0x1e, + 0x9e, 0x26, 0xbd, 0x63, 0xcc, 0xb6, 0x4b, 0x36, 0x4d, 0x91, 0x8c, 0x15, 0x65, 0x4b, 0x72, + 0xa6, 0xda, 0xb9, 0x56, 0x7e, 0xf2, 0x57, 0xf2, 0x50, 0x2f, 0xc2, 0xca, 0x84, + ], + // Transfer block + &[ + 0x04, 0x00, 0x00, 0x00, 0x27, 0xe3, 0x01, 0x34, 0xd6, 0x20, 0xe9, 0xfe, 0x61, 0xf7, 0x19, + 0x93, 0x83, 0x20, 0xba, 0xb6, 0x3e, 0x7e, 0x72, 0xc9, 0x1b, 0x5e, 0x23, 0x02, 0x56, 0x76, + 0xf9, 0x0e, 0xd8, 0x11, 0x9f, 0x02, 0xe2, 0xec, 0x78, 0x12, 0x64, 0x23, 0x8b, 0xa6, 0xf5, + 0xab, 0xc9, 0xc0, 0x66, 0xf5, 0x1f, 0xe1, 0xb9, 0xf7, 0xb3, 0xd1, 0xa4, 0x40, 0xce, 0xa0, + 0xf0, 0x60, 0x79, 0xb4, 0x43, 0x15, 0x9d, 0xe7, 0x13, 0x64, 0x84, 0x07, 0x94, 0x1f, 0xda, + 0x44, 0xf6, 0xf5, 0xa1, 0x3e, 0xaf, 0xf5, 0xb2, 0xe1, 0x35, 0x1b, 0x63, 0xb4, 0x81, 0x96, + 0x3f, 0x2a, 0xf5, 0x7e, 0x56, 0x38, 0xa3, 0x99, 0x92, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xa6, 0x0c, 0x20, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0xfd, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x80, 0x85, 0x20, 0x2f, 0x89, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x02, 0x51, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x40, 0xbe, 0x40, 0x25, + 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, + 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x57, + 0x6a, 0xc2, 0x2a, 0x5e, 0xe1, 0xc1, 0x53, 0x80, 0x98, 0x98, 0x9d, 0x4e, 0xe3, 0x6a, 0x88, + 0xb9, 0x25, 0xea, 0xdd, 0xc9, 0x0b, 0x5c, 0x14, 0xbb, 0xc9, 0xf1, 0x0a, 0xa0, 0x22, 0x46, + 0x2f, 0xd7, 0xfb, 0xb2, 0xf4, 0xca, 0x12, 0x4b, 0xc6, 0xfe, 0x41, 0xc0, 0x35, 0x88, 0x21, + 0x86, 0x0b, 0x89, 0x43, 0x19, 0x29, 0x8e, 0x4f, 0xa3, 0xd4, 0x00, 0x9e, 0x16, 0x9e, 0x7a, + 0x54, 0x49, 0x20, 0x55, 0xd0, 0xbd, 0xc9, 0x0c, 0xb9, 0xc3, 0xae, 0x0d, 0x2d, 0x10, 0x47, + 0x08, 0xcd, 0x4e, 0xb9, 0x02, 0x45, 0x0b, 0x5b, 0xc5, 0xbd, 0xcd, 0x65, 0xdb, 0x40, 0x22, + 0xc4, 0x8f, 0x12, 0x70, 0x98, 0x75, 0x30, 0xcb, 0x0c, 0xa4, 0x9a, 0x68, 0x0f, 0xe5, 0x06, + 0x35, 0xfd, 0x8c, 0x75, 0x37, 0x81, 0xb3, 0xfc, 0x96, 0xa6, 0xe4, 0x5d, 0x4c, 0xba, 0x55, + 0xe4, 0x9e, 0x43, 0x13, 0x37, 0x74, 0x1a, 0x35, 0x48, 0x2b, 0x9d, 0xfe, 0x06, 0xb0, 0xa8, + 0x6c, 0x89, 0x50, 0x7e, 0x17, 0xf0, 0x75, 0xad, 0xf1, 0x35, 0xad, 0xed, 0xc1, 0x63, 0xb9, + 0x96, 0xbd, 0xbc, 0xcd, 0x38, 0x1f, 0x58, 0xb9, 0xb3, 0x67, 0x02, 0x93, 0x03, 0x0f, 0x68, + 0x2d, 0x61, 0xcc, 0xf8, 0x1d, 0xd5, 0xb4, 0x37, 0x8a, 0xa5, 0x9f, 0x55, 0x10, 0x25, 0xfd, + 0x0c, 0x41, 0x40, 0x60, 0xab, 0xe6, 0x04, 0x57, 0x76, 0x8c, 0x08, 0xbf, 0x0d, 0x4c, 0x85, + 0x61, 0x1b, 0x33, 0x31, 0xaf, 0x5a, 0x33, 0xe1, 0x39, 0x8d, 0x37, 0xd9, 0x4a, 0x72, 0x2e, + 0x81, 0xe7, 0x44, 0x4c, 0xdd, 0xbb, 0x34, 0x4e, 0xdc, 0x4e, 0x75, 0xca, 0x13, 0x07, 0x50, + 0x13, 0x10, 0x6c, 0x46, 0x31, 0x80, 0x39, 0x23, 0xf2, 0x56, 0x9e, 0xc6, 0x2f, 0x1a, 0xff, + 0xea, 0x1a, 0xe6, 0x72, 0x53, 0x08, 0xfa, 0x07, 0x8d, 0x94, 0x6e, 0x31, 0x57, 0xa0, 0x32, + 0xb2, 0x96, 0x6f, 0xb8, 0xb0, 0x3c, 0x49, 0x56, 0xd2, 0xa0, 0xe0, 0x3f, 0x3c, 0x07, 0x89, + 0x61, 0xb4, 0x3d, 0x2f, 0x78, 0xed, 0xfb, 0xfe, 0x0f, 0x89, 0x5f, 0x7c, 0x35, 0x8e, 0x70, + 0x42, 0x40, 0x2d, 0xaa, 0xfe, 0xe5, 0xb4, 0xee, 0x02, 0x47, 0x5a, 0x66, 0xe9, 0x83, 0xf3, + 0x9d, 0xb0, 0x91, 0xa7, 0x94, 0x62, 0xac, 0x68, 0x7d, 0xc0, 0x53, 0xcc, 0xbe, 0x98, 0xbd, + 0x20, 0xe3, 0xd9, 0xd6, 0xf4, 0x02, 0x68, 0x81, 0x96, 0x8a, 0x81, 0x6f, 0x4c, 0x2f, 0x2d, + 0x10, 0x42, 0xdb, 0xf7, 0xdc, 0x8a, 0x56, 0xbc, 0x15, 0x60, 0x0a, 0x30, 0x3c, 0x7c, 0x4f, + 0xdc, 0x09, 0x78, 0x9c, 0x99, 0x2f, 0x6d, 0xe9, 0x0f, 0x41, 0xf7, 0xf5, 0x13, 0x06, 0x05, + 0xf3, 0x00, 0xa9, 0x36, 0xc5, 0x6b, 0x71, 0x4f, 0xc0, 0x60, 0xd2, 0x15, 0xe2, 0x52, 0x17, + 0x38, 0x29, 0x1a, 0x4a, 0x0c, 0x96, 0x95, 0xe4, 0xf6, 0x62, 0xcb, 0x51, 0xcd, 0x81, 0xfe, + 0x70, 0x20, 0x48, 0x1b, 0xac, 0x5f, 0x90, 0xc8, 0x01, 0x9f, 0x82, 0x33, 0x30, 0x13, 0xd4, + 0x3a, 0x8d, 0x78, 0xf5, 0xf0, 0xb3, 0xa5, 0x77, 0xa3, 0xc1, 0xb4, 0xc2, 0xc7, 0x50, 0x30, + 0x7b, 0x6f, 0xbe, 0xf8, 0xa3, 0x20, 0x80, 0x38, 0x37, 0xed, 0x32, 0x7e, 0x9a, 0xe7, 0xeb, + 0xd6, 0xb8, 0xc8, 0xd2, 0x82, 0x43, 0xd9, 0x88, 0xdf, 0xf4, 0x05, 0x66, 0xbf, 0x45, 0x83, + 0x26, 0x85, 0xf7, 0x30, 0x7f, 0x4a, 0x29, 0x16, 0x21, 0x23, 0xb6, 0x7f, 0x51, 0x9e, 0x1b, + 0xc6, 0x59, 0x8b, 0x63, 0x6a, 0x41, 0xf2, 0xb7, 0x6d, 0xa9, 0x4a, 0xc9, 0xcf, 0x17, 0x74, + 0x91, 0xf8, 0xbd, 0x09, 0x98, 0x0a, 0x4f, 0x09, 0xb8, 0x95, 0x6c, 0xa7, 0x18, 0x50, 0x49, + 0x53, 0xd9, 0xc6, 0x86, 0xc9, 0xba, 0xf5, 0x09, 0xc7, 0xc8, 0x74, 0x50, 0x75, 0xa8, 0xe0, + 0x49, 0x38, 0x72, 0x1d, 0xaa, 0xb0, 0xf9, 0xf2, 0x3d, 0x42, 0x2b, 0x0a, 0x04, 0xd7, 0x19, + 0x5c, 0xbb, 0xb2, 0x70, 0xeb, 0x0f, 0x1d, 0xcd, 0x8f, 0xf3, 0xbf, 0x6d, 0xf8, 0xdc, 0x32, + 0x0d, 0xca, 0x6a, 0xe6, 0xa0, 0x81, 0xe6, 0xa9, 0x2b, 0x8d, 0x8d, 0xea, 0xea, 0x34, 0xb7, + 0x02, 0x78, 0x75, 0xc2, 0xfa, 0xc2, 0x35, 0x27, 0xdc, 0x28, 0xcc, 0xf9, 0xee, 0x53, 0x55, + 0x6c, 0xf8, 0xee, 0x38, 0xe8, 0x43, 0x32, 0x24, 0xcc, 0x1c, 0x7a, 0x97, 0xcf, 0x1d, 0x42, + 0x60, 0xcc, 0x04, 0x25, 0x8d, 0x45, 0x3e, 0x57, 0x61, 0x8f, 0x94, 0xb7, 0x0c, 0xf1, 0xab, + 0x28, 0x96, 0x3c, 0x0c, 0x19, 0x11, 0xef, 0x7a, 0xad, 0x20, 0xa1, 0x01, 0xaa, 0x58, 0xfc, + 0x48, 0xae, 0x53, 0xd6, 0xc3, 0xab, 0x3b, 0x31, 0xa0, 0x14, 0xa3, 0x35, 0xb0, 0x91, 0xe5, + 0x28, 0x2e, 0x0c, 0x3f, 0x18, 0x2b, 0x11, 0x30, 0xa9, 0x85, 0xa8, 0xe1, 0xbe, 0x51, 0xd1, + 0x0f, 0x27, 0x79, 0xf0, 0x99, 0x43, 0xd6, 0xb1, 0x5f, 0x98, 0x78, 0x81, 0xcd, 0xa4, 0xf1, + 0x4d, 0x8c, 0x1b, 0xd7, 0xcc, 0x0e, 0xfd, 0x00, 0x7b, 0xf2, 0xff, 0x61, 0xca, 0x20, 0xed, + 0x8d, 0xf8, 0xb9, 0x19, 0x2b, 0x3c, 0xab, 0x2f, 0xd1, 0x8d, 0x2b, 0x50, 0x88, 0x10, 0x16, + 0x86, 0xdd, 0x00, 0xd9, 0xee, 0x8a, 0x3c, 0x1f, 0x82, 0x0a, 0xae, 0xeb, 0xb8, 0xe5, 0xb8, + 0x83, 0x0b, 0x7a, 0xbe, 0x02, 0x62, 0xf2, 0xfa, 0xa4, 0x28, 0xa5, 0xd3, 0x53, 0xa6, 0x82, + 0xca, 0x17, 0xeb, 0x78, 0x3a, 0x30, 0x84, 0xc5, 0x66, 0x38, 0xcd, 0xb0, 0xb7, 0x33, 0x27, + 0x33, 0x35, 0x24, 0xeb, 0x48, 0xb0, 0x4c, 0x1e, 0xd3, 0xe4, 0x88, 0x38, 0x00, 0x56, 0xe1, + 0x23, 0x82, 0x20, 0x63, 0xdb, 0xe6, 0xd6, 0x04, 0x45, 0x7b, 0x21, 0xcf, 0xbf, 0xa5, 0x5a, + 0xc2, 0x4e, 0x60, 0x21, 0x4f, 0xec, 0xe1, 0xdd, 0xf5, 0xdb, 0x4e, 0x29, 0xc8, 0x38, 0x1d, + 0x12, 0x33, 0xe5, 0x75, 0x63, 0x3e, 0x09, 0xdd, 0x74, 0x21, 0x1a, 0x6f, 0xfc, 0x5c, 0xbf, + 0x81, 0xba, 0x77, 0xf7, 0x5c, 0x5e, 0xe0, 0xeb, 0xea, 0x3c, 0xf4, 0x45, 0x27, 0x86, 0xd7, + 0x40, 0x56, 0xee, 0xe6, 0xa6, 0xb0, 0x36, 0x1b, 0x99, 0x4a, 0x26, 0x40, 0x06, 0xe6, 0x0b, + 0x8d, 0x3f, 0xe4, 0xa4, 0x88, 0x74, 0x5d, 0x6e, 0xb2, 0x7c, 0xec, 0x87, 0x20, 0x29, 0x4a, + 0xa2, 0x71, 0x60, 0x77, 0x8f, 0x95, 0x7e, 0x7a, 0x44, 0xf9, 0x17, 0x36, 0xa6, 0x39, 0xcc, + 0x3e, 0xcc, 0x49, 0x4d, 0xe8, 0x5c, 0x12, 0x04, 0x36, 0x2b, 0x08, 0x5d, 0x42, 0x32, 0xa8, + 0xde, 0xf8, 0xdb, 0x98, 0xe8, 0xa0, 0x98, 0xf2, 0x5d, 0xec, 0x9a, 0xa3, 0x3e, 0xf9, 0xab, + 0xc7, 0x7c, 0x8f, 0xac, 0xa6, 0x41, 0x83, 0x59, 0x51, 0x8a, 0x05, 0x65, 0x28, 0x48, 0xfe, + 0x2c, 0x2c, 0x73, 0xfd, 0xb1, 0xe8, 0x6e, 0x8c, 0x7d, 0x0a, 0xf7, 0xdc, 0x7b, 0x64, 0x23, + 0x4b, 0x17, 0xc4, 0x3e, 0xbf, 0xc0, 0xb6, 0xdb, 0x34, 0x73, 0x75, 0x07, 0xa9, 0x4f, 0x91, + 0xdf, 0xc2, 0x69, 0x50, 0x99, 0xe9, 0xf7, 0xc2, 0xa9, 0x30, 0x10, 0x75, 0xf1, 0x49, 0x7f, + 0x26, 0x09, 0x8d, 0x6b, 0x6b, 0xfa, 0xf8, 0x9c, 0x6e, 0x5a, 0x08, 0xed, 0x89, 0x57, 0x12, + 0x38, 0x18, 0xf6, 0x14, 0x51, 0x8a, 0x6c, 0x4e, 0x04, 0x60, 0xd3, 0x01, 0x78, 0x33, 0x16, + 0x00, 0x78, 0x81, 0x0f, 0x4d, 0x5b, 0x54, 0x31, 0x08, 0x2c, 0x6a, 0x6d, 0x76, 0x3e, 0xeb, + 0x58, 0x04, 0x94, 0x86, 0xf0, 0x2f, 0x16, 0xfd, 0xa8, 0x34, 0x1d, 0x71, 0x33, 0x1c, 0x32, + 0x61, 0xf5, 0xf7, 0x8e, 0xf3, 0x9a, 0xdc, 0x65, 0x0f, 0x84, 0xe9, 0xed, 0xf2, 0x12, 0xf6, + 0xe0, 0x6c, 0x42, 0xd1, 0xe6, 0x80, 0x61, 0x60, 0x4d, 0x97, 0xb3, 0x11, 0x3f, 0x57, 0xe3, + 0xbe, 0x90, 0x25, 0xaf, 0xec, 0x25, 0x11, 0x6b, 0xdb, 0x40, 0x3d, 0x51, 0xe5, 0x75, 0x16, + 0xbe, 0xcb, 0xb0, 0xd9, 0xee, 0xd6, 0x38, 0x5a, 0xc6, 0xe5, 0x9b, 0x2d, 0x84, 0x5b, 0x12, + 0xc9, 0x5c, 0x89, 0x99, 0x2a, 0x9e, 0xda, 0xb7, 0xd3, 0xfd, 0xf3, 0x5d, 0x30, 0xae, 0xf5, + 0xd8, 0xeb, 0xc6, 0x90, 0x02, 0x51, 0xc9, 0xbc, 0xaf, 0x36, 0x2d, 0xa4, 0xf4, 0x76, 0xcd, + 0x34, 0x89, 0x6c, 0x44, 0x6e, 0x41, 0xb2, 0x7b, 0x85, 0xf1, 0x72, 0xa1, 0xf3, 0xe0, 0x07, + 0xf3, 0x56, 0x58, 0xc6, 0x86, 0x13, 0x50, 0x70, 0xd5, 0x4e, 0x23, 0xb5, 0x15, 0x4f, 0x3e, + 0x5a, 0x80, 0x22, 0x4e, 0x2e, 0x05, 0x01, 0x1a, 0x72, 0x95, 0x50, 0xfe, 0x90, 0xcf, 0xe5, + 0xa1, 0x2a, 0x28, 0x63, 0x49, 0x4c, 0xd2, 0x88, 0x9b, 0x5a, 0x5f, 0x29, 0xf2, 0xa0, 0x14, + 0x78, 0xac, 0x02, 0x0a, 0x3e, 0xd6, 0xbf, 0x7a, 0x74, 0x5d, 0x21, 0x4e, 0xb6, 0x14, 0xd7, + 0x33, 0x64, 0x6e, 0x8c, 0x6d, 0x54, 0x87, 0xc6, 0x00, 0x44, 0xa4, 0x3c, 0x0a, 0x13, 0xcc, + 0xfd, 0x33, 0x6c, 0xb3, 0x6a, 0xb2, 0xb6, 0x49, 0x40, 0xcc, 0x6e, 0xfc, 0x59, 0xcc, 0xb7, + 0x7a, 0xbc, 0xd5, 0xe0, 0xb7, 0x31, 0x5e, 0x88, 0xe9, 0x16, 0xbe, 0x17, 0x12, 0xe0, 0x96, + 0x4d, 0xf7, 0x6e, 0x01, 0x2e, 0x68, 0xfc, 0xda, 0x6c, 0x2b, 0x0d, 0x54, 0x84, 0x9a, 0x6c, + 0xe1, 0xc4, 0xba, 0xc9, 0x4a, 0xca, 0xae, 0x0f, 0xcb, 0x6e, 0xf9, 0x19, 0x6c, 0x6f, 0x84, + 0xf1, 0xda, 0x0e, 0xd6, 0x2b, 0x40, 0xbd, 0x5e, 0xc6, 0x02, 0xe8, 0x97, 0x15, 0xa0, 0x76, + 0x07, 0x47, 0xa5, 0x32, 0xd4, 0x64, 0x16, 0xb2, 0x68, 0x49, 0xe9, 0x06, 0xd4, 0x36, 0xeb, + 0x23, 0x2a, 0x7b, 0x4f, 0x87, 0x3e, 0x63, 0x57, 0xed, 0x03, 0xba, 0xb9, 0x74, 0x86, 0xf1, + 0xaa, 0xdd, 0x70, 0xd1, 0xb9, 0xc5, 0x51, 0x8e, 0x2c, 0x98, 0xf2, 0x5b, 0xf6, 0x3a, 0x79, + 0x95, 0x37, 0xe1, 0x91, 0xca, 0x01, 0x78, 0x24, 0xe2, 0x3e, 0x94, 0xe1, 0xf5, 0x24, 0x13, + 0xa1, 0xb5, 0x06, 0xe9, 0x15, 0xa4, 0xac, 0x91, 0x67, 0x8a, 0xd8, 0x1a, 0x53, 0xd6, 0x3f, + 0x58, 0x3c, 0xc4, 0xfd, 0x05, 0x2b, 0xce, 0x3c, 0x86, 0x88, 0x22, 0x06, 0x34, 0x96, 0x59, + 0x39, 0x38, 0x5f, 0x2f, 0x8d, 0xc8, 0xd6, 0x86, 0xbc, 0xa3, 0x41, 0x84, 0x50, 0x49, 0xa3, + 0x46, 0xad, 0xb0, 0xc2, 0x00, 0xa7, 0xb7, 0x14, 0xca, 0xe3, 0x39, 0x4e, 0x84, 0x49, 0xa1, + 0x78, 0x8f, 0x95, 0x73, 0x48, 0xfa, 0x2c, 0xe3, 0x77, 0x92, 0x84, 0x0e, 0x8b, 0x5f, 0x49, + 0xfe, 0x21, 0x3b, 0x90, 0xee, 0x21, 0x2c, 0x73, 0x18, 0xbf, 0xa1, 0x06, 0xe1, 0xc1, 0xd8, + 0xac, 0x5f, 0xe4, 0xe5, 0x83, 0x13, 0x8a, 0xd4, 0xff, 0x58, 0x38, 0x1c, 0x5d, 0x5d, 0xa9, + 0x3c, 0xca, 0xb5, 0xcd, 0xda, 0xff, 0x6d, 0x14, 0x0d, 0x99, 0xa6, 0xae, 0xfa, 0x5b, 0x0f, + 0xd0, 0x20, 0x97, 0x30, 0xbc, 0x34, 0x63, 0xfd, 0x77, 0x09, 0x7b, 0x2b, 0xcd, 0x5e, 0x01, + 0xe9, 0x98, 0x07, 0xb8, 0xb5, 0xc2, 0xc3, 0x77, 0xc7, 0x16, 0xe0, 0xc3, 0xaa, 0x5b, 0x52, + 0x99, 0x0e, 0x15, 0x6c, 0x10, 0xfc, 0x3c, 0x71, 0xab, 0x6c, 0xcc, 0xad, 0x0e, 0x7d, 0xed, + 0xe2, 0xdf, 0xcd, 0xd1, 0x8b, 0xb4, 0x8f, 0x77, 0x8f, 0x40, 0x02, 0x3e, 0x38, 0x39, 0x91, + 0xb9, 0x80, 0xab, 0x30, 0x0d, 0xba, 0x52, 0x97, 0x38, 0x81, 0xb5, 0x4b, 0x47, 0x66, 0xf5, + 0x58, 0x4d, 0x75, 0x57, 0x90, 0xa1, 0xf5, 0xcd, 0x8c, 0x1b, 0x8d, 0xbd, 0xfb, 0xf4, 0xed, + 0xd2, 0xdf, 0xb6, 0x36, 0xc3, 0x6e, 0xbd, 0x97, 0x78, 0x3f, 0x4f, 0xb8, 0x31, 0x00, 0x60, + 0x39, 0x75, 0xee, 0xef, 0xdd, 0x61, 0x2c, 0xcb, 0x3c, 0x55, 0x00, 0x67, 0xbb, 0x9e, 0x57, + 0x5f, 0x73, 0x45, 0xc3, 0xff, 0xa4, 0x04, 0x0b, 0x21, 0x9b, 0xd8, 0x57, 0xa2, 0x88, 0x2a, + 0xf2, 0x71, 0x94, 0xe3, 0x85, 0x0f, 0x7c, 0x2e, 0x96, 0x14, 0x24, 0x4a, 0xb4, 0xc7, 0xfb, + 0x18, 0x51, 0x6f, 0xcb, 0x84, 0xd7, 0xf1, 0x35, 0x62, 0xae, 0x7c, 0x5c, 0x8c, 0x62, 0x12, + 0x36, 0xed, 0x38, 0xb1, 0x33, 0x02, 0x66, 0x61, 0xce, 0xb3, 0xc2, 0x92, 0x15, 0xcb, 0x80, + 0x19, 0xbf, 0x76, 0x89, 0x45, 0x20, 0x89, 0x27, 0xb9, 0xea, 0x91, 0x8b, 0xcf, 0x72, 0xdc, + 0xd5, 0xf9, 0x95, 0x4b, 0xf2, 0x96, 0xf8, 0xf6, 0x97, 0x7c, 0xa3, 0xc2, 0xb5, 0x3e, 0x0a, + 0x88, 0xbf, 0x87, 0x24, 0xf4, 0xc3, 0x3f, 0x8a, 0x99, 0x63, 0xc4, 0x94, 0xd2, 0x29, 0x21, + 0x06, 0x17, 0xed, 0x3e, 0xbf, 0x63, 0x3d, 0xf8, 0xe9, 0x9b, 0x4a, 0x43, 0xf4, 0xc0, 0x4c, + 0xe3, 0x50, 0x5f, 0x67, 0x2e, 0x51, 0xd7, 0x56, 0x09, 0xd0, 0xf6, 0x8f, 0x27, 0xd5, 0xda, + 0x03, 0x2f, 0xad, 0x49, 0xfc, 0xc8, 0x11, 0x92, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5f, 0xd6, 0x1c, 0x7a, 0x83, 0xfd, 0x08, 0x31, 0xa4, 0xc2, 0xd7, 0xed, 0xd3, + 0x13, 0x02, 0x5e, 0xb3, 0x4b, 0xf1, 0x70, 0xb1, 0xf4, 0x20, 0x7a, 0xbf, 0xeb, 0xbf, 0x17, + 0x4f, 0x13, 0x89, 0x2d, 0xfd, 0xe0, 0x1c, 0xf8, 0xfe, 0x41, 0x80, 0xed, 0x2c, 0xe8, 0x8c, + 0xa8, 0x5d, 0xfb, 0xeb, 0x24, 0xc7, 0x0b, 0xb0, 0x44, 0x4c, 0x42, 0xa4, 0x9f, 0x6e, 0x04, + 0xae, 0x5f, 0x0c, 0x0f, 0x48, 0x7b, 0x33, 0xc1, 0x35, 0xe7, 0xe1, 0x89, 0x07, 0x42, 0x6f, + 0x41, 0x0b, 0x2d, 0xdd, 0xe5, 0x44, 0xa0, 0xf2, 0xe3, 0xd4, 0x73, 0xf4, 0x91, 0x39, 0x7d, + 0x5b, 0x3f, 0x2a, 0xc7, 0xd3, 0x32, 0x3c, 0x26, 0x5e, 0x83, 0x31, 0xec, 0x7e, 0xe8, 0x0b, + 0xfa, 0x3a, 0x48, 0x7c, 0x2a, 0xb2, 0xb6, 0xda, 0x18, 0x21, 0xe4, 0x6b, 0xe6, 0xc9, 0xe2, + 0x92, 0x03, 0x9c, 0x94, 0x27, 0x46, 0xbd, 0xd8, 0x74, 0xb7, 0x87, 0xbb, 0x18, 0xae, 0x29, + 0x01, 0x74, 0x81, 0x42, 0x5f, 0x5a, 0x61, 0x91, 0xb9, 0x04, 0x42, 0x46, 0x9b, 0x2d, 0x74, + 0x1b, 0x06, 0x18, 0xc5, 0x7b, 0xf1, 0x95, 0xf8, 0xd6, 0x23, 0x62, 0xfc, 0x71, 0x5d, 0xa9, + 0xeb, 0xcf, 0x55, 0x3e, 0x19, 0x1a, 0x8e, 0x36, 0x5f, 0x94, 0x6d, 0x1d, 0xf3, 0x4a, 0xd0, + 0x79, 0x43, 0x9a, 0x4a, 0xff, 0x9f, 0xbf, 0xf3, 0xeb, 0x40, 0xd9, 0xd5, 0xb5, 0xfd, 0xa9, + 0xe1, 0xaf, 0xd2, 0x15, 0x2e, 0x8a, 0x2f, 0x7a, 0xaf, 0xbb, 0xc4, 0xc1, 0xfb, 0x21, 0x6a, + 0x08, 0x55, 0x70, 0x78, 0x59, 0x40, 0xb9, 0x11, 0x2a, 0xfc, 0x2e, 0x47, 0x25, 0xe6, 0x78, + 0xf1, 0x18, 0x0e, 0x82, 0xec, 0xcb, 0xd4, 0xc7, 0xff, 0xca, 0xd2, 0x8d, 0xd2, 0xc2, 0x38, + 0x19, 0xb3, 0xe7, 0x46, 0x18, 0x95, 0xf2, 0x8a, 0x4d, 0x96, 0x83, 0x50, 0xf3, 0x2f, 0x4e, + 0x44, 0x7b, 0xfc, 0x66, 0xbc, 0x32, 0x1a, 0x68, 0x45, 0xd6, 0x5d, 0xcc, 0x20, 0x21, 0x2f, + 0x56, 0x14, 0xf5, 0xd0, 0x90, 0x0c, 0x98, 0x87, 0x69, 0xa9, 0x5c, 0x37, 0x97, 0xbb, 0x78, + 0x62, 0x15, 0xf7, 0xaa, 0xda, 0x71, 0x97, 0x28, 0x65, 0x4f, 0x40, 0xf7, 0x15, 0x22, 0xb9, + 0xa5, 0x08, 0xd2, 0x1d, 0xca, 0x0d, 0xcc, 0xfc, 0x8f, 0xf8, 0x89, 0xf8, 0xee, 0x7c, 0xfe, + 0x70, 0x93, 0xb3, 0xd4, 0x0f, 0x5f, 0xf9, 0x36, 0xc5, 0x29, 0x56, 0x12, 0x5a, 0xd9, 0x7e, + 0x02, 0x1e, 0x9b, 0x23, 0x77, 0x5e, 0x4d, 0xbf, 0x7e, 0x85, 0x00, 0x7a, 0x75, 0x3d, 0x58, + 0x97, 0x5f, 0x41, 0xe3, 0xdd, 0x72, 0xd6, 0x4c, 0x75, 0x3e, 0x4a, 0xa4, 0x7e, 0xb4, 0xcc, + 0x3c, 0x75, 0x40, 0x41, 0x9f, 0x55, 0x79, 0x60, 0xe0, 0x4b, 0xaf, 0x9b, 0x5a, 0x4c, 0x8d, + 0x38, 0xa7, 0x0b, 0xcd, 0x93, 0x30, 0x6a, 0x23, 0xce, 0xb1, 0x3a, 0x74, 0x43, 0xb4, 0xd6, + 0xc0, 0x20, 0x2a, 0x90, 0x6d, 0xfb, 0x91, 0xf2, 0xd8, 0xe8, 0x4d, 0x0d, 0xcb, 0x48, 0x49, + 0xc3, 0x45, 0xf5, 0x68, 0xbc, 0x86, 0x47, 0x26, 0x61, 0x71, 0x55, 0x59, 0xc7, 0x02, 0x43, + 0x1b, 0x65, 0x13, 0x99, 0x45, 0x3e, 0x03, 0x31, 0xe8, 0x00, 0x00, 0x7e, 0x39, 0x4a, 0x81, + 0x89, 0xda, 0x5d, 0xea, 0xe9, 0xb7, 0x10, 0xcc, 0xcc, 0x76, 0xd7, 0x02, 0xcb, 0xd8, 0x07, + 0xa0, 0x80, 0x94, 0xbe, 0xf7, 0xed, 0xca, 0x3c, 0xe6, 0x5f, 0xf3, 0x7e, 0x5c, 0xc1, 0xfe, + 0x26, 0x92, 0x42, 0x50, 0x8d, 0x9b, 0x20, 0xa5, 0x8c, 0xba, 0x93, 0xee, 0x57, 0xdf, 0xf4, + 0x03, 0x08, 0x5a, 0x63, 0x97, 0x46, 0x47, 0xb7, 0x4d, 0x58, 0x78, 0xf1, 0x56, 0xa2, 0x10, + 0xc0, 0xdf, 0x7f, 0x29, 0xeb, 0x70, 0x6f, 0x1a, 0xf0, 0x84, 0xca, 0xca, 0xde, 0x4a, 0x0f, + 0x0c, 0x1e, 0x05, 0x05, 0xb3, 0xb2, 0x2c, 0x67, 0x29, 0x51, 0x2b, 0x7e, 0xc9, 0xf0, 0x87, + 0x2b, 0x9b, 0xff, 0x75, 0xdb, 0xa3, 0x8d, 0x55, 0x95, 0x50, 0x82, 0x90, 0xdf, 0x86, 0xb9, + 0xa7, 0xf2, 0x69, 0xfb, 0x48, 0x17, 0xe5, 0xb3, 0x19, 0x65, 0xd1, 0x90, 0x72, 0xe8, 0xca, + 0xb5, 0xbd, 0xaa, 0x1b, 0x00, 0xf7, 0x3f, 0x75, 0x80, 0xe4, 0x6f, 0xb3, 0x0c, 0xb9, 0x6e, + 0x53, 0x26, 0xb4, 0xa7, 0x6b, 0x4b, 0xa8, 0x39, 0xa4, 0xd6, 0x1d, 0x9d, 0xdf, 0xe8, 0x70, + 0x5f, 0x97, 0xaa, 0xcd, 0x45, 0xfe, 0xcb, 0x58, 0xfd, 0x10, 0x6d, 0x89, 0xc7, 0x64, 0x88, + 0x0d, 0xad, 0x12, 0x30, 0x50, 0x4e, 0xac, 0xdf, 0x3a, 0x53, 0x90, 0x86, 0xaa, 0xe2, 0x1d, + 0xcf, 0xfa, 0xaf, 0xb9, 0x57, 0xa2, 0xb4, 0xce, 0x46, 0x03, 0x02, 0x9a, 0x0f, 0x56, 0x48, + 0x99, 0x94, 0x6c, 0x55, 0x5b, 0x39, 0xe7, 0xee, 0x8a, 0xa9, 0x49, 0x8c, 0x69, 0xa3, 0x89, + 0xef, 0xf9, 0xa5, 0x47, 0x0e, 0x2a, 0xf6, 0xe4, 0xc8, 0x76, 0x61, 0x64, 0xc2, 0xb1, 0x40, + 0x6f, 0x83, 0xda, 0xca, 0xe9, 0x82, 0x45, 0x42, 0xfd, 0xe4, 0x51, 0x27, 0x08, 0xb3, 0xb2, + 0xa3, 0x98, 0xd0, 0xfc, 0xad, 0xfa, 0xa5, 0xd8, 0x0c, 0x03, 0xfa, 0x69, 0xe5, 0xe8, 0x60, + 0x3a, 0x0f, 0xcf, 0x4b, 0x26, 0xc1, 0x4d, 0x60, 0x8a, 0xfe, 0x9f, 0x17, 0x30, 0xc6, 0x50, + 0x76, 0xa9, 0x50, 0x94, 0x9a, 0x71, 0xf7, 0x94, 0x38, 0xb3, 0x2b, 0xc9, 0xab, 0x0e, 0x22, + 0x5b, 0x04, 0xed, 0x1b, 0x14, 0x16, 0x34, 0x8c, 0x86, 0x2c, 0xb8, 0xcc, 0xc7, 0xfa, 0x84, + 0x9c, 0xec, 0x4a, 0x62, 0x9d, 0x24, 0x0b, 0x86, 0x07, 0xd3, 0xb3, 0xdb, 0xfe, 0x00, 0x9d, + 0x7c, 0x8d, 0x60, 0x03, 0x6e, 0x37, 0xe4, 0x27, 0x76, 0xb6, 0x66, 0x3f, 0xbe, 0x16, 0xb9, + 0x37, 0x9c, 0x22, 0x84, 0xa8, 0x29, 0xf5, 0xa5, 0xe4, 0x07, 0xf9, 0x01, 0x59, 0xb0, 0xa5, + 0x1b, 0x91, 0xb5, 0xd0, 0x22, 0x11, 0x4b, 0x6f, 0x1f, 0xb8, 0x2e, 0x50, 0xb3, 0xb2, 0x78, + 0xfb, 0x86, 0x16, 0x38, 0xb6, 0x1e, 0x75, 0x29, 0x4b, 0x39, 0x27, 0x49, 0xe8, 0xc2, 0x89, + 0xeb, 0x04, 0x8d, 0xfb, 0xcc, 0xb7, 0x35, 0xd9, 0xb3, 0x80, 0x46, 0xbc, 0xf6, 0xda, 0x54, + 0x3e, 0x73, 0x2c, 0x8e, 0x97, 0x03, 0xd5, 0x5f, 0xfc, 0x6a, 0x4a, 0x27, 0x0f, 0xee, 0x27, + 0x5c, 0x51, 0x9b, 0xa4, 0xf5, 0xc8, 0x6d, 0x89, 0x2b, 0xc0, 0x9f, 0x51, 0xb2, 0x54, 0x8d, + 0x57, 0x5d, 0x31, 0x30, 0x92, 0xb8, 0x74, 0xd4, 0xb4, 0x81, 0xb3, 0x74, 0xc1, 0x82, 0xe8, + 0xfd, 0xa9, 0x73, 0x5e, 0x97, 0x2b, 0xc7, 0x0f, 0x98, 0x0e, 0x41, 0xe5, 0xee, 0xbf, 0xcc, + 0x54, 0x8f, 0x5c, 0x01, 0x01, 0x41, 0x6f, 0xae, 0x13, 0x30, 0x8b, 0xac, 0x9d, 0x1a, 0x92, + 0x2e, 0xb3, 0x0d, 0x97, 0xac, 0x74, 0x30, 0xed, 0xf9, 0xa8, 0x18, 0xf4, 0x86, 0xe1, 0xcc, + 0xb2, 0x91, 0x77, 0xe7, 0x8e, 0x61, 0xe3, 0x25, 0x59, 0x45, 0x58, 0x09, 0xf2, 0x11, 0x53, + 0xea, 0xe4, 0xbf, 0x81, 0xb0, 0x77, 0xcb, 0xbe, 0x01, 0x58, 0xfe, 0x9b, 0x01, 0xc9, 0xe3, + 0x6b, 0xaa, 0xc4, 0xf6, 0x82, 0x47, 0x03, 0xa9, 0xe9, 0xe9, 0x0b, 0xdc, 0xdc, 0x7a, 0xbd, + 0xdd, 0xb6, 0xbb, 0x32, 0x91, 0xdf, 0xe4, 0x06, 0xce, 0x04, 0x02, 0x5a, 0x99, 0xb6, 0x1b, + 0x19, 0xe3, 0xa8, 0x3d, 0xd4, 0xc0, 0x77, 0x27, 0xe6, 0x83, 0xac, 0x55, 0xcd, 0x0b, 0x75, + 0x76, 0x53, 0xda, 0xbf, 0xe0, 0x8a, 0xa1, 0x33, 0x11, 0xc5, 0xbc, 0x47, 0xf2, 0x09, 0xdd, + 0x07, 0x6a, 0x69, 0xe1, 0x83, 0x95, 0x0e, 0xe4, 0xad, 0xf3, 0x18, 0xa7, 0xe1, 0x9b, 0xba, + 0x32, 0x7c, 0xb9, 0xec, 0xa7, 0x01, 0x4c, 0xc7, 0x04, 0xc8, 0x03, 0x52, 0xb8, 0xea, 0x73, + 0x2d, 0xf2, 0x18, 0x8f, 0x1a, 0x0b, 0x1f, 0x8c, 0xa4, 0x63, 0x4f, 0x92, 0x6d, 0xcf, 0x18, + 0x62, 0x3a, 0x64, 0x9c, 0x80, 0xb6, 0xaf, 0xe9, 0x27, 0x36, 0x9f, 0xd4, 0x8f, 0x74, 0xdc, + 0x74, 0x85, 0x30, 0x4d, 0xbc, 0x01, 0xdd, 0xa4, 0x0d, 0x99, 0x20, 0x79, 0x45, 0x92, 0xe2, + 0x0d, 0xef, 0x16, 0x52, 0x60, 0x68, 0x86, 0x71, 0x32, 0x96, 0x14, 0xcc, 0x8a, 0x43, 0x0d, + 0x9c, 0xd6, 0x48, 0x7f, 0x71, 0xbc, 0x38, 0xe4, 0xac, 0xda, 0x23, 0x90, 0xa9, 0x40, 0x5d, + 0x77, 0x79, 0x9d, 0x39, 0x40, 0x51, 0x22, 0xa5, 0xa5, 0x8f, 0xd6, 0x37, 0xc4, 0x97, 0xa7, + 0x7a, 0x1a, 0xb2, 0xf6, 0xd8, 0x9f, 0x6a, 0x0f, 0x91, 0x3f, 0x26, 0x0b, 0xc6, 0xd9, 0xcd, + 0xd2, 0x7a, 0x8c, 0xdc, 0xd9, 0x8b, 0xd1, 0x9e, 0x62, 0x82, 0x0a, 0xa7, 0x05, 0xd1, 0x08, + 0xc9, 0x32, 0x71, 0xe2, 0x49, 0xcf, 0xf0, 0x2e, 0x1a, 0x49, 0x7f, 0x1e, 0x11, 0x20, 0xd9, + 0xb8, 0x75, 0xda, 0x29, 0xa5, 0x02, 0x8d, 0x62, 0x4f, 0x44, 0x6f, 0xdd, 0x66, 0x9e, 0x15, + 0xbf, 0x8c, 0xda, 0xac, 0xd7, 0x06, 0xf3, 0x52, 0xe2, 0x43, 0x01, 0xe4, 0x9b, 0xf2, 0x0a, + 0x7f, 0x47, 0xc9, 0x51, 0xa7, 0xfb, 0xcc, 0xb3, 0x28, 0x9f, 0xce, 0xaf, 0x7e, 0x46, 0x15, + 0xd5, 0x53, 0x75, 0xee, 0x63, 0x87, 0xbf, 0x95, 0xde, 0x52, 0x50, 0xe8, 0xf2, 0xee, 0x74, + 0xea, 0x06, 0x84, 0xd4, 0xa1, 0xf5, 0xf1, 0x37, 0xc8, 0x73, 0x9a, 0xfa, 0xad, 0x6f, 0x00, + 0x5c, 0x07, 0x01, 0x24, 0xe7, 0x8b, 0x83, 0x35, 0x0e, 0x61, 0x5f, 0xa8, 0x5b, 0xaf, 0x15, + 0x8a, 0xc9, 0xe0, 0x8b, 0x3b, 0xce, 0x47, 0x33, 0x2c, 0x14, 0x78, 0xc4, 0x96, 0x7c, 0x9d, + 0xfb, 0xe6, 0x23, 0xbe, 0xbf, 0x84, 0x7f, 0x9c, 0x18, 0xb0, 0x25, 0xd0, 0xe4, 0x98, 0x9d, + 0x01, 0x04, 0x67, 0x14, 0x0d, 0xa6, 0x76, 0x08, 0xec, 0xc7, 0x89, 0x27, 0x26, 0x96, 0x79, + 0x79, 0x95, 0xee, 0x90, 0x00, 0xac, 0xc5, 0x4d, 0xc2, 0x4f, 0x8e, 0x11, 0xb4, 0x0a, 0xaa, + 0x90, 0x04, 0x9f, 0x56, 0x6c, 0x9e, 0x80, 0xe0, 0xaf, 0xf8, 0x68, 0xd8, 0x39, 0x63, 0x6c, + 0x1b, 0x2b, 0x56, 0x79, 0xb0, 0x00, 0x01, 0x22, 0xaf, 0xa4, 0x9b, 0x9f, 0x69, 0x04, 0x96, + 0x3d, 0xfb, 0xae, 0x74, 0x95, 0xac, 0x6c, 0x14, 0x9e, 0x9b, 0x0f, 0x3b, 0xa2, 0x11, 0x8a, + 0x8b, 0xee, 0x90, 0x98, 0x6e, 0xa9, 0x5c, 0x26, 0x34, 0x90, 0xe5, 0xfb, 0x28, 0xcd, 0x8a, + 0x3e, 0x64, 0x44, 0x77, 0xd0, 0x80, 0x04, 0x20, 0xc7, 0x62, 0xf6, 0x51, 0x9e, 0x24, 0x4d, + 0x0e, 0xc7, 0xa7, 0xf1, 0xdb, 0x53, 0x09, 0xaf, 0xca, 0x30, 0x3a, 0xdc, 0xad, 0x15, 0x1e, + 0xd7, 0xf4, 0x3c, 0x6a, 0x44, 0x2b, 0x24, 0xb5, 0x51, 0xd5, 0x93, 0x66, 0x89, 0xad, 0x3d, + 0x51, 0x73, 0x60, 0x75, 0xa2, 0x26, 0x04, 0x4e, 0x44, 0x1c, 0xb3, 0x80, 0x8c, 0x1b, 0x3d, + 0xd7, 0x7a, 0xc3, 0x7b, 0x93, 0x95, 0xa9, 0x97, 0x3d, 0x18, 0xe6, 0x5c, 0x09, 0x07, 0x70, + 0xbf, 0x4e, 0xcb, 0x6d, 0x19, 0xec, 0xb5, 0x8f, 0x84, 0x8a, 0x41, 0x3f, 0x40, 0x43, 0x59, + 0xa4, 0x68, 0x0d, 0x9b, 0xa7, 0x02, 0x07, 0x2b, 0x92, 0x56, 0xc1, 0x61, 0x1e, 0x93, 0xaa, + 0xc9, 0x97, 0x9a, 0x85, 0x07, 0x34, 0xd8, 0xbd, 0x9d, 0x9f, 0xb1, 0x0e, 0x5d, 0x75, 0xe9, + 0x35, 0xb5, 0x75, 0x09, 0xdc, 0x8c, 0xda, 0x2a, 0x81, 0x4b, 0x4e, 0xaf, 0x51, 0xb6, 0x35, + 0x31, 0x18, 0xdd, 0x7b, 0x14, 0x80, 0x18, 0xfd, 0x6e, 0x2c, 0x29, 0x4a, 0x0f, 0x7e, 0x64, + 0x76, 0x5e, 0xcd, 0x41, 0x5e, 0x0c, 0x4a, 0xfa, 0x5a, 0xe6, 0x97, 0xa4, 0x4c, 0xeb, 0xd5, + 0x57, 0x6d, 0xb5, 0xb3, 0xd6, 0x23, 0x7f, 0x14, 0x36, 0x11, 0x27, 0xe1, 0xe3, 0x89, 0xdb, + 0x0d, 0x4f, 0x4f, 0xfb, 0xad, 0x7f, 0x78, 0x90, 0x76, 0x3f, 0x60, 0xbd, 0xb6, 0x56, 0x1c, + 0xe1, 0x14, 0xa1, 0x2a, 0x75, 0x52, 0xc6, 0x38, 0x9d, 0x61, 0xf4, 0xea, 0xc5, 0xf3, 0x15, + 0x1f, 0x77, 0x22, 0xa8, 0xe2, 0x46, 0xce, 0xb9, 0xff, 0xbc, 0xe1, 0x0a, 0xb0, 0x97, 0xb7, + 0xf9, 0x3b, 0x44, 0x85, 0x25, 0xaf, 0x69, 0x5e, 0xf2, 0x96, 0x56, 0x41, 0xf0, 0x22, 0xb2, + 0xd5, 0xe3, 0x92, 0x15, 0x01, 0x59, 0xf9, 0x1e, 0xe2, 0x64, 0x0e, 0xa7, 0x9f, 0xd9, 0x5f, + 0x4a, 0x82, 0x2b, 0xac, 0xaa, 0x36, 0x2c, 0x80, 0x2f, 0x68, 0x5d, 0x1c, 0xaf, 0x3e, 0x83, + 0xca, 0x00, 0x42, 0x83, 0xdd, 0xce, 0x1f, 0x63, 0x06, 0x83, 0x48, 0x99, 0xb8, 0x4b, 0x4c, + 0xbf, 0xe0, 0x02, 0x0c, 0x17, 0x10, 0xd7, 0x14, 0x6f, 0xac, 0xf5, 0x15, 0xcf, 0x2a, 0xb2, + 0xbb, 0xdd, 0x9a, 0x5b, 0x12, 0xed, 0x89, 0xdb, 0xc7, 0x9c, 0xe3, 0x62, 0x64, 0x73, 0x50, + 0x09, 0x42, 0x51, 0x76, 0x67, 0x0d, 0x3b, 0x64, 0x6c, 0x47, 0xf9, 0x7f, 0xae, 0x23, 0x40, + 0xb8, 0xce, 0x37, 0xc9, 0x8f, 0xf3, 0x52, 0x4a, 0x92, 0xae, 0x25, 0x99, 0xe4, 0xb4, 0xc0, + 0xe3, 0x87, 0x43, 0x1f, 0xa4, 0x1b, 0x01, 0xb1, 0xdc, 0xcc, 0xb7, 0x42, 0x2b, 0xab, 0x5f, + 0x09, 0x95, 0xf0, 0x7f, 0x0c, 0x4a, 0xc3, 0xf3, 0x2d, 0x80, 0x2e, 0xf0, 0xdb, 0x06, 0x06, + 0xbe, 0x1d, 0x48, 0x04, 0x57, 0x03, 0x33, 0x1b, 0x33, 0x21, 0xbe, 0xa1, 0x6d, 0xc2, 0x0a, + 0x74, 0x9c, 0x82, 0x3f, 0x3e, 0x59, 0x31, 0x8b, 0x2b, 0xf8, 0xbd, 0x41, 0xce, 0x8d, 0xba, + 0xa3, 0xe8, 0x73, 0xce, 0xd2, 0x83, 0x61, 0x47, 0x96, 0x46, 0x0f, 0x1c, 0xc4, 0x53, 0x84, + 0x42, 0x9d, 0x56, 0xd4, 0xd6, 0x55, 0x29, 0x1c, 0x7d, 0x42, 0x6a, 0x9e, 0xd7, 0x27, 0x83, + 0xaa, 0xf2, 0x61, 0x22, 0x03, 0xf5, 0x8c, 0x77, 0x02, 0xab, 0xf8, 0xc9, 0x06, 0x25, 0xad, + 0xbd, 0x01, 0xaa, 0x2c, 0xb8, 0xb3, 0xc3, 0x39, 0x1d, 0x61, 0x54, 0x93, 0x9e, 0x33, 0x14, + 0x52, 0xc7, 0x25, 0x3e, 0x80, 0x6d, 0xdf, 0x82, 0xde, 0x26, 0x8c, 0xfa, 0x7c, 0xd6, 0x19, + 0x30, 0xa0, 0x37, 0xba, 0x7a, 0x2f, 0x02, 0x8c, 0x5d, 0x19, 0xec, 0xf9, 0x2b, 0x99, 0xe0, + 0xbd, 0x65, 0x13, 0x52, 0xc6, 0x90, 0x26, 0x95, 0xb1, 0xe7, 0x59, 0x3c, 0xbc, 0x0b, 0x06, + 0x72, 0x79, 0x3b, 0x35, 0x1d, 0xca, 0x90, 0x12, 0x24, 0xf0, 0x49, 0x43, 0x8f, 0xa6, 0xea, + 0x38, 0xc1, 0x9f, 0x04, 0x46, 0xe2, 0x3a, 0x89, 0xe3, 0x20, 0xa5, 0x06, 0x4c, 0x9b, 0x0b, + 0x37, 0xc0, 0x0f, 0x41, 0x2d, 0x23, 0x20, 0xaf, 0xea, 0x62, 0x6e, 0x11, 0xff, 0x17, 0x7f, + 0x6d, 0xd8, 0xbe, 0x8f, 0xe3, 0xfb, 0x26, 0x0b, 0x64, 0x2a, 0xc0, 0x50, 0xb2, 0x99, 0x10, + 0x44, 0x64, 0xbe, 0x65, 0xeb, 0x4b, 0x13, 0xee, 0xea, 0xfc, 0x38, 0x35, 0xa2, 0x82, 0xe6, + 0x0c, 0xfc, 0x19, 0x99, 0x18, 0x7c, 0x80, 0xa3, 0x8a, 0xcd, 0x6a, 0xa0, 0xff, 0x2b, 0x7c, + 0x57, 0x7b, 0x0b, 0x28, 0xd4, 0x8a, 0xb1, 0xff, 0x09, 0x12, 0x3d, 0x13, 0x8c, 0x96, 0x4a, + 0xb4, 0x18, 0xde, 0xb2, 0x59, 0x99, 0x2d, 0xda, 0x7d, 0x9d, 0xc1, 0x99, 0x58, 0x83, 0xaa, + 0xea, 0x94, 0xe8, 0xb4, 0x24, 0xf1, 0x2d, 0x30, 0x51, 0xde, 0x35, 0x25, 0x1a, 0x2c, 0x24, + 0x9c, 0xb5, 0x62, 0x06, 0x92, 0xc2, 0x24, 0x33, 0x89, 0x77, 0xfa, 0x0a, 0x44, 0xd2, 0x8f, + 0x11, 0xa2, 0x35, 0x55, 0x1a, 0xdc, 0x9b, 0x2a, 0x52, 0xf1, 0x0b, 0x8e, 0x0f, 0xf4, 0x4b, + 0xdc, 0xf6, 0x23, 0x5f, 0xbf, 0x01, 0x41, 0x95, 0x4f, 0x95, 0x48, 0x22, 0x41, 0x4f, 0x77, + 0x5b, 0xca, 0x89, 0xbf, 0xc9, 0x3f, 0x8b, 0x9a, 0x03, 0xf8, 0x8a, 0x69, 0x10, 0x39, 0x06, + 0xac, 0x72, 0x27, 0x23, 0x7b, 0xbd, 0x6f, 0x78, 0xae, 0x62, 0xd1, 0x15, 0x20, 0x1b, 0x83, + 0xae, 0x9f, 0x5a, 0xb2, 0x51, 0xb7, 0x52, 0xe2, 0x7f, 0x31, 0xf3, 0x04, 0x27, 0xab, 0x39, + 0x14, 0x25, 0x17, 0xd6, 0x35, 0x83, 0x2b, 0x69, 0xda, 0x7a, 0x6c, 0xc8, 0xae, 0xb8, 0x5f, + 0xd8, 0x1d, 0x85, 0x5a, 0x2d, 0xe3, 0x29, 0x4c, 0x84, 0xc9, 0x99, 0x6c, 0x91, 0x84, 0x98, + 0xea, 0xf4, 0x6a, 0x2c, 0x2e, 0xaa, 0x92, 0x14, 0xc0, 0xe6, 0x79, 0x6b, 0x40, 0x8a, 0x24, + 0x47, 0x15, 0x93, 0xcf, 0xf9, 0x62, 0x29, 0xdd, 0xd6, 0xb6, 0x59, 0xd0, 0xd7, 0x02, 0x2b, + 0xdb, 0x7e, 0xd9, 0x71, 0x3a, 0x2a, 0x06, 0x9b, 0xc4, 0x70, 0x24, 0xe4, 0xed, 0x89, 0xf1, + 0xa1, 0x75, 0x21, 0xaf, 0x89, 0x9a, 0x49, 0xbc, 0xf8, 0xb5, 0xf9, 0xd5, 0x70, 0xdd, 0xec, + 0xc2, 0x92, 0xd6, 0xc2, 0x04, 0x8d, 0xdf, 0x03, 0x30, 0x79, 0x84, 0x6d, 0x70, 0xd5, 0x2e, + 0xe7, 0xf4, 0x35, 0x72, 0x5b, 0x59, 0xcc, 0x78, 0x67, 0x42, 0x3c, 0xde, 0xa7, 0x2f, 0x2a, + 0xb1, 0x24, 0xdf, 0x54, 0xcc, 0x6b, 0x6c, 0x07, 0x64, 0x39, 0x56, 0x95, 0x37, 0x85, 0x28, + 0x5b, 0x84, 0x79, 0x5d, 0x40, 0x82, 0x74, 0xc9, 0xba, 0xd2, 0x29, 0x10, 0x8e, 0x4b, 0x72, + 0x2c, 0xd7, 0x30, 0xce, 0xbf, 0x34, 0x02, 0x05, 0xd3, 0xed, 0xf3, 0x10, 0x58, 0x48, 0xde, + 0x20, 0x7f, 0x3c, 0xaa, 0xd0, 0xfa, 0x6b, 0x6b, 0xae, 0xdc, 0xa9, 0x63, 0x1a, 0xf1, 0x13, + 0xb0, 0xf9, 0xb7, 0xdf, 0xd4, 0xb4, 0x37, 0x94, 0xb5, 0x21, 0x28, 0x4f, 0xba, 0x23, 0x5d, + 0x01, 0xe9, 0x0e, 0x7e, 0x71, 0x59, 0x29, 0xba, 0x07, 0xe8, 0x51, 0xaa, 0x13, 0xdf, 0xb7, + 0x96, 0xac, 0x50, 0xc5, 0x9a, 0x48, 0x27, 0xa5, 0xb8, 0xdb, 0xbb, 0x9c, 0x1c, 0x51, 0xd0, + 0x3d, 0xde, 0x63, 0x50, 0xe9, 0x4c, 0x6a, 0x4b, 0x26, 0x2d, 0xb6, 0xaf, 0xcd, 0x8d, 0xfe, + 0x99, 0x3a, 0x0e, 0x31, 0x75, 0xeb, 0x62, 0x53, 0x8f, 0x8c, 0xb6, 0xe7, 0x1a, 0x45, 0x6d, + 0x85, 0x1e, 0x1f, 0x48, 0xc8, 0x50, 0x20, 0x5f, 0x59, 0x3e, 0x68, 0xcf, 0xc5, 0xa0, 0xf7, + 0x6c, 0xa8, 0xdb, 0x7a, 0x8d, 0xbc, 0x8f, 0x7d, 0x28, 0x92, 0x5a, 0xaf, 0x3b, 0xa7, 0xf8, + 0x2e, 0x07, 0xa9, 0x56, 0x3f, 0xab, 0x0a, 0xd3, 0x57, 0x02, 0xa0, 0xc4, 0x18, 0x6f, 0x5d, + 0x58, 0x98, 0x94, 0x6d, 0x3d, 0x21, 0xaf, 0x9c, 0x01, 0x18, 0x69, 0xb1, 0x06, 0xa7, 0xeb, + 0xb5, 0x42, 0x10, 0x68, 0x1f, 0xca, 0x1f, 0x23, 0x68, 0x32, 0xab, 0x9d, 0xad, 0xb3, 0x1b, + 0x97, 0x73, 0x15, 0x10, 0x83, 0x93, 0x33, 0x09, 0x14, 0x13, 0xaf, 0xb2, 0x11, 0xc8, 0xc1, + 0x15, 0xe8, 0xce, 0x14, 0xfb, 0x7c, 0x14, 0xb2, 0x19, 0xd4, 0x12, 0x4d, 0xee, 0x2d, 0x72, + 0xf3, 0x76, 0x2c, 0x68, 0xae, 0x2e, 0xde, 0x4d, 0x5f, 0xb8, 0x9f, 0xe9, 0x08, 0xef, 0x7d, + 0x4c, 0x71, 0x48, 0x1a, 0x74, 0x15, 0x49, 0xf6, 0x36, 0xfe, 0x20, 0xd7, 0x4b, 0xff, 0x8a, + 0x2a, 0x0a, 0x19, 0x2d, 0x92, 0xa3, 0x5b, 0x11, 0x31, 0x2b, 0x97, 0x02, 0x4c, 0xc3, 0x85, + 0xe6, 0x77, 0xde, 0x92, 0x92, 0x80, 0xa6, 0x76, 0xd0, 0x35, 0xbe, 0x89, 0x16, 0xbc, 0x53, + 0xdf, 0xa3, 0x24, 0x75, 0x83, 0x3d, 0x9e, 0x2e, 0xcd, 0xa1, 0x2c, 0x1a, 0x73, 0x89, 0x8f, + 0x6a, 0xe5, 0x15, 0xf5, 0x74, 0xbc, 0x66, 0x73, 0x7a, 0x39, 0x7d, 0x72, 0xb6, 0xc9, 0x32, + 0xa7, 0x1c, 0x30, 0x25, 0xf0, 0xcc, 0xb1, 0xd8, 0x66, 0xba, 0xb3, 0xc6, 0x2f, 0xa6, 0x62, + 0x3e, 0x14, 0xd1, 0x71, 0x58, 0x83, 0x74, 0x30, 0x0d, 0x70, 0x44, 0x03, 0x3e, 0xfd, 0x62, + 0x6a, 0x06, 0x83, 0x59, 0x39, 0xfe, 0x5e, 0x35, 0x11, 0xdf, 0x9d, 0x2f, 0x57, 0x70, 0xbb, + 0x1b, 0x8b, 0x63, 0x55, 0xe6, 0xa2, 0x73, 0xb9, 0xd1, 0x83, 0x9d, 0xfb, 0xb8, 0xb6, 0x79, + 0x1a, 0xbd, 0x4a, 0x23, 0x86, 0xfb, 0x0b, 0xfc, 0xb9, 0x28, 0x49, 0xfe, 0x90, 0x67, 0x04, + 0x6f, 0x77, 0x35, 0xdc, 0x88, 0xcc, 0xd7, 0x55, 0xa9, 0x8c, 0x78, 0x4e, 0x5f, 0x6d, 0x6a, + 0x83, 0xa9, 0x22, 0x02, 0xe1, 0x29, 0x27, 0x76, 0x57, 0x29, 0x42, 0xc4, 0xcf, 0x4c, 0x3b, + 0x4c, 0x69, 0x75, 0x70, 0x1a, 0x91, 0x56, 0x9b, 0x3a, 0x43, 0x7a, 0xf2, 0x2b, 0x88, 0x4b, + 0x50, 0xc9, 0x9f, 0xd3, 0x37, 0xe7, 0xf4, 0x1b, 0x3c, 0xce, 0x32, 0xb5, 0xc9, 0x85, 0xf9, + 0x11, 0x3a, 0x40, 0x5d, 0xde, 0xd6, 0xd0, 0x7e, 0xf4, 0xf8, 0xfa, 0x4b, 0xe9, 0x34, 0xb1, + 0x8b, 0x18, 0x4b, 0xf0, 0xb5, 0x15, 0xcc, 0xa2, 0x5e, 0x36, 0x6d, 0xa8, 0x7c, 0x60, 0xe1, + 0x5d, 0x13, 0x4e, 0x3e, 0xe6, 0x4d, 0xd7, 0x3d, 0x74, 0xe8, 0xf1, 0xed, 0x36, 0x6d, 0x5c, + 0x5a, 0x92, 0xd3, 0xf3, 0x71, 0xa7, 0xdf, 0xf1, 0x86, 0x84, 0x97, 0x39, 0x52, 0x3e, 0xed, + 0xa4, 0x7b, 0xba, 0xc5, 0x5c, 0x60, 0xb9, 0xaa, 0x0e, 0x5b, 0xf2, 0x7d, 0x26, 0x07, 0x88, + 0x43, 0xa1, 0x40, 0x9d, 0x50, 0x83, 0x94, 0xe1, 0xc9, 0xc8, 0x37, 0xcf, 0x14, 0x35, 0xb2, + 0x53, 0x20, 0x94, 0x27, 0x38, 0x02, 0x09, 0x00, 0xf6, 0x19, 0xf4, 0x3e, 0xbe, 0x1b, 0x0f, + 0x37, 0x63, 0x3b, 0x1a, 0x99, 0x0a, 0xad, 0x26, 0x16, 0x0b, 0x73, 0xaf, 0x76, 0xef, 0xa5, + 0x23, 0x34, 0xa0, 0xee, 0x07, 0xd3, 0x0e, 0xcf, 0x3f, 0xac, 0x27, 0xc7, 0x03, 0xac, 0x25, + 0xc2, 0xe8, 0xf8, 0x4d, 0xac, 0x38, 0x18, 0x0e, 0xf2, 0xfe, 0xff, 0x0e, 0xcb, 0xf3, 0x78, + 0xc5, 0xf7, 0x1b, 0xdf, 0x99, 0x52, 0x82, 0x6f, 0xf2, 0x06, 0xfc, 0xfb, 0x71, 0xfd, 0x00, + 0xfa, 0x08, 0x94, 0x17, 0x59, 0xb6, 0x2c, 0xf4, 0xed, 0x35, 0x95, 0xd2, 0x95, 0xe6, 0x3a, + 0x21, 0xdb, 0x33, 0x98, 0x10, 0xcf, 0xad, 0x06, 0xa7, 0x7a, 0x20, 0xe1, 0xc1, 0x15, 0x20, + 0x02, 0x27, 0x4a, 0x2f, 0xe3, 0xb8, 0xbb, 0xd6, 0x13, 0x1d, 0x82, 0x23, 0x61, 0xf8, 0x88, + 0x79, 0x86, 0xec, 0x57, 0x8d, 0x77, 0x2b, 0x0f, 0x05, 0x7a, 0x88, 0xb5, 0x32, 0xec, 0x33, + 0xf1, 0xe8, 0x84, 0xf4, 0x1e, 0xf3, 0x27, 0xff, 0x37, 0x5a, 0xed, 0x6e, 0xad, 0x89, 0xfc, + 0x5c, 0x58, 0xcd, 0xea, 0xd5, 0x77, 0x0f, 0x0a, 0x12, 0xff, 0x45, 0xaf, 0x4a, 0xce, 0x38, + 0xaa, 0x7d, 0xf3, 0xdb, 0xda, 0x1e, 0xec, 0xfa, 0x8a, 0xa1, 0x61, 0xa3, 0x15, 0x50, 0xac, + 0xa1, 0x62, 0x54, 0x50, 0x04, 0xf1, 0x46, 0xc6, 0x9b, 0x44, 0x3c, 0xcd, 0xfb, 0x33, 0x8f, + 0xf7, 0xe7, 0xf1, 0x97, 0x86, 0x4c, 0xf3, 0xe9, 0x49, 0x5b, 0xe5, 0xad, 0x00, 0x9c, 0x9b, + 0x2c, 0x2a, 0xcf, 0x41, 0x66, 0xb0, 0x49, 0x92, 0x2d, 0x20, 0xfa, 0xdc, 0x08, 0x4a, 0xc8, + 0x1a, 0x83, 0x37, 0xee, 0x9f, 0x39, 0xe6, 0x48, 0x5f, 0x12, 0x7e, 0x62, 0x8b, 0xe9, 0x4b, + 0xf8, 0xde, 0x6e, 0xa4, 0xe7, 0x9f, 0x1a, 0x0d, 0x5c, 0x36, 0xd7, 0xda, 0x6b, 0x95, 0x07, + 0xa3, 0xda, 0x1c, 0x64, 0x84, 0x9d, 0x9f, 0x9e, 0xc2, 0x25, 0x40, 0xe8, 0x44, 0xfb, 0x35, + 0xc1, 0x8f, 0x8e, 0x06, 0xa7, 0x55, 0x42, 0x9c, 0xad, 0x32, 0x95, 0x8e, 0xdc, 0xd3, 0x83, + 0x3c, 0x39, 0x8a, 0x16, 0x40, 0xe7, 0xe2, 0x84, 0x3f, 0xa5, 0x28, 0x79, 0x34, 0xd6, 0xf5, + 0xc0, 0x8c, 0xe9, 0xcf, 0x8a, 0xbd, 0x39, 0x2c, 0x50, 0x57, 0x09, 0xa6, 0x46, 0xba, 0x0d, + 0x22, 0x44, 0x8a, 0x03, 0x4d, 0x0f, 0xcf, 0x92, 0xf9, 0xd6, 0x86, 0xbb, 0x4d, 0xec, 0x89, + 0xd1, 0x05, 0x69, 0x4c, 0xeb, 0xeb, 0xcd, 0xea, 0x7b, 0xbf, 0xc2, 0x1a, 0x02, 0xb9, 0x66, + 0xf8, 0x96, 0xd4, 0x6d, 0x5d, 0x09, 0xe0, 0xb5, 0x80, 0x9f, 0xd6, 0xd3, 0x11, 0x24, 0x3a, + 0x53, 0x09, 0x70, 0x06, 0x7f, 0x6e, 0xba, 0xa8, 0x8d, 0x96, 0x61, 0xe4, 0x75, 0x9d, 0x8f, + 0xa6, 0x52, 0x59, 0x9b, 0xc5, 0x00, 0x8f, 0x2f, 0x21, 0xc0, 0xb4, 0x16, 0x56, 0xe4, 0x4e, + 0x11, 0x45, 0x01, 0xae, 0x26, 0x7d, 0x08, 0x19, 0x4e, 0xa7, 0x22, 0x96, 0x4c, 0xbb, 0xc2, + 0x12, 0xf6, 0xc4, 0x0b, 0x39, 0x7f, 0xb7, 0xa5, 0x61, 0x35, 0x77, 0x0b, 0x4e, 0x11, 0xfb, + 0xe3, 0x5c, 0xc0, 0xfb, 0xdd, 0x19, 0x37, 0x59, 0xcb, 0x98, 0xd6, 0x08, 0x52, 0xf4, 0x87, + 0xab, 0xd7, 0x99, 0x2b, 0x87, 0x8c, 0xde, 0x74, 0x6f, 0x34, 0xd0, 0x31, 0xc6, 0xc1, 0x72, + 0x3a, 0xe2, 0x49, 0xcf, 0x61, 0xb7, 0x06, 0x67, 0x80, 0xc7, 0x87, 0x84, 0xb9, 0x86, 0x8c, + 0x99, 0x94, 0xbe, 0x54, 0xa0, 0xa9, 0x7c, 0x89, 0x7a, 0xef, 0xa9, 0x0f, 0xf9, 0x30, 0x02, + 0xb6, 0xe3, 0xf1, 0x55, 0x7b, 0xe9, 0x49, 0xa6, 0xe2, 0xa3, 0x66, 0xc6, 0xb7, 0xfd, 0xa4, + 0x58, 0x32, 0x5c, 0x30, 0x9e, 0xd4, 0x19, 0x17, 0xd2, 0x7c, 0xc5, 0x93, 0x21, 0x70, 0x8b, + 0x1b, 0xb4, 0x4f, 0x9f, 0x82, 0x88, 0x0b, 0x60, 0x3f, 0x21, 0x75, 0xab, 0x48, 0x82, 0x10, + 0x7f, 0x49, 0x6d, 0x22, 0x3a, 0xcd, 0x56, 0x75, 0x07, 0xd2, 0xdc, 0xac, 0x6b, 0x77, 0x8b, + 0x62, 0xe1, 0x3a, 0x76, 0xac, 0x9c, 0x41, 0x6c, 0x24, 0x59, 0x13, 0x63, 0x5c, 0x4d, 0xd9, + 0xfe, 0x0e, 0x5c, 0xa9, 0x69, 0x0f, 0x52, 0xd8, 0xbb, 0x13, 0x9b, 0x80, 0xdc, 0xb6, 0x7b, + 0x75, 0x1e, 0xb3, 0x7a, 0x1e, 0xed, 0x26, 0xb9, 0x27, 0xfd, 0x4d, 0x55, 0xb1, 0x29, 0xfe, + 0xa7, 0x21, 0x21, 0x8c, 0x5f, 0x96, 0xc6, 0xee, 0xc0, 0xb6, 0xe9, 0x45, 0x70, 0xe2, 0x53, + 0x70, 0xef, 0xd5, 0xbb, 0x2f, 0x28, 0x02, 0xb4, 0xfd, 0x1f, 0x62, 0xe1, 0x67, 0xa9, 0x1b, + 0x89, 0x1d, 0x0e, 0xc9, 0xb0, 0xd7, 0x97, 0xa6, 0xc9, 0xe1, 0xdc, 0xcb, 0x3e, 0x68, 0x91, + 0x07, 0x27, 0xe8, 0xda, 0x49, 0x1a, 0x3d, 0x71, 0x08, 0xbf, 0xc3, 0x61, 0xf8, 0xdd, 0x23, + 0x4b, 0x13, 0xe3, 0xa0, 0x7c, 0xc7, 0xb7, 0x56, 0x4d, 0x17, 0x66, 0x6b, 0xf9, 0x9d, 0x08, + 0x2c, 0x91, 0x6f, 0x3e, 0xff, 0xa4, 0xe7, 0xf9, 0x8a, 0xe5, 0x1f, 0xc7, 0x75, 0x69, 0x85, + 0x12, 0xce, 0xad, 0xd8, 0x6c, 0xa5, 0x76, 0x56, 0x76, 0x71, 0x56, 0xed, 0xf8, 0x0f, 0xa4, + 0x24, 0xdd, 0x69, 0xd0, 0x3c, 0x1d, 0xee, 0xba, 0xa2, 0x35, 0x95, 0x37, 0x13, 0x65, 0x64, + 0xfa, 0x42, 0x58, 0xe2, 0x6a, 0x67, 0x5c, 0x32, 0x3c, 0x68, 0x3c, 0x81, 0x12, 0xdf, 0x34, + 0x06, 0x52, 0xe4, 0x2e, 0x76, 0x6c, 0x56, 0xc3, 0xf4, 0xfc, 0xf8, 0xd0, 0x1a, 0x5d, 0x2e, + 0xed, 0x60, 0x62, 0x01, 0xd7, 0x1e, 0xc7, 0x6f, 0x14, 0x20, 0x20, 0x3e, 0x03, 0xc0, 0x10, + 0x13, 0xed, 0xbb, 0x5c, 0x37, 0xc7, 0x26, 0x71, 0x8d, 0x95, 0x89, 0x00, 0xff, 0xde, 0x69, + 0xf8, 0x06, 0x5b, 0xef, 0xa5, 0x7f, 0xf3, 0x87, 0x4f, 0x08, 0x33, 0x40, 0xdc, 0x76, 0x9a, + 0x4c, 0xb6, 0x72, 0x14, 0xcb, 0xc8, 0x7c, 0xdc, 0x91, 0x83, 0x15, 0x57, 0xcc, 0xe5, 0x69, + 0x84, 0x2b, 0x00, 0x0b, 0xbd, 0x6a, 0xae, 0x39, 0xd4, 0x9f, 0xbb, 0x59, 0x1f, 0x3f, 0xc1, + 0x8b, 0xb2, 0x1c, 0x18, 0x95, 0xfb, 0x93, 0x07, 0x89, 0xa1, 0x32, 0x60, 0xaa, 0x76, 0x6b, + 0x65, 0x79, 0x70, 0x13, 0x52, 0x1e, 0xa1, 0x51, 0x60, 0x2c, 0x2a, 0x83, 0x78, 0x36, 0x64, + 0xd3, 0x8f, 0x0d, 0xe7, 0xdc, 0x9e, 0x1e, 0x2d, 0x1d, 0x7c, 0x49, 0x21, 0x33, 0x8d, 0xe5, + 0x10, 0xea, 0xf7, 0x10, 0x5f, 0x04, 0x54, 0x01, 0xe0, 0x48, 0x73, 0xe7, 0xa1, 0xdb, 0x4d, + 0x39, 0xb1, 0x00, 0x01, 0xf9, 0xa9, 0x20, 0xa7, 0xef, 0xfd, 0x11, 0xa4, 0x89, 0x5b, 0xab, + 0x48, 0xb2, 0xce, 0xba, 0xf9, 0x4e, 0xdc, 0x4c, 0x70, 0x16, 0xc0, 0xd8, 0x72, 0x31, 0x33, + 0x35, 0xa8, 0x9b, 0x5c, 0xe9, 0x5d, 0x04, 0x61, 0x1c, 0x56, 0xad, 0x0f, 0xcc, 0x80, 0x1c, + 0x12, 0x0f, 0xee, 0xb0, 0x60, 0x03, 0xb5, 0x7a, 0x02, 0x24, 0xa2, 0x12, 0xf6, 0xc5, 0x0f, + 0x63, 0x11, 0x70, 0xe2, 0xdf, 0xa7, 0xd8, 0x2d, 0x52, 0x52, 0x67, 0x08, 0x94, 0xe6, 0x4c, + 0x53, 0x89, 0xea, 0xbf, 0x77, 0x0d, 0xda, 0xe9, 0x40, 0x21, 0xf5, 0xbf, 0x91, 0x13, 0xcb, + 0x81, 0xe0, 0x43, 0xa5, 0x7d, 0xb7, 0xf2, 0x96, 0xe5, 0xa9, 0x47, 0x58, 0x55, 0x9f, 0xc5, + 0x2e, 0x66, 0xf0, 0x79, 0x39, 0xdb, 0x07, 0xd2, 0x8e, 0x23, 0x16, 0xc2, 0x16, 0x09, 0x50, + 0x36, 0x7f, 0xdc, 0x85, 0x27, 0x2d, 0xb1, 0xe2, 0x90, 0x59, 0x64, 0x7e, 0x7a, 0xe9, 0x8d, + 0x4c, 0xd6, 0x1e, 0x06, 0x0b, 0x9d, 0x4e, 0x3a, 0x90, 0xc5, 0xcd, 0x00, 0xb2, 0xd0, 0xea, + 0xa0, 0xc4, 0x14, 0xb3, 0x4c, 0xd8, 0xa8, 0x24, 0xe3, 0x5c, 0xa3, 0xf4, 0x81, 0xba, 0xf2, + 0x74, 0xf6, 0xf7, 0xf6, 0xde, 0xae, 0x79, 0x5a, 0xa9, 0x6b, 0x34, 0x2d, 0xdf, 0x8d, 0xcc, + 0x89, 0xf9, 0xd7, 0x6d, 0x18, 0xc5, 0xf6, 0x81, 0xa1, 0x21, 0xfa, 0xe3, 0x21, 0x80, 0x17, + 0xb3, 0x20, 0x2e, 0x17, 0x9a, 0x0b, 0xd3, 0xcf, 0x35, 0xa3, 0x64, 0x10, 0xd5, 0xda, 0x8a, + 0xcb, 0xbb, 0x4c, 0x55, 0x3a, 0x5c, 0x10, 0xa4, 0xbc, 0x35, 0xce, 0xb3, 0x9f, 0x46, 0xeb, + 0xbf, 0x59, 0x1a, 0x0c, 0xad, 0xfd, 0x11, 0xcf, 0x3f, 0xf5, 0xa9, 0x24, 0xe9, 0x0f, 0xf7, + 0xc2, 0xf2, 0xfa, 0xad, 0x4a, 0xf9, 0x54, 0x8b, 0x0a, 0x4e, 0x99, 0x73, 0x5d, 0x8e, 0x77, + 0xef, 0x56, 0x9e, 0xcf, 0x46, 0x79, 0xe8, 0xb7, 0x40, 0xa6, 0x20, 0x24, 0x2c, 0xe5, 0xe0, + 0x77, 0x7c, 0xfd, 0x6a, 0x07, 0x24, 0x90, 0xcb, 0x8b, 0xc3, 0x13, 0x41, 0x89, 0xdb, 0x24, + 0x6d, 0x31, 0x6b, 0xd5, 0x17, 0xa9, 0xee, 0xe8, 0x80, 0xeb, 0x70, 0x7e, 0xb2, 0x73, 0xbf, + 0xa5, 0x4d, 0xe3, 0x22, 0x17, 0xd9, 0x15, 0x5b, 0xb2, 0xbd, 0xe9, 0x29, 0x3a, 0x0d, 0x50, + 0x6b, 0xf3, 0xba, 0x30, 0xd0, 0x34, 0x1c, 0x69, 0xd2, 0x02, 0x56, 0x02, 0x35, 0x1d, 0xa0, + 0x84, 0xf9, 0xee, 0xe0, 0x24, 0x50, 0xc4, 0x73, 0x40, 0x2e, 0x70, 0x13, 0x89, 0xc7, 0x1d, + 0x5f, 0x00, 0x82, 0x1b, 0x91, 0x2e, 0x40, 0x4c, 0x33, 0x9e, 0x38, 0xb2, 0xbd, 0xf3, 0x64, + 0x30, 0x51, 0xc2, 0x19, 0x45, 0xf0, 0x38, 0xc3, 0x99, 0x2c, 0x8f, 0x4f, 0xbc, 0xba, 0xf8, + 0x71, 0x13, 0xe2, 0x62, 0xdd, 0x02, 0x95, 0x3d, 0x23, 0x51, 0x12, 0xad, 0x22, 0x53, 0x72, + 0x1c, 0xf8, 0x6a, 0xf4, 0x49, 0xcd, 0x58, 0xf7, 0x91, 0xef, 0xec, 0x37, 0x4a, 0x23, 0xd8, + 0x41, 0xbd, 0xcf, 0x1f, 0xd1, 0x0a, 0x8d, 0x66, 0xd4, 0x49, 0x84, 0x38, 0xbb, 0xa8, 0x3f, + 0xdb, 0x28, 0x28, 0x7a, 0xeb, 0x77, 0xa2, 0xbb, 0x17, 0x9b, 0x8d, 0x4e, 0x1f, 0xde, 0xf9, + 0x43, 0x2d, 0x69, 0x92, 0x3e, 0x29, 0x4c, 0xfa, 0xe9, 0x6f, 0x20, 0x49, 0x51, 0xa0, 0x3b, + 0x41, 0x77, 0xe6, 0x0d, 0x48, 0x58, 0x94, 0x04, 0xd9, 0x1c, 0x78, 0x26, 0x8b, 0x31, 0x3f, + 0xf7, 0xb7, 0x43, 0x26, 0x47, 0x81, 0x2d, 0x12, 0x6a, 0xb2, 0xbb, 0x6c, 0xdc, 0xfe, 0xd8, + 0xa8, 0x0e, 0x1f, 0x36, 0x17, 0x1e, 0x98, 0xcb, 0x3f, 0xf3, 0x28, 0x80, 0x3e, 0xa7, 0x39, + 0x02, 0x41, 0xdf, 0x69, 0xd4, 0x8c, 0xf1, 0xd3, 0x57, 0x08, 0x64, 0xcc, 0xda, 0xac, 0x9e, + 0x19, 0xd6, 0xde, 0x81, 0xdc, 0x3e, 0xd3, 0x0d, 0xe8, 0x00, 0xa3, 0xd4, 0x13, 0x02, 0x66, + 0x9d, 0x1c, 0xe2, 0x54, 0x43, 0xa5, 0x4f, 0x64, 0x2a, 0xdd, 0x16, 0x06, 0xfe, 0x07, 0x54, + 0xae, 0xb4, 0x1b, 0x5e, 0x7c, 0x22, 0x76, 0x46, 0x51, 0x40, 0xbd, 0x77, 0x52, 0x11, 0x7c, + 0x08, 0x9e, 0x5b, 0xd8, 0x6b, 0x71, 0x7c, 0x30, 0x68, 0x92, 0x1b, 0x25, 0x24, 0x38, 0x95, + 0xa2, 0x16, 0xae, 0xa3, 0xa5, 0xa0, 0xd9, 0x93, 0xe1, 0x85, 0x3b, 0x0b, 0x77, 0x7d, 0x6b, + 0xb7, 0x20, 0x49, 0x1d, 0x67, 0x11, 0x8d, 0x4c, 0x21, 0xad, 0x82, 0x65, 0xbe, 0xe7, 0xef, + 0x38, 0x80, 0x45, 0x1a, 0x7b, 0xb0, 0x35, 0x86, 0x99, 0x9c, 0x52, 0x9a, 0x32, 0x27, 0x1b, + 0x65, 0xf1, 0x33, 0xe6, 0xd2, 0x20, 0x6a, 0xa9, 0xb5, 0x36, 0x6a, 0x6a, 0xeb, 0x5f, 0xc1, + 0x15, 0xab, 0x32, 0x86, 0x18, 0x60, 0x46, 0xe3, 0xfd, 0x2b, 0xbd, 0xbf, 0x13, 0x86, 0x32, + 0xf6, 0xf2, 0xf6, 0x4b, 0x33, 0x07, 0x54, 0x11, 0xaf, 0xf0, 0x00, 0xc2, 0x79, 0xcc, 0x51, + 0xb2, 0x28, 0x36, 0x31, 0x27, 0x12, 0x31, 0x77, 0xee, 0x21, 0xc3, 0xdb, 0xc6, 0x62, 0xb5, + 0x0a, 0xb4, 0x68, 0xa8, 0x40, 0xe4, 0x15, 0x22, 0x45, 0x84, 0x21, 0xd9, 0x81, 0xca, 0x5b, + 0x7c, 0xad, 0xda, 0x7f, 0x85, 0x0f, 0x0a, 0xe5, 0x01, 0x8c, 0x07, 0x96, 0x26, 0x62, 0x6e, + 0x58, 0x7f, 0x6a, 0x45, 0x30, 0x0f, 0x76, 0xbc, 0xf8, 0x9b, 0x07, 0x29, 0x04, 0x32, 0xd2, + 0xe5, 0x4d, 0x10, 0x8f, 0x50, 0x8e, 0x74, 0x0e, 0x3f, 0x57, 0x8d, 0x99, 0x00, 0xc2, 0x08, + 0x2d, 0x66, 0xf8, 0x14, 0x21, 0x32, 0x28, 0x4d, 0x1b, 0x1c, 0xd8, 0x4a, 0xdd, 0xe8, 0x3a, + 0x29, 0xd7, 0x64, 0x41, 0x5a, 0x57, 0xf0, 0x22, 0xd2, 0x9d, 0x2e, 0x4c, 0xcf, 0x8f, 0xaa, + 0x69, 0x76, 0x59, 0x49, 0x50, 0xd5, 0x94, 0x5f, 0x6b, 0xb4, 0xbd, 0x64, 0xb2, 0x07, 0x3e, + 0x1a, 0x62, 0x46, 0x60, 0xb4, 0xf4, 0x23, 0x7d, 0x56, 0xf5, 0xb9, 0x7b, 0x05, 0x16, 0xff, + 0xdf, 0x8a, 0x5f, 0xfa, 0x36, 0x79, 0xc0, 0xe7, 0x21, 0x85, 0x6e, 0x03, 0x92, 0x26, 0x61, + 0xed, 0x22, 0xec, 0x81, 0xc5, 0xb7, 0xbe, 0xc4, 0x8a, 0x1b, 0x22, 0x90, 0xc6, 0xee, 0x27, + 0xf2, 0x50, 0x32, 0x87, 0x0f, 0xae, 0x8f, 0x6c, 0x04, 0x85, 0x55, 0x44, 0x94, 0x5e, 0x1c, + 0x59, 0x29, 0x55, 0x09, 0xfd, 0x63, 0x98, 0x39, 0x21, 0xe7, 0x31, 0x4f, 0xbe, 0x6f, 0xdd, + 0xcf, 0x12, 0x32, 0x0d, 0x8c, 0xfd, 0x78, 0xbb, 0x4c, 0x31, 0xb7, 0x45, 0x59, 0xda, 0x15, + 0x93, 0xb3, 0x0c, 0xa5, 0xb8, 0x58, 0x97, 0xa3, 0x87, 0x40, 0xa2, 0xbb, 0x61, 0xfa, 0x54, + 0x4c, 0x3a, 0xdf, 0x13, 0x02, 0x0f, 0xb6, 0x99, 0x7f, 0x6e, 0x3d, 0x10, 0xb7, 0x13, 0x27, + 0x4a, 0xdd, 0x3d, 0x9b, 0x2a, 0x7d, 0x9a, 0x31, 0x57, 0x62, 0x76, 0xc9, 0x9a, 0xa0, 0xbe, + 0x9e, 0xbf, 0xda, 0x9d, 0x9a, 0x12, 0x5b, 0x60, 0xd5, 0x5f, 0x7d, 0x4f, 0x97, 0xae, 0x64, + 0x73, 0xa7, 0x51, 0xcb, 0x6e, 0xf9, 0xaf, 0x4b, 0x9b, 0x0b, 0xd9, 0xef, 0xb5, 0xae, 0xe3, + 0xf1, 0x22, 0x14, 0xc5, 0xbe, 0xcf, 0xa7, 0x3e, 0x9c, 0xa2, 0x38, 0x13, 0xd7, 0xba, 0xa7, + 0xa7, 0x8b, 0xeb, 0x00, 0x8c, 0x81, 0xbf, 0x29, 0x69, 0x74, 0x7f, 0x9a, 0x43, 0xee, 0xc6, + 0x02, 0x66, 0x3c, 0x60, 0x31, 0xc0, 0xe3, 0x29, 0xa3, 0x12, 0x61, 0xa2, 0x16, 0x76, 0x1f, + 0x50, 0x80, 0x29, 0x7d, 0xa5, 0x4b, 0x56, 0x24, 0x0e, 0x17, 0x52, 0xe4, 0x82, 0x06, 0xdc, + 0x31, 0xb1, 0x95, 0x8f, 0xe6, 0xce, 0x97, 0x0e, 0x1d, 0x17, 0xc9, 0x04, 0x39, 0x24, 0x54, + 0x97, 0xaa, 0x1a, 0x29, 0x6e, 0x41, 0x9c, 0x56, 0x91, 0x39, 0x13, 0xf2, 0x1b, 0xb3, 0xb5, + 0x2e, 0x7d, 0x27, 0x51, 0xda, 0x42, 0x2c, 0xe3, 0x58, 0x86, 0xa7, 0xdb, 0xbf, 0x14, 0xc4, + 0x2c, 0x8c, 0x84, 0xcf, 0xd8, 0x07, 0x0f, 0xac, 0x15, 0xec, 0x66, 0x1b, 0x1e, 0x5a, 0xe9, + 0x15, 0xb8, 0x71, 0x63, 0x81, 0x4d, 0xf5, 0x9e, 0x94, 0x5a, 0xb3, 0x12, 0x0d, 0x46, 0x8a, + 0x2b, 0x49, 0x85, 0xc1, 0xcb, 0xac, 0xa0, 0x3e, 0x80, 0x83, 0x98, 0xde, 0x2e, 0x5a, 0x41, + 0x8e, 0x3d, 0xf0, 0xda, 0xdd, 0x09, 0x8a, 0xea, 0x21, 0xcc, 0x3e, 0x9e, 0x3d, 0x0d, 0x4d, + 0x01, 0xef, 0x36, 0xaf, 0xe0, 0x4e, 0x1a, 0xef, 0x97, 0xb7, 0xa0, 0xaf, 0x14, 0xd3, 0x4e, + 0xe0, 0x92, 0x22, 0xc4, 0x3e, 0xa4, 0xd4, 0x5b, 0xd1, 0x22, 0xe8, 0x71, 0xd8, 0xf8, 0xfe, + 0xfc, 0xde, 0xe0, 0xb6, 0x2c, 0x07, 0xb5, 0xef, 0xa2, 0xf9, 0x52, 0x21, 0xc8, 0x13, 0x11, + 0x8b, 0x19, 0x04, 0xca, 0x07, 0xce, 0x41, 0xb8, 0xc5, 0xf3, 0x95, 0xa7, 0xaa, 0x1a, 0x0d, + 0xf4, 0x45, 0x1b, 0xf4, 0x8e, 0xce, 0x11, 0x8a, 0x31, 0xf2, 0xaa, 0xeb, 0x20, 0xb7, 0x32, + 0x3f, 0x16, 0x7e, 0x3a, 0xce, 0xb5, 0xb5, 0xfd, 0x3e, 0xba, 0x84, 0x55, 0xbd, 0x27, 0xbe, + 0xa1, 0x17, 0xfa, 0xa2, 0x53, 0x1b, 0x12, 0x63, 0x18, 0x85, 0x5e, 0x84, 0x00, 0xbe, 0x96, + 0xfb, 0x7e, 0x38, 0x70, 0xfa, 0x73, 0xef, 0xb4, 0xe2, 0x0b, 0x9a, 0x9c, 0x2f, 0x18, 0xec, + 0x3a, 0x0f, 0xde, 0xf0, 0x54, 0x92, 0xba, 0xc1, 0x18, 0x4b, 0x28, 0x7d, 0xe0, 0x31, 0x72, + 0x90, 0xa5, 0x1b, 0x80, 0x56, 0xc7, 0x5b, 0xac, 0x11, 0xe0, 0x02, 0x01, 0x90, 0x15, 0xfc, + 0x17, 0xcb, 0xed, 0x31, 0x14, 0xc3, 0xb4, 0xf5, 0x40, 0x8c, 0xf7, 0x3f, 0x0e, 0x4e, 0x36, + 0x6f, 0x30, 0xef, 0x00, 0xcd, 0x49, 0x25, 0x32, 0x14, 0xfb, 0x8c, 0xdb, 0xc4, 0x73, 0x00, + 0x34, 0x9d, 0xd8, 0xa8, 0x8d, 0xaf, 0x32, 0x05, 0x40, 0xbc, 0xcd, 0x93, 0x7c, 0xf2, 0x0d, + 0x0a, 0xea, 0x1e, 0x04, 0xb7, 0x72, 0xf4, 0x77, 0x66, 0x89, 0x22, 0x5e, 0x40, 0x31, 0x4d, + 0xf8, 0xdc, 0x74, 0x50, 0xcb, 0xec, 0x1c, 0xf7, 0xd3, 0xf0, 0x1a, 0xfb, 0x18, 0xc3, 0x17, + 0x86, 0x1c, 0x11, 0xa4, 0xa1, 0xce, 0xba, 0x9e, 0x61, 0x0c, 0x42, 0xd0, 0x5b, 0x0d, 0x8a, + 0x7c, 0xee, 0x71, 0xbd, 0x63, 0x95, 0xaf, 0x38, 0x3e, 0xfa, 0xc9, 0xc3, 0x87, 0x2f, 0x3f, + 0x3e, 0xe4, 0x22, 0x32, 0xe7, 0x48, 0x30, 0xb3, 0xe6, 0x99, 0x41, 0x0b, 0x62, 0x19, 0x38, + 0xa8, 0x1e, 0x97, 0xc5, 0x4c, 0x41, 0xef, 0xab, 0x92, 0x5a, 0x7f, 0xa4, 0x58, 0xac, 0x7b, + 0x8c, 0xa4, 0xe2, 0xe3, 0x91, 0x0f, 0x45, 0x13, 0x70, 0x2f, 0x07, 0x91, 0x3d, 0xee, 0x61, + 0x5d, 0xc9, 0xaf, 0x71, 0x01, 0x1f, 0x5a, 0x8b, 0xf2, 0xa9, 0xeb, 0x44, 0x7a, 0x22, 0x79, + 0xe6, 0x2b, 0x77, 0xb9, 0x2e, 0x91, 0x8e, 0x00, 0x9f, 0xe7, 0x1e, 0x6d, 0xea, 0xe7, 0x73, + 0x24, 0x12, 0x70, 0xcf, 0xb8, 0xba, 0xc3, 0x8d, 0x53, 0xa7, 0x24, 0x8b, 0x8a, 0xa2, 0xea, + 0x65, 0x8e, 0xe4, 0x31, 0xdf, 0x27, 0xee, 0x7d, 0x3a, 0x3f, 0xcf, 0x0e, 0x5d, 0x6e, 0x6d, + 0x65, 0x2c, 0x28, 0xcc, 0x9d, 0x04, 0x17, 0xac, 0xcb, 0x81, 0x04, 0x44, 0xfd, 0xb2, 0xb2, + 0xc6, 0x8d, 0xa3, 0x3b, 0x56, 0x24, 0xbf, 0xd5, 0x2f, 0xb0, 0x91, 0x1b, 0x1f, 0x79, 0x57, + 0x9d, 0x8d, 0x9b, 0x5d, 0x0f, 0x4c, 0x6c, 0x22, 0xf6, 0x0c, 0x6c, 0x5a, 0xf6, 0x56, 0xbf, + 0xa6, 0x6b, 0x29, 0x78, 0x7e, 0x87, 0x89, 0xfc, 0xf3, 0xc3, 0x9b, 0x43, 0x96, 0x2c, 0x9f, + 0x43, 0x1f, 0x6d, 0xae, 0xe9, 0x99, 0xfe, 0x0d, 0x6e, 0xb7, 0x3f, 0xe8, 0x74, 0x33, 0x2b, + 0x56, 0x60, 0xee, 0xee, 0xab, 0x2c, 0x34, 0xed, 0x46, 0x5a, 0x99, 0xd9, 0x3c, 0x28, 0xf2, + 0x0d, 0x43, 0x20, 0xf3, 0xd7, 0xa6, 0x54, 0xc2, 0x1c, 0x8d, 0x21, 0xcd, 0x70, 0x54, 0x3e, + 0xa8, 0x32, 0x3e, 0xf5, 0x70, 0x10, 0x47, 0x37, 0x84, 0x67, 0x62, 0x2c, 0xd2, 0xc6, 0x5a, + 0x60, 0x58, 0x32, 0x8d, 0x66, 0x14, 0x32, 0xd0, 0xa5, 0x13, 0x3a, 0xfd, 0xe0, 0x07, 0x83, + 0x5a, 0xce, 0xd0, 0x61, 0xaf, 0x89, 0x42, 0xe0, 0x89, 0x5d, 0xd2, 0x77, 0x61, 0x44, 0xac, + 0xbe, 0x34, 0x44, 0x6f, 0x3a, 0x7b, 0x06, 0xd1, 0x96, 0x35, 0xcf, 0xbf, 0xbd, 0x06, 0x7b, + 0xa7, 0x95, 0x58, 0xb7, 0x19, 0x3d, 0x80, 0xc2, 0xf7, 0x0f, 0xef, 0x43, 0xda, 0x60, 0x62, + 0x5f, 0xe4, 0xb0, 0x07, 0xba, 0x16, 0x23, 0xb7, 0x59, 0x8a, 0x90, 0xc7, 0xf9, 0xa1, 0x8d, + 0xa4, 0x33, 0x80, 0x03, 0xc0, 0xf3, 0x3a, 0x84, 0xca, 0xcd, 0xcc, 0x75, 0x7a, 0xb8, 0xf9, + 0xfc, 0xb9, 0x88, 0x5c, 0x67, 0xd3, 0xb1, 0xd7, 0x33, 0x56, 0xe7, 0x1f, 0x87, 0x1c, 0x7e, + 0x07, 0x64, 0x73, 0xc3, 0x78, 0x90, 0xc0, 0x30, 0x15, 0xdf, 0x76, 0x74, 0xc0, 0xe9, 0x80, + 0x81, 0x61, 0x4f, 0xea, 0xdb, 0x88, 0x77, 0x10, 0x20, 0x97, 0x22, 0xea, 0xa6, 0x94, 0x51, + 0x88, 0xe8, 0xf4, 0x73, 0x58, 0x22, 0x7d, 0x63, 0x8c, 0x24, 0xdf, 0xfd, 0x9f, 0x40, 0xa3, + 0xf7, 0xfe, 0xbb, 0x64, 0xcd, 0x62, 0x60, 0x9d, 0x32, 0x7a, 0x88, 0xad, 0x1b, 0x05, 0xa3, + 0xd2, 0x14, 0x10, 0x06, 0x6e, 0x4c, 0x87, 0x9c, 0x33, 0x7d, 0xd7, 0x0d, 0xa8, 0x46, 0xb8, + 0x79, 0x9f, 0x77, 0xef, 0xa9, 0xbc, 0x38, 0x98, 0xc7, 0x91, 0xe8, 0xf2, 0xe8, 0x63, 0x14, + 0x7e, 0xe5, 0x19, 0x20, 0x2e, 0x5a, 0x9a, 0xa6, 0x6a, 0xbb, 0xa1, 0x61, 0x59, 0x5b, 0x5c, + 0x02, 0x56, 0x96, 0x2f, 0xd3, 0xcc, 0x1a, 0x94, 0xf4, 0xd8, 0x11, 0x80, 0x0f, 0xa8, 0x12, + 0xb7, 0x37, 0x80, 0x0e, 0x7f, 0xef, 0xca, 0x28, 0xd1, 0x55, 0x3d, 0x10, 0x96, 0xe7, 0x25, + 0x27, 0xf5, 0x9f, 0x63, 0x81, 0xa9, 0xea, 0xff, 0x01, 0x7f, 0x21, 0x6f, 0x5b, 0x34, 0x27, + 0xe9, 0x63, 0x70, 0x0a, 0x8e, 0x5d, 0xee, 0xe2, 0xbb, 0x5c, 0xb1, 0x25, 0x59, 0xf8, 0xb1, + 0xc5, 0x83, 0xf2, 0x55, 0xf6, 0xad, 0x0c, 0xfc, 0x38, 0x86, 0xca, 0xfd, 0x64, 0x34, 0x9d, + 0x36, 0x75, 0xf4, 0xcd, 0x26, 0x29, 0x73, 0x73, 0x67, 0xc6, 0xcf, 0xc7, 0x8a, 0xd0, 0x9d, + 0xb6, 0x6f, 0x69, 0x79, 0x17, 0x07, 0xb1, 0xe3, 0xd9, 0x94, 0x33, 0x47, 0xf7, 0xc7, 0x00, + 0x09, 0x44, 0x01, 0xe6, 0x57, 0xf0, 0x35, 0x03, 0x67, 0xa0, 0x59, 0x60, 0xff, 0x2a, 0x92, + 0x1f, 0xd5, 0x33, 0xf5, 0xcb, 0xc9, 0xbd, 0xbe, 0x96, 0x76, 0xa8, 0x0f, 0x18, 0x77, 0xdd, + 0x80, 0x3a, 0xf4, 0x7a, 0xb7, 0xf9, 0x5e, 0x63, 0xb7, 0x30, 0x97, 0xe3, 0x37, 0x9f, 0xb0, + 0xa1, 0xa6, 0x76, 0x38, 0x37, 0xae, 0xca, 0x13, 0x5d, 0xb7, 0xb2, 0x9d, 0xfe, 0xad, 0x96, + 0xc5, 0x72, 0x04, 0xfa, 0x0c, 0x4e, 0x65, 0x77, 0x19, 0x48, 0x01, 0x1f, 0xc2, 0x18, 0x80, + 0xd6, 0xea, 0xfb, 0x99, 0xc0, 0x7b, 0xc4, 0xce, 0x13, 0x13, 0x27, 0x98, 0x22, 0x11, 0xe6, + 0xc8, 0x8b, 0x69, 0x9d, 0xa2, 0xac, 0x23, 0xe2, 0x2a, 0x8a, 0x2f, 0x83, 0x73, 0x0c, 0x7b, + 0x85, 0x4d, 0xdf, 0xe3, 0x4b, 0x53, 0xdf, 0x2e, 0x86, 0xab, 0x5b, 0xde, 0xf5, 0x99, 0x59, + 0xbf, 0xe9, 0x66, 0x29, 0xc8, 0xf4, 0xb2, 0x03, 0x31, 0x2d, 0x55, 0xfb, 0xdc, 0x3d, 0x86, + 0x37, 0xf2, 0x58, 0x71, 0xb2, 0x59, 0xf0, 0x62, 0xf2, 0x62, 0xbe, 0x70, 0x9f, 0xa6, 0x3e, + 0xa5, 0x77, 0xe8, 0xf1, 0xdd, 0x97, 0x7e, 0x49, 0x8b, 0x3d, 0xb1, 0xf2, 0x54, 0x16, 0x39, + 0x0d, 0x59, 0x3f, 0x6b, 0x39, 0x94, 0x5d, 0x96, 0x4c, 0xdf, 0x60, 0xf5, 0x5b, 0xf8, 0x50, + 0xd5, 0xbe, 0xa3, 0x1c, 0x4c, 0x54, 0x3b, 0xeb, 0xfc, 0x3f, 0x49, 0x3c, 0xa8, 0x08, 0x01, + 0x80, 0xeb, 0x6a, 0x84, 0x10, 0xbd, 0x3e, 0xf1, 0x27, 0xd2, 0x50, 0xa1, 0x94, 0x91, 0xd2, + 0x3d, 0x49, 0x09, 0xcb, 0xf1, 0xf2, 0xa3, 0xda, 0xe2, 0xb2, 0x75, 0x3a, 0x08, 0x22, 0xc4, + 0x0a, 0xe7, 0x66, 0xa7, 0xbf, 0xb5, 0x2c, 0x1a, 0x87, 0x18, 0x3e, 0xa3, 0xc5, 0x12, 0xe2, + 0xbd, 0xc8, 0x99, 0x19, 0x17, 0x23, 0x64, 0x6e, 0x5a, 0x64, 0x18, 0x34, 0x39, 0xb6, 0xe1, + 0x96, 0xb5, 0xcf, 0xd1, 0xf7, 0x9d, 0xec, 0x72, 0x13, 0x95, 0x7f, 0x50, 0xb9, 0x0b, 0xed, + 0x65, 0xba, 0xff, 0x28, 0x85, 0xc9, 0xab, 0xbc, 0xda, 0x63, 0xdc, 0x8a, 0x5a, 0xe6, 0x77, + 0xbc, 0x2c, 0x22, 0x7d, 0xd2, 0x00, 0xba, 0x18, 0xf8, 0x1c, 0x3b, 0xfb, 0xc3, 0xe4, 0x6f, + 0xb3, 0xdd, 0x77, 0x59, 0x95, 0x05, 0x57, 0x27, 0xd3, 0x1f, 0x33, 0x72, 0x49, 0xc4, 0xcf, + 0xbd, 0x05, 0x52, 0x65, 0xf3, 0xee, 0x3c, 0x27, 0x7e, 0xdd, 0x19, 0xf9, 0x1a, 0x5c, 0xc7, + 0xe8, 0x76, 0xf2, 0x70, 0x4e, 0x45, 0x11, 0x2c, 0x9e, 0x1e, 0x60, 0x4c, 0x23, 0xc4, 0x61, + 0x54, 0x86, 0x2a, 0xf4, 0xdc, 0xb2, 0x56, 0x68, 0x02, 0x59, 0x7b, 0xd8, 0x3d, 0x94, 0x37, + 0x2d, 0xdd, 0x20, 0x89, 0xaa, 0x90, 0x89, 0x9d, 0x6c, 0x81, 0x06, 0x41, 0x39, 0xd7, 0x7c, + 0x32, 0x99, 0xca, 0xb7, 0xd5, 0xa4, 0x19, 0xa3, 0xc3, 0x5e, 0xdd, 0x07, 0xe5, 0xde, 0x54, + 0xe3, 0x38, 0xb6, 0x76, 0x61, 0xc5, 0xd3, 0x64, 0xb7, 0x91, 0xe6, 0x8e, 0x8d, 0x6c, 0x7d, + 0xa6, 0x0f, 0xa8, 0x55, 0x8d, 0xd7, 0x58, 0xdd, 0x21, 0xac, 0xb8, 0xf0, 0x5e, 0x5f, 0x49, + 0x0b, 0xf0, 0xa1, 0x24, 0x13, 0xf2, 0xd9, 0x25, 0x25, 0x02, 0x09, 0xb7, 0xd2, 0x1a, 0x85, + 0xcc, 0x3e, 0x82, 0xf2, 0xf9, 0x5f, 0xee, 0xe7, 0x95, 0xa0, 0x34, 0xb8, 0x73, 0x86, 0xac, + 0x5e, 0xef, 0x55, 0x16, 0xb8, 0x1a, 0x49, 0x4a, 0xd6, 0x9e, 0x9b, 0x0c, 0x4b, 0xed, 0x6b, + 0x35, 0x12, 0x72, 0x53, 0x22, 0x2f, 0x91, 0xe4, 0x1f, 0x4c, 0x16, 0x2a, 0x7e, 0xb1, 0x0f, + 0x11, 0xe1, 0xcb, 0xd1, 0x11, 0xb4, 0x7a, 0x2b, 0xff, 0x1d, 0xc4, 0x57, 0x1e, 0xd7, 0x32, + 0x0c, 0x00, 0x32, 0x3f, 0x7c, 0xfb, 0x39, 0x7e, 0x30, 0x34, 0xc6, 0xe0, 0x64, 0x99, 0x2f, + 0x9e, 0x04, 0x30, 0x15, 0xb5, 0xef, 0x3c, 0x51, 0xa3, 0x0d, 0x44, 0x25, 0xe6, 0x7e, 0x97, + 0x70, 0x67, 0x06, 0xa1, 0xb6, 0x9e, 0xe3, 0xa4, 0xd2, 0x2b, 0x81, 0xb4, 0x24, 0x39, 0x1a, + 0x4a, 0x0c, 0xc8, 0x85, 0xaf, 0x15, 0x25, 0x64, 0x1d, 0x0b, 0xf4, 0x0d, 0x96, 0xb6, 0x50, + 0xd1, 0xe5, 0x01, 0x7e, 0x73, 0x59, 0xd3, 0x69, 0xc8, 0x8e, 0x48, 0x9b, 0xe2, 0xc6, 0x10, + 0x06, 0x6e, 0x25, 0xf9, 0x7b, 0x36, 0x4a, 0x56, 0xa2, 0x0a, 0xed, 0xd7, 0xe1, 0x1a, 0x58, + 0x30, 0x43, 0x4c, 0x3e, 0x38, 0x22, 0xdc, 0x66, 0xb1, 0xf6, 0x28, 0x84, 0xb2, 0xd6, 0x68, + 0x52, 0x9b, 0xee, 0xf3, 0x8d, 0xef, 0xdf, 0xe8, 0xd4, 0x99, 0xe0, 0x03, 0x51, 0x67, 0xa3, + 0x38, 0xf0, 0xff, 0x63, 0x3c, 0x4e, 0xf3, 0x8e, 0xb7, 0xcf, 0xb4, 0xbb, 0x37, 0x0a, 0xea, + 0xe5, 0x30, 0x58, 0x9a, 0xb0, 0xcb, 0x64, 0x2d, 0x7f, 0x04, 0xbf, 0xd3, 0xb8, 0xf2, 0x15, + 0xd1, 0x9e, 0x20, 0x6d, 0x7d, 0xd5, 0xfe, 0xc7, 0x87, 0xcc, 0xfe, 0xf1, 0x81, 0x74, 0x88, + 0x34, 0x6f, 0xba, 0x4d, 0xeb, 0x49, 0x72, 0xb2, 0x15, 0x37, 0x25, 0xab, 0xaa, 0xcd, 0x50, + 0x1a, 0xe1, 0x1e, 0xae, 0x18, 0x89, 0x56, 0x65, 0xba, 0x6b, 0x7a, 0x55, 0x07, 0x13, 0xfa, + 0xd3, 0x11, 0x51, 0x55, 0x3f, 0x30, 0x5b, 0x2a, 0x9e, 0x5a, 0x0c, 0x13, 0x21, 0x8d, 0x54, + 0x22, 0xe5, 0x6c, 0xbd, 0x96, 0x06, 0x22, 0xa5, 0x5e, 0x7a, 0xb2, 0x1f, 0x43, 0x4b, 0x4f, + 0xc5, 0x10, 0x0a, 0x7d, 0x08, 0xef, 0xed, 0xd8, 0xb5, 0x00, 0xc4, 0x03, 0x87, 0x11, 0xae, + 0x01, 0x63, 0x0c, 0x76, 0x11, 0x03, 0x25, 0x26, 0x18, 0x19, 0x39, 0x19, 0x52, 0x32, 0xaa, + 0x06, 0xe1, 0x88, 0xad, 0x09, 0x36, 0x15, 0xd8, 0xbf, 0xa9, 0xdb, 0x76, 0x71, 0x44, 0x23, + 0x0e, 0x20, 0xa2, 0x39, 0x01, 0x06, 0xd0, 0xd1, 0xa1, 0x71, 0x26, 0xf8, 0x90, 0x8e, 0x22, + 0xef, 0xb7, 0x02, 0x59, 0x60, 0x26, 0x17, 0xf8, 0xee, 0x0b, 0xe1, 0x2f, 0xbd, 0x29, 0x84, + 0xa5, 0xf5, 0x2f, 0xaf, 0x2f, 0x34, 0x00, 0x92, 0x53, 0x99, 0xd1, 0xb8, 0x20, 0x08, 0xec, + 0xda, 0xae, 0x1c, 0x3e, 0xa7, 0x36, 0xe1, 0xd2, 0x28, 0xee, 0x6e, 0x94, 0x5a, 0x80, 0x02, + 0xac, 0x71, 0xcb, 0x6a, 0xab, 0x34, 0x15, 0xb0, 0x59, 0x41, 0xe8, 0xe8, 0x84, 0x43, 0x0f, + 0xca, 0xa8, 0xdf, 0xd3, 0x7c, 0x3d, 0xcc, 0x81, 0xb8, 0x94, 0x5f, 0x86, 0xcd, 0x52, 0x4a, + 0xe2, 0x36, 0x1b, 0xa1, 0x98, 0xdf, 0x3c, 0x75, 0x5b, 0x12, 0x37, 0x84, 0xc0, 0xf3, 0xbf, + 0xf2, 0x31, 0x9a, 0x64, 0xff, 0xfc, 0xf3, 0x2c, 0x1a, 0x4c, 0x11, 0x6a, 0x43, 0x48, 0xb5, + 0x4b, 0x3d, 0xac, 0x6c, 0xa3, 0x8e, 0xdb, 0x1d, 0xa4, 0x2c, 0x42, 0x06, 0x31, 0xa7, 0x51, + 0xcb, 0xe2, 0x88, 0xaa, 0x9d, 0xd7, 0xc2, 0x08, 0x73, 0xbc, 0x58, 0x0e, 0x79, 0x4a, 0x75, + 0x9b, 0x9c, 0xe4, 0xbf, 0x36, 0x85, 0x49, 0x03, 0xf6, 0x91, 0x43, 0x21, 0xb0, 0xc2, 0xc3, + 0x11, 0x2c, 0x68, 0x30, 0x4b, 0x10, 0xdf, 0x17, 0xf4, 0xb8, 0x1d, 0x17, 0x25, 0x5f, 0x17, + 0x2d, 0x96, 0x69, 0x8d, 0x7f, 0x98, 0xcc, 0xdc, 0x3a, 0xc8, 0x52, 0x0d, 0x8d, 0x6e, 0x06, + 0xce, 0x05, 0xca, 0xb3, 0xa7, 0xe2, 0x23, 0x1e, 0x46, 0xe5, 0xc9, 0xa0, 0x3e, 0x9e, 0xd3, + 0xa2, 0x95, 0x0d, 0x4a, 0x5b, 0xf8, 0x99, 0x54, 0xf0, 0xd6, 0x4e, 0x3a, 0x78, 0x4b, 0xf6, + 0x64, 0x58, 0x4d, 0x93, 0x6e, 0xed, 0x4c, 0xa4, 0xe3, 0x11, 0xf3, 0x85, 0x22, 0xd6, 0x05, + 0x95, 0x5d, 0x9b, 0x70, 0xfe, 0x61, 0x5c, 0xb9, 0x39, 0x0a, 0xd9, 0x33, 0x0f, 0x46, 0x0b, + 0x42, 0x8d, 0x39, 0x2b, 0xc4, 0x5e, 0x95, 0x68, 0x4f, 0x68, 0x00, 0x24, 0x31, 0xc9, 0x0a, + 0xe9, 0x38, 0x86, 0x21, 0x13, 0x10, 0xe7, 0x75, 0x48, 0x07, 0xb2, 0xa1, 0x26, 0x6a, 0xbd, + 0x45, 0x63, 0x09, 0xa4, 0x2e, 0xda, 0x9d, 0x76, 0xed, 0xbe, 0xd2, 0x7e, 0xee, 0x01, 0x89, + 0x1e, 0x12, 0x41, 0x4e, 0x54, 0xd2, 0xc8, 0x6a, 0xc1, 0xf4, 0xd4, 0xe1, 0x48, 0x3d, 0x85, + 0xc4, 0x64, 0xae, 0xa4, 0xeb, 0x83, 0x54, 0x9c, 0x6a, 0x6c, 0x4a, 0xb9, 0xf4, 0x42, 0x03, + 0x9b, 0xfe, 0x42, 0x5d, 0x14, 0x07, 0xdb, 0xae, 0xf4, 0x15, 0x11, 0x85, 0x17, 0xd9, 0x70, + 0x09, 0xa7, 0x19, 0x62, 0xef, 0x65, 0x5f, 0xec, 0x22, 0xfa, 0xcd, 0x3e, 0x55, 0x6f, 0x83, + 0xf8, 0x2e, 0x31, 0xbf, 0xcf, 0xd4, 0xa6, 0x35, 0x7f, 0xde, 0xdc, 0x09, 0xab, 0x2d, 0x13, + 0xd8, 0xfc, 0x94, 0x85, 0x3b, 0x04, 0x75, 0x5e, 0xcb, 0x7f, 0x06, 0xa9, 0xfd, 0xdf, 0xca, + 0xd1, 0x96, 0x32, 0xc4, 0x94, 0xe7, 0x46, 0x3f, 0x8c, 0xe4, 0xfd, 0x9f, 0xe0, 0xca, 0xaf, + 0x9e, 0xa2, 0xa9, 0x99, 0x22, 0xe1, 0x13, 0x6f, 0x30, 0x65, 0xdd, 0x8e, 0x0a, 0xc9, 0xef, + 0x25, 0x39, 0x58, 0x8a, 0x76, 0x0b, 0x9c, 0xcb, 0xea, 0x64, 0x7d, 0xda, 0x28, 0x0f, 0xac, + 0x68, 0x24, 0x60, 0x6b, 0x8b, 0x12, 0x78, 0xcc, 0x19, 0xe3, 0x87, 0x48, 0x50, 0x02, 0xb0, + 0x52, 0xdd, 0xb4, 0x47, 0xa0, 0xf8, 0x0d, 0xe0, 0x35, 0x3b, 0x17, 0xc4, 0xf1, 0x68, 0xe5, + 0x5d, 0x47, 0x68, 0xbc, 0x34, 0x7c, 0x4e, 0x98, 0xf0, 0x64, 0x28, 0xbb, 0x10, 0x3b, 0x3f, + 0xbf, 0x3d, 0x07, 0x23, 0xdc, 0x59, 0xa5, 0xdc, 0x91, 0xc1, 0x0b, 0x1a, 0xb8, 0x56, 0x93, + 0x58, 0x68, 0x14, 0xc4, 0x30, 0x27, 0x16, 0x4a, 0x3a, 0x64, 0x5e, 0xad, 0x75, 0xd5, 0x94, + 0x79, 0xe4, 0xf5, 0x88, 0x62, 0x9c, 0x3e, 0xac, 0xea, 0xb3, 0x0b, 0x2b, 0x1f, 0x07, 0x57, + 0xe9, 0xeb, 0x2e, 0x4c, 0x51, 0x83, 0x5c, 0xcf, 0x35, 0x68, 0x32, 0x61, 0x34, 0xf7, 0xe3, + 0x0f, 0xfb, 0x7b, 0x4e, 0x32, 0x79, 0x51, 0x95, 0x78, 0xdc, 0x00, 0x23, 0xa6, 0xfe, 0xb8, + 0x49, 0x01, 0x40, 0xd0, 0xd3, 0x66, 0x6d, 0xd9, 0xf0, 0x08, 0xa1, 0xa7, 0xa9, 0x79, 0x72, + 0x84, 0x57, 0x2e, 0xf9, 0x0d, 0x20, 0x26, 0xe5, 0x78, 0x60, 0xc1, 0x0f, 0xe0, 0x28, 0x8f, + 0xa7, 0x0d, 0xb7, 0x85, 0x53, 0x2a, 0x3f, 0x85, 0x1d, 0xdb, 0x3b, 0x50, 0x3a, 0x29, 0x38, + 0x9e, 0xd2, 0x80, 0x14, 0xee, 0xa1, 0x5a, 0x83, 0xe8, 0x0c, 0x6f, 0x63, 0xe2, 0x4a, 0x5a, + 0x84, 0x36, 0x84, 0x87, 0x19, 0x8f, 0x6c, 0xaf, 0x88, 0xd6, 0xc4, 0x67, 0x2e, 0xbf, 0x18, + 0x7f, 0x32, 0xe0, 0x53, 0x2b, 0x8c, 0x60, 0xdf, 0xee, 0xd7, 0x87, 0xb6, 0xe6, 0x62, 0xaa, + 0x43, 0x73, 0x92, 0x8c, 0xce, 0x98, 0x0a, 0x65, 0x5d, 0xd4, 0x1c, 0x31, 0x3c, 0x37, 0xdc, + 0x99, 0x1a, 0x4a, 0xa4, 0xc9, 0x86, 0xd1, 0xe8, 0x57, 0xcc, 0x07, 0x79, 0xa7, 0xe8, 0x21, + 0x09, 0x29, 0x17, 0x50, 0xe1, 0x51, 0x81, 0x04, 0xc0, 0x30, 0xcc, 0x90, 0x43, 0x0a, 0xf4, + 0x24, 0xbf, 0x22, 0x66, 0x5f, 0xd8, 0xe2, 0x20, 0x22, 0x69, 0x7d, 0x8e, 0xeb, 0x0b, 0xe2, + 0xea, 0x9b, 0x93, 0x94, 0xb7, 0xd2, 0x63, 0x2e, 0xe2, 0xa7, 0x25, 0x3e, 0x61, 0x02, 0x98, + 0xde, 0x66, 0x9c, 0xf1, 0xf3, 0x9c, 0xcb, 0xd9, 0x2c, 0x98, 0x03, 0x70, 0x74, 0x6c, 0xa0, + 0x97, 0xd5, 0x35, 0xcb, 0x9f, 0xf5, 0x57, 0x98, 0xbb, 0xc1, 0xdc, 0x34, 0x74, 0xff, 0xd8, + 0xea, 0x58, 0xa2, 0x43, 0x45, 0xd2, 0xa4, 0xe3, 0x78, 0x0f, 0x28, 0xf0, 0xee, 0x85, 0xf1, + 0xc9, 0x55, 0x52, 0x86, 0x6e, 0x29, 0xe1, 0x50, 0xbf, 0x7c, 0xb1, 0xff, 0x1a, 0x95, 0xa5, + 0xc5, 0xad, 0xf9, 0xd8, 0xba, 0x6e, 0xab, 0x43, 0x3f, 0xae, 0xa2, 0x97, 0xa1, 0x51, 0x0c, + 0x82, 0xae, 0x07, 0xc9, 0xda, 0xfe, 0xc9, 0x6a, 0x2d, 0xfa, 0x83, 0xaa, 0x53, 0xcd, 0x31, + 0x2f, 0x6d, 0x70, 0x40, 0x19, 0x37, 0xd4, 0xff, 0xc3, 0x32, 0xd6, 0x4b, 0x46, 0x23, 0x79, + 0xd9, 0x90, 0x0d, 0x70, 0x42, 0x03, 0x9b, 0x93, 0xe6, 0xc1, 0xdf, 0x02, 0x08, 0xf8, 0x72, + 0x45, 0xe9, 0x91, 0xc6, 0x7e, 0x29, 0x30, 0x56, 0xfe, 0x2e, 0x21, 0x1f, 0x34, 0xc3, 0x41, + 0x2f, 0x79, 0x47, 0xe0, 0x02, 0x9c, 0x53, 0xb3, 0x13, 0xf8, 0x5d, 0xb0, 0xd0, 0xe0, 0x0f, + 0x75, 0x8a, 0x26, 0xdf, 0x1f, 0xad, 0x22, 0xe9, 0xbd, 0x11, 0x81, 0x98, 0xb3, 0x58, 0x99, + 0x99, 0xd3, 0x19, 0x5f, 0x01, 0xa4, 0x5c, 0x6f, 0xa0, 0x9c, 0xb1, 0x5d, 0xfe, 0xfe, 0xbf, + 0x9e, 0x48, 0x44, 0xd0, 0x71, 0x24, 0x86, 0xe4, 0xaa, 0xd5, 0x59, 0x5a, 0xaa, 0x0f, 0xa5, + 0x11, 0xb4, 0xf4, 0x00, 0x43, 0x44, 0x59, 0xf1, 0x95, 0x62, 0x0e, 0x8f, 0x07, 0x51, 0xd3, + 0x66, 0x1a, 0x20, 0xb1, 0xab, 0x36, 0x3e, 0x10, 0x12, 0xae, 0xe0, 0xa2, 0x05, 0xe7, 0x7c, + 0xd5, 0x34, 0xcd, 0x86, 0x43, 0xb0, 0x29, 0xc3, 0xfc, 0xcb, 0x9b, 0x39, 0xf5, 0x1e, 0x2f, + 0x13, 0x1b, 0xfa, 0x4f, 0x68, 0xe3, 0x41, 0x99, 0x05, 0xfd, 0xa1, 0x10, 0x5a, 0x65, 0x13, + 0xc3, 0xc7, 0xc1, 0xc8, 0x83, 0xfa, 0x5e, 0x5b, 0xa6, 0x76, 0x03, 0xc3, 0x21, 0x23, 0x56, + 0xb4, 0x9a, 0x89, 0xdb, 0xa5, 0xa4, 0xb1, 0x9e, 0xe7, 0x85, 0xe6, 0x20, 0x11, 0x71, 0x59, + 0x81, 0x19, 0x9f, 0xef, 0xac, 0xd2, 0x6f, 0x5e, 0x26, 0x3f, 0x7d, 0x33, 0x08, 0xa3, 0x28, + 0x3f, 0x75, 0x6a, 0x25, 0xe7, 0xb3, 0x78, 0xe9, 0x46, 0x46, 0x4f, 0xb0, 0xab, 0x48, 0x03, + 0x8a, 0xca, 0xa7, 0x42, 0x57, 0x6b, 0xa5, 0x0f, 0x4e, 0x6f, 0xf1, 0x1b, 0x0d, 0x6b, 0xa9, + 0x8e, 0x21, 0xb7, 0x96, 0x22, 0xba, 0xc6, 0xac, 0xa4, 0xb8, 0x58, 0x07, 0xf1, 0x0c, 0x1a, + 0x5b, 0x0e, 0x42, 0x49, 0x10, 0xeb, 0x91, 0x2b, 0x2a, 0xdd, 0xef, 0x08, 0x32, 0x7e, 0x5d, + 0xaf, 0x32, 0x1b, 0x29, 0xa6, 0x17, 0x92, 0x46, 0x1a, 0x7b, 0x32, 0xcc, 0x5f, 0x9f, 0xd7, + 0xf4, 0x52, 0x68, 0x35, 0x47, 0x7a, 0xeb, 0xc1, 0x20, 0xf9, 0xe4, 0x6f, 0xa0, 0xc5, 0x0f, + 0x61, 0x82, 0xc0, 0xa0, 0xb5, 0xa3, 0x12, 0x5c, 0xa8, 0xbd, 0xa2, 0x9a, 0xb8, 0x0b, 0xd5, + 0xda, 0x4e, 0xe5, 0xaf, 0x94, 0x24, 0x53, 0x34, 0xc9, 0xed, 0x57, 0xa7, 0xb0, 0x3b, 0x5e, + 0xd2, 0x58, 0x89, 0xe8, 0xb0, 0x62, 0xf4, 0x2d, 0xec, 0xd3, 0x63, 0x73, 0x46, 0xf8, 0x15, + 0xc9, 0xc4, 0xab, 0xa9, 0x33, 0x57, 0x1d, 0x11, 0x4b, 0xc5, 0xde, 0xd0, 0x9f, 0x17, 0xdc, + 0x5d, 0x77, 0xe8, 0x58, 0x23, 0xd9, 0x0d, 0x43, 0xbf, 0x36, 0x8f, 0x04, 0x8f, 0xb9, 0xa2, + 0x8b, 0xf3, 0x2b, 0xb2, 0x8c, 0x54, 0x43, 0xf4, 0xba, 0xb4, 0x11, 0x68, 0x90, 0x6d, 0xd0, + 0x8e, 0xe2, 0x7d, 0xa9, 0x75, 0xaf, 0x71, 0xcf, 0xb1, 0xdb, 0x85, 0xc7, 0xda, 0x61, 0x1a, + 0x4e, 0xaa, 0xd0, 0xa5, 0xd0, 0x42, 0x5e, 0x7a, 0x96, 0x24, 0x05, 0x1e, 0x00, 0x90, 0x04, + 0x42, 0x5b, 0x45, 0xbc, 0xe5, 0x61, 0xe6, 0xf1, 0x44, 0x79, 0x91, 0x21, 0x0d, 0x9d, 0xa9, + 0x0e, 0x99, 0x39, 0xf6, 0x29, 0x0d, 0xe2, 0x91, 0x78, 0x38, 0x49, 0x87, 0x89, 0x97, 0x25, + 0x17, 0x53, 0x25, 0x25, 0x2e, 0x6c, 0xf5, 0x5c, 0xec, 0x19, 0xe3, 0x0e, 0x7b, 0x30, 0xb7, + 0x7d, 0xbd, 0xb6, 0x77, 0x93, 0xc9, 0x3b, 0xd9, 0x97, 0xc3, 0x46, 0x51, 0x61, 0x3c, 0x50, + 0x4f, 0x3f, 0x00, + ], + // Burn block + &[ + 0x04, 0x00, 0x00, 0x00, 0x27, 0xe3, 0x01, 0x34, 0xd6, 0x20, 0xe9, 0xfe, 0x61, 0xf7, 0x19, + 0x93, 0x83, 0x20, 0xba, 0xb6, 0x3e, 0x7e, 0x72, 0xc9, 0x1b, 0x5e, 0x23, 0x02, 0x56, 0x76, + 0xf9, 0x0e, 0xd8, 0x11, 0x9f, 0x02, 0x18, 0x0b, 0xf8, 0x73, 0x87, 0x12, 0x3e, 0x5b, 0xf1, + 0xff, 0x12, 0x2a, 0xd2, 0x7e, 0x1d, 0x26, 0x5c, 0xd4, 0xde, 0x75, 0x6f, 0xe5, 0xf6, 0xca, + 0x98, 0xaf, 0x7d, 0x82, 0x2d, 0xd7, 0xe4, 0x8c, 0x8b, 0x3d, 0x63, 0xe9, 0x2b, 0x4e, 0x01, + 0x7f, 0x6f, 0xae, 0x46, 0xfc, 0x20, 0x6e, 0x93, 0x75, 0x4b, 0xbd, 0xa0, 0xba, 0x7c, 0x5b, + 0x18, 0xc2, 0xfb, 0x1d, 0x3a, 0x9f, 0x81, 0x2f, 0xc3, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xa6, 0x0c, 0x20, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0xfd, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x80, 0x85, 0x20, 0x2f, 0x89, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x02, 0x51, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x40, 0xbe, 0x40, 0x25, + 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, + 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, + 0xca, 0xe4, 0xbf, 0xa4, 0xba, 0xfc, 0x37, 0x22, 0xd8, 0xf9, 0x3c, 0x6c, 0xfb, 0xcc, 0xba, + 0xd7, 0x94, 0x44, 0x58, 0x85, 0x10, 0xba, 0x7a, 0x9d, 0x8e, 0xa3, 0x90, 0x6e, 0x7f, 0xdc, + 0xa8, 0x7a, 0x06, 0x13, 0x03, 0x39, 0x58, 0x9a, 0x79, 0x4c, 0x5a, 0x25, 0x5a, 0x2c, 0xd2, + 0xf8, 0x68, 0x30, 0x8b, 0xcc, 0x89, 0x88, 0x3a, 0x44, 0x0b, 0x4d, 0xa1, 0xbc, 0xd1, 0xbd, + 0x74, 0xdb, 0x3d, 0xbf, 0x6d, 0x78, 0xf8, 0x78, 0x34, 0x11, 0x9b, 0xde, 0x3d, 0x5e, 0x4c, + 0x3f, 0x2f, 0x8f, 0x4e, 0xda, 0xda, 0x54, 0xe2, 0x9f, 0x1c, 0x35, 0x44, 0x41, 0x84, 0x83, + 0x8e, 0xab, 0xd5, 0xa0, 0x9f, 0xf0, 0xc5, 0xd9, 0xdd, 0x94, 0x3e, 0xe1, 0xcb, 0x9d, 0x09, + 0x3c, 0x98, 0x56, 0x33, 0x3f, 0x49, 0x3a, 0x4b, 0xfc, 0x72, 0xda, 0xf2, 0xa6, 0xe6, 0xbb, + 0x44, 0x25, 0x13, 0x4b, 0x56, 0x89, 0x0e, 0x70, 0x76, 0x51, 0xef, 0x2d, 0x8f, 0xa2, 0x49, + 0x16, 0xc5, 0xfd, 0xd2, 0x70, 0xdd, 0x87, 0xc2, 0x1c, 0x7b, 0xd6, 0xd9, 0xa3, 0xd4, 0xe1, + 0x60, 0xbe, 0x2f, 0xad, 0xf0, 0x54, 0xb4, 0xd7, 0x0d, 0x3b, 0xcf, 0x02, 0x31, 0x1e, 0x0d, + 0xcb, 0x8a, 0x95, 0xe7, 0x91, 0xaf, 0xa3, 0xfa, 0x85, 0xbf, 0x90, 0x79, 0x4b, 0x27, 0x62, + 0x01, 0x76, 0x23, 0x40, 0x39, 0x5b, 0x12, 0x97, 0x95, 0x56, 0xe9, 0xd7, 0x1f, 0x4e, 0x1a, + 0xaf, 0x76, 0x00, 0xff, 0x87, 0x8a, 0xdb, 0x86, 0xf6, 0xc7, 0x17, 0x40, 0x44, 0x6a, 0xaf, + 0x38, 0xa0, 0xc1, 0xf3, 0xe3, 0x3f, 0xfa, 0xfa, 0x47, 0x00, 0xeb, 0x10, 0x14, 0xb0, 0xaf, + 0x94, 0x39, 0x03, 0xa8, 0x30, 0x17, 0xa7, 0xe1, 0x74, 0x7b, 0x95, 0xb8, 0x29, 0xfb, 0xfd, + 0x65, 0xee, 0xba, 0xe5, 0x9e, 0xfa, 0x63, 0xa2, 0x61, 0x5e, 0xae, 0xd2, 0xca, 0xb8, 0xcb, + 0xe6, 0x69, 0x62, 0x90, 0xdb, 0x6f, 0xd9, 0x59, 0x91, 0xf2, 0x03, 0x07, 0x6a, 0x27, 0xa6, + 0x92, 0x65, 0x25, 0xd4, 0x78, 0x39, 0xdc, 0xc5, 0x54, 0xf4, 0x2c, 0x41, 0x3b, 0x9a, 0xc0, + 0x8b, 0x9b, 0x7b, 0xa2, 0x3b, 0xfb, 0x6b, 0xc6, 0xe8, 0x3f, 0x31, 0x9c, 0xa3, 0xb0, 0x79, + 0xf1, 0xb4, 0xf0, 0xf9, 0xb8, 0xe8, 0xfa, 0x32, 0xcd, 0x58, 0x9a, 0xc9, 0xaf, 0xe3, 0xa0, + 0x28, 0x2b, 0x9b, 0x93, 0x1b, 0x09, 0x67, 0xc2, 0x66, 0xc9, 0xad, 0xce, 0x66, 0x3f, 0x59, + 0xed, 0x95, 0xaa, 0xa6, 0x5c, 0x5e, 0x90, 0x67, 0xb0, 0xc9, 0x81, 0x8d, 0x96, 0xcd, 0x89, + 0xd1, 0x62, 0x95, 0xf4, 0x47, 0x2b, 0xa1, 0x50, 0x48, 0x95, 0x62, 0xfc, 0x02, 0x5f, 0xa6, + 0xca, 0x5c, 0x6a, 0x2c, 0xef, 0xdd, 0x26, 0x21, 0x9b, 0xb3, 0xc5, 0x0d, 0x0e, 0xf5, 0x76, + 0xb3, 0x1a, 0x6d, 0x87, 0x63, 0x37, 0xbb, 0x4d, 0x27, 0xa4, 0xa9, 0x72, 0x70, 0x22, 0xce, + 0xa8, 0x15, 0x9d, 0xdb, 0x3b, 0x01, 0x56, 0xe0, 0x15, 0x46, 0x03, 0xb6, 0xb5, 0xda, 0xae, + 0x01, 0x12, 0xe3, 0x44, 0x3d, 0x82, 0x0f, 0xa2, 0x56, 0xc0, 0x7d, 0xe9, 0x00, 0xb5, 0x8a, + 0xf3, 0x52, 0xb5, 0x34, 0xbb, 0x5b, 0x4d, 0x9b, 0x6f, 0xbc, 0x93, 0xa9, 0x07, 0x63, 0x8d, + 0x48, 0xe4, 0x7d, 0xa2, 0xa0, 0x6a, 0x0f, 0x84, 0xb9, 0x8c, 0xd7, 0xe3, 0xa5, 0x2c, 0x8e, + 0xbd, 0xec, 0xb2, 0xec, 0xe6, 0x4e, 0xf6, 0xae, 0x07, 0xba, 0xcf, 0xcd, 0xc5, 0xce, 0xbd, + 0xf6, 0xc1, 0x8f, 0xa0, 0x50, 0x83, 0xec, 0x60, 0x0d, 0xa2, 0xb7, 0x65, 0x7d, 0xdd, 0xcd, + 0x8e, 0x6e, 0xda, 0xfc, 0xee, 0x5d, 0xe1, 0x98, 0x27, 0x70, 0xf1, 0x8c, 0x5c, 0xa1, 0x18, + 0x1c, 0x7b, 0x53, 0x1e, 0xa0, 0x9c, 0xd2, 0xb9, 0x25, 0xfb, 0x16, 0xa7, 0x12, 0xd4, 0xe9, + 0xed, 0x53, 0x8d, 0x1c, 0xbd, 0xcc, 0x12, 0x8f, 0x72, 0xec, 0xc0, 0x93, 0xba, 0xcb, 0xaf, + 0xaf, 0x3b, 0xef, 0x5f, 0x1e, 0xb1, 0xd7, 0x0d, 0x5d, 0xc8, 0xe1, 0xfb, 0x25, 0x9a, 0xfa, + 0x0c, 0xb0, 0x18, 0x3d, 0x7b, 0x53, 0x1e, 0x60, 0x36, 0xdf, 0xb8, 0x32, 0x14, 0x81, 0x6d, + 0xda, 0xc0, 0xbb, 0xc6, 0xe8, 0xf5, 0xa0, 0x36, 0xcf, 0x21, 0xf4, 0xa8, 0xd8, 0x48, 0x56, + 0x72, 0x78, 0x00, 0xe2, 0xda, 0xc1, 0xa4, 0xde, 0x38, 0x50, 0x94, 0x35, 0x79, 0x95, 0xd7, + 0x97, 0x8e, 0xfe, 0x22, 0x9f, 0xca, 0x58, 0x14, 0xee, 0x42, 0x29, 0x50, 0x9f, 0x76, 0xb6, + 0x80, 0x81, 0x0b, 0x93, 0x00, 0x5c, 0xd9, 0xc8, 0xfc, 0x50, 0x74, 0x3e, 0x23, 0xa0, 0x83, + 0xef, 0x98, 0x33, 0x4c, 0x2c, 0x9c, 0x81, 0x4f, 0x21, 0xf3, 0xaf, 0xce, 0xbf, 0xfc, 0xf7, + 0xfa, 0x0c, 0x7a, 0xdd, 0x4c, 0xb2, 0x6a, 0xe0, 0x19, 0xde, 0x6e, 0xe2, 0x84, 0xee, 0xeb, + 0xb6, 0x4c, 0xcc, 0xf0, 0x7b, 0x3b, 0x69, 0x6b, 0x98, 0xef, 0x4a, 0xb0, 0x95, 0xa7, 0x8f, + 0xc1, 0x58, 0xd0, 0xe1, 0x34, 0x63, 0xed, 0x22, 0x6d, 0xe5, 0x84, 0x7b, 0x59, 0x6a, 0xb7, + 0xdb, 0xe5, 0x1b, 0x3b, 0xb3, 0xa6, 0xb2, 0x4f, 0x85, 0xd1, 0x24, 0xbb, 0xb6, 0x2c, 0x15, + 0x69, 0x0a, 0x32, 0xde, 0xe3, 0x2d, 0x08, 0x9c, 0x6c, 0x89, 0x80, 0x4e, 0xab, 0xef, 0x6f, + 0x3c, 0x8f, 0x67, 0x7f, 0xfb, 0xf9, 0x13, 0xe3, 0xa0, 0x94, 0x66, 0xc9, 0x94, 0x41, 0x31, + 0xbc, 0xa9, 0x9a, 0x8f, 0x0d, 0x46, 0x90, 0xc3, 0x3d, 0xa8, 0xba, 0x1a, 0x52, 0xa4, 0x1f, + 0x95, 0xb0, 0x60, 0xd3, 0x82, 0x92, 0xe1, 0xde, 0x1f, 0x38, 0xf8, 0x1a, 0xb4, 0xe3, 0xa1, + 0xac, 0x9f, 0x58, 0x86, 0x37, 0xf4, 0x9f, 0xe6, 0xbb, 0x66, 0x47, 0x5b, 0x6d, 0x70, 0x1d, + 0x15, 0x2f, 0x7d, 0x55, 0x45, 0x61, 0x20, 0xce, 0x55, 0xe4, 0x89, 0xc8, 0x95, 0x4e, 0x15, + 0x4e, 0xcf, 0x05, 0xbd, 0xac, 0x28, 0xf1, 0x4d, 0x64, 0x00, 0x36, 0xb6, 0xbe, 0xdf, 0x14, + 0x91, 0x32, 0xf5, 0x10, 0x0a, 0x40, 0xeb, 0x66, 0xa2, 0x58, 0xf4, 0xeb, 0xc9, 0xd6, 0x2d, + 0x7f, 0xb3, 0xd7, 0x40, 0xf4, 0x74, 0xe0, 0x4a, 0xe4, 0x00, 0xd2, 0xee, 0x72, 0xbc, 0xd2, + 0x2f, 0xcd, 0xa3, 0x3d, 0x10, 0xcd, 0x31, 0x4b, 0x2b, 0xb9, 0x12, 0xed, 0xdc, 0x04, 0xb7, + 0x5c, 0x38, 0xd7, 0x71, 0xd4, 0x34, 0x65, 0x39, 0xdd, 0xfe, 0x1b, 0x73, 0x05, 0xb5, 0x27, + 0xc7, 0x53, 0x64, 0xb6, 0x7b, 0x16, 0x97, 0xba, 0xbf, 0x13, 0x4e, 0x5c, 0xc8, 0xf4, 0xcf, + 0x5a, 0x5c, 0x12, 0x96, 0xb5, 0xd5, 0x7e, 0x73, 0x7f, 0x4a, 0x64, 0x55, 0xa0, 0x7d, 0x00, + 0xd7, 0x47, 0x8c, 0x9f, 0x97, 0xcd, 0x55, 0x7f, 0x52, 0x55, 0x30, 0x2f, 0x9a, 0x34, 0x09, + 0x59, 0xa4, 0x04, 0x27, 0xb1, 0x90, 0xbe, 0xdd, 0xba, 0x2b, 0xbf, 0xfd, 0xd1, 0xf3, 0x2a, + 0xba, 0xb5, 0x34, 0xbd, 0xb4, 0x4f, 0x66, 0x15, 0x27, 0x88, 0xb3, 0x8e, 0x91, 0xde, 0x9c, + 0xd5, 0x2c, 0x2c, 0xa9, 0x36, 0xc7, 0xa1, 0x08, 0x28, 0xc3, 0x18, 0xdc, 0xce, 0xa1, 0xf1, + 0xff, 0x0d, 0x89, 0xaf, 0x8f, 0xa6, 0x0d, 0xd4, 0x0b, 0x1b, 0x62, 0x5a, 0x3b, 0xc1, 0x1c, + 0x4b, 0x52, 0x37, 0x81, 0x0c, 0xc5, 0x08, 0xb4, 0x72, 0xf6, 0x96, 0xf5, 0x8c, 0xa2, 0x4d, + 0x6b, 0x63, 0xe5, 0x28, 0x26, 0xdd, 0x61, 0xc7, 0x85, 0xfa, 0x94, 0x85, 0xde, 0x58, 0xdd, + 0x69, 0xae, 0x6d, 0x05, 0x21, 0x19, 0xa1, 0x5c, 0xb4, 0x8b, 0x22, 0xd3, 0x13, 0xc0, 0x70, + 0x50, 0x23, 0x19, 0xd9, 0x38, 0x99, 0x25, 0x7a, 0x03, 0xa1, 0x56, 0x6c, 0x57, 0x67, 0x16, + 0x07, 0xe7, 0x7d, 0xed, 0xf3, 0x45, 0xfb, 0x23, 0x9d, 0x9f, 0x78, 0xc4, 0x36, 0x14, 0x2f, + 0x45, 0x58, 0x52, 0x29, 0xd7, 0x40, 0x36, 0xac, 0x36, 0x14, 0x11, 0x72, 0x8c, 0xe8, 0x08, + 0x6f, 0x5b, 0x7e, 0x3e, 0x76, 0x40, 0x57, 0xcd, 0xa1, 0x36, 0x30, 0x7b, 0x06, 0x16, 0xe5, + 0xba, 0xf7, 0xdb, 0xec, 0xff, 0x12, 0xe3, 0x91, 0x62, 0xc3, 0x75, 0x26, 0x68, 0x73, 0x38, + 0xc7, 0xcf, 0x26, 0xe1, 0xc9, 0x2b, 0xc3, 0xa6, 0x6b, 0x12, 0x6d, 0x98, 0x3d, 0xe0, 0x80, + 0x37, 0x7b, 0x68, 0xc8, 0x9a, 0xfd, 0x3e, 0x85, 0x64, 0x77, 0x5f, 0xe5, 0x53, 0xa3, 0xfd, + 0xe1, 0xe8, 0x48, 0x42, 0x6f, 0xaa, 0xdb, 0x8f, 0x8a, 0x69, 0x55, 0x47, 0xfa, 0x75, 0xcf, + 0xd7, 0x15, 0x3e, 0x57, 0xfa, 0x74, 0x2e, 0xcb, 0x1c, 0x7d, 0x37, 0xf9, 0xb1, 0xc9, 0xd8, + 0x71, 0x21, 0x78, 0x8e, 0xc3, 0xe3, 0x79, 0x97, 0x9d, 0x8b, 0x22, 0x4a, 0x0f, 0x63, 0x02, + 0xbe, 0x5f, 0x31, 0x8e, 0xd6, 0x03, 0xe7, 0xd8, 0x94, 0x6a, 0x0c, 0x92, 0x93, 0x57, 0xdc, + 0x60, 0xc7, 0xac, 0xc5, 0x0a, 0x7f, 0x74, 0x63, 0x98, 0x06, 0x29, 0x0a, 0x82, 0x03, 0xa0, + 0x20, 0x10, 0x64, 0x1e, 0x98, 0xea, 0x1a, 0x1b, 0x18, 0x5f, 0xbf, 0x56, 0xd7, 0x48, 0xa3, + 0x4e, 0x61, 0x0c, 0xa9, 0x87, 0xef, 0x35, 0xa1, 0x42, 0x55, 0xcf, 0x73, 0x07, 0xb7, 0x14, + 0xb0, 0xdf, 0x26, 0x6d, 0xf2, 0x10, 0x4d, 0xa5, 0xcd, 0x1d, 0xe5, 0x1c, 0x1f, 0xb9, 0x64, + 0x17, 0x99, 0x9e, 0xf6, 0xb7, 0x56, 0x29, 0xd1, 0xe8, 0x9a, 0x5e, 0x3c, 0x40, 0xc2, 0xe5, + 0xfc, 0x9d, 0x34, 0x10, 0x88, 0x14, 0x9c, 0xc6, 0xf6, 0x91, 0xe7, 0x18, 0xfe, 0x24, 0x3f, + 0xa7, 0x50, 0x3b, 0x11, 0xd7, 0xf0, 0xba, 0x7f, 0xcf, 0x8d, 0xb6, 0x92, 0x6e, 0x5a, 0x22, + 0x65, 0xf4, 0x34, 0xd7, 0x2c, 0x77, 0x03, 0xf5, 0xc9, 0x9b, 0xc2, 0x3b, 0xc9, 0xe5, 0xce, + 0x58, 0xa4, 0x7f, 0xf1, 0xdb, 0xcb, 0x89, 0x5d, 0xac, 0x93, 0x8a, 0xb4, 0x55, 0x57, 0x4d, + 0x0f, 0x39, 0x59, 0x46, 0xa7, 0x15, 0x3d, 0x61, 0xe3, 0x56, 0x47, 0x26, 0xe8, 0xb9, 0xe5, + 0x6e, 0xf3, 0xa7, 0x24, 0xd5, 0x45, 0xf7, 0x73, 0x55, 0x41, 0xe0, 0x8d, 0x5b, 0xc3, 0xb5, + 0x4d, 0xe9, 0xc7, 0x9a, 0xa9, 0x93, 0x13, 0x7c, 0xda, 0xc8, 0xfc, 0x27, 0x86, 0xb8, 0x35, + 0xf8, 0x07, 0xfa, 0x0f, 0x4c, 0x37, 0xe9, 0x24, 0x6d, 0xee, 0x42, 0x25, 0x20, 0x58, 0xb1, + 0xd0, 0x91, 0x49, 0x9c, 0xf7, 0x66, 0x44, 0x51, 0x2d, 0x60, 0x7d, 0x42, 0xd0, 0xdf, 0xda, + 0x06, 0xdf, 0x41, 0x1a, 0xce, 0xd3, 0xd4, 0x8f, 0x21, 0x34, 0x83, 0xa7, 0x19, 0x12, 0x5a, + 0x96, 0x5e, 0x5e, 0x3c, 0x5e, 0xf0, 0xee, 0x67, 0xbb, 0x44, 0x8e, 0x29, 0x0b, 0xac, 0xb3, + 0xe6, 0x9a, 0x1e, 0xdc, 0xb4, 0xee, 0xb4, 0x3f, 0x7e, 0x38, 0x51, 0x63, 0x74, 0xb3, 0x51, + 0x72, 0x0a, 0x6f, 0x34, 0xd8, 0x3c, 0x34, 0x09, 0x58, 0x5d, 0x88, 0xa9, 0x10, 0xf0, 0x21, + 0x4a, 0xd0, 0x7f, 0x0a, 0xb7, 0x2c, 0xfa, 0xbb, 0x1b, 0xcf, 0x21, 0x82, 0xdd, 0xa2, 0x96, + 0x33, 0xdc, 0xdd, 0x47, 0xf4, 0x43, 0x82, 0xea, 0xa1, 0xf5, 0xd9, 0x02, 0xb1, 0x15, 0x1c, + 0x44, 0x31, 0x11, 0xf2, 0xfd, 0x8e, 0xba, 0x04, 0x72, 0xa9, 0xb0, 0xbd, 0x06, 0xed, 0x2a, + 0x3a, 0x43, 0x14, 0xc7, 0x70, 0xa9, 0x3d, 0x28, 0xee, 0x3f, 0x16, 0x13, 0x10, 0x2b, 0x3e, + 0x8d, 0x07, 0x59, 0x48, 0x91, 0xe8, 0x5b, 0x2a, 0x86, 0x47, 0xea, 0x47, 0xd9, 0xb5, 0xb8, + 0x4d, 0xed, 0xf0, 0x0e, 0x1f, 0x95, 0xf9, 0x4f, 0x5a, 0xb1, 0x35, 0xda, 0x2c, 0xbd, 0xd4, + 0x08, 0x31, 0x5f, 0xe0, 0x22, 0x84, 0x70, 0xf6, 0x93, 0x08, 0x47, 0x21, 0xe2, 0xf8, 0x37, + 0xc4, 0x26, 0x67, 0xae, 0x1b, 0xa3, 0x16, 0xb8, 0x88, 0x38, 0x0a, 0x59, 0xcf, 0x92, 0xb7, + 0x63, 0xc9, 0x61, 0xa5, 0x2f, 0xdf, 0x51, 0x5c, 0x58, 0xcc, 0x4e, 0xb3, 0xab, 0xa7, 0xe9, + 0x5a, 0x16, 0xb4, 0xe8, 0x47, 0x2e, 0xd8, 0x8b, 0xf1, 0x25, 0x72, 0x26, 0x4c, 0x65, 0x33, + 0x2f, 0xa1, 0x13, 0x4f, 0x38, 0xe9, 0x56, 0x80, 0xb9, 0xf5, 0xdf, 0x96, 0x9b, 0xaa, 0xfe, + 0x01, 0x87, 0xe8, 0x0e, 0x98, 0xa0, 0xb6, 0x90, 0x45, 0x80, 0x2b, 0x9a, 0x6c, 0xc0, 0x94, + 0xbb, 0x6f, 0xea, 0x14, 0xbd, 0x9d, 0xab, 0x9d, 0xe3, 0x9a, 0x08, 0x80, 0xa2, 0x19, 0x21, + 0x35, 0x33, 0xb9, 0x3c, 0x5f, 0xb4, 0x6b, 0xf0, 0xef, 0xec, 0xe8, 0x8d, 0x4a, 0xcf, 0xdc, + 0x84, 0x4d, 0xb5, 0xe8, 0xaa, 0xac, 0xf5, 0xd0, 0x4f, 0x46, 0xb7, 0xf8, 0x8f, 0x46, 0x3d, + 0x92, 0x97, 0x57, 0xc9, 0xd4, 0xdf, 0x96, 0x9c, 0x9d, 0x8c, 0x3e, 0x4e, 0x78, 0xe4, 0xcf, + 0xd6, 0xcd, 0xf7, 0x05, 0x75, 0x21, 0x6c, 0x1b, 0xf9, 0x5f, 0x70, 0x0e, 0xed, 0x8b, 0x56, + 0x6b, 0x78, 0xf5, 0x43, 0x0e, 0x8e, 0x7f, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x89, 0xb9, 0x7e, 0x92, 0x7c, 0xb6, 0xce, 0xd7, 0xde, 0xa4, 0x52, 0x2e, 0x4d, + 0x92, 0x78, 0x5d, 0xad, 0x6d, 0x63, 0x95, 0x4f, 0xb2, 0xec, 0xba, 0xca, 0x16, 0x80, 0x1c, + 0xe9, 0x2a, 0xff, 0x0c, 0xfd, 0xe0, 0x1c, 0x28, 0x95, 0x9d, 0xe4, 0xbe, 0xa6, 0xea, 0x9c, + 0x3f, 0xd1, 0x95, 0x44, 0x48, 0x2f, 0xb9, 0x2e, 0x1f, 0x8c, 0xd8, 0xb2, 0xc9, 0xbe, 0xda, + 0x00, 0xc6, 0xc1, 0x77, 0xf6, 0xae, 0xa7, 0x67, 0x39, 0x8b, 0x03, 0x00, 0x15, 0x80, 0x70, + 0xa4, 0x55, 0x24, 0xf2, 0xc7, 0xa2, 0xe9, 0xf0, 0x75, 0x18, 0x1a, 0x89, 0xc2, 0x60, 0xe2, + 0x9c, 0x66, 0xa9, 0xbe, 0xdd, 0x6d, 0xf9, 0xdb, 0x3a, 0x6e, 0x87, 0x60, 0x31, 0xb2, 0xea, + 0xb8, 0x4c, 0x63, 0xfd, 0x63, 0x01, 0xa8, 0x11, 0x43, 0xc6, 0xa7, 0xee, 0x8b, 0x48, 0xe2, + 0x82, 0x1a, 0x8b, 0x94, 0xee, 0x6d, 0xe8, 0x28, 0xf0, 0xd6, 0x41, 0x6a, 0x85, 0x29, 0x32, + 0xb5, 0x0b, 0x35, 0x18, 0xe3, 0x40, 0xba, 0xbd, 0x28, 0x1d, 0x48, 0x67, 0x9d, 0x66, 0x1a, + 0x17, 0xd9, 0x33, 0xcd, 0xa6, 0x87, 0xd2, 0xda, 0xd4, 0x99, 0x9f, 0x7e, 0x81, 0x2b, 0x8c, + 0xe5, 0x23, 0x1b, 0x4f, 0x0f, 0x20, 0x53, 0xfa, 0x6c, 0x04, 0x1c, 0xd9, 0xad, 0x6e, 0x66, + 0x3a, 0x6b, 0x2f, 0x53, 0x1d, 0x23, 0x14, 0xca, 0x45, 0xb8, 0xa6, 0x14, 0x24, 0x5f, 0xc7, + 0x2b, 0x87, 0x36, 0x3a, 0x80, 0x10, 0x2b, 0x1f, 0x3d, 0x4f, 0xfe, 0x0a, 0x08, 0xff, 0x46, + 0xee, 0x13, 0x51, 0x08, 0x7b, 0x26, 0x1f, 0xeb, 0xf7, 0xb7, 0x07, 0xd5, 0xa9, 0x39, 0x5b, + 0x62, 0xb3, 0xff, 0x82, 0xfa, 0x50, 0x60, 0x71, 0xd0, 0x02, 0xf2, 0xb7, 0xf6, 0x83, 0xe8, + 0xbf, 0xb0, 0xd9, 0x87, 0x82, 0x25, 0x86, 0xd4, 0x72, 0x58, 0xdc, 0x5f, 0x43, 0x52, 0xb2, + 0xa5, 0x78, 0x10, 0x40, 0x88, 0x16, 0x3a, 0xc0, 0xb8, 0x1b, 0x85, 0x27, 0x62, 0xcc, 0xe8, + 0xf7, 0x1f, 0x1e, 0x6c, 0x99, 0xaa, 0x10, 0x6b, 0x1c, 0xe6, 0xc0, 0xf3, 0x95, 0x9d, 0xf8, + 0x2b, 0x44, 0x1c, 0x73, 0xc0, 0x25, 0xea, 0x15, 0x05, 0x85, 0xcc, 0xbd, 0x5e, 0xe9, 0x7a, + 0xea, 0x43, 0xfb, 0x8d, 0x16, 0x88, 0x54, 0xf1, 0xb2, 0x4b, 0xd7, 0x89, 0x26, 0x74, 0xc2, + 0xca, 0xe3, 0x8c, 0x26, 0x00, 0x55, 0x65, 0xc9, 0xb4, 0x38, 0x50, 0xa5, 0x09, 0x17, 0x6e, + 0x68, 0xde, 0x0b, 0xeb, 0xa1, 0x60, 0x57, 0x5c, 0xff, 0x9f, 0x75, 0xc0, 0xda, 0x26, 0x0d, + 0x9c, 0x0c, 0x11, 0x73, 0x7e, 0x20, 0xbf, 0xf4, 0x1d, 0x4e, 0x55, 0x80, 0xac, 0x99, 0x1b, + 0xf9, 0x75, 0xe2, 0xa8, 0xc3, 0x06, 0xfc, 0xc2, 0x70, 0x1e, 0xcb, 0x66, 0x3e, 0x70, 0x8a, + 0x08, 0x23, 0xe1, 0xa7, 0x40, 0x15, 0x0a, 0xcd, 0x49, 0xce, 0xb9, 0x77, 0xd1, 0x3e, 0xee, + 0x98, 0x07, 0xc4, 0x9b, 0xdd, 0xc8, 0x05, 0x9a, 0xe1, 0xbf, 0xdd, 0x1a, 0xe6, 0x01, 0x35, + 0x29, 0x55, 0x16, 0xb7, 0x10, 0x75, 0x6d, 0x02, 0x4d, 0xe7, 0x27, 0xec, 0xa4, 0x9a, 0xe6, + 0xb3, 0x0e, 0x8b, 0xda, 0xe1, 0xec, 0x6c, 0x76, 0x64, 0x82, 0x59, 0x63, 0x22, 0x41, 0x11, + 0x04, 0xf5, 0x77, 0xb1, 0x18, 0xdc, 0x80, 0x6c, 0xa8, 0xc3, 0x8c, 0x21, 0x2b, 0xd8, 0xc2, + 0xa9, 0x33, 0xad, 0x9a, 0x1b, 0x17, 0xb8, 0x9a, 0xae, 0xf4, 0x54, 0x60, 0xf9, 0x93, 0xd4, + 0x26, 0xff, 0x26, 0xfb, 0xa8, 0xbf, 0x2d, 0xd5, 0x42, 0x12, 0xa2, 0x23, 0xab, 0x3d, 0x0c, + 0x1f, 0xd2, 0x8f, 0xc7, 0x16, 0x65, 0x97, 0x9b, 0x3c, 0xb9, 0x92, 0x37, 0x7b, 0x9e, 0x0f, + 0xe4, 0x2c, 0x22, 0x7b, 0x9a, 0xdd, 0x69, 0xfe, 0x2b, 0x27, 0xbe, 0x7e, 0xe7, 0x5e, 0xae, + 0xb4, 0xf9, 0xe5, 0x70, 0xae, 0x2d, 0x2d, 0x52, 0x90, 0x70, 0x62, 0xf1, 0x81, 0x8f, 0xe0, + 0xbb, 0xf7, 0x6d, 0x1a, 0xee, 0x1d, 0x36, 0x49, 0x39, 0x82, 0x62, 0x7a, 0x62, 0xb0, 0x6e, + 0x38, 0x77, 0x44, 0x25, 0x92, 0xa1, 0x8b, 0x86, 0x34, 0x69, 0x9a, 0x2c, 0x03, 0x54, 0x85, + 0x68, 0xbf, 0x9e, 0xc6, 0x32, 0x9a, 0x03, 0x79, 0x7c, 0x89, 0x36, 0x61, 0xa3, 0x62, 0xb9, + 0x96, 0xc3, 0xa2, 0x0b, 0xa8, 0x6d, 0xe5, 0x8c, 0x8a, 0x22, 0x2f, 0x30, 0x15, 0x7c, 0xb7, + 0x32, 0xf3, 0x03, 0x04, 0xe9, 0xd2, 0x3d, 0x09, 0x90, 0xa6, 0x96, 0x59, 0x98, 0xb0, 0x73, + 0x9e, 0x1d, 0x91, 0xd6, 0xf2, 0x16, 0xd4, 0xb1, 0xec, 0xe9, 0xb0, 0x6c, 0x3b, 0x0e, 0x95, + 0x21, 0x5b, 0xd9, 0x2b, 0xb1, 0x19, 0xdd, 0x72, 0x4c, 0xcc, 0x74, 0xf1, 0x28, 0xd8, 0xf7, + 0x3f, 0x3e, 0xa2, 0x21, 0xfb, 0x16, 0x22, 0xf6, 0xca, 0x7c, 0x0b, 0xa6, 0xa6, 0x0d, 0x12, + 0x83, 0xfb, 0x96, 0xa8, 0xaa, 0xf6, 0x6c, 0x27, 0x77, 0xbd, 0x01, 0xdf, 0x3e, 0x66, 0x56, + 0x0f, 0x61, 0x07, 0xab, 0xd0, 0x31, 0xac, 0x1d, 0x76, 0x97, 0x6b, 0x77, 0x80, 0x13, 0x4e, + 0x6e, 0xa0, 0x74, 0x8f, 0x4f, 0xf7, 0x49, 0x32, 0xde, 0xbf, 0x56, 0x09, 0xbf, 0x51, 0x47, + 0x05, 0x73, 0x5f, 0xf7, 0xe4, 0xd8, 0xcd, 0x60, 0x1a, 0x05, 0x2e, 0x0d, 0x26, 0x7c, 0xb5, + 0x55, 0x3a, 0xca, 0xbb, 0x0e, 0x34, 0xf7, 0x59, 0xb7, 0xed, 0xcc, 0x2a, 0x8d, 0x75, 0xf3, + 0x4b, 0x5a, 0x3b, 0xe5, 0xcc, 0x6d, 0xcb, 0x55, 0x24, 0x85, 0x9a, 0xee, 0xe2, 0xeb, 0x81, + 0x6c, 0xe9, 0x72, 0xd8, 0xe6, 0xaf, 0x9a, 0xd2, 0x1b, 0x9b, 0x80, 0x40, 0x0e, 0x57, 0xe8, + 0x9e, 0x87, 0xe0, 0x78, 0x82, 0x43, 0xcc, 0x46, 0x96, 0x78, 0x2b, 0xbf, 0x89, 0xd2, 0x08, + 0x72, 0x79, 0x3a, 0x38, 0x05, 0x4d, 0xce, 0x00, 0xe9, 0x3f, 0xcd, 0x03, 0x2e, 0x51, 0xa1, + 0x13, 0x56, 0xae, 0xd7, 0x27, 0x48, 0x94, 0x74, 0x52, 0x5f, 0xed, 0xff, 0xb3, 0x2a, 0x8b, + 0xb9, 0x93, 0xb8, 0x4a, 0xb0, 0xcf, 0x6c, 0x17, 0x02, 0x9f, 0x93, 0xed, 0xec, 0x6f, 0x4b, + 0x28, 0xfb, 0xc1, 0x9b, 0x58, 0x0f, 0x8e, 0x01, 0x99, 0x27, 0x40, 0x0d, 0x9c, 0x07, 0x41, + 0x02, 0xab, 0x8d, 0xc8, 0xe5, 0xab, 0x0e, 0xde, 0x3d, 0xaf, 0x3d, 0xa6, 0xc3, 0x3c, 0x83, + 0x3e, 0x63, 0xcf, 0xf7, 0xa0, 0x88, 0xea, 0x80, 0x05, 0x49, 0x58, 0x3d, 0xa9, 0xec, 0x4a, + 0x94, 0x11, 0xb8, 0x00, 0xd0, 0xb1, 0xc0, 0x45, 0x81, 0x7a, 0x76, 0xc4, 0x32, 0x0f, 0x80, + 0xa3, 0xe4, 0xd4, 0x4c, 0x18, 0x77, 0xee, 0x3b, 0xba, 0x0a, 0x88, 0x87, 0x7e, 0x11, 0xbe, + 0x10, 0x69, 0x88, 0xad, 0x39, 0x16, 0x76, 0x33, 0x8f, 0xbf, 0xe6, 0x40, 0xa4, 0xd3, 0xfb, + 0x09, 0xe9, 0x8f, 0x30, 0xba, 0x80, 0xfb, 0xe3, 0x81, 0x79, 0x5a, 0x1b, 0x8b, 0x4b, 0xf2, + 0x11, 0xdd, 0x31, 0xf5, 0x74, 0x41, 0x0a, 0xa8, 0x72, 0x5f, 0xed, 0x98, 0xd8, 0x31, 0x86, + 0x8b, 0x19, 0x05, 0xa0, 0xe3, 0xb7, 0xbd, 0x54, 0xce, 0xc6, 0xb1, 0xf4, 0x47, 0xa3, 0x83, + 0x6a, 0xaa, 0xeb, 0xa3, 0x52, 0x47, 0xae, 0xd8, 0x84, 0x42, 0x2b, 0x63, 0x92, 0x2a, 0xa5, + 0x63, 0x38, 0xcc, 0xe7, 0x17, 0x10, 0x71, 0xe1, 0x81, 0x04, 0xbc, 0x71, 0x19, 0xf9, 0x94, + 0x53, 0xcc, 0x84, 0xdd, 0x6a, 0x79, 0xc3, 0x47, 0x4b, 0xee, 0xce, 0xb9, 0x60, 0x41, 0xc7, + 0x2e, 0xe8, 0x87, 0x62, 0xd0, 0xd8, 0x9a, 0x1b, 0x55, 0x4a, 0x12, 0xf8, 0x82, 0xfd, 0x1c, + 0x17, 0x86, 0x8b, 0x7c, 0xd2, 0x0e, 0xb2, 0xed, 0x8c, 0x7f, 0x56, 0x89, 0x70, 0xea, 0x2c, + 0x33, 0x7e, 0x01, 0x84, 0xa6, 0x86, 0x0d, 0xa4, 0xb0, 0xbd, 0xa7, 0x73, 0x43, 0xcd, 0xbe, + 0x9e, 0xcc, 0xbf, 0x94, 0x9f, 0xa4, 0xa5, 0xdf, 0x95, 0xd6, 0x01, 0xa3, 0xcd, 0x2c, 0xe6, + 0xb8, 0xb3, 0x5e, 0x33, 0x2b, 0x2f, 0xea, 0xc5, 0x1b, 0x6d, 0x1c, 0x54, 0x32, 0xb7, 0x26, + 0x08, 0xc5, 0x7e, 0xf9, 0x6d, 0x33, 0xcc, 0x51, 0x2c, 0x57, 0x06, 0xa4, 0xf5, 0x8c, 0x47, + 0x5b, 0x2c, 0x36, 0xb4, 0xf2, 0x40, 0xcb, 0x1a, 0x3b, 0x9d, 0xa5, 0x0f, 0x3e, 0xe2, 0x73, + 0xe5, 0xf0, 0x1e, 0x50, 0xef, 0x54, 0x41, 0x68, 0x6c, 0x7c, 0xe6, 0x7d, 0x57, 0xad, 0x38, + 0x0f, 0xa0, 0xcf, 0x95, 0x93, 0xbd, 0x6c, 0x20, 0xc8, 0xa4, 0x36, 0xf3, 0xe0, 0x2a, 0xa0, + 0xc4, 0x4b, 0xec, 0x3b, 0x68, 0x2f, 0xb8, 0xa9, 0x66, 0x39, 0x94, 0x2c, 0xcf, 0x3f, 0xd4, + 0x47, 0xb5, 0x5c, 0xf4, 0xc6, 0xd4, 0x19, 0x3f, 0x3a, 0x05, 0x2a, 0x69, 0x0a, 0xa6, 0x3b, + 0xca, 0xb0, 0x10, 0xc0, 0x19, 0xdb, 0x9b, 0x53, 0x6a, 0x47, 0xbb, 0x3a, 0x36, 0x88, 0x6a, + 0xd9, 0xae, 0x4c, 0x4d, 0x12, 0x2d, 0x8d, 0x43, 0x23, 0x7f, 0x99, 0x0a, 0x99, 0xeb, 0x0b, + 0xef, 0x37, 0x78, 0x80, 0xf4, 0x40, 0xcf, 0x18, 0x15, 0x82, 0xaa, 0x92, 0x27, 0x82, 0x4c, + 0x5a, 0x37, 0x49, 0x66, 0xf5, 0x9a, 0xe5, 0x1b, 0xef, 0x26, 0x8e, 0x9c, 0x39, 0x79, 0xd8, + 0x87, 0xdc, 0xd3, 0x84, 0xf8, 0xbc, 0x8f, 0xfa, 0x28, 0x62, 0xa5, 0xa2, 0xe6, 0x51, 0x90, + 0x66, 0xf0, 0xe6, 0xa9, 0x93, 0xef, 0xcb, 0x25, 0xf0, 0xa6, 0x4b, 0x40, 0xdc, 0xeb, 0x0b, + 0x45, 0xa3, 0xc7, 0x0a, 0x4e, 0xd5, 0x26, 0x30, 0xf4, 0xd3, 0xea, 0x88, 0x1e, 0x22, 0x91, + 0xad, 0x86, 0xf2, 0x93, 0xa2, 0xd8, 0x08, 0xa9, 0x4e, 0x6f, 0xa3, 0x2e, 0xf8, 0xde, 0x1e, + 0x11, 0x84, 0xe8, 0x31, 0x82, 0x7a, 0xb7, 0x2e, 0xf8, 0x2f, 0x29, 0xa7, 0xeb, 0x73, 0x47, + 0x57, 0xf8, 0x34, 0x37, 0xc2, 0x3b, 0x28, 0x72, 0x41, 0xb9, 0xdd, 0x2a, 0x7e, 0x56, 0xb5, + 0x43, 0x26, 0xa6, 0xfa, 0xfd, 0x80, 0x53, 0x39, 0x4f, 0x82, 0x2a, 0x8a, 0xe7, 0xe4, 0x2c, + 0x40, 0xfa, 0x59, 0x60, 0x5a, 0x29, 0x25, 0x60, 0x13, 0xff, 0xaf, 0x70, 0x69, 0x97, 0xd5, + 0x55, 0x80, 0x12, 0x2a, 0xc1, 0x17, 0x06, 0x8f, 0xdf, 0xc8, 0x4c, 0xa5, 0x56, 0x98, 0x57, + 0x48, 0x56, 0x87, 0x90, 0xa0, 0x03, 0xf4, 0x2d, 0x4d, 0x09, 0x32, 0x74, 0xed, 0xfc, 0x9e, + 0x53, 0xd2, 0x4b, 0xc5, 0xdf, 0xdd, 0xe2, 0xb9, 0x71, 0x2d, 0xf0, 0x40, 0x2e, 0xaa, 0xe7, + 0x8b, 0xf2, 0xd3, 0x6c, 0xd3, 0x34, 0xaf, 0x58, 0x71, 0x98, 0x7a, 0x6b, 0x56, 0x15, 0xfd, + 0x06, 0x1a, 0xf5, 0x4a, 0x8c, 0xea, 0xa5, 0x9a, 0x06, 0x80, 0x0d, 0x03, 0x62, 0x3f, 0x02, + 0x03, 0xcb, 0x9c, 0x73, 0x6b, 0x95, 0xfd, 0x10, 0x11, 0xf2, 0xc9, 0xfa, 0x97, 0x9e, 0x67, + 0x8b, 0x15, 0xe2, 0x7c, 0xfc, 0x00, 0x96, 0xcf, 0x76, 0x5e, 0x97, 0x38, 0x41, 0x42, 0x9a, + 0xe4, 0xf4, 0xfd, 0xaf, 0xbf, 0x90, 0xbb, 0x80, 0xe5, 0x9b, 0x87, 0x0e, 0x2a, 0xcc, 0xfc, + 0x16, 0x05, 0x5c, 0xf0, 0xca, 0x67, 0xf1, 0x70, 0xef, 0x17, 0x68, 0xb0, 0x73, 0x0b, 0x35, + 0x30, 0xda, 0xeb, 0x2c, 0x0f, 0x8c, 0x0f, 0x1e, 0x86, 0x95, 0x7b, 0x45, 0x7a, 0x0d, 0xb2, + 0xf4, 0xb2, 0x6a, 0x1c, 0x4a, 0x9d, 0x59, 0x44, 0x9c, 0x4b, 0x4a, 0x9c, 0xd8, 0x87, 0xa6, + 0xac, 0xad, 0x5a, 0x96, 0x5d, 0x8c, 0xaa, 0xc7, 0x1a, 0x1f, 0x68, 0x44, 0x4d, 0x32, 0xc4, + 0x3a, 0x44, 0x85, 0x60, 0x4e, 0x89, 0x5d, 0xb6, 0xc2, 0x3a, 0xdf, 0xa5, 0x8d, 0xa0, 0xb5, + 0x0c, 0x25, 0xa9, 0x1c, 0x6d, 0xa9, 0x95, 0x35, 0xae, 0x03, 0x3e, 0x79, 0xbd, 0x20, 0x6e, + 0x30, 0x93, 0x6e, 0x9e, 0x0e, 0x21, 0x7a, 0x4c, 0x2f, 0xac, 0xf1, 0x2d, 0xb9, 0xf8, 0xab, + 0x2b, 0x6c, 0x17, 0x07, 0x55, 0xe0, 0x53, 0x49, 0xc2, 0xad, 0xcc, 0x45, 0xae, 0xb2, 0x5a, + 0x38, 0x68, 0xae, 0x79, 0x27, 0x82, 0x22, 0x68, 0xeb, 0x75, 0x02, 0x1e, 0x7d, 0xd3, 0x15, + 0x0e, 0xd9, 0x66, 0x32, 0x60, 0xe5, 0x51, 0x47, 0xd8, 0xd8, 0xe7, 0x70, 0x77, 0xc5, 0xbd, + 0xe7, 0x6e, 0x6f, 0x8b, 0x98, 0x8e, 0x19, 0x4d, 0x1c, 0x0c, 0xf2, 0x47, 0x71, 0xa1, 0x64, + 0x8b, 0xf4, 0xc6, 0x80, 0x0f, 0xab, 0x1e, 0x5d, 0x10, 0x62, 0xfd, 0x17, 0x18, 0x3f, 0x92, + 0x20, 0x05, 0x8f, 0xca, 0x87, 0xfc, 0xf7, 0xf4, 0xa9, 0xdd, 0xa6, 0x4d, 0x02, 0xc4, 0x5d, + 0xce, 0xf9, 0x93, 0xaf, 0x4d, 0x42, 0xa0, 0x64, 0x42, 0x29, 0x5b, 0xcf, 0x93, 0xfb, 0x8e, + 0x0a, 0xa3, 0xf0, 0xb3, 0x64, 0xbd, 0xc9, 0xdf, 0xbc, 0xbf, 0x87, 0xef, 0x73, 0x53, 0xcd, + 0xed, 0x2f, 0xb7, 0xee, 0xe8, 0x3d, 0xcc, 0x0d, 0xd5, 0x12, 0xdb, 0xf4, 0x6f, 0x8b, 0xe7, + 0x08, 0x4a, 0x7b, 0x1b, 0x54, 0x14, 0x5a, 0x0c, 0x63, 0x16, 0xb2, 0xa1, 0x1f, 0x7b, 0x76, + 0x18, 0x13, 0xfa, 0x31, 0x83, 0xb7, 0xc9, 0x99, 0x24, 0x65, 0xdc, 0x0a, 0x6f, 0xb6, 0xf8, + 0x3f, 0xe2, 0xb9, 0xf6, 0x54, 0x28, 0x49, 0x28, 0xa3, 0x1c, 0x01, 0xa7, 0x0d, 0x55, 0x45, + 0xd2, 0x02, 0x80, 0x03, 0xe5, 0xc9, 0xe2, 0xd3, 0x7d, 0xe7, 0xf3, 0x37, 0xfe, 0x28, 0x09, + 0x12, 0x26, 0x07, 0x4c, 0x80, 0xe4, 0x39, 0x04, 0x73, 0x39, 0x00, 0x06, 0xa5, 0xa3, 0x22, + 0x6d, 0xd8, 0x86, 0x99, 0x14, 0x5d, 0x50, 0xb4, 0x20, 0x17, 0xd6, 0x06, 0x36, 0x16, 0x2b, + 0xbc, 0xc6, 0xc8, 0x73, 0x87, 0x17, 0xd6, 0xc9, 0x41, 0x25, 0xcd, 0x3e, 0x50, 0x29, 0x91, + 0x32, 0x8f, 0xba, 0x37, 0x65, 0x45, 0x5e, 0x6c, 0x1c, 0x41, 0xab, 0x94, 0xbc, 0x21, 0xd5, + 0x16, 0x04, 0xa1, 0xd9, 0xe4, 0x87, 0x86, 0x9a, 0x97, 0x13, 0x98, 0x84, 0x48, 0x1f, 0x39, + 0xec, 0x7d, 0x81, 0x0c, 0x35, 0xf0, 0xac, 0x12, 0xde, 0x4b, 0x8f, 0x47, 0x5b, 0x82, 0xd0, + 0xbb, 0x10, 0x36, 0xaf, 0x94, 0x62, 0xf6, 0x93, 0xf6, 0x3a, 0x99, 0x91, 0xdb, 0x28, 0x45, + 0x19, 0xe6, 0x64, 0xba, 0x4a, 0x9f, 0xe3, 0x85, 0x68, 0x5f, 0x29, 0xad, 0x1e, 0x64, 0xbd, + 0xae, 0x36, 0xcb, 0xc6, 0xd5, 0x7b, 0xb7, 0x55, 0xa5, 0x9a, 0xf4, 0x26, 0x7b, 0x90, 0xf4, + 0x4d, 0x0a, 0x39, 0xf3, 0x5c, 0x79, 0x00, 0xd8, 0x7a, 0x07, 0x6e, 0x02, 0x5e, 0x6a, 0x69, + 0x75, 0x00, 0x6e, 0x7c, 0xfe, 0x24, 0x66, 0x38, 0xa6, 0xa2, 0x8d, 0x9a, 0x23, 0x36, 0x1e, + 0x9e, 0x9f, 0x45, 0x7b, 0x17, 0xfe, 0xb8, 0x77, 0x99, 0x42, 0x7d, 0x5d, 0x0b, 0xd8, 0x74, + 0x70, 0xfb, 0x29, 0x15, 0x46, 0x4e, 0xae, 0x8d, 0x67, 0xc5, 0xde, 0x2d, 0x1b, 0x40, 0x61, + 0x07, 0x1f, 0xa4, 0x04, 0xbb, 0x49, 0x15, 0xc3, 0x07, 0x83, 0x24, 0x11, 0x68, 0x37, 0x10, + 0x74, 0x9a, 0xb8, 0x68, 0xbf, 0xd3, 0x78, 0x89, 0xe9, 0x3a, 0x29, 0x70, 0x93, 0x1d, 0x60, + 0x19, 0x70, 0x2e, 0x53, 0xe4, 0x4d, 0x7c, 0x6d, 0x08, 0x99, 0x60, 0x1a, 0xdb, 0x96, 0x56, + 0x0d, 0xbf, 0x9d, 0xf8, 0xde, 0xca, 0x54, 0x22, 0xc9, 0x28, 0xff, 0xd0, 0xf9, 0xe4, 0x3f, + 0x2a, 0x4d, 0xfa, 0x03, 0x06, 0x2a, 0xcd, 0x29, 0x58, 0xe2, 0x08, 0xb9, 0x8c, 0x9e, 0x2c, + 0x6e, 0x58, 0x9c, 0x5a, 0x2a, 0x0f, 0x7e, 0xd3, 0xe4, 0xad, 0x3f, 0x61, 0xad, 0x80, 0x9d, + 0xe7, 0x3b, 0xe7, 0x51, 0x1f, 0x23, 0x84, 0xae, 0xa0, 0x86, 0xbc, 0x6a, 0x0a, 0x9e, 0x41, + 0x7d, 0x99, 0x5d, 0x67, 0x4b, 0x93, 0xd5, 0xd1, 0x29, 0xf6, 0x1c, 0xf5, 0x7f, 0x3f, 0xe3, + 0x70, 0x52, 0x66, 0x11, 0xb2, 0xf3, 0x60, 0x14, 0x03, 0x40, 0x1a, 0x3f, 0x7a, 0x79, 0x22, + 0x7b, 0xdb, 0xba, 0xfa, 0x4a, 0xc7, 0x10, 0x8a, 0xc2, 0x8f, 0x41, 0x77, 0x2e, 0x82, 0xd7, + 0xa0, 0x3d, 0xdb, 0xf5, 0xed, 0x67, 0xa4, 0x03, 0x96, 0x00, 0x95, 0xb6, 0x8d, 0x7f, 0x5b, + 0xbf, 0x1a, 0xfa, 0x95, 0xd5, 0x3c, 0xab, 0xfd, 0xdd, 0x8e, 0x1f, 0xb4, 0x32, 0x9c, 0x08, + 0x43, 0x27, 0xd4, 0xdc, 0xa0, 0x55, 0x2e, 0x21, 0x6f, 0x49, 0xc6, 0x5e, 0x60, 0x42, 0x95, + 0x1f, 0x1a, 0xbd, 0x09, 0x9e, 0xab, 0xb9, 0xc7, 0x38, 0x38, 0x6e, 0x5f, 0xfa, 0x5c, 0x15, + 0xd3, 0x87, 0x3e, 0x0a, 0x69, 0x97, 0xaa, 0x3f, 0x46, 0xe8, 0xe8, 0xf5, 0x97, 0x10, 0x94, + 0x6c, 0x5d, 0xf4, 0x4e, 0x73, 0x06, 0x35, 0x85, 0xbd, 0x17, 0x1a, 0x79, 0x52, 0xee, 0xf8, + 0x43, 0x3a, 0x75, 0x04, 0x0a, 0x04, 0xde, 0x4b, 0x4e, 0xcf, 0x75, 0x1d, 0x2d, 0xe3, 0x12, + 0xb5, 0x8b, 0x48, 0x1c, 0xfd, 0xdd, 0x5b, 0x1b, 0x5d, 0x27, 0x18, 0x1f, 0x7e, 0xc5, 0x14, + 0x94, 0xa0, 0x2a, 0xca, 0xb6, 0x8c, 0x44, 0x09, 0x4f, 0x4a, 0x97, 0x68, 0x7b, 0x9a, 0x3c, + 0x3e, 0xc6, 0xfb, 0x6c, 0x2b, 0xc7, 0x88, 0x05, 0x44, 0x14, 0xc3, 0x51, 0x4e, 0xf8, 0x4b, + 0x0b, 0x6e, 0x6a, 0xcc, 0x50, 0x7b, 0xfa, 0xc3, 0xd4, 0x82, 0x7b, 0xc4, 0xa8, 0xf4, 0x82, + 0x64, 0xf2, 0xb0, 0xce, 0x14, 0xdb, 0x51, 0xc7, 0xd1, 0x08, 0x32, 0x26, 0x16, 0xd1, 0x2b, + 0xcb, 0xba, 0x8f, 0x41, 0x6d, 0xbb, 0x28, 0xfd, 0xdc, 0x9d, 0x9e, 0xfc, 0x05, 0xc0, 0x4b, + 0xb0, 0x6c, 0x2e, 0x6d, 0x60, 0x45, 0xc9, 0x4d, 0x8b, 0x48, 0x62, 0x08, 0x27, 0x37, 0xea, + 0xb2, 0x06, 0x3c, 0x61, 0x8b, 0x3c, 0x15, 0x26, 0x4c, 0x5b, 0x59, 0xc3, 0x7e, 0x68, 0xfa, + 0xaf, 0x7d, 0x70, 0x4a, 0x55, 0x89, 0x9c, 0xea, 0x68, 0xdb, 0xa8, 0x63, 0xe7, 0x6b, 0x43, + 0x0e, 0xcb, 0x47, 0x0e, 0x76, 0x36, 0x49, 0xb2, 0x61, 0x34, 0x5d, 0x2e, 0x31, 0x9c, 0x0f, + 0x18, 0x5a, 0xbf, 0x7c, 0x29, 0x33, 0x59, 0xa6, 0xc4, 0x55, 0x22, 0xfd, 0xe2, 0x19, 0x09, + 0x3f, 0x5d, 0x15, 0x16, 0xf7, 0xfe, 0x52, 0x4e, 0x59, 0xe0, 0xae, 0x96, 0xfb, 0x1b, 0x00, + 0xfe, 0xc0, 0xbc, 0x4a, 0xdf, 0xd4, 0x24, 0x6b, 0xf1, 0x7e, 0x23, 0x64, 0x5b, 0x23, 0x14, + 0x40, 0x22, 0x52, 0x2f, 0x2f, 0xdb, 0x8a, 0x08, 0x7a, 0xa0, 0x45, 0x8b, 0x93, 0xef, 0xeb, + 0xc7, 0x64, 0xc6, 0x35, 0xe3, 0xfa, 0x7c, 0x74, 0xbd, 0xd3, 0x81, 0xde, 0xdd, 0x33, 0x3b, + 0x9d, 0x94, 0x5e, 0x55, 0xf5, 0xc0, 0x3b, 0x69, 0x2f, 0xd5, 0xd9, 0x5b, 0x88, 0x42, 0xa2, + 0x1d, 0xe7, 0xde, 0x8b, 0xc0, 0x72, 0xde, 0x71, 0x8f, 0xa4, 0xdc, 0x6a, 0x28, 0x4a, 0xb7, + 0x33, 0xe9, 0x06, 0x3a, 0x9b, 0x88, 0x9f, 0x1a, 0x3b, 0x90, 0x0d, 0xb8, 0x36, 0x1d, 0x4b, + 0x23, 0x5c, 0xa5, 0x28, 0xdf, 0x64, 0x82, 0xa8, 0xfc, 0x6d, 0xdf, 0x4c, 0x9f, 0xbb, 0x8e, + 0x3c, 0x39, 0xba, 0xe6, 0x60, 0xf5, 0x55, 0xa7, 0x66, 0x55, 0x3f, 0x1f, 0xfc, 0x99, 0x03, + 0x16, 0x2e, 0xcb, 0x66, 0x74, 0x8d, 0xb2, 0x6b, 0xce, 0x32, 0xb6, 0xf6, 0x24, 0xcd, 0x7a, + 0xbf, 0x4c, 0xd8, 0x3c, 0x20, 0x23, 0x46, 0x71, 0x07, 0x99, 0x57, 0x29, 0x04, 0x98, 0x18, + 0x1c, 0x46, 0x67, 0xcb, 0xeb, 0xcf, 0xc0, 0x46, 0x46, 0xa3, 0xfd, 0xb3, 0x70, 0x89, 0x90, + 0x38, 0xf8, 0x5a, 0x9e, 0x46, 0xae, 0x10, 0x6b, 0x17, 0x67, 0x18, 0x75, 0x20, 0xff, 0x19, + 0x62, 0x60, 0xaa, 0x5d, 0xd1, 0x34, 0xb4, 0xca, 0xf2, 0xc3, 0x16, 0xdf, 0x2b, 0x4d, 0x46, + 0xfc, 0x87, 0x14, 0x4a, 0xc3, 0x2d, 0x4c, 0x26, 0x34, 0x02, 0x0c, 0xbf, 0x9e, 0x82, 0x08, + 0x2c, 0x0c, 0xc6, 0xb6, 0xe2, 0xbd, 0xa4, 0x88, 0x1d, 0xf1, 0xba, 0x8a, 0xef, 0x3a, 0xf2, + 0x3e, 0xb0, 0x8d, 0xe8, 0x08, 0x62, 0x9b, 0xa5, 0xe4, 0xb6, 0xd4, 0xbf, 0xf6, 0xc2, 0x7c, + 0xfe, 0xce, 0x14, 0x18, 0xd6, 0x6f, 0x7d, 0x2c, 0xb9, 0x9a, 0xb0, 0x72, 0xf0, 0x55, 0x3d, + 0xaf, 0x18, 0xb8, 0x9d, 0x0d, 0x0b, 0x09, 0x41, 0x22, 0x9e, 0xf4, 0xf0, 0x78, 0xfe, 0xd3, + 0xaa, 0x47, 0xf6, 0xe4, 0xad, 0x2e, 0xf1, 0xaf, 0xa4, 0x5c, 0xff, 0xd4, 0x7b, 0x68, 0x75, + 0x12, 0xba, 0x74, 0xc5, 0x61, 0xd4, 0x48, 0x77, 0x37, 0x6d, 0x12, 0xbc, 0x3d, 0x46, 0x44, + 0xe7, 0x66, 0xc0, 0x0c, 0x98, 0xec, 0x78, 0x33, 0xb9, 0x38, 0x14, 0xed, 0x9c, 0xfe, 0x61, + 0xc7, 0xcc, 0x16, 0x79, 0x3b, 0xea, 0x09, 0xea, 0x08, 0xfe, 0x74, 0x78, 0x72, 0x1d, 0x17, + 0xe4, 0x6f, 0x06, 0x4f, 0xec, 0xa2, 0x95, 0xd6, 0x3f, 0x2c, 0x06, 0x66, 0x42, 0x4b, 0x64, + 0xba, 0x19, 0x41, 0x3a, 0x9a, 0x6e, 0x5b, 0xea, 0x31, 0x02, 0xd1, 0x97, 0x21, 0xeb, 0x61, + 0xff, 0x4d, 0x8b, 0xdd, 0x33, 0x7f, 0x22, 0xb0, 0xe9, 0xd7, 0x77, 0x24, 0x1f, 0xb8, 0xd3, + 0x39, 0x51, 0xec, 0x69, 0xde, 0x45, 0x58, 0xdd, 0x6d, 0x1e, 0x7d, 0xba, 0x98, 0xe9, 0xe2, + 0xc5, 0xe5, 0xf5, 0xa7, 0x2a, 0x9a, 0x8a, 0xe7, 0x16, 0x1c, 0xde, 0x19, 0x39, 0x34, 0x65, + 0x7e, 0xd5, 0x29, 0x59, 0x85, 0x21, 0x54, 0x86, 0x0d, 0xfb, 0xf5, 0xe7, 0xf1, 0x03, 0xb9, + 0x42, 0x41, 0x0c, 0x8e, 0x06, 0xd2, 0x14, 0x70, 0x09, 0x5d, 0xa7, 0x71, 0xeb, 0x94, 0x97, + 0x04, 0x1a, 0xa4, 0xcd, 0x95, 0x87, 0xc8, 0x06, 0xbe, 0x7d, 0xaa, 0x77, 0x0a, 0x4e, 0xb1, + 0x31, 0x1b, 0x55, 0x3f, 0xf0, 0x42, 0x3b, 0x99, 0x5f, 0x4b, 0x2f, 0x6e, 0xae, 0xc9, 0x43, + 0x1b, 0x55, 0x22, 0x07, 0x38, 0x3e, 0xc5, 0xf7, 0x41, 0x03, 0x7d, 0xba, 0x82, 0xac, 0x2d, + 0x78, 0xad, 0xb8, 0x39, 0xef, 0x3d, 0x97, 0x62, 0xcd, 0x15, 0xa0, 0x99, 0x46, 0x5d, 0xf3, + 0xe0, 0xae, 0x65, 0x77, 0x11, 0xd0, 0x89, 0x78, 0x5c, 0x56, 0x2c, 0x60, 0xbd, 0xa9, 0x42, + 0x4b, 0xb0, 0x90, 0x23, 0x8e, 0xc6, 0xeb, 0x39, 0x37, 0x74, 0x2b, 0x34, 0x2a, 0x4d, 0x9f, + 0xf4, 0x0a, 0x5b, 0xa5, 0x3c, 0xaa, 0x33, 0x86, 0x0a, 0xe1, 0x3f, 0x7a, 0x34, 0xae, 0x45, + 0x57, 0x17, 0x8c, 0x64, 0xa2, 0xd4, 0xa1, 0x50, 0xe6, 0x14, 0x8d, 0xcc, 0x3f, 0x7d, 0xbf, + 0x87, 0xc3, 0x11, 0x8b, 0x6d, 0x09, 0xd2, 0x93, 0x30, 0xff, 0x48, 0xaf, 0x7b, 0x7c, 0x45, + 0x3f, 0x28, 0xbd, 0xaf, 0x8f, 0x24, 0xb9, 0x34, 0xe5, 0x09, 0xeb, 0xa7, 0xef, 0x58, 0x0f, + 0x86, 0x0f, 0xc1, 0xaf, 0x4c, 0x70, 0x96, 0xeb, 0x17, 0x50, 0x1a, 0x33, 0x72, 0xbb, 0x18, + 0xa0, 0x66, 0x99, 0x17, 0x80, 0x08, 0xec, 0x95, 0xb8, 0x5e, 0xae, 0xbe, 0xd3, 0xc0, 0xa3, + 0xa5, 0xc5, 0x15, 0x69, 0xc3, 0xf2, 0x8d, 0x4c, 0x36, 0xe7, 0x8e, 0x7b, 0x2a, 0xbc, 0x0e, + 0xec, 0xd0, 0x6a, 0xdc, 0x0a, 0xff, 0x5f, 0xd2, 0x42, 0xb9, 0xda, 0x41, 0x9e, 0xcb, 0xaa, + 0xef, 0x02, 0xbe, 0xa0, 0x1e, 0xb7, 0xed, 0x83, 0xac, 0xd4, 0xf3, 0x19, 0x6e, 0xb1, 0x1d, + 0x7b, 0x0b, 0x48, 0x51, 0xbd, 0xda, 0x5b, 0x04, 0x14, 0xd4, 0x37, 0x01, 0x7b, 0x32, 0xa6, + 0xe4, 0xd9, 0x11, 0x46, 0x6d, 0xec, 0xd9, 0xf0, 0x2e, 0x3b, 0xb6, 0xf0, 0x98, 0xc0, 0x14, + 0xd2, 0x12, 0xae, 0x07, 0x85, 0x0f, 0x87, 0x89, 0x93, 0x32, 0xa1, 0x25, 0x10, 0x40, 0xc8, + 0xf6, 0xee, 0xb9, 0x3a, 0xfa, 0x69, 0xfa, 0x3f, 0xe3, 0xc3, 0xea, 0x9a, 0xca, 0xe5, 0x7d, + 0x11, 0x3d, 0x80, 0x21, 0x90, 0xc5, 0xbd, 0xbe, 0x3e, 0x22, 0xf6, 0x20, 0x42, 0x1e, 0xda, + 0xfc, 0x78, 0xec, 0xac, 0x84, 0x75, 0xce, 0x86, 0x3c, 0xd0, 0xb0, 0xd7, 0xa7, 0x43, 0xc7, + 0xdd, 0x6d, 0x8d, 0xda, 0xdf, 0x1e, 0xfa, 0x41, 0x72, 0x5d, 0x42, 0xb4, 0xcb, 0xca, 0xf1, + 0xd6, 0xe3, 0x36, 0xb2, 0xee, 0x7e, 0x55, 0x31, 0x1c, 0x13, 0x83, 0xf4, 0x57, 0x99, 0x5f, + 0x57, 0xf6, 0x15, 0xba, 0x0b, 0xdb, 0x2d, 0x0e, 0xdc, 0x78, 0x21, 0xe9, 0x45, 0x39, 0xe3, + 0x83, 0x4d, 0xb2, 0xfc, 0x67, 0xe8, 0x36, 0x13, 0xd5, 0xd3, 0x9c, 0x37, 0xa6, 0x1d, 0x79, + 0x61, 0x80, 0x02, 0xa7, 0x3c, 0x29, 0x45, 0x2c, 0x53, 0x20, 0xa6, 0x98, 0x7b, 0xf1, 0x3a, + 0xef, 0x34, 0x24, 0x39, 0xe0, 0xb5, 0x8e, 0x65, 0xc9, 0x2c, 0xb5, 0xfd, 0xa1, 0xd3, 0xad, + 0x34, 0xb4, 0x29, 0xcd, 0x0c, 0xfa, 0x34, 0xb2, 0x55, 0xba, 0x2b, 0x26, 0x95, 0x8a, 0x47, + 0xe9, 0xa0, 0xb8, 0xaf, 0x53, 0xaa, 0xc9, 0x10, 0x86, 0x6c, 0x7f, 0xde, 0x02, 0xe5, 0xeb, + 0x77, 0x0d, 0xff, 0x30, 0x31, 0xae, 0x21, 0xda, 0x0e, 0x72, 0x51, 0x34, 0x34, 0x15, 0x64, + 0xa7, 0x8f, 0xde, 0x48, 0xa3, 0x7e, 0x4b, 0xd2, 0xcf, 0xfa, 0x7c, 0xc1, 0x50, 0x9a, 0xa2, + 0x3e, 0x1d, 0xd5, 0xb0, 0xf5, 0x6f, 0xc3, 0xd0, 0xbe, 0xd0, 0x26, 0xc8, 0xc1, 0x2f, 0xd7, + 0x09, 0xc8, 0xbf, 0xaf, 0x74, 0xa4, 0x53, 0xd1, 0xf4, 0x02, 0x44, 0xe6, 0xaa, 0x6f, 0x9d, + 0x00, 0x2c, 0x31, 0x6b, 0xa4, 0xb5, 0x0c, 0xdc, 0xc3, 0x41, 0xd7, 0x4d, 0x90, 0x5f, 0x77, + 0x42, 0x02, 0x3c, 0x0c, 0x3f, 0x3a, 0xf3, 0xac, 0x57, 0x85, 0x54, 0x4e, 0xac, 0xdf, 0x6a, + 0x79, 0x7f, 0x3e, 0x29, 0xb5, 0x1d, 0x1a, 0x22, 0x8b, 0x9a, 0x09, 0xd7, 0x72, 0xbb, 0x0f, + 0xa3, 0xdd, 0xa6, 0xf0, 0x00, 0xbf, 0x2e, 0x0f, 0x63, 0x5f, 0xe1, 0xf7, 0x85, 0x02, 0x61, + 0x03, 0x47, 0xa9, 0xe2, 0xfe, 0xaa, 0x9d, 0x34, 0xca, 0x34, 0xb5, 0x3b, 0xb9, 0xb7, 0xa9, + 0x5a, 0xea, 0xb0, 0x17, 0x97, 0x44, 0x34, 0xd6, 0x68, 0xac, 0xdb, 0x58, 0xdd, 0x38, 0xfe, + 0x58, 0x23, 0x95, 0xc6, 0xea, 0xf6, 0xf9, 0x00, 0x58, 0xe3, 0x37, 0x22, 0x3d, 0x4b, 0xfc, + 0x2b, 0x9e, 0xf8, 0x4b, 0x39, 0x4a, 0xf1, 0xb0, 0x0b, 0x2e, 0x91, 0x77, 0xb2, 0xc5, 0x16, + 0xe8, 0x6c, 0xaa, 0x42, 0x19, 0xba, 0x22, 0x1c, 0x3b, 0xd9, 0x2f, 0x29, 0x03, 0xde, 0x50, + 0x83, 0xc2, 0xb6, 0x22, 0x66, 0x4b, 0x95, 0x86, 0xfb, 0x3f, 0x1f, 0x3e, 0xe1, 0x58, 0xf5, + 0x51, 0x87, 0xeb, 0x3b, 0x32, 0xad, 0xd8, 0x43, 0xe7, 0x80, 0xcc, 0x89, 0xac, 0x04, 0x3f, + 0x12, 0x47, 0x27, 0x58, 0xb3, 0x54, 0x11, 0x36, 0xc1, 0x06, 0xcd, 0xa2, 0x2b, 0x87, 0x25, + 0xa6, 0xc8, 0x94, 0x1d, 0x74, 0x4f, 0xb9, 0x32, 0x45, 0x02, 0xdb, 0x16, 0xfd, 0xcd, 0x69, + 0x78, 0x84, 0x89, 0xa8, 0x39, 0xfe, 0x07, 0xe4, 0x6c, 0x8e, 0x13, 0xf4, 0x41, 0x4b, 0x2e, + 0xdf, 0x57, 0xed, 0x3b, 0x42, 0xfb, 0xf0, 0x02, 0x6b, 0x7b, 0x04, 0xb3, 0xb3, 0x56, 0x4f, + 0xe8, 0xe1, 0xaa, 0x27, 0xdc, 0x13, 0x0d, 0xa7, 0x21, 0xa3, 0xdb, 0x54, 0x08, 0x2a, 0xd9, + 0xae, 0x3a, 0xbe, 0xf2, 0x60, 0x0b, 0x39, 0x11, 0x54, 0xe8, 0xb8, 0x85, 0x61, 0x72, 0x1e, + 0x7a, 0x9b, 0x39, 0x12, 0x9d, 0x57, 0xfd, 0xde, 0x0c, 0x73, 0xb3, 0xfd, 0x8c, 0xec, 0x66, + 0x37, 0xdf, 0x97, 0x10, 0xf2, 0xc6, 0x07, 0x97, 0x18, 0x2c, 0xd0, 0xf5, 0x5b, 0xa7, 0x28, + 0xd4, 0xae, 0xfe, 0x53, 0x7b, 0x7b, 0x83, 0xd4, 0x7e, 0x99, 0x55, 0xe6, 0x40, 0xff, 0x3e, + 0x4e, 0xc6, 0xce, 0xf3, 0x50, 0x1c, 0x91, 0x2d, 0xd8, 0x30, 0xcd, 0x6e, 0xcc, 0x51, 0x72, + 0x1c, 0xe9, 0x91, 0x44, 0x3c, 0xf2, 0x77, 0x37, 0x79, 0x04, 0x7f, 0xc6, 0xb5, 0x80, 0xf8, + 0x91, 0x53, 0x64, 0x65, 0x6a, 0x9f, 0x75, 0x16, 0x4c, 0x08, 0x37, 0x32, 0x83, 0xfb, 0x4b, + 0x48, 0xba, 0xed, 0x1a, 0x73, 0xe7, 0x58, 0x92, 0xdf, 0xa7, 0xc2, 0x68, 0xe9, 0x65, 0x42, + 0xfa, 0xf8, 0x40, 0x8a, 0xda, 0x20, 0x9e, 0x14, 0x09, 0x0e, 0xea, 0x6f, 0x9e, 0x78, 0x9d, + 0x91, 0xe4, 0x3d, 0x09, 0x7f, 0x16, 0xde, 0xec, 0x4e, 0x58, 0x2b, 0x07, 0xdd, 0xbc, 0x68, + 0x6e, 0xb4, 0x4c, 0x68, 0x7b, 0x4c, 0x8c, 0xc9, 0x62, 0x4a, 0x65, 0x33, 0x1c, 0xcc, 0x6b, + 0x9b, 0x1b, 0xaf, 0xa1, 0x4a, 0x22, 0x40, 0x57, 0x9e, 0xc5, 0x69, 0x08, 0xba, 0x24, 0x20, + 0x03, 0x43, 0x22, 0x1b, 0x63, 0xb1, 0x81, 0xd5, 0x9c, 0x33, 0x20, 0x54, 0xda, 0x14, 0x31, + 0x2f, 0x22, 0xe4, 0x63, 0xbc, 0x5b, 0xb6, 0x0e, 0x7c, 0x2c, 0x04, 0xf9, 0xbe, 0x99, 0xa7, + 0x7a, 0x63, 0x02, 0x73, 0x8e, 0x9a, 0xb7, 0x7b, 0xc2, 0xa4, 0xf4, 0x0e, 0x34, 0x51, 0xe0, + 0x04, 0x5c, 0xc7, 0xd0, 0xba, 0x01, 0xef, 0xdf, 0x12, 0x3f, 0xd4, 0x8c, 0xc8, 0x2c, 0xd5, + 0xcc, 0xe9, 0xdd, 0x69, 0x2d, 0x2f, 0xf5, 0xf6, 0x5a, 0x79, 0xc7, 0x0c, 0x50, 0x04, 0x31, + 0x2b, 0xcf, 0x03, 0xc1, 0x93, 0xbe, 0xf3, 0x32, 0x30, 0x49, 0x25, 0xe2, 0xbe, 0x42, 0x62, + 0x2f, 0x61, 0x91, 0x1a, 0xb6, 0x2f, 0x89, 0xce, 0x8c, 0x96, 0x49, 0x56, 0x7c, 0x05, 0xf4, + 0xf7, 0x06, 0x56, 0x0d, 0x35, 0x7b, 0x81, 0x9a, 0xc7, 0xaa, 0x47, 0x36, 0x9f, 0x3a, 0xf3, + 0xbb, 0x3a, 0x4e, 0x4b, 0xe0, 0x8e, 0x82, 0x52, 0x31, 0xb8, 0xac, 0x13, 0x33, 0x75, 0x99, + 0xe7, 0xb6, 0x01, 0x24, 0x07, 0x01, 0x06, 0x77, 0x39, 0x69, 0xfb, 0x5e, 0x0e, 0x18, 0x1d, + 0xf8, 0x66, 0x5b, 0xe0, 0xde, 0xbc, 0x04, 0x7e, 0x7c, 0x99, 0x1b, 0xf5, 0x7d, 0xb2, 0x0b, + 0xa9, 0x89, 0x3d, 0x46, 0x16, 0xc4, 0x0a, 0x8a, 0x24, 0x99, 0xaf, 0xe1, 0x90, 0x1e, 0x61, + 0x6b, 0x34, 0xe2, 0xa2, 0x8d, 0xb7, 0xb4, 0xfa, 0x71, 0x95, 0x3f, 0xb2, 0xa2, 0x37, 0x04, + 0xb9, 0xa6, 0xce, 0xa0, 0xa6, 0x03, 0xbb, 0xdc, 0x7e, 0x8a, 0x11, 0x58, 0x02, 0x6f, 0x11, + 0xd8, 0x2b, 0x15, 0x82, 0xdd, 0x15, 0x7a, 0x56, 0x88, 0x36, 0xc3, 0xd4, 0xb3, 0x1f, 0x3a, + 0x67, 0x21, 0x46, 0x00, 0x17, 0xd1, 0x83, 0xad, 0x3d, 0xe5, 0x8d, 0x92, 0x26, 0xfa, 0x8c, + 0x50, 0xa3, 0x54, 0x93, 0x4b, 0x3a, 0x47, 0x50, 0xe9, 0x93, 0xb0, 0xd3, 0x13, 0x82, 0xd2, + 0x61, 0x09, 0xab, 0x96, 0xdd, 0xda, 0xab, 0x8d, 0x90, 0xbd, 0x72, 0x5e, 0xab, 0x7f, 0x28, + 0x8c, 0x58, 0x97, 0x56, 0xaf, 0x2c, 0xb9, 0x8d, 0x40, 0x0c, 0x09, 0x4d, 0x19, 0x15, 0xd6, + 0x0b, 0x56, 0x30, 0x49, 0x1c, 0x04, 0xec, 0x34, 0xa4, 0x11, 0xcc, 0x70, 0x2d, 0x39, 0xda, + 0x58, 0x0f, 0x25, 0x6b, 0x28, 0x19, 0xca, 0xb9, 0x29, 0x3c, 0x92, 0x95, 0x1b, 0x12, 0x23, + 0xcd, 0xdd, 0x16, 0x03, 0xac, 0xce, 0x3d, 0x29, 0x46, 0x0f, 0xba, 0x60, 0x92, 0x51, 0x68, + 0xa2, 0x4d, 0xf2, 0x27, 0x05, 0xa2, 0xde, 0xde, 0x7c, 0x79, 0xf4, 0x51, 0x7f, 0xc5, 0x5e, + 0x72, 0xc2, 0x84, 0x61, 0xb0, 0xda, 0xbe, 0x3c, 0x20, 0xc4, 0xa4, 0x7c, 0x9e, 0x2b, 0x03, + 0x1e, 0x59, 0x49, 0xdf, 0xb4, 0x3c, 0x47, 0x8e, 0x50, 0x63, 0x96, 0x38, 0x82, 0x90, 0x49, + 0xc2, 0xcd, 0x77, 0xdf, 0xfd, 0x05, 0x31, 0x9b, 0xce, 0x68, 0x97, 0x00, 0x4e, 0x62, 0xbf, + 0x05, 0x61, 0x3f, 0x27, 0x46, 0x08, 0xcd, 0x2f, 0xa8, 0x9f, 0xb6, 0x52, 0x1e, 0xa7, 0xbe, + 0x97, 0x0d, 0x2e, 0x83, 0x4e, 0x12, 0xf7, 0xaa, 0x2c, 0xdb, 0x7a, 0x75, 0x10, 0x93, 0x07, + 0xde, 0xdd, 0xab, 0x0f, 0x2a, 0x8c, 0xf6, 0xf2, 0xcc, 0x12, 0xc0, 0xf7, 0x17, 0x0c, 0x7c, + 0x51, 0x57, 0x32, 0xe0, 0x4e, 0xe1, 0xa3, 0xb1, 0x6d, 0xf8, 0x6b, 0xa6, 0x74, 0x0b, 0x18, + 0x02, 0xed, 0x37, 0x00, 0x1c, 0x67, 0x93, 0x44, 0x49, 0x60, 0x6d, 0x36, 0xfc, 0xdb, 0xab, + 0x9e, 0x7c, 0x0e, 0x9f, 0x88, 0xf9, 0xf4, 0x3f, 0xc0, 0xf4, 0xdb, 0x80, 0xbd, 0xab, 0xa3, + 0x64, 0x97, 0x5b, 0xdd, 0xbf, 0xab, 0xca, 0xdd, 0xc5, 0xa7, 0x13, 0xcf, 0x9a, 0x39, 0xd1, + 0x55, 0x13, 0xec, 0xd0, 0x03, 0x83, 0xb5, 0xf0, 0x8a, 0xe6, 0x40, 0x9d, 0x92, 0x9a, 0x0d, + 0x41, 0x5c, 0xf3, 0x7b, 0x29, 0x9c, 0xa4, 0xea, 0x86, 0xce, 0xcf, 0x0e, 0x43, 0x13, 0xd6, + 0x27, 0x58, 0xee, 0x10, 0x10, 0x57, 0xd9, 0x3f, 0xcc, 0xfa, 0xfc, 0x34, 0xbb, 0x2b, 0xb9, + 0x3b, 0x93, 0xa3, 0xed, 0x90, 0x06, 0xdb, 0x95, 0x21, 0x8e, 0x69, 0x3c, 0xf3, 0xaa, 0xcf, + 0x7b, 0x5f, 0x02, 0x5a, 0x89, 0xbc, 0x9f, 0xbd, 0x9c, 0x65, 0x11, 0x67, 0x0b, 0x04, 0x88, + 0x69, 0xf1, 0x43, 0x4f, 0xa1, 0x5f, 0xdc, 0x75, 0xbc, 0xf7, 0xe0, 0xf2, 0x14, 0xfc, 0xe7, + 0x8f, 0x8e, 0x97, 0x80, 0x2a, 0x24, 0xb9, 0xbb, 0xb8, 0x34, 0x00, 0x60, 0xfe, 0xfa, 0x84, + 0xe8, 0xa4, 0x9e, 0xa0, 0x3c, 0xba, 0x75, 0xb4, 0x17, 0xb2, 0xc3, 0xcd, 0xed, 0x28, 0x15, + 0x00, 0x68, 0x13, 0x6d, 0xf1, 0x83, 0x3c, 0x72, 0x47, 0xdf, 0x93, 0x84, 0x82, 0xc8, 0x84, + 0x34, 0x1b, 0xab, 0x45, 0xf7, 0x4d, 0x25, 0x4e, 0xb4, 0xe0, 0x97, 0xe7, 0x5a, 0xc4, 0x39, + 0xd3, 0x15, 0x6e, 0xb1, 0xd7, 0x43, 0xad, 0x27, 0x15, 0x00, 0xbf, 0x54, 0x46, 0x5b, 0x84, + 0x92, 0xa8, 0xfc, 0xa2, 0x10, 0x52, 0x5a, 0xcb, 0x82, 0x41, 0xe8, 0xe2, 0xe6, 0xd8, 0x36, + 0xae, 0x43, 0x49, 0xbc, 0xf3, 0x18, 0x57, 0xa4, 0xba, 0xd3, 0x1b, 0x05, 0xa3, 0x1e, 0x78, + 0x43, 0x9c, 0xec, 0x18, 0x2d, 0x92, 0x9a, 0x87, 0x33, 0xfc, 0x25, 0x2e, 0xd1, 0x0b, 0xa6, + 0xc6, 0x86, 0x6d, 0xc0, 0x27, 0x32, 0x80, 0x79, 0xb8, 0x5e, 0x2c, 0x4f, 0x2d, 0x74, 0x16, + 0x70, 0x36, 0x8e, 0xa0, 0x8b, 0xf0, 0x67, 0x6c, 0x4a, 0x6e, 0xeb, 0xc6, 0xb7, 0x56, 0xc6, + 0x55, 0x91, 0x1f, 0xf4, 0x5a, 0x2a, 0x53, 0xb0, 0x65, 0x35, 0xc0, 0xe4, 0x47, 0xb8, 0x1f, + 0x77, 0xab, 0x87, 0xaf, 0x4f, 0xee, 0xa5, 0xec, 0x41, 0xc1, 0xa1, 0xfe, 0x4f, 0xeb, 0xb2, + 0x4b, 0x96, 0xc6, 0x12, 0x94, 0x93, 0x0a, 0x00, 0x17, 0xf1, 0xbc, 0xe1, 0x78, 0x67, 0x66, + 0xb2, 0x03, 0x3d, 0xa7, 0xff, 0xe1, 0x1d, 0x39, 0xac, 0xb9, 0xa6, 0x6c, 0x2a, 0x76, 0x37, + 0xfd, 0xcd, 0x48, 0x42, 0x39, 0x72, 0x56, 0xe6, 0x67, 0x1e, 0x20, 0xf9, 0xdd, 0x2e, 0xa9, + 0xf0, 0xac, 0xc2, 0x38, 0x88, 0xea, 0xd3, 0x63, 0x66, 0x02, 0xe3, 0x9f, 0xe5, 0xae, 0x95, + 0x98, 0x7d, 0x4f, 0xb9, 0xd4, 0x7c, 0x77, 0xc1, 0xf4, 0x55, 0xc3, 0xe0, 0x89, 0xbf, 0x0c, + 0xf4, 0x02, 0xef, 0xd5, 0xb9, 0x17, 0x6e, 0x13, 0xa8, 0xee, 0x99, 0xa5, 0x27, 0xcd, 0xc6, + 0xbd, 0x6a, 0x14, 0x7f, 0x40, 0xaf, 0xbf, 0x1e, 0x65, 0x28, 0xb7, 0xab, 0x82, 0x4a, 0x91, + 0xf3, 0x26, 0xc3, 0x1d, 0x23, 0x28, 0x7b, 0x27, 0x6f, 0xc6, 0x5c, 0x1b, 0x68, 0xc1, 0xc5, + 0x39, 0x7c, 0x49, 0x93, 0x7d, 0x28, 0x13, 0xe1, 0xf9, 0x46, 0x5d, 0x44, 0xb4, 0x4e, 0x47, + 0x92, 0x11, 0x26, 0xe7, 0xc1, 0x50, 0x70, 0x18, 0xe7, 0x35, 0x76, 0x6a, 0x63, 0x75, 0xb2, + 0xe7, 0xd0, 0x2e, 0xeb, 0xa7, 0xab, 0x05, 0xc0, 0x76, 0xf0, 0xb3, 0x04, 0xde, 0xf5, 0xb4, + 0x86, 0x93, 0x90, 0x0c, 0x6c, 0x63, 0x03, 0xfa, 0x99, 0x6e, 0x1f, 0x0c, 0xbc, 0x47, 0x1f, + 0x9a, 0x9b, 0x11, 0xe1, 0x73, 0x1f, 0x89, 0x20, 0x4a, 0x1d, 0x76, 0x43, 0x3c, 0x8d, 0x4c, + 0x64, 0x93, 0xfd, 0x3d, 0x09, 0x2f, 0xcf, 0x85, 0x11, 0xef, 0x9f, 0x5a, 0x30, 0x2d, 0x77, + 0x5c, 0xef, 0xd1, 0xb0, 0xb9, 0x20, 0xb3, 0xf7, 0x03, 0x29, 0xb1, 0x6b, 0x48, 0x59, 0x68, + 0x0a, 0x96, 0xae, 0x17, 0x87, 0x14, 0xe3, 0x56, 0x3e, 0x8e, 0xcd, 0xa7, 0x81, 0x70, 0xc0, + 0x31, 0xc9, 0xf7, 0x58, 0x99, 0xa2, 0x0a, 0xd3, 0xa3, 0x8d, 0xec, 0xcf, 0xe3, 0x63, 0xf8, + 0xc6, 0x50, 0xb3, 0xf2, 0x06, 0xc4, 0x12, 0x3c, 0x20, 0xf7, 0xeb, 0xc3, 0xbf, 0xc8, 0xca, + 0x70, 0x3a, 0x13, 0x5a, 0x66, 0xf4, 0x21, 0x67, 0xc3, 0x65, 0x5d, 0xaa, 0x7a, 0xa1, 0x66, + 0xac, 0x07, 0x3a, 0x4c, 0x75, 0x8b, 0x32, 0x54, 0x69, 0xf2, 0x5e, 0x8a, 0xaf, 0x04, 0x95, + 0x38, 0xc7, 0x4e, 0x5f, 0x1a, 0xc0, 0xf6, 0x93, 0xe4, 0x58, 0x48, 0xa8, 0x14, 0xd5, 0x6e, + 0x5d, 0x09, 0x6d, 0xe9, 0x23, 0x94, 0xf3, 0xa0, 0x6f, 0xb1, 0xff, 0x3d, 0x88, 0x47, 0x54, + 0xe6, 0x52, 0x89, 0xa0, 0x9a, 0x5f, 0x03, 0x8f, 0xd6, 0xfa, 0x47, 0x43, 0x34, 0x85, 0xad, + 0xa7, 0x61, 0x09, 0x38, 0x27, 0x89, 0x70, 0xbe, 0x14, 0x7a, 0x87, 0x0f, 0xe1, 0xcb, 0x67, + 0x01, 0x97, 0x6d, 0x4d, 0x2d, 0x78, 0xff, 0x07, 0x32, 0xfd, 0xab, 0x98, 0x12, 0x96, 0x54, + 0xda, 0xcb, 0xda, 0xfd, 0xc3, 0xb9, 0x65, 0x18, 0x86, 0x2b, 0x05, 0xe1, 0x8e, 0xb3, 0x7b, + 0xa8, 0xe2, 0x5f, 0xc3, 0x83, 0x5c, 0x41, 0xe7, 0x50, 0xd0, 0x11, 0x83, 0x5f, 0x25, 0xf9, + 0x5b, 0xe4, 0x4f, 0x22, 0xa4, 0x82, 0x48, 0x10, 0x7c, 0xbb, 0x9a, 0x9f, 0x74, 0x87, 0x07, + 0x83, 0x71, 0x55, 0x4e, 0x5a, 0x4a, 0xb5, 0x2d, 0x08, 0x41, 0x3f, 0x31, 0x2c, 0x45, 0x79, + 0x07, 0xa1, 0x5f, 0x73, 0xbe, 0xb1, 0x19, 0x64, 0x3d, 0x8f, 0x0b, 0x1a, 0xfe, 0xdf, 0xaf, + 0x70, 0x55, 0x24, 0xfe, 0x2b, 0x76, 0x1f, 0x62, 0x88, 0xb0, 0x90, 0xfa, 0xf2, 0xc6, 0x07, + 0xa4, 0xe7, 0xee, 0x3a, 0xba, 0x2a, 0xd0, 0xa9, 0x4e, 0xca, 0xcd, 0x24, 0x43, 0x12, 0x0c, + 0x01, 0xb0, 0x75, 0x13, 0x28, 0xf5, 0xcc, 0x57, 0xb8, 0x17, 0xbf, 0xc7, 0xff, 0x26, 0x9a, + 0x88, 0x0f, 0xfb, 0x59, 0x72, 0x1a, 0x19, 0x60, 0x6e, 0x79, 0x13, 0x12, 0xc4, 0x27, 0xdf, + 0xaa, 0xae, 0x47, 0x11, 0xf1, 0x74, 0xd2, 0x97, 0xe5, 0x9b, 0x3c, 0xa4, 0x86, 0xdd, 0x53, + 0xec, 0xfd, 0x91, 0x1b, 0x3a, 0xd7, 0x7c, 0xd8, 0x93, 0xcc, 0xa0, 0xf9, 0x81, 0x8a, 0xcc, + 0x91, 0x74, 0xb6, 0x5e, 0x49, 0x83, 0x81, 0xb6, 0x45, 0xeb, 0x85, 0xe5, 0x54, 0xe6, 0xe1, + 0x4c, 0x03, 0x2e, 0xa5, 0xf2, 0x19, 0xa9, 0xb6, 0x97, 0xcf, 0xd3, 0x77, 0xca, 0x89, 0x10, + 0xc5, 0x71, 0x61, 0x32, 0x57, 0xc7, 0x48, 0x3c, 0xfb, 0x06, 0x66, 0xf3, 0x5c, 0x82, 0x43, + 0xf5, 0x4c, 0xc3, 0x9c, 0xb7, 0xa4, 0x32, 0x16, 0x4f, 0xe2, 0xf2, 0x33, 0xb1, 0xe0, 0xd8, + 0x6b, 0xce, 0x27, 0xfd, 0xce, 0x77, 0xd5, 0x10, 0xc2, 0xc5, 0x3c, 0x43, 0x40, 0xbe, 0xa5, + 0x1c, 0x66, 0x45, 0xa6, 0x9a, 0xd1, 0xac, 0x34, 0xcc, 0x08, 0xa6, 0xc7, 0x9a, 0xb1, 0xbe, + 0xbc, 0xe1, 0x59, 0xef, 0xaf, 0x2c, 0xa7, 0x84, 0x88, 0x47, 0x39, 0xfd, 0x3c, 0x76, 0x6e, + 0x95, 0xdb, 0x17, 0x99, 0x75, 0x0f, 0x5f, 0xad, 0x9b, 0xe2, 0x68, 0x3f, 0x0c, 0x66, 0xbe, + 0xbd, 0x2e, 0xb3, 0xbb, 0xfd, 0xca, 0xeb, 0xb2, 0x7c, 0xe5, 0x11, 0x3f, 0x5b, 0xb6, 0x60, + 0x99, 0x32, 0x3c, 0x2f, 0xe5, 0x77, 0xe6, 0xee, 0x73, 0x04, 0x2d, 0xf6, 0x9b, 0x26, 0x62, + 0x6c, 0x13, 0x9d, 0x3f, 0x1d, 0x7b, 0x91, 0x68, 0x0d, 0xb1, 0xc6, 0x0c, 0x2d, 0x32, 0x77, + 0xa7, 0x0c, 0xee, 0x9a, 0x7e, 0x15, 0x6f, 0x0f, 0x5a, 0x0e, 0x48, 0x74, 0x27, 0x34, 0xfe, + 0x39, 0xb6, 0x46, 0x0d, 0x93, 0x79, 0x23, 0x4a, 0x03, 0x78, 0x02, 0x89, 0xf3, 0xb8, 0xa8, + 0xf2, 0xef, 0x8e, 0x03, 0x73, 0x76, 0x5d, 0x37, 0xdf, 0x94, 0x50, 0x9b, 0x43, 0xf2, 0x4c, + 0x66, 0x79, 0x29, 0xeb, 0x58, 0xed, 0x90, 0xca, 0xc5, 0xf9, 0x5a, 0x69, 0xb7, 0x4d, 0x69, + 0x38, 0x22, 0x46, 0x46, 0x32, 0x31, 0xc8, 0x3d, 0xb1, 0x8e, 0x57, 0xbd, 0xba, 0x72, 0x8f, + 0x1a, 0xc9, 0x01, 0xe5, 0x17, 0x3d, 0x36, 0x74, 0xfa, 0x74, 0xa6, 0x78, 0x72, 0x95, 0xc1, + 0xe6, 0x7c, 0x0b, 0x93, 0xc0, 0x1b, 0x7a, 0xad, 0xd7, 0x3d, 0x04, 0xda, 0xde, 0xc4, 0x12, + 0x77, 0xac, 0xfc, 0xfd, 0x1f, 0x10, 0x16, 0x57, 0xcc, 0x53, 0xa7, 0xcd, 0x7b, 0x70, 0x67, + 0x16, 0x0f, 0x70, 0x26, 0x0e, 0x51, 0x2d, 0x40, 0x23, 0xf1, 0x95, 0x8c, 0xb8, 0xaa, 0x6f, + 0xec, 0x26, 0xd5, 0x06, 0x83, 0x02, 0x27, 0xb7, 0x3a, 0x20, 0x27, 0xd1, 0x32, 0xe3, 0xc1, + 0xfa, 0xf8, 0x29, 0x31, 0x06, 0x64, 0xfa, 0xc9, 0x02, 0xf4, 0x1c, 0x6a, 0x8f, 0x59, 0x0c, + 0xc0, 0x1c, 0x47, 0x0f, 0x46, 0x42, 0xdf, 0x79, 0x87, 0x4a, 0x06, 0x29, 0x08, 0xad, 0xce, + 0x43, 0xb1, 0x65, 0xb5, 0x0d, 0xe3, 0x20, 0x66, 0x53, 0x6e, 0x06, 0x81, 0xb7, 0x45, 0x12, + 0xd6, 0x27, 0x7a, 0x7d, 0x63, 0xd6, 0xf6, 0x8c, 0x86, 0xf6, 0xbe, 0x76, 0x0b, 0x01, 0xb3, + 0x68, 0x2a, 0x98, 0x50, 0xdb, 0xd9, 0xa8, 0xbb, 0xe4, 0x9c, 0xf8, 0x60, 0xe4, 0x7a, 0x07, + 0x16, 0xb8, 0x6d, 0xca, 0x61, 0x0c, 0x8b, 0x81, 0x51, 0xc7, 0x57, 0x24, 0xd3, 0x78, 0x04, + 0x23, 0x00, 0x96, 0x30, 0x20, 0xf8, 0x6c, 0x97, 0x57, 0xbf, 0x59, 0xc8, 0x16, 0xad, 0x66, + 0xea, 0xfa, 0xde, 0xc6, 0x0c, 0xe5, 0x82, 0xa3, 0xf1, 0x23, 0x23, 0x77, 0x77, 0xb0, 0x9c, + 0x7f, 0x39, 0xa9, 0x54, 0x55, 0x76, 0x56, 0xc8, 0x0f, 0x13, 0x36, 0x5f, 0xb6, 0x67, 0x16, + 0x4a, 0x1f, 0x6d, 0x9d, 0xc2, 0xd7, 0x43, 0x4e, 0xe7, 0xd7, 0x8a, 0x49, 0xd8, 0xee, 0x2d, + 0xac, 0x67, 0xd6, 0x1f, 0xe2, 0x42, 0xaa, 0x4a, 0x24, 0x64, 0x52, 0x24, 0xbf, 0x10, 0xe8, + 0x2f, 0x0e, 0xcb, 0x03, 0x19, 0x6c, 0x68, 0xb0, 0x57, 0xf2, 0x01, 0xbc, 0x3d, 0x66, 0x30, + 0x26, 0xd2, 0x7e, 0xcb, 0xcb, 0x21, 0xd1, 0x81, 0xb9, 0xb7, 0x92, 0xab, 0xe6, 0x4e, 0x47, + 0x33, 0x44, 0x2f, 0xed, 0x9e, 0x10, 0xd4, 0x7b, 0x55, 0xf6, 0xac, 0xa6, 0x23, 0xa7, 0xdb, + 0x0a, 0x28, 0x31, 0xbf, 0x73, 0xba, 0xe8, 0x0b, 0x86, 0x66, 0x3b, 0x85, 0x64, 0xd0, 0xd6, + 0x46, 0xd6, 0xe5, 0x4a, 0x77, 0xbc, 0xf1, 0xdd, 0xd2, 0x99, 0xad, 0x5f, 0x76, 0xf0, 0x57, + 0xf3, 0xa1, 0x93, 0xdb, 0x5e, 0x51, 0x14, 0x1e, 0x28, 0x26, 0x17, 0x5d, 0x37, 0xd9, 0xb2, + 0xef, 0x03, 0x72, 0x4c, 0xf3, 0x15, 0x3a, 0xf8, 0x9d, 0xf5, 0x09, 0xac, 0xb3, 0x31, 0x30, + 0x25, 0x15, 0x60, 0xeb, 0x5f, 0xcc, 0x7b, 0x48, 0x41, 0x4f, 0x65, 0x0e, 0x09, 0xd5, 0x23, + 0x7e, 0x2e, 0x68, 0x4f, 0x46, 0x76, 0x6f, 0x76, 0x1a, 0x76, 0x72, 0xbb, 0xa9, 0x31, 0x39, + 0x62, 0x54, 0x90, 0x1f, 0x3b, 0x62, 0xa5, 0xfb, 0x78, 0x05, 0xf3, 0x8f, 0x60, 0x0c, 0xc9, + 0x37, 0x3e, 0xad, 0xc1, 0x80, 0xaa, 0x78, 0x40, 0x8e, 0x68, 0xbb, 0x1d, 0x3d, 0x6e, 0x20, + 0xdc, 0x60, 0x45, 0x6f, 0x71, 0xa6, 0x8d, 0x79, 0x05, 0x96, 0xe6, 0x99, 0x4e, 0x82, 0x74, + 0x23, 0x78, 0xb4, 0xd9, 0xd2, 0x98, 0x4c, 0x9b, 0x75, 0x8f, 0x35, 0x64, 0x12, 0xda, 0x4d, + 0xb0, 0x94, 0x42, 0xb3, 0x8f, 0x1a, 0x03, 0xce, 0xd0, 0x3f, 0x69, 0xf4, 0xbb, 0x03, 0x3e, + 0xac, 0x32, 0x1f, 0x0c, 0x65, 0x2c, 0x81, 0x7b, 0xc0, 0x5b, 0xf2, 0xe7, 0xc8, 0xfa, 0xf2, + 0x96, 0x1c, 0x74, 0xc4, 0xbb, 0x5b, 0x88, 0xd9, 0x29, 0x26, 0xdf, 0xbe, 0xcb, 0x2e, 0x11, + 0xa2, 0xeb, 0x17, 0x67, 0x3f, 0x91, 0x90, 0x08, 0x73, 0x87, 0x1f, 0x49, 0xff, 0x92, 0xed, + 0xfd, 0x19, 0x4f, 0x28, 0xe6, 0x1c, 0xca, 0xb4, 0xbf, 0x8c, 0xee, 0x9d, 0xa6, 0xf0, 0xd8, + 0x48, 0xdd, 0xac, 0xec, 0xc2, 0x08, 0x3c, 0x8f, 0x56, 0x2c, 0x15, 0xf5, 0xee, 0xce, 0x67, + 0x13, 0x11, 0xcf, 0xf2, 0xf7, 0x0c, 0xd0, 0xa7, 0x7e, 0x93, 0x4d, 0xa0, 0x6f, 0xdc, 0x5c, + 0xb6, 0x10, 0x13, 0x11, 0xa3, 0x0e, 0x82, 0xf5, 0x35, 0x41, 0xc4, 0xdb, 0x56, 0x80, 0x6f, + 0x5b, 0xfa, 0xdd, 0x8c, 0x04, 0xa9, 0x07, 0x19, 0xc2, 0x2d, 0x24, 0xde, 0x14, 0x7d, 0xe3, + 0x3e, 0x5d, 0x9f, 0x9f, 0x2a, 0x4c, 0x9b, 0xe8, 0xdc, 0x93, 0x00, 0x13, 0x90, 0x3d, 0x41, + 0xd5, 0x3c, 0x5d, 0x6f, 0x9a, 0xda, 0xc6, 0x6e, 0xb7, 0xee, 0x9d, 0x92, 0x30, 0xfe, 0xe1, + 0xbb, 0xe9, 0x93, 0x7d, 0x9c, 0x03, 0xd6, 0x13, 0x2b, 0x37, 0x97, 0xd6, 0x35, 0x3f, 0x09, + 0x57, 0xe1, 0xe6, 0xb2, 0x9b, 0x95, 0x8d, 0x2b, 0x84, 0xc5, 0x34, 0x91, 0xb0, 0x13, 0xed, + 0x53, 0x1a, 0x84, 0x3e, 0x00, 0x30, 0x92, 0x38, 0x07, 0xfe, 0x3d, 0x18, 0x80, 0x16, 0x09, + 0x04, 0xe1, 0x16, 0x8f, 0x77, 0xf8, 0x7c, 0x0a, 0xe3, 0x95, 0x49, 0xbf, 0xb1, 0xf4, 0x60, + 0x60, 0x9b, 0xa4, 0x46, 0x4c, 0x3e, 0xf2, 0xcd, 0x19, 0x2c, 0x9c, 0xe9, 0xf5, 0xbb, 0xca, + 0x14, 0x3d, 0xa5, 0x9f, 0x18, 0xce, 0x11, 0x7a, 0x10, 0xd0, 0xd8, 0xcb, 0x88, 0x12, 0x7c, + 0x61, 0xf8, 0x3e, 0x79, 0x81, 0xb6, 0xd9, 0xc0, 0x37, 0x26, 0xc7, 0xde, 0x71, 0xa2, 0x8f, + 0x2f, 0x07, 0xa7, 0x31, 0x8b, 0x69, 0xd5, 0x45, 0x77, 0xc8, 0x58, 0xc2, 0x08, 0x98, 0x6c, + 0x6b, 0x99, 0x1f, 0xeb, 0x87, 0x34, 0xd7, 0xdb, 0x4f, 0x2f, 0x19, 0x6a, 0x48, 0xcd, 0x9c, + 0x09, 0xb5, 0x27, 0x38, 0xab, 0x0c, 0x83, 0xdd, 0xea, 0x2e, 0xd7, 0xdd, 0x4d, 0x36, 0x01, + 0xc4, 0x64, 0xef, 0xd5, 0x52, 0x5e, 0x7a, 0xb7, 0x98, 0x6c, 0xc9, 0xbb, 0xb7, 0x4d, 0xc9, + 0x61, 0x0c, 0xa8, 0xe1, 0x52, 0xec, 0xc8, 0x0f, 0x69, 0x14, 0xb0, 0x9e, 0x19, 0x2d, 0xa7, + 0x6b, 0x8a, 0x80, 0x1d, 0xb0, 0x3f, 0x1e, 0x5c, 0xde, 0x8a, 0xb7, 0x8b, 0x24, 0xa0, 0x07, + 0xf4, 0x96, 0x74, 0x25, 0xfa, 0x27, 0x14, 0x2f, 0x9a, 0x20, 0x78, 0x41, 0xd7, 0x8c, 0x54, + 0xfb, 0xdd, 0x5f, 0xd9, 0x31, 0x51, 0x8d, 0x70, 0xba, 0xe4, 0x6c, 0x84, 0x49, 0x89, 0xa0, + 0xfc, 0x99, 0x2a, 0xb5, 0x37, 0x7b, 0x3b, 0x01, 0x3a, 0x21, 0xa0, 0x21, 0x40, 0xbf, 0x0c, + 0x96, 0xb9, 0xac, 0xdb, 0x8a, 0x68, 0x6b, 0x83, 0xad, 0x03, 0xf8, 0xde, 0xe8, 0x60, 0xcf, + 0xdf, 0xd7, 0x25, 0x8c, 0xe9, 0xf3, 0xe8, 0xac, 0x7b, 0x7f, 0xaf, 0xdc, 0x3f, 0x11, 0x5a, + 0xf9, 0x9f, 0xeb, 0x5a, 0x4c, 0x27, 0x17, 0x97, 0x51, 0x2b, 0x3a, 0x16, 0x4a, 0x57, 0x3a, + 0x44, 0xe9, 0x9f, 0x12, 0x52, 0x01, 0xa4, 0x77, 0x39, 0x77, 0x1b, 0xb7, 0x8e, 0xfd, 0xff, + 0x3b, 0xcb, 0xa4, 0x8d, 0xe2, 0xe0, 0xc0, 0xea, 0x9f, 0x86, 0x2b, 0xe2, 0x37, 0xfd, 0x7d, + 0x72, 0x19, 0xf3, 0xbb, 0xa3, 0x48, 0xc9, 0x8a, 0xd5, 0x4b, 0xfe, 0x4c, 0xb5, 0xd3, 0xc9, + 0x04, 0x62, 0x24, 0xf4, 0x05, 0x23, 0xc6, 0x9d, 0x68, 0x42, 0x10, 0x50, 0x71, 0xcd, 0xc0, + 0xec, 0x3b, 0xb6, 0xbc, 0xb5, 0xac, 0x80, 0xa4, 0xc1, 0x7e, 0x15, 0x65, 0xa6, 0x6e, 0x6d, + 0xdf, 0x70, 0x0f, 0xf1, 0x33, 0x17, 0x91, 0x24, 0x98, 0x27, 0xaa, 0xf0, 0xe4, 0x55, 0xab, + 0xb6, 0x63, 0xed, 0x7d, 0x69, 0x80, 0x9b, 0xdd, 0x0a, 0x5c, 0xfa, 0x4a, 0x9c, 0x12, 0x8b, + 0x5f, 0xb1, 0x87, 0x44, 0x5a, 0xc0, 0x21, 0x0f, 0x70, 0x65, 0xa1, 0x43, 0x36, 0x97, 0xd9, + 0xb7, 0x0d, 0x73, 0xa7, 0x41, 0x6d, 0x1b, 0x0a, 0x81, 0x5d, 0x6b, 0x69, 0x2a, 0x28, 0x17, + 0x19, 0x44, 0x8e, 0x9b, 0xd8, 0xc2, 0x00, 0x55, 0x20, 0x2e, 0xfc, 0x84, 0xb5, 0xba, 0x8a, + 0x2f, 0x79, 0x3e, 0xd0, 0x34, 0xf5, 0xf3, 0x3f, 0x5b, 0x12, 0x11, 0x62, 0x79, 0x23, 0x22, + 0xa4, 0x42, 0x75, 0x6d, 0xde, 0x84, 0x88, 0x32, 0x2a, 0xce, 0x0d, 0xe6, 0x40, 0xb6, 0x5e, + 0x2d, 0x9c, 0x97, 0x08, 0xf9, 0xfc, 0x3e, 0x3b, 0x02, 0x0e, 0x95, 0x49, 0xf0, 0x73, 0x1c, + 0x73, 0xeb, 0xaf, 0x0a, 0x2e, 0xaf, 0x32, 0x14, 0x58, 0xd3, 0xb3, 0x37, 0x08, 0x4a, 0xef, + 0x53, 0x31, 0x6e, 0x65, 0xa6, 0xe4, 0x40, 0x9d, 0x0a, 0x45, 0x36, 0xdf, 0xb5, 0xdc, 0xbc, + 0x43, 0x33, 0x66, 0x64, 0x11, 0x4d, 0x94, 0x61, 0xa3, 0x6b, 0x36, 0x3f, 0xc2, 0x3b, 0x01, + 0xe8, 0x35, 0xde, 0xa6, 0x50, 0x68, 0x8d, 0xdb, 0x75, 0x54, 0xd9, 0xc3, 0x74, 0xb9, 0x56, + 0x96, 0xd3, 0x73, 0x27, 0x5e, 0xf4, 0xb5, 0xe5, 0x9f, 0xfb, 0x3c, 0xf9, 0xdd, 0x0c, 0xa8, + 0x7a, 0x27, 0xfb, 0x46, 0x1f, 0x46, 0x6f, 0x47, 0xec, 0x88, 0xe5, 0x85, 0x48, 0xbf, 0xd5, + 0x57, 0xa0, 0xe3, 0xad, 0x7e, 0x4a, 0xb5, 0xdc, 0x13, 0x55, 0x7e, 0xd1, 0xf1, 0x83, 0x54, + 0x42, 0x47, 0xee, 0xad, 0x0f, 0xa8, 0x91, 0x8c, 0x1d, 0xcc, 0xc6, 0x9e, 0xf6, 0x93, 0x9f, + 0x8f, 0xde, 0x89, 0x3b, 0x26, 0x5c, 0x24, 0x81, 0xb6, 0xdd, 0x9f, 0x67, 0xb2, 0x05, 0xf4, + 0xf0, 0x1d, 0x84, 0x06, 0xb4, 0x3f, 0x88, 0xf9, 0xe6, 0x1e, 0xe4, 0xc6, 0x10, 0x8e, 0x9f, + 0x99, 0x92, 0x6a, 0xaa, 0x25, 0x0b, 0x19, 0xd3, 0xa4, 0xa2, 0x48, 0xe6, 0x0b, 0x8e, 0x52, + 0x3b, 0x6d, 0x6d, 0xcd, 0x69, 0xa5, 0x04, 0x09, 0xfd, 0xd0, 0xe2, 0xb4, 0x74, 0x63, 0x22, + 0xeb, 0x3c, 0x81, 0x56, 0x4f, 0xd5, 0xd1, 0xb5, 0x63, 0x1a, 0xa4, 0xeb, 0x0f, 0xe8, 0xbc, + 0x48, 0x9f, 0x0a, 0x66, 0x56, 0xdb, 0x32, 0xe9, 0x5b, 0x23, 0xc4, 0x55, 0x46, 0x37, 0xee, + 0x71, 0x93, 0xd4, 0x52, 0x83, 0xdc, 0xc2, 0x79, 0x61, 0xa8, 0xf5, 0xb1, 0x3c, 0x10, 0xd5, + 0xff, 0x62, 0x99, 0x43, 0x6d, 0xe2, 0x86, 0xad, 0x5e, 0x7e, 0xc0, 0x06, 0x03, 0x6b, 0xf5, + 0x5a, 0x1f, 0x6b, 0x44, 0x4d, 0x95, 0xd9, 0x24, 0x92, 0x19, 0x5d, 0x79, 0x73, 0x8d, 0x84, + 0x13, 0x09, 0xaa, 0x72, 0x7c, 0x38, 0x7d, 0x7c, 0xd2, 0xd7, 0xe2, 0x49, 0xc3, 0x09, 0x0f, + 0xf3, 0xc7, 0x46, 0xa7, 0x01, 0x50, 0x61, 0x28, 0xfc, 0x22, 0xda, 0x15, 0xa2, 0xd3, 0xe6, + 0xa9, 0xc7, 0xad, 0x0a, 0x6b, 0xb8, 0x4d, 0x7d, 0x5b, 0x28, 0x3f, 0xdb, 0xa1, 0xb8, 0x07, + 0x3f, 0x54, 0xd1, 0x4a, 0x1c, 0x29, 0xcf, 0xc6, 0xea, 0x0b, 0x20, 0x78, 0x14, 0xe8, 0xbf, + 0x40, 0x09, 0x93, 0x20, 0x39, 0x0e, 0xe1, 0x45, 0x92, 0xc9, 0xcb, 0xe9, 0xdd, 0x50, 0xbb, + 0x6f, 0xc1, 0x3c, 0xa6, 0xb8, 0xf4, 0x83, 0x4f, 0xa9, 0xfc, 0xd3, 0x8c, 0x99, 0x07, 0x1f, + 0xd4, 0xc5, 0x52, 0xd3, 0x80, 0x3e, 0xcb, 0x59, 0x6b, 0xf4, 0xec, 0xc1, 0x46, 0x24, 0xed, + 0x97, 0x0e, 0x16, 0x39, 0x1c, 0x2e, 0xfd, 0x64, 0x72, 0xa5, 0xc5, 0xb3, 0x2f, 0xda, 0xc4, + 0x62, 0x66, 0xb4, 0x3a, 0xb6, 0xc0, 0x72, 0x73, 0xd2, 0xe2, 0x18, 0x52, 0x8b, 0x22, 0x1b, + 0x21, 0x69, 0x3b, 0x30, 0x54, 0xfb, 0xbb, 0xc5, 0x5c, 0x5e, 0x97, 0x5f, 0x25, 0xb8, 0xd5, + 0x2f, 0x4e, 0x78, 0x4a, 0xf8, 0x2f, 0xe2, 0x20, 0xa6, 0xfe, 0x77, 0xc8, 0x25, 0x08, 0xb4, + 0x6d, 0xea, 0x66, 0xa2, 0xcc, 0x81, 0x82, 0x8b, 0x0d, 0xcd, 0x7f, 0x86, 0x91, 0x91, 0xc1, + 0xbb, 0x53, 0x35, 0xb0, 0xff, 0xfb, 0x8b, 0xb3, 0xf2, 0xbd, 0x16, 0xdb, 0xbf, 0x11, 0xc0, + 0x48, 0x84, 0xe8, 0xf7, 0xfb, 0xb4, 0x7f, 0xc2, 0xaa, 0x17, 0x06, 0xa4, 0x70, 0xdd, 0xc6, + 0x77, 0xb3, 0xd7, 0x56, 0x21, 0xf3, 0xd9, 0x2a, 0x62, 0x81, 0x24, 0x11, 0x71, 0xff, 0xff, + 0x25, 0x3f, 0xc9, 0x25, 0x52, 0x63, 0x89, 0xbb, 0x17, 0x66, 0x66, 0x24, 0x29, 0x01, 0xd6, + 0x11, 0x8c, 0x10, 0xc6, 0xba, 0xf8, 0xa8, 0xe3, 0xcd, 0x44, 0x5d, 0xfd, 0xa1, 0xc0, 0xd8, + 0x6a, 0x60, 0xc0, 0x2a, 0xd8, 0xd9, 0xad, 0xf0, 0x46, 0x9e, 0x42, 0xe6, 0x8c, 0x5e, 0x04, + 0x27, 0x8a, 0xd7, 0xf5, 0xb7, 0x70, 0x80, 0x37, 0xc0, 0x6d, 0x6c, 0xd0, 0x0f, 0x8a, 0xc4, + 0xf8, 0x76, 0xfc, 0x02, 0x97, 0xf2, 0xac, 0x3f, 0x07, 0x41, 0xd5, 0xea, 0x38, 0xe9, 0xad, + 0x0e, 0x14, 0x85, 0xfc, 0xd3, 0x6b, 0x10, 0x65, 0xd4, 0x12, 0x35, 0x6d, 0xa5, 0x47, 0x60, + 0xe9, 0x2d, 0x02, 0x33, 0xa9, 0x7b, 0x81, 0x2e, 0x87, 0x8c, 0x23, 0x98, 0x67, 0x2c, 0x59, + 0x0d, 0x68, 0x9d, 0x03, 0x13, 0xd7, 0x4d, 0x34, 0xcf, 0xb9, 0xb3, 0x34, 0xa5, 0xb8, 0xce, + 0xf3, 0xce, 0x4c, 0x46, 0xb5, 0x74, 0x2a, 0x29, 0xa6, 0x78, 0x10, 0x29, 0xec, 0xe7, 0x62, + 0xcd, 0xf0, 0xb8, 0x7b, 0x30, 0xa0, 0xb4, 0x07, 0x5a, 0x37, 0x19, 0x91, 0x5a, 0x1e, 0xc4, + 0x9f, 0x44, 0xf0, 0x5c, 0x25, 0xde, 0x2a, 0xce, 0xe6, 0x1a, 0x4b, 0x89, 0xa3, 0x42, 0xa1, + 0x9a, 0x0b, 0x85, 0xf8, 0x4a, 0x59, 0x0e, 0x1e, 0x50, 0xa3, 0x77, 0xe8, 0x06, 0xce, 0x76, + 0xb0, 0x6d, 0x17, 0x3a, 0xe3, 0x1a, 0xf9, 0xb8, 0x8c, 0xcd, 0x44, 0x52, 0x5e, 0x6c, 0x58, + 0x7f, 0xad, 0x7b, 0x3a, 0x2c, 0xce, 0x5d, 0x9e, 0xed, 0x31, 0xf8, 0x7b, 0x0f, 0x2b, 0x1e, + 0xf0, 0x8e, 0xa4, 0x33, 0xa6, 0xc5, 0x83, 0xba, 0xdc, 0xd9, 0x44, 0x4e, 0x4a, 0x94, 0x63, + 0xb2, 0x33, 0x9e, 0xcd, 0x59, 0x8e, 0x13, 0xd0, 0xb6, 0x22, 0x5e, 0xa3, 0x4e, 0x9c, 0x09, + 0x2e, 0x6f, 0xc8, 0x66, 0x8b, 0xd4, 0x82, 0x63, 0x8f, 0x9b, 0xe8, 0x28, 0x98, 0x4d, 0xea, + 0xc4, 0xeb, 0x8e, 0xc5, 0x08, 0x2a, 0x9f, 0x0f, 0x15, 0x17, 0x6b, 0x6f, 0xe0, 0x84, 0x08, + 0x77, 0xe9, 0x51, 0xa8, 0xa4, 0x66, 0x71, 0x0d, 0x55, 0xcf, 0x21, 0xdb, 0xc8, 0xd0, 0x2d, + 0x43, 0xac, 0x6a, 0xca, 0x71, 0x7c, 0x74, 0xef, 0x21, 0x68, 0x5f, 0xc6, 0xdb, 0xf2, 0x8f, + 0x82, 0xa8, 0xce, 0x56, 0xe9, 0x11, 0x5d, 0xae, 0xb2, 0x7f, 0x69, 0xea, 0x9a, 0x9c, 0x25, + 0x1d, 0xcb, 0x23, 0xdb, 0x14, 0x07, 0x52, 0x88, 0xe3, 0xb0, 0xf2, 0x8c, 0xa2, 0x17, 0x35, + 0xa2, 0x12, 0x3c, 0x83, 0xd2, 0xa4, 0x06, 0x9d, 0x46, 0xbf, 0x02, 0x35, 0x0c, 0xf5, 0x20, + 0x8e, 0xf0, 0x15, 0x2e, 0xa2, 0xf8, 0x9b, 0xa0, 0x7d, 0x78, 0x06, 0xb2, 0x9b, 0x68, 0xf1, + 0xbe, 0xe3, 0x92, 0x6a, 0x82, 0xa0, 0x42, 0xbd, 0x60, 0xe3, 0xae, 0x02, 0x04, 0x9f, 0x30, + 0x8c, 0xa9, 0x80, 0x4c, 0x27, 0x17, 0x9a, 0x70, 0x47, 0xc5, 0xb6, 0x3c, 0xf3, 0xf0, 0xf7, + 0x15, 0xbf, 0x0a, 0x65, 0x48, 0x67, 0x80, 0xcc, 0x86, 0x31, 0x1e, 0x55, 0xeb, 0xc8, 0x63, + 0x88, 0x12, 0x93, 0xaf, 0x05, 0xb6, 0x2e, 0x2f, 0x4f, 0xa6, 0x07, 0x5f, 0xed, 0x69, 0x0b, + 0x3f, 0x65, 0x23, 0x46, 0xdc, 0x5e, 0x3a, 0xef, 0x82, 0x29, 0x45, 0x79, 0xcb, 0x64, 0xad, + 0x71, 0xe1, 0xfe, 0xe4, 0xd4, 0x3d, 0x01, 0xa4, 0xea, 0xa2, 0x61, 0x70, 0x68, 0xc6, 0x50, + 0x77, 0x92, 0xc7, 0x84, 0xbc, 0x99, 0xe8, 0x30, 0x1b, 0x7c, 0xbf, 0x77, 0xa4, 0x4f, 0x9a, + 0xb4, 0x07, 0xff, 0x08, 0xe0, 0x84, 0x19, 0xba, 0xe7, 0xa5, 0xdc, 0x38, 0xd1, 0x89, 0xea, + 0x84, 0x24, 0x85, 0x89, 0x38, 0xfc, 0xf4, 0x33, 0xdd, 0xfa, 0x2f, 0xbf, 0x9b, 0xa9, 0x4c, + 0xfd, 0xb8, 0xa1, 0xb2, 0x17, 0x4f, 0xed, 0xc0, 0x1e, 0xdf, 0x7e, 0x84, 0x94, 0xfc, 0x98, + 0x2e, 0x49, 0x7d, 0x5d, 0xcf, 0x28, 0x13, 0x80, 0xe6, 0x67, 0xaf, 0xca, 0x0e, 0x78, 0x80, + 0xd4, 0x6b, 0x2a, 0x41, 0xe2, 0x92, 0xd3, 0xa3, 0xbc, 0x0e, 0x91, 0x51, 0xe8, 0xe2, 0x5f, + 0x0d, 0x04, 0x5e, 0xf7, 0xdc, 0x00, 0xc1, 0x26, 0xf2, 0x94, 0x7b, 0xe5, 0xd2, 0xd7, 0x9e, + 0x11, 0x05, 0x4b, 0x92, 0x13, 0x80, 0x17, 0x18, 0x45, 0x78, 0x35, 0xc1, 0x86, 0xfe, 0xd2, + 0xe0, 0x3f, 0xe4, 0xe5, 0xfa, 0x96, 0x95, 0x01, 0x1f, 0xb3, 0x12, 0x57, 0xd2, 0x89, 0xa8, + 0x9c, 0x3a, 0x0f, 0x0e, 0xd5, 0xbd, 0x71, 0xb5, 0x0d, 0xae, 0x04, 0xfb, 0x9e, 0xaa, 0xf2, + 0x21, 0x22, 0x68, 0x95, 0xee, 0xca, 0x10, 0xf2, 0x53, 0x51, 0x64, 0x31, 0x8d, 0x12, 0x60, + 0x06, 0x43, 0x02, 0x3f, 0x41, 0x0b, 0x4c, 0x7f, 0x37, 0x5c, 0xfe, 0x86, 0x29, 0xe1, 0x05, + 0xea, 0x7b, 0x04, 0x04, 0xe3, 0x19, 0x42, 0xf5, 0xd0, 0x20, 0x8c, 0xb1, 0x9e, 0xf7, 0x21, + 0x64, 0xd2, 0x87, 0x7e, 0xd4, 0xee, 0x3b, 0x16, 0x11, 0xce, 0xa4, 0xee, 0xc1, 0x29, 0x61, + 0xf9, 0x34, 0xaa, 0x41, 0x17, 0xbb, 0xce, 0x04, 0xc3, 0xea, 0x38, 0xfa, 0xf6, 0x7e, 0xbb, + 0xe6, 0x68, 0xef, 0x0e, 0xaf, 0x6b, 0x8f, 0x90, 0x9a, 0x0b, 0x22, 0xed, 0x81, 0x68, 0x17, + 0x7a, 0xc2, 0xde, 0x31, 0x2a, 0xf0, 0x6f, 0xac, 0x7b, 0xc4, 0x62, 0x60, 0x62, 0x38, 0x03, + 0x42, 0x52, 0x88, 0x44, 0x18, 0xd3, 0xcf, 0x3d, 0xd8, 0x0f, 0x03, 0x3e, 0x01, 0xc9, 0xcd, + 0x43, 0x2e, 0xde, 0xa8, 0x73, 0x19, 0xb8, 0xbd, 0xf5, 0xb4, 0x00, 0xd1, 0x7c, 0xb0, 0xd4, + 0x74, 0x3f, 0x21, 0x74, 0xc1, 0x50, 0x37, 0xc7, 0xfd, 0x9e, 0x5c, 0xdc, 0xe9, 0x45, 0x86, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x6e, 0xfc, 0xcf, 0xd6, 0x50, 0x59, + 0x56, 0xba, 0x5c, 0x84, 0x50, 0x05, 0xa2, 0x3f, 0xbd, 0x48, 0xe9, 0x9d, 0xce, 0xde, 0x81, + 0xb8, 0x40, 0xa0, 0xd0, 0x5b, 0x7e, 0x8e, 0x35, 0xfd, 0x0a, 0xf3, 0x08, 0xe3, 0x37, 0xfa, + 0xd8, 0xb9, 0x08, 0x94, 0x79, 0xdd, 0x35, 0x73, 0x05, 0x8e, 0x64, 0x48, 0x82, 0xe9, 0xb0, + 0x49, 0x1d, 0x06, 0x89, 0x26, 0xc4, 0x8c, 0x06, 0x52, 0xad, 0xd9, 0x32, 0x00, 0x06, 0x00, + 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x56, 0x90, 0xe6, 0xfe, 0xfc, 0x61, 0x4c, + 0xd6, 0x40, 0xc0, 0xfc, 0x9c, 0x69, 0x91, 0x0d, 0x55, 0xd2, 0x0f, 0x25, 0xad, 0xfe, 0x3e, + 0x4c, 0x9c, 0x06, 0x96, 0x9a, 0xe3, 0x2a, 0x51, 0xbe, 0x9a, 0x7a, 0x06, 0x13, 0x03, 0x39, + 0x58, 0x9a, 0x79, 0x4c, 0x5a, 0x25, 0x5a, 0x2c, 0xd2, 0xf8, 0x68, 0x30, 0x8b, 0xcc, 0x89, + 0x88, 0x3a, 0x44, 0x0b, 0x4d, 0xa1, 0xbc, 0xd1, 0xbd, 0x74, 0xdb, 0x3d, 0xef, 0x27, 0xa6, + 0x4e, 0xe8, 0x32, 0x34, 0xd7, 0x81, 0x3f, 0x46, 0x09, 0x1f, 0xff, 0x84, 0x9d, 0x9d, 0x62, + 0x1c, 0x11, 0x61, 0x5d, 0xd0, 0x73, 0x16, 0xe3, 0x9e, 0x00, 0xf0, 0x42, 0x42, 0x8a, 0xab, + 0xd6, 0x1b, 0x3b, 0x2e, 0x01, 0x15, 0x0f, 0xf5, 0xe9, 0xdb, 0x99, 0x6d, 0x5c, 0x8a, 0x3a, + 0xc1, 0x68, 0x54, 0xbf, 0xee, 0xea, 0xd1, 0x00, 0x8b, 0xe5, 0x3b, 0x7d, 0x15, 0x4a, 0x5e, + 0x36, 0x80, 0x58, 0x13, 0x14, 0xce, 0xd6, 0x26, 0x36, 0x7d, 0x7d, 0xc0, 0x34, 0x53, 0x5f, + 0x54, 0x62, 0x0f, 0xa5, 0x9d, 0xb4, 0x7d, 0x5e, 0xa3, 0xc4, 0xe8, 0x44, 0x66, 0xf7, 0x37, + 0x38, 0xef, 0x91, 0x3c, 0x6a, 0x36, 0x4a, 0xd8, 0x3d, 0x09, 0x45, 0x00, 0x62, 0xa8, 0x9c, + 0x25, 0x2a, 0x02, 0xa7, 0x13, 0xf9, 0xa3, 0x70, 0xb0, 0xeb, 0xdd, 0xf2, 0x0b, 0x82, 0xf1, + 0x43, 0x75, 0xc3, 0x18, 0xa0, 0xaf, 0x1d, 0x9c, 0x75, 0xe4, 0x90, 0xdf, 0x51, 0x6b, 0x3e, + 0x1f, 0x26, 0xf9, 0x68, 0x63, 0x9c, 0xc5, 0xef, 0xae, 0x44, 0xed, 0x31, 0x3f, 0xca, 0xaf, + 0x54, 0x28, 0xe3, 0x7e, 0x85, 0xea, 0x43, 0x75, 0x39, 0x82, 0xf3, 0x13, 0xd5, 0xa2, 0x9f, + 0x79, 0xee, 0xd4, 0x8f, 0xec, 0x3a, 0x56, 0x3f, 0x0e, 0x27, 0xb5, 0x17, 0x17, 0x43, 0x93, + 0x45, 0x82, 0x31, 0x0f, 0x7a, 0x56, 0xfb, 0xb7, 0x78, 0xef, 0x6e, 0x43, 0x63, 0x3a, 0x54, + 0xcc, 0xb6, 0x5b, 0x5c, 0x19, 0x11, 0xe2, 0x5d, 0xd5, 0xbe, 0xb0, 0xa2, 0x18, 0x77, 0x8e, + 0x97, 0x15, 0x12, 0x3a, 0x8c, 0x01, 0xc3, 0x98, 0x9b, 0xc3, 0x66, 0x2c, 0xc3, 0xa8, 0x94, + 0xc6, 0x2d, 0x0b, 0x77, 0x88, 0xc4, 0xa1, 0xdc, 0xd6, 0x96, 0x35, 0xea, 0xb9, 0xd8, 0x55, + 0xfc, 0x73, 0xf0, 0xd8, 0x2a, 0x38, 0x50, 0x16, 0x40, 0xa5, 0xe4, 0x91, 0xc3, 0x33, 0xc8, + 0xcc, 0xf1, 0xd1, 0x42, 0xf7, 0x9a, 0x35, 0x24, 0x21, 0xb2, 0x23, 0x0f, 0xd7, 0xb9, 0xca, + 0xfd, 0x96, 0x75, 0x9b, 0xf0, 0x07, 0x19, 0xcb, 0xa4, 0xe8, 0x78, 0x35, 0xe6, 0x3d, 0xdd, + 0x89, 0x76, 0x34, 0xa2, 0xf6, 0xa6, 0xac, 0x96, 0x25, 0xea, 0x2d, 0x05, 0x3f, 0xba, 0x50, + 0xb8, 0x5f, 0x12, 0xc9, 0xc6, 0x2b, 0xfc, 0xd0, 0x97, 0x33, 0xdc, 0x31, 0xce, 0xa4, 0xd0, + 0xf3, 0xd6, 0x44, 0x9b, 0xc4, 0xc4, 0x29, 0x96, 0xc6, 0x44, 0x94, 0x4c, 0xbc, 0xbc, 0xca, + 0xaf, 0xd1, 0x6d, 0x9f, 0xbb, 0x2a, 0xbf, 0xfc, 0xb5, 0x8e, 0xe9, 0xab, 0xd1, 0xbd, 0x4d, + 0xa7, 0x29, 0x32, 0x5b, 0xc4, 0x85, 0x0d, 0x10, 0xe7, 0xf2, 0x58, 0xd5, 0xba, 0xa3, 0x1b, + 0xaf, 0x9d, 0xff, 0xfd, 0xb0, 0x82, 0x19, 0xad, 0x30, 0xb7, 0x25, 0x23, 0x10, 0x77, 0x76, + 0xc4, 0x32, 0x95, 0x2c, 0xa7, 0xdd, 0x09, 0x35, 0xb6, 0x5a, 0xc8, 0x2d, 0x19, 0x8d, 0x55, + 0x4b, 0xa2, 0xc5, 0x7b, 0x82, 0x3e, 0x13, 0x3d, 0x5d, 0x5b, 0xa5, 0x19, 0x37, 0x47, 0xd8, + 0xdc, 0x09, 0x0e, 0x46, 0x19, 0xfc, 0x29, 0xd8, 0x70, 0x70, 0x26, 0xcb, 0x51, 0x83, 0x75, + 0x2b, 0x2c, 0xf2, 0xe7, 0xf7, 0xf9, 0xea, 0xb7, 0xfd, 0xa7, 0xe2, 0x8c, 0x68, 0x35, 0x8c, + 0xc7, 0x58, 0x4b, 0x22, 0xd2, 0x65, 0xf4, 0xd9, 0x03, 0x8b, 0xdb, 0xb6, 0xa8, 0xca, 0x7d, + 0x7c, 0xc0, 0x7f, 0x27, 0xf4, 0xd2, 0xaf, 0xfb, 0x95, 0x60, 0x37, 0x5c, 0x94, 0x6d, 0x6c, + 0x1f, 0xd7, 0x54, 0x6a, 0x05, 0xb2, 0x45, 0x0d, 0xc7, 0xe0, 0x17, 0x37, 0x9a, 0xd3, 0x0c, + 0x16, 0x2d, 0x9c, 0x1e, 0xee, 0x5a, 0x74, 0xea, 0x3c, 0x92, 0x6c, 0x10, 0x84, 0x96, 0xd2, + 0x67, 0x96, 0x99, 0xee, 0xb1, 0x41, 0x9e, 0x97, 0x11, 0x16, 0xce, 0xf3, 0xdd, 0x6a, 0xd8, + 0x7e, 0xfc, 0xae, 0xdc, 0xb0, 0x8a, 0xc0, 0xa0, 0xbb, 0x09, 0x9a, 0x48, 0xcc, 0x5c, 0xd1, + 0x49, 0x69, 0x8a, 0x1c, 0x97, 0xcc, 0x46, 0xdf, 0x8f, 0x29, 0x01, 0x69, 0x98, 0xce, 0x0e, + 0x43, 0x56, 0x1e, 0x71, 0xa6, 0x09, 0x07, 0x84, 0x0b, 0x79, 0x86, 0xa7, 0x14, 0x2b, 0x6a, + 0xc0, 0x6b, 0xf8, 0x3d, 0xd6, 0x55, 0x45, 0xb9, 0xbd, 0x62, 0x33, 0x7e, 0xab, 0xd5, 0x5f, + 0x7c, 0x66, 0x45, 0xd9, 0xf5, 0xcf, 0x14, 0x5d, 0x0a, 0x81, 0x24, 0xe4, 0x91, 0xa6, 0x91, + 0xfa, 0x19, 0x32, 0xcc, 0xce, 0x71, 0x9d, 0xda, 0xa3, 0xc2, 0xfb, 0x54, 0xf7, 0x36, 0x45, + 0x0f, 0xf9, 0x90, 0x19, 0x88, 0xa7, 0x40, 0xa8, 0xc5, 0x5c, 0x21, 0xfe, 0xa0, 0x06, 0x6b, + 0x10, 0x93, 0x24, 0x45, 0x86, 0x31, 0xe0, 0xfd, 0x51, 0x64, 0xb7, 0xed, 0xbc, 0x38, 0xa0, + 0x8b, 0xdf, 0x2e, 0xb0, 0xf7, 0x20, 0xb3, 0x5d, 0xaa, 0x55, 0x43, 0x7f, 0x5a, 0x29, 0xb9, + 0xdc, 0xd6, 0x5f, 0xc8, 0xea, 0x49, 0x30, 0xe3, 0x59, 0x8a, 0x76, 0xf7, 0x08, 0x3e, 0x39, + 0xc3, 0x88, 0xae, 0x43, 0x62, 0x44, 0xe4, 0x65, 0xc1, 0xfe, 0xf0, 0xa4, 0x33, 0xec, 0x6c, + 0xd5, 0xe6, 0xf3, 0xc3, 0x7c, 0xa4, 0x47, 0x1f, 0xe6, 0xca, 0x6e, 0xf4, 0x83, 0x65, 0x61, + 0xf4, 0xfb, 0x2c, 0x60, 0xff, 0x27, 0xa9, 0xc7, 0x5d, 0x43, 0x1a, 0x2e, 0xbd, 0x28, 0x1e, + 0x22, 0xa5, 0x6b, 0xef, 0x99, 0x3d, 0x3e, 0x50, 0xbd, 0xe1, 0x8b, 0x99, 0xf0, 0x42, 0xbe, + 0xdd, 0x60, 0x35, 0x8a, 0x3e, 0xc6, 0xd8, 0x6c, 0x74, 0x72, 0x4b, 0xf3, 0x34, 0x50, 0x23, + 0x4f, 0x58, 0x3c, 0x26, 0xb2, 0x59, 0x0b, 0xd3, 0x3d, 0x26, 0x3a, 0xe3, 0x04, 0x17, 0xc7, + 0x4b, 0x92, 0x7c, 0xe5, 0xac, 0xae, 0x02, 0x37, 0xb8, 0x39, 0x54, 0x4a, 0x5f, 0xb7, 0x6d, + 0x5f, 0xd9, 0xd3, 0x58, 0xed, 0xa3, 0xeb, 0xea, 0x26, 0x69, 0xfd, 0xec, 0xd2, 0xd4, 0xe0, + 0xea, 0x19, 0xe1, 0x85, 0xaf, 0xbd, 0xad, 0x51, 0x4a, 0x84, 0x78, 0xde, 0xc6, 0x4d, 0x0e, + 0x5c, 0x9e, 0x88, 0xbe, 0xf1, 0x19, 0x1a, 0xd9, 0x92, 0xc1, 0xea, 0x75, 0x0b, 0x84, 0x90, + 0x4d, 0x39, 0x03, 0x69, 0x10, 0x0b, 0xb0, 0x37, 0xd6, 0xec, 0x9f, 0xe6, 0xed, 0x3a, 0xd6, + 0x9d, 0xee, 0x76, 0xa0, 0x3e, 0xbf, 0xb9, 0x91, 0x81, 0x2f, 0xac, 0xc1, 0xdd, 0x04, 0x3b, + 0xe0, 0x63, 0x60, 0xca, 0xa9, 0xf8, 0x52, 0xf0, 0x28, 0x10, 0xd3, 0x79, 0x74, 0x20, 0xe5, + 0x8a, 0x1b, 0x5c, 0xa3, 0x38, 0x51, 0xfe, 0x64, 0xf5, 0x98, 0x80, 0x88, 0x41, 0xe2, 0xfd, + 0xec, 0x9a, 0xe8, 0x05, 0x29, 0xf9, 0x1b, 0xc5, 0xf3, 0x15, 0x2d, 0x58, 0x9a, 0xc4, 0x75, + 0xfd, 0x99, 0x23, 0x24, 0xcf, 0xb1, 0x00, 0x62, 0x47, 0xaa, 0x14, 0xa3, 0x7e, 0x1e, 0x38, + 0x9a, 0xa8, 0x18, 0xf7, 0x62, 0xb9, 0x9e, 0x3f, 0x10, 0x2f, 0x45, 0xf4, 0x36, 0x0e, 0x91, + 0x23, 0x1c, 0x04, 0xcf, 0x4d, 0xf9, 0xd4, 0x21, 0x7b, 0x86, 0x0a, 0xf7, 0x65, 0x67, 0xd5, + 0x11, 0xb2, 0x58, 0x90, 0x12, 0xd9, 0x12, 0x22, 0xe8, 0x13, 0xdf, 0x04, 0xd8, 0x4d, 0xad, + 0xa2, 0x0d, 0x7c, 0x8d, 0x71, 0xe5, 0xeb, 0x52, 0xd0, 0x26, 0xe2, 0xad, 0xaa, 0xd5, 0xcd, + 0x89, 0x28, 0xac, 0xc4, 0x2c, 0x20, 0x2d, 0xcf, 0x01, 0x27, 0x69, 0xd3, 0x81, 0xe2, 0x7e, + 0x4b, 0x25, 0x03, 0x03, 0x80, 0x67, 0xd4, 0x8d, 0x13, 0x7f, 0x59, 0x38, 0x80, 0x43, 0x0c, + 0x82, 0x70, 0x5c, 0xbd, 0xda, 0x97, 0x7f, 0x50, 0xb3, 0x8a, 0x44, 0xa5, 0xed, 0x73, 0x23, + 0x1f, 0xae, 0x55, 0x32, 0xb8, 0xa7, 0x39, 0x89, 0x6b, 0x93, 0x7a, 0x01, 0xca, 0xde, 0x59, + 0x9c, 0x52, 0xce, 0xb8, 0x38, 0x26, 0x21, 0xc8, 0x48, 0x95, 0x7f, 0xf9, 0xd8, 0x96, 0x71, + 0x72, 0xf3, 0xc1, 0x53, 0xed, 0xfb, 0xe7, 0x0b, 0xcf, 0xf1, 0x74, 0xd6, 0xe6, 0xaf, 0xe5, + 0xb7, 0x0d, 0xd2, 0x72, 0xc6, 0xe4, 0x00, 0x17, 0x72, 0xc2, 0xd7, 0xa6, 0x7b, 0x52, 0x14, + 0x0c, 0x66, 0xa2, 0x80, 0x66, 0x3d, 0x0e, 0x4e, 0xa9, 0x53, 0x0c, 0x20, 0x00, 0x41, 0xc5, + 0x3c, 0xc6, 0x75, 0x00, 0xfa, 0x64, 0x59, 0x2a, 0x02, 0xbd, 0x49, 0xc8, 0x1a, 0xaa, 0xec, + 0xb1, 0xfe, 0x67, 0xbb, 0x6f, 0xa9, 0xc1, 0x50, 0xbd, 0x63, 0xf4, 0xef, 0x4b, 0x33, 0x1f, + 0xb4, 0xad, 0xe2, 0x85, 0xa6, 0x2e, 0xd9, 0x61, 0xaf, 0x52, 0x44, 0xfe, 0x2e, 0xaa, 0x8f, + 0x69, 0x54, 0xff, 0x09, 0x32, 0xb2, 0xe7, 0x64, 0x49, 0x9f, 0x76, 0xae, 0x3a, 0x71, 0xef, + 0xc6, 0x42, 0x76, 0xda, 0x34, 0x7e, 0xe9, 0x5c, 0x01, 0xc4, 0x08, 0x28, 0xf6, 0xd9, 0x4b, + 0xcd, 0x88, 0x4d, 0xbd, 0x47, 0x2a, 0x8f, 0x51, 0x42, 0x65, 0x98, 0x95, 0x04, 0xa4, 0x3e, + 0xf3, 0x7d, 0xa7, 0xed, 0xac, 0xd8, 0x16, 0x70, 0xa4, 0x25, 0xbf, 0x1f, 0x58, 0x64, 0xdd, + 0x25, 0x55, 0x0b, 0xa4, 0xe3, 0x74, 0xb8, 0x79, 0xa9, 0xa2, 0xc5, 0x41, 0x36, 0x41, 0xd7, + 0xb7, 0x33, 0xab, 0x4a, 0xe0, 0x94, 0x10, 0xc6, 0x7e, 0x6b, 0xeb, 0x74, 0x0f, 0xcf, 0x97, + 0xa3, 0xc0, 0xc5, 0x55, 0x6f, 0xa8, 0x92, 0xba, 0x83, 0x77, 0x91, 0xdf, 0xed, 0xe8, 0x39, + 0xf2, 0x1e, 0x57, 0x08, 0xa5, 0x05, 0x94, 0x44, 0xca, 0x07, 0x37, 0x33, 0x27, 0x7e, 0xd1, + 0xbd, 0x9e, 0x1d, 0x40, 0x3e, 0x01, 0x03, 0x68, 0xfd, 0xf6, 0x44, 0xe4, 0x31, 0x9c, 0xe0, + 0xe1, 0xf4, 0x7f, 0x18, 0xaa, 0xa9, 0x3d, 0x27, 0xe8, 0xc5, 0x23, 0x79, 0x0a, 0x59, 0xd4, + 0xfe, 0xb0, 0xa7, 0x7a, 0xdc, 0xa9, 0xb0, 0xa9, 0xd5, 0xb5, 0x3d, 0xb0, 0x1c, 0x59, 0x2e, + 0x4d, 0xfd, 0x62, 0xad, 0x32, 0x4a, 0xbe, 0x3d, 0x23, 0x9e, 0x8d, 0x4f, 0xc9, 0x5f, 0xa1, + 0x07, 0x5e, 0x79, 0x0e, 0xf9, 0x2f, 0xb3, 0xdf, 0xb9, 0x4d, 0x01, 0x5e, 0x40, 0x5a, 0xd8, + 0x00, 0x78, 0xa0, 0x0a, 0xef, 0x1c, 0xa5, 0x1c, 0x0c, 0xac, 0xe7, 0x1c, 0x82, 0x37, 0xb1, + 0x67, 0x96, 0xfb, 0xe5, 0x39, 0x4c, 0x7e, 0x18, 0x7a, 0x51, 0x21, 0x0b, 0x1f, 0xa5, 0xc9, + 0x06, 0xb6, 0x39, 0x79, 0x59, 0x65, 0xb4, 0x5f, 0xca, 0x9b, 0x67, 0x7d, 0x22, 0xc6, 0x48, + 0xab, 0x92, 0xd1, 0xf2, 0x6e, 0xa1, 0xff, 0xc2, 0x5d, 0x8d, 0xdb, 0x10, 0xf8, 0xf1, 0x42, + 0x88, 0x98, 0x41, 0x8b, 0x59, 0x52, 0x91, 0x23, 0x77, 0xa2, 0xf4, 0x9c, 0xf4, 0xe1, 0xb2, + 0x55, 0xe7, 0x27, 0xaa, 0x9f, 0x6c, 0x99, 0x53, 0xf0, 0x68, 0xde, 0xa5, 0x92, 0x60, 0xec, + 0x1b, 0x62, 0xb8, 0xe7, 0x7e, 0x6f, 0x61, 0xe6, 0x1c, 0x24, 0x6b, 0x63, 0xec, 0x7d, 0xab, + 0x81, 0xd7, 0xb2, 0x8b, 0x8d, 0xc8, 0x9e, 0x37, 0x3e, 0x27, 0xb9, 0x19, 0x7e, 0x96, 0xcf, + 0xdd, 0x67, 0x32, 0x42, 0x89, 0x49, 0xbc, 0x2a, 0xc0, 0x0c, 0x04, 0xf3, 0x20, 0x8b, 0x33, + 0x82, 0x0d, 0xa6, 0x65, 0x43, 0x56, 0x12, 0x6c, 0xb8, 0xe9, 0x33, 0x92, 0x1e, 0xf5, 0x2b, + 0x65, 0x61, 0xa1, 0xef, 0x5e, 0xe3, 0x43, 0x10, 0x42, 0x35, 0xec, 0x50, 0xbd, 0xd2, 0xd3, + 0x15, 0xbd, 0x86, 0x63, 0x2a, 0x88, 0xcf, 0x58, 0x47, 0xe0, 0xe5, 0x80, 0x28, 0xe1, 0xbc, + 0xf6, 0x01, 0xd3, 0xd8, 0x31, 0x03, 0xaa, 0xcc, 0x93, 0xf5, 0x60, 0x1a, 0xf6, 0xbf, 0xf0, + 0x18, 0x1b, 0x8f, 0xaa, 0x72, 0x0d, 0x68, 0xce, 0x19, 0xa2, 0x36, 0xe9, 0xf9, 0xd2, 0x88, + 0xd3, 0xe3, 0x36, 0x7f, 0x95, 0x9b, 0x2a, 0xa0, 0x14, 0x53, 0xd0, 0xa7, 0xa1, 0xc3, 0xf0, + 0x6d, 0x7a, 0xba, 0x70, 0xc6, 0x63, 0xf2, 0xb8, 0x72, 0x97, 0x35, 0x11, 0x40, 0x9b, 0x3a, + 0x50, 0x97, 0x22, 0xc9, 0x8b, 0xe6, 0x10, 0x4b, 0x6a, 0x36, 0x60, 0xb1, 0xc9, 0x6a, 0xdc, + 0x6f, 0x52, 0x69, 0x98, 0x5f, 0x33, 0xb8, 0x91, 0x77, 0x96, 0x04, 0xc9, 0x2e, 0x19, 0xb1, + 0x27, 0x07, 0xe8, 0x8f, 0x56, 0x69, 0x21, 0xe3, 0x90, 0xfd, 0x8c, 0x48, 0x31, 0x93, 0x59, + 0x04, 0xc4, 0xf8, 0x46, 0xad, 0x48, 0x6e, 0x71, 0x00, 0xba, 0xfa, 0x35, 0x70, 0x49, 0x31, + 0x64, 0x86, 0x5d, 0xf0, 0x1e, 0x20, 0x3c, 0xa6, 0x83, 0x43, 0xc2, 0x26, 0x72, 0xef, 0x08, + 0x7f, 0x32, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xb9, 0x7e, 0x92, + 0x7c, 0xb6, 0xce, 0xd7, 0xde, 0xa4, 0x52, 0x2e, 0x4d, 0x92, 0x78, 0x5d, 0xad, 0x6d, 0x63, + 0x95, 0x4f, 0xb2, 0xec, 0xba, 0xca, 0x16, 0x80, 0x1c, 0xe9, 0x2a, 0xff, 0x0c, 0xfd, 0xe0, + 0x1c, 0x43, 0x91, 0xbb, 0x35, 0xd5, 0x13, 0xec, 0x97, 0x7a, 0x9a, 0x1c, 0xbb, 0x8c, 0xfe, + 0xd9, 0xac, 0x9e, 0x2b, 0x75, 0xfd, 0x12, 0xfb, 0x29, 0x96, 0x71, 0xc8, 0x59, 0x47, 0x5e, + 0xc3, 0x5c, 0x13, 0xe2, 0x3b, 0x40, 0xfa, 0x97, 0xf3, 0x21, 0x98, 0xe9, 0xe0, 0xa4, 0xf8, + 0xb1, 0x82, 0x8c, 0xb4, 0x7c, 0xd4, 0xa0, 0x27, 0xdd, 0xb2, 0x94, 0xc9, 0x56, 0x2e, 0x6e, + 0x22, 0xd3, 0xda, 0xa0, 0xa0, 0x43, 0x75, 0xd7, 0x01, 0xd1, 0x4d, 0x91, 0x12, 0xf6, 0x5f, + 0x87, 0x27, 0x83, 0xf1, 0x1a, 0xb8, 0x44, 0x91, 0x06, 0xb3, 0x6c, 0x2f, 0x24, 0xe0, 0x1a, + 0x17, 0xbf, 0x3d, 0x6c, 0xd4, 0x8a, 0x8d, 0xc4, 0x18, 0xf5, 0xdd, 0xc4, 0x89, 0xe0, 0x4e, + 0xfb, 0x93, 0x5b, 0x70, 0xf6, 0x93, 0xf5, 0xeb, 0xf8, 0x52, 0x3d, 0xdb, 0x8a, 0x79, 0x44, + 0x3f, 0xec, 0x99, 0xa6, 0xb0, 0xa6, 0x86, 0xdc, 0x3e, 0xbc, 0x04, 0x77, 0x44, 0xce, 0xd6, + 0xfe, 0x00, 0x43, 0xa0, 0xa3, 0x7a, 0xf2, 0x20, 0x16, 0x6f, 0x21, 0x89, 0x17, 0x1f, 0x88, + 0x4e, 0xac, 0xad, 0x69, 0x7b, 0x69, 0x7e, 0xfd, 0xdb, 0xfc, 0x89, 0x35, 0xd1, 0xb3, 0xa3, + 0x01, 0x75, 0x5b, 0xe9, 0xc5, 0x60, 0x61, 0xf9, 0x4b, 0xca, 0x38, 0xd0, 0x34, 0xd4, 0x13, + 0xc6, 0xab, 0xce, 0xc8, 0x96, 0xab, 0xe6, 0x90, 0x73, 0x50, 0x34, 0x64, 0x98, 0x7f, 0xd0, + 0xf0, 0x85, 0x7c, 0x2b, 0xe9, 0x4e, 0x65, 0xbc, 0x34, 0xd0, 0xb1, 0xdd, 0xe1, 0x8c, 0xce, + 0xff, 0x31, 0x12, 0x33, 0x3d, 0x0d, 0xf2, 0x4c, 0xff, 0xe1, 0x27, 0xab, 0xd9, 0x6c, 0x2e, + 0x2e, 0xf6, 0x7c, 0x05, 0xf1, 0x3b, 0xfd, 0x19, 0xe3, 0x49, 0x3b, 0xa6, 0xd6, 0xc2, 0x38, + 0x6c, 0x6a, 0x28, 0x8d, 0x85, 0x5e, 0x19, 0xda, 0xb9, 0x32, 0x2e, 0xa4, 0xe6, 0xdb, 0xa6, + 0x4c, 0x36, 0xcd, 0xb6, 0x82, 0x35, 0xad, 0x85, 0xc3, 0x21, 0x89, 0x61, 0x14, 0xa1, 0xc5, + 0xb1, 0xa9, 0x69, 0xbf, 0x21, 0x1b, 0x2b, 0x87, 0x28, 0xfb, 0x15, 0xcf, 0x97, 0xe6, 0x10, + 0x2b, 0xf7, 0x9f, 0x03, 0x5d, 0x9b, 0xbc, 0x3d, 0x2e, 0x8b, 0x3b, 0x98, 0x2a, 0x82, 0xe7, + 0xa2, 0xb5, 0x72, 0x46, 0xb9, 0xcc, 0xa1, 0x24, 0xe6, 0xe6, 0x70, 0xf8, 0x31, 0x46, 0x6a, + 0x70, 0x34, 0xe6, 0x34, 0x7d, 0x3f, 0x6f, 0xa0, 0xdb, 0x81, 0xda, 0x1a, 0x40, 0x17, 0xeb, + 0x9b, 0x3d, 0x1f, 0x23, 0x1d, 0x61, 0x1d, 0x1b, 0x14, 0x29, 0x66, 0xf1, 0xff, 0xe9, 0x48, + 0x09, 0x48, 0x5d, 0x1d, 0x02, 0xe5, 0x6e, 0x33, 0x3b, 0x4b, 0xe3, 0x86, 0xd8, 0x2f, 0x34, + 0xc2, 0xe2, 0x34, 0x3a, 0xb2, 0xe8, 0x25, 0x64, 0xd8, 0x4e, 0x51, 0x42, 0x8d, 0x48, 0x56, + 0x3c, 0xd6, 0x8d, 0x37, 0xaf, 0x41, 0x4e, 0xf5, 0x10, 0x32, 0x82, 0x16, 0xb1, 0x24, 0xa6, + 0x45, 0x58, 0xbf, 0x35, 0xd1, 0x39, 0x24, 0xe2, 0xc1, 0xe3, 0x7f, 0xfb, 0xee, 0x36, 0x04, + 0x6b, 0x62, 0x99, 0x7d, 0x85, 0x88, 0x4d, 0x71, 0xca, 0xda, 0x5e, 0x08, 0x3d, 0x27, 0xfc, + 0x32, 0x98, 0xd6, 0xd9, 0x83, 0x1a, 0x65, 0xdb, 0xa8, 0x9e, 0xfd, 0x3b, 0xe9, 0x05, 0x49, + 0x5c, 0xb0, 0xb8, 0x93, 0xfe, 0xc4, 0x55, 0xf7, 0x7e, 0xa7, 0x2f, 0xc0, 0x06, 0x80, 0xee, + 0xe6, 0x68, 0x4d, 0x88, 0xc8, 0x1d, 0xa7, 0x2c, 0xf2, 0x94, 0xc8, 0xbd, 0x0a, 0xd0, 0xa0, + 0x1e, 0x53, 0x42, 0xca, 0x38, 0x52, 0xf3, 0xe1, 0x75, 0x05, 0xbe, 0x02, 0x41, 0xd4, 0x86, + 0x19, 0xf7, 0xfa, 0x3a, 0x45, 0x73, 0x31, 0xd1, 0xe4, 0xb6, 0xf5, 0xb2, 0x4f, 0x16, 0x0d, + 0x36, 0x5a, 0x09, 0xe3, 0x80, 0xe7, 0xea, 0x39, 0x87, 0xb3, 0x4c, 0x20, 0x73, 0x8d, 0x00, + 0xbe, 0x47, 0x82, 0x8e, 0xf9, 0xfc, 0x61, 0x1f, 0xe2, 0xc5, 0xad, 0xdb, 0xd6, 0x90, 0xa8, + 0x92, 0x82, 0x6a, 0x0e, 0x8e, 0x5d, 0x1e, 0xae, 0x44, 0xa1, 0x84, 0xd3, 0xc1, 0x17, 0x53, + 0xc3, 0x7f, 0x63, 0x72, 0x8b, 0x46, 0x30, 0x92, 0x1d, 0x16, 0x6f, 0xfa, 0x75, 0xc5, 0x1b, + 0xc7, 0x5a, 0xc6, 0xca, 0xd9, 0x44, 0xd4, 0x06, 0x49, 0xb7, 0x1a, 0x88, 0xb3, 0x06, 0x0a, + 0xaa, 0xd4, 0x45, 0x65, 0x30, 0x47, 0x2a, 0x6d, 0xf4, 0xa7, 0x95, 0x97, 0x52, 0xb2, 0x25, + 0x0e, 0x02, 0xc7, 0xb2, 0x4a, 0x84, 0xff, 0x7c, 0x0e, 0x1f, 0x59, 0xbf, 0x96, 0xfb, 0xaa, + 0x1a, 0x87, 0xbe, 0xfa, 0xf7, 0x8c, 0xfe, 0xb8, 0x1c, 0xb7, 0xe1, 0x07, 0x6c, 0xc4, 0x01, + 0x0d, 0x96, 0xf7, 0xaa, 0x52, 0x17, 0x20, 0x2a, 0xcd, 0x1e, 0x3d, 0x64, 0xa8, 0x2b, 0x27, + 0x46, 0x4b, 0xe2, 0x11, 0xd7, 0x4b, 0xf4, 0xd4, 0x26, 0x24, 0xb1, 0x6a, 0xdd, 0xf5, 0x0c, + 0x6a, 0x9b, 0x2b, 0x73, 0x6e, 0x8f, 0x1a, 0x49, 0x91, 0x7c, 0xf2, 0x70, 0x5d, 0x4e, 0xad, + 0x1c, 0x72, 0x1a, 0x2f, 0x30, 0xda, 0xfe, 0x1e, 0x33, 0xf5, 0xaf, 0xa2, 0x25, 0x95, 0xe9, + 0xca, 0x1e, 0x39, 0xcd, 0x8d, 0xc0, 0x94, 0xcf, 0x89, 0x10, 0xf5, 0xee, 0xe7, 0xf8, 0x35, + 0x82, 0xc4, 0x84, 0xd8, 0xab, 0xc9, 0x28, 0x65, 0x82, 0x3f, 0xba, 0x62, 0xde, 0xce, 0xb7, + 0xbd, 0x3b, 0x55, 0x19, 0x27, 0xfe, 0x91, 0xb8, 0xf8, 0x12, 0xb5, 0xc2, 0xe2, 0xe2, 0x5d, + 0x51, 0x8d, 0x82, 0x56, 0xbf, 0x9b, 0x0e, 0xee, 0x3d, 0xef, 0x67, 0xb4, 0x5f, 0xfc, 0x2e, + 0x9b, 0xbb, 0x65, 0xa4, 0xa4, 0xc9, 0x6b, 0x74, 0xef, 0x40, 0x45, 0xd9, 0xb1, 0x73, 0xd7, + 0x2d, 0xfc, 0x60, 0xee, 0xca, 0x3e, 0x4a, 0x06, 0xc4, 0x01, 0x71, 0x9b, 0xac, 0x73, 0xc8, + 0xb7, 0x72, 0x58, 0xb4, 0x28, 0x0f, 0x09, 0x9e, 0xee, 0x8d, 0x9a, 0x30, 0x0e, 0xdf, 0xd9, + 0x21, 0x11, 0x76, 0xa6, 0x90, 0x0c, 0x1c, 0xb1, 0xc9, 0x28, 0x77, 0x9b, 0x81, 0x9d, 0x96, + 0x18, 0x29, 0xb7, 0xbd, 0x1d, 0x0e, 0xec, 0x07, 0x84, 0xc9, 0xe1, 0xc0, 0xc9, 0x6f, 0x81, + 0x29, 0x0b, 0x46, 0xf9, 0x5e, 0xfa, 0x7b, 0xb5, 0x58, 0xe6, 0x9e, 0x57, 0xdc, 0xcf, 0x0e, + 0x3e, 0xbf, 0x8c, 0xa3, 0x0c, 0xe4, 0xa7, 0x3a, 0xb9, 0xad, 0x08, 0x82, 0x5f, 0x9a, 0xd7, + 0xcf, 0xfc, 0x35, 0xcd, 0x56, 0x31, 0xee, 0xd7, 0x7c, 0xc0, 0x6e, 0x0f, 0x10, 0x6c, 0x8a, + 0xa7, 0xd8, 0x23, 0x1b, 0xe6, 0x7b, 0x8c, 0xf1, 0x42, 0x27, 0xbd, 0x0d, 0x96, 0x45, 0x0f, + 0x8c, 0x3f, 0xb4, 0xc1, 0x98, 0xf0, 0x11, 0x64, 0x16, 0x9c, 0xef, 0x6c, 0xda, 0x01, 0x7d, + 0x4f, 0x2f, 0x49, 0xa7, 0xb9, 0xae, 0x4e, 0x8c, 0x35, 0xc7, 0x98, 0xb0, 0x4f, 0xfa, 0xdc, + 0x05, 0xa8, 0x06, 0x9b, 0xea, 0xa6, 0x8e, 0x24, 0x92, 0x9b, 0xeb, 0x90, 0xba, 0x3a, 0x4e, + 0x84, 0xc3, 0x9d, 0x46, 0x10, 0x19, 0x31, 0x4d, 0x73, 0xa7, 0xdd, 0x32, 0x37, 0x00, 0x6b, + 0x2c, 0x25, 0x72, 0xfe, 0x78, 0xb5, 0x26, 0xa6, 0xf2, 0xa7, 0xe7, 0xd7, 0x64, 0xa0, 0xec, + 0x45, 0x65, 0x4c, 0x82, 0x1f, 0x7e, 0xb8, 0x79, 0xf9, 0xb9, 0xd7, 0xcd, 0x37, 0x34, 0x43, + 0x93, 0x21, 0xaf, 0x95, 0x5d, 0x4b, 0xa5, 0xb8, 0x3e, 0x3e, 0x2c, 0xa0, 0x0b, 0x86, 0x4c, + 0x19, 0x18, 0x38, 0x0a, 0x39, 0xb1, 0xb5, 0x3b, 0x37, 0x3b, 0x29, 0x6f, 0xdc, 0x08, 0xae, + 0xe5, 0xbd, 0x93, 0x4d, 0x29, 0x90, 0x77, 0x52, 0x13, 0x10, 0xdf, 0xf4, 0x1a, 0x59, 0xda, + 0xf2, 0x78, 0x0e, 0xa8, 0x10, 0x33, 0x0e, 0x40, 0xb1, 0xc5, 0xae, 0xa1, 0xbc, 0x39, 0x82, + 0x71, 0xa2, 0x27, 0xa2, 0xb8, 0x8f, 0x6c, 0xd9, 0x6c, 0x96, 0x24, 0x1d, 0x0c, 0x32, 0x18, + 0x4e, 0xe3, 0xca, 0xba, 0xba, 0xfa, 0xce, 0xe7, 0x1c, 0x27, 0xad, 0x78, 0x4d, 0x23, 0xde, + 0xa8, 0x6c, 0xfe, 0x4b, 0xc9, 0x29, 0x23, 0xc4, 0xe3, 0x88, 0x51, 0xdc, 0x93, 0x1e, 0x5a, + 0x06, 0xf7, 0x3a, 0xba, 0x2b, 0xd2, 0x47, 0x41, 0x0e, 0xc9, 0xd5, 0x13, 0xbe, 0x52, 0xe7, + 0x31, 0xe8, 0xd7, 0xc7, 0xd6, 0x27, 0x0e, 0xe4, 0x8d, 0x30, 0x61, 0x40, 0xb7, 0xe1, 0x5f, + 0x28, 0x1b, 0xbb, 0x2a, 0xf0, 0xb0, 0x0f, 0x61, 0xd7, 0x6f, 0xc1, 0x1e, 0xd5, 0x37, 0x65, + 0x78, 0xae, 0x39, 0xc1, 0x85, 0x3a, 0x84, 0x7f, 0xc0, 0xce, 0x96, 0x19, 0xce, 0x36, 0x5f, + 0x3f, 0x41, 0x93, 0xe9, 0xaf, 0x5b, 0x5c, 0x08, 0xec, 0xec, 0xf1, 0xa9, 0x9a, 0xb3, 0x23, + 0xa4, 0xe7, 0xaa, 0xb4, 0x7a, 0x10, 0x2b, 0x76, 0x12, 0x7b, 0x51, 0xf7, 0x01, 0xbc, 0x08, + 0xd1, 0x07, 0x45, 0x67, 0x78, 0xe7, 0x36, 0x24, 0xfc, 0xfc, 0x04, 0xac, 0x37, 0xf9, 0xba, + 0xf3, 0x7f, 0x5c, 0x98, 0xbd, 0x1d, 0x2f, 0x85, 0x8f, 0x93, 0x7c, 0xcf, 0x57, 0x15, 0x91, + 0x9a, 0x62, 0xb0, 0x91, 0xf9, 0x8e, 0x75, 0x43, 0x50, 0xfb, 0x45, 0x07, 0x9d, 0xb9, 0x7a, + 0x47, 0x10, 0xc7, 0xfe, 0x43, 0xb5, 0xe2, 0x43, 0x1e, 0x25, 0x1a, 0x5a, 0x2b, 0x1a, 0xab, + 0xac, 0xad, 0x85, 0xd4, 0x00, 0x94, 0x9e, 0x0e, 0x24, 0xa1, 0x74, 0xd7, 0xe8, 0xc4, 0x10, + 0xab, 0xb6, 0xa4, 0x73, 0x81, 0x48, 0xf1, 0xfe, 0xa2, 0x3b, 0x4a, 0x68, 0x6b, 0x19, 0x0e, + 0xe2, 0xde, 0x79, 0x38, 0xac, 0x53, 0x14, 0x09, 0x16, 0x0e, 0x58, 0x2d, 0x2f, 0xd3, 0xbd, + 0x90, 0x6a, 0x7c, 0xb1, 0xd6, 0x50, 0x36, 0x8f, 0x6a, 0x80, 0x2e, 0x40, 0x0a, 0xab, 0x6e, + 0x4a, 0xc6, 0xe5, 0xd7, 0xe7, 0x1e, 0x8a, 0xf0, 0x51, 0xe9, 0xe6, 0xdc, 0x8b, 0xd0, 0xad, + 0xf7, 0xe1, 0x69, 0x95, 0x14, 0xc4, 0xa1, 0x04, 0x0c, 0xd1, 0x91, 0x8a, 0x3c, 0x0d, 0x28, + 0xff, 0x97, 0x65, 0xec, 0xd2, 0x90, 0x8b, 0xbe, 0xe2, 0x6c, 0xfe, 0xa8, 0x9b, 0x0f, 0x9e, + 0xe2, 0xba, 0x5a, 0xcd, 0x05, 0x75, 0x0f, 0xc8, 0x6a, 0x86, 0x78, 0xfe, 0x0f, 0x43, 0x8f, + 0x0e, 0xf4, 0xa8, 0x12, 0xe7, 0x30, 0x63, 0xe0, 0x87, 0xa3, 0xa9, 0x29, 0x6e, 0x9d, 0xab, + 0xaf, 0x40, 0xe3, 0x5d, 0x39, 0xa0, 0x9a, 0x83, 0xc8, 0x53, 0xb1, 0xc2, 0xe3, 0xdf, 0xa4, + 0x78, 0x9b, 0xfa, 0x43, 0xf7, 0xc8, 0xf7, 0xd5, 0xad, 0xf7, 0xda, 0x29, 0x7c, 0x4b, 0xf3, + 0xf0, 0xfb, 0x5d, 0x2a, 0x64, 0xab, 0x04, 0xd1, 0xfb, 0x0a, 0xa5, 0x75, 0xbd, 0xb7, 0xdd, + 0xf5, 0x50, 0xb0, 0xab, 0x4d, 0xe0, 0x97, 0xf1, 0x9f, 0x02, 0xdb, 0x52, 0xba, 0x23, 0xb5, + 0x71, 0xd7, 0xf1, 0x2f, 0xf6, 0xd2, 0xfd, 0xe8, 0x00, 0x8b, 0x17, 0x9f, 0x59, 0x46, 0x0f, + 0xa2, 0xc7, 0x77, 0xf9, 0xcc, 0x83, 0x0d, 0x3d, 0x6f, 0x27, 0x81, 0x19, 0xe4, 0x04, 0xfc, + 0xa8, 0x4a, 0xfd, 0x2e, 0xb1, 0xb6, 0x03, 0x6d, 0x4b, 0x33, 0xb7, 0x52, 0x15, 0xc7, 0x9a, + 0xe1, 0x02, 0x41, 0xb0, 0x55, 0x6b, 0xb2, 0x6b, 0xed, 0xde, 0xc7, 0xbb, 0xcb, 0x49, 0x98, + 0x4b, 0xe8, 0x0b, 0x95, 0x27, 0x44, 0xc1, 0xc4, 0x1d, 0xa2, 0x71, 0xa7, 0xba, 0xf3, 0xef, + 0x84, 0x0d, 0xb9, 0x9a, 0xbf, 0xb8, 0x4b, 0xe3, 0xe4, 0xf3, 0x3c, 0x49, 0xc6, 0x79, 0x41, + 0xf0, 0x34, 0x78, 0x8b, 0xb2, 0x58, 0x2c, 0x52, 0xc4, 0x7e, 0xad, 0x89, 0xc6, 0x99, 0x71, + 0xf7, 0xe7, 0xac, 0xac, 0x53, 0xf7, 0x08, 0x0c, 0xc4, 0x45, 0x67, 0x15, 0x2b, 0xf2, 0x79, + 0x89, 0x2f, 0x52, 0x57, 0xac, 0xff, 0x97, 0x9f, 0x43, 0xca, 0x0a, 0x99, 0xd2, 0x28, 0x91, + 0xac, 0x28, 0xbe, 0x7f, 0x75, 0x01, 0x18, 0xa1, 0xdc, 0xc9, 0x8d, 0x1c, 0x87, 0xd8, 0x52, + 0x73, 0x36, 0x08, 0x5d, 0xca, 0xd5, 0xe2, 0x58, 0x3e, 0xbd, 0xa4, 0xb1, 0x0b, 0xb0, 0xec, + 0xae, 0x86, 0x81, 0x09, 0x7a, 0x0b, 0x83, 0xba, 0x8f, 0x3c, 0x41, 0x3e, 0x1c, 0xde, 0x0b, + 0xcc, 0x7d, 0x79, 0x2d, 0xcb, 0xa8, 0x97, 0xbe, 0x5e, 0x7a, 0x31, 0xa4, 0xa6, 0x56, 0x84, + 0x3c, 0xe0, 0x8d, 0x6e, 0x0e, 0x6e, 0x14, 0x88, 0xd6, 0xea, 0x30, 0xab, 0x48, 0x84, 0xc4, + 0xfa, 0x05, 0x35, 0x32, 0x1a, 0xbc, 0xcb, 0xa9, 0x09, 0x66, 0xfe, 0x61, 0x31, 0xd4, 0x22, + 0xb0, 0xdd, 0x31, 0x06, 0x84, 0x36, 0xaf, 0x74, 0x83, 0xa8, 0x65, 0x46, 0xde, 0xc2, 0xdd, + 0xd0, 0x26, 0xeb, 0x71, 0x95, 0x70, 0x6f, 0xc5, 0xcc, 0x0e, 0xc5, 0x3e, 0xd4, 0x0c, 0xad, + 0xbf, 0xe3, 0xf6, 0xe7, 0xc4, 0xee, 0xc7, 0x13, 0x27, 0xce, 0xdb, 0x7a, 0xab, 0x18, 0x77, + 0x02, 0x00, 0x14, 0x87, 0xe0, 0x94, 0x5b, 0xc1, 0xe8, 0xdc, 0xec, 0xf8, 0x20, 0x75, 0xad, + 0x87, 0x1a, 0x0b, 0xfa, 0x2f, 0x06, 0x55, 0xc2, 0xc2, 0xf7, 0xb9, 0x6c, 0x28, 0x49, 0x29, + 0xfd, 0x4c, 0xbf, 0x92, 0x77, 0x6a, 0x55, 0x99, 0x93, 0x18, 0x45, 0xdd, 0x24, 0xe3, 0xbe, + 0x6a, 0xaa, 0xc2, 0x3c, 0xdb, 0x93, 0xc0, 0x23, 0x56, 0xed, 0xfd, 0xb2, 0xe6, 0x4f, 0x0c, + 0x1d, 0xb9, 0xee, 0x97, 0xd0, 0x1b, 0xe1, 0xa1, 0x4b, 0x93, 0x3c, 0xd9, 0x56, 0x4d, 0xd6, + 0xb7, 0x20, 0x92, 0x7b, 0x15, 0x3a, 0x30, 0xf2, 0x69, 0x43, 0x86, 0x4c, 0x8d, 0x11, 0xab, + 0xc7, 0x8a, 0xe4, 0x66, 0x3d, 0xe3, 0x88, 0xe0, 0x4d, 0x53, 0x11, 0xdf, 0x73, 0x63, 0xc0, + 0xa9, 0x84, 0xf0, 0x03, 0xca, 0x97, 0x1d, 0x3f, 0xd0, 0x61, 0x29, 0x43, 0x07, 0x57, 0xbb, + 0x69, 0x21, 0x40, 0x82, 0x71, 0x58, 0xd9, 0x41, 0x8a, 0x56, 0xb3, 0x41, 0xd3, 0x9a, 0xf7, + 0x9a, 0x6c, 0x41, 0x9b, 0xc7, 0x84, 0x3a, 0xf1, 0xf9, 0x10, 0xb4, 0x61, 0x9d, 0xd2, 0x30, + 0xcc, 0x48, 0xde, 0x23, 0x22, 0xed, 0x85, 0x65, 0x0c, 0x08, 0x78, 0x24, 0x85, 0x07, 0x43, + 0x9c, 0xda, 0x2b, 0x34, 0xbd, 0x3f, 0xe3, 0x25, 0x22, 0x91, 0xf1, 0x20, 0x35, 0xb0, 0x65, + 0x10, 0xda, 0xae, 0x28, 0x4d, 0x10, 0xea, 0x90, 0x0b, 0x60, 0x64, 0xf4, 0xf6, 0x7f, 0x08, + 0xd8, 0x14, 0x81, 0x19, 0x88, 0xc5, 0x50, 0x6a, 0x08, 0x5b, 0x60, 0x05, 0x9d, 0x11, 0x9c, + 0x1d, 0x5f, 0x55, 0x84, 0x79, 0xcf, 0x9f, 0x39, 0x6b, 0xde, 0x72, 0x58, 0x20, 0x9d, 0x4f, + 0x59, 0x63, 0x2d, 0xe4, 0x8b, 0x53, 0x69, 0x4a, 0xab, 0x1f, 0x6d, 0xc5, 0x7c, 0xb9, 0x07, + 0x00, 0x93, 0xa0, 0xf3, 0x3f, 0x88, 0x35, 0xc2, 0xbe, 0x26, 0x53, 0x3d, 0xf4, 0x56, 0x41, + 0x9d, 0x1f, 0xde, 0xde, 0x51, 0xcf, 0xc7, 0x86, 0x66, 0x61, 0x41, 0x90, 0x1d, 0x71, 0x37, + 0x07, 0x6d, 0x30, 0xfd, 0x29, 0xc2, 0x1c, 0x0f, 0xc8, 0x6a, 0x04, 0x26, 0x4a, 0x3a, 0x68, + 0x7a, 0x13, 0x76, 0xcf, 0x11, 0x94, 0x30, 0xdd, 0xcf, 0x7a, 0x62, 0xd6, 0x3d, 0x38, 0x29, + 0x62, 0xb5, 0x7b, 0x16, 0x1d, 0x91, 0xce, 0x24, 0xa9, 0x0e, 0x54, 0x91, 0x70, 0x6e, 0x03, + 0x33, 0x5f, 0x07, 0x0d, 0x1d, 0x48, 0xa6, 0x21, 0x6f, 0xf4, 0x4c, 0x6f, 0xed, 0x05, 0xfe, + 0x51, 0x3e, 0x87, 0x1b, 0xfe, 0x96, 0x08, 0xff, 0x73, 0x2b, 0xa5, 0x22, 0x4d, 0x90, 0x3b, + 0x2f, 0xa0, 0xca, 0xdb, 0x20, 0x43, 0x0c, 0xeb, 0x94, 0x8b, 0x3e, 0x6f, 0x56, 0x18, 0xe1, + 0xa4, 0xde, 0xe0, 0x94, 0xea, 0x22, 0xe7, 0x0c, 0x25, 0xed, 0x1b, 0x70, 0xb3, 0x50, 0x90, + 0x54, 0xc3, 0xe5, 0x0e, 0x8e, 0xbb, 0xd1, 0xed, 0xa5, 0xc6, 0xd9, 0x80, 0x20, 0x5c, 0x27, + 0xfa, 0x16, 0xe9, 0x94, 0xe9, 0xaf, 0xf5, 0xba, 0xc3, 0x98, 0x3a, 0x05, 0x9c, 0x9f, 0x30, + 0x9a, 0x13, 0x5a, 0x58, 0xd9, 0xda, 0x57, 0x55, 0x8c, 0xcd, 0x7c, 0xac, 0xa6, 0x6e, 0x47, + 0x25, 0xaa, 0xb9, 0xb0, 0xeb, 0x7e, 0xd1, 0xdf, 0x03, 0x7a, 0x5e, 0x3f, 0x32, 0xf3, 0x95, + 0xd5, 0x51, 0x36, 0xab, 0x0e, 0x25, 0xfc, 0x10, 0x55, 0xc1, 0x58, 0xe2, 0x2f, 0xa3, 0x9f, + 0x2e, 0xbf, 0x9a, 0x70, 0x37, 0x00, 0x31, 0xc2, 0x31, 0xce, 0x21, 0x96, 0xf7, 0xb2, 0x02, + 0x40, 0x2d, 0x61, 0x38, 0xf4, 0xba, 0xdf, 0xee, 0x17, 0xfd, 0xf6, 0x97, 0x4b, 0x94, 0x4b, + 0x46, 0xf2, 0x77, 0x5a, 0xc6, 0xe2, 0x08, 0xf7, 0x03, 0x13, 0xa5, 0xe7, 0x86, 0xe6, 0xcd, + 0x8c, 0x00, 0xe9, 0xf4, 0x4c, 0x16, 0x79, 0x73, 0x41, 0xcd, 0x40, 0x0b, 0x38, 0x25, 0xe3, + 0x33, 0xc2, 0xda, 0x64, 0x29, 0x07, 0xd4, 0x41, 0xd3, 0x15, 0xb8, 0x16, 0x97, 0x13, 0x13, + 0xf0, 0xdf, 0x9d, 0x25, 0x2f, 0x7e, 0xb2, 0xd2, 0xe0, 0x90, 0xb7, 0x18, 0xa3, 0x6d, 0x23, + 0xe4, 0x25, 0xd0, 0x1f, 0x2c, 0x5f, 0x00, 0xd2, 0x2a, 0xf0, 0x97, 0x46, 0xbb, 0x92, 0xba, + 0xcd, 0x86, 0x05, 0x6e, 0xd7, 0x3e, 0x19, 0xa0, 0xce, 0x42, 0x12, 0x25, 0x2f, 0x58, 0xde, + 0x94, 0x0c, 0x04, 0x16, 0x84, 0x14, 0x27, 0xb4, 0x40, 0xb9, 0x78, 0xf1, 0x5e, 0x04, 0xa1, + 0x61, 0x3c, 0xf1, 0xbe, 0xe3, 0x6b, 0x49, 0x3e, 0x66, 0x84, 0x5f, 0xba, 0x10, 0xfe, 0x29, + 0x55, 0xd5, 0x80, 0x36, 0x8f, 0x8a, 0x44, 0x32, 0xa7, 0x98, 0x48, 0x61, 0x3f, 0x72, 0x7e, + 0xac, 0xd2, 0x1e, 0xc1, 0x90, 0xdf, 0x21, 0x95, 0x2a, 0x29, 0xaf, 0x8b, 0xde, 0x96, 0x60, + 0x6d, 0x64, 0xca, 0x99, 0x4c, 0x80, 0x22, 0x4c, 0x7d, 0x4b, 0xe7, 0xe0, 0xe7, 0xff, 0xcf, + 0x51, 0x60, 0xa7, 0x3f, 0xfd, 0xd9, 0xbf, 0xe8, 0x70, 0xb9, 0xed, 0x06, 0xd4, 0xec, 0x8a, + 0xc6, 0x28, 0xd5, 0x7d, 0x5a, 0xe4, 0x04, 0x7e, 0xc0, 0x83, 0xaf, 0xaa, 0x62, 0x69, 0xe9, + 0x80, 0xbb, 0x59, 0xb2, 0xe9, 0x62, 0x4d, 0x87, 0x49, 0xc8, 0xe8, 0xfb, 0xb3, 0x28, 0xe5, + 0x10, 0x9c, 0xb5, 0xdc, 0xe5, 0xec, 0x62, 0x75, 0x2f, 0x40, 0xe5, 0xd5, 0x23, 0x41, 0x0a, + 0x5e, 0x73, 0xa9, 0x48, 0xe5, 0x6d, 0xce, 0x40, 0xf4, 0x69, 0xde, 0xf9, 0xde, 0x85, 0x49, + 0x3e, 0xff, 0x4a, 0x0f, 0xad, 0x7a, 0x04, 0x3a, 0xdc, 0xfc, 0x17, 0xbc, 0xa9, 0x53, 0x2c, + 0x53, 0x66, 0xc1, 0x85, 0x65, 0xe7, 0xde, 0x1a, 0x21, 0xcf, 0xac, 0x2e, 0x6b, 0xac, 0x74, + 0x1d, 0x55, 0x1a, 0xe5, 0x1f, 0x11, 0x79, 0x00, 0x60, 0x93, 0xaf, 0xc8, 0x1c, 0x18, 0x3c, + 0xc0, 0x0b, 0x97, 0x12, 0x34, 0xf7, 0xfa, 0xd9, 0x8a, 0x49, 0xd6, 0xf4, 0xee, 0x75, 0x8d, + 0x5c, 0x66, 0xa2, 0xe1, 0x07, 0x1b, 0xda, 0x70, 0xa8, 0xd6, 0x3e, 0x9f, 0xa7, 0xa2, 0x14, + 0xa1, 0xd5, 0x45, 0xaa, 0x0c, 0xb2, 0x5f, 0x64, 0xd6, 0x04, 0x0c, 0xc8, 0xa5, 0x89, 0xf6, + 0xed, 0xbc, 0x10, 0xb5, 0xaf, 0xf7, 0x39, 0xdd, 0xe8, 0xf4, 0xab, 0x67, 0xcf, 0xd7, 0x69, + 0x32, 0xea, 0x96, 0xc7, 0x38, 0x43, 0x8c, 0xec, 0xf2, 0x8a, 0x84, 0x88, 0xa9, 0xd8, 0x67, + 0x05, 0x51, 0x4e, 0xdf, 0x80, 0x74, 0x38, 0xcf, 0x24, 0x37, 0xa9, 0x9d, 0x11, 0xdd, 0x04, + 0xd4, 0xf0, 0x2c, 0x7a, 0x31, 0x78, 0x1b, 0xe9, 0x92, 0x90, 0x35, 0x25, 0x75, 0xa7, 0x8c, + 0x6a, 0x26, 0x45, 0xfd, 0xaf, 0x8a, 0x1f, 0xc1, 0x1f, 0x61, 0x32, 0x31, 0xf0, 0x4c, 0xfc, + 0x1f, 0x8c, 0xc5, 0xee, 0x81, 0xaf, 0xc3, 0x86, 0x9b, 0x82, 0xa6, 0x1d, 0x8f, 0xa8, 0xc1, + 0x0c, 0x2d, 0xdd, 0x21, 0x86, 0x68, 0xe6, 0x66, 0xcf, 0x65, 0x00, 0x73, 0x11, 0xf0, 0xe1, + 0xab, 0xcc, 0x20, 0xab, 0x6f, 0x68, 0x41, 0xfa, 0x00, 0xed, 0xf6, 0xaa, 0x9f, 0xcb, 0x96, + 0x24, 0x52, 0xeb, 0x65, 0x27, 0xcb, 0x53, 0xf8, 0x06, 0xff, 0x30, 0x9e, 0x59, 0xe0, 0x38, + 0x46, 0x38, 0x7c, 0x22, 0xda, 0x05, 0x25, 0x2e, 0xda, 0xfc, 0x21, 0x87, 0x6f, 0x83, 0x35, + 0x2d, 0x90, 0x93, 0x1c, 0xaf, 0xf3, 0x16, 0x92, 0xa5, 0x6e, 0x0d, 0xdb, 0xdc, 0xf6, 0x4e, + 0x22, 0x34, 0xa2, 0xa7, 0xc5, 0xda, 0x31, 0xac, 0x49, 0x75, 0x52, 0x59, 0x4e, 0xdd, 0x11, + 0xd9, 0x8e, 0x33, 0x76, 0x13, 0xad, 0xfb, 0x19, 0x18, 0x0e, 0xb7, 0x31, 0x2a, 0xe2, 0x31, + 0xc3, 0x6a, 0x4f, 0x2e, 0x10, 0x92, 0x28, 0xa5, 0xd3, 0x11, 0x6e, 0x65, 0xe7, 0x20, 0x49, + 0x51, 0x61, 0xbd, 0x42, 0x3e, 0xc6, 0x90, 0xad, 0xa4, 0x5e, 0xf1, 0x76, 0x22, 0xc3, 0x58, + 0xac, 0xaa, 0x22, 0x7a, 0x0c, 0x32, 0x44, 0x9d, 0x75, 0xfd, 0x7b, 0xa5, 0xfa, 0xd9, 0xc7, + 0x19, 0xf7, 0x93, 0x2e, 0x41, 0x45, 0x63, 0x43, 0x58, 0x75, 0x73, 0xc2, 0x7d, 0xfd, 0xd3, + 0x3b, 0x2d, 0x0e, 0x4a, 0xce, 0x88, 0x18, 0x17, 0xd2, 0x6c, 0xa0, 0xb8, 0xbb, 0xf8, 0x34, + 0x02, 0x8f, 0x79, 0xe8, 0xa8, 0xfe, 0x7c, 0x81, 0x17, 0x08, 0xe0, 0xbe, 0x6b, 0x4b, 0xd1, + 0x2b, 0x5c, 0x15, 0xd4, 0x11, 0x76, 0x43, 0xc3, 0xa6, 0x06, 0x2a, 0x10, 0x8b, 0x01, 0xc2, + 0x2e, 0x0b, 0xe4, 0xe8, 0xe3, 0x0d, 0xbd, 0x7e, 0xc6, 0x76, 0x91, 0x05, 0xf8, 0xfb, 0x3c, + 0x5d, 0x03, 0xb0, 0x54, 0x93, 0xb7, 0xc8, 0xad, 0x94, 0xa9, 0x1c, 0x0a, 0xec, 0x68, 0x7b, + 0xca, 0xba, 0xda, 0x88, 0xb7, 0x6a, 0xc3, 0x89, 0x0d, 0x44, 0x93, 0xfe, 0x6e, 0xb2, 0xe5, + 0x15, 0xa0, 0x6a, 0x5f, 0x60, 0x6c, 0x97, 0x20, 0x01, 0x19, 0xa1, 0x78, 0x51, 0x1c, 0xa2, + 0x65, 0x7e, 0x7c, 0x7a, 0xfe, 0x62, 0x7d, 0x2d, 0x8c, 0x87, 0x02, 0x6b, 0x1b, 0xbb, 0x4f, + 0x3e, 0x62, 0x90, 0x4d, 0x77, 0x6f, 0x50, 0xb8, 0x38, 0x78, 0x67, 0xfc, 0x72, 0x35, 0x05, + 0x2b, 0x06, 0x44, 0xa3, 0xe8, 0x3a, 0x07, 0xbe, 0xf1, 0xb4, 0x3a, 0x1b, 0x87, 0x18, 0x44, + 0x84, 0xb5, 0x68, 0x80, 0xf6, 0xde, 0x13, 0xf4, 0xba, 0x77, 0xb0, 0x5b, 0xfd, 0xb2, 0x22, + 0xb4, 0x48, 0x28, 0xf3, 0xcd, 0x7f, 0x52, 0xec, 0x47, 0xdb, 0x13, 0xe4, 0x70, 0x1f, 0x02, + 0x4d, 0x10, 0x2a, 0x9f, 0x6c, 0xa3, 0x8e, 0x5b, 0x46, 0x1d, 0xdf, 0x7b, 0x5d, 0x4b, 0x71, + 0x32, 0x1d, 0xd1, 0x99, 0x33, 0xdd, 0x70, 0xb2, 0x77, 0x71, 0x00, 0x1e, 0x76, 0xd1, 0x8f, + 0x9f, 0xa4, 0xf4, 0xfd, 0x38, 0x9d, 0x64, 0xa9, 0x54, 0xd2, 0x30, 0x03, 0x31, 0x47, 0xaf, + 0x17, 0xc9, 0x7f, 0x31, 0x58, 0xd8, 0x3f, 0x0a, 0x56, 0x9e, 0xa4, 0xe1, 0x58, 0x82, 0xc7, + 0x6f, 0x67, 0x10, 0x77, 0xf8, 0x59, 0x93, 0x45, 0x09, 0x58, 0xfc, 0x94, 0xe1, 0xd7, 0xca, + 0x3e, 0xd9, 0x46, 0x7b, 0x6b, 0x96, 0x9e, 0x67, 0x37, 0x5c, 0xfb, 0xc0, 0x0d, 0x07, 0xfe, + 0x03, 0x92, 0xce, 0x87, 0x19, 0x34, 0x6b, 0x50, 0xec, 0xa1, 0x1d, 0x5c, 0x73, 0xdf, 0x28, + 0x04, 0x47, 0xdc, 0xfb, 0x67, 0xa7, 0x49, 0xf9, 0xbc, 0x72, 0x34, 0x55, 0x0e, 0xa4, 0x11, + 0x9f, 0x86, 0x57, 0x8e, 0xcc, 0x1e, 0xcd, 0xcd, 0xa1, 0xa6, 0x87, 0x20, 0xf7, 0xfd, 0xef, + 0x18, 0x1d, 0xb4, 0x54, 0x88, 0xb0, 0xe9, 0xfb, 0xda, 0xa7, 0x61, 0xb4, 0x32, 0x36, 0xda, + 0x53, 0xda, 0xa4, 0xeb, 0xde, 0xca, 0x1f, 0x3c, 0xbc, 0x9f, 0x3e, 0x61, 0x07, 0x2d, 0x30, + 0x99, 0x41, 0xc2, 0x67, 0x1e, 0x80, 0x57, 0xbb, 0x89, 0x23, 0x47, 0xf6, 0x8b, 0x40, 0x2d, + 0x01, 0x4e, 0x03, 0x48, 0xf1, 0xd3, 0x4d, 0xa0, 0xbc, 0x91, 0xf0, 0x43, 0x51, 0xe6, 0x5b, + 0x99, 0x1f, 0xd8, 0x72, 0x2c, 0xf9, 0x5d, 0xa1, 0xbc, 0x63, 0x8d, 0x2c, 0x13, 0xb8, 0x9f, + 0x47, 0x09, 0x3c, 0xf0, 0xae, 0xad, 0xbf, 0xc1, 0x88, 0x7e, 0x32, 0xd3, 0x74, 0x7f, 0x5c, + 0xe7, 0xb9, 0x3e, 0xaf, 0x08, 0x62, 0xd0, 0xed, 0x60, 0x9c, 0xdd, 0x49, 0x5b, 0x22, 0xde, + 0x53, 0x05, 0xd1, 0x33, 0x97, 0x98, 0x73, 0x43, 0x2e, 0x34, 0xf1, 0xcf, 0xa0, 0x98, 0x5a, + 0x14, 0xeb, 0xa0, 0xad, 0xb7, 0xb3, 0x36, 0xb9, 0x1a, 0xa7, 0x98, 0x0e, 0x13, 0xa8, 0x22, + 0xc0, 0xfe, 0xc0, 0x20, 0xd0, 0x11, 0x8d, 0x58, 0x2d, 0xff, 0x15, 0x21, 0x61, 0x6a, 0xc5, + 0xd0, 0x9d, 0x31, 0x89, 0x0a, 0xd0, 0x44, 0xf2, 0x5f, 0x3f, 0x6d, 0x9e, 0xc5, 0xc8, 0x3c, + 0x36, 0x51, 0x5c, 0x46, 0x1c, 0xf3, 0x7e, 0x2b, 0xdc, 0xbe, 0xee, 0x70, 0xe5, 0x66, 0xaf, + 0x1a, 0xbd, 0xe4, 0x3b, 0x44, 0x1c, 0x8c, 0xc1, 0xd0, 0x68, 0x53, 0xf4, 0xb8, 0x81, 0x93, + 0xe3, 0x52, 0xff, 0xaf, 0x2c, 0xc7, 0xab, 0x1c, 0xba, 0x22, 0x36, 0xba, 0x02, 0x95, 0x91, + 0x90, 0x3e, 0xa6, 0x1f, 0x86, 0xce, 0xe1, 0x43, 0x90, 0x0d, 0xe0, 0xa8, 0xf3, 0xe2, 0x82, + 0x48, 0x51, 0x96, 0x71, 0x09, 0xe8, 0x79, 0x61, 0x6e, 0x1d, 0xd6, 0x19, 0x19, 0x70, 0xdf, + 0x0a, 0x97, 0x43, 0xcf, 0x27, 0xe0, 0x57, 0x43, 0xb2, 0x89, 0xbe, 0xa6, 0x59, 0xd7, 0x3c, + 0x50, 0xa5, 0xb0, 0x44, 0xf7, 0xfc, 0x53, 0xd3, 0xa9, 0x57, 0xc1, 0x95, 0x44, 0x0d, 0x0d, + 0x19, 0xb2, 0x01, 0xe4, 0xad, 0x06, 0xbb, 0xc7, 0xfa, 0x04, 0xad, 0xd4, 0x52, 0xdf, 0x0c, + 0xb5, 0xf7, 0x89, 0x50, 0xa9, 0xe9, 0x57, 0x69, 0x1d, 0xd2, 0x17, 0xf9, 0xbf, 0x3e, 0xd1, + 0x08, 0x8e, 0xae, 0x03, 0x2a, 0x4d, 0xf3, 0xee, 0xa1, 0xa1, 0x8f, 0x65, 0x62, 0x42, 0x28, + 0xa3, 0x9c, 0xd9, 0x37, 0x96, 0x8b, 0x2c, 0x30, 0x98, 0xcf, 0xc8, 0x34, 0xdd, 0x03, 0xcd, + 0x48, 0x4b, 0x39, 0x16, 0xe4, 0xfb, 0x9a, 0x01, 0xc3, 0x0e, 0x77, 0xbc, 0x7a, 0x84, 0x5b, + 0xff, 0x25, 0x45, 0x63, 0x28, 0x28, 0x9b, 0x7b, 0x3a, 0x5a, 0x81, 0x0f, 0x56, 0x8d, 0xe7, + 0xe8, 0x00, 0xc6, 0x0e, 0x09, 0x29, 0xfb, 0x96, 0x1f, 0xee, 0xae, 0x3b, 0xaf, 0x58, 0xee, + 0x5e, 0x75, 0x4f, 0xdb, 0x7d, 0x8a, 0x9b, 0x65, 0xbb, 0xc4, 0xb6, 0xd6, 0xd2, 0x49, 0xb4, + 0x9c, 0x74, 0x64, 0x36, 0x07, 0x49, 0x0b, 0x0d, 0xb2, 0xe4, 0x26, 0xe3, 0xf2, 0x3a, 0x30, + 0xbd, 0x7f, 0xe8, 0x11, 0x51, 0x1b, 0x78, 0xa4, 0xac, 0xc7, 0x81, 0xf8, 0x8d, 0xb2, 0x17, + 0x23, 0xef, 0xe2, 0x0e, 0x7d, 0x0c, 0x4c, 0x22, 0x19, 0x0c, 0xd4, 0x5a, 0x57, 0x4e, 0xb7, + 0xa7, 0xf9, 0x50, 0xfc, 0x94, 0x74, 0xdc, 0xae, 0x77, 0xdb, 0xb1, 0x89, 0x1c, 0x75, 0xbf, + 0x4e, 0xc8, 0x49, 0x55, 0x65, 0xe3, 0x80, 0xee, 0xa9, 0xc9, 0x00, 0x3b, 0xca, 0xac, 0x28, + 0x54, 0x17, 0xe8, 0x77, 0xb0, 0xb5, 0x77, 0x04, 0x34, 0xd8, 0x41, 0xe0, 0x5a, 0x71, 0x87, + 0x8e, 0x05, 0xc6, 0xcc, 0xe3, 0xda, 0x2b, 0x75, 0x4e, 0xce, 0xa4, 0x70, 0x0c, 0x4a, 0x4e, + 0x18, 0x67, 0xf8, 0x59, 0x4e, 0x89, 0x38, 0xc4, 0x4a, 0x67, 0x7a, 0xc0, 0x1e, 0xb5, 0x0b, + 0xf2, 0x27, 0x18, 0x87, 0x2f, 0x08, 0xa4, 0x3d, 0x56, 0xbd, 0xec, 0xd9, 0x2f, 0x48, 0x39, + 0x3f, 0x4b, 0xf8, 0x69, 0xb6, 0x1f, 0x81, 0xf0, 0x63, 0x6d, 0x69, 0x90, 0xa9, 0x27, 0x60, + 0x29, 0x07, 0x52, 0x0e, 0x12, 0xd5, 0xa7, 0xce, 0x2c, 0x3d, 0x6c, 0x8d, 0x31, 0x7f, 0x7b, + 0xca, 0x0e, 0x9a, 0xb8, 0x0a, 0x6a, 0xec, 0xe8, 0xcd, 0x62, 0x6e, 0x2a, 0x91, 0xf9, 0xee, + 0xad, 0xad, 0xd8, 0xd7, 0x09, 0xb2, 0xce, 0xe1, 0x03, 0x9a, 0x8c, 0xb9, 0x11, 0x5d, 0x37, + 0xee, 0x41, 0x63, 0x0c, 0x37, 0x00, 0x6c, 0x2e, 0xb2, 0x3c, 0x4c, 0x22, 0x9c, 0x28, 0x9c, + 0x50, 0xf7, 0x2f, 0x94, 0x8c, 0xea, 0xb0, 0xb7, 0x7c, 0x85, 0x81, 0xf2, 0x6f, 0x34, 0x82, + 0xa6, 0x12, 0x31, 0xc7, 0x72, 0x1d, 0xa5, 0x6c, 0x2c, 0x6c, 0xa0, 0x00, 0x81, 0xc0, 0x8a, + 0xc6, 0xa2, 0x08, 0x36, 0x70, 0x77, 0xa9, 0x26, 0xe8, 0xe7, 0x6b, 0xaf, 0x79, 0x4a, 0x8a, + 0xa2, 0x92, 0xa5, 0x79, 0x99, 0x70, 0xd2, 0x28, 0x2c, 0x2e, 0xc6, 0x15, 0x4a, 0x73, 0xdf, + 0x04, 0xc3, 0xaf, 0xa2, 0xc4, 0xa9, 0xbf, 0xfb, 0x80, 0xb5, 0x38, 0xb5, 0xec, 0x15, 0x9e, + 0x94, 0x0e, 0x9b, 0xdd, 0x22, 0x5a, 0x99, 0x53, 0x58, 0x29, 0x8a, 0x37, 0x74, 0xea, 0x73, + 0x85, 0xe1, 0xe5, 0x63, 0x3a, 0x60, 0x16, 0x71, 0xb3, 0x8c, 0x1e, 0xda, 0x3e, 0x20, 0xfa, + 0x1b, 0x53, 0xeb, 0x8c, 0xa8, 0x82, 0xd4, 0xb9, 0x12, 0x32, 0xa6, 0x14, 0xd0, 0xa2, 0x64, + 0xc2, 0xab, 0x25, 0xb8, 0xc4, 0xd0, 0x79, 0xa2, 0x77, 0xc6, 0x28, 0xd9, 0x90, 0xc1, 0xbb, + 0xf3, 0x51, 0xf5, 0xdd, 0x1d, 0x6c, 0x27, 0x2c, 0xc7, 0xab, 0x75, 0xcb, 0xc8, 0x0a, 0xc7, + 0x20, 0x45, 0x87, 0xdc, 0xdc, 0xed, 0x9c, 0xfc, 0x18, 0xc4, 0x20, 0xc4, 0x75, 0x9d, 0xbf, + 0x2c, 0x0b, 0x44, 0xd9, 0x6c, 0x20, 0x6a, 0x5e, 0xb4, 0xdd, 0x73, 0x5a, 0x0e, 0xf8, 0x17, + 0x2f, 0x7a, 0x2c, 0x0e, 0xe5, 0x9c, 0x97, 0x33, 0x29, 0x23, 0x91, 0x90, 0x64, 0x76, 0x5c, + 0xb2, 0x69, 0x40, 0x1a, 0x8c, 0x93, 0x0d, 0x06, 0xe5, 0x60, 0x49, 0x9e, 0xb5, 0xda, 0xd4, + 0x07, 0x46, 0x21, 0xcf, 0x57, 0xae, 0xc8, 0xde, 0xa6, 0x11, 0xd8, 0x37, 0xca, 0x66, 0x4e, + 0x5c, 0x04, 0x24, 0x42, 0x9b, 0xfb, 0x53, 0x65, 0x26, 0x9f, 0xd1, 0x1b, 0x25, 0xa8, 0x0c, + 0x74, 0x62, 0xd1, 0xee, 0x02, 0xe3, 0xf9, 0xd3, 0xc3, 0x11, 0x31, 0x73, 0x07, 0xbc, 0x3a, + 0xcf, 0x54, 0xce, 0xc2, 0x23, 0xe7, 0x7e, 0x65, 0xf7, 0xc8, 0xc4, 0x13, 0x52, 0x5f, 0xd7, + 0x76, 0x0d, 0x76, 0x09, 0x00, 0x41, 0x26, 0x5e, 0xbf, 0xb5, 0x28, 0x70, 0x33, 0x8d, 0xf0, + 0xb3, 0xf1, 0xa8, 0xfe, 0x04, 0xa2, 0xc9, 0x7a, 0x07, 0x39, 0x71, 0x1d, 0xa2, 0xbd, 0xc3, + 0x9e, 0xc7, 0x42, 0x0b, 0xff, 0x9e, 0x4f, 0x18, 0x34, 0x6c, 0x3f, 0x6d, 0x8e, 0x69, 0x87, + 0xb5, 0xec, 0x25, 0x7d, 0x0f, 0x33, 0xa6, 0xf9, 0x8d, 0xa4, 0x3e, 0x1e, 0x8a, 0x45, 0x5e, + 0xbc, 0x23, 0x94, 0x7a, 0x34, 0xfa, 0x0c, 0x84, 0x0c, 0x4c, 0x0d, 0x12, 0x54, 0x7c, 0xbb, + 0x18, 0xe8, 0xd2, 0xb2, 0x6c, 0x51, 0x2f, 0x6e, 0x7c, 0xeb, 0x23, 0xd3, 0x76, 0x30, 0x83, + 0x42, 0x2d, 0xd9, 0x74, 0x90, 0x49, 0xe9, 0xd1, 0x72, 0xb8, 0xf4, 0x9f, 0x3e, 0x19, 0x41, + 0xe6, 0xea, 0x6d, 0x98, 0xbc, 0x7e, 0x5f, 0x26, 0x43, 0xaf, 0xad, 0xe3, 0x0d, 0x56, 0x47, + 0x5c, 0x3f, 0x3b, 0x4e, 0xd6, 0xa9, 0xb9, 0x5e, 0xf6, 0xc2, 0x94, 0xa9, 0x17, 0x76, 0x15, + 0x5e, 0x80, 0x19, 0xbd, 0x2e, 0xa6, 0x53, 0x02, 0x2f, 0xf9, 0xa5, 0xc8, 0x89, 0xbb, 0xc1, + 0x0b, 0x15, 0xa5, 0x21, 0x14, 0xbc, 0xb7, 0x31, 0xf2, 0x5c, 0xbb, 0x71, 0x2b, 0xb3, 0xea, + 0x3a, 0x35, 0x0b, 0x57, 0xc6, 0x04, 0xc8, 0x07, 0x08, 0x48, 0x70, 0x2e, 0x8b, 0x6c, 0x30, + 0x67, 0x49, 0x89, 0xa4, 0xb5, 0x69, 0xfd, 0x25, 0x5a, 0x1f, 0xe0, 0x39, 0xe7, 0xc4, 0xc1, + 0x5b, 0xd8, 0xac, 0x04, 0xd4, 0x2f, 0x23, 0x2c, 0xcb, 0xd1, 0x46, 0xd5, 0x37, 0x79, 0x37, + 0xb2, 0x63, 0x3e, 0xa7, 0x61, 0x1c, 0xfa, 0x34, 0x50, 0x23, 0xa0, 0x53, 0x39, 0x60, 0x97, + 0x8a, 0xa4, 0x76, 0x86, 0x19, 0x16, 0xb6, 0x56, 0x50, 0x3c, 0x38, 0x9a, 0x79, 0xc4, 0xdf, + 0x57, 0x27, 0xbb, 0x6f, 0x6a, 0x65, 0xa4, 0x33, 0x6b, 0xc7, 0x36, 0xd5, 0x1c, 0xd4, 0x3b, + 0x29, 0x48, 0x37, 0x41, 0xd7, 0x66, 0xaa, 0x15, 0x08, 0x95, 0x61, 0xb0, 0x78, 0xfc, 0x98, + 0xc1, 0xa6, 0xbc, 0xd2, 0x7d, 0x37, 0xf9, 0xb0, 0x08, 0xfe, 0x36, 0xfe, 0x29, 0x60, 0x1b, + 0xe7, 0x4d, 0x6a, 0x02, 0xb6, 0x7c, 0xf4, 0x2c, 0xa9, 0x10, 0x20, 0xc7, 0xd3, 0x21, 0x3f, + 0xe6, 0x4b, 0x01, 0x65, 0xde, 0x20, 0xc7, 0xe4, 0x40, 0x40, 0x4e, 0x75, 0xa1, 0x22, 0x9d, + 0x48, 0x21, 0xe5, 0x9a, 0xed, 0xfd, 0xf9, 0x95, 0x3f, 0x6a, 0xc8, 0x2a, 0x32, 0x60, 0x9b, + 0x97, 0xdb, 0xf0, 0x78, 0x93, 0x96, 0x83, 0x86, 0x84, 0xae, 0x6f, 0x82, 0x58, 0x73, 0x66, + 0xa7, 0xd5, 0xb7, 0x5c, 0x25, 0x5d, 0xaa, 0x64, 0x32, 0x06, 0x47, 0x88, 0x00, 0x03, 0x00, + 0xfd, 0xda, 0xa8, 0xf4, 0xc4, 0xef, 0x99, 0xa4, 0x88, 0x67, 0xa4, 0x65, 0x67, 0x64, 0x26, + 0xa8, 0x62, 0xa1, 0xae, 0x98, 0x5b, 0x71, 0x20, 0x33, 0xb4, 0x18, 0xc0, 0x6d, 0xf3, 0xc3, + 0x0b, 0xf3, 0xf8, 0x5d, 0xd0, 0x2a, 0x68, 0x24, 0xfe, 0x17, 0x48, 0x78, 0xa0, 0x30, 0x9b, + 0x4c, 0xa0, 0xb8, 0x42, 0x29, 0xac, 0x60, 0xc2, 0xea, 0xb6, 0xa5, 0xff, 0x74, 0x01, 0x24, + 0x48, 0xf3, 0x1b, 0xe5, 0x62, 0x0d, 0x5a, 0x8b, 0x69, 0x66, 0x17, 0x52, 0xa7, 0xff, 0xe6, + 0x5f, 0x4b, 0xd3, 0x83, 0x4d, 0x1a, 0x2d, 0x50, 0xa2, 0x13, 0x9a, 0xd0, 0xe4, 0x92, 0xd5, + 0x47, 0xbc, 0x88, 0xb8, 0x30, 0x06, 0x4c, 0xde, 0x13, 0x39, 0x3a, 0xa7, 0x7b, 0x9e, 0x00, + 0x8d, 0xbb, 0x00, 0x4e, 0xf9, 0x5d, 0x5e, 0x84, 0x26, 0x74, 0x2e, 0x59, 0x00, 0x8b, 0x06, + 0x40, 0x12, 0x64, 0x99, 0xc4, 0x9e, 0x1f, 0xac, 0x35, 0x6b, 0xa6, 0x30, 0x44, 0x03, 0x8c, + 0x15, 0xc7, 0x67, 0x7c, 0xa5, 0x02, 0x5d, 0xe8, 0x86, 0xc4, 0x72, 0xe0, 0x2f, 0x05, 0x8c, + 0xbe, 0xda, 0x37, 0x9c, 0x60, 0x20, 0xdc, 0x56, 0x3f, 0xe9, 0xec, 0x9d, 0x63, 0x55, 0xbc, + 0x54, 0xe0, 0x58, 0xbc, 0xae, 0xb2, 0x18, 0x1a, 0xea, 0xc4, 0x23, 0xb6, 0xbb, 0x55, 0x94, + 0xb2, 0x0f, 0xad, 0x8c, 0x98, 0x79, 0x7f, 0xe5, 0xd9, 0xfc, 0x39, 0x91, 0xa3, 0x64, 0x43, + 0x98, 0x8f, 0xb3, 0x03, 0xe1, 0x9b, 0x74, 0x74, 0xaa, 0x32, 0x74, 0x46, 0xd0, 0xd3, 0x62, + 0x56, 0xfa, 0x8a, 0x21, 0x9f, 0xeb, 0x55, 0x3c, 0x07, 0xdf, 0x86, 0x7e, 0x34, 0x6b, 0xb9, + 0xfc, 0xf4, 0x38, 0x53, 0x31, 0xfa, 0xd0, 0x2c, 0x50, 0x6a, 0x2c, 0x74, 0x78, 0x01, 0x41, + 0xeb, 0x93, 0x4b, 0xf3, 0xec, 0xeb, 0xa4, 0x68, 0x67, 0x06, 0x63, 0x3d, 0x35, 0x73, 0x21, + 0x58, 0x76, 0x49, 0xd4, 0x8b, 0xdb, 0x29, 0xe5, 0x32, 0x5b, 0x09, 0xd7, 0x87, 0xc8, 0x12, + 0x03, 0x34, 0xcc, 0x6e, 0xce, 0xfd, 0xfc, 0x45, 0xe3, 0x26, 0xcb, 0x41, 0x75, 0xf0, 0x62, + 0xc1, 0x2b, 0x55, 0xca, 0xf6, 0x40, 0x70, 0x49, 0x0a, 0xb0, 0x53, 0x66, 0xa8, 0x59, 0x16, + 0x99, 0x7d, 0xa0, 0xda, 0x77, 0x24, 0x3a, 0xeb, 0xc6, 0x49, 0x0f, 0xde, 0x46, 0xdb, 0x81, + 0x53, 0x17, 0x1a, 0x0f, 0xed, 0x4e, 0xf8, 0x15, 0x29, 0x90, 0xba, 0x63, 0x8b, 0x2a, 0x41, + 0x1d, 0xf5, 0x7f, 0x4a, 0x26, 0xe9, 0x25, 0xcd, 0xd8, 0x1b, 0x39, 0x5c, 0xa7, 0xc7, 0xd1, + 0xe0, 0x8c, 0x57, 0xd1, 0x23, 0x2f, 0xec, 0x3f, 0x9c, 0x78, 0x0a, 0xc0, 0x53, 0xf2, 0x93, + 0xbb, 0x11, 0x05, 0x29, 0xbd, 0x90, 0x3b, 0x82, 0x63, 0xe4, 0x33, 0x9a, 0x85, 0xbc, 0x9c, + 0xee, 0xb2, 0x7d, 0xd6, 0x01, 0x21, 0xd5, 0x14, 0x35, 0xf2, 0x98, 0x89, 0x7a, 0xe3, 0xce, + 0x23, 0x89, 0xc0, 0xe8, 0xbd, 0x17, 0xed, 0x4b, 0xee, 0xc2, 0xba, 0xe7, 0xba, 0x5f, 0x9b, + 0x04, 0xd8, 0x8e, 0x11, 0x11, 0xab, 0x30, 0xa1, 0x98, 0x2a, 0xb2, 0x64, 0xae, 0xa0, 0xfa, + 0x20, 0x62, 0xa2, 0x75, 0xf8, 0xca, 0xb0, 0x94, 0xc0, 0x3a, 0xe5, 0x77, 0xe4, 0xb8, 0x1e, + 0x47, 0x7d, 0xc8, 0xfb, 0x39, 0x9c, 0x65, 0x0e, 0x43, 0x2e, 0x04, 0x3c, 0x11, 0x68, 0x26, + 0x26, 0x11, 0xe6, 0xa0, 0xde, 0x74, 0x09, 0x04, 0xfc, 0xa2, 0xd6, 0x60, 0x63, 0x2b, 0x57, + 0x16, 0xcf, 0xe4, 0x92, 0xc9, 0x72, 0xf8, 0x43, 0x07, 0x79, 0xe2, 0xdc, 0x01, 0x1e, 0xc3, + 0xea, 0x17, 0x1d, 0x21, 0xd7, 0x15, 0x87, 0xc6, 0x1a, 0x31, 0xd9, 0x23, 0x2a, 0x29, 0xd5, + 0x3a, 0x33, 0x1c, 0x6e, 0xbd, 0xcb, 0xf5, 0xe1, 0x9e, 0x3e, 0x7a, 0x17, 0xeb, 0xf8, 0x54, + 0x31, 0xa0, 0x32, 0x9c, 0x6e, 0x1d, 0x54, 0x96, 0xa7, 0x8c, 0xf3, 0x8f, 0x94, 0x66, 0x73, + 0x55, 0x1d, 0x60, 0x63, 0x6c, 0xa4, 0xe4, 0xad, 0xb1, 0xe3, 0x93, 0xbf, 0xad, 0xd2, 0x7f, + 0xb6, 0x53, 0x03, 0x67, 0x08, 0xe0, 0xcf, 0xa5, 0xd1, 0x1e, 0x19, 0xd5, 0x62, 0x55, 0x23, + 0xad, 0x0a, 0x2a, 0x9c, 0xfe, 0x62, 0x65, 0x93, 0x4d, 0xe6, 0x8a, 0xad, 0xbc, 0xc9, 0x95, + 0x63, 0xbd, 0xdc, 0x91, 0x36, 0xf1, 0x1d, 0x41, 0x69, 0x62, 0x9a, 0x12, 0x1d, 0x17, 0x2f, + 0x09, 0xe2, 0xa7, 0xd2, 0xdf, 0xd2, 0xc4, 0xc4, 0x05, 0xde, 0x39, 0xb7, 0xf3, 0x56, 0x98, + 0x94, 0x89, 0x2e, 0xe4, 0xd8, 0x92, 0x0c, 0xa4, 0xb3, 0xaa, 0x90, 0x3b, 0x4f, 0x82, 0x1f, + 0x46, 0x42, 0x58, 0xee, 0xb3, 0x75, 0x21, 0x49, 0x3b, 0x7a, 0xf3, 0xe0, 0xc6, 0x8b, 0x3a, + 0x98, 0x0b, 0x15, 0x99, 0x31, 0x09, 0xc5, 0x75, 0x18, 0x36, 0x25, 0x69, 0x3c, 0xeb, 0x48, + 0x35, 0x09, 0xbe, 0xdb, 0xd5, 0x47, 0xfe, 0xa1, 0x9d, 0xf7, 0x38, 0xe1, 0x63, 0x0b, 0x34, + 0xca, 0x37, 0x56, 0xb6, 0x7c, 0x49, 0xb0, 0x77, 0x61, 0xf7, 0x3a, 0xc1, 0xe3, 0x6d, 0x41, + 0xed, 0xdf, 0xfb, 0x33, 0x57, 0x90, 0xd5, 0x7e, 0x0c, 0x48, 0x63, 0x1f, 0x56, 0x1e, 0x3d, + 0x7b, 0x1e, 0x49, 0xa4, 0x79, 0x51, 0xa1, 0x76, 0x45, 0x82, 0x23, 0x43, 0x1f, 0x4e, 0xa1, + 0x4d, 0xd0, 0x84, 0x8c, 0x32, 0xaf, 0x6e, 0xd5, 0x67, 0xe9, 0x8a, 0xd5, 0xf9, 0xaa, 0x45, + 0xd8, 0x0f, 0x1f, 0x25, 0xae, 0x47, 0xeb, 0x4c, 0x48, 0x08, 0x3e, 0x63, 0xee, 0x78, 0x3f, + 0xea, 0xdc, 0x3e, 0xb6, 0x5d, 0xcf, 0x2e, 0x2a, 0x9f, 0xd1, 0x43, 0xee, 0x9f, 0xbb, 0x47, + 0x84, 0x21, 0x0a, 0x72, 0xb2, 0xcb, 0x02, 0x95, 0xa7, 0xdb, 0x3b, 0x3c, 0xdf, 0x82, 0x49, + 0xe9, 0x0a, 0x70, 0x11, 0x86, 0x29, 0xaa, 0x62, 0x07, 0xa5, 0x15, 0x31, 0x2e, 0x65, 0xf9, + 0xd9, 0x04, 0xdc, 0xfc, 0x17, 0xa6, 0xd5, 0xd2, 0x89, 0x6c, 0x68, 0x90, 0xd0, 0xdb, 0x83, + 0xd3, 0xb9, 0x5b, 0x3a, 0x2e, 0xb2, 0xfc, 0xe6, 0x7e, 0x36, 0xcf, 0x35, 0xf5, 0x7f, 0xe4, + 0x70, 0x68, 0x1e, 0xb9, 0xd2, 0x1b, 0x36, 0x78, 0xd0, 0x78, 0x61, 0xed, 0x0c, 0xaa, 0xb8, + 0x7d, 0xa9, 0x44, 0x2c, 0x44, 0x37, 0xc6, 0xf7, 0x85, 0x58, 0x4d, 0x9a, 0x3f, 0x63, 0x19, + 0x12, 0xf4, 0x53, 0xcb, 0x5f, 0xe9, 0x99, 0x1c, 0x2f, 0xe9, 0x96, 0x87, 0xbc, 0xb4, 0x80, + 0x8a, 0xd2, 0xa3, 0x65, 0x2d, 0xa4, 0xd5, 0x3c, 0x09, 0xc1, 0x42, 0x7a, 0xce, 0xd5, 0x56, + 0x3c, 0xd8, 0x76, 0x58, 0xca, 0xe3, 0xb6, 0x4e, 0x2c, 0x5f, 0x1a, 0x48, 0x95, 0x88, 0x71, + 0x31, 0x6a, 0xc0, 0x80, 0x1c, 0x6e, 0x59, 0xc5, 0xc0, 0x1f, 0xe3, 0xee, 0x7d, 0xb1, 0x2b, + 0xee, 0x13, 0x70, 0x6f, 0x40, 0x74, 0x7d, 0x73, 0xcb, 0x89, 0x80, 0x13, 0x67, 0x70, 0xc0, + 0x82, 0x42, 0x91, 0xe2, 0x88, 0x9f, 0xf6, 0x4a, 0x52, 0x65, 0x06, 0x28, 0x39, 0x96, 0x6d, + 0xc0, 0xde, 0x1f, 0x8a, 0x22, 0xd1, 0xae, 0x39, 0xe8, 0x29, 0xae, 0x2f, 0xe7, 0x21, 0xdf, + 0x6a, 0xd7, 0x35, 0xb7, 0xa4, 0x3d, 0x97, 0x53, 0xc2, 0x2e, 0xca, 0xa9, 0x66, 0x32, 0xe3, + 0x76, 0x67, 0xd2, 0x9e, 0x61, 0xeb, 0x94, 0xa3, 0xd7, 0x0c, 0x96, 0xdd, 0x01, 0xe9, 0x6e, + 0xdd, 0x67, 0xa6, 0x75, 0x01, 0x97, 0xf6, 0x63, 0x5d, 0x75, 0xbc, 0x33, 0xe9, 0xe8, 0xa6, + 0x17, 0x13, 0x24, 0xb0, 0x93, 0x75, 0x03, 0xc4, 0x54, 0x7d, 0x8b, 0xc3, 0xc4, 0xb8, 0x6a, + 0xd0, 0xb4, 0x83, 0x65, 0x13, 0x11, 0x9d, 0xf2, 0x3f, 0x59, 0x3f, 0x8f, 0x54, 0x4a, 0xf6, + 0x7b, 0x9e, 0x12, 0x03, 0x5f, 0x16, 0xa4, 0x70, 0x80, 0x64, 0xf4, 0xed, 0xa5, 0x68, 0x83, + 0xc5, 0x8c, 0x44, 0x5d, 0xb2, 0x4e, 0x3f, 0x92, 0xf3, 0xa1, 0xa4, 0xc7, 0x60, 0x94, 0xcc, + 0x1b, 0x5c, 0x48, 0xdc, 0x3c, 0x79, 0xf9, 0x06, 0x54, 0xa2, 0x5b, 0xc4, 0xfa, 0xa1, 0x11, + 0xcf, 0x83, 0xc1, 0x25, 0x20, 0x76, 0x1a, 0xea, 0xd3, 0x01, 0xda, 0xc7, 0xe2, 0xa1, 0x1d, + 0x63, 0xf4, 0x0f, 0x04, 0x4d, 0x53, 0x2c, 0x68, 0x3c, 0x58, 0xc2, 0xd6, 0x8a, 0xe3, 0x8b, + 0x3f, 0x39, 0xb4, 0x1e, 0x07, 0x6f, 0xa1, 0x4c, 0x1b, 0xe5, 0xae, 0xcc, 0xbd, 0xdd, 0x36, + 0x4b, 0x82, 0x7c, 0x2f, 0xb6, 0xe0, 0x66, 0x87, 0x24, 0x9c, 0x5e, 0x80, 0xe5, 0x95, 0xab, + 0xf6, 0x59, 0xcd, 0x26, 0xcf, 0x96, 0x6f, 0xcc, 0x12, 0xe3, 0xf3, 0xc3, 0x6c, 0xc4, 0xa0, + 0xcc, 0x73, 0x48, 0x2b, 0x63, 0x41, 0x4e, 0x3d, 0xbf, 0xd9, 0x23, 0xe3, 0x2a, 0x1b, 0xbc, + 0x55, 0x91, 0x90, 0xf9, 0xde, 0x83, 0xad, 0xaa, 0x90, 0x69, 0xe9, 0xcd, 0x08, 0x74, 0xb4, + 0x50, 0x81, 0x2f, 0xe5, 0x5b, 0xa2, 0xc6, 0xe5, 0x5d, 0x4a, 0xe5, 0x87, 0x1d, 0x6d, 0x61, + 0x69, 0xc4, 0x6d, 0xf5, 0x9d, 0x49, 0x36, 0x99, 0x22, 0xf4, 0x18, 0x83, 0x0f, 0x7d, 0x2e, + 0x02, 0x38, 0xbb, 0xb3, 0x34, 0xff, 0xa7, 0x0c, 0xad, 0x13, 0xa9, 0x80, 0xbb, 0x5b, 0x3e, + 0x33, 0x2d, 0xfb, 0x94, 0xf2, 0x25, 0x04, 0x68, 0xef, 0x9c, 0x55, 0x36, 0x9d, 0x2c, 0x0a, + 0x53, 0xfb, 0x08, 0x8a, 0xd6, 0x80, 0x5a, 0x58, 0x54, 0xb9, 0x73, 0xf8, 0x21, 0x3b, 0xfe, + 0x72, 0x02, 0xa2, 0x93, 0xb8, 0x09, 0x08, 0x92, 0x40, 0x0e, 0x0f, 0xda, 0xbf, 0x63, 0x1c, + 0x8b, 0xa1, 0x82, 0x4c, 0x89, 0x98, 0x34, 0x01, 0xa3, 0x04, 0xb5, 0xf6, 0xf4, 0x79, 0xc2, + 0xab, 0xd6, 0x15, 0x09, 0x1c, 0xf4, 0x16, 0x3a, 0x0c, 0xbe, 0xba, 0x73, 0x43, 0x91, 0x24, + 0xfe, 0x0b, 0x16, 0xd6, 0xe4, 0xb2, 0xd4, 0xab, 0xb8, 0xa2, 0xfd, 0xba, 0x61, 0xca, 0xef, + 0xef, 0x33, 0x01, 0x14, 0x0f, 0x08, 0xe0, 0x5e, 0xb4, 0xb0, 0x8c, 0x24, 0xf5, 0xd4, 0x3c, + 0x09, 0x16, 0x3a, 0xee, 0x9f, 0x3b, 0x58, 0xe3, 0x53, 0x1a, 0xd9, 0x60, 0x45, 0xc2, 0x90, + 0x05, 0xae, 0xd8, 0xd6, 0xf2, 0x5d, 0x51, 0x0a, 0x11, 0x37, 0x53, 0x7a, 0x35, 0xa9, 0x65, + 0xa0, 0x36, 0xfe, 0x61, 0x58, 0x06, 0xfa, 0x1b, 0x66, 0x25, 0x6b, 0x64, 0x39, 0xb8, 0x61, + 0x5f, 0x61, 0xd1, 0x02, 0xf7, 0x12, 0x2c, 0x1a, 0x16, 0x1c, 0xd6, 0xd7, 0x1c, 0xd8, 0x02, + 0x44, 0x23, 0xc2, 0x3e, 0xbf, 0x2b, 0x18, 0xb3, 0x8f, 0x94, 0x0e, 0xe0, 0xba, 0x74, 0x01, + 0xbf, 0xb6, 0x71, 0x95, 0x7f, 0x04, 0xf8, 0xa8, 0x6b, 0x39, 0x96, 0x39, 0xf7, 0x6b, 0x47, + 0x39, 0x13, 0xa4, 0x33, 0x12, 0x09, 0x0e, 0x0f, 0xa9, 0x9e, 0xb2, 0x51, 0x5c, 0x94, 0x68, + 0x55, 0x79, 0x34, 0x7d, 0x58, 0x81, 0x06, 0x1e, 0x3e, 0x8c, 0x08, 0x43, 0xaa, 0x16, 0x88, + 0xa0, 0x9d, 0xa1, 0xfc, 0x54, 0xfe, 0x40, 0xdb, 0xdf, 0x25, 0xa2, 0x05, 0x6d, 0xcd, 0xfd, + 0x47, 0xe4, 0xfc, 0x0c, 0x82, 0xe2, 0x87, 0x74, 0x74, 0x90, 0x5f, 0x3d, 0xa2, 0x17, 0x3b, + 0x2b, 0x29, 0x3c, 0x6d, 0x39, 0x87, 0x0c, 0xad, 0x13, 0x20, 0x39, 0x28, 0xdb, 0xcf, 0xde, + 0xcc, 0x03, 0x02, 0xf3, 0xf0, 0xc9, 0x94, 0xe3, 0xd4, 0xff, 0xd8, 0x0b, 0xe5, 0x6a, 0xec, + 0x9e, 0xf5, 0x03, 0x5d, 0xc4, 0x8e, 0x5e, 0x8d, 0x29, 0x2a, 0x94, 0xaf, 0xf6, 0x35, 0x8b, + 0xc5, 0xda, 0x60, 0x1e, 0x67, 0x20, 0x93, 0x38, 0xdd, 0xbc, 0x07, 0x93, 0xff, 0x35, 0x08, + 0x4b, 0x53, 0x71, 0x1d, 0x1b, 0xfd, 0x05, 0xad, 0x17, 0xdd, 0xac, 0xc1, 0xaa, 0x66, 0x9e, + 0x61, 0x78, 0xc7, 0xa1, 0x67, 0x33, 0x09, 0xbe, 0x18, 0x4e, 0xf8, 0xb8, 0x05, 0x32, 0xe2, + 0x52, 0x5a, 0x9b, 0x42, 0xea, 0x6e, 0x2e, 0x01, 0x6a, 0x5b, 0x82, 0xd1, 0xf0, 0xa2, 0xdd, + 0xa2, 0xf8, 0xe8, 0x47, 0xc8, 0x98, 0x67, 0x72, 0xe0, 0x9f, 0x48, 0xb1, 0xa8, 0xd1, 0x50, + 0x93, 0x03, 0xb1, 0x13, 0xb4, 0x69, 0x37, 0xda, 0x39, 0x88, 0x79, 0x6e, 0xfb, 0x96, 0xbc, + 0x5c, 0xc9, 0x1e, 0xa1, 0xc7, 0x28, 0x22, 0x9c, 0xe1, 0x4e, 0x6a, 0x74, 0x4b, 0x52, 0xf7, + 0x7d, 0x4f, 0xdd, 0x76, 0xc7, 0x88, 0xce, 0xa9, 0x8e, 0x6c, 0x16, 0xa1, 0x9d, 0x35, 0x73, + 0xfe, 0xcb, 0x27, 0xc6, 0xbf, 0xdf, 0x94, 0xb5, 0xb3, 0x40, 0x06, 0x11, 0x5d, 0x23, 0x36, + 0x65, 0x05, 0xeb, 0xc1, 0xec, 0xfa, 0xbd, 0x43, 0xf5, 0x71, 0xd6, 0xdc, 0x17, 0xeb, 0x1e, + 0xa4, 0x8f, 0x56, 0x4b, 0x0c, 0xb7, 0x81, 0xbb, 0xa2, 0x84, 0x7c, 0x54, 0xf0, 0xb3, 0x7e, + 0xf0, 0x3a, 0x69, 0xac, 0xe5, 0xca, 0xaf, 0x30, 0x39, 0xb3, 0xe6, 0xdd, 0x0e, 0x13, 0x0b, + 0xf3, 0x7f, 0xc4, 0x35, 0xa0, 0x59, 0xc5, 0xfb, 0xe8, 0xec, 0x0e, 0x26, 0x82, 0x2e, 0x3b, + 0xc2, 0xde, 0xeb, 0x0f, 0xaf, 0x48, 0x04, 0x2e, 0xac, 0xcc, 0x9b, 0xf6, 0x3c, 0xb7, 0xec, + 0xa5, 0x37, 0x0d, 0x4f, 0x94, 0xe1, 0x68, 0x2d, 0xa5, 0x6e, 0x4c, 0x76, 0x21, 0x97, 0x66, + 0x16, 0x3e, 0x79, 0x4e, 0x96, 0x7e, 0x2f, 0x11, 0xcb, 0x8d, 0x2b, 0x40, 0xed, 0xa7, 0x97, + 0xdb, 0x6d, 0xe6, 0x37, 0x8b, 0x25, 0x00, 0xa2, 0x22, 0x81, 0xd7, 0x76, 0x09, 0xf7, 0x17, + 0x3d, 0xb9, 0xec, 0x7b, 0x6a, 0x00, 0x9b, 0x89, 0xb6, 0xf9, 0xb4, 0x58, 0x52, 0x51, 0xd5, + 0xed, 0xa8, 0x3a, 0x5f, 0x94, 0x27, 0x96, 0x87, 0x8d, 0x41, 0xef, 0x7f, 0xdf, 0xd1, 0xd7, + 0xba, 0xb3, 0x00, 0xb1, 0xb3, 0xd8, 0xe2, 0x3a, 0x20, 0x0c, 0xf6, 0x17, 0xfa, 0x60, 0xa0, + 0xb4, 0x55, 0x75, 0x57, 0x69, 0x2e, 0x6d, 0x27, 0x94, 0x31, 0x3d, 0x35, 0x37, 0x05, 0xc0, + 0x50, 0x3a, 0x02, 0x0f, 0xdb, 0x7f, 0x7f, 0x7e, 0xea, 0x8c, 0xda, 0x09, 0x6f, 0x7b, 0xfe, + 0x80, 0x96, 0x85, 0x31, 0xb1, 0xfa, 0x19, 0xe2, 0x91, 0x2a, 0x7c, 0xfa, 0x2c, 0x9c, 0x3e, + 0xea, 0x74, 0x35, 0x9f, 0x0d, 0xe1, 0x34, 0x4f, 0x2a, 0x35, 0x40, 0x1d, 0xb9, 0xb7, 0x2d, + 0x10, 0xfe, 0xfd, 0xf9, 0xa6, 0xbd, 0xe4, 0xa1, 0xf9, 0xbc, 0x4f, 0x01, 0x3c, 0xac, 0x75, + 0xe6, 0x0e, 0xc1, 0x4e, 0xc9, 0x18, 0xcb, 0xd1, 0x69, 0xb8, 0xb4, 0xa2, 0x78, 0xed, 0xb5, + 0x95, 0x72, 0xaa, 0xb2, 0x3a, 0x60, 0xcd, 0x5c, 0xb6, 0xaf, 0x4f, 0x44, 0xae, 0x03, 0xad, + 0xdf, 0x8e, 0x64, 0xa0, 0x26, 0x32, 0xc9, 0xe6, 0x42, 0x9b, 0x10, 0x95, 0x99, 0x69, 0xe8, + 0xe6, 0xa2, 0x72, 0x7c, 0x20, 0x19, 0x4c, 0xbf, 0x4d, 0x1f, 0x82, 0xb7, 0xe1, 0x8e, 0xbf, + 0x25, 0x25, 0x92, 0xc4, 0x55, 0x96, 0xb6, 0xd2, 0xc6, 0xdb, 0x93, 0x2c, 0x6d, 0x4b, 0x8b, + 0x4a, 0x60, 0x96, 0xd9, 0xd5, 0xff, 0xb2, 0x18, 0xbe, 0x91, 0x9a, 0x97, 0x57, 0xea, 0xa0, + 0x86, 0x3b, 0x38, 0x3a, 0xed, 0x41, 0x13, 0xd1, 0x4b, 0xbc, 0x09, 0x1b, 0xb9, 0x16, 0x3b, + 0xaa, 0x67, 0xaf, 0xdf, 0x64, 0x1f, 0xef, 0xd4, 0xd4, 0x14, 0x98, 0xa9, 0x2c, 0x8e, 0xe8, + 0x90, 0x29, 0xd0, 0xe5, 0x3c, 0xa4, 0xfe, 0xa4, 0xc8, 0xdc, 0x03, 0x81, 0x64, 0x4f, 0x6c, + 0xca, 0x82, 0x96, 0xa3, 0x61, 0x1c, 0x3a, 0x0c, 0x82, 0x9e, 0x6c, 0x8b, 0xc2, 0x95, 0xc0, + 0x6a, 0x69, 0xf0, 0xef, 0x93, 0x89, 0x19, 0xfd, 0xa8, 0x36, 0x81, 0x9f, 0xbf, 0x5c, 0xd8, + 0x71, 0x60, 0x55, 0xd9, 0x23, 0xd0, 0x78, 0x80, 0x33, 0xae, 0x87, 0xfa, 0xe1, 0xa6, 0x6e, + 0x19, 0x2a, 0xcf, 0xe3, 0x68, 0x33, 0xde, 0x96, 0x0b, 0x1c, 0x53, 0x9b, 0xd1, 0x1a, 0x38, + 0x95, 0xd5, 0x45, 0xa6, 0xee, 0x64, 0xe9, 0x29, 0x88, 0xc8, 0xc2, 0x23, 0x14, 0x4e, 0xad, + 0xa2, 0xb1, 0xa5, 0xbc, 0x46, 0x86, 0xec, 0xef, 0x3b, 0x28, 0x0e, 0x41, 0x8a, 0xfb, 0xaa, + 0x60, 0x96, 0xe7, 0xe7, 0x60, 0x3b, 0xc8, 0x52, 0x4c, 0xab, 0xbf, 0xe0, 0x88, 0x20, 0x45, + 0x02, 0xdc, 0x35, 0x24, 0x15, 0x8b, 0xb9, 0xa3, 0xf8, 0xa5, 0xb2, 0x49, 0x0a, 0x43, 0xe3, + 0x08, 0xb7, 0xf8, 0x89, 0xb2, 0xd9, 0xc1, 0xd2, 0xc0, 0x61, 0x4c, 0x11, 0xe7, 0x44, 0xb1, + 0xa6, 0xc7, 0x4c, 0x8c, 0x09, 0xe4, 0x40, 0x74, 0x6e, 0xd6, 0x70, 0x3e, 0x7a, 0xa4, 0x37, + 0x6b, 0xcc, 0xab, 0x6b, 0x5d, 0x86, 0x44, 0xf6, 0xfe, 0xd2, 0x4d, 0x40, 0xf0, 0xc0, 0x89, + 0x66, 0x17, 0x2c, 0x8a, 0x43, 0x29, 0xd6, 0x91, 0x69, 0x8f, 0x87, 0x8a, 0xdf, 0xec, 0x2c, + 0xbf, 0x02, 0xc4, 0xe1, 0x26, 0x07, 0x26, 0x34, 0x5d, 0x60, 0x5b, 0x38, 0x0c, 0xaf, 0xa2, + 0xba, 0xe6, 0xd4, 0x42, 0xed, 0x62, 0xe5, 0x51, 0xce, 0xb5, 0x71, 0xb8, 0x9a, 0x20, 0x10, + 0x54, 0x2b, 0x32, 0x08, 0xca, 0x89, 0x67, 0xc9, 0xf9, 0x29, 0x5d, 0x66, 0x18, 0xf7, 0x4b, + 0x5d, 0x9b, 0x7d, 0xae, 0x0c, 0x38, 0x74, 0x0c, 0x15, 0xd4, 0x55, 0x3d, 0x53, 0x9f, 0x05, + 0x4c, 0x7f, 0x59, 0xb8, 0x09, 0x35, 0x49, 0xc4, 0x68, 0xfd, 0x52, 0xdc, 0x2d, 0x9e, 0x1f, + 0x27, 0xa8, 0x72, 0xb4, 0xfc, 0xcf, 0x7e, 0x9c, 0xca, 0xf6, 0x38, 0x2a, 0x75, 0x99, 0x39, + 0xd5, 0x84, 0x34, 0xd7, 0x52, 0x32, 0xb9, 0x19, 0x4a, 0x10, 0xd9, 0xa0, 0x07, 0xd9, 0xd5, + 0xdd, 0xf1, 0x4f, 0xcb, 0x90, 0xdf, 0x97, 0x8f, 0x46, 0x34, 0xc7, 0xa7, 0x9e, 0x0b, 0x24, + 0xef, 0x22, 0x0a, 0xf8, 0xf9, 0x9d, 0xad, 0x73, 0x32, 0x98, 0x42, 0xf4, 0x4f, 0xcc, 0x64, + 0x5d, 0xc2, 0x20, 0x00, 0x81, 0x4c, 0x8c, 0x6c, 0x15, 0xd9, 0x7e, 0x31, 0xa5, 0x5d, 0x26, + 0x74, 0x32, 0xcf, 0xef, 0x2a, 0xc3, 0xc3, 0x03, 0x1c, 0x36, 0xc2, 0xbe, 0x9d, 0x50, 0x81, + 0xed, 0xe5, 0x50, 0xc9, 0x23, 0x85, 0x2e, 0xb6, 0x00, 0x40, 0x9c, 0x84, 0x76, 0xfc, 0x97, + 0x16, 0x8e, 0x84, 0x88, 0x6d, 0x92, 0x3e, 0x0c, 0x2a, 0x90, 0x67, 0x24, 0x8f, 0x09, 0x54, + 0x9c, 0x6e, 0x75, 0x1a, 0x38, 0x79, 0xf5, 0x0c, 0xbf, 0x67, 0xdf, 0x8c, 0x1e, 0xb7, 0x26, + 0x61, 0x14, 0x3e, 0xb4, 0x5d, 0x18, 0xe5, 0x85, 0x59, 0xda, 0xf0, 0x0e, 0xf5, 0x6a, 0xb7, + 0xb9, 0x55, 0x1e, 0x1a, 0x2e, 0x6f, 0x70, 0xc7, 0xec, 0x41, 0xb6, 0x8d, 0xb0, 0xb8, 0x8b, + 0xf2, 0xf8, 0x5e, 0x7c, 0x02, 0xf4, 0xd8, 0x84, 0x33, 0x1f, 0xfe, 0x16, 0xe6, 0xda, 0x96, + 0xc1, 0x33, 0x9d, 0x6e, 0xcc, 0x60, 0xf4, 0x40, 0x03, 0xe1, 0xb9, 0x26, 0x9d, 0x68, 0x7f, + 0xd8, 0xc5, 0x78, 0x63, 0x38, 0xc7, 0xe8, 0x6d, 0xda, 0x72, 0x53, 0x5e, 0x88, 0x20, 0x01, + 0xab, 0x67, 0x82, 0xb0, 0x9c, 0xae, 0x52, 0x55, 0x42, 0xaa, 0xe4, 0x80, 0x02, 0x9e, 0xb9, + 0xc9, 0x2f, 0x64, 0x97, 0x17, 0xb7, 0x75, 0xea, 0x37, 0x3f, 0xcd, 0x78, 0xe0, 0x92, 0x0c, + 0xdc, 0x4e, 0x95, 0xf7, 0xa1, 0x9b, 0x36, 0x53, 0xad, 0x5e, 0xe9, 0xcf, 0xa1, 0x95, 0x8c, + 0x59, 0x8d, 0x62, 0x54, 0xa1, 0x1e, 0x2c, 0x3f, 0x19, 0xc9, 0x45, 0xab, 0x98, 0xd0, 0xfb, + 0xa3, 0x29, 0x31, 0xca, 0xcf, 0xab, 0xa0, 0x1b, 0xb6, 0xab, 0xb6, 0x6e, 0x5d, 0x12, 0x22, + 0xd5, 0x74, 0xe0, 0x7c, 0x2b, 0x1c, 0xf5, 0xdf, 0x00, 0xc7, 0x5a, 0x35, 0x03, 0x7c, 0x14, + 0xec, 0x69, 0x02, 0x20, 0xc7, 0x76, 0x8f, 0x37, 0xb6, 0x0c, 0x84, 0x66, 0xd4, 0x47, 0xf5, + 0xb2, 0x91, 0xb5, 0x70, 0xfe, 0x8f, 0xbb, 0x55, 0xae, 0xe4, 0x83, 0x21, 0xd7, 0xc4, 0xb7, + 0xec, 0x9e, 0x67, 0xb8, 0xd6, 0x45, 0xb3, 0xd4, 0xe8, 0xad, 0x0d, 0xa3, 0x36, 0x36, 0xaf, + 0x06, 0xc9, 0x80, 0x0f, 0x4d, 0x6c, 0x31, 0xcd, 0x58, 0xe3, 0x2c, 0x2f, 0x53, 0xd1, 0xa9, + 0x42, 0xfd, 0xcb, 0x25, 0x57, 0x3e, 0x34, 0x1e, 0x31, 0x59, 0x96, 0xcc, 0xf2, 0x7d, 0x9a, + 0xae, 0x46, 0x36, 0x9c, 0x7e, 0x03, 0x4e, 0xa8, 0x02, 0x94, 0x87, 0x6f, 0x77, 0x8c, 0xfe, + 0xd4, 0x2f, 0xb3, 0x2e, 0x9a, 0xcc, 0x24, 0x17, 0x0b, 0xa3, 0x19, 0x50, 0x7f, 0x48, 0x7d, + 0x15, 0x36, 0x17, 0xb6, 0xf4, 0xde, 0xd8, 0xc9, 0xf3, 0xce, 0x60, 0x81, 0x69, 0xb2, 0xfd, + 0xce, 0x57, 0xe3, 0x33, 0xd7, 0x1a, 0x8e, 0x16, 0xf2, 0xee, 0x7f, 0xa6, 0x41, 0x26, 0x57, + 0xb6, 0xce, 0xa0, 0x10, 0x49, 0xee, 0x63, 0x1e, 0xba, 0x6c, 0xd3, 0x31, 0xc9, 0x8a, 0xe6, + 0xc1, 0x56, 0x4b, 0x01, 0x22, 0xcc, 0x89, 0x89, 0x88, 0xb9, 0xb3, 0xa8, 0xbe, 0x19, 0xdc, + 0x84, 0x33, 0x26, 0x03, 0x2d, 0x0b, 0x7f, 0xfd, 0x3e, 0x85, 0x75, 0x5c, 0x71, 0x54, 0x51, + 0x07, 0x53, 0xe7, 0xfe, 0x99, 0x02, 0x51, 0xa5, 0xf0, 0xb2, 0xb8, 0x3e, 0x67, 0xcd, 0x20, + 0x5d, 0x29, 0xee, 0xc9, 0x2e, 0xe9, 0x7c, 0xb0, 0x48, 0x9f, 0xa9, 0x37, 0x59, 0x07, 0x7c, + 0x85, 0x8c, 0x82, 0xc8, 0xa1, 0x1e, 0x04, 0x89, 0x06, 0xcf, 0xef, 0xcd, 0xd3, 0xc4, 0xad, + 0xdd, 0xff, 0xbb, 0x38, 0x3b, 0xad, 0x4f, 0x7f, 0xc1, 0x2d, 0xa9, 0xd3, 0x2f, 0x2b, 0x58, + 0x21, 0x44, 0xeb, 0x39, 0x74, 0xd9, 0xd9, 0x84, 0x31, 0x39, 0xe6, 0x82, 0xde, 0x06, 0x82, + 0x00, 0xf7, 0xc2, 0xd7, 0x41, 0xda, 0x24, 0x2e, 0xb2, 0xca, 0xd0, 0xa7, 0x66, 0x27, 0xa2, + 0xfa, 0xd5, 0xc7, 0x98, 0xc9, 0x84, 0x24, 0x32, 0x1e, 0x86, 0x10, 0xf0, 0xc1, 0xdc, 0x83, + 0x12, 0x2a, 0x8e, 0xde, 0x5d, 0x7e, 0x2a, 0x63, 0x84, 0x80, 0x66, 0x66, 0xcb, 0x04, 0x07, + 0x79, 0xb0, 0xe8, 0x54, 0x84, 0xf2, 0x44, 0x55, 0xd5, 0x49, 0xad, 0xeb, 0x00, 0x8d, 0xca, + 0x2c, 0x38, 0xa5, 0x30, 0x54, 0xe6, 0x9a, 0xa3, 0x11, 0x39, 0x4a, 0xd3, 0xb3, 0x1e, 0xc3, + 0x34, 0xcc, 0x95, 0x6c, 0x57, 0xe1, 0x1d, 0x26, 0x8b, 0x04, 0xca, 0x4f, 0x98, 0x21, 0xac, + 0xfe, 0xd5, 0x02, 0xdd, 0x49, 0x48, 0x8d, 0xd4, 0xbe, 0x2c, 0xa7, 0x91, 0x1d, 0xd0, 0x54, + 0x64, 0x25, 0x04, 0xd2, 0x26, 0x4c, 0x4f, 0xc5, 0xdb, 0x1a, 0x15, 0x8b, 0x7c, 0x81, 0xe9, + 0xd9, 0xdb, 0x80, 0x1d, 0x1d, 0xee, 0x7d, 0xa0, 0x58, 0x70, 0xcf, 0xcb, 0xe9, 0xdc, 0x5f, + 0x9c, 0x83, 0xe0, 0xe6, 0xb5, 0x0e, 0x7b, 0x55, 0xe5, 0xe2, 0xcb, 0x23, 0x51, 0x42, 0xa4, + 0x18, 0x03, 0x24, 0xbb, 0x98, 0x63, 0xe0, 0xbf, 0x0b, 0xb8, 0x20, 0xfa, 0x93, 0x69, 0x3a, + 0xad, 0xb1, 0x17, 0x6e, 0x3a, 0x30, 0x33, 0x14, 0x67, 0x76, 0x01, 0x3b, 0xec, 0x97, 0x23, + 0x4b, 0x47, 0x23, 0x12, 0x10, 0x0c, 0x53, 0x44, 0xe3, 0xdf, 0x75, 0xbc, 0x54, 0xa7, 0xfa, + 0xf3, 0x79, 0xee, 0x18, 0x94, 0x77, 0x82, 0xc3, 0xbb, 0xfa, 0x7b, 0x2a, 0xd0, 0xd2, 0xec, + 0x46, 0xd9, 0x4a, 0xf0, 0x57, 0xe6, 0x86, 0x33, 0x2c, 0xbc, 0x74, 0x61, 0xb4, 0xc1, 0x12, + 0x28, 0xe6, 0x28, 0xf7, 0xf8, 0x18, 0xe5, 0x00, 0xbb, 0x71, 0x28, 0x71, 0x9d, 0xc0, 0x27, + 0x23, 0x81, 0x61, 0x15, 0x66, 0xd7, 0xc9, 0xc9, 0xfc, 0xb2, 0x7b, 0xd9, 0x89, 0x62, 0x4e, + 0x77, 0x7c, 0xb5, 0xc5, 0x3b, 0xe8, 0xcd, 0x09, 0xf8, 0xee, 0xfe, 0xd6, 0x1c, 0x0b, 0xe0, + 0x70, 0x10, 0xdb, 0x5f, 0xd4, 0x75, 0x25, 0xae, 0x91, 0xb6, 0x03, 0xa3, 0xc6, 0x03, 0x7b, + 0x1e, 0xe7, 0x29, 0xe0, 0xe2, 0xd2, 0x2d, 0xa7, 0xeb, 0x54, 0x18, 0xb2, 0x4a, 0x0e, 0xa0, + 0xa9, 0xba, 0x4e, 0x91, 0x95, 0x1d, 0x8a, 0xaa, 0x35, 0xa1, 0x72, 0x58, 0x99, 0xe5, 0x35, + 0xf7, 0x74, 0x2d, 0x7a, 0xcb, 0x9c, 0xa2, 0x6e, 0xf2, 0x7c, 0xfd, 0xc7, 0x27, 0xd9, 0xe4, + 0x7c, 0x03, 0xa0, 0x87, 0xbf, 0x48, 0xb5, 0xc9, 0x34, 0x8d, 0x76, 0xd1, 0x70, 0xce, 0xb3, + 0x48, 0x21, 0x92, 0xf0, 0xa8, 0x8c, 0x04, 0x66, 0x26, 0x50, 0x7f, 0xce, 0xcc, 0x79, 0x60, + 0x60, 0x1b, 0x56, 0x1b, 0xe8, 0xab, 0xed, 0xaa, 0x87, 0x72, 0xe2, 0x0f, 0x7b, 0xa0, 0xf5, + 0x24, 0x76, 0x90, 0x8b, 0xfc, 0x0b, 0xdf, 0x22, 0x08, 0x03, 0x7d, 0x10, 0x5e, 0x75, 0xc6, + 0x5b, 0x07, 0xdc, 0xba, 0x69, 0x0e, 0x01, 0xc9, 0xcd, 0x43, 0x2e, 0xde, 0xa8, 0x73, 0x19, + 0xb8, 0xbd, 0xf5, 0xb4, 0x00, 0xd1, 0x7c, 0xb0, 0xd4, 0x74, 0x3f, 0x21, 0x74, 0xc1, 0x50, + 0x37, 0xc7, 0xfd, 0x9e, 0x5c, 0xdc, 0xe9, 0x45, 0x86, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0xf0, 0x72, 0x6d, 0xf7, 0x79, 0x95, 0xfe, 0x01, 0x66, 0x40, 0x3b, 0xc7, + 0xf4, 0x51, 0x43, 0x6b, 0x76, 0xa6, 0x8b, 0x1f, 0xa3, 0x04, 0xbe, 0x50, 0x3e, 0x28, 0xbb, + 0xa2, 0x36, 0x35, 0x25, 0x55, 0x22, 0xa4, 0xe8, 0x17, 0x41, 0x25, 0xa3, 0x7a, 0x8b, 0x8b, + 0xc8, 0xcc, 0xd5, 0x38, 0x01, 0xc8, 0x0a, 0xda, 0x60, 0x83, 0x7b, 0x54, 0x76, 0x70, 0x81, + 0x55, 0xdd, 0x29, 0x77, 0xc8, 0x18, 0x00, + ], +]; From ffe49b795ac652c72a32965581d85989d2ce4445 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 17 Nov 2024 19:50:57 +0100 Subject: [PATCH 070/157] Make zebra_chain::orchard_zsa::tests::vectors::BLOCKS visible for zebra-state crate --- zebra-chain/src/orchard_zsa.rs | 6 ++++-- zebra-chain/src/orchard_zsa/tests.rs | 3 ++- zebra-chain/src/orchard_zsa/tests/vectors.rs | 3 ++- zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index 91445ebf949..313c5ab9c0e 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -4,8 +4,10 @@ #[cfg(any(test, feature = "proptest-impl"))] pub(crate) mod arbitrary; -#[cfg(test)] -mod tests; +// FIXME: feature = "proptest-impl" and pub are needed to access test vectors from another crates, +// remove it then +#[cfg(any(test, feature = "proptest-impl"))] +pub mod tests; mod burn; mod issuance; diff --git a/zebra-chain/src/orchard_zsa/tests.rs b/zebra-chain/src/orchard_zsa/tests.rs index 1c895a420d9..8c927c50432 100644 --- a/zebra-chain/src/orchard_zsa/tests.rs +++ b/zebra-chain/src/orchard_zsa/tests.rs @@ -1,2 +1,3 @@ mod blocks; -mod vectors; +// FIXME: pub is needed to access test vectors from another crates, remove it then +pub mod vectors; diff --git a/zebra-chain/src/orchard_zsa/tests/vectors.rs b/zebra-chain/src/orchard_zsa/tests/vectors.rs index d5664e50b19..0f7c4eceb48 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors.rs @@ -1,3 +1,4 @@ mod blocks; -pub(crate) use blocks::BLOCKS; +// FIXME: pub is needed to access test vectors from another crates, change it to pub(crate) then +pub use blocks::BLOCKS; diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs index db0eca9fb0b..e68775732f6 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -1,4 +1,5 @@ -pub(crate) const BLOCKS: [&[u8]; 4] = [ +// FIXME: pub is needed to access test vectors from another crates, change it to pub(crate) then +pub const BLOCKS: [&[u8]; 4] = [ // Genesis block &[], // Issuance block From 697d38a85a2346480af225b20e700ecf06a0bde7 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 17 Nov 2024 19:52:20 +0100 Subject: [PATCH 071/157] Add initial version of ZSA woirkflow tests to zebra-chain --- zebra-state/Cargo.toml | 4 +- zebra-state/tests/zsa.rs | 163 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 zebra-state/tests/zsa.rs diff --git a/zebra-state/Cargo.toml b/zebra-state/Cargo.toml index af73168ae39..45dcf9e96c6 100644 --- a/zebra-state/Cargo.toml +++ b/zebra-state/Cargo.toml @@ -15,8 +15,8 @@ keywords = ["zebra", "zcash"] categories = ["asynchronous", "caching", "cryptography::cryptocurrencies"] [features] -default = [] -#default = ["tx-v6"] +#default = [] +default = ["tx-v6"] # Production features that activate extra dependencies, or extra features in dependencies diff --git a/zebra-state/tests/zsa.rs b/zebra-state/tests/zsa.rs new file mode 100644 index 00000000000..cae0546e051 --- /dev/null +++ b/zebra-state/tests/zsa.rs @@ -0,0 +1,163 @@ +use zebra_chain::orchard_zsa::tests::vectors::BLOCKS; + +use std::sync::Arc; + +use color_eyre::eyre::Report; + +use zebra_chain::{ + block::{genesis::regtest_genesis_block, Block, Height}, + parameters::Network, + serialization::ZcashDeserialize, +}; + +use zebra_state::{Config, Request, Response}; + +use zebra_test::transcript::{ExpectedTranscriptError, Transcript}; + +fn patch_block_coinbase_height(block: &mut Block, previous_block: &Block) { + let mut transactions: Vec> = + block.transactions.iter().cloned().collect(); + if let Some(tx_arc) = transactions.first_mut() { + let mut tx = (**tx_arc).clone(); + if let Some(input) = tx.inputs_mut().first_mut() { + if let zebra_chain::transparent::Input::Coinbase { ref mut height, .. } = input { + *height = previous_block + .coinbase_height() + .expect("block has coinbase_height") + .next() + .expect("block has next coinbase_height"); //zebra_chain::block::Height(new_height) + } + } + *tx_arc = Arc::new(tx); + } + block.transactions = transactions.into(); +} + +fn patch_block(block: &mut Block, previous_block: &Block, commitment_bytes: [u8; 32]) { + let mut header = *block.header; + header.previous_block_hash = previous_block.hash(); + *header.commitment_bytes = commitment_bytes; + block.header = header.into(); + patch_block_coinbase_height(block, previous_block); +} + +fn create_transcript_data( + network: Network, +) -> Vec<(Request, Result)> { + let genesis_block = regtest_genesis_block(); + + let mut issuance_block: Block = + Block::zcash_deserialize(BLOCKS[1].as_ref()).expect("issuance block should deserialize"); + let mut transfer_block: Block = + Block::zcash_deserialize(BLOCKS[2].as_ref()).expect("transfer block should deserialize"); + let mut burn_block: Block = + Block::zcash_deserialize(BLOCKS[3].as_ref()).expect("burn block should deserialize"); + + let genesis_hash = genesis_block.hash(); + println!( + "Genesis hash: {:?}, previous: {:?}", + genesis_hash, genesis_block.header.previous_block_hash + ); + + //assert_eq!(genesis_hash, network.genesis_hash()); + + // Patch issuance block + patch_block(&mut issuance_block, &genesis_block, [0u8; 32]); + + let issuance_hash = issuance_block.hash(); + println!( + "Issuance hash: {:?}, previous: {:?}", + issuance_hash, issuance_block.header.previous_block_hash + ); + + // Patch transfer block + patch_block( + &mut transfer_block, + &issuance_block, + [ + 0xb7, 0x76, 0x07, 0x73, 0x39, 0x2d, 0x36, 0x6e, 0x31, 0xc4, 0xb4, 0xce, 0xce, 0xfa, + 0x5e, 0x1f, 0x85, 0x60, 0x21, 0x21, 0x1e, 0x2f, 0x91, 0xa9, 0x1e, 0x05, 0xb3, 0x06, + 0xea, 0x80, 0x57, 0x24, + ], + ); + + let transfer_hash = transfer_block.hash(); + println!( + "Transfer hash: {:?}, previous: {:?}", + transfer_hash, transfer_block.header.previous_block_hash + ); + + // Patch burn block + patch_block( + &mut burn_block, + &transfer_block, + [ + 0x6d, 0xec, 0x74, 0x8e, 0x07, 0xd1, 0x86, 0x67, 0xad, 0xb8, 0x39, 0x50, 0xe9, 0x48, + 0xc2, 0xca, 0x51, 0x9f, 0xad, 0x67, 0x45, 0x7a, 0xff, 0x4c, 0x3f, 0xa5, 0xad, 0x76, + 0xd2, 0x3a, 0xa8, 0x4c, + ], + ); + + let burn_hash = burn_block.hash(); + println!( + "Burn hash: {:?}, previous: {:?}", + burn_hash, burn_block.header.previous_block_hash + ); + + //println!("{:#?}", transfer_block); + + vec![ + ( + Request::CommitCheckpointVerifiedBlock(genesis_block.clone().into()), + Ok(Response::Committed(genesis_hash)), + ), + ( + Request::Block(genesis_hash.into()), + Ok(Response::Block(Some(genesis_block))), + ), + ( + //Request::CommitSemanticallyVerifiedBlock(Arc::new(issuance_block.clone()).into()), + Request::CommitCheckpointVerifiedBlock(Arc::new(issuance_block.clone()).into()), + Ok(Response::Committed(issuance_hash)), + ), + ( + Request::Block(issuance_hash.into()), + Ok(Response::Block(Some(Arc::new(issuance_block)))), + ), + ( + Request::CommitCheckpointVerifiedBlock(Arc::new(transfer_block.clone()).into()), + Ok(Response::Committed(transfer_hash)), + ), + ( + Request::Block(transfer_hash.into()), + Ok(Response::Block(Some(Arc::new(transfer_block)))), + ), + ( + Request::CommitCheckpointVerifiedBlock(Arc::new(burn_block.clone()).into()), + Ok(Response::Committed(burn_hash)), + ), + ( + Request::Block(burn_hash.into()), + Ok(Response::Block(Some(Arc::new(burn_block)))), + ), + ] +} + +#[tokio::test(flavor = "multi_thread")] +//#[tokio::test] +async fn check_zsa_workflow() -> Result<(), Report> { + let _init_guard = zebra_test::init(); + //let network = Network::new_default_testnet(); + let network = Network::new_regtest(None, None, None); + + for transcript_data in &[create_transcript_data(network.clone())] { + // We're not verifying UTXOs here. + let (service, _, _, _) = + zebra_state::init(Config::ephemeral(), &network.clone(), Height::MAX, 0); + let transcript = Transcript::from(transcript_data.iter().cloned()); + // check the on disk service against the transcript + transcript.check(service).await?; + } + + Ok(()) +} From fa948b840823c757eb54fa5d2bbf7758815492c4 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 18 Nov 2024 11:35:23 +0100 Subject: [PATCH 072/157] Improve zebra-state/tests/zsa.rs code --- zebra-state/tests/zsa.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/zebra-state/tests/zsa.rs b/zebra-state/tests/zsa.rs index cae0546e051..c01d5a8f46d 100644 --- a/zebra-state/tests/zsa.rs +++ b/zebra-state/tests/zsa.rs @@ -17,8 +17,10 @@ use zebra_test::transcript::{ExpectedTranscriptError, Transcript}; fn patch_block_coinbase_height(block: &mut Block, previous_block: &Block) { let mut transactions: Vec> = block.transactions.iter().cloned().collect(); + //let transactions: &mut Vec> = + // Arc::make_mut(&mut block.transactions); if let Some(tx_arc) = transactions.first_mut() { - let mut tx = (**tx_arc).clone(); + let tx = Arc::make_mut(&mut *tx_arc); if let Some(input) = tx.inputs_mut().first_mut() { if let zebra_chain::transparent::Input::Coinbase { ref mut height, .. } = input { *height = previous_block @@ -28,19 +30,18 @@ fn patch_block_coinbase_height(block: &mut Block, previous_block: &Block) { .expect("block has next coinbase_height"); //zebra_chain::block::Height(new_height) } } - *tx_arc = Arc::new(tx); } block.transactions = transactions.into(); } fn patch_block(block: &mut Block, previous_block: &Block, commitment_bytes: [u8; 32]) { - let mut header = *block.header; + let header = Arc::make_mut(&mut block.header); header.previous_block_hash = previous_block.hash(); *header.commitment_bytes = commitment_bytes; - block.header = header.into(); patch_block_coinbase_height(block, previous_block); } +// FIXME: remove printlns fn create_transcript_data( network: Network, ) -> Vec<(Request, Result)> { @@ -146,7 +147,7 @@ fn create_transcript_data( #[tokio::test(flavor = "multi_thread")] //#[tokio::test] async fn check_zsa_workflow() -> Result<(), Report> { - let _init_guard = zebra_test::init(); + //let _init_guard = zebra_test::init(); //let network = Network::new_default_testnet(); let network = Network::new_regtest(None, None, None); From 1df822e2ed1bbf527060b0ecf688609dddceb54e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 19 Nov 2024 15:50:24 +0100 Subject: [PATCH 073/157] Modify zebra-consensus to use ItemVerifyingKey for Orchard ZSA (there're two keys now - VERIFYING_KEY_VANILLA and VERIFYING_KEY_ZSA --- zebra-consensus/src/primitives/halo2.rs | 99 ++++++++++---- zebra-consensus/src/primitives/halo2/tests.rs | 22 +++- zebra-consensus/src/transaction.rs | 123 ++++++++++++++++-- 3 files changed, 202 insertions(+), 42 deletions(-) diff --git a/zebra-consensus/src/primitives/halo2.rs b/zebra-consensus/src/primitives/halo2.rs index ab88f6cbde4..5d1ab07bcf6 100644 --- a/zebra-consensus/src/primitives/halo2.rs +++ b/zebra-consensus/src/primitives/halo2.rs @@ -19,7 +19,7 @@ use tower::{util::ServiceFn, Service}; use tower_batch_control::{Batch, BatchControl}; use tower_fallback::Fallback; -use zebra_chain::orchard::{OrchardFlavorExt, OrchardVanilla}; +use zebra_chain::orchard::{OrchardFlavorExt, OrchardVanilla, OrchardZSA}; use crate::BoxError; @@ -75,10 +75,13 @@ pub type BatchVerifyingKey = ItemVerifyingKey; /// This is the key used to verify individual items. pub type ItemVerifyingKey = VerifyingKey; +// FIXME: Check if the Orchard code (called from the zebra-consensus) checks burn as a part of bidning signature lazy_static::lazy_static! { - /// The halo2 proof verifying key. - // FIXME: support OrchardZSA? - pub static ref VERIFYING_KEY: ItemVerifyingKey = ItemVerifyingKey::build::<::Flavor>(); + /// The halo2 proof verifying key for Orchard Vanilla + pub static ref VERIFYING_KEY_VANILLA: ItemVerifyingKey = ItemVerifyingKey::build::<::Flavor>(); + + /// The halo2 proof verifying key for Orchard ZSA + pub static ref VERIFYING_KEY_ZSA: ItemVerifyingKey = ItemVerifyingKey::build::<::Flavor>(); } // === TEMPORARY BATCH HALO2 SUBSTITUTE === @@ -133,8 +136,8 @@ impl BatchVerifier { // === END TEMPORARY BATCH HALO2 SUBSTITUTE === -impl From<&zebra_chain::orchard::ShieldedData> for Item { - fn from(shielded_data: &zebra_chain::orchard::ShieldedData) -> Item { +impl From<&zebra_chain::orchard::ShieldedData> for Item { + fn from(shielded_data: &zebra_chain::orchard::ShieldedData) -> Item { use orchard::{circuit, note, primitives::redpallas, tree, value}; let anchor = tree::Anchor::from_bytes(shielded_data.shared_anchor.into()).unwrap(); @@ -148,11 +151,13 @@ impl From<&zebra_chain::orchard::ShieldedData> for Item { // FIXME: simplify the flags creation - make `Flags::from_parts` method pub? // FIXME: support OrchardZSA? - let flags = match (enable_spend, enable_output) { - (false, false) => orchard::builder::BundleType::DISABLED.flags(), - (false, true) => orchard::bundle::Flags::SPENDS_DISABLED_WITHOUT_ZSA, - (true, false) => orchard::bundle::Flags::OUTPUTS_DISABLED, - (true, true) => orchard::bundle::Flags::ENABLED_WITHOUT_ZSA, + let flags = match (enable_spend, enable_output, V::ZSA_ENABLED) { + (false, false, _) => orchard::builder::BundleType::DISABLED.flags(), + (false, true, false) => orchard::bundle::Flags::SPENDS_DISABLED_WITHOUT_ZSA, + (false, true, true) => orchard::bundle::Flags::SPENDS_DISABLED_WITH_ZSA, + (true, false, _) => orchard::bundle::Flags::OUTPUTS_DISABLED, + (true, true, false) => orchard::bundle::Flags::ENABLED_WITHOUT_ZSA, + (true, true, true) => orchard::bundle::Flags::ENABLED_WITH_ZSA, }; let instances = shielded_data @@ -204,23 +209,22 @@ impl From for Halo2Error { } } -/// Global batch verification context for Halo2 proofs of Action statements. -/// -/// This service transparently batches contemporaneous proof verifications, -/// handling batch failures by falling back to individual verification. -/// -/// Note that making a `Service` call requires mutable access to the service, so -/// you should call `.clone()` on the global handle to create a local, mutable -/// handle. -pub static VERIFIER: Lazy< - Fallback< - Batch, - ServiceFn BoxFuture<'static, Result<(), BoxError>>>, - >, -> = Lazy::new(|| { +type VerificationContext = Fallback< + Batch, + ServiceFn BoxFuture<'static, Result<(), BoxError>>>, +>; + +pub(crate) trait OrchardVerifier: OrchardFlavorExt { + const ZSA_ENABLED: bool; + + fn get_verifying_key() -> &'static ItemVerifyingKey; + fn get_verifier() -> &'static VerificationContext; +} + +fn create_verification_context() -> VerificationContext { Fallback::new( Batch::new( - Verifier::new(&VERIFYING_KEY), + Verifier::new(V::get_verifying_key()), HALO2_MAX_BATCH_SIZE, None, super::MAX_BATCH_LATENCY, @@ -235,11 +239,50 @@ pub static VERIFIER: Lazy< // to erase the result type. // (We can't use BoxCloneService to erase the service type, because it is !Sync.) tower::service_fn( - (|item: Item| Verifier::verify_single_spawning(item, &VERIFYING_KEY).boxed()) + (|item: Item| Verifier::verify_single_spawning(item, V::get_verifying_key()).boxed()) as fn(_) -> _, ), ) -}); +} + +/// Global batch verification context for Halo2 proofs of Action statements. +/// +/// This service transparently batches contemporaneous proof verifications, +/// handling batch failures by falling back to individual verification. +/// +/// Note that making a `Service` call requires mutable access to the service, so +/// you should call `.clone()` on the global handle to create a local, mutable +/// handle. +pub static VERIFIER_VANILLA: Lazy = + Lazy::new(create_verification_context::); + +/// FIXME: copy a doc from VERIFIER_VANILLA or just refer to its doc? +pub static VERIFIER_ZSA: Lazy = + Lazy::new(create_verification_context::); + +impl OrchardVerifier for OrchardVanilla { + const ZSA_ENABLED: bool = false; + + fn get_verifying_key() -> &'static ItemVerifyingKey { + &VERIFYING_KEY_VANILLA + } + + fn get_verifier() -> &'static VerificationContext { + &VERIFIER_VANILLA + } +} + +impl OrchardVerifier for OrchardZSA { + const ZSA_ENABLED: bool = true; + + fn get_verifying_key() -> &'static ItemVerifyingKey { + &VERIFYING_KEY_ZSA + } + + fn get_verifier() -> &'static VerificationContext { + &VERIFIER_ZSA + } +} /// Halo2 proof verifier implementation /// diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index 8af73f182e1..539a7fe2a0c 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -148,6 +148,7 @@ where Ok(()) } +// FIXME: add OrchardZSA support #[tokio::test(flavor = "multi_thread")] async fn verify_generated_halo2_proofs() { let _init_guard = zebra_test::init(); @@ -168,14 +169,18 @@ async fn verify_generated_halo2_proofs() { // Use separate verifier so shared batch tasks aren't killed when the test ends (#2390) let mut verifier = Fallback::new( Batch::new( - Verifier::new(&VERIFYING_KEY), + Verifier::new(&OrchardVanilla::get_verifying_key()), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, ), tower::service_fn( - (|item: Item| ready(item.verify_single(&VERIFYING_KEY).map_err(Halo2Error::from))) - as fn(_) -> _, + (|item: Item| { + ready( + item.verify_single(&OrchardVanilla::get_verifying_key()) + .map_err(Halo2Error::from), + ) + }) as fn(_) -> _, ), ); @@ -216,6 +221,7 @@ where Ok(()) } +// FIXME: add OrchardZSA support #[tokio::test(flavor = "multi_thread")] async fn correctly_err_on_invalid_halo2_proofs() { let _init_guard = zebra_test::init(); @@ -236,14 +242,18 @@ async fn correctly_err_on_invalid_halo2_proofs() { // Use separate verifier so shared batch tasks aren't killed when the test ends (#2390) let mut verifier = Fallback::new( Batch::new( - Verifier::new(&VERIFYING_KEY), + Verifier::new(&OrchardVanilla::get_verifying_key()), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, ), tower::service_fn( - (|item: Item| ready(item.verify_single(&VERIFYING_KEY).map_err(Halo2Error::from))) - as fn(_) -> _, + (|item: Item| { + ready( + item.verify_single(&OrchardVanilla::get_verifying_key()) + .map_err(Halo2Error::from), + ) + }) as fn(_) -> _, ), ); diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 9083ddaf9ac..c6b1ac0473d 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -417,13 +417,20 @@ where // FIXME: implement proper V6 verification #[cfg(feature = "tx-v6")] Transaction::V6 { + sapling_shielded_data, + orchard_shielded_data, .. - } => { - tracing::debug!(?tx, "V6 transaction verification is not supported for now"); - return Err(TransactionError::WrongVersion); - } - }; + } => Self::verify_v6_transaction( + &req, + &network, + script_verifier, + cached_ffi_transaction.clone(), + sapling_shielded_data, + orchard_shielded_data, + )?, + }; + if let Some(unmined_tx) = req.mempool_transaction() { let check_anchors_and_revealed_nullifiers_query = state .clone() @@ -792,6 +799,106 @@ where } } + // FIXME: Consider avoiding code duplication with verify_v5_transaction. + // FIXME: Fix the following doc comment if needed (now it's basically a copy of the same comment for V5). + /// Verify a V6 transaction. + /// + /// Returns a set of asynchronous checks that must all succeed for the transaction to be + /// considered valid. These checks include: + /// + /// - transaction support by the considered network upgrade (see [`Request::upgrade`]) + /// - transparent transfers + /// - sapling shielded data (TODO) + /// - orchard shielded data (TODO) + /// + /// The parameters of this method are: + /// + /// - the `request` to verify (that contains the transaction and other metadata, see [`Request`] + /// for more information) + /// - the `network` to consider when verifying + /// - the `script_verifier` to use for verifying the transparent transfers + /// - the prepared `cached_ffi_transaction` used by the script verifier + /// - the sapling shielded data of the transaction, if any + /// - the orchard shielded data of the transaction, if any + #[allow(clippy::unwrap_in_result)] + fn verify_v6_transaction( + request: &Request, + network: &Network, + script_verifier: script::Verifier, + cached_ffi_transaction: Arc, + sapling_shielded_data: &Option>, + orchard_shielded_data: &Option>, + ) -> Result { + let transaction = request.transaction(); + let upgrade = request.upgrade(network); + + Self::verify_v6_transaction_network_upgrade(&transaction, upgrade)?; + + let shielded_sighash = transaction.sighash( + upgrade + .branch_id() + .expect("Overwinter-onwards must have branch ID, and we checkpoint on Canopy"), + HashType::ALL, + cached_ffi_transaction.all_previous_outputs(), + None, + ); + + Ok(Self::verify_transparent_inputs_and_outputs( + request, + network, + script_verifier, + cached_ffi_transaction, + )? + .and(Self::verify_sapling_shielded_data( + sapling_shielded_data, + &shielded_sighash, + )?) + .and(Self::verify_orchard_shielded_data( + orchard_shielded_data, + &shielded_sighash, + )?)) + // FIXME: Do we need to verify IssueBundle here in a some way? + // FIXME: Do we need to verify burns (separately or inside verify_orchard_shielded_data)? + } + + /// Verifies if a V6 `transaction` is supported by `network_upgrade`. + fn verify_v6_transaction_network_upgrade( + transaction: &Transaction, + network_upgrade: NetworkUpgrade, + ) -> Result<(), TransactionError> { + match network_upgrade { + // FIXME: Fix the following comment if needed (now it's basically a copy of the same comment for V5). + // Supports V6 transactions + // + // # Consensus + // + // > [NU5 onward] The transaction version number MUST be 4 or 5. + // > If the transaction version number is 4 then the version group ID MUST be 0x892F2085. + // > If the transaction version number is 5 then the version group ID MUST be 0x26A7270A. + // + // https://zips.z.cash/protocol/protocol.pdf#txnconsensus + // + // Note: Here we verify the transaction version number of the above rule, the group + // id is checked in zebra-chain crate, in the transaction serialize. + NetworkUpgrade::Nu7 => Ok(()), + + // Does not support V6 transactions + NetworkUpgrade::Genesis + | NetworkUpgrade::BeforeOverwinter + | NetworkUpgrade::Overwinter + | NetworkUpgrade::Sapling + | NetworkUpgrade::Blossom + | NetworkUpgrade::Heartwood + | NetworkUpgrade::Canopy + // FIXME: Just checking: is it correct that we consider Nu5 and Nu6 as unsupported for V6? + | NetworkUpgrade::Nu5 + | NetworkUpgrade::Nu6 => Err(TransactionError::UnsupportedByNetworkUpgrade( + transaction.version(), + network_upgrade, + )), + } + } + /// Verifies if a transaction's transparent inputs are valid using the provided /// `script_verifier` and `cached_ffi_transaction`. /// @@ -1022,8 +1129,8 @@ where } /// Verifies a transaction's Orchard shielded data. - fn verify_orchard_shielded_data( - orchard_shielded_data: &Option>, + fn verify_orchard_shielded_data( + orchard_shielded_data: &Option>, shielded_sighash: &SigHash, ) -> Result { let mut async_checks = AsyncChecks::new(); @@ -1041,7 +1148,7 @@ where // Actions in one transaction. So we queue it for verification // only once instead of queuing it up for every Action description. async_checks.push( - primitives::halo2::VERIFIER + V::get_verifier() .clone() .oneshot(primitives::halo2::Item::from(orchard_shielded_data)), ); From e5d5dacd83ee134ee71b3386c6fc256506f33970 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 19 Nov 2024 19:58:41 +0100 Subject: [PATCH 074/157] Temporary update get_blockchain_info@testnet_10 snapshot zebra-rpc to use 77777777 as consensus branch id for Nu7 (to ajdust it with ones used in librustzcash) --- .../methods/tests/snapshots/get_blockchain_info@testnet_10.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap index 9d7ea3f5176..20776940884 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap @@ -71,7 +71,7 @@ expression: info "activationheight": 2976000, "status": "pending" }, - "c8e71056": { + "77777777": { "name": "NU7", "activationheight": 2942001, "status": "pending" From a18a456de6e47c21af50bdb1c42d872792c771d9 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 19 Nov 2024 20:52:02 +0100 Subject: [PATCH 075/157] Fix cargo fmt issue --- zebra-consensus/src/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index c6b1ac0473d..8c5a6d69c92 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -430,7 +430,7 @@ where )?, }; - + if let Some(unmined_tx) = req.mempool_transaction() { let check_anchors_and_revealed_nullifiers_query = state .clone() From 215ec92e4ab53845502e54b43db26abdf755549a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 19 Nov 2024 20:52:29 +0100 Subject: [PATCH 076/157] Add cargo clippy to ci-basic --- .github/workflows/ci-basic.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 226f1528046..e52c70103b6 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -34,3 +34,5 @@ jobs: run: cargo doc --all-features --document-private-items - name: Run format check run: cargo fmt -- --check + - name: Run clippy + run: cargo clippy --workspace --all-features --all-targets -- -D warnings From d9c87205c4c629bb18f33d83cb41aac0ece46125 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 19 Nov 2024 21:25:07 +0100 Subject: [PATCH 077/157] Add temporary docs for pub test constants amd modules --- zebra-chain/src/orchard_zsa.rs | 4 ++-- zebra-chain/src/orchard_zsa/tests.rs | 2 +- zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index 313c5ab9c0e..cb3dcd0aa28 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -4,8 +4,8 @@ #[cfg(any(test, feature = "proptest-impl"))] pub(crate) mod arbitrary; -// FIXME: feature = "proptest-impl" and pub are needed to access test vectors from another crates, -// remove it then +/// FIXME: feature = "proptest-impl" and pub are needed to access test vectors from another crates, +/// remove it then #[cfg(any(test, feature = "proptest-impl"))] pub mod tests; diff --git a/zebra-chain/src/orchard_zsa/tests.rs b/zebra-chain/src/orchard_zsa/tests.rs index 8c927c50432..a5d2fee1572 100644 --- a/zebra-chain/src/orchard_zsa/tests.rs +++ b/zebra-chain/src/orchard_zsa/tests.rs @@ -1,3 +1,3 @@ mod blocks; -// FIXME: pub is needed to access test vectors from another crates, remove it then +/// FIXME: pub is needed to access test vectors from another crates, remove it then pub mod vectors; diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs index e68775732f6..324f270c04d 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -1,4 +1,4 @@ -// FIXME: pub is needed to access test vectors from another crates, change it to pub(crate) then +/// FIXME: pub is needed to access test vectors from another crates, change it to pub(crate) then pub const BLOCKS: [&[u8]; 4] = [ // Genesis block &[], From 90dac031999581cab77c0d43105d808e7a2fa8a2 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 20 Nov 2024 07:04:56 +0100 Subject: [PATCH 078/157] Fix zsa consensus tests --- zebra-chain/src/orchard_zsa/tests.rs | 3 +++ zebra-consensus/src/lib.rs | 2 ++ 2 files changed, 5 insertions(+) diff --git a/zebra-chain/src/orchard_zsa/tests.rs b/zebra-chain/src/orchard_zsa/tests.rs index a5d2fee1572..2a757269874 100644 --- a/zebra-chain/src/orchard_zsa/tests.rs +++ b/zebra-chain/src/orchard_zsa/tests.rs @@ -1,3 +1,6 @@ +/// FIXME: refactor orchard_zsa/tests (possibly move vectors to zebra-tests), remove cfg(test) here etc. +#[cfg(test)] mod blocks; + /// FIXME: pub is needed to access test vectors from another crates, remove it then pub mod vectors; diff --git a/zebra-consensus/src/lib.rs b/zebra-consensus/src/lib.rs index 95381fd9e07..c61a1fe408d 100644 --- a/zebra-consensus/src/lib.rs +++ b/zebra-consensus/src/lib.rs @@ -65,3 +65,5 @@ pub use router::RouterError; /// A boxed [`std::error::Error`]. pub type BoxError = Box; + +mod zsa; From 2bb599f836b031a5e04e2627dac91e3af7e74e23 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 20 Nov 2024 07:58:35 +0100 Subject: [PATCH 079/157] Add missed ZSA test modules in zebra-consensus --- zebra-consensus/src/zsa.rs | 2 + zebra-consensus/src/zsa/tests.rs | 121 +++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 zebra-consensus/src/zsa.rs create mode 100644 zebra-consensus/src/zsa/tests.rs diff --git a/zebra-consensus/src/zsa.rs b/zebra-consensus/src/zsa.rs new file mode 100644 index 00000000000..87c2771955a --- /dev/null +++ b/zebra-consensus/src/zsa.rs @@ -0,0 +1,2 @@ +#[cfg(test)] +mod tests; diff --git a/zebra-consensus/src/zsa/tests.rs b/zebra-consensus/src/zsa/tests.rs new file mode 100644 index 00000000000..4d995c78c24 --- /dev/null +++ b/zebra-consensus/src/zsa/tests.rs @@ -0,0 +1,121 @@ +// FIXME: consider merging it with router/tests.rs + +// FIXME: fix warnings, clippy, remove printlns and commented out lines + +use std::sync::Arc; + +use color_eyre::eyre::Report; + +use zebra_chain::{ + block::{genesis::regtest_genesis_block, Block, Hash}, + orchard_zsa::tests::vectors::BLOCKS, + parameters::Network, + serialization::ZcashDeserialize, +}; +use zebra_test::transcript::{ExpectedTranscriptError, Transcript}; + +use crate::{block::Request, Config}; + +fn patch_block_coinbase_height(block: &mut Block, previous_block: &Block) { + let proper_height = previous_block + .coinbase_height() + .expect("block has coinbase_height") + .next() + .expect("block has next coinbase_height"); + + let mut transactions: Vec> = + block.transactions.iter().cloned().collect(); + //let transactions: &mut Vec> = + // Arc::make_mut(&mut block.transactions); + if let Some(tx_arc) = transactions.first_mut() { + let tx = Arc::make_mut(&mut *tx_arc); + + if let Some(input) = tx.inputs_mut().first_mut() { + if let zebra_chain::transparent::Input::Coinbase { ref mut height, .. } = input { + *height = proper_height; + } + } + } + + block.transactions = transactions.into(); +} + +fn patch_block(block: &mut Block, previous_block: &Block, commitment_bytes: [u8; 32]) { + println!( + "patch_block merkle_root before: {:?}", + block.header.merkle_root + ); + let header = Arc::make_mut(&mut block.header); + header.previous_block_hash = previous_block.hash(); + *header.commitment_bytes = commitment_bytes; + + patch_block_coinbase_height(block, previous_block); + + let transaction_hashes: Arc<[_]> = block.transactions.iter().map(|t| t.hash()).collect(); + let merkle_root = transaction_hashes.iter().cloned().collect(); + println!("patch_block merkle_root after: {:?}", merkle_root); + let header = Arc::make_mut(&mut block.header); + header.merkle_root = merkle_root; +} + +fn create_transcript_data() -> [(Request, Result); 4] { + let genesis_block: Arc = regtest_genesis_block(); + + let mut issuance_block: Block = + Block::zcash_deserialize(BLOCKS[1].as_ref()).expect("issuance block should deserialize"); + let mut transfer_block: Block = + Block::zcash_deserialize(BLOCKS[2].as_ref()).expect("transfer block should deserialize"); + let mut burn_block: Block = + Block::zcash_deserialize(BLOCKS[3].as_ref()).expect("burn block should deserialize"); + + patch_block(&mut issuance_block, &genesis_block, [0u8; 32]); + + patch_block( + &mut transfer_block, + &issuance_block, + [ + 0xb7, 0x76, 0x07, 0x73, 0x39, 0x2d, 0x36, 0x6e, 0x31, 0xc4, 0xb4, 0xce, 0xce, 0xfa, + 0x5e, 0x1f, 0x85, 0x60, 0x21, 0x21, 0x1e, 0x2f, 0x91, 0xa9, 0x1e, 0x05, 0xb3, 0x06, + 0xea, 0x80, 0x57, 0x24, + ], + ); + + patch_block( + &mut burn_block, + &transfer_block, + [ + 0x6d, 0xec, 0x74, 0x8e, 0x07, 0xd1, 0x86, 0x67, 0xad, 0xb8, 0x39, 0x50, 0xe9, 0x48, + 0xc2, 0xca, 0x51, 0x9f, 0xad, 0x67, 0x45, 0x7a, 0xff, 0x4c, 0x3f, 0xa5, 0xad, 0x76, + 0xd2, 0x3a, 0xa8, 0x4c, + ], + ); + + [ + genesis_block, + Arc::new(issuance_block), + Arc::new(transfer_block), + Arc::new(burn_block), + ] + .map(|block| (Request::Commit(block.clone()), Ok(block.hash()))) +} + +// FIMXE: uncomment when blocks test data will be fixed +//#[tokio::test(flavor = "multi_thread")] +async fn check_zsa_workflow() -> Result<(), Report> { + let _init_guard = zebra_test::init(); + + let network = Network::new_regtest(Some(1), Some(1), Some(1)); + + let state_service = zebra_state::init_test(&network); + + let ( + block_verifier_router, + _transaction_verifier, + _groth16_download_handle, + _max_checkpoint_height, + ) = crate::router::init(Config::default(), &network, state_service.clone()).await; + + Transcript::from(create_transcript_data()) + .check(block_verifier_router.clone()) + .await +} From 1faf196170e80a5410aa36a7b52ee22fd3a0b794 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 20 Nov 2024 08:00:59 +0100 Subject: [PATCH 080/157] Remove zebra-state zsa workflow tests (in favour of workflow tests in zebra-consensus) --- zebra-state/tests/zsa.rs | 164 --------------------------------------- 1 file changed, 164 deletions(-) delete mode 100644 zebra-state/tests/zsa.rs diff --git a/zebra-state/tests/zsa.rs b/zebra-state/tests/zsa.rs deleted file mode 100644 index c01d5a8f46d..00000000000 --- a/zebra-state/tests/zsa.rs +++ /dev/null @@ -1,164 +0,0 @@ -use zebra_chain::orchard_zsa::tests::vectors::BLOCKS; - -use std::sync::Arc; - -use color_eyre::eyre::Report; - -use zebra_chain::{ - block::{genesis::regtest_genesis_block, Block, Height}, - parameters::Network, - serialization::ZcashDeserialize, -}; - -use zebra_state::{Config, Request, Response}; - -use zebra_test::transcript::{ExpectedTranscriptError, Transcript}; - -fn patch_block_coinbase_height(block: &mut Block, previous_block: &Block) { - let mut transactions: Vec> = - block.transactions.iter().cloned().collect(); - //let transactions: &mut Vec> = - // Arc::make_mut(&mut block.transactions); - if let Some(tx_arc) = transactions.first_mut() { - let tx = Arc::make_mut(&mut *tx_arc); - if let Some(input) = tx.inputs_mut().first_mut() { - if let zebra_chain::transparent::Input::Coinbase { ref mut height, .. } = input { - *height = previous_block - .coinbase_height() - .expect("block has coinbase_height") - .next() - .expect("block has next coinbase_height"); //zebra_chain::block::Height(new_height) - } - } - } - block.transactions = transactions.into(); -} - -fn patch_block(block: &mut Block, previous_block: &Block, commitment_bytes: [u8; 32]) { - let header = Arc::make_mut(&mut block.header); - header.previous_block_hash = previous_block.hash(); - *header.commitment_bytes = commitment_bytes; - patch_block_coinbase_height(block, previous_block); -} - -// FIXME: remove printlns -fn create_transcript_data( - network: Network, -) -> Vec<(Request, Result)> { - let genesis_block = regtest_genesis_block(); - - let mut issuance_block: Block = - Block::zcash_deserialize(BLOCKS[1].as_ref()).expect("issuance block should deserialize"); - let mut transfer_block: Block = - Block::zcash_deserialize(BLOCKS[2].as_ref()).expect("transfer block should deserialize"); - let mut burn_block: Block = - Block::zcash_deserialize(BLOCKS[3].as_ref()).expect("burn block should deserialize"); - - let genesis_hash = genesis_block.hash(); - println!( - "Genesis hash: {:?}, previous: {:?}", - genesis_hash, genesis_block.header.previous_block_hash - ); - - //assert_eq!(genesis_hash, network.genesis_hash()); - - // Patch issuance block - patch_block(&mut issuance_block, &genesis_block, [0u8; 32]); - - let issuance_hash = issuance_block.hash(); - println!( - "Issuance hash: {:?}, previous: {:?}", - issuance_hash, issuance_block.header.previous_block_hash - ); - - // Patch transfer block - patch_block( - &mut transfer_block, - &issuance_block, - [ - 0xb7, 0x76, 0x07, 0x73, 0x39, 0x2d, 0x36, 0x6e, 0x31, 0xc4, 0xb4, 0xce, 0xce, 0xfa, - 0x5e, 0x1f, 0x85, 0x60, 0x21, 0x21, 0x1e, 0x2f, 0x91, 0xa9, 0x1e, 0x05, 0xb3, 0x06, - 0xea, 0x80, 0x57, 0x24, - ], - ); - - let transfer_hash = transfer_block.hash(); - println!( - "Transfer hash: {:?}, previous: {:?}", - transfer_hash, transfer_block.header.previous_block_hash - ); - - // Patch burn block - patch_block( - &mut burn_block, - &transfer_block, - [ - 0x6d, 0xec, 0x74, 0x8e, 0x07, 0xd1, 0x86, 0x67, 0xad, 0xb8, 0x39, 0x50, 0xe9, 0x48, - 0xc2, 0xca, 0x51, 0x9f, 0xad, 0x67, 0x45, 0x7a, 0xff, 0x4c, 0x3f, 0xa5, 0xad, 0x76, - 0xd2, 0x3a, 0xa8, 0x4c, - ], - ); - - let burn_hash = burn_block.hash(); - println!( - "Burn hash: {:?}, previous: {:?}", - burn_hash, burn_block.header.previous_block_hash - ); - - //println!("{:#?}", transfer_block); - - vec![ - ( - Request::CommitCheckpointVerifiedBlock(genesis_block.clone().into()), - Ok(Response::Committed(genesis_hash)), - ), - ( - Request::Block(genesis_hash.into()), - Ok(Response::Block(Some(genesis_block))), - ), - ( - //Request::CommitSemanticallyVerifiedBlock(Arc::new(issuance_block.clone()).into()), - Request::CommitCheckpointVerifiedBlock(Arc::new(issuance_block.clone()).into()), - Ok(Response::Committed(issuance_hash)), - ), - ( - Request::Block(issuance_hash.into()), - Ok(Response::Block(Some(Arc::new(issuance_block)))), - ), - ( - Request::CommitCheckpointVerifiedBlock(Arc::new(transfer_block.clone()).into()), - Ok(Response::Committed(transfer_hash)), - ), - ( - Request::Block(transfer_hash.into()), - Ok(Response::Block(Some(Arc::new(transfer_block)))), - ), - ( - Request::CommitCheckpointVerifiedBlock(Arc::new(burn_block.clone()).into()), - Ok(Response::Committed(burn_hash)), - ), - ( - Request::Block(burn_hash.into()), - Ok(Response::Block(Some(Arc::new(burn_block)))), - ), - ] -} - -#[tokio::test(flavor = "multi_thread")] -//#[tokio::test] -async fn check_zsa_workflow() -> Result<(), Report> { - //let _init_guard = zebra_test::init(); - //let network = Network::new_default_testnet(); - let network = Network::new_regtest(None, None, None); - - for transcript_data in &[create_transcript_data(network.clone())] { - // We're not verifying UTXOs here. - let (service, _, _, _) = - zebra_state::init(Config::ephemeral(), &network.clone(), Height::MAX, 0); - let transcript = Transcript::from(transcript_data.iter().cloned()); - // check the on disk service against the transcript - transcript.check(service).await?; - } - - Ok(()) -} From 689e7916466fa806d6291b2765d204dffce5a497 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 20 Nov 2024 08:07:36 +0100 Subject: [PATCH 081/157] Fix cargo clippy issues --- zebra-chain/src/orchard_zsa/tests/blocks.rs | 9 ++++----- zebra-consensus/src/primitives/halo2/tests.rs | 8 ++++---- zebra-consensus/src/zsa.rs | 5 +++-- zebra-consensus/src/zsa/tests.rs | 3 +-- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/zebra-chain/src/orchard_zsa/tests/blocks.rs b/zebra-chain/src/orchard_zsa/tests/blocks.rs index 2828acb311c..8c10e3d8801 100644 --- a/zebra-chain/src/orchard_zsa/tests/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/blocks.rs @@ -5,11 +5,10 @@ use super::vectors::BLOCKS; #[test] fn deserialize_blocks() { let issuance_block = - Block::zcash_deserialize(BLOCKS[1].as_ref()).expect("issuance block should deserialize"); - let transfer_block = - Block::zcash_deserialize(BLOCKS[2].as_ref()).expect("transfer block should deserialize"); - let burn_block = - Block::zcash_deserialize(BLOCKS[3].as_ref()).expect("burn block should deserialize"); + Block::zcash_deserialize(BLOCKS[1]).expect("issuance block should deserialize"); + let _transfer_block = + Block::zcash_deserialize(BLOCKS[2]).expect("transfer block should deserialize"); + let _burn_block = Block::zcash_deserialize(BLOCKS[3]).expect("burn block should deserialize"); for transaction in issuance_block.transactions { if let Transaction::V6 { diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index 539a7fe2a0c..45c4fb6e7a4 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -169,7 +169,7 @@ async fn verify_generated_halo2_proofs() { // Use separate verifier so shared batch tasks aren't killed when the test ends (#2390) let mut verifier = Fallback::new( Batch::new( - Verifier::new(&OrchardVanilla::get_verifying_key()), + Verifier::new(OrchardVanilla::get_verifying_key()), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, @@ -177,7 +177,7 @@ async fn verify_generated_halo2_proofs() { tower::service_fn( (|item: Item| { ready( - item.verify_single(&OrchardVanilla::get_verifying_key()) + item.verify_single(OrchardVanilla::get_verifying_key()) .map_err(Halo2Error::from), ) }) as fn(_) -> _, @@ -242,7 +242,7 @@ async fn correctly_err_on_invalid_halo2_proofs() { // Use separate verifier so shared batch tasks aren't killed when the test ends (#2390) let mut verifier = Fallback::new( Batch::new( - Verifier::new(&OrchardVanilla::get_verifying_key()), + Verifier::new(OrchardVanilla::get_verifying_key()), crate::primitives::MAX_BATCH_SIZE, None, crate::primitives::MAX_BATCH_LATENCY, @@ -250,7 +250,7 @@ async fn correctly_err_on_invalid_halo2_proofs() { tower::service_fn( (|item: Item| { ready( - item.verify_single(&OrchardVanilla::get_verifying_key()) + item.verify_single(OrchardVanilla::get_verifying_key()) .map_err(Halo2Error::from), ) }) as fn(_) -> _, diff --git a/zebra-consensus/src/zsa.rs b/zebra-consensus/src/zsa.rs index 87c2771955a..0f20158de73 100644 --- a/zebra-consensus/src/zsa.rs +++ b/zebra-consensus/src/zsa.rs @@ -1,2 +1,3 @@ -#[cfg(test)] -mod tests; +// FIMXE: uncomment when blocks test data will be fixed +//#[cfg(test)] +//mod tests; diff --git a/zebra-consensus/src/zsa/tests.rs b/zebra-consensus/src/zsa/tests.rs index 4d995c78c24..d66ac8c09b9 100644 --- a/zebra-consensus/src/zsa/tests.rs +++ b/zebra-consensus/src/zsa/tests.rs @@ -99,8 +99,7 @@ fn create_transcript_data() -> [(Request, Result) .map(|block| (Request::Commit(block.clone()), Ok(block.hash()))) } -// FIMXE: uncomment when blocks test data will be fixed -//#[tokio::test(flavor = "multi_thread")] +#[tokio::test(flavor = "multi_thread")] async fn check_zsa_workflow() -> Result<(), Report> { let _init_guard = zebra_test::init(); From ab7c077cb10cea6cd345b14199ca279ebac35044 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 21 Nov 2024 09:54:35 +0100 Subject: [PATCH 082/157] Modify Orchard ShieldedData binding_verification_key function to subtract ValueCommitment of burn items if they are present --- zebra-chain/src/orchard/commitment.rs | 11 ++++++++++ zebra-chain/src/orchard/orchard_flavor_ext.rs | 14 +++++++++--- zebra-chain/src/orchard/shielded_data.rs | 6 +++++ zebra-chain/src/orchard_zsa/burn.rs | 22 +++++++++++++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/zebra-chain/src/orchard/commitment.rs b/zebra-chain/src/orchard/commitment.rs index 4e69258c4e5..2e6ea3ed32d 100644 --- a/zebra-chain/src/orchard/commitment.rs +++ b/zebra-chain/src/orchard/commitment.rs @@ -14,6 +14,8 @@ use halo2::{ use lazy_static::lazy_static; use rand_core::{CryptoRng, RngCore}; +use orchard::note::AssetBase; + use crate::{ amount::Amount, error::RandError, @@ -249,6 +251,15 @@ impl ValueCommitment { let v = pallas::Scalar::from(value); Self::from(*V * v + *R * rcv) } + + /// Generate a new `ValueCommitment` from an existing `rcv on a `value` (ZSA version). + #[cfg(feature = "tx-v6")] + #[allow(non_snake_case)] + pub fn with_asset(rcv: pallas::Scalar, value: Amount, asset: &AssetBase) -> Self { + let v = pallas::Scalar::from(value); + let V_zsa = asset.cv_base(); + Self::from(V_zsa * v + *R * rcv) + } } lazy_static! { diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index 6ad05abd889..0ade1c75d39 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -9,7 +9,10 @@ use proptest_derive::Arbitrary; use orchard::{note_encryption::OrchardDomainCommon, orchard_flavor}; -use crate::serialization::{ZcashDeserialize, ZcashSerialize}; +use crate::{ + orchard::ValueCommitment, + serialization::{ZcashDeserialize, ZcashSerialize}, +}; #[cfg(feature = "tx-v6")] use crate::orchard_zsa::{Burn, NoBurn}; @@ -50,7 +53,13 @@ pub trait OrchardFlavorExt: Clone + Debug { /// A type representing a burn field for this protocol version. #[cfg(feature = "tx-v6")] - type BurnType: Clone + Debug + Default + ZcashDeserialize + ZcashSerialize + TestArbitrary; + type BurnType: Clone + + Debug + + Default + + ZcashDeserialize + + ZcashSerialize + + Into + + TestArbitrary; } /// A structure representing a tag for Orchard protocol variant used for the transaction version `V5`. @@ -78,6 +87,5 @@ impl OrchardFlavorExt for OrchardZSA { type Flavor = orchard_flavor::OrchardZSA; type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; - #[cfg(feature = "tx-v6")] type BurnType = Burn; } diff --git a/zebra-chain/src/orchard/shielded_data.rs b/zebra-chain/src/orchard/shielded_data.rs index 844c1ff3994..109fcfb94cc 100644 --- a/zebra-chain/src/orchard/shielded_data.rs +++ b/zebra-chain/src/orchard/shielded_data.rs @@ -119,7 +119,13 @@ impl ShieldedData { let cv_balance: ValueCommitment = ValueCommitment::new(pallas::Scalar::zero(), self.value_balance); + #[cfg(not(feature = "tx-v6"))] let key_bytes: [u8; 32] = (cv - cv_balance).into(); + + // FIXME: use asset to create ValueCommitment here for burns and above for value_balance? + #[cfg(feature = "tx-v6")] + let key_bytes: [u8; 32] = (cv - cv_balance - self.burn.clone().into()).into(); + key_bytes.into() } diff --git a/zebra-chain/src/orchard_zsa/burn.rs b/zebra-chain/src/orchard_zsa/burn.rs index 0e0c007709b..75301a47008 100644 --- a/zebra-chain/src/orchard_zsa/burn.rs +++ b/zebra-chain/src/orchard_zsa/burn.rs @@ -2,9 +2,12 @@ use std::io; +use halo2::pasta::pallas; + use crate::{ amount::Amount, block::MAX_BLOCK_BYTES, + orchard::ValueCommitment, serialization::{ ReadZcashExt, SerializationError, TrustedPreallocate, ZcashDeserialize, ZcashSerialize, }, @@ -109,6 +112,13 @@ impl<'de> serde::Deserialize<'de> for BurnItem { #[derive(Default, Clone, Debug, PartialEq, Eq, Serialize)] pub struct NoBurn; +impl From for ValueCommitment { + fn from(_burn: NoBurn) -> ValueCommitment { + // FIXME: is there a simpler way to get zero ValueCommitment? + ValueCommitment::new(pallas::Scalar::zero(), Amount::zero()) + } +} + impl ZcashSerialize for NoBurn { fn zcash_serialize(&self, mut _writer: W) -> Result<(), io::Error> { Ok(()) @@ -131,6 +141,18 @@ impl From> for Burn { } } +// FIXME: consider conversion from reference to Burn instead, to avoid using `clone` when it's called +impl From for ValueCommitment { + fn from(burn: Burn) -> ValueCommitment { + burn.0 + .into_iter() + .map(|BurnItem(asset, amount)| { + ValueCommitment::with_asset(pallas::Scalar::zero(), amount, &asset) + }) + .sum() + } +} + impl ZcashSerialize for Burn { fn zcash_serialize(&self, writer: W) -> Result<(), io::Error> { self.0.zcash_serialize(writer) From ada6a3725093b083726f47016ddcdfd0c2394e5a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 25 Nov 2024 10:07:58 +0100 Subject: [PATCH 083/157] Update consensus ZSA workflow tests and test vectors --- zebra-consensus/src/zsa.rs | 5 +- zebra-consensus/src/zsa/tests.rs | 97 +++++--------------------------- zebra-test/src/vectors.rs | 2 + 3 files changed, 17 insertions(+), 87 deletions(-) diff --git a/zebra-consensus/src/zsa.rs b/zebra-consensus/src/zsa.rs index 0f20158de73..87c2771955a 100644 --- a/zebra-consensus/src/zsa.rs +++ b/zebra-consensus/src/zsa.rs @@ -1,3 +1,2 @@ -// FIMXE: uncomment when blocks test data will be fixed -//#[cfg(test)] -//mod tests; +#[cfg(test)] +mod tests; diff --git a/zebra-consensus/src/zsa/tests.rs b/zebra-consensus/src/zsa/tests.rs index d66ac8c09b9..dbea27190bb 100644 --- a/zebra-consensus/src/zsa/tests.rs +++ b/zebra-consensus/src/zsa/tests.rs @@ -1,102 +1,31 @@ // FIXME: consider merging it with router/tests.rs -// FIXME: fix warnings, clippy, remove printlns and commented out lines - use std::sync::Arc; use color_eyre::eyre::Report; use zebra_chain::{ block::{genesis::regtest_genesis_block, Block, Hash}, - orchard_zsa::tests::vectors::BLOCKS, parameters::Network, serialization::ZcashDeserialize, }; -use zebra_test::transcript::{ExpectedTranscriptError, Transcript}; - -use crate::{block::Request, Config}; - -fn patch_block_coinbase_height(block: &mut Block, previous_block: &Block) { - let proper_height = previous_block - .coinbase_height() - .expect("block has coinbase_height") - .next() - .expect("block has next coinbase_height"); - - let mut transactions: Vec> = - block.transactions.iter().cloned().collect(); - //let transactions: &mut Vec> = - // Arc::make_mut(&mut block.transactions); - if let Some(tx_arc) = transactions.first_mut() { - let tx = Arc::make_mut(&mut *tx_arc); - - if let Some(input) = tx.inputs_mut().first_mut() { - if let zebra_chain::transparent::Input::Coinbase { ref mut height, .. } = input { - *height = proper_height; - } - } - } - - block.transactions = transactions.into(); -} -fn patch_block(block: &mut Block, previous_block: &Block, commitment_bytes: [u8; 32]) { - println!( - "patch_block merkle_root before: {:?}", - block.header.merkle_root - ); - let header = Arc::make_mut(&mut block.header); - header.previous_block_hash = previous_block.hash(); - *header.commitment_bytes = commitment_bytes; - - patch_block_coinbase_height(block, previous_block); - - let transaction_hashes: Arc<[_]> = block.transactions.iter().map(|t| t.hash()).collect(); - let merkle_root = transaction_hashes.iter().cloned().collect(); - println!("patch_block merkle_root after: {:?}", merkle_root); - let header = Arc::make_mut(&mut block.header); - header.merkle_root = merkle_root; -} - -fn create_transcript_data() -> [(Request, Result); 4] { - let genesis_block: Arc = regtest_genesis_block(); - - let mut issuance_block: Block = - Block::zcash_deserialize(BLOCKS[1].as_ref()).expect("issuance block should deserialize"); - let mut transfer_block: Block = - Block::zcash_deserialize(BLOCKS[2].as_ref()).expect("transfer block should deserialize"); - let mut burn_block: Block = - Block::zcash_deserialize(BLOCKS[3].as_ref()).expect("burn block should deserialize"); - - patch_block(&mut issuance_block, &genesis_block, [0u8; 32]); +use zebra_test::{ + transcript::{ExpectedTranscriptError, Transcript}, + vectors::ZSA_WORKFLOW_BLOCKS, +}; - patch_block( - &mut transfer_block, - &issuance_block, - [ - 0xb7, 0x76, 0x07, 0x73, 0x39, 0x2d, 0x36, 0x6e, 0x31, 0xc4, 0xb4, 0xce, 0xce, 0xfa, - 0x5e, 0x1f, 0x85, 0x60, 0x21, 0x21, 0x1e, 0x2f, 0x91, 0xa9, 0x1e, 0x05, 0xb3, 0x06, - 0xea, 0x80, 0x57, 0x24, - ], - ); +use crate::{block::Request, Config}; - patch_block( - &mut burn_block, - &transfer_block, - [ - 0x6d, 0xec, 0x74, 0x8e, 0x07, 0xd1, 0x86, 0x67, 0xad, 0xb8, 0x39, 0x50, 0xe9, 0x48, - 0xc2, 0xca, 0x51, 0x9f, 0xad, 0x67, 0x45, 0x7a, 0xff, 0x4c, 0x3f, 0xa5, 0xad, 0x76, - 0xd2, 0x3a, 0xa8, 0x4c, - ], - ); +fn create_transcript_data() -> impl Iterator)> +{ + let workflow_blocks = ZSA_WORKFLOW_BLOCKS.iter().map(|block_bytes| { + Arc::new(Block::zcash_deserialize(&block_bytes[..]).expect("block should deserialize")) + }); - [ - genesis_block, - Arc::new(issuance_block), - Arc::new(transfer_block), - Arc::new(burn_block), - ] - .map(|block| (Request::Commit(block.clone()), Ok(block.hash()))) + std::iter::once(regtest_genesis_block()) + .chain(workflow_blocks) + .map(|block| (Request::Commit(block.clone()), Ok(block.hash()))) } #[tokio::test(flavor = "multi_thread")] diff --git a/zebra-test/src/vectors.rs b/zebra-test/src/vectors.rs index cfcd48e811b..7937b19ba7f 100644 --- a/zebra-test/src/vectors.rs +++ b/zebra-test/src/vectors.rs @@ -6,10 +6,12 @@ use lazy_static::lazy_static; mod block; mod orchard_note_encryption; mod orchard_shielded_data; +mod zsa; pub use block::*; pub use orchard_note_encryption::*; pub use orchard_shielded_data::*; +pub use zsa::*; /// A testnet transaction test vector /// From e0ee6c686ed28243411518aa1857ea362e71c672 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 25 Nov 2024 10:19:44 +0100 Subject: [PATCH 084/157] Add ZSA workflow test vectors --- zebra-test/src/vectors/zsa.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 zebra-test/src/vectors/zsa.rs diff --git a/zebra-test/src/vectors/zsa.rs b/zebra-test/src/vectors/zsa.rs new file mode 100644 index 00000000000..f4caefb4afd --- /dev/null +++ b/zebra-test/src/vectors/zsa.rs @@ -0,0 +1,15 @@ +//! ZSA test vectors + +#![allow(missing_docs)] + +use hex::FromHex; +use lazy_static::lazy_static; + +lazy_static! { +pub static ref ZSA_WORKFLOW_BLOCKS: [Vec; 3] = + [ + "0400000027e30134d620e9fe61f719938320bab63e7e72c91b5e23025676f90ed8119f02c71c7ffa660028b5f3bc0b0bedf9b76a829ce8f2ef82c2c69ab6948bc9fd00a80000000000000000000000000000000000000000000000000000000000000000f2fa494d3fa60c200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025100ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000001000000000000000000000000000006000080f8694a1277777777000000001c1d1c000000000002000adfbfe7961473dc7f8ffd411b3e2eeb005a37342e6081d5121f18f5648c8480adb28949796e09a38118152905839afc125618be1fdaf921d188488b607f2544e12a249ab310f17a9349bfe463c7de09d2b822ab0efa88b6d32f77d7c38793192b944aeec0ca94918390dbe44c50e706407692e348ed9b7cedd231941a673722ef1e7e74888672b2b2d08c97a9ac114b7039feffbeb8bbe197db4a0bca8d395cd40551c1d5d788acc2ad09eddda73a5948de2d9e2d82aa638dad6f5dc61042d6850b926d944f29f17e96eca84684252c97ce4382f2642e54208929a4b37954e8e386c677f2aee3e8f4f4aee9f76a87d868fa2210445c09b927b842485918c869a23be8213ae21937a8ca83406fab193cecfd3fcf3b1c698e8057a6c87c059dc6f4ccb30af8e608a7c04088cf3ca32ab20cd780da9443606b092c8b5d85c9a76433c0993e3eee385884ce1f3890abf95462c49bed01a3a5c09df98cb7082e9770bdee196f8b968003f5cc76d82bf575f01da3ed40e44b3b15721f4a9dd5ecd14fb71a42b24ccb7d7e6a3bc10b53ebcb7e0ec6ace91dbc19801eff0c76ec0c10602bca2cfce9f3e79536a25143d351ed2894b4eb4e549960f212f0787057ab1ac8b249c3d3ff8652cb3fb17d7656d50c5e6833b056feb26855332f60e7b8d1ebba32df63d8561fd7d209a1e5adb9853bb5b5d6a41bf1ec52d348023e945bc02e8d6ae8d5b6c7a9225991cca4aa0b41861f237b3bf545220799f152767c7fdcc693a989057e119c18a96007c69c8fe5751a4258ec3f0f99c1aea8dbbaf4df9953ccf6b42cf2f4265011ca89ec7b9ef2c6e9410886291054f50db6310b225ddf32f9db26416da6ca9ef6e3198db36ebab9802517aeaf628d41358fd141dda8fab32fcded20707abc3d00191e0b2690a1e2fa044814191323155fb21e3da8798e0bafef8c2da4c73f967504f51e716cf87117f90fd028df17f3ea26aebeda7f5b3192cd5f4855044e9a41bbfb817074ca1680a458338b191a9619dd337bd0335cb1896d79c79cce10e454b58fecb1cf10da9f53129bbf3cae2bde82007ed98505f16922b6ae53a3a709c2e01ff7e529925d6069807c06bb0c73abf8d463b2a944a97d150935cc76e1ae1f8f95159a928a5afbf76d54544a771fd4bc482ca522274b94c87b4f1c7cc3399709b5572c5133bc945cca63bad59b454ee301e3582f09c5c31f326a59705a2b534d8e9a79835bf767ea563b0aa74d3301c40a303f6fc04ba0f3807c5decb6743aabfed1a092f88975820c324e2229829462e4985e299c2415eccbdbb4ff26789b74e91db286e6a4af023e8a18e826e930d9d4ac8d92cd8a1098d0705852cda367ba067e723ace9ea8b9502e20e6519dc72b1cb477c4f3091ae4d20eb7401acac77d923eaf5de00ecbb61baa3aca9044f3e66262245aa9f3dce1d02a88e8c26b34e3c27b4e4e5f91cb633c9b6e098063d052dd6883d4c2b153c739ef78c5f375c640ff747adc1110de2f9d011118f3208bee2f3af9990d56ecddab1cfde0c053020b1116afdec7a3303fffe6f6880072482f95aa3115724814aa5fad017e3b7637f3dba509f1e371c9b87a275cfceb68aa5317dbac0e1959367d124935c76631b8aeb532d99c393374f214af2d6a3a5bf4071d97b6ad39b5b2ec03f1feb520ce467808eb2cedb3ec933c20322bcd4511b838de111f9faafb5d45ffd8edbb1fe8f0928d535ab9809b4cbf588af635419b10f7ad9f4418c766d88526215b74518cb6554e833ada2dea5e57776a09541d76ba545f8a727bbe7722912cf00da4a48a462a5b7b13c88941762462142f97e8da2b358435c9cb53d24b6443ea2e1bdaaf6ce58dbd0bcc598cf170a193e14e76ca8bde66ccc786bd330c6ce61db5f202b01c7faf185877e3614c1a1b4484cae6dbef080142f8c45e3e48485746fd3505bba099ae7b37b96e22b2cfe6a0dea5b017974126259d5055a28ad510b3b7116c27287fb7e635f1918d5a9ca2529b1741c9e86c59ddf11c3f70a56fac7c9607eb9bb36612494ed1ae819c092cfff73b7c9c5d3e8680dbe73f92b749c84363c374d80632fc488d0b7d35f25ecac1c151ad8427d7a4eacf24fa6937fd5c416776654bcfae92d999b51c49d76bd53a9d5600b40915acab5d31f0ea3f7a68adccbb72cb454164beb35819af0e9e06ecb40e96c9c2aa8018883301f65cfbaa7ea894737d49b44aa5d76c4b26bbb6de7126bf785fc2a8760ce1664150be0b6828659513561b52906e6a4782732749897a41ffce670736ce0baf5730fce9bcb50a44e1e9bba166f4812ecfdbc2ddd8483405cd2bc68ac179177e1713220348da35c7b2a30c9ad9670d99a53a3c4c4a611fcefe9e39024732d6996568f2fd8eca433a41664b070000000000000000ae2935f1dfd8a24aed7c70df7de3a668eb7a49b1319880dde2bbd9031ae5d82ffde01c599a33ae69b9dcc093a546efd4cdc2c8daa0479ccdc63123cbd0622fa54f8c15ce9a049727b659c998b2fc935ddfae5788c51772e00dd8fafb91e7b9e7b9d4a34efad77ea3f54eaf8bb5bfd4c5d5ec6761689042ec6b1639e79d2628e712669e32f33d058707141549b0a0fc31d9fe4a633871d1ca48096cd8272f735a0838bc1a440947547ce52183863bf080eba73bb36f5130d7dc8676be2e28d00714dc36ccc580d88f6d878357e7121a811a03eb12faddcb75c9c3703ccc4afdaa85101244e619f565a5635e6b8c856fda2edfc27b5c06a711730beb1c361a6a916fd713ba64385734b8563775d66adace055205c6cf9a6c90faca0629e7b93511d0e51e3405210bc3d3c590ead6671e57af44a9418a5d3c6369d5b6d294032f1592c601c2782f5e5fb7ef820f548a7e21661944982f5b04f8722ebf42456df6748a2f9ba2b816bfdfe1432f6c4911daec2b75802d43000403272e1de73bfd625b9742b8970133c0599a17cb7fd7984d6a3da82e845e179ea888019c6d86016cbef610a7a0e3409f0a2bac1181ce62a22fe3fdad2708225ec503077caf354dc5c12f6fad975509172383e2f87405fc7c387b1de333f435426fa3b8a524cea377f3c24690918a4ea2dbf4940ded498169b9b85adcd9d37175ac43897abea5d629775f4f9792d2ece6ff69dec38e38d0c1c9e40dd2967aa103a20a148290a9b89ea82e1bb5235bfd29d260862365933e19f81eb19be2c775707433d66c15f68e5bb8a578a925f20e9d1bc34132c5a214ade50ff48489b89cb674fd3a9c787d0ab539849aa19486e3d4081d4f361517f45fa35168e0432fbb69251a6a7e8f5d33b30564338f693e636d04203502588b4e9128744f49005a77e5de0f79e06053c01e82f4bc29f0bdaf3292c300030eb758fe2a7e98f41f0db618ecb99924e25084b0e69da78bb4918b365b8c613ff5e033d4994e176b5abe710fa552b3e5e21f59a33e4e0aad74c0504c2eeffcf213301b35d9b0bd3c7d140c849012b1fa7ee177e994366b9b278afd94f6bf9a65bbd1cfcf5f3525512e5b257f6a5cd61c43ff2c695cd9571d8d0e24bff92a5ace203d9a643b7c52d794b3a6a2f0cdc6c8c1527e51b32847935dd0c12b1f1aef49cc40d4318b5b067ab9d238e7dc4a8903d8ed224c15ed66b11043fb6ca6109587b6210027df615ef57125d696d0de758be6e4b1693e260589e441ebb020177a4bc7c577a7f2c7d415e00fe93cf1436bf13f738f0cb7d0448074f1436457dfdc03217b585d133dd44928779072129072c0cf0ad9ff3fdbc686f12d219313ceb77e01846f030d631c8014987081a1e3659239e009105143ff3fd3d999fb10e1a1b8f0adce31db881d5da746138462e5a1b45d47862fff760d3b1ae1de946257f2f0edd1bb911495fe1a24ec3a7cd5285e5bb25ac1d206d2f926f9dfd574758a6eb2ee5faed26e5a8e07dbeb11ba4dcfad69d93cc718fca7658b97384a243589699547d476887de967e325ba5e3b982b079eddf83998849579a849dbd3f2f487eaf9242512899756352f3680f334e0585bd43a3439bd62404297912e545e7c18e0c2e19714752b7525bebea1d83222648bc9457ff3fed4c91b1fabc6c88b5c3805dde0267f72a0abba1715fcbacce4253881625026ec2e240e8bb98c5316d28d361a91a1a572caa057492fec8d5e8d8b51f5890515186f7c97ba4a3810f40e9916567ea7a1980fd806d295c73a8b1243b538c373f531994507ae50889cddbe473a8dac128c98eeaa965cb0cdec2dce36fae175334b1dccd48839b7d28292a7c753cf23990d111e518a4260631d5a99a28f3bfd01db75d8271d08556abef553106fdc472ae97b5f4d2d3741a5104d06560d85f48d3e3acb040c3264d37f370f2acbff61ed733f655d8815983c7e78942131b41645f1ddcb24711ef39dede1317c4d7dd9b01f77066b9f3714b5f09dbb35e8341188e4384bad7238d9ef7d73e2055bb9e6706a90348ae9e5057780666f3642d7a18085e115e5ea3447fdd013a7d976d00e39edee09b271286c1a325161d3d6eac566cb86c5af3d287b5a56dcc48faec1d8342bf3c5436ccf03c0b47cb880aa7001e2c5464a406e24dfd9d021e62558e3cc9ae3228f03ddab021d5519fb426551e0a39ad08f68229662f16b79b7653b8f827a8527f1dc556a02f9e3c7d0f3872467a60340dbb0641d91d6956a33f5c905069ac39e67b40fc8d5dc617e00e89dd926bac628eb187ca1d0c41972b73b628f18159633c6d4697893bab32cb760a193b57034804a66381e62bebd6b729294bb14a113c5750a2bbdb57d40ec9e37ce7f3a486b920bf2972779b88d4ffd3136e2c10286682a4c413ed2991ce333060be5e348dde9eaded10e4cfc84ab1b157713936149239477a0b5a437574a45f24843ec4a525a71813c05c2524b92c893cb6aa0dda8df21d550371f5ac622038baef7071007a31cc486158ca1a8ec2a0c274ea26100fcfa5a3991b6f79384ae487975207d2b0b068df60c7bd63c014d13d2b5215ba7be1802b78742cee248c07cb00f3d5472dde9f85a1a9a323125a3cca08fe5c8d89f73c3fb600a4a3c7f28f12ccdac1e911c8d62242deb1ceb63eb40ffad0ae8845cc9efe69e9f5a7d2cb9910306e16b529d8e16e235e8e54eb84859d4346bfbfbefd453f9a4c8f4cc5c6c80a616433dbbcbb512651578d1d2736f513afa0fc68b401b53086d4a32d2a73100b59f8c07c06f43d17d2021fdc15410e22b5911b3572d5f7996703e97d24699da3fe7714ce74a1daa802609cc631db787abb71504d8c016cb7f5973c0d5f91899bbb100b97d4063ca590d15f176612d2e8779f89132428c6a17ce0dcab8ca081b9d891d3d0cd0bc755a193c5d5180d28d917ea7c5121c702e7c66a58b5499ba4fae3336a2040c986afd2f44d92047b338db4b6b3b6c176d88c641a6d9b4d4749654d55785002b3201ba3eb86562adf07f94b3e39bb3304a2d022a872ae74cbf27f0194c5c73037bca2d3daf1150aee2f81991aecca23660de5072568652037ce13944ec9d75f7cf424607e36233008df0a9707913985b837c631288ac62c253c9cc1586706b9e8238bb0d3d14fcfad900dff65772b36ca252d9f81450ec29d6be025262bc1104a1643c099b3bae8914c8c78cf39d09907d725a52f3ef3a9981c2dec6cccb88017805cf2163e8909eb0822c34d2b42ed08af78dbae9484e7e4faaf2a40b0762f23b491a2ccbdb5cdb4df184b2b70cd39b0fd39b8a50e4cc527f4c6169e79e9c1cca54900a1624e198a0214d8013c017a2dad0aea1521269505213c1c873cb5531b6dcaf1c5430d741514e49e7f3c0f7bea8c9e3ecddacc99e2a8e729f8a0e9c87687f11158aaa9a7159ca567598add54fdb1a58eb08da87154c59bb9214e9d63fc280ce2fe1300b12d4b805d2d992a5e5f74b04e6b41ef9e4f364aaf3f90aad6435d7662d5639882f9edf5dc7ae1e5623fb1cfd9578fbe00cf82353ecf865d9ea24b5d5050e6f7609205b2ef209c57df854ab27f2dbf047e69666ecb731f0b11e540edc105301dd9b915fb4fb1d96f4f8b99b9c42f55f99cedb22638167927766642f0c1f6c4038d4ebc8dfacf6a3ea59532d6275fa5947cc80f44650719be2802f83f62b86776c7a8ac0b92305c69583eb7b1457e21760890e8b9f42f0043af46d07f82f8aab3168ea992bb165dc7396aef85646148b9e9fa88735bcc4f2f94d70fe02200480795aed487d24810b4875284d8e51e25493075e17b7f9f319da50e339a61412cee460382cef9feefa131bb3038360535c5593039fe5fa3795bdff94b1d41e0538536a9e6de8e4a9228d65bdc5cf6868680f452599112cbb3750f9f167ed33017d61dc6b6b374d87384d3a81e74289bd5253ebd20edd58d54bd3711fed8b2273d5c39ab91cfa21b2d3a901891eff40eefd70b8d0d55c1c33a9bbbf2e0dfa2430c736a18addf449dbaa6ed37f04b5a921f945bca6bda7cc75fe47f4c8395918236dbd810406e684aec3eca46c8079dc76defdd90c746859df26c661e746260ec99f15b3bcef2d4eba263d6563f305d522b58f2a39d9f420625b2da43f7dab24c63ac0cd79078a56156ddb4a295057c02dfd02bb52511d08547ec1c0be7a7a1ffdeb550551cf0170e89d9ccf024e862eb9df3458bede7e0bc7060860bcefe43e526edc7ed295f331d5167705f7f32da9721abf972e7eb1235344776ac19bc23e6b916d3a5e54f6863dfe0f46b17800ca77c07f80f0fbe0b2a39fdd2e0107e53148182c577a60a52ce377947c1c44f9264db8fe29b5d9943ec70997fbd1759539f1c5c279f645b68a856d58571bd99d0589f444f239f194c9e73e1606f8affd027a78fec78b8ce11a3871e416307c4357e761b6836be85570d3f155e9d19db103d148cf9dd8b51faabd6157e5e80c9b78e19501489fb6fabc2c1b7de2d9f480006f0b5858eae39893f9ec8a36ed92f2d6e64a31a7c1b13dfa8540d3176e2d451b09237feca9752c8e14b48eee5dec0cc314a00cf41303c8af57c727140be157376f5182e5bd20ef43bfb73077f388b2152c79b40c7bd7360aa0da790677535a1e1ea76528a51b5ea8ceecf9babab979606945dc154ab3269d729996e6f7ed843e8207cd7893e5f8be32fecbcae63474a8f3d3e66f5ad3be91ebd42319d4d4e81377d3531f4bbb7279ba63403c9d827875d7c244a9e7a7c83818af42fee45603039becb40982e1ec43e71c919a409cebd605b865e99936dac09953b4be63ee592eb0f1bc6c8a0fb156bde6c4e05df97253dfa07ad950253f18e0bde6eb9baaad215c785a73750c6f30b36acff3e760abd513258e60d80770b4116cc7f925f34b286649676697b49fecdc8e99c6fe3311d34fcc8c4cc1f066ce680bbf9c9fc32722c858204e9f8201dab9bd6639830830e9a24830a2dfc02f767eea40019df8d41f2e0f63562cdbe55f71b136d52a61b271a24e5992a123f08babf356fd83468d20ecb634bb0ad02be4af5fa5163445cf5ae233804ea209f5c279c726db78f1c81974fb8cabc783e54ee537c9bc3c83370bba589e1389bb1e63ecf59250dcc2752fe0e1081cffb2e7f4c62d44e54a46480a809d383e81106a1b06165f419a8f3502cc7fef7c9067599af2f049fac6ee80b15122555362f7419ab7f3379cf9f27503c503eacc8e94bde23efcd0257fca4da1ac39ad5f580174c42860c91be20a8b1b95c2ccd2a51466da013a02d728d54c168eb50c064b30da49f272f08ca19099058805f91afce70776194f24a151fe36c2619df9fab6760554cbb58781514f131f1ec127a06d98e5ce4ba82fcf1165937ed258ddc9ace565827b6b8cc009b87b083119fc093a106d5f5c679e7a145b619e34f69ac0531a9d7e17ece8e335b66f14fa874dafa045603e127954d89dfcc0994581a48f54fec32d4228831dabe01d0d9f887f4604e975326e8cda35e2151a452be21a4f7117740e70bfb98cbbdaba32795fae8150ab9be24746faf5c8a9ab253cf34f2807e30a238a3ce2aa5de2691371c49b1475e62444947f632da3da60786d0f1f52a8ddb0f69bb293540830f10cf70b3d84609d16fb1c6285a4ca9ab615ea8b0aa6274317dc9c06fba50e001d00fb9db760fe6e4e751a720bb33cfa914fd5ccd5a5e5ee325805cabfbdbfdbe82a45aa53570a50fc22573e6bbf7fb641f16d01f44b9176f965b1ae610b0bf2a73fa1125b14bded8008d3d1617951e19f225d0698241746b651e003fafa16764506610fd92caf131e8c278fece483410fc3e2c6f2cc76d4a9b66028ff3aa83d4a074cce66ef035e8f2186d2ff9ed2615b0c451c8564b812f225feecf9cbbb2de6238dc4c8770a0e17feb7cb02217da98318414257c4dbf3022d8f1e5ad79fea78168c8f1771affdf4597994697e6cece2e6bfc7219d3018e3ac49549e37b8a57e0e69ef51c8944a3ed215f36c15a2883aceab247dac03ef5a82f235fea559e6b42cccd5eafc30066a3a3173bcf2f7ad34004071bd080e69c7ad3f514c62c928e63457afd2973142069ea68111c6820af10202db0396474cb2a78e1a7121ec04900d9f4ebbadf3d306273afaeaaaaf0d882dbd511146f009b748c2e093f02baac204a3b4ebd4bee5aedc3935775b9d01cab2723ce0c06ccfd5e2a8a2c8fc467c9a06ff3964e96e104890097d00a99811114179536be5457dc37864f4b5f848d27d28a6143b90bc2ae09b218e867fbd6791404ccb662fb779119b8cd2472d1f9e360ccc37f39f2019c79f365c813fd80faf189985f1704016f096acfc6bc0b674fb117ba7eab0f4138791416638ba365c546180b8d5662bfe157f3f63430198548216d7cec0ec8724ebde55883b2c384cbb67b2d7179362f9114dbbe561c8acb3d40ccde56ea66cd7c832b299a96f3a0e0aebb57e9246068d5fbdb126e6a149f7ef2214c35f30409f1b44de792cd741df0cf48f273f6dcafd69547fde219908a75b3b594f45a382ffda619f7e1378df37a8b2a25aad273329002ef931a95a0a7b670dba6dcfc08119783f60b84aba6ba878de6158e689ab051e5ed1743f6fe28a3c061198e7a49d08a68271205e4151c49264929d9ba38dcb2559f45658ce96b2c232cdf40e63bd8828794ef664543bc2f700a65d7c86f218a9b76ad0391906f4480f5563b434403e35eca1079d8c1f906a271ffa21d669a27883108ee78a4fceaa056c0bd5aa4496ec5f37b2dab8b19abc88c61ec5891759c6fb2263f534df3d7116d6874f42d8bc3a1ff9383a68ef3955295b5478c28308c79ab25ae9ca31544427a2cde901ea588ba872f37cedac395f6661ec659f1bcde925f6a82502b32fbb07d4356efda64e82c35356f9abaf5d3f0abbcbf0b0fcc2191501aeb7b59b21e00858b19492aaab25c62afc3b0cecd3d7746eb6cb1edb0cdc569602791a17911802c9f5ccca92717ac661cfd4d4dd8bcdec75492a64bdd2150c2235e7d87759e137b213cb3ab4e275a99e4ac77fda073e2870b6486ba384c44b4f59b382847a5d0a4f87198a996e639f51246014a0d9751db9f85bcbea056a7609332bb1e7ffee3baf262a346e45697d9c97c5ef099e109251368b5a807e6b69c1247e8430d2ac2261aab0ef2a0f695c22086b86fee0adb6bdc8a14af3d02ea0effac0f6f55e8203503b48deb8c8673b92c499284b935abd06352b391c253e35870f024bcbec4332f578a74d4ab0be09e73e3cbf5e1ed7e53eceeeff4ec26941dec578ce3a33f701bb540da65f810e7f4df368804cfcb6078c99d45e4f15ee1d1ad6831c3e6e01102e6ebeed1f86940de0759b256594c9f91041716bd57ea464e77cca292090f612bd7daf20e9b534bacf13ca7d940c90fa9c18b188fbcc17e282edb1156cf5c1351a9f118dcbc5cc720c5c6dad1ccfd04f1beab7817561e86442665b841c97150d10395fd842b54d025a221d81f05c820474e492341a0c6dff31f4a38ee089082f7bfb17b9d8c8355dc76bcefcf0c7692ece39649e85ddf7e395f1baf893eb960d8e1374e84a1d32fc1924ec5808c1255b34946db13ada6163b368754820d519197aceb746d33f556f9932aa775b5547d4b42ab6433e4adfea54bbd7d173e622229660e74ec486937fba081cbb26de3ce7f6f76e070cf54315f18b03675cee1c06fc765f145b7fe4fd12f897c83e21c299fb9614533e163564b9d3090cb00f253029a3a4042e2047cead0dcd42969685de183ded532773056cebbe0242e9bdbf079eb9c8b0a64df4833ad35fc40a317e99070683255e7087a0896b20e0b483410f9e4913bf36cd028555302162a6c6152803b31b8dede9717b80947efaa233f6324941e0714473c92da512fbec873e4b745505a5e691e2f1b6dc2e98d1cacf4c1a42dff6e360909bb82027b6ad070f34ea2d1bea39653da363b2dd14633f5d0f11cc1617ab8239e9832b162b2bc18d8703a39a21ac2ce9b1f23395225f6b34671d5e7679459e7f86391c80e2e3c350220f3f3cb40e575fd8afae3bbe1104246b092e405bb740e213734a5a171aeb6d82b185973a797cf3f17d77cee462e4f3032d053044aa6d8060928f6227bee4a2ad6f7cc6bf49df364cc75fdb9c9aefda07130967032ecb5a29b38bafd4e6755e2427585746460d696c9481db581ccd583311b68da1e80fc45b330e7fc6744105cf7f329effa8d05e5f04f891e6a45c0f620a1c516f22c796523a325d03aa141674b2d257074a20a7b14308310c73ccefa815f73715282cb467a763532504523a1b1fdcf2ed3af8381fa967e02294195a9d0eb43a1f5413be08d6e9ac6e95ebddb34f6962bb64dbde6e94bf734cca4cd1d70feb5b3525d1a4f8551facc79b5f00732cb252e9df686627a56b80b13fd033cf279cfc12ae321a0fa58da9df8da8e6f9f64214e40c22334f13bf1f6da122b4673deedbff3f98958b53af0f4b40158d79e63778123cc6dfd55f43f4bce42f318b0ac418dac56dd9436e78bb527c37dfc28180fed5c439f952931b29e271d83b633effe9809a6399282048357028ab1b540cc0510ee6b19a63643714857fe51c2b1b2963b7964cb602861e81eb52348453e9bc497c447e8a8eb73c79f3997ba17f35f32121ac7b0172845bd8caed56a79285e97d17aa467312c4d10b8bce1d18e416c383b128ded04fd1724a29cd8fe9377ead625ae91efff1a562e03d382e4b4621b28f717ac6fa928dac4a086aea4e122d59f28c961ace3dea0bfc79eb62a5702870bb86a8d82e6284b39f61d2c39b7d99eb65f319cce48af91a9028a48cae8c3c08134f7285c9e7161a570947fab3497f00476f9ede57415cf5889ec18501783af4c371a24560a3046a2683741e851ec1c34fe45c777ed5cb03dfb8ae6648a1224bfbc723f1a69a9edc5ef37147baa1a84b199be1dd645dcc0fba7ca9e8365309f3669b6d1d2e8a47e21d34d1405e6530e0d200dd9997ad72de1e70e660dcf53a6bc4bccd999214ef9206af79b44915e9956f8a019919290066728eb9ae5ccf073eefa4b9f771f584c03648cccfbc1823d118326d7488e2fdb2319df94a593ab0bb34c9970d038dddf2c174631f7b73eba3e6fdae9edee2ead25e57f4c498c32a567c546f089930cabc63db6421a25915714aeef8d9ccd320237cb0e4d302fe1c964c4aaa604714105a1228fe5ad6ca7f42fb2e07c7d6b0bae5f3b320f59e9821d0f66b702e0bef73c4f3d891454e90599f033a96da7df2faf22455f49e28b10ca126096573ceb1d4154791bd607ab67ddc372cdc3da2957e67ce2c599d50b90710895a934fe744c3cb75b1836eed5ac9a549c28930a6388a7c993c7d5a5aa302ee7bf08d177548ecd98c65152d6197286f52b57a3f918218fda1241e28c86201d6e3b6ca12d8e6756223bf9b19387c321db1a0ea2fdcb7a7705f7e8c81a998368a1cdb7788be5629a43704d8e91662b3e1a5ab205f85a27a139a5dd5e40cab92e6dcadb5be50ca3343905fd10ba97df8aa658634c914db6389809d9b18f59fbe371733e5ae1fb35f0f6230a2394119aca72cb11db8a0d0c82a0313562b97528fb50b99f21e3c4097366b763b0325a2f8875b32cd4beadb07925be74aa54aa89f9b52eb1394e1863899f04d7fb451fdb81fc4360a3320dc2a24b3b2c0fd463d9906b0797c3215595d59e5350da3a8cd519d51e76904a80d73a163b384fa68002516c7d7efb1f14aee9258b3aab9c5033b8d929430ef742cc88665799fb1207f2c8d333db1ac85d4c15235103d28b3769df98a763426546b21a8eb0f67872edc8c9d448b8c70d6f7af172d13c3aac5d4ae5bfc8ca9c891e501f2c473eac63cdc16a96b0f74cffb89211a411b0e6b4a0d794b5be83a7cdde651573a142789aaa6aaf76c7f6ba4851d1eedce7feb5f7a2c1179e351a6d97620395b96850238967e8264f581ba4ad4dc85933c874e30fa3adf74901f6ece0504879356a835eb019e12e5761f5555f63c91142c59cb32515de844c0284a31d5e148b694c53e3c69378a1c2880e893fce50f5ebb5b46b7ddc8753e7104f5effea9b0c36e3720469c3f20b8d97cd39c06cecf7881d20032be0f23ed939613cb0dc5ac81ece654aaf5ec36ba427cda4a0031328afc840ffda24b1829153682cbee0da142cfac74394c073def27b4b38f5cdc1c7b699d281d1fd41ac559410cba3330d16c74c8d035ef0210c8dd151a3850db594502d1d50c2959301c384da313611e361e71e937a5d1799d1a45398ce25b1111c86177152676d64393e6ed1f11821c1fb5dca4cddce3a3b1e28975d80dca762c79210222f6771d20ac64da695035d00dae321be393b17008e5f0037f4c1733e4a9f17ce275a85fb44ba59edf9e20403843b11863e4db333233314661bfaf853d6269b187bbb6c0eb0f510d4912645056813ad34cf3bfe5277c589a0314bae0aa802cff46b510c6c76938cb84e921f7b4cf4200da1a82942a807a2075c0f7dfebf768b54b2e308dc49488c4080d6c71c0bf8d773d5de3cd112c588a8ffe11d7a17534a6c7fef432c380ccf252a10d8cd1fa13a5cea6e546349923de83cceee44f2981984fef7144be4e72ea0c149458a7aa6648c9f658622c00be9d0074d3b0d498e475c8e4bfdc9ed4ce81d3aba532aabf7e18d5097ce37505c2dfe9df59a6bb30fe45d62c8a1f2b065ca8bf74f81bc3da5ea3bc5fe855ed0f0104574554480151238458b0d0dd6d493ec964a7462117237ea214ab8bb54b5a7d9e005f5606865f5c7c04adb7149725e02ae803000000000000c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945862d09879b6ff8bdded4f70af68cd3e81dc71a4c671032da6cd9224a5c6c1a660aa1393872b9170453d05c1f40ee3bcb8f727b3e196cbb9c72e7f12ea97080f67e003c99764d0dda139b3165da5dc4bf9700c6a563fcd0543f549e7b19d4cc4caf777c3aac4386f3bb692fd45d7197df5894f1c9545709c9c2255a3b6ed950385ba5a7c9c5fe91bfc671695898f78518380e34231b3e36a49b641cb3e940beec0062", + "040000007d24b5bfe1999a3b21189a3c4d4867784bc2105a0196aba2ba6fd1c9a63e22e1be3fd8ef559f3e7d94c5da9f3ffdb276804f413014d8bf07fe14907d6a37659320e538c79c0033eb2537c88a69d77f048cf4cc4fadd09c9bbb91b4d965ac8f2e0a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025200ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000002000000000000000000000000000006000080f8694a1277777777000000001c1d1c000000000002ef753da29c8538cbe9669c722c10bec5663e07d101f0a6c3f1f86440a7b00dbe374e5118632c4075f9e84b6c62791de12f1ec0e70e7d415d61c6639d786b1a0c0289051e9e5ef26a5dcbceee48051ae1ee91d70e02022fcf954f3d1190186523ec4cb0ad65db85d28e247bc1daf3fa5b111983e5d328166df852374f3efa9430f7e7d5ef94c51c82437ac68d11f78c190ff7314fdfe4fe007c0be3aeae7bc1094c0be2db5c7d2b24faddb22ac70bfa8499783f312f0bec068f8c09483f7b7edb6e63753d60feb460e2ea1f683740eded3d994f602670d174d38dd95b2a151d0b1d5f2592bd522084eba11fe9f8fb1eac057b84bde9119816ff74790db723529e8713c8daf25996fad08f2a78ceff248ccc91a83402b94311946343866a6dace2226d246cb8226f2bf7555640d4891457a7f6bb6c85962a5e482ec760b6d6483a15f6b44108c2096492765fea12c37da638a7add8d0b74b1bbeb5784c3712349881b78d229a682f024cb21c0c3961704a71ebd54be06a17f44b1fb1926844f14c3a9eceb626fcacc77ddb138846bb40f28daaf7e431d5d09d6f2be928bd09b03f6ee2302cf572c781cda2167d7d8e9b1f4667c8b3f7621c0cf85aeb45462eebe743a33bebb34a9d118cb2d4a69d2038d591e3266e77e122f9fb889ab83325e5d2ab3bea0e85e10cfdd1508d3233ede0b9de84634972e6d3cbcf9325407c43fba5c9dd30a70aece3ac6ac3d5598fd2dd29907584b85398cf21879b4e9ca3c2066e65fad046e788e56fd4a9098b5a4b0fbbe12c0f7c0b5caffbbfa69e4289c9cca89ffb3158dabeb2952a6af2bac251010a3644c01918e0198b835da28e26f694ca21d897785240d0477cadd8bd03bad34639189525c02fea6172168722cf2ae9a6b51412b4f9b24495b9b2852cf045c1acc6d97dd0d6746dd116cf8bbce3258c862e1fb18a4e91d9118c5741a38d6a7aed613910b11cb881cb6d1437669ad853512778ced215ff5b460a47cbfd30e86f9eec227fc123262d73f45d71e66f17492af0457191e797ac9fe6149f4b3cd631dce8f9844bf16588f55003371165f0e48562a11799c33c5b4e4dd390b3943fddf0162c033f0751530acaf5ac2530f320c157c498452ac5012adbde2cc19339fe82e1ee6245dcea9f587a40f3b78600de1209ef9eb6a903d267a95742c856aab1829fc8974731e49b6e8f674eefa81b23026d0bcb1d770c31a60232798a8828fecba930b51b80ae6b98645be3c5b80b195828dfab3bf8763ae660dbe4f02ed5b52abb301b18f3ebf8f1f81b8feeeed620809673472aedf9d70ac86268b7a162d0f46c0ff6bf52bf5dd289a9f34c19632198cf15730427971369cebadb6e943a6d8dfa84f83f2f6451e9d155449f6ff1b41f538eb760edccc3697ef679a586c8295afff2cd8de2ddcaabecdd1c0b41e8db2790ca35e263372e2aadc2b579fcd47d74bcfa188dabae48a78eb8e32e403a3f4bbf86b8535c568a332e0b64de3b3ba0e75a2ce01deefb1b1faa6fc59cf602d1359180616258847d458d03990f158398018e63abf87086caacdeeabf6daf6965d184bf8dac33b1c5af2223168e023a2f5021874300012761f400e35e341e3b54683442a1bbf7907060b54181d27021ea69caefe8326414462f03c44eacac9f26c8a37a8eae78c76dbe19d33f6b198e8a2f4d77a2d50bdc9785518a1e210fea6451bc05e85bd106737ad37e9c96105db1b9bb09bd7cecc45960de0bd6d803913fa43935a8c17de7bf573089ec323b1aba8f6eaf0603b91e53c540305cefe8361dfe47b787257add20569bcb7aad355d93dfe9d28443da5662fd1030a8e251fef553877edd1e1559bba63ebcec258035548d037eb34276f4b256b22631489e8f7201c86537a53502b6f9b4ae7c2a7272459a4df0d203b7399ca1bae6b5260566332b955e342132535e527fa207f8ec9b0bcf9442b7794160497121720d2fd698e3eee28fa34de2321afe580958dd133b1dd2b36afa84dbd004c4a571afa48466d3b7915c84753186b5a3e7b724a8fb8e411f8732b963fe81bbaa48b247330eec8a0897ebd64a25032e8aa4c987ff8153bb447308bb3cf5ab699504746794711928457df6e10d689d81cd6a846123375f5c46ed603f14b0ac6c9729075873179c3bae9740c273d0ec9e1ce060285211c4e60fbd2801cae6c7337570601712fb81abfc25d9a43464541e13bc42b02f01f8ec78a7e5dd3e84fa9576891397106427a6ef262e11f24a55af39caf98130c69bb042475834753518d2f67f66c04d81c574eaf7d8b83bb029f037c4999159186e170752880638619096dd852f29994be72f3a6922a97610fa11085d4288214fe131d2243929d40dd5915a6789c77a499f43489ec2a0b7ad37e7b5070000000000000000dcdeed4e7121d043c65c8049da787baf0bb29c59b75e9608dc59b97fb001c92ffde01cdc9b9d97951e4247bb513ff71eff5413fda3522232fb7d7bc48429bf301c3bbf60c1e5346e6b2412ec70d7ec4091384f5a9cd1feddbf9b02fa15e591c1f86bb9ee9b65bccc11ed903646e771b8d252e63306498d3b325c7cf46dd9e4f8e1e385bd5631b11f427848e7fa3bb78f8f97d090ff15457ddb0030fa9a8332dd2ed68ec267909771b6ee3edd3370ba34516a4a7171680d2d912e2fa4c966942b231609e3a4f5860f35991d117445464ebf6049e31d0b0eacd23a11122c2cce82c6f72a160e131c588770bc6df3888503df8add4f1285f1417543f380479052a2bf8597f56b0d5587578c3b896ed7bf0e057b9a39ca8ee3b1abc2bb967bf5fd7064150871024113211114f203ce5f150e30ff55747a6ecd17a342b77fc7c41ba70e1a216112048b26bea002606abde584d49e7cd633b7a5391290e7808978100e2d5f955cda22772bf642aa0e3b4e8f30edc8c9e6dc1d4952160377205a83730dc58516ad5d5f1b121f397aa2d43f47ff7a09b602b9c61958a3317d2316b9c8db14e40a53e88f1744655a81b850ed7c9388c5388da56e36ed67ec15e15b52cac4bf47a088df916d2c70c9bb348640cb429cbed26810d8fe2218424a6c63f1dfb5bfd3277bc64dd12ae6c088d7f55c4804f6c8bcfd6332bf4d6edbce09574a9c64d3fdb1e41c4d17a403646efc749f7ca43eaf94b014dd269c833ac3e19bc7442ab86b815a9eaa9efa44d01e69c77f73f600c5a911f6e50b5713d079c855ddcc2ba6462077f5d170cda9bf0eb8e477095aad7cd5c081864b328a9cefe21b44b53ae46d38a66f6aeded011536310c3bc0dcf64d2dd0c9015c6c2f83d36d146f9bc9f5a627dca73c5e092953815715ce9ad107d5450b84d449e0e93bf16a4e03d8b15d8b938216cd6c0bc08ccbba0658391f8d8cccfcecf77a85778b9904105bce80cd8c15e38114a80fb6e6870fbc92af588a905da1de9cd58d7c288e7cf406ef916c27b1b4b61fac457fa6390d7a7b6c14256c7a87fd510806be27244e778173f993bf86ff5cbe48b85178c8ba1d529a974a00995ccaf42b64d4e714fb5df79980d79492002f7e220dceb7a14769cff9c1dba91247cb300eb8bfcfc3a85e360266fc4b9f328ba12a6098aeebc67e4fc9aae6762defa078251a0d9653cdbec24fbe31ffa3ef322e6ba7c7114d0f642b72c7ea2688505047248fb18b8321959dec8693a1ab349c16770aaf10889e46d8d8f508f3233a69c9a820b88fce5d5ed044b9cd7420f456459d3ae87a23cc72d3d9c770f94c82224d95426e10107ceb351676c1dea9f252470ec81a9825bf0c2b4a3342ffd702cdb306a351ef3bdb56539da5022b878e08549a6ec8d8773b44c19281da0e307614f72a30e46b73f8db627c4ae9f530c0ea6ea523a6b857f96acdf37b42808ffd31fccef667f92d7ae7ee853233308d0e6a61fb0f78f1d0ee35278788dc3f7585fff3688ce16d40da875b756b2cf4aa33875e01404fe7c74614f184a5eb458acd986abc580f0cf2517110b9f1239615194055de68c7925573faef91ec11706d27b7b672b42b323c32b25a796e795baa58a7dcf5e19a46f21b27bb14e2db080ea704f7a1d15c2ff114964a65bb7429a216ff96939999a743316b073d63cf87ec39d924f6e7658f325dd6a77c9921b2b21f49a22b1d96155d1dc9a206a9d521a5b3372c397556febe9495bbad48c1d9a50f0578bf5e0fdaf8d0276c1fbcd0eda0a5b72ced1fcddd7f6dc0df854aae139d42527db885aaed6998cfe1daef4865a39fccbf57673eae767a975e43f1b198185b1e37a7d1afe476cc35602f148cfee549147584f19255d6cb3e31def73cef31e3adff8184109cffcb6aba6e268367a2f1d803604aefe48404ec5b431c13dbb14374dc9e118736b43f342a3c93f57c707f58dab5f2359f88b48eb85c37d052105bdabb93a8e1f2866330f5548252ffbfd62b448fdeb777168701bdc6136a22bcc048e3679f6098c00ca7151267a4bb1c6561685f5f6fba0d1976a6b7999257a1e4d5155020b124f65e43dc06da593c7fdd96c6fd84afe493d2ade3624fd7672fc0fa7c77d97bea5be3c865655cc77440c7d28ea2cff6eb9bcf85780f2ff0e4215c8c18f63012aa4067fc1524e81c1b9d2e08975b0305c2a1add51a9471c9181835d923cf51b854cc659616fc1932e4997b2b3b737e661945abeb0d9b1fe3c113c2b2a8b371d8630927bcc23c21faff67fc6680ea0b3468b8a0279e3e160629bfccc7f1aac37b5aba4e275cb9cb8ada5c99361c70125a45c0536a9467343dbf1a22610ee2da7ab15fb8d3c5680cc447458f81523ee75668a3f75302693169b7a20349c35b77ef8e99cd3c8b852e4d1871972415de7b9bc9859697d7eab02e559f03cd57fae9e5d3d692e617a2cfbdc34eee3c9db4efdad6f1fb19a7c4907db5173f80ec204fe16919bcca832722c58273f8fb67f69e5d8b24c285aa1a74581f0f9d1fc11b42f578a1eafe7a7dc2c6f11065697d3207585344122314bcd914733132cd0bf5a661eb329dae384c0a85f559932a49d31facb17189716a38b20e3f0c0f30ab4686e79cfe9ad03c00fb0d726991869b6c89ea25da9450c3d6cc5bba1bb17c7a3c38962361890e3f7e24ce94253f63e12dcff3e2c3d045ad05f45ad9349575c7ccd0cd82fdf1e083c56dfed867382a4cf758decef9c05bea3138ca4507b7f638edbfe8f1512911ec00d4379fa996b4d64060078b95064cc81e92aff21e4b30d0b848a8d8d5ceab8f665e686881a79bb390d75f94c593be007bcd38d10de1e750df1a9256375c15e2bed4da66082248abb6d6660ec9ef6351125c245527c3b13e22d77ab516f2457d890f9dd5a6c8d0a21a4d626a5fcfc4bc3a427b5d3581830e070fc6b4c0ac8038bfa1aa52b12b0329410b6b8d0d78407817ec0cd708eaa5215921b14e113e8ceee38318fe47f3cf5a58c1ab86a6eb7734170e55b5002ab3a48cefe62fc6c897aeae4ef82eee968be5b59bf329cca3d03ad5dd38dc287eeda31de96cfb4ee94eca046b1d9e83632f1ce043b7c65782940b60bc0f9f35cde82d5623c83c6d3540139ba820af7bdada01c22a2531b1e3171e6befc5b8289868ccceedb49fe28a32bee69055d5e167eeaeb320832e0da67d6f536b7ea5226e86420f72ee68978a460d1a5f5d0f22e7b3fb59f68489f757581bb4fa107c14829bf5b93ee95f76a84c2f08514f73aa5c062585b57b02de19dd4039afc4480d8666cef6de93ea111a934295350433ecb4d7cd9957a0cc739439bd5308449d3ab744b76f429b3997611e9edfcc49f021f65645ac5524ddbc8fe9f49d8820633ea37d9e9dd5bfef0912fdc1ba80500df637ca3701122f543e99df4f528519c6233fe9cc94e5d2591124212b6a7711cb083018647b0e7200811aa58b82b5fbb10d347fb64ddf7ecc1e526d69bf7d0bf9ac4287ac42db1e4e1d9037ed3d9624cd19c590c460c87c71e7c5055cf0b78318761a5e5b8ea36978ac18275470e04d8e3da440cc7fda0b2fb7857bc2a0bda4843a60d21c3bfaaf7e32f16de155a161e01392be4ef0ab5df2bf0b18a0aaddcc364acf987c625c20fcb90b22e3a0bd6fdd161780a58517012cbfd7086a042f1e13b3f337ed2dfb4f66635d188287bfdadc3bab7a139c3ed8d784c2773836618e440f2f5ecabb712c9116a0d8536419ce663402b427556e899d12be13a588c66565c60fa3ee42f5b21cd3a8febc2b906eb91a778baf31aceeb53acb3556007cd7752fcda896c3a4a41cee337e5e63a5bd7d3d9be234295ccc93a1cd3b4c171f3a7210306901bcaabea6776909baa057ec840813de6ca414318b10d18787403f9ae1a57d671cecb824163683d2e8f3d40cd916a9e6d63aaf5f69dac13bf6cbcf9562a915febaf7d95e8fdc956018e42276703719e4f0d7c698051290d59531e034f884fe7794175006fa69b6b09897979881187a31d33c3728eb87e0562213ae81f502108314c35d590b02b4484caf58925d3f9620e89d5e4272be9fc2bcd587d337de2b815b64ebb3dc542dda0e64ff6d6037fff10941f565cb6814ac3058945d4fdd79c3f97819906551441b1914a4b6c4346a34d7d05315eeffa813cf95b83767317386bc21f1456ccf52cc983777764c02dd9c5ebf3940c19c8d4cd2c1e6366935211884e8aee011aac2fddcb0646cfb290d3f7ac0ea8fd1ec20b57f67a28a470673c4c202eb57409ca729c4ffadcb1828daed09ec1223d758548e477e7e06f8d9015df9a40b964438b2c59261a8527d0755b468601d381e60826627dad42f680f33a83027246eaa154ae2cf04ce7cfd0eae34735da1ecd1b408f4d41a9278115695b16a248cb697366105585a863b4629f6a6899d77dca911091f73e33a812f5baa98b3460edecd6cf2bda734810a7412943426e8d8e00e24afacc681379b92978ec8e049f34b22de5488e9ab25a7bd135ddcb766dcc95ee688268ef957b83130c6869bcf0bf43d606209c5071b00e32a20cd6da4bd4cc5492f435a62561348e3769093639c533570f22b9ecda5aa7c2773753211c68672101694fa491eaec2005a9cc439f773801afe423675efc54e302fdb5e09b895316e7ac8898343bcdd91ad238211e3318ddfe0d86c5ae1c6d83d791c52d9b35496b8ed9978a1c7b5dd00bc6c9697f39247238c2042258025121816660ef0c53a49995cd9b45ba1712d45695472b69d6757e56c572c0f290ad6225d35ca5e5f564ad2c3ac7fb0aa41ac346ec3036adaab5000b9c58d8861aed031b0e627a1e665c36dfceebc558f59df5b6235ee823de9d185d171a9237a20811d9b5e4efe508fb9907d25b6849dedff9e8d71fd0b2cff2f8ea8cc1a7e98b204295f267dae98a6476d99f9eb73499fc918e2db191b9decac79eef1b046e9958c32ff1c8bca28c125b2b2340f980219d5cc979eeabf2b2dadec09e43ea4bb67b136dd30cfcda9dbb611d899e5c3656d46bca5b43affc771c9eb1697b10936d6922c17baf10888d8fc10b4a891d4bfe5ead9136c4f79215c61d4796897fb39834f0440db29202211d82d2b16e69d9398fe33e22959a4310d274c67a4dc9ae6acf72abd13a1afb5fc319c3d5ae89933158c91ffc851e5e5fc854b102a047a0d30211afda1cb548d279fc894f1002c3721e3229519b560f0a71bb648149bc763b3401b9ad57704139a85d936bd0879a820f90be6ea7d78b6fe1679d336dcc2f776a3373e473ab5ee54f5e0a8df6114fd0e2d88ed6e7035d232eae1e4d785b417a43e06bdf7bfc3509bb4ad808d39ca785673436a1009dcce6cd055f10439de64652c31dcac2b65ec47264fec73581f8598f8c318bc0f8d0eb929e7c4d6e5f012238e01e19b1fd6b54feb463912e6557b65741ff8919434e44e04e41a5caadb74f3cc0254541c06faa480499326b7146499b55a2fced4dd416d5a31779c8de5dea938385217832cbc605788ff4fa96e24fdc3875b52769db18abdc76a687974925a52081043864ee8e39574d7f27fac30650eabb1fe70d5d7bab946b234d1b8ee449f08654ac868a22839924b9e7b94175e60c5b575263089b525f40d6f76570d2740095a43696a90f486332f45f4f6ee2d1d55d4b3f2311637a9e73f921a56ea0529104573b25b2c48307adcbe3b2232cc04933dae07c34c491099c57dd7e4b393fe34db10623bb35b74ce92f8b1892d24b9fd88eb7cfc3d1791b0bc3bddebcf42592093e6ffde9f40766ad3c21a67caed25b8b250946ec46773565fdcc6305803362274e612308b8b767423afffdb27239f3b9bcb8e70bf0ee68cc8a1af4e59f6972d7c90b182d862066d1b83ec044b259b398840cc736ece77dac61d07e4b338083a97146137dce132a2a8a0255d1c5aea80b5e0095b6181dbdf1fa23317c74c0e25cb86b08c4136065729777527f49f407256d36049e4c236201174b312e80090376a2113d62058b659f63de5b8695e52fd178c573ae0e14f205cb2fd929c9f09079930738deea7a2090288911af17e157d6c9ea4bc04f6264c81e4f3b5b087fd17a7c0b7eb631c1d1476ddce8be398fb7f576f3f01f98b823b7e8eca7cb3831c0ed3c036219c94ecf5a0c2d112f788d73a432394247fc0244de10e28d4577ecc084c521f0007f3a6215a549abb3091e59c6d6cd674c8e5775acd276c980033df3c2143be0589f65da81bfab1dff81e6783f814980bed3cf47e51dda6424ff43c2a82e966c7ec5b197a73cc580919db591cc522f87a561ca46753679b8d26110d1667bbcc24706633f219617f620958cfc35c1d70e034c0555bf76d9d854f8e5a0a973b88cd6096e5f3d2a72f3196f4bd42b32d6849fd37d10df37225b0cfe05c1005ff528c59352ad6e319f77da2ddf1c94b8b7e7c7a25c7cd15121540f31ec51725e71924c3616257756be8d404b53cb3091c6c3a11940c44cc8808426305550f35f9a4c5322222e661561bdecd8ace024f4c2fffeb3bc1bfa7f69454f6699d36dc42f35d78130f04b39ef392c5969a4d8de6d5271ee7a32af3f311386857fc0c21d053bae00a066ada63a28fd84b0fae439f1060a7b633ea07813863162195125e00d9c2aa7f25c11c981794cc97718f22e3cdbd21701d6f6f5fc25885be6330ac8b8266bd64a227535648a926a002345e224cb6bb4ec6767c1f1511c2c1753def927f97f9fd620c27eae292cca484472b6fe5d68aa58d3fbc772153043073308ec7c0a37c5355c0bdd43179025aa0e8d492353849fd7accf1a0acb7507f11281ab671d69ceaabbf539eae572f0015426f5e9a57e8c4d4d92216a93027572c11172cfb505e590e4d5899aa663a5ea32d5cc163ebef26c92908e15fe3c0705d06e32504c7901bebbbe7de2bb3f5ec28dd50299d941b24242ea0e151d747e129357f4fd6c98876dd0779fe40a7cd386f198150b43d5fced11d2906915937905f104a9ab5f0d05ddf227110e72a6c80a7878e559b5d8b1fd632e851633256254a22608358228feba5055a91dcfa6f702d55b8a463f0e0dd4af11872694e1b38ce25e8f8b4ec993d38223eba5dbc585fdd5ba53b179c20a278181fe3a0d13a7feb333941b59748b2b06b2c51d6c52d0a8bdcf833628cc30787d9d16c0991bb5a523a92da788563800133ac376a6feb09a8ce1de5c1ac1ce128272cdacb42b9592611e34bb0848a05f3c69e274b33481fd2b351ce7562413c2b2eee4cde66944b64103734d44e69b9187d0c98ee204f539c59b2374eef044e731b1bb3d06465f37d16634579e24f7ba512a29204e0e3fe7d89809914e41b7ad8d17e5ac11af5246b2192c833af76bad3906f95683240ea619360d9a0ad9e7e97777e2797180447e13067cdd4efb5ee7429fc5b97e80d3f9b8396b8d2df51ac47b434ee0109b0eaa22f854d4de4ada9dcc003a4a8e147ceed375d607922b59a50312813519571e2a526774b1241513f77d2b53d3d435f141c55eddad14021ccc542ac37aea8e24b9331fcceaa35dec147c114e181e9a6800f1748c3aa1b425d532da7ed19bf10ec5304900d6f685acba0fed0d7bde86d5d5dab0fe046efe66fe78b886d24c097fa252a7a9151e7ba2cf15798d1cdc07904c8f32c1853b8e79be4d344b6d8820005ff2e11ceaa7833e1de67fa3f64637bf20963bea0a981ee810562a0b8b2dd532e01140421a975d2e7f39c3988e99e5cc8116cd9462e2f405121dea5a03616d7fcad17ba0956b84671d94c524efaa13b6b0bcc15b98b6433619bbfc9736d5432fc5237b9a018b716c2e08e4eac57d2b7c33ffd813816a0b01f7d09a5afa082e1d10a327247e0f086f3360dd6b9b736903a518390b887a6dd2f5cfa65322e5fe6dd801ce6ff44388ecfcc02ab12c562f55484cbda45465049da5aba32131491f3bfd92a1f9e85fef13e622e06445252fe64b42680ba24d09d0cf28c9f517a24ac14322d57761c1d53491940ce65df7c1ce7b6f766409f66f6ab4a9b455df1de0316ea2281d48f8f2bfa74f001509e7d2222b7931453759b1cb0ef887335e62bf97aeb1fae49095be74c11f89ae74297e22a342f60ff851f43c1e695080527747f9326097ef0a6838a1f46daab1f109c4e921beb2ea1cb6a334dedc57e55e58469aea61a185933a8a4c5fcb5366487d36541c46f12d8b830ab05c415cdafeb875eb2031e154fdde2d07437c0297ba56e4416cab08544013b2728a42ac6daac513c436f3e07dc6aeee0957297b17c242e221c41187df1fe919602d84805486c0dfe8ba108bc4c5b95c300bf121307d465a3b69f99fece83b1ddba11e3a8ebde80cedaa52c7b5acc9d0417064415bfb6d8ff6ff46444a62619c9321171883977194fddaa0fb059c29139fea48955b1ceddae3ac8051923472d23f06773f49e6624a8f2ba23b36a6c574d85b40f701d705c983ad5bce01bb2d031617bf8b2769ffc90d2ef086be32b2e84cad752afdee010c8e26ee09ea95e963b57e93188d4af84a71a5224e383a0dde184ed343fc59f77620045b9d6cffdb1a89ef0d5cb7e853810f24523a211f2a2fc19a49729d02fbc51b9674783ed4c7c0ef070c6b47413681ee65934cbc65777f92d13f01879a5851ca57501b5cd016cce8e9902f4379997d5c75b3558161552ebe9eb325a3ee76fe87bfde3d2cb44fb9009bcf14ea07900a9e120367d6a0253fba1b57f388efab647bcbad82a4ef8b5a7158c3d0ddfd134e568c937375a9df0304080a5ae883ec3661b176c272c7dd87aa40f209c9fef9d07bd102818b55f3e7a8c0e06dad914acae44f9023a04395e12b1d41b7d425634c748713a709547376cff51e864654c3b24b19d294b99c5e61abbc2f270163995512a5d042d94e1df1b49bc9f2fc814d7409f97758487ea49b276ce60ba980b9e2df67e1a186a18ea60ac743f45714b80eeb90cc06d7158f6cf09c54a858fef698ffe7032c22de1618bfd90bbe8dd7db0aba29f53abf0aca67e1471bee1c871bf3595f423213645b9dd88a4153c7dee3845194b496abcc0104997fc89eebd4fc72c5ca73cb5789cbbec9cdd9cb0cf9117718041860fb2073fb3842c45cd1a8e44a295b3166e1ab0a5a18aaf22575454d4d3750aa838944d1f5caf671d9402cf331785d83c50c29b2e49d402ce4ba32516fe1b37c463359d7cb780d3561ac8c6ecf1626d33aa1b482f343086e740be27175fbe1cc6ff2f798b9cc96e2d88baa6d80b0e443374cdc7f11cda7def2a1875595f6980d0779641c9777632f7a5aebeb48f3e9d01c187695217de185ea6c99cd47b321c53c26a83cd2f749612ca143a2a3a594c2e80c1ec90d98564f2a69e579f9713c20af6a559f541514a7514b8fd88165be486e825c3de6899e97f9e39a1654e51ed9690cefd5e225602e68480e9f2346b3f8d61268dc5f6add54484b7f4bf8fe086110f74183a0bc2515056f9a0bad6f4dbbd848d80df7a24d5d92a6b6b2b16fabc0486028a13b67a2bbe17f9812ccf6692327e78a5dfeb56feb6dda38c9ff2360062cf7128f357ab4b395b26880fdf80dd889ab809da70b1f58f5c1005a3e054f9c40691c287163f445610bdf0f14e6cb73e0eac5ab2fa5a9db4a9774c135e92200c27a34aaa2f3b9e2d568d28ae69652f1a351636492a590f79df0d4f9d589ba0651aa572a6cf9070a873ce75a200506ca74339dafbf0da6add65d5b5594b5b49bb0b63b398b44ff5f996115ce0d1b6f220b7b7b20049f5fc9f26e4fd8b7668578c4dda8365a9e79db99378091b3572473747ca3b4104e7b7bb1bc22988df73cc1e6fdb242c78804b4334550788a3e6a50a17fd8a0985f2449eb8554bc28c989cc1d9755aac8b33482d2c70525e102b4518f7aed260cbc6d6e7317a22e92b776183ccd105ac9bfbed1bbf0da4be0c0203a390cb9b488ed0aaa098ba8d5ebb9659fbf19b8cbc1b4d78edae8f5f272d2bf0303fdedd0e3de90ec360fced0ebbc85d612a9c396ba66cde481b92efc7ac9a1381dea34d170791896ea030cfce7234a0a2d2301bc79043aa7dfed6f3ea7bbe28a344a274fd9b9670b70cd74379a6fa1849a26609f1ef892c0073b7db34f09b8631af1884552a234f7f37263e04c61418b602bddc8561c0e097c5767fdeddc5deabac6308e5ae1c41565baa4d0bb33718486f3c655245f26b26a12becdc95a31819afa5729cbf3127bca5596f9d409301a32e80a3b7ec270b9387e88e9e1422b9ac903aab06f29970b50673222a3460acc1ed2a6ed45d10d3b42887d803e880f39141ce63b8d3fcaf49d87a9ec7f9720808aeaf8eab0ab37ab690f97cbc125be08fd6cd41df957059878d19b106b39e06bf30cc9d3c85f25de650f4afd295dc11025f9a72a5e46422d88c01972e22bf024fe61e0dfb824df1bf44d1f77db0118127ae48e2a145d82bcb537cc4be81e7bbe0e1d3e19b56537e7bee8931d4fc38a03d1c387079b64590d1f775566cf0a16ca2bbad3409c29ca616d8f91040a3ef52bd0b7fb2dea0b65f0841a03fcf8d25a6d7a0904a74ca61835e3e0734e4addddd167cbe9d3ccc89a0965191fd70065b0fc48f450ebd036f9c15039393ebd191a982fff506847cb3de8eed4cb8074da6076302b1e7623cbf5bb1ac4d6af09fad853100eb1aeb302717031608283897f3edb7e5b7f5768a363eb2bfe951b6a9c470d9abfad6ebabd17dadc0ec021684726a3f7daceb4acfed42084e70c8e721034f481300", + "04000000821ccb50796e05b15fde182e6e3170ad072e8c43cd976e191b214cc0b1bd9957f972fed3d6ea50bc8dc07827d9314a989ff91fdf51efc2506c098a000b9675c3e2ce3df4527cec45858a7a5313b87d0ee29b8e001768bc64da9b0416a06ec0210a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025300ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000003000000000000000000000000000006000080f8694a1277777777000000001c1d1c0000000000025ffd47baa3f5a5b90eeff3e0779f2d3563860fd5b9d7666cc06abf31b105a8140643a0cc5b44e881a3eead60361c59cc283f1fad00138eb02268408b29029232df48832e00e32157fd299f16bfd4482cc933ab2ff4cb953b162c8998e03a4d05bb13c472eb737e2e3cff834999cb5438003c74df6993c0579033e56a1fade81706ac0a77b99cb933f66906bfd2a2402c8739f844ee72d34ba50a1e1e9486a73e4c7a063267570a483bac82673d954ab903345b291266f89526184c5633a54bfaebc05f6cea64c403025806e65d8e89cbb0ca967dbefb653063a35597715c488891d19d68a5b7f0b74ca44b7552aea2308e325c71f7199ed497deb6c755c6727993f4d218e3128bbef26bd03941a19b344e8e629d81f15559abb7f6881ef7c688146640b02a0e5a9a78e8c587006eccd05bb1d5ee2ab8d1c743391970a0cfe2da89d18fbb51bf3d6b9fb9aa1818619406b89b53200b86d8b3094e46a01a67d63ff2b113b266cd38203f05bd01cce4e4f39a0072baf5f582315a98575332523e967e353cc3ef8d1df1d26dd79e5375cf9bd93f804e4d709004967bc70b3ae79bd7a9cb67cd273bf3df4e1218ec3f67dd9254b589fc73d5ce565e106eb6c6621a5c2438fe784eb5d95efff8e3b008a63bb1c329c5bba077bc756f875acc5d0eb0d02d67f2aa04738c8c625b56c82cab932b05ae2e50092322887318df508180080e1c7b80cf66894cac8de85931e7fedef575e2f7146ecc4658ae936a722548c527593bfdc59acb58ab6c4f360bc0ef75e3bd171c1c730a51749bc95bc2ab4eb7cc3792e107c31239e3711f35b3094c207d73cb0ceea7643d175cf97ae6d8d221f48fd048236449a28b497b36ed3c817c161d4ea89b7bae5170dfc9c33b3b08f0a38e964eabde9f4020eac2a7b480b9dbc7111d67b45997fb94f4244cb8bfefd0d6326a9da5203ad489ebb4e66f382a5bf82e9011e8d3a44cd8b6eaa60662d20be380bb5f474e5f8d70585cef0c5e490254ae896caa9bdc42b85c4fc0cdaace29679ade3adb96628241c509aa1adf1bdd633850f4df4b24765fc4dda5feddcaa6de3a55d58978cd71c9fdc5bfc77b33506ff8b198dbb4ba4cf3d6d4da3db5b76cfdb26379050cec5d43ecc5edb79d046e56ce8582078f6dae1f9802665db37c5285ab13076b7910c0d230f090375c46e44b0f142d540e32b8020f271de3f8ffcd2a9c8cbc1a7f5db56852ec2e9078731d724824ef0db06e8eebd7f111b7326a751086cde390eb42268a8dd44b7b9b1362a594858308abe397b2abc43a57612f98d027afbe7a5d3035c418bc32f556c8564c0901f9aa322de146697139f8801fe1f4836a800dd0eb2033d3b1c79b4f1b630b85a57a009c887eb4faaa0ae71aa5a1b9ce1dedecd5a9aeee985941c39fd28e2412193dbcd3a941c7d20e6ae310ed6082184c17dd2fca5fb27a1985843a6d92bfbea1c0ca8f7aa583e0336cb786cf38b893deef8f5d9a7ad8b096013090ce9224270c5ca0ed72961b44a2749eb99c23089258895392fc65c6181e59bdf0284a08b6bbcac67a394d3b73185f1c454ac279da8c360bd816131add0e86431a2f4bd018bf1e558bb79761851f9b6b1c198ece4e6ea28d4650ca1f5fbf1401306709d11c65829df6ff7b6a4b8bb55921ec2a3bd146728b717f31681c355cdcbd551e6f310a85ec235ba6014dd384c0118d9aec510c0ff524cc07a525b4e80cd1d2d51649cc6889b2240672cf91d9270ce131b10e839c5ba8dd5ae0bdfc943f9052aaf4e838cd0ad9074d845312f17f33a1333c5e580f48dd93b4c013ce245e807acc8e9bc89429027b3e782bd1054c1ed0b81c6f5b54184e7c0c3289dda890f9d5c21cbf13660d4a5634777d00944d6e9a91a560a7422b354fa46282871b9f29bf0dc7cba8547b19c53c16c5e9cf9986701d8d15ac5893d6f5827bb02e0eae3f589f4fcf153515406a1804d2cf8f62d765eb65e09d16c6dd3acca553ff0083ca089e62fa06898a1859d224d8f823f01ff17a2a53d2e27ba6eb1ace30b7f9a97049c581b912645ca1337d449fef95b61cee2b825716f8db4defd52709f08214e1be87c2a1fdce6c3225c10e72b0e8137dd99e2080a033af6eeb1ab4734cd25b822c7b6ab2060774df62fce9bdc9d238b679514b336dda53a630aaa419af1b4df7489bf0fa054c82bbcdded5f01eba9137164a023f495ddaaa883bc42edcc05c2361488731d9352278c9f9075197db5e29a1c87add4cadfe063c6a072f6e1fa9f8b1ddb2a5e46c7b3120627845eb9891cd09b299270c63f0147376065b406b531dbb2283bfbbd7f793de7f627685263d89308ac3896d62920ac548a7f97681b9c0b48671dbe6b6cdff66b3c80dd90b7f5aea8f2616a57f0c47f2375f070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c4e5f35dd019ce932c8d81f52f6ac4b4c7ad62d1513e1c5c445d10faaf17053387812744aea4097a7d1707dd944080558fe3569fccc6920fcc5edee87764c76b69c14f4fd2f140a5aa80078ac3bafab06214182cd9e26ab213ef6a424b4752d8b8b2b693f46bdd24a46bea270af5a4ff7fa74189ebcb1163d359d3dbfa7042509689bc397969857751feed4314241810eeccfd63998768b5a811277d852abb5a1e88196c0e6f98596ff2ecb67af89c3dd6568a4fc2e495559d85d9a043c117615fdc8135207ea0cac2c99648e6047226055013ba411abbe71fed3f3fb678bf99ac4d44d51224662036ac1be7e71d203934498d1f0489bd4e9f8463ce20e381a31cab6da793065a53353682f60fa162048ec3c278685200128c45ed315900a3111b2a3f36810bf78e75a36765a59b3e618177b61f6a90944e0e5973a573c9f048f17f1acb7a5e29889ceaa14f78ffcdbf9b83a3a8ee5233dde72047074853d78a6b7f5de7b73d0b861dfdedb8f2719ac647a67161803b611e5b80338be8f0012bbcbf1f5f05558b742a7d4271865a4e3c1fe55489ced6624aa329fedced737980ebcccee2210078dc20db162ee0da6d8f12d6293b9079bcd29416068e738f129991e084f498a98b41c4c7a8430ab26e0e06ed6115ff86611a29893b50c4190322ab26aa6a3ea878671fadb3b77b694dfb541dfd52d8e199569c800b003931def1aa79159208545edab077606d0f61947a571b6e7c0551002d739157c6f5fc1fd81a2e7172e9f480f0499f9162ff55146ea147508098c2ae0c723d8f113a9fc8db656a25264b4d4f1ff86acaa7498f351934e3fd113c2f8e45488360a40b0cd1e8be9ef9c323cad2df8c077fdb1ca88159d3339818c557e4ce14e8efa0a60f9ec0e474f05cf1478643238fe22a7ea8c74c555d37bb9555e9e733e07cbd25a3446847a3ed44d0390261cae0a92841eb6c49b20dba2869f3cdd0f33754e813f8b270d8d7c8c7a605541067e929ee330f34ee19f5de779bd0d74c4f82d97e0d794afac96f3184bf7456e8a6a1ae576889b198fe9d619425b3378e2b8cc97caae0497a3730f2adc1642f039a99b7df9d68e080e9ae10dfb93da507276b50644d8a963a0f381f5f2970725ce544f384ef4797e5cf686a0e242621501b3b5b58caeb4ce31d8dc19de210ac4744180a3698c1ccd5b68ba48edd1d242764e287d1b22262ca260c8e5d4c031a798684aaa48b739b19ea140db60fcc23cd4849deb5c3b3137331f2504ac002856a0e2a18bc613f2de3b0b615335755d9a7de9cf27d1ab273b93c87e0c03af4414f1586512fba9bba193ae17f636dbc8f2957bf28f31b2f7f53d3e4dd6f1ce49137a89a55549f23445de2650e4f1c00b22c6396c08a49e803505406be93b90080bc7e1317a4040810726d775090a6b8ff2ced7e1d150b21d3990d64cd3f943db519722fb8b4bc68656188e109fa6670235ff5f2261e4819b0a3ba1d15be9a6b39a07f579923924d4fecf753ff918356801b662ed3071753bc110adf8ace113d4bd09634b88a48095caa9ba92b2dc5bf8a59a2b7964861493ab25fc0e588f29bf7dc2b08fc95b27d8673685d313551aa6869ddf013253c6ccca39ca9bd71e3f31c77efb8b7a8a5d05afee6d24c027e0ceab5b3159632de281253ec3bbdffea8a9e761b4f1ee56047dbacbbf7d3c88240d18e4d2f625e24d2fd4922f81cd50895c276a738557723711934ea1705ef98a29d87527af74fabf3bee87f2813ded83917d8ebc2890f9dd3fe5d988aca61f771aba9df9455e22fff03e8565feafdb0619706f36b9dca969747e4061be9248ac3a23add9452f9830849e3e72c8a1b13873ed3759589e03f800f9209df6ff23edfedf91fb8eb35db90a1e31305ba079f6cfd6751c036a050c091081a7cd92f6a0b9099e3deba523218be28c11da50788de3f60ee17d78cb8d9f210365f94a9b938f37a5f4aa1c1637c596a04ac232242d6725b6b49b12208d10a47d8264c2346b598935fe0f43eb56e0361eea0a8a631562defff77b502e1cf0359bd42f1bf330664217a637476406e402ab0bcdada496cc5527f74b911a96d7b4b927a80fd918255830fcda63832500e53c4b5cdb90bc83099b65f18f4b84561aa54c7d2d969aa3464eaa220c59669baf9d7e08216d3b33c39f5573c41411f1a0a10c43eab6cb39be9baae5f828ce41e50352863a60c4575a4863482939f2d3e2db6414b0cf533468ca0f547d02030ec80c58632311a48ffe647a6ff5bf0defddee45927b9c888a8307ea592a3037261215036fd0b441aa141c7356d91031919b2f8e2f92af9134b9e42df419bd91cb582984da871da855643b4ff5bb4c5cd16a773c99688817fdd76b7faa1b0b1341de20e35209ab6a1016197fe373807f9e406214c7b9c0ae7aa8e4412c7330f88d053056363d0cb4ffe3c34b05727144ba6e418ff0c5236ff9a4bb716986c86694990d1887982d0d8c1caa1c471c793cea11b5fda1d346da4caa12e74f36a0fd8af52d743b9aabb1262ca1295342cef187f3fb13c1e565f7bb85863f86f93dddeb2613dc2aa2db4259e9c086ae837c4e8655a7e37a6e3801c6811718bf76704804fe276aaefa402ffbb5394227225f69e1adcc7556936bac642048dd86b35effc30b0723034ad8fac787a99022903d8b074cf8fdadb8ed3b8cbf75006acebf1d110534f3f533ae921c0b78ce67452adc26124ae25dd9bfaba7d4914b379360a812813d3f5743f889a442d4b6d437b1558b97e15a5db16296f36cf499417a484b4eed0ad96a626149a4d847df37d7a88f7e1773f89a26ff26e90b930fc2a8494cd6170479e0457a55b481b045dddf6e7362c99ab049d097d3251431e61242c819b4d22f70db675f50a7dea683a71b66f7f91c6ecb99c019d207a6edb7ca4f9ffeab7e29aaa723bb87f14efb2fdce5eca874cbe2e6f8a1801d1f7faad249cd9bbe72913f121b8ac6fe1446a0b182d661b0d8594f52e971955322c9c6595840aee5178518853df56c9676206ebaba2aa04f8a20960e2b5cc3be71681e85d686ee75cb2a39cb9b6eb6b0933f34a49487839995931a1c0c4f804c1f9dbc45c9996811926a0e8f9cddda2e7d6c946d70ccb58717660a1c8bbc7bdf868849de9198995148b210c81081f7515983e9e7cb807dad9da48aab614439811826d84a1f97515f915109383260e314f80fbf1f5606509db8f2103ea1788570dd8d452a8b2dd13fbf1538fa9cf2e9c9fa3d12362fa93d496d1d770c71516c794fa7a442c2fb0395afc70d900847ca74b989a9e400d3fd4c5ca81c2211c856126b72a296513fb401aeed0892efad767e23594b6c4da91e8e45779c76c6c94cd9a02d0adf3b9ded9bed2520064891d9fa14d4e26a311910148f057bfa59684b73813264a2a901d4f953040e2a277a15089841f12882b2e069f913787a37f7f9671be7747f7abce6a97e16183d03c5ca8f71f38824c0b2e197b57f5aab474201cfe23f90ca1e7a4f11e3733b1dcefd8652a7cf727c5ee648caaca370a20ef0e658334520c38d3c78870a9b3824ae09f4d0452dc5adfe57192007c4ee608e8594e7bcb5a8983004f2f0271b1a129b5c0f9a9a5435c9116c86bc33b1a2cca7b104cccd8e96a31618aa869f011056e5b876f257bf9557381e4e812ff830ed34ae2bfaab746c49e65b0811dab906967440a6850c570aa0a80f3bfe70996d14a1a9a3b356562a2bed99c40acaf107eae6809d0adfd64bbeb5045ba87073ed5714a13839906f11a0263fa078420606787ee1d0c1fd90dd8cd8f2f1c796604d54826d472df55ab8d72d20fafad1ae39c3dbf0d54c1b38d84e8ad9dccf402c27448364a7c30c169367386b9795f27e0b0b56b00facc89636a1b1391ca960f8e0fac566eadfe44aabdb359c9efa8d3d331b2b6105d5403730d9d180a6c65658565a1723d858425a078e6cd8d9a73c3e1fff7f57c2e12ba17ffa065efdefb1b78bd8f9221aaa227eb21bc4dec5d0d01011711bce5dfb699f2810f2fa15d955c9b71934b28e2bc0b1e37b075515690f870ca8324ffbb1ccce79a1fc706e78bbb465bc37034cd5d5dc6c390f1b41cbfb94256b64253f2f43657968313cb6908d8061db87209cf3da1050bb8a757dc765243e42590255037bfbec6701406049e81a5326d5f423a0f189ff94c32a333221882636fd5b98cdc9c14731eb93e9e3564b3b93ea155faf3eabafa21126a0d52c8c3b514080698bee3bba11f5ae26b5d20fc7f0ab3319bc5d6b5ff6d63a781cf1d02c570ad8d007a7c27e495437a2f6fa86f38e9343363ff315ebd95e23d57414a50dd97bb934b3ac9bc5b5cb6742c2f50d746590cdbec2cc2c025a1b6abcac53171c04ee700a6ea6096d462801d172680cdd919b21c80d7b0730642cdd53f10b420799c09b8e03e5a0ce59f1870fd90a5ea31dba28da6d43b278b39f0edd2d9fc82929e2f41d737dd9ad010c1bc06ecac08030713bbf9abd30e7f7bea89bf50f8020530dea34e2127c58e35d9268c1e7267cb00bfa9ebdbd929d5eb0f686d8927f28cd8e2d6487a99523fb8704f426d68d27fd8e843b880d5e1830d94c66537c36263e231c78baee3d32836658aa0cfa222377bed6912e61c6bf920e28421062dd1df2ca1fd3524ad599ed2ebf7ea512b7326e2b86a2724c74977cbcde823d5f1128c8061a4e6edd0e180ff55de5b77f37cf6c7b50f1be0b4d1d8b6ea176e14ef03593024fa9a801677a3ce854d53fb7dd0041f47c5c466a1ca103238ff5648bf52fccc159b34e16196d3e91ab6a92571211f3154ab9b44e25d546c0539e2c59b428d36e5c2cd272ed254500c49a6d09984e221fac248325ad848c01ade7319a3520c83cad8fade9995048fc2e377b91a0522200c1d3d38e54ce2315dba3d792c12d6759f17eef0edb7d502572f6e3f1bbddf2002e2807afe73cbcc481572ed55f11b920e0d25bfa52f10c00c175605eaeac91308d0512e298a055e05de156f0d633c3a0c73525e62d7e5c61edb032139f9aa7d55902a0fda39066fd662b782f4405041e3f54f29781b264c4194d1464335fea1e618ba2a6e5ba4b62c8a5f0d694254379ef615bbe3a66d75cc329f68aeeed52693d63a0f66f794d700f72d2edc303a6e57ae7f4c0987da01d7de8c60c263ffc64c01a92dc1f4d066e525ef07c602af211d442c45e23c1f78b9060a95f3f102b3557dd3fdf5e673b02a23f81d91639a936a656c0c877ea8ba7d235c78a91b09ee51db1e5e9919cac5febcbd39cb70c95ac9efb1c547e9a7f88399e5362dac5136b3fb3581cefb79994c01f07ce2434d891d7831fefbef2bc7983e7dbd9dcd83d8de60d0c68536e8fd5ea14f5d33b27fd3e2ba87cce7f94d9421210fc1989758efcfd4bb6ab8dac93be06477bf57c02840a3a6c7252a91bd612007b1e0568b0829ab2d41347594017d337f06db94c11c35ded31fa365b0874cbee6000b9ab06eecddaca8d0c8fc064e4ec96efdd9e2b6cc3992bc48220f8f1f6ef697063d0c46a617246641a73c6c3ab3d26bfaf8706dfd89adbee69abdd9f198419b0ea1e8510de1b92c616ee2eb2725334bbfee90c13fb8742087c0c70cde18a8576166601332aa002a347e65452e2a2237cee6705cec7a1e2425fa6044339b63bf5a047ba52a49ed6bd1e88e4d6ffce458480df30afaf3ac08037e0dbe7a6cc95c7842909db75c6d8e1731eefbe358d7773c71b1aeeb77c102780d48018f417edc1429ee3f3d18cdba62e6b0b4488684967e79520b4a1ba5a8df08f892253e1fed1915cdd201e87d75c6d1d2554a99a341e487a1654eda35019c7c38c86f5c75020f7f9619a61150d213b99b756924f5f9895e71f49d172a31028270f39dcc1ddf929992a516e4c270ac591674e6ba2c13dd06e0b506041e8942778deca31ddc84f4262ff4ad4d81e531cf16d4d041f3911441c12c77ed92459409ab65ed1949920a684e729d0904593d7a42ffbceed454a9cd23eb7e1742bbf6effde398f122a8443e86c272fdb97ef9455f33ec1161b73013800c40bda9d301d96758c6de69d103c430ee0192f74956b3d73cdf3cff36850d0192633385b19d546bc8f0b1f9e3524757f2d4245646a218b78e6a9f4e289b7882910167b2cca4ac0b90203e5ccf084ca174b16b6c0570f6d9c4e5f08815017f92a4aedd6d5cc3f40a4b9384a77405efb4b87a15caf74bc5d04197ca425592c0900484b814b3d1926954716e1df3b7017a22951344fdf52496f797562f397be1a3ef6bab299a518e7ccda7e5fdd166a6c3e94debb1930febcdc609b93dea783be0d009656909f18ed83eeac7cfdb0a5954dc8b9d604db26c6904d8ce0abbef49d005d2b718f92cb54a7adad0d106a0400ba35808525068312f938a58963d7266f1829495bce11d4c0c05073ff5a72bb508eee9fcf3bcaeba833bd03edd36a49272a1bd479d2408c272e3badb2ff2e6e036aae1ed1667b8bfd538889f705c624b93f37293759a9bc6b57833ea34b0973dfa3171bd9c81715bdcdd39a1a5a16645532b276af5eb53fa910f837f367301e75c8eaaf25dc6842212f5a43b71a6f76c92d600408f82c64dadddd2e72075a070e7e62baabb69fd006132d441c4f184c5d0f869993de13d03ae69b61956f37f191f05b24d242c23bcee76e5ae1726a296b1b15bae2365e9379db640dfeda8d9c7d12a653252a104891a78fd4aa3971af9731c00ee4e0c2f2a4e4fc6e50d67ab75024acfde2fcba159829904f9b27982f2e251f941d897bcec7ce91edf7156cb1754e27813c59d3bfae136b5fdc4ec32e7f17f5d4c4d078f68e91ead670d0cbb30054f2e90fcdf204ac0b99c8c435d932c10ba9267de7a61d791731e0d39b6927f8d8c4b395e03f239d84b717021375480b2c36e3b110777eda7b9e67fbeadb56cbd75ae21d5bbe2f95bd5a2d21ec1a5a403c619e55e46f332c9f98368823f03e4bbf12041f138dcdf2423400dd940062381e75ed02772618afbcf1bcdd949e34afa5bdd0c25b0addc12c1bff4e7faf0a1608d0a36b250d7997bb5711e1b6c74fbf391bff697982fa2b388f1c1934483517257f23bc65aa0e32b5631cb27606e552c49d8376d70c7dbd53570b8d92ea893d3c7b1bc8f62c174ac33faf08269b8d173605aa9a18d81fdbec0e392a6b0910443c504165eee0571388028e1512b8384f60cfcdaf2ea17b7e9c1be172676062a02de0409faeb6f0594e0fb6e696d6605dcf8a5be6115589e2322d7c838bb06f7908aab838bd06e720a051d07233bc7bda3bf1dd16820777d5f57d15d8ce486c9c0081681824871c37c137be3355e8587d12417caa506e3c14caf7a1e9f2d94d6c15e4fc132b2a62f4fef4d12d118ba9d39313a212980dd0f4d7a177cee3ed87f02812f6c2546004e10249c06aaa49a01657c7c7d2ef5c155310e2b69bf2e2b5ac3beea29add230e49ab31149447760e2c54745a77fc33127beb384adea5efd15e17aec6db9af767f1c1d5d7b2cb07c3b193acf0ab44c5804ae5c3e382538cbafa1ddfc31f1448eaea7b0a7504e9fc5256e4dfff39ee61145fe246856fc4fa93d22154068a45c9c12234f6e4aa3748b0a5418e4992a22eb18bb8033793715318370834424065bd4cab694acffa6f0448a61844d4328eb406b72b3c9b2b610b5eb50007bdfc74c7feade19a2459ac4b21856868aa06a2d175589dc86345b311df552ab8a56a724630d565e4ba55a1abb0946a0a8d6e2bc453d4dcebf1159c82b98816c8584ef251cacd77c3ffa104ffbaa96a90d876145fa73fc5fff5f5570a6d8d1580e1c4cce5b5f8e8a5d2b1d20b41b4009c79ebfd4a8e1636f6f93f12593f0532d565ccdf90ed011e0ab0fcb3db28f10535ef5e93f59851db610641feb3bba4190f3074e4257bdfed4f05a52c98c380a471bb3b952488283be1f14fcad4a3d219765b4b2b3421d5ef845f6c7b9ad6af6b66a75ef0c03ab4f2c5150c078068943d1e89d298524d9e9cc5b20c3bd03d89d7a6d3cf30b02e17516e0001b071b92a35d245e0c596071fb8dc53e53159eead8cf86441e0348a0a951d4a2ce30274b423bf3cef4e5969077107e166199d2c5714e25e2e0bbd8db356fcdcfb3d3b8b04066c193c83903ab0f0eb18d2faa428f3104af484d07a96e43ec593a5a9bc6d9c2176535fd5727a3acb3ab4b2e9e9a570f06455bf2b68cbe461743af5466bf7f8050f5c7710b8cd086922c098d4c9c26e53708c5523c0739705505aac79ef65781f226761215eec4cb44f8317b2fffdb15dec242532c0cc8db35c117a35278c54034cdb69bb5df20b8cc8f1eff23bb6e8b929a130e44e0b0812e937fc89b3de0a13afe080628083e386b703ff58a07fb599b66605d12342bcd8fbe69ef239f3ec30bb2fba014ab66bd3344d60786edcd434fd3a19f46353cc0c7901e051405544028bb9dbb1ba427c4b6e6b5a3ec8a593f0832d6a61692d72bc6faf044ee5664b1a7b5a3d38fd1a1b436b833287a162ae7851085a1f63bae8f2fe18b09c603ff33bf0b5ddd6cee3a4b4275348c9835ef59b44f2db1f828f77d0b7d8df70487c91205dd731d9d516d9cb6fd88080f45312c10edc4cb8729c7e71fc9fa87808bf3a3099918984a60eccb1ce433aef537927236f3e0f59fc922b0ff7d0b39fa53f7c19b5048f8fd2e9a3cbdb8e6d7d156b697bd7242355bce57cb3d94d16a5f9adc607288f3ec2641d42eb3303e0344ffe4e4cad5d58be766687da989e8448a5cc7c1ca4ddb0e6cb4f4d22104b1d32f6dc3632fa7012ed5e9d5a2111dcfb62c7666e1bedb86bd966f9caadc2ba81da0488c78352f7d3ad94f35fb75a12272754630a20e42a38a52c4934c5d3bea8631f590e31ac72b485478b7d8ba786e2bbdcff8d22a0082034283aad9f28adf92604124062230891d81f71872c135d234bcb76e82dcfaa6969b84c9171805683b4a419f41a830bd88a76618ae387e3a69254ee920a1375d8362b4e038a2e2b4a98b1c181ae9e5f24b19b07c5d46bd50d0e1e37502646eceabe404904f3813c243675a8322f853d45614c7d56fb8667badf80b87b10ca9d2363e37281fbebfaa303a7366de81d92fdb81edae1f057fd933523dd0a0b88f33140db7acf9131d23420c2b976156d2bfd785e9c8c7c7a520abf8b58d204ef04b5f5f9424c5f305ec6d97f582627a9f7b1d124dbbe6bbd4a36340292b70be4278a0bf1833f90bec6598d3a85fd10c37d2c7fccb02e440deaf2f191492c242d84f09ec1e0a034843a5fffa7c63cca1be0c6c378ce3ca56bde144d25b52412b27185ea5d4a3f4764ee54f0bc70c489f6d81e8a9c7208638f9a3a0bac5ff8b857a74cf8363d05ee1d8f3a166cd50701e0fe692879ce79a3d691424066b749abc3e738d5647bb844731b409cde36b48e420348197710106d7cc0d216cdc677b81c4300b93de75630c4b3e117cf10b678e538db372b2304f314a19d41b5534d9213d408155635a716fe42fa7a03ad90cf8866c124e99a66405883e8bb6f9a502937e18db7c266d8cdd119d12c7121c580f83c2be68d9a65744d77e15c337fe898e1b2fadd3b48b4e03d08d4cbb2bd50f567c1913084eeb5dd249c81b71a1d3a20e2c0d6a8fb7f2099c60904310e9416d9b34407ab6d32fe2bba4cfcf688c5c92b34fa937b7c5345fc8724085c893a5ee567bf6e3b2c1adae130a72f2a3a16d8920cd7e6b93ddd1352a13b1505cc0cf4b00a3ae34a00cb2f85591672068027403537fd0721374d5936ac968952ce66bdf64318c927bb6c184a880fa15e384a3112b78c3969161d05b00c431ff94c55f794c150ff7bcb35265782fbc6ef4903632144809ddbbe3d801f67d840f06a15f966775826cc19fd1f431d9b2dc8b552ba3b28eb47a6b96a038432ce40c84eec8854e48d1172af6aa5719778915b64cbf2bdfd1df50cc32b2736181d4664ed8bfae97f49c20e30bf9c4ea8e67b53fe74afb41c63b12c30eae8c890a5ca1bebc6ea3d553f500b755430896246cf8f4577b3975759e150ec920229f0909348a612900466b5d66e5e2d331d6d9aafabb50bdab70c93cb2d3f6647ff3e399e06946844e96897d74d22795ed647aef1526ccf5dace92d9f5578c19b0d4747d50ab9442ccbd04807a28a35e0df84cd1d4e9c8dc025717871bf8a9f9495ea8d6f6d1687cb1b3c2a6ccb25924ea8c6ad9dc62bd510325df9f6c52c391218b8fb35468e6a855878f17f6d83f866cffa34a2d1f3c21e17cf28514bc1b80740721f43424681e4b421367c296b90a75a116d59c3bc06aa93cf2d809158a67ce2ae3ce452706f919af9669e0f7ed795a3c0316b4ad876d292063107e29e7374826e95233a7e66a89cc7fb4a6d96487f2f2fb1d68df0c0092201b68d49a7d03461d3fd5927b89fe693bbdd3cd201155aef2f533edd651b1802f530b807760dfe1b4385c3ed4000f6a8118b0a3df4c412e79944e444fe063d340f4871ba816c772ce322db4e55348b6e5046b1e6cdb665ef7731e4dc58c93a21102ead248952e94d44bd8357a49f2641bb636285ea307eebf48939441ee1e31a03adf3198df993b59a995d271e9b851fdeac457d6355f9c207292515c0ac2b3801c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce9458607000000000000009ff3604b2c9238c3575aaba36bf28511d83a0aaf443d53981899c20be308112327ed070500b374e359a90435a60363235ca445da700abc2c3b962e89ddae24040006000080f8694a1277777777000000001c1d1c00000000000234ba607b674dd1faf18173ab52cb86ada65b24659b7ab0db262a4d46ef6307813610d535a38b024b19e566c3d73cb49c5dc6a73457c658fa61aa19c9a669d70823c009c26d2c4c5949f83ffb187b8d03a7e05970d87668b9ebb172e5b44c4f300bffbdba179aceb954a3d6da0cc8e9f59587e9a4ab1e9578466bc9eb508b791bc0497d33ffab8b845eed45ec6d6d9072da6064b0afe5eca2b8e3caa4801e04990e2ce95ee1594a1f922a2ad1e0550fa5268c2e1486785a68ad25200e0d1a1fff176fbd7f928197be17c9ea0d4b2f1987cb4c5d4e62ddd8001803e1672d2509ce5607d0ada2ebfd792a4eada56d50babab5b04f4999d97a78f2fc35e1ff001aef6c11bca252ab1f6959508604fd29f29642562b862c9d326655c735e7e9ff0e5b539d819b0ff9b7594947225abffd69d94748a59b5e4798eb4f0d9f41848da1acc1c42ba1af1a4e69227887f00de8aad96af6043998f72164b95e9157ef40f3253d38dd577c636fb694a49fbbeb14a153d3615454c5ed2913c49454efa45880b7e81c288c34793ab18eb68dddb3b5eb8c6f9ef4889d0fb8d3a2dd58164e5edb536fc705b63b194f2dcf384c026004d3aff29e11cdd17ac5c71c26d30ef20b5c157fa9c1c4b33d9bb95cc5882bd36d990fb12700baf432d820f66283742ef447d962088dddc54a21b162d0ed191f12d4b335b4227aef5583bd2a7639a275dd3c6397d11baf62a2983eb982d0d4e5bc64f8bdfb72a5b7f99c81c4af1395d153c9535ae61358ea5fd933e1ca35dfb4344a3a096236e9c777626575f9773f1ed0e64c7e67616b36b48d9f481453f8815d4e48601961cce17d7e5cb37be71839a205a208fd7d35652247b32d384453f30376c2b0dde5d64285c86ea396bf919978de33d5959c7a2bf9fb5e15da56ba2b11b805789d994dd44b5b39952d90bb9cbe0209c63123cec7ff2f2da1c1ebc0930b0e3a03b90dd6e58bf83187e7b71a9a5264fbbfeb90c57647c5d6de4752ccdf657a95007a21a6d8e4910ae99c90e98bef3ba13ae57614499747369bae218a8fcbdf074b48a5f374f74e769d02af067b82283116764abbd30fdc9923a3995d144bf1033ab26d3197ab184748b4992bfb51b0ea22cf3bb574236f2209a2e1391f153b706d5b7640e8a23778332fbdcb1e35cdee0bdfa55c35b02b793b6f2fb01893363d01388391479aee427cc977bef4cdd250e78a7f0f39e711aeb13be5f9a895792dae2657ac2789d2f0a5b0b7a9093fdafe072883f6842e377b05a046488db93fc23002a40a7315e284aa164b2e144cd5ffc6afc8584eb5d52b21b48a924e257b72a180792eb6f8f0a5220c0db0fdf5f5d0a0aecdde7f194e88369ee5d2efda82edf85e8d20b69680c677a4ed53eb33475b9beca2c560386cceb4ddfbd30292b111c37530ae6ee207b87fe5b67b5a90943e2a3c43c66eb8f9b1b006fe008f9da8791e71915349b9a9652d9c508adab7668438eafbfb46288de70ea1f96a32d36ea48e0dfc3fbafa1ea69d28f2b3b1e291a02823229ab70510e1fc102e5df0f6160c7af5ce67e8a6dbdf5e486d285f2b4ebcfcf2c10426ec94e0886edbcc0727b0703ee6ba3a1f7d4a5ceab9386123e531cab919407eba95c72314e0237e4208e22981b912ed9c2b4cac88a8592fb62d648846bf411b886a6b89b83ad03210cf072b00019dc6d0e541b6bb9a22ac9b3603ac0ede0b27cf0998333446344fa2cb44350f9dbc5d557cbdb74d335c6bb398ecd2eef9686763c1f21a34970e810a8eff7b37947fd455ada6010eb00ed5f1f92395ff7d1fa77b05beac74c53db704530f54a5947187366dedae6d48386d68c303b5eeac6e4848607890ad4c4ec6fe25251b4727e8cd22d8fc8972840fc8d5887ce647ad628b298e15f9cdd49b917887e0f8e8ebe0312fd04f3871c68f402f8dcfee60e81283a66f1725ce579861c999ede9f9e2d976a83253ea608b66ccd6ac83359bae0d060adb0f5573ca385446cf54f14fa3231830ba0243fd574aa8ab787ef0150be0cb9c38970043d6fe200fbb6d03158f33f5e3a811887ca482b83122242d228451449593c8dfb33190298e873d49c01b8d0b9ce8851e60e65308325bf3a934054fcc53e791fb117dec249e9836d466ec94188df94077762d8c12e8cfcbac6a9af9741395ee566c26f9e5ef21d7e08a0453fd22ed3228f9118bf2606e87e0e0d1e495075f348b16701162640d2b805fd4d2d3890cd6bfd5afb790ee9163e30d55f8015ee86b07d063dd0398366e4cea8379c951160896d3374b1c39093954117d7e3840715e3018b917c6ddf9c47869bb01a71793b2d414c252cf62e9d781e29137f59978d39b8ff60d45540bdd2dfc73dd0bacb811267b486783e9e9a0d0d5a2a161e082adaa070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c02f3f899fc0cfbb1beb2f0a6b1364b43fbfd5e372a1b64b90685c1b0750cf93993917608f18aca5ec561fec653860b83841a345f03b0e9ad5360c2616b8b511f973cb8eaa583b1e65825fb0cde26316a897f759b9c79d96d4bcaec217948791d524ca3ba26457a5b6f5278171729abc58fcfc844a5e2e9ff048bb334bd46692d97beb0e892e144acb380a1a2810048d5b4226ce2b4f9bd020ae4b26ef3d03419236d3862dde808d4fbc7187da8d7a63c5154c369f26a905f355469a0db4e562de2ead4d75b8693256748db27c5d041f6bd93bc97c7cf7a6f2c2966c29817bc398cf4a61ff5c81b66a7c725dc820e24ccbb2402b16e8a5a9e0d676193924ecb3a48bed2157a84205b689c5f673b45f5cf8589d2e048366b6e3ef58a6cfab7781e90d5f0f2922fa407d0882daf4644908abfbc5da2bc90c09be46ecd7667947d00094c2024142dc31a072b758c2b4c5306e458256fda993ea15295f970f480cd333f986e7f633ba84f8981266e9db3b78a3fa87052a648fa99c4dcb5d1420da4bac5c6ffe822276ffdd6de43f39987e9ffb1562c8e136ec163623c1ef0b957bfb67cd4af92e6433d2b3c757be0b74d7053fee3d1833bea1b076b4e2e878b68be8b661b0c54f6cf9e3bec410ee0a65c0371b4cee0f3cf196d88ac4ef5ca02a42e352785e77307367dbdeb20cc0aaf0be2f72ddb4b12cb9d1e7ed530eeef35a44daf8d80446626e90ff4d6705317ddea944a45e094901680b89133957343b5209a0146722d0d494c9fa805231b072740b15fdb7a1e0dba39015437cb2e61f0cca0179c0128c874cdcb3e4c377925a097d46a2ea86ebcb2aaac4e69b8d93f3f813fa110857017ec1126b0f48e1b61ef1ee9f2d3288a1ba037b28294d381855a9db1a44f6aa83f17773222761fad2add32acb500f060e76600b50779934496796f4c86114c123c55b42ce44d600055e9e249fe7d5f1a80f54d49e5b0dfd71518a7669538471b5e759dfb425c51d742df88cd4237000e0989d5e554f698d0112bd61a33a307b36b22a76aa8e2938e884191321c09c1d90a5678e903a5b76446698e5031233ad87218bf81d1f49cac719c2b27afcc4a191daca45a1c9f51425cf48008a1a569e2adae4627c233bbd024ef0f7c3973ba5bbf9fa0704e111223cce823d50b5d91fc0d805e0bc51daf91f0375b6feb67ed3a729933f275fdde5f8c1885cb9275fbfe2796b9cb4dc5d3eedd1044ffe62bb5a4f20c0969ecce5a0233c5a7740f9f18ba0a6c9a38ffe4b0e5377e6e84e659ece4b09a516f1f5e158f633a18b527ae8cb2813b6fc27f5108a7230bb2ccd25f9934b0899ce9c8cb3d5afa146791b52509aa6f78f02904882b0730d1a8630eb2c3e408aed611ab9cdede995bd2ab2940dcb74cbad21b1a8c27bcdd2b3758c61e5c0d271dda23139fdfa17fe97f19358fd6e4e6efcf71996b359eaea79979375a010436dc45f4ab138d7426f806450b624c14febce156041a32539494b096a3210d114d203df26b1cc826fa2946f53b2521ddeffc30550bb2d26dbd6900c912852b1741e76aa7f77b6c4aaafd16760429d5ce5d3cecaa3e1ff1d3399dd2e4bb0123d668b63b61bed7b097daf5a4710e82dcae3e2db6fd652bcfa527938559d83ae86982f26cffd2be75bb6f842883ac73819dc831dac60616f3c85011bc5139d67254cee29b964ab71fce45fba367356f2122a61544345df6d07f423d13bb32c328125323ff62ec30d67cfafde6eb20c8bf832b8a51e3de2726ba66fb6a0224da5f79286ab7861dac4d7fcc85c62f85fe476216c55ee4e5ebb7ecd3f642c547ec45844ec95586eac20c1834a5abb0ab3901c50deeee97ebd64d9980c53e0b8ff88e2273331b1484adc54fd459eaed17ade204477a17b54cfac56fd8d05f3ff4edc2e473295817cc00ab5c34806f1e370a9f97dc474e0d4e6955f915cd6d2069df587eb0650c72b4d2454142230623070f6d21be2bdd0173bb0a959990d9d250e47a2148b42030900e9e7014806e22ae690eafac7a2b3fbf45d6b51dfecbbd21993a12e057c82425533990c8b5c238a6d329c4c41387bd693ec77f1d6d200f17a86063111051f7090c2bfa3ed2a58ea8d22015a2cff83e127edc0383eac49c3b6caf9b5e0ab4abe911658ab63925d60842f70fe83f9ce4258bb79b6311bff08b231078eb8eff59e9dbc955af596ea7acd15fa8b8e1ba88e110ac383eeecca4340797afebeca8fa7c5839a3a306d4bb8004cdcd0372d83cf4e2214394cc2a09252971cd530af7802ac06d57fa0784500c40581efce6bcc497fae84e8bbdfaac727bac1cc0d49c0fadd64639c6c839f6b3e4735074e5f2cd2b5fe6fc9cc34152d723f1e1ef3fede91d41cf39a8207ad69044d14925961ca8b535362da356e419de13adc49ddf8708b82e6ba3b5609ae6110f28333601eed005b94b0d31699c8a687ae732b7d7bb263081cdabb462241911bba94585d0e20c9b41f4d8d5565e70bf351ea95382544864f4a960b8850fd5095213c2bb602338ab2a3f9b1fd97e8d42f68f2f943441ded01beb76f463997f1709e92c9e6df0341cc64ce46bee5ae1ccf0037b77ea00edf62f5f545d16bd063bd9097ef8eaa34d9dd1cb7b2d7f080fe56d14e4eb521da00c7c1d19c13e934601f963f80fe122c184cbc0047fd38cc0a7b4389debb41f44c7cccb596c41936e2fc672796877e1f0d013df6aa65a8d39c60e49eaaaf4bbcab70fa97a0b864aad214ba57bf5ba65abe585e52fec23b33a8fec951699fa4ef19e4af9e7c237248e1f4a71e6166133b2f1b6949d70f072170002b3d38dfaccb3843e641e85bedcde02e289d94ab76f935ced360b5b4abcd503d274923c222d757f8436e97156e067037c7c984ebb22b836bde9b5aefd12b6f079dbab91f69bd904facc456154ca3a1730b6fc7095af42e8e20d0b94ee3c797049971d28d583d5d1d7b539e8794a7710c2de9d2a9db9e6842f7a6a410b9df0f16fdf6bb58c35ca3a7d44b965f04e5e0391f7ab9789ca3f88973b59f50cf46f0d472e4cf49cd81c1b05d8640d625d601155db952b3544d54e5742be75a4bc9cf0d1084bc141b76cbb06290971fa526001e135397dfaadbb5865bb00fc424700901c4e50c7aa4db925b9b7fb0d8631b311fb820bceed1f83a6c166f78819a059017c7e7bc0b134aafbcb063ed15ff67f165441f7015d9a3514ad604c82e400703302c8e2e2bfbf738ef380e6f690392712d64c59fca62f638f2dd8edbb842a7ceafc4926febecfe42d5327af88fa21a9320d1f590803f35b2ecae7e605f0aaf99504537de024e600435f4963aae484cc3f6620243c307ad03f87bbb60696bf1b66409b143dd80362b48e74627ba790e700b4a6d10a4961fd6e4d954af5e585e44a02dc9137a9f2c5b2f09c5edd52924a0f62e0db46f2eb9c15ce3e9940f16a4c7c4be030c02182b2aef10f01de089f380e8afe59f6ace4c9f34738d041cfa61e19a64156a675832d16f4ee54526e0b7c39a8f48dbba330e8ef36b5564d263060c90009a367bfc4a9d1fa7e7903d0de3b2a68de720b8bf070f456306084485cb3858e98004be70aea72b6d0200def4f340ec415fdd2bcaf28eb60a1c2854fe016de38232c721b6d3f3325a101b77ded810b660a83f31c46a5f13a5a08aa6df7da23d0eba9fcbb45ff299761741ca950e12f2f1881946ed0c16f62139d03b430d1dedc3e7f7c68f2bd50993adeeeaad42315b36e0e592b42f1caa568156ea7aaba4072425cc227be504ae30f50335793483ae94a208efe33d61a1bd8cf95db05914e3b732a6c2ea57180dd5421a85a94ca2a97c80a41c04484c5552bd6489ca235c28d773a4d5122d93fbbcfcf8707b88f3d2604da1a47cee05bb3a9fce7528905b5a279a51b44a72a7bfcc9d1769db1813e161dee4387ebefb87805c1bc133b7cf56d549d165356bd3c24b4fd4cbb7a920cca8bd5e43b14557d48c1131a5ec93b3dd64a8d0791d9e50f4f501a5c858f2110418e110a74f7469c1b2ecb54c929d4c08927ff36c4106d696b6758823b235b2a0704d52ad4da79b09c140c266153e7e54ffe69776b2fb97ae8d605c37142c40bd45690f4207e4d3905cc0e69f548c9ec024a2ddddff639d148577de8be4a322d756efa88eaa2e92f2edf13a664924d341a8f95760db3d00329c8f882c24ced3ae07c89e35d51b7e11b0d1e53270bb0523ddde6e95ef8a0c05d2d2b6ba7c6ec169202e6102335e193e302b8c460ed998878abfb1db24e1797d1e7605e13598923a088f38ee8d824d556ebca3d36311acdc402555cc962cdd10936bb4e1ece2e39a6078516e98169fc31fabca7a0edacc689d6a5b4fe2475c0c73ce3d8510bb903260e1e381fc5fa6ea920c8bd2a8ec145eb778f9891d840ba5a3f08b0f6dd3f07e753899c30fe2b565e821fefe44cadf2117d358a2447b0d8ce48f742325b7d358a96536be71ba650ebc36783be0ecd540fb04bdd6a4cc39073df2b9a5ed9b23a4e2cd9ffdbc2967e690188dfc052f21bc49e9c81be87d12b4ea1a770e108d50de901bbb0d046c50a4228254aa095f0cef9d608b0ef50208b0eed938cc7d136207105030c72580f3d5c707b62090a29415e32af9066217272ea6cd498b5c1a81d06314c21406328037ddfa23222cc84c3afbf8cd1c3762faf04352bc37910971404fd446bc4beaa71b98135724118a1dc65ffb937d5310fe1f40c307095f0d3314199773a33bd6e2c89405f48bf12d6651d789e66f1820cdabb6107bdb309b937d8e0f513fef644f96b702e509903ce203c95a10ec4c9f4a71e75c9495038b423de361a86cea19cc2cb4f1f1874e672b2b2e97ee9462090f0639864e95331262a4a560c9948f3c74db29b1d979b7648a7a18536d7f6d8d2fd422f7070756835185866ac588a4daa8094185982d0879768320c5a05a95f1a761a9042efb4e291395bcfe4924fd4df12b131c3520fa984499532946adcfe20cd2fa56d8d44296926284e91509bf8ae72338c28b93974700af04d3ca38f55824ad9f52bd0e6b05f2c7bd8d324b4bfd657855c8cd458baea1bac09386c4444cff7594a870650c1e524230b2a26d865605eee5a016efeedc957effda3d1c145ad66982ad9188bb80c2d1546650750c7e79416c80d7ac102b47bc7798048489afde2f8461a9162997824253047f3d0b0148160aca7c533bdb6710281b42e64ab5eb5194a78d4244e601b67451ddf954d429fa006f25e09ef2a78388c6dca6228f17e3fe61510038f162626435783cba9d6809fb7b50fc1bcfb6231466454b5925c32d04c02e5bac1903df02e8b2ef25e64fb78d7daba63afe4bce774148ae824c62d778d88b6d6c7723cd5d56278b36058f492e4dcd6cb898414f521d9a21cde732aceb5a62adb996f1e18d950a982f9fee6c02750b13965ee93d80751116df1a5884ee24d05f0a74a3faee0198fa1f42bc5241dcdc623ab172dacf6108535f92e0279b9ceb96395073a5b009395aaf3ce8df09add65b351f341d2600351d24d3474f7d123fa7e51f017b0a0b90c4cdcc5db57927d8e87319914fb60ca897c7642e0e323376070cd6f05fec5e74c88c3175010761c7f1ac3c00e263611050c29a932af6cc7908eea6d1e2cefe518c6092cbf7fe7a6c5b0b821aadf6f4c504a1de79e723b5c17bd68d634d7b18b4b9955b37d765c464dcaaab31b9613567d37640e3b7ba9c2abc9b8ad3fbe2ee8b62b4ec7223792f76658bccff7069454442873c81104f5859de761160347deb9e1390544369afd02640ad5f6868e92c2d576a13808199a53fcff7863344ece1634086ca08e72b8d8dad0c11744ca5889437dc482375b6371f12853a22b37ee12ac0bf851194eca88f4e711d6c010135c46cac6c4b6d4d22ded888f4306369c5e7b716720ddcfd1550760b2674eae607713c5696f43d84af2d853505636f0aa30d128cd5ea230bff5a9322b0f38fc998eb902fa2e66a5cdf573b67faf264bd8aee6a7baaa4607ca070939347511a3e7fcc1c2aed75942bf4b02a7a3680f21e60ba2c3fb198e823ef8742241a5193df74d2fd25e4d28080588ed992440022cac1c026a3bf2c1de232751ee2c56381cc320b8511846093b8c82c3b69bee0a5703ebce82d93c99555970e5f192bf4c1438ef3d583f40e8b4042138963b862055a0a8b1df6cad65b82d57850dc251e50508dcf9d58c60b4d6d5f706b10bbb25717263300d3b432ccb759ddbd52e5dc847469dbe7db86ed6d35997f93f8cc939ea38e0eefecedb429e6ed8b028a6ba59954ad0b1345816bb14ef04d6d922770d40b19adfd065256ac351479ec65435951bb014a5fdee04be55231894b9390a28c7823bcb54409faa06f1c3da22ec89f0f9421fa9a33bc840a1362863b549360829e94a149010328b366b45d94e44b03182eb30c63fc967159c1df1386350c53d8f249a1d5cf7529434d61cf0085c59fd02171e5af8f1c82f63d8fbabf8f07622899eb8d01eca1fc6e242d202799005db7e6d26f734d6963a81ab2cf54936440914330b0a7a64f4c785c0958d72e82720124629c630ebe6c2fa7efa9e2272c234db67c5049db7b62f7e1eb3bbbdbfb842fa3df06ac020f84fac21207504412516cf601b65700c971606725d4fc31c4ef15a6635efde36696e339f2cfd775184233eba170149c0d215428706551ada80a5e9509949d22eeb0ff390d1d172b7033c153fadbd3f158b87cb300dea6364874ae86b93e5863f46d3fa2a0c507b4c382a46e0f953854689ce9b7f2a30945ac9ab4848297b833b4fedd6f839ef106a7028f1469d0950628256fec62aa432d6c0a85c3c4f5a6b792c12992a84ce000e6c1aeb6bd6c354960d9a741e0ef483a723762006e291f5950075e35b4223c471cd23733b1dddf91eeca80a4535db48fea257297e0b02eeeeb3da56c2b7acc338240f0e1eff611efae168d566dcb55b9a9d569539031fc4100eb6ca194a369c1330395dfc82e506d8669ae0b80d185a1f037fea20a2cc16da225b6e3ebe2dea684a032dd222dc5df9679f927887e0323e2be5c6b5db8b45640bc9fa099432d28c833a00b04697cd0817b118b78aa4a1ed51dcfe3fc69560b06c859284c8581b6ba223af7d55a3c623400aa0a30fbf3756e3d167100f5739ec9f7fcab49e5164b08b3628f9de44f0e7fd887a88b54305cd1c57a7b9b4ae5547dc617b4aa616b02fd638f4d030b7d9394929abe4264653c79bab88d1210197fe186b41c32c4ffe2827174edabc9cb926173a4afcfdc16e9386d2c2867d9d07d014161ba69169d51d61056d0e3d4c6f7e2fd93d244df132e72f560569889d635cd192f7c6c75fa777570aa806c5c9ec31b9432ad8070eb1474e9d685eb85116aef47ec47eb621c33a38301ae2348233d3b49ac13e64c70d4c4d594927cf3508f8ca6c040e71c95963820d7a70f22fe3120ad893234799be5de84d096b5b8961cdf8b09a52eefb994f433ee5b57ed74f1eda8d6894d2d19fd1faec1d6f34aa175e4b3a8298159f8a6e4130c3d2100d2c9ba994be1e20367f5d587d34ad6c2b00078ae1fc589c77ef3c3d2f0819eeccff1e7b686308122d9d8504b39be1bc01425d29147ad7e24db8c1c132b955ab073d37fc1a83a12d4155f747ffb33779b2f58e4c862d97bfee479631188a1c888ae437b39bf9f197fda0ce1708be825c4eb5bcf8c419b7f44d1be60c224b70e8536ba3f0eb79d6255438988b420f80a81c2f986a8abc2a7c60bf54f0027e1c190c4a8711fbc8551441c6640130372c515be3f22cb10fb9b53223096821a135a309f40922d5cbc2acd57e0d7cbec9d47837ae1465312424a77c6be3451090277f17d6225a0d634455659903b1bc51e79c1330a70d6139e9d7fac08e5928f23d2c10c6268ebbfda4cc45948a33a263f672a523125d188f64c9c01b2ef801686f5fd26321808e96e07433968d05a44864eddc2d190155cd3266c23778dd1cf843a779f77919c8e7a5560dfebc817d703f3eeaa802c613992e5ee2ba6ae90600125b1aa07f04902c524d3cf57e1461d9895461117ec413fb3537752d755737738bebbe1135afa71db91e93f33771d16ab3134f0d6d588dfe23ec6661698421c010d43df3dd7e9c422f8b1e34ad0953e9fe8d7ce81f4b0a62334f5229c6b11fbf5889642660619a2c1f0e98fc561836f62f61861712455a193e54e7c4fe6f1052296ee852b33ded957545dea80dc5f0c97cbda1d7a6a74ae0f482a59e8cb33bb42522b6652eae4ffa1184a2de0e215a662edc4731a0e6042a69f93fa68cc9088fca3e3d8473d5aaabc62ee5956144fd68eacf289eabfe35e6112e919837b82d7084db1a4cfd8e1a86c4ea3b90b890aac23156b50e21f293d0091cb71822592ff9c0493c1dbfd67640a5da51820cbdf5b86bdfcf47065c715bdf265190284a0b73ae525c70e05f0b35f67f8d8652f31cb650c02195c931546a32dc64207c2e0bc73fc8158e7188e8dcb8e258236356ebe5e35361b0bd759fc8652773690a2908ccc0ebd47a889f3ab783f4f3cf12738b7b2323680c69eb1f28688820c02c601f93ccb28717da6b6e5ac20fbaf7fb283784370fd30fed3aa8e0b485027dda030449a6abeb922c705c903a2f349dfb075b9ce0c18e90df690fad3177e02ee6ef19ce602f6cf463ca06a38203017ebfd02519b5b607a11718243b01084656792f3bec57956232f1c5f6ea03fe34bed97e55a8ab67741617263ab232293b19fac40daa9688655da4d37882b0b21980dd5201b4fcef42e0c038e8033a024c787ec218988b08396e9a621ac4374b10bd13d521b52f0afccb3efa4681e8f6ca1fd2152142c89c09aa954cf4c5e4073fdc99cb6cd151458b59552f0ac5f61888679ffc3711d4b806e756a77f31c993ec9239927414ec4fe996e7fc498cecacc56b30440add6f71b02bc34f3705681e7e19cd3722febf38b6ecc25398bb9b527c77fce532371b2463d4fd5a8d0f1dbf97b95eb59acf0281d7805f99e519aa4efb65699a2b2ed89cc8af53bc305bc1a4f750a953086fab18a36eace7e0311de9a6d400042c17846ede3f280a7ab4dda32bbf364fad1722b5bbdc0bab21aba5e4f43b243b2165258d04633957684ae38ab2b101914a21dc1bdc31423f7748d0e36ba5d3201552a2aa76507dc1d4b4d92c4f16329c00c167765ee4f340a281f1f3d73478bd1a0d31ad5bc40969f7ae3cfed770c1b9eea1d75b8b655bfb6932610eec0d5ab113b12dd78802355c2cc8e71427ddbed5ce2cf37d454fe788c09772ce1668b9d120d1cf5f9b0503b193b2378df3b292666df3df011ec6b94271a61fae493f6f92a7308f733d9a12fd7b5596db6a6285d44ea2a0ad64d329ceeff2296a403a730c2a18881d32ebfd93d502d54021471ab8f9473af265b6e42c1fb98c1767a92d5613e29d270a27af9fa8a71f666fe1766d071813b2156e912182a7aa914439c96ab469a576c17510f1617b4536f69c2ded22c1d50d7482cb7fbcde67af59ea734f3742a0e375c7e0210ae4ecff0f818f71b270d49137e46a6ab38afffc1e24cbbd1719870d3e86dc6ff5d1bd5411bb64dd569d593e4c248415f7d59339ff83a749b6a05dd86280bab71b975247de7eb838de56281ca26849ecb8e86cf7bf9a0cae3d93acb75b4af9a46f93c830ccb8c922facef21700878b23cd313fedda6ab91908b77f5142bd60e02deb87c4a2e80b25fc7c51982d1a700fc827a45cf4114305bbb485f8a04e9a4c576365222319432630051ceea8dbcbd0513366fe622b7c15b9c5b9c7697fa7ee201eae4aad0423bb61b96652b3f1e19a5670bad143d6d8b90a9472a2f0177fae07a68dce0172384663be8e4099ec3c154e81a0a2a42363569f8f4030ab4bba6ecede9447835cd97adce8f030e3abf7fe531c9b63a81a5285bf7b45c1f3599a59c5a6ecb70cd6a747b61245e673243b55bf0bf824bc01b754810a19812c082b2252e891d98896999590ce20c9cf78be0e86967f099849b7613ac45084d0c4b7490389500f296efcc38e69fccacd8a9cb3df706bc09c399886164afd22de21676d0fdb93fee1efaf2d363e2ee83295c2bfcdfd4bcce1f0197c9052a92b3ad4032d871562d7c46a0d7deb229244414be672c0dd9a0de1cdd818b8b498ecbf1c786d53e82bb1dfa187d22b4bae3179d56ca4fdd6f8f2d4c81df80726dfcf243829c33d23b77b8d039b0d169c5613ecde639a30eec12dbd364bdca747e8bbf610033c8a02b1f2763aa9a63806d07364d24228d7ba621133ec01c79059f65c54748703fc60eecc810382fbd160a8df4dcd47aa57f640f5ffd74a1f94f9a56156f7c0c6e34fdd6e43a5a0ac46b71474140fb8f16c10aab75678875f19fa82dad79a6cd284c78488aee66c5279d16acb21b8db2df30327783b64335934d7db219dc6846d9199329fa8f8e8a949863b39c03bbf8d83850920f4e87f41bc8f14c5fe3541444af632f5df9866dcae93493fae87809f16ee551bac8c4ddd0bce15ff7be0e573cd46fbac5fc7f4b764f46fd3bb09ab24bbbd9c38ee0f648386d892a90165e2acc2e5057c7aef96648ae013178932d6eab4b60d94555a7f380201c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945860300000000000000af3ce8279bc3e39954527b6314ce47076c97b16c3577c2e7ef014a9f62bb1e248ebb21fb1ca0aea57f0a3df15877c9de9751b1767d705d511fb67eec61dfd42f00" + ].map(|hex| >::from_hex(hex).expect("Block bytes are in valid hex representation")); +} From bf18f0c0a7aa466e04e91fd54fd2e7a5e97b808e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Sun, 18 Aug 2024 22:34:58 +0200 Subject: [PATCH 085/157] Introduce Nu7 --- zebra-chain/src/block/commitment.rs | 4 ++-- zebra-chain/src/history_tree.rs | 4 ++-- zebra-chain/src/parameters/network.rs | 2 ++ zebra-chain/src/parameters/network/testnet.rs | 8 ++++++- .../src/parameters/network/tests/vectors.rs | 5 ++-- zebra-chain/src/parameters/network_upgrade.rs | 23 ++++++++++++++++--- zebra-chain/src/primitives/zcash_history.rs | 3 ++- zebra-chain/src/transaction/arbitrary.rs | 2 +- 8 files changed, 39 insertions(+), 12 deletions(-) diff --git a/zebra-chain/src/block/commitment.rs b/zebra-chain/src/block/commitment.rs index 2cb09e75b22..ec4ef7d2616 100644 --- a/zebra-chain/src/block/commitment.rs +++ b/zebra-chain/src/block/commitment.rs @@ -125,7 +125,7 @@ impl Commitment { // NetworkUpgrade::current() returns the latest network upgrade that's activated at the provided height, so // on Regtest for heights above height 0, it could return NU6, and it's possible for the current network upgrade // to be NU6 (or Canopy, or any network upgrade above Heartwood) at the Heartwood activation height. - (Canopy | Nu5 | Nu6, activation_height) + (Canopy | Nu5 | Nu6 | Nu7, activation_height) if height == activation_height && Some(height) == Heartwood.activation_height(network) => { @@ -136,7 +136,7 @@ impl Commitment { } } (Heartwood | Canopy, _) => Ok(ChainHistoryRoot(ChainHistoryMmrRootHash(bytes))), - (Nu5 | Nu6, _) => Ok(ChainHistoryBlockTxAuthCommitment( + (Nu5 | Nu6 | Nu7, _) => Ok(ChainHistoryBlockTxAuthCommitment( ChainHistoryBlockTxAuthCommitmentHash(bytes), )), } diff --git a/zebra-chain/src/history_tree.rs b/zebra-chain/src/history_tree.rs index 91fa3a17628..613bf0616d7 100644 --- a/zebra-chain/src/history_tree.rs +++ b/zebra-chain/src/history_tree.rs @@ -102,7 +102,7 @@ impl NonEmptyHistoryTree { )?; InnerHistoryTree::PreOrchard(tree) } - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => { + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => { let tree = Tree::::new_from_cache( network, network_upgrade, @@ -156,7 +156,7 @@ impl NonEmptyHistoryTree { )?; (InnerHistoryTree::PreOrchard(tree), entry) } - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => { + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => { let (tree, entry) = Tree::::new_from_block( network, block, diff --git a/zebra-chain/src/parameters/network.rs b/zebra-chain/src/parameters/network.rs index e8571340b7d..d119c087dd9 100644 --- a/zebra-chain/src/parameters/network.rs +++ b/zebra-chain/src/parameters/network.rs @@ -152,10 +152,12 @@ impl Network { pub fn new_regtest( nu5_activation_height: Option, nu6_activation_height: Option, + nu7_activation_height: Option, ) -> Self { Self::new_configured_testnet(testnet::Parameters::new_regtest( nu5_activation_height, nu6_activation_height, + nu7_activation_height, )) } diff --git a/zebra-chain/src/parameters/network/testnet.rs b/zebra-chain/src/parameters/network/testnet.rs index 78f7a69a302..7c3ab24477b 100644 --- a/zebra-chain/src/parameters/network/testnet.rs +++ b/zebra-chain/src/parameters/network/testnet.rs @@ -206,6 +206,9 @@ pub struct ConfiguredActivationHeights { /// Activation height for `NU6` network upgrade. #[serde(rename = "NU6")] pub nu6: Option, + /// Activation height for `NU7` network upgrade. + #[serde(rename = "NU7")] + pub nu7: Option, } /// Builder for the [`Parameters`] struct. @@ -336,6 +339,7 @@ impl ParametersBuilder { canopy, nu5, nu6, + nu7, }: ConfiguredActivationHeights, ) -> Self { use NetworkUpgrade::*; @@ -358,6 +362,7 @@ impl ParametersBuilder { .chain(canopy.into_iter().map(|h| (h, Canopy))) .chain(nu5.into_iter().map(|h| (h, Nu5))) .chain(nu6.into_iter().map(|h| (h, Nu6))) + .chain(nu7.into_iter().map(|h| (h, Nu7))) .map(|(h, nu)| (h.try_into().expect("activation height must be valid"), nu)) .collect(); @@ -588,6 +593,7 @@ impl Parameters { pub fn new_regtest( nu5_activation_height: Option, nu6_activation_height: Option, + nu7_activation_height: Option, ) -> Self { #[cfg(any(test, feature = "proptest-impl"))] let nu5_activation_height = nu5_activation_height.or(Some(100)); @@ -647,7 +653,7 @@ impl Parameters { disable_pow, pre_blossom_halving_interval, post_blossom_halving_interval, - } = Self::new_regtest(None, None); + } = Self::new_regtest(None, None, None); self.network_name == network_name && self.genesis_hash == genesis_hash diff --git a/zebra-chain/src/parameters/network/tests/vectors.rs b/zebra-chain/src/parameters/network/tests/vectors.rs index 4282c86844f..ca341184b8c 100644 --- a/zebra-chain/src/parameters/network/tests/vectors.rs +++ b/zebra-chain/src/parameters/network/tests/vectors.rs @@ -109,6 +109,7 @@ fn activates_network_upgrades_correctly() { let expected_activation_height = 1; let network = testnet::Parameters::build() .with_activation_heights(ConfiguredActivationHeights { + // FIXME: nu7? nu6: Some(expected_activation_height), ..Default::default() }) @@ -147,7 +148,7 @@ fn activates_network_upgrades_correctly() { (Network::Mainnet, MAINNET_ACTIVATION_HEIGHTS), (Network::new_default_testnet(), TESTNET_ACTIVATION_HEIGHTS), ( - Network::new_regtest(None, None), + Network::new_regtest(None, None, None), expected_default_regtest_activation_heights, ), ] { @@ -198,7 +199,7 @@ fn check_configured_network_name() { "Mainnet should be displayed as 'Mainnet'" ); assert_eq!( - Network::new_regtest(None, None).to_string(), + Network::new_regtest(None, None, None).to_string(), "Regtest", "Regtest should be displayed as 'Regtest'" ); diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 57165d0c760..c1719451fca 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -15,7 +15,7 @@ use hex::{FromHex, ToHex}; use proptest_derive::Arbitrary; /// A list of network upgrades in the order that they must be activated. -pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 9] = [ +pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 10] = [ Genesis, BeforeOverwinter, Overwinter, @@ -25,6 +25,7 @@ pub const NETWORK_UPGRADES_IN_ORDER: [NetworkUpgrade; 9] = [ Canopy, Nu5, Nu6, + Nu7, ]; /// A Zcash network upgrade. @@ -61,6 +62,8 @@ pub enum NetworkUpgrade { /// The Zcash protocol after the NU6 upgrade. #[serde(rename = "NU6")] Nu6, + /// The Zcash protocol after the NU7 upgrade. + Nu7, } impl fmt::Display for NetworkUpgrade { @@ -90,6 +93,8 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_046_400), Canopy), (block::Height(1_687_104), Nu5), (block::Height(2_726_400), Nu6), + // FIXME: TODO: Add NU7 with a correct value + // (block::Height(2_726_401), Nu7), ]; /// Fake mainnet network upgrade activation heights, used in tests. @@ -104,6 +109,7 @@ const FAKE_MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] = &[ (block::Height(30), Canopy), (block::Height(35), Nu5), (block::Height(40), Nu6), + (block::Height(45), Nu7), ]; /// Testnet network upgrade activation heights. @@ -126,6 +132,8 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_028_500), Canopy), (block::Height(1_842_420), Nu5), (block::Height(2_976_000), Nu6), + // FIXME: TODO: Set a correct value for NU7 + (block::Height(2_942_001), Nu7), ]; /// Fake testnet network upgrade activation heights, used in tests. @@ -140,6 +148,7 @@ const FAKE_TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] = &[ (block::Height(30), Canopy), (block::Height(35), Nu5), (block::Height(40), Nu6), + (block::Height(45), Nu7), ]; /// The Consensus Branch Id, used to bind transactions and blocks to a @@ -216,6 +225,8 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Canopy, ConsensusBranchId(0xe9ff75a6)), (Nu5, ConsensusBranchId(0xc2d6d0b4)), (Nu6, ConsensusBranchId(0xc8e71055)), + // FIXME: use a proper value below + (Nu7, ConsensusBranchId(0xc8e71056)), ]; /// The target block spacing before Blossom. @@ -332,7 +343,8 @@ impl NetworkUpgrade { Heartwood => Some(Canopy), Canopy => Some(Nu5), Nu5 => Some(Nu6), - Nu6 => None, + Nu6 => Some(Nu7), + Nu7 => None, } } @@ -409,7 +421,9 @@ impl NetworkUpgrade { pub fn target_spacing(&self) -> Duration { let spacing_seconds = match self { Genesis | BeforeOverwinter | Overwinter | Sapling => PRE_BLOSSOM_POW_TARGET_SPACING, - Blossom | Heartwood | Canopy | Nu5 | Nu6 => POST_BLOSSOM_POW_TARGET_SPACING.into(), + Blossom | Heartwood | Canopy | Nu5 | Nu6 | Nu7 => { + POST_BLOSSOM_POW_TARGET_SPACING.into() + } }; Duration::seconds(spacing_seconds) @@ -531,6 +545,9 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Canopy => Self::Canopy, zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, + // FIXME: do we need the following cfg check? + #[cfg(zcash_unstable = "nu7")] + zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu7, } } } diff --git a/zebra-chain/src/primitives/zcash_history.rs b/zebra-chain/src/primitives/zcash_history.rs index e8ca97d63f8..4b52c85d8e8 100644 --- a/zebra-chain/src/primitives/zcash_history.rs +++ b/zebra-chain/src/primitives/zcash_history.rs @@ -276,7 +276,8 @@ impl Version for zcash_history::V1 { NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy | NetworkUpgrade::Nu5 - | NetworkUpgrade::Nu6 => zcash_history::NodeData { + | NetworkUpgrade::Nu6 + | NetworkUpgrade::Nu7 => zcash_history::NodeData { consensus_branch_id: branch_id.into(), subtree_commitment: block_hash, start_time: time, diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index cf4aa7a9552..0541bd7acd3 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -778,7 +778,7 @@ impl Arbitrary for Transaction { NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy => { Self::v4_strategy(ledger_state) } - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => prop_oneof![ + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => prop_oneof![ Self::v4_strategy(ledger_state.clone()), Self::v5_strategy(ledger_state) ] From 99ec8e6356ef041e5967db5197315f77d93f2f7e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 19 Aug 2024 07:51:31 +0200 Subject: [PATCH 086/157] Introduce Nu7 fo other crates of Zebra --- zebra-consensus/src/transaction.rs | 5 +++-- zebra-consensus/src/transaction/tests/prop.rs | 3 ++- zebra-network/src/config.rs | 17 +++++++++++------ zebra-network/src/protocol/external/types.rs | 3 +++ .../types/get_block_template/proposal.rs | 2 +- zebrad/tests/common/configs/v1.9.0.toml | 2 ++ 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index 1c303003615..192f1413332 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -678,7 +678,8 @@ where | NetworkUpgrade::Heartwood | NetworkUpgrade::Canopy | NetworkUpgrade::Nu5 - | NetworkUpgrade::Nu6 => Ok(()), + | NetworkUpgrade::Nu6 + | NetworkUpgrade::Nu7 => Ok(()), // Does not support V4 transactions NetworkUpgrade::Genesis @@ -766,7 +767,7 @@ where // // Note: Here we verify the transaction version number of the above rule, the group // id is checked in zebra-chain crate, in the transaction serialize. - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => Ok(()), + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => Ok(()), // Does not support V5 transactions NetworkUpgrade::Genesis diff --git a/zebra-consensus/src/transaction/tests/prop.rs b/zebra-consensus/src/transaction/tests/prop.rs index f45b4731de0..3f57bbb74bf 100644 --- a/zebra-consensus/src/transaction/tests/prop.rs +++ b/zebra-consensus/src/transaction/tests/prop.rs @@ -344,7 +344,8 @@ fn sanitize_transaction_version( BeforeOverwinter => 2, Overwinter => 3, Sapling | Blossom | Heartwood | Canopy => 4, - Nu5 | Nu6 => 5, + // FIXME: Use 6 for Nu7 + Nu5 | Nu6 | Nu7 => 5, } }; diff --git a/zebra-network/src/config.rs b/zebra-network/src/config.rs index 8619507fa0d..25e82714ae5 100644 --- a/zebra-network/src/config.rs +++ b/zebra-network/src/config.rs @@ -668,12 +668,17 @@ impl<'de> Deserialize<'de> for Config { (NetworkKind::Mainnet, _) => Network::Mainnet, (NetworkKind::Testnet, None) => Network::new_default_testnet(), (NetworkKind::Regtest, testnet_parameters) => { - let (nu5_activation_height, nu6_activation_height) = testnet_parameters - .and_then(|params| params.activation_heights) - .map(|ConfiguredActivationHeights { nu5, nu6, .. }| (nu5, nu6)) - .unwrap_or_default(); - - Network::new_regtest(nu5_activation_height, nu6_activation_height) + let (nu5_activation_height, nu6_activation_height, nu7_activation_height) = + testnet_parameters + .and_then(|params| params.activation_heights) + .map(|ConfiguredActivationHeights { nu5, nu6, nu7, .. }| (nu5, nu6, nu7)) + .unwrap_or_default(); + + Network::new_regtest( + nu5_activation_height, + nu6_activation_height, + nu7_activation_height, + ) } ( NetworkKind::Testnet, diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index c6241ba4d78..725d8d6d8de 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -106,6 +106,9 @@ impl Version { (Mainnet, Nu5) => 170_100, (Testnet(params), Nu6) if params.is_default_testnet() => 170_110, (Mainnet, Nu6) => 170_120, + // FIXME: use proper values for Nu7 + (Testnet(params), Nu7) if params.is_default_testnet() => 170_111, + (Mainnet, Nu7) => 170_121, // It should be fine to reject peers with earlier network protocol versions on custom testnets for now. (Testnet(_), _) => CURRENT_NETWORK_PROTOCOL_VERSION.0, diff --git a/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs b/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs index fc0805b533d..373ba2d7c20 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs/types/get_block_template/proposal.rs @@ -217,7 +217,7 @@ pub fn proposal_block_from_template( | NetworkUpgrade::Blossom | NetworkUpgrade::Heartwood => panic!("pre-Canopy block templates not supported"), NetworkUpgrade::Canopy => chain_history_root.bytes_in_serialized_order().into(), - NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 => { + NetworkUpgrade::Nu5 | NetworkUpgrade::Nu6 | NetworkUpgrade::Nu7 => { block_commitments_hash.bytes_in_serialized_order().into() } }; diff --git a/zebrad/tests/common/configs/v1.9.0.toml b/zebrad/tests/common/configs/v1.9.0.toml index 11bcf62107a..93291298f98 100644 --- a/zebrad/tests/common/configs/v1.9.0.toml +++ b/zebrad/tests/common/configs/v1.9.0.toml @@ -73,6 +73,8 @@ Heartwood = 903_800 Canopy = 1_028_500 NU5 = 1_842_420 NU6 = 2_000_000 +# FIXME: Use a proper value for NU7. +NU7 = 2_000_001 [network.testnet_parameters.pre_nu6_funding_streams.height_range] start = 0 From 7e2ca82aa0e2964b0de97986aa38162cbe573f06 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 11:05:59 +0200 Subject: [PATCH 087/157] Fix of new_regtest call (as it additionally needs Nu7 arg now) --- zebrad/tests/common/regtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebrad/tests/common/regtest.rs b/zebrad/tests/common/regtest.rs index bf1cba697de..f7b571e5a09 100644 --- a/zebrad/tests/common/regtest.rs +++ b/zebrad/tests/common/regtest.rs @@ -43,7 +43,7 @@ pub(crate) async fn submit_blocks_test() -> Result<()> { let _init_guard = zebra_test::init(); info!("starting regtest submit_blocks test"); - let network = Network::new_regtest(None, None); + let network = Network::new_regtest(None, None, None); let mut config = os_assigned_rpc_port_config(false, &network)?; config.mempool.debug_enable_at_height = Some(0); From 78e035ac70396ca95b88d0901d10fd4f156aea13 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 13:15:21 +0200 Subject: [PATCH 088/157] Fix of new_regtest call (as it additionally needs Nu7 arg now) (2) --- zebra-consensus/src/checkpoint/list/tests.rs | 2 +- zebrad/tests/acceptance.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zebra-consensus/src/checkpoint/list/tests.rs b/zebra-consensus/src/checkpoint/list/tests.rs index 5a2fe803f3d..698eaf36082 100644 --- a/zebra-consensus/src/checkpoint/list/tests.rs +++ b/zebra-consensus/src/checkpoint/list/tests.rs @@ -237,7 +237,7 @@ fn checkpoint_list_load_hard_coded() -> Result<(), BoxError> { let _ = Mainnet.checkpoint_list(); let _ = Network::new_default_testnet().checkpoint_list(); - let _ = Network::new_regtest(None, None).checkpoint_list(); + let _ = Network::new_regtest(None, None, None).checkpoint_list(); Ok(()) } diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index cd3572ce3f2..c71cede4c3b 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -2907,7 +2907,7 @@ async fn fully_synced_rpc_z_getsubtreesbyindex_snapshot_test() -> Result<()> { async fn validate_regtest_genesis_block() { let _init_guard = zebra_test::init(); - let network = Network::new_regtest(None, None); + let network = Network::new_regtest(None, None, None); let state = zebra_state::init_test(&network); let ( block_verifier_router, @@ -2982,7 +2982,7 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { use zebra_state::{ReadResponse, Response}; let _init_guard = zebra_test::init(); - let mut config = os_assigned_rpc_port_config(false, &Network::new_regtest(None, None))?; + let mut config = os_assigned_rpc_port_config(false, &Network::new_regtest(None, None, None))?; config.state.ephemeral = false; let network = config.network.network.clone(); From ac491b8041f98603c32259482787dcc1ca3b0567 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 14:46:17 +0200 Subject: [PATCH 089/157] Set Nu7 as a network update for testnet in zebra-chain network tests --- zebra-chain/src/parameters/network/tests/vectors.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zebra-chain/src/parameters/network/tests/vectors.rs b/zebra-chain/src/parameters/network/tests/vectors.rs index ca341184b8c..6c1426e4e0e 100644 --- a/zebra-chain/src/parameters/network/tests/vectors.rs +++ b/zebra-chain/src/parameters/network/tests/vectors.rs @@ -109,8 +109,7 @@ fn activates_network_upgrades_correctly() { let expected_activation_height = 1; let network = testnet::Parameters::build() .with_activation_heights(ConfiguredActivationHeights { - // FIXME: nu7? - nu6: Some(expected_activation_height), + nu7: Some(expected_activation_height), ..Default::default() }) .to_network(); From 6883488fc2fdafbc5e0bf1706bea6f163e6d8dd6 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 15:14:51 +0200 Subject: [PATCH 090/157] Fix serde names for NU7 --- zebra-chain/src/parameters/network_upgrade.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index c1719451fca..06b99879279 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -63,6 +63,7 @@ pub enum NetworkUpgrade { #[serde(rename = "NU6")] Nu6, /// The Zcash protocol after the NU7 upgrade. + #[serde(rename = "NU7")] Nu7, } From aa373f1d2eeecd54b7f156f1dbca1fa708595dfa Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 17 Oct 2024 15:19:20 +0200 Subject: [PATCH 091/157] Update test snapshot in zebra-rpc to use NU7 --- .../tests/snapshots/get_blockchain_info@testnet_10.snap | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap index 3bea6c01509..9d7ea3f5176 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap @@ -1,5 +1,6 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs +assertion_line: 562 expression: info --- { @@ -69,6 +70,11 @@ expression: info "name": "NU6", "activationheight": 2976000, "status": "pending" + }, + "c8e71056": { + "name": "NU7", + "activationheight": 2942001, + "status": "pending" } }, "consensus": { From 0fba7f3c31901a36174da4cbb3d58044c18d6413 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 10:20:11 +0100 Subject: [PATCH 092/157] Copy Nu7-related changes from zsa-integration-state --- zebra-chain/src/parameters/network/testnet.rs | 1 + zebra-chain/src/parameters/network_upgrade.rs | 10 ++++++---- zebra-network/src/constants.rs | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/zebra-chain/src/parameters/network/testnet.rs b/zebra-chain/src/parameters/network/testnet.rs index 7c3ab24477b..dc1b4c83e28 100644 --- a/zebra-chain/src/parameters/network/testnet.rs +++ b/zebra-chain/src/parameters/network/testnet.rs @@ -610,6 +610,7 @@ impl Parameters { canopy: Some(1), nu5: nu5_activation_height, nu6: nu6_activation_height, + nu7: nu7_activation_height, ..Default::default() }) .with_halving_interval(PRE_BLOSSOM_REGTEST_HALVING_INTERVAL); diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 06b99879279..1eade62208c 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -227,7 +227,7 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Nu5, ConsensusBranchId(0xc2d6d0b4)), (Nu6, ConsensusBranchId(0xc8e71055)), // FIXME: use a proper value below - (Nu7, ConsensusBranchId(0xc8e71056)), + (Nu7, ConsensusBranchId(0x77777777)), ]; /// The target block spacing before Blossom. @@ -545,10 +545,12 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Heartwood => Self::Heartwood, zcash_protocol::consensus::NetworkUpgrade::Canopy => Self::Canopy, zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, + // FIXME: remove this cfg + //#[cfg(zcash_unstable = "nu6")] zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, - // FIXME: do we need the following cfg check? - #[cfg(zcash_unstable = "nu7")] - zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu7, + // FIXME: remove this cfg and process Nu7 properly (uses Self::Nu6 for now) + //#[cfg(zcash_unstable = "nu6")] + zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, } } } diff --git a/zebra-network/src/constants.rs b/zebra-network/src/constants.rs index a116fd63018..a9ecf68537a 100644 --- a/zebra-network/src/constants.rs +++ b/zebra-network/src/constants.rs @@ -403,7 +403,7 @@ lazy_static! { hash_map.insert(NetworkKind::Mainnet, Version::min_specified_for_upgrade(&Mainnet, Nu5)); hash_map.insert(NetworkKind::Testnet, Version::min_specified_for_upgrade(&Network::new_default_testnet(), Nu5)); - hash_map.insert(NetworkKind::Regtest, Version::min_specified_for_upgrade(&Network::new_regtest(None, None), Nu5)); + hash_map.insert(NetworkKind::Regtest, Version::min_specified_for_upgrade(&Network::new_regtest(None, None, None), Nu5)); hash_map }; From b42d84a56ce4d41c84554671864628e16f56f24e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 11:03:41 +0100 Subject: [PATCH 093/157] Uncomment zcash_unstable = nu7 --- zebra-chain/src/parameters/network_upgrade.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 1eade62208c..36f9e297272 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -549,7 +549,7 @@ impl From for NetworkUpgrade { //#[cfg(zcash_unstable = "nu6")] zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, // FIXME: remove this cfg and process Nu7 properly (uses Self::Nu6 for now) - //#[cfg(zcash_unstable = "nu6")] + #[cfg(zcash_unstable = "nu7")] zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, } } From d8b48c92a733d5a9c2ed8d755f627026ea607ab5 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 12:05:08 +0100 Subject: [PATCH 094/157] Fix Nu7 constants and add cfg(zcash_unstable ...) attribute according to PR #15 review comments --- zebra-chain/src/parameters/network_upgrade.rs | 19 ++++++++++--------- zebra-network/src/protocol/external/types.rs | 4 ++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 36f9e297272..ae6cf89fd7e 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -94,8 +94,9 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_046_400), Canopy), (block::Height(1_687_104), Nu5), (block::Height(2_726_400), Nu6), - // FIXME: TODO: Add NU7 with a correct value - // (block::Height(2_726_401), Nu7), + // FIXME: TODO: Use a proper value below. + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + (block::Height(2_726_401), Nu7), ]; /// Fake mainnet network upgrade activation heights, used in tests. @@ -133,7 +134,8 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(1_028_500), Canopy), (block::Height(1_842_420), Nu5), (block::Height(2_976_000), Nu6), - // FIXME: TODO: Set a correct value for NU7 + // FIXME: TODO: Use a proper value below. + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] (block::Height(2_942_001), Nu7), ]; @@ -226,8 +228,9 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Canopy, ConsensusBranchId(0xe9ff75a6)), (Nu5, ConsensusBranchId(0xc2d6d0b4)), (Nu6, ConsensusBranchId(0xc8e71055)), - // FIXME: use a proper value below - (Nu7, ConsensusBranchId(0x77777777)), + // FIXME: TODO: Use a proper value below. + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + (Nu7, ConsensusBranchId(0x77190AD8)), ]; /// The target block spacing before Blossom. @@ -545,11 +548,9 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Heartwood => Self::Heartwood, zcash_protocol::consensus::NetworkUpgrade::Canopy => Self::Canopy, zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, - // FIXME: remove this cfg - //#[cfg(zcash_unstable = "nu6")] zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, - // FIXME: remove this cfg and process Nu7 properly (uses Self::Nu6 for now) - #[cfg(zcash_unstable = "nu7")] + // FIXME: TODO: Use a proper value below. + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, } } diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 725d8d6d8de..652a2fe8776 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -107,8 +107,8 @@ impl Version { (Testnet(params), Nu6) if params.is_default_testnet() => 170_110, (Mainnet, Nu6) => 170_120, // FIXME: use proper values for Nu7 - (Testnet(params), Nu7) if params.is_default_testnet() => 170_111, - (Mainnet, Nu7) => 170_121, + (Testnet(params), Nu7) if params.is_default_testnet() => 170_130, + (Mainnet, Nu7) => 170_140, // It should be fine to reject peers with earlier network protocol versions on custom testnets for now. (Testnet(_), _) => CURRENT_NETWORK_PROTOCOL_VERSION.0, From 75f56e7e5615001346b0487919821c773e9db3bb Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 13:32:15 +0100 Subject: [PATCH 095/157] Update network constant values according to PR #15 review comments --- zebra-chain/src/parameters/network_upgrade.rs | 2 +- .../tests/snapshots/get_blockchain_info@testnet_10.snap | 4 ++-- zebrad/tests/common/configs/v1.9.0.toml | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index ae6cf89fd7e..4518a5bfb2a 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -230,7 +230,7 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Nu6, ConsensusBranchId(0xc8e71055)), // FIXME: TODO: Use a proper value below. #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - (Nu7, ConsensusBranchId(0x77190AD8)), + (Nu7, ConsensusBranchId(0x77190ad8)), ]; /// The target block spacing before Blossom. diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap index 9d7ea3f5176..3fb53c4f71c 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap @@ -71,9 +71,9 @@ expression: info "activationheight": 2976000, "status": "pending" }, - "c8e71056": { + "77190ad8": { "name": "NU7", - "activationheight": 2942001, + "activationheight": 2726401, "status": "pending" } }, diff --git a/zebrad/tests/common/configs/v1.9.0.toml b/zebrad/tests/common/configs/v1.9.0.toml index 93291298f98..98a4b14bf67 100644 --- a/zebrad/tests/common/configs/v1.9.0.toml +++ b/zebrad/tests/common/configs/v1.9.0.toml @@ -73,7 +73,6 @@ Heartwood = 903_800 Canopy = 1_028_500 NU5 = 1_842_420 NU6 = 2_000_000 -# FIXME: Use a proper value for NU7. NU7 = 2_000_001 [network.testnet_parameters.pre_nu6_funding_streams.height_range] From bba5fd53e3eaa6e70cc39ef7b62da1218b52585f Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 13:40:07 +0100 Subject: [PATCH 096/157] Update zebra-consensus/src/primitives/halo2/tests.rs Co-authored-by: Arya --- zebra-consensus/src/primitives/halo2/tests.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index 9b5c367e640..d5768709681 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -88,14 +88,7 @@ fn generate_test_vectors() { rk: <[u8; 32]>::from(a.rk()).into(), cm_x: pallas::Base::from_repr(a.cmx().into()).unwrap(), ephemeral_key: a.encrypted_note().epk_bytes.try_into().unwrap(), - // FIXME: support OrchardZSA too, 580 works for OrchardVanilla only! - // FIXME: consider more "type safe" way to do the following conversion - // (now it goes through &[u8]) - enc_ciphertext: <[u8; 580]>::try_from( - a.encrypted_note().enc_ciphertext.as_ref(), - ) - .unwrap() - .into(), + enc_ciphertext: a.encrypted_note().enc_ciphertext.0.into(), out_ciphertext: a.encrypted_note().out_ciphertext.into(), }; zebra_chain::orchard::shielded_data::AuthorizedAction { From f2b10a52b6464a9bee3e9767d1b3890a2c817b91 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 13:43:24 +0100 Subject: [PATCH 097/157] Add zcash_unstable=nu6 Rust flag to .cargo/config.toml to use nu6 by default --- .cargo/config.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 1368e393fe4..ab7095e21bd 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,6 +3,9 @@ # Flags that apply to all Zebra crates and configurations [target.'cfg(all())'] rustflags = [ + # FIXME: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) + "--cfg", "zcash_unstable=\"nu6\"", + # Zebra standard lints for Rust 1.65+ # High-risk code From 611830354713128afc9d8a1ac368ab8966e15ecb Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 13:43:55 +0100 Subject: [PATCH 098/157] Update zebra-chain/src/orchard/note/ciphertexts.rs Co-authored-by: Arya --- zebra-chain/src/orchard/note/ciphertexts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index b27ffbc53a1..5685633374d 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -1,6 +1,6 @@ //! Encrypted parts of Orchard notes. -// FIXME: make it a generic and add support for OrchardZSA (encrypted tote size ofr it is not 580!) +// FIXME: make it a generic and add support for OrchardZSA (where encrypted note size is not 580!) use std::{fmt, io}; From e97f991c95eb296604f97b5181e180c485ad59c8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 13:55:18 +0100 Subject: [PATCH 099/157] Use zcash_unstable = nu6 TODO nu7 as nu6 cfg attribute --- zebra-chain/src/parameters/network_upgrade.rs | 6 ++---- zebra-chain/src/primitives/zcash_primitives.rs | 9 +++------ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 3d35f0526d2..49a76d0a449 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -530,11 +530,9 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Heartwood => Self::Heartwood, zcash_protocol::consensus::NetworkUpgrade::Canopy => Self::Canopy, zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, - // FIXME: remove cfg - #[cfg(zcash_unstable = "nu6")] zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, - // FIXME: remove cfg and process Nu7 properly (uses Self::Nu6 for now) - #[cfg(zcash_unstable = "nu6")] + // FIXME: TODO: Use a proper value below. + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, } } diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index be90f18ed23..6c7bd634861 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -137,8 +137,7 @@ impl zp_tx::components::orchard::MapAuth for IdentityMap { @@ -157,12 +156,10 @@ impl<'a> zp_tx::Authorization for PrecomputedAuth<'a> { type SaplingAuth = sapling_crypto::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; - // FIXME: is this correct? - #[cfg(zcash_unstable = "nu6")] + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type OrchardZsaAuth = orchard::bundle::Authorized; - // FIXME: is this correct? - #[cfg(zcash_unstable = "nu6")] + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type IssueAuth = orchard::issuance::Signed; } From a5980e7bec664c020a45008a9d1533200c0a975d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 14:13:33 +0100 Subject: [PATCH 100/157] Add TODO comment for bridgetree dependency downgrading --- zebra-chain/Cargo.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 0a866a9153c..7b7c19c9acf 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -68,6 +68,7 @@ bitflags = "2.5.0" bitflags-serde-legacy = "0.1.1" blake2b_simd = "1.0.2" blake2s_simd = "1.0.2" +# TODO: Revert to "0.6.0" (or appropriate version) when the ZSA orchard fork is updated. bridgetree = "0.4.0" bs58 = { version = "0.5.1", features = ["check"] } byteorder = "1.5.0" @@ -178,7 +179,3 @@ required-features = ["bench"] [[bench]] name = "redpallas" harness = false - -# FIXME: remove this and all zcash_unstable usage in the code after updating librustzcash -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } From a0241d8352fb24f04e3657a98b1f514f9ac907b2 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 15:06:58 +0100 Subject: [PATCH 101/157] Add ENABLE_ZSA orchard flag --- zebra-chain/src/orchard/shielded_data.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zebra-chain/src/orchard/shielded_data.rs b/zebra-chain/src/orchard/shielded_data.rs index 5347919cd01..f830b3a30ff 100644 --- a/zebra-chain/src/orchard/shielded_data.rs +++ b/zebra-chain/src/orchard/shielded_data.rs @@ -231,6 +231,8 @@ bitflags! { const ENABLE_SPENDS = 0b00000001; /// Enable creating new non-zero valued Orchard notes. const ENABLE_OUTPUTS = 0b00000010; + /// Enable ZSA transactions. + const ENABLE_ZSA = 0b00000100; } } From f74671ea86df70353519685e8a39c1fa630fe85f Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 15:09:12 +0100 Subject: [PATCH 102/157] Update zebra-consensus/src/primitives/halo2.rs Co-authored-by: Arya --- zebra-consensus/src/primitives/halo2.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/zebra-consensus/src/primitives/halo2.rs b/zebra-consensus/src/primitives/halo2.rs index 447d9bbd449..baf1900670f 100644 --- a/zebra-consensus/src/primitives/halo2.rs +++ b/zebra-consensus/src/primitives/halo2.rs @@ -144,14 +144,9 @@ impl From<&zebra_chain::orchard::ShieldedData> for Item { .flags .contains(zebra_chain::orchard::Flags::ENABLE_OUTPUTS); - // FIXME: simplify the flags creation - make `Flags::from_parts` method pub? // FIXME: support OrchardZSA? - let flags = match (enable_spend, enable_output) { - (false, false) => orchard::builder::BundleType::DISABLED.flags(), - (false, true) => orchard::bundle::Flags::SPENDS_DISABLED_WITHOUT_ZSA, - (true, false) => orchard::bundle::Flags::OUTPUTS_DISABLED, - (true, true) => orchard::bundle::Flags::ENABLED_WITHOUT_ZSA, - }; + let flags = orchard::bundle::Flags::from_byte(shielded_data.flags.bits()) + .expect("type should not have unexpected bits"); let instances = shielded_data .actions() From 56a445f7333bac2acbaf90a710aef72873075b00 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 15:15:17 +0100 Subject: [PATCH 103/157] Remove resolved FIXMEs --- zebra-chain/src/orchard/note/ciphertexts.rs | 2 -- zebra-chain/src/primitives/zcash_primitives.rs | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index 5685633374d..8f857cf1444 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -1,7 +1,5 @@ //! Encrypted parts of Orchard notes. -// FIXME: make it a generic and add support for OrchardZSA (where encrypted note size is not 580!) - use std::{fmt, io}; use serde_big_array::BigArray; diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 6c7bd634861..67cef7716a2 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -288,10 +288,8 @@ impl<'a> PrecomputedTxData<'a> { all_prev_outputs: all_previous_outputs, }, }; - let tx_data: zp_tx::TransactionData = alt_tx - .into_data() - // FIXME: do we need to pass another arg values or orchard_zsa and issue instead of IdentityMap? - .map_authorization( + let tx_data: zp_tx::TransactionData = + alt_tx.into_data().map_authorization( f_transparent, IdentityMap, IdentityMap, From 25c5486ec7d045387fd139e29488ed77d4d81699 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 15:17:08 +0100 Subject: [PATCH 104/157] Remove resolved FIXMEs (2) --- zebra-consensus/src/primitives/halo2.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/zebra-consensus/src/primitives/halo2.rs b/zebra-consensus/src/primitives/halo2.rs index baf1900670f..c5d264674e4 100644 --- a/zebra-consensus/src/primitives/halo2.rs +++ b/zebra-consensus/src/primitives/halo2.rs @@ -75,7 +75,6 @@ pub type ItemVerifyingKey = VerifyingKey; lazy_static::lazy_static! { /// The halo2 proof verifying key. - // FIXME: support OrchardZSA? pub static ref VERIFYING_KEY: ItemVerifyingKey = ItemVerifyingKey::build::(); } @@ -144,7 +143,6 @@ impl From<&zebra_chain::orchard::ShieldedData> for Item { .flags .contains(zebra_chain::orchard::Flags::ENABLE_OUTPUTS); - // FIXME: support OrchardZSA? let flags = orchard::bundle::Flags::from_byte(shielded_data.flags.bits()) .expect("type should not have unexpected bits"); From 58da3357f7f5b464f31249a2588099f8996ddf72 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 10 Feb 2025 15:29:45 +0100 Subject: [PATCH 105/157] Add zcash_unstable = nu6 cfg in zebra-network/.../types.rs --- zebra-network/src/protocol/external/types.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 652a2fe8776..45c2278db51 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -106,8 +106,9 @@ impl Version { (Mainnet, Nu5) => 170_100, (Testnet(params), Nu6) if params.is_default_testnet() => 170_110, (Mainnet, Nu6) => 170_120, - // FIXME: use proper values for Nu7 + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] (Testnet(params), Nu7) if params.is_default_testnet() => 170_130, + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] (Mainnet, Nu7) => 170_140, // It should be fine to reject peers with earlier network protocol versions on custom testnets for now. From 9a5a5a121110280bd2d7b41319c5286f99cdabbf Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 11 Feb 2025 11:29:09 +0100 Subject: [PATCH 106/157] Fix nu7 activation heights in network_upgrade.rs (nu6 value + 1 does not work - causes a test failure) --- zebra-chain/src/parameters/network_upgrade.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 4518a5bfb2a..fe9eb672c01 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -96,7 +96,7 @@ pub(super) const MAINNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(2_726_400), Nu6), // FIXME: TODO: Use a proper value below. #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - (block::Height(2_726_401), Nu7), + (block::Height(3_111_000), Nu7), ]; /// Fake mainnet network upgrade activation heights, used in tests. @@ -136,7 +136,7 @@ pub(super) const TESTNET_ACTIVATION_HEIGHTS: &[(block::Height, NetworkUpgrade)] (block::Height(2_976_000), Nu6), // FIXME: TODO: Use a proper value below. #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - (block::Height(2_942_001), Nu7), + (block::Height(3_222_000), Nu7), ]; /// Fake testnet network upgrade activation heights, used in tests. @@ -551,7 +551,7 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, // FIXME: TODO: Use a proper value below. #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, + zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu7, } } } From 64d9994bdd02d1d2339469b27c84cd39b6702c57 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 11 Feb 2025 11:44:23 +0100 Subject: [PATCH 107/157] Uncomment RUSTFLAGS/RUSTDOCFLAGS variable settings in ci-basic.yml as it turned out they are still required despite the adding zcash_unstable to .cargo/config.toml --- .github/workflows/ci-basic.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index 226f1528046..c2cde8686bf 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -16,10 +16,9 @@ jobs: ROCKSDB_LIB_DIR: /usr/lib # Use system-installed Snappy library for compression in RocksDB SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu - # FIXME: remove the following commented lines # Enable the `nu6` feature in `zcash_protocol` - #RUSTFLAGS: '--cfg zcash_unstable="nu6"' - #RUSTDOCFLAGS: '--cfg zcash_unstable="nu6"' + RUSTFLAGS: '--cfg zcash_unstable="nu6"' + RUSTDOCFLAGS: '--cfg zcash_unstable="nu6"' steps: - uses: actions/checkout@v4 From cfaac4b1c0f6e86a4e0de40e3be849e0411546ef Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 11 Feb 2025 14:24:57 +0100 Subject: [PATCH 108/157] Update librustzcash and orchard version hashes in Cargo.lock, make a minorr fix in code to sync with that --- Cargo.lock | 22 +++++++++---------- .../src/primitives/zcash_note_encryption.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6690a968028..8b6f2e5b90d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1372,7 +1372,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "blake2b_simd", "byteorder", @@ -1407,7 +1407,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "blake2b_simd", ] @@ -2878,7 +2878,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.8.0" -source = "git+https://github.com/QED-it/orchard?branch=zsa1#a7c02d22a1e2f4310130ae2e7b9813136071bc75" +source = "git+https://github.com/QED-it/orchard?branch=zsa1#3dbdbc52c6e2ffeca015ae6eb80ad7f1c870384d" dependencies = [ "aes", "bitvec", @@ -5814,7 +5814,7 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" version = "0.3.2" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "bech32", "bs58", @@ -5826,7 +5826,7 @@ dependencies = [ [[package]] name = "zcash_client_backend" version = "0.12.1" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "base64 0.21.7", "bech32", @@ -5865,7 +5865,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "byteorder", "nonempty", @@ -5874,7 +5874,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "blake2b_simd", "byteorder", @@ -5910,7 +5910,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "bech32", "blake2b_simd", @@ -5947,7 +5947,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.15.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "aes", "bip0039", @@ -6008,7 +6008,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.1.1" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "document-features", "memuse", @@ -6548,7 +6548,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.0.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#2684455ab69452669132eff8effd1229fb5c8de9" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" dependencies = [ "base64 0.21.7", "nom", diff --git a/zebra-chain/src/primitives/zcash_note_encryption.rs b/zebra-chain/src/primitives/zcash_note_encryption.rs index cbc19afc5d2..20270117003 100644 --- a/zebra-chain/src/primitives/zcash_note_encryption.rs +++ b/zebra-chain/src/primitives/zcash_note_encryption.rs @@ -51,7 +51,7 @@ pub fn decrypts_successfully(transaction: &Transaction, network: &Network, heigh if let Some(bundle) = alt_tx.orchard_bundle() { for act in bundle.actions() { if zcash_note_encryption::try_output_recovery_with_ovk( - &orchard::note_encryption::OrchardDomain::for_action(act), + &orchard::domain::OrchardDomain::for_action(act), &orchard::keys::OutgoingViewingKey::from([0u8; 32]), act, act.cv_net(), From 6b7e6655034a8aab6e544b5443fd97694a85409c Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 11 Feb 2025 14:44:45 +0100 Subject: [PATCH 109/157] Fix consenus test to use the new orchard builder return type --- zebra-consensus/src/primitives/halo2/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index d5768709681..fc4a7aeba5c 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -63,7 +63,7 @@ fn generate_test_vectors() { .unwrap(); } - let bundle: Bundle<_, i64, OrchardVanilla> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, OrchardVanilla> = builder.build(rng).unwrap().0; let bundle = bundle .create_proof(&proving_key, rng) From 8ae0b92bc35c85579f715150b9ebe444b4fd0374 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 12 Feb 2025 15:25:31 +0100 Subject: [PATCH 110/157] Add cfg for CURRENT_NETWORK_PROTOCOL_VERSION constant definition, add FIXMEs for a couple of Nu6 processing cases, add processing of Nu7 --- zebra-chain/src/parameters/network/testnet.rs | 1 + zebra-consensus/src/block/check.rs | 1 + zebra-consensus/src/block/subsidy/funding_streams/tests.rs | 1 + zebra-network/src/constants.rs | 4 ++++ zebra-network/src/protocol/external/types.rs | 6 ++++-- zebra-rpc/src/methods/get_block_template_rpcs.rs | 1 + .../src/methods/tests/snapshot/get_block_template_rpcs.rs | 1 + zebrad/tests/acceptance.rs | 3 +++ 8 files changed, 16 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/parameters/network/testnet.rs b/zebra-chain/src/parameters/network/testnet.rs index dc1b4c83e28..f6153c8b304 100644 --- a/zebra-chain/src/parameters/network/testnet.rs +++ b/zebra-chain/src/parameters/network/testnet.rs @@ -787,6 +787,7 @@ impl Network { /// Returns post-Canopy funding streams for this network at the provided height pub fn funding_streams(&self, height: Height) -> &FundingStreams { + // FIXME: Would this work after Nu7 activation? if NetworkUpgrade::current(self, height) < NetworkUpgrade::Nu6 { self.pre_nu6_funding_streams() } else { diff --git a/zebra-consensus/src/block/check.rs b/zebra-consensus/src/block/check.rs index 24ef2ba2ed1..eaf193cda10 100644 --- a/zebra-consensus/src/block/check.rs +++ b/zebra-consensus/src/block/check.rs @@ -272,6 +272,7 @@ pub fn miner_fees_are_valid( // input. // // > [NU6 onward] The total output of a coinbase transaction MUST be equal to its total input. + // FIXME: Would this work after Nu7 activation? if if NetworkUpgrade::current(network, height) < NetworkUpgrade::Nu6 { total_output_value > total_input_value } else { diff --git a/zebra-consensus/src/block/subsidy/funding_streams/tests.rs b/zebra-consensus/src/block/subsidy/funding_streams/tests.rs index 91faa923c93..5cb8b3bc5f9 100644 --- a/zebra-consensus/src/block/subsidy/funding_streams/tests.rs +++ b/zebra-consensus/src/block/subsidy/funding_streams/tests.rs @@ -8,6 +8,7 @@ use crate::block::subsidy::general::block_subsidy; use super::*; /// Checks that the Mainnet funding stream values are correct. +// FIXME: Would this work after Nu7 activation? #[test] fn test_funding_stream_values() -> Result<(), Report> { let _init_guard = zebra_test::init(); diff --git a/zebra-network/src/constants.rs b/zebra-network/src/constants.rs index a9ecf68537a..a879a4562bf 100644 --- a/zebra-network/src/constants.rs +++ b/zebra-network/src/constants.rs @@ -340,7 +340,10 @@ pub const TIMESTAMP_TRUNCATION_SECONDS: u32 = 30 * 60; /// /// This version of Zebra draws the current network protocol version from /// [ZIP-253](https://zips.z.cash/zip-0253). +#[cfg(not(zcash_unstable = "nu6" /* TODO nu7 */ ))] pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_120); +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] +pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_140); /// The default RTT estimate for peer responses. /// @@ -398,6 +401,7 @@ lazy_static! { /// Testnet network upgrades. // TODO: Change `Nu5` to `Nu6` after NU6 activation. // TODO: Move the value here to a field on `testnet::Parameters` (#8367) + // TODO: FIXME: Change `Nu...` to `Nu7` after NU7 activation? pub static ref INITIAL_MIN_NETWORK_PROTOCOL_VERSION: HashMap = { let mut hash_map = HashMap::new(); diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 45c2278db51..91a1874c024 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -209,8 +209,9 @@ mod test { let _init_guard = zebra_test::init(); let highest_network_upgrade = NetworkUpgrade::current(network, block::Height::MAX); - assert!(highest_network_upgrade == Nu6 || highest_network_upgrade == Nu5, - "expected coverage of all network upgrades: add the new network upgrade to the list in this test"); + assert!( + highest_network_upgrade == Nu7 || highest_network_upgrade == Nu6 || highest_network_upgrade == Nu5, + "expected coverage of all network upgrades: add the new network upgrade to the list in this test"); for &network_upgrade in &[ BeforeOverwinter, @@ -221,6 +222,7 @@ mod test { Canopy, Nu5, Nu6, + Nu7, ] { let height = network_upgrade.activation_height(network); if let Some(height) = height { diff --git a/zebra-rpc/src/methods/get_block_template_rpcs.rs b/zebra-rpc/src/methods/get_block_template_rpcs.rs index 2d50552cfec..30661b664f7 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs.rs @@ -1234,6 +1234,7 @@ where // Separate the funding streams into deferred and non-deferred streams .partition(|(receiver, _)| matches!(receiver, FundingStreamReceiver::Deferred)); + // FIXME: Would this work after Nu7 activation? let is_nu6 = NetworkUpgrade::current(&network, height) == NetworkUpgrade::Nu6; let [lockbox_total, funding_streams_total]: [std::result::Result< diff --git a/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs b/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs index 8afb7dd312d..5479f0a9271 100644 --- a/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs @@ -149,6 +149,7 @@ pub async fn test_responses( ); if network.is_a_test_network() && !network.is_default_testnet() { + // FIXME: Would this work after Nu7 activation? let fake_future_nu6_block_height = NetworkUpgrade::Nu6.activation_height(network).unwrap().0 + 100_000; let get_block_subsidy = get_block_template_rpc diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index c71cede4c3b..4c717f62eb0 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -3362,6 +3362,7 @@ async fn nu6_funding_streams_and_coinbase_balance() -> Result<()> { panic!("this getblocktemplate call without parameters should return the `TemplateMode` variant of the response") }; + // FIXME: Would this work after Nu7 activation? let proposal_block = proposal_block_from_template(&block_template, None, NetworkUpgrade::Nu6)?; let hex_proposal_block = HexData(proposal_block.zcash_serialize_to_vec()?); @@ -3459,6 +3460,7 @@ async fn nu6_funding_streams_and_coinbase_balance() -> Result<()> { ..(*block_template) }; + // FIXME: Would this work after Nu7 activation? let proposal_block = proposal_block_from_template(&block_template, None, NetworkUpgrade::Nu6)?; // Submit the invalid block with an excessive coinbase output value @@ -3502,6 +3504,7 @@ async fn nu6_funding_streams_and_coinbase_balance() -> Result<()> { ..block_template }; + // FIXME: Would this work after Nu7 activation? let proposal_block = proposal_block_from_template(&block_template, None, NetworkUpgrade::Nu6)?; // Submit the invalid block with an excessive coinbase input value From 88b705d8edeae38b6fc2c95fab4c0e7793811a0b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 12 Feb 2025 15:47:44 +0100 Subject: [PATCH 111/157] Update get_blockchain_info@testnet_10.snap --- .../methods/tests/snapshots/get_blockchain_info@testnet_10.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap index 3fb53c4f71c..14085ee0770 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap @@ -73,7 +73,7 @@ expression: info }, "77190ad8": { "name": "NU7", - "activationheight": 2726401, + "activationheight": 3222000, "status": "pending" } }, From ef3f6da101357e8c9973f7a65617a7547cd3bf82 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 12 Feb 2025 16:06:30 +0100 Subject: [PATCH 112/157] Update get_blockchain_info@mainnet_10.snap --- .../tests/snapshots/get_blockchain_info@mainnet_10.snap | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap index 9986da0ec95..9fadb83a0fb 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap @@ -1,5 +1,6 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs +assertion_line: 562 expression: info --- { @@ -69,6 +70,11 @@ expression: info "name": "NU6", "activationheight": 2726400, "status": "pending" + }, + "77190ad8": { + "name": "NU7", + "activationheight": 3111000, + "status": "pending" } }, "consensus": { From c277d51cb900d88451da7b7fab2842c688422799 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 12 Feb 2025 15:25:31 +0100 Subject: [PATCH 113/157] Add cfg for CURRENT_NETWORK_PROTOCOL_VERSION constant definition, add FIXMEs for a couple of Nu6 processing cases, add processing of Nu7 --- zebra-chain/src/parameters/network/testnet.rs | 1 + zebra-consensus/src/block/check.rs | 1 + zebra-consensus/src/block/subsidy/funding_streams/tests.rs | 1 + zebra-network/src/constants.rs | 4 ++++ zebra-network/src/protocol/external/types.rs | 6 ++++-- zebra-rpc/src/methods/get_block_template_rpcs.rs | 1 + .../src/methods/tests/snapshot/get_block_template_rpcs.rs | 1 + zebrad/tests/acceptance.rs | 3 +++ 8 files changed, 16 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/parameters/network/testnet.rs b/zebra-chain/src/parameters/network/testnet.rs index dc1b4c83e28..f6153c8b304 100644 --- a/zebra-chain/src/parameters/network/testnet.rs +++ b/zebra-chain/src/parameters/network/testnet.rs @@ -787,6 +787,7 @@ impl Network { /// Returns post-Canopy funding streams for this network at the provided height pub fn funding_streams(&self, height: Height) -> &FundingStreams { + // FIXME: Would this work after Nu7 activation? if NetworkUpgrade::current(self, height) < NetworkUpgrade::Nu6 { self.pre_nu6_funding_streams() } else { diff --git a/zebra-consensus/src/block/check.rs b/zebra-consensus/src/block/check.rs index 24ef2ba2ed1..eaf193cda10 100644 --- a/zebra-consensus/src/block/check.rs +++ b/zebra-consensus/src/block/check.rs @@ -272,6 +272,7 @@ pub fn miner_fees_are_valid( // input. // // > [NU6 onward] The total output of a coinbase transaction MUST be equal to its total input. + // FIXME: Would this work after Nu7 activation? if if NetworkUpgrade::current(network, height) < NetworkUpgrade::Nu6 { total_output_value > total_input_value } else { diff --git a/zebra-consensus/src/block/subsidy/funding_streams/tests.rs b/zebra-consensus/src/block/subsidy/funding_streams/tests.rs index 91faa923c93..5cb8b3bc5f9 100644 --- a/zebra-consensus/src/block/subsidy/funding_streams/tests.rs +++ b/zebra-consensus/src/block/subsidy/funding_streams/tests.rs @@ -8,6 +8,7 @@ use crate::block::subsidy::general::block_subsidy; use super::*; /// Checks that the Mainnet funding stream values are correct. +// FIXME: Would this work after Nu7 activation? #[test] fn test_funding_stream_values() -> Result<(), Report> { let _init_guard = zebra_test::init(); diff --git a/zebra-network/src/constants.rs b/zebra-network/src/constants.rs index a9ecf68537a..a879a4562bf 100644 --- a/zebra-network/src/constants.rs +++ b/zebra-network/src/constants.rs @@ -340,7 +340,10 @@ pub const TIMESTAMP_TRUNCATION_SECONDS: u32 = 30 * 60; /// /// This version of Zebra draws the current network protocol version from /// [ZIP-253](https://zips.z.cash/zip-0253). +#[cfg(not(zcash_unstable = "nu6" /* TODO nu7 */ ))] pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_120); +#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] +pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_140); /// The default RTT estimate for peer responses. /// @@ -398,6 +401,7 @@ lazy_static! { /// Testnet network upgrades. // TODO: Change `Nu5` to `Nu6` after NU6 activation. // TODO: Move the value here to a field on `testnet::Parameters` (#8367) + // TODO: FIXME: Change `Nu...` to `Nu7` after NU7 activation? pub static ref INITIAL_MIN_NETWORK_PROTOCOL_VERSION: HashMap = { let mut hash_map = HashMap::new(); diff --git a/zebra-network/src/protocol/external/types.rs b/zebra-network/src/protocol/external/types.rs index 45c2278db51..91a1874c024 100644 --- a/zebra-network/src/protocol/external/types.rs +++ b/zebra-network/src/protocol/external/types.rs @@ -209,8 +209,9 @@ mod test { let _init_guard = zebra_test::init(); let highest_network_upgrade = NetworkUpgrade::current(network, block::Height::MAX); - assert!(highest_network_upgrade == Nu6 || highest_network_upgrade == Nu5, - "expected coverage of all network upgrades: add the new network upgrade to the list in this test"); + assert!( + highest_network_upgrade == Nu7 || highest_network_upgrade == Nu6 || highest_network_upgrade == Nu5, + "expected coverage of all network upgrades: add the new network upgrade to the list in this test"); for &network_upgrade in &[ BeforeOverwinter, @@ -221,6 +222,7 @@ mod test { Canopy, Nu5, Nu6, + Nu7, ] { let height = network_upgrade.activation_height(network); if let Some(height) = height { diff --git a/zebra-rpc/src/methods/get_block_template_rpcs.rs b/zebra-rpc/src/methods/get_block_template_rpcs.rs index 2d50552cfec..30661b664f7 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs.rs @@ -1234,6 +1234,7 @@ where // Separate the funding streams into deferred and non-deferred streams .partition(|(receiver, _)| matches!(receiver, FundingStreamReceiver::Deferred)); + // FIXME: Would this work after Nu7 activation? let is_nu6 = NetworkUpgrade::current(&network, height) == NetworkUpgrade::Nu6; let [lockbox_total, funding_streams_total]: [std::result::Result< diff --git a/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs b/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs index 8afb7dd312d..5479f0a9271 100644 --- a/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs @@ -149,6 +149,7 @@ pub async fn test_responses( ); if network.is_a_test_network() && !network.is_default_testnet() { + // FIXME: Would this work after Nu7 activation? let fake_future_nu6_block_height = NetworkUpgrade::Nu6.activation_height(network).unwrap().0 + 100_000; let get_block_subsidy = get_block_template_rpc diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index c71cede4c3b..4c717f62eb0 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -3362,6 +3362,7 @@ async fn nu6_funding_streams_and_coinbase_balance() -> Result<()> { panic!("this getblocktemplate call without parameters should return the `TemplateMode` variant of the response") }; + // FIXME: Would this work after Nu7 activation? let proposal_block = proposal_block_from_template(&block_template, None, NetworkUpgrade::Nu6)?; let hex_proposal_block = HexData(proposal_block.zcash_serialize_to_vec()?); @@ -3459,6 +3460,7 @@ async fn nu6_funding_streams_and_coinbase_balance() -> Result<()> { ..(*block_template) }; + // FIXME: Would this work after Nu7 activation? let proposal_block = proposal_block_from_template(&block_template, None, NetworkUpgrade::Nu6)?; // Submit the invalid block with an excessive coinbase output value @@ -3502,6 +3504,7 @@ async fn nu6_funding_streams_and_coinbase_balance() -> Result<()> { ..block_template }; + // FIXME: Would this work after Nu7 activation? let proposal_block = proposal_block_from_template(&block_template, None, NetworkUpgrade::Nu6)?; // Submit the invalid block with an excessive coinbase input value From c48c753c7ac2e39764ec9263e6afccaaba0c4bc2 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 12 Feb 2025 15:47:44 +0100 Subject: [PATCH 114/157] Update get_blockchain_info@testnet_10.snap --- .../methods/tests/snapshots/get_blockchain_info@testnet_10.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap index 3fb53c4f71c..14085ee0770 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap @@ -73,7 +73,7 @@ expression: info }, "77190ad8": { "name": "NU7", - "activationheight": 2726401, + "activationheight": 3222000, "status": "pending" } }, From 152d8935682bdc1630024e3cb1fe047137bef897 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 12 Feb 2025 16:06:30 +0100 Subject: [PATCH 115/157] Update get_blockchain_info@mainnet_10.snap --- .../tests/snapshots/get_blockchain_info@mainnet_10.snap | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap index 9986da0ec95..9fadb83a0fb 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap @@ -1,5 +1,6 @@ --- source: zebra-rpc/src/methods/tests/snapshot.rs +assertion_line: 562 expression: info --- { @@ -69,6 +70,11 @@ expression: info "name": "NU6", "activationheight": 2726400, "status": "pending" + }, + "77190ad8": { + "name": "NU7", + "activationheight": 3111000, + "status": "pending" } }, "consensus": { From 225dac1a303adc30ddd43446cd3d96767d6aa2ca Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 11:10:13 +0100 Subject: [PATCH 116/157] Minor fix to align with orchard changes --- zebra-chain/src/orchard/orchard_flavor_ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index f8ce25d0ed5..ea8931130a1 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -7,7 +7,7 @@ use serde::{de::DeserializeOwned, Serialize}; #[cfg(any(test, feature = "proptest-impl"))] use proptest_derive::Arbitrary; -use orchard::{note_encryption::OrchardDomainCommon, orchard_flavor}; +use orchard::{domain::OrchardDomainCommon, orchard_flavor}; use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; From a1fc48eb77a01569765c68bb064a6ec35534a50d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 13:24:37 +0100 Subject: [PATCH 117/157] Update OrchardZSA test vectors to use the correct consensus branch id value --- .../src/orchard_zsa/tests/vectors/blocks.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs index 324f270c04d..d715755509b 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -110,8 +110,8 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, - 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x55, 0x10, 0xe7, + 0xc8, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x40, 0xa8, 0x86, 0x5d, 0x61, 0x39, 0xb3, 0x39, 0x62, 0x94, 0xee, 0x42, 0xc5, 0xa6, 0x0b, 0x63, 0x57, 0xca, 0x65, 0x8b, 0xa6, 0x76, 0xf2, 0xd6, 0xda, 0x8e, 0x00, 0xcf, 0x60, 0xe8, 0x33, 0xa4, 0x55, 0xec, 0x7c, 0x99, 0x0f, 0xda, 0xd2, 0x46, 0xc0, 0x5b, 0x4a, 0x8f, 0xe5, @@ -860,8 +860,8 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, - 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x57, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x55, 0x10, 0xe7, + 0xc8, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x57, 0x6a, 0xc2, 0x2a, 0x5e, 0xe1, 0xc1, 0x53, 0x80, 0x98, 0x98, 0x9d, 0x4e, 0xe3, 0x6a, 0x88, 0xb9, 0x25, 0xea, 0xdd, 0xc9, 0x0b, 0x5c, 0x14, 0xbb, 0xc9, 0xf1, 0x0a, 0xa0, 0x22, 0x46, 0x2f, 0xd7, 0xfb, 0xb2, 0xf4, 0xca, 0x12, 0x4b, 0xc6, 0xfe, 0x41, 0xc0, 0x35, 0x88, 0x21, @@ -1594,8 +1594,8 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, - 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x55, 0x10, 0xe7, + 0xc8, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0xca, 0xe4, 0xbf, 0xa4, 0xba, 0xfc, 0x37, 0x22, 0xd8, 0xf9, 0x3c, 0x6c, 0xfb, 0xcc, 0xba, 0xd7, 0x94, 0x44, 0x58, 0x85, 0x10, 0xba, 0x7a, 0x9d, 0x8e, 0xa3, 0x90, 0x6e, 0x7f, 0xdc, 0xa8, 0x7a, 0x06, 0x13, 0x03, 0x39, 0x58, 0x9a, 0x79, 0x4c, 0x5a, 0x25, 0x5a, 0x2c, 0xd2, @@ -2221,7 +2221,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0xb8, 0x40, 0xa0, 0xd0, 0x5b, 0x7e, 0x8e, 0x35, 0xfd, 0x0a, 0xf3, 0x08, 0xe3, 0x37, 0xfa, 0xd8, 0xb9, 0x08, 0x94, 0x79, 0xdd, 0x35, 0x73, 0x05, 0x8e, 0x64, 0x48, 0x82, 0xe9, 0xb0, 0x49, 0x1d, 0x06, 0x89, 0x26, 0xc4, 0x8c, 0x06, 0x52, 0xad, 0xd9, 0x32, 0x00, 0x06, 0x00, - 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x55, 0x10, 0xe7, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x56, 0x90, 0xe6, 0xfe, 0xfc, 0x61, 0x4c, 0xd6, 0x40, 0xc0, 0xfc, 0x9c, 0x69, 0x91, 0x0d, 0x55, 0xd2, 0x0f, 0x25, 0xad, 0xfe, 0x3e, 0x4c, 0x9c, 0x06, 0x96, 0x9a, 0xe3, 0x2a, 0x51, 0xbe, 0x9a, 0x7a, 0x06, 0x13, 0x03, 0x39, From 015f8b3dd2d37d7a03a65d31348007dbf5f9f27b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 15:14:53 +0100 Subject: [PATCH 118/157] Revert "Update OrchardZSA test vectors to use the correct consensus branch id value" This reverts commit a1fc48eb77a01569765c68bb064a6ec35534a50d. --- .../src/orchard_zsa/tests/vectors/blocks.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs index d715755509b..324f270c04d 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -110,8 +110,8 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x55, 0x10, 0xe7, - 0xc8, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x40, 0xa8, 0x86, 0x5d, 0x61, 0x39, 0xb3, 0x39, 0x62, 0x94, 0xee, 0x42, 0xc5, 0xa6, 0x0b, 0x63, 0x57, 0xca, 0x65, 0x8b, 0xa6, 0x76, 0xf2, 0xd6, 0xda, 0x8e, 0x00, 0xcf, 0x60, 0xe8, 0x33, 0xa4, 0x55, 0xec, 0x7c, 0x99, 0x0f, 0xda, 0xd2, 0x46, 0xc0, 0x5b, 0x4a, 0x8f, 0xe5, @@ -860,8 +860,8 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x55, 0x10, 0xe7, - 0xc8, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x57, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x57, 0x6a, 0xc2, 0x2a, 0x5e, 0xe1, 0xc1, 0x53, 0x80, 0x98, 0x98, 0x9d, 0x4e, 0xe3, 0x6a, 0x88, 0xb9, 0x25, 0xea, 0xdd, 0xc9, 0x0b, 0x5c, 0x14, 0xbb, 0xc9, 0xf1, 0x0a, 0xa0, 0x22, 0x46, 0x2f, 0xd7, 0xfb, 0xb2, 0xf4, 0xca, 0x12, 0x4b, 0xc6, 0xfe, 0x41, 0xc0, 0x35, 0x88, 0x21, @@ -1594,8 +1594,8 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x55, 0x10, 0xe7, - 0xc8, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0xca, 0xe4, 0xbf, 0xa4, 0xba, 0xfc, 0x37, 0x22, 0xd8, 0xf9, 0x3c, 0x6c, 0xfb, 0xcc, 0xba, 0xd7, 0x94, 0x44, 0x58, 0x85, 0x10, 0xba, 0x7a, 0x9d, 0x8e, 0xa3, 0x90, 0x6e, 0x7f, 0xdc, 0xa8, 0x7a, 0x06, 0x13, 0x03, 0x39, 0x58, 0x9a, 0x79, 0x4c, 0x5a, 0x25, 0x5a, 0x2c, 0xd2, @@ -2221,7 +2221,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0xb8, 0x40, 0xa0, 0xd0, 0x5b, 0x7e, 0x8e, 0x35, 0xfd, 0x0a, 0xf3, 0x08, 0xe3, 0x37, 0xfa, 0xd8, 0xb9, 0x08, 0x94, 0x79, 0xdd, 0x35, 0x73, 0x05, 0x8e, 0x64, 0x48, 0x82, 0xe9, 0xb0, 0x49, 0x1d, 0x06, 0x89, 0x26, 0xc4, 0x8c, 0x06, 0x52, 0xad, 0xd9, 0x32, 0x00, 0x06, 0x00, - 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x55, 0x10, 0xe7, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x56, 0x90, 0xe6, 0xfe, 0xfc, 0x61, 0x4c, 0xd6, 0x40, 0xc0, 0xfc, 0x9c, 0x69, 0x91, 0x0d, 0x55, 0xd2, 0x0f, 0x25, 0xad, 0xfe, 0x3e, 0x4c, 0x9c, 0x06, 0x96, 0x9a, 0xe3, 0x2a, 0x51, 0xbe, 0x9a, 0x7a, 0x06, 0x13, 0x03, 0x39, From 10f37407b7348a9ee894c6c486c3b01b66a18c93 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 15:17:34 +0100 Subject: [PATCH 119/157] Update librustzcash commit in Cargo.lock --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b6f2e5b90d..c700474b30a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1372,7 +1372,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "blake2b_simd", "byteorder", @@ -1407,7 +1407,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "blake2b_simd", ] @@ -5814,7 +5814,7 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" version = "0.3.2" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "bech32", "bs58", @@ -5826,7 +5826,7 @@ dependencies = [ [[package]] name = "zcash_client_backend" version = "0.12.1" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "base64 0.21.7", "bech32", @@ -5865,7 +5865,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "byteorder", "nonempty", @@ -5874,7 +5874,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "blake2b_simd", "byteorder", @@ -5910,7 +5910,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "bech32", "blake2b_simd", @@ -5947,7 +5947,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.15.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "aes", "bip0039", @@ -6008,7 +6008,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.1.1" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "document-features", "memuse", @@ -6548,7 +6548,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.0.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#5ea95ea2bfa55ccd8d39c1be39eb4978ec338045" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" dependencies = [ "base64 0.21.7", "nom", From 164e5de4e89401e13ce54a144005f5d95adfb282 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 15:20:58 +0100 Subject: [PATCH 120/157] Change TX_V6_VERSION_GROUP_ID value back to a temporary 0x7777_7777, to aling with the one used in librustzcash --- zebra-chain/src/parameters/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index 77b88abca44..0eb6f04ff66 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -17,4 +17,4 @@ pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; /// Orchard transactions must use transaction version 5 and this version /// group ID. // FIXME: use a proper value! -pub const TX_V6_VERSION_GROUP_ID: u32 = 0x26A7_270B; +pub const TX_V6_VERSION_GROUP_ID: u32 = 0x7777_7777; From 998a2c7046a257b8a34d6d2ac10557e34ef135f6 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 15:54:58 +0100 Subject: [PATCH 121/157] Update zebra-chain to sync with the updated librustzcash (zcash_primitives) interface (OrchardBundle enum etc.) --- .../src/primitives/zcash_note_encryption.rs | 44 ++++++++++++++----- .../src/primitives/zcash_primitives.rs | 14 ++---- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/zebra-chain/src/primitives/zcash_note_encryption.rs b/zebra-chain/src/primitives/zcash_note_encryption.rs index 20270117003..1b6673d5e11 100644 --- a/zebra-chain/src/primitives/zcash_note_encryption.rs +++ b/zebra-chain/src/primitives/zcash_note_encryption.rs @@ -8,6 +8,33 @@ use crate::{ transaction::Transaction, }; +use orchard::{ + bundle::{Authorization, Bundle}, + domain::OrchardDomainCommon, +}; + +use zcash_primitives::transaction::OrchardBundle; + +fn orchard_bundle_decrypts_successfully( + bundle: &Bundle, +) -> bool { + for act in bundle.actions() { + if zcash_note_encryption::try_output_recovery_with_ovk( + &orchard::domain::OrchardDomain::for_action(act), + &orchard::keys::OutgoingViewingKey::from([0u8; 32]), + act, + act.cv_net(), + &act.encrypted_note().out_ciphertext, + ) + .is_none() + { + return false; + } + } + + true +} + /// Returns true if all Sapling or Orchard outputs, if any, decrypt successfully with /// an all-zeroes outgoing viewing key. /// @@ -49,18 +76,11 @@ pub fn decrypts_successfully(transaction: &Transaction, network: &Network, heigh } if let Some(bundle) = alt_tx.orchard_bundle() { - for act in bundle.actions() { - if zcash_note_encryption::try_output_recovery_with_ovk( - &orchard::domain::OrchardDomain::for_action(act), - &orchard::keys::OutgoingViewingKey::from([0u8; 32]), - act, - act.cv_net(), - &act.encrypted_note().out_ciphertext, - ) - .is_none() - { - return false; - } + if !match bundle { + OrchardBundle::OrchardVanilla(bundle) => orchard_bundle_decrypts_successfully(bundle), + OrchardBundle::OrchardZSA(bundle) => orchard_bundle_decrypts_successfully(bundle), + } { + return false; } } diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 67cef7716a2..9aba76215f2 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -156,9 +156,6 @@ impl<'a> zp_tx::Authorization for PrecomputedAuth<'a> { type SaplingAuth = sapling_crypto::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - type OrchardZsaAuth = orchard::bundle::Authorized; - #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type IssueAuth = orchard::issuance::Signed; } @@ -288,14 +285,9 @@ impl<'a> PrecomputedTxData<'a> { all_prev_outputs: all_previous_outputs, }, }; - let tx_data: zp_tx::TransactionData = - alt_tx.into_data().map_authorization( - f_transparent, - IdentityMap, - IdentityMap, - IdentityMap, - IdentityMap, - ); + let tx_data: zp_tx::TransactionData = alt_tx + .into_data() + .map_authorization(f_transparent, IdentityMap, IdentityMap, IdentityMap); PrecomputedTxData { tx_data, From 90c884761e71b29c8796fdb7fdf7fb649396de2e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 15:56:16 +0100 Subject: [PATCH 122/157] Removed previousely added unused variables --- zebra-consensus/src/primitives/halo2.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/zebra-consensus/src/primitives/halo2.rs b/zebra-consensus/src/primitives/halo2.rs index c5d264674e4..bddce6f7c01 100644 --- a/zebra-consensus/src/primitives/halo2.rs +++ b/zebra-consensus/src/primitives/halo2.rs @@ -136,13 +136,6 @@ impl From<&zebra_chain::orchard::ShieldedData> for Item { let anchor = tree::Anchor::from_bytes(shielded_data.shared_anchor.into()).unwrap(); - let enable_spend = shielded_data - .flags - .contains(zebra_chain::orchard::Flags::ENABLE_SPENDS); - let enable_output = shielded_data - .flags - .contains(zebra_chain::orchard::Flags::ENABLE_OUTPUTS); - let flags = orchard::bundle::Flags::from_byte(shielded_data.flags.bits()) .expect("type should not have unexpected bits"); From 642776f67cb5309df5536f7c7d6d4cb913dd6205 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 16:01:38 +0100 Subject: [PATCH 123/157] Add lints.rust/unexpected_cfgs into zebra-chain Cargo.toml to avoid compiler warnings about zcash_unstable cfg --- zebra-chain/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 7b7c19c9acf..25d4e2bea4e 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -179,3 +179,6 @@ required-features = ["bench"] [[bench]] name = "redpallas" harness = false + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } From 9f80f6d1a049d824452331cc2e1613070d2a4af9 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 16:02:54 +0100 Subject: [PATCH 124/157] Pin Rust version to 1.82.0 by adding rust-toolchain.toml file, to avoid compiler warnings for new compiler versions --- rust-toolchain.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 rust-toolchain.toml diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000000..30e035b8e74 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.82.0" +components = [ "clippy", "rustfmt" ] From 526e92d0f377395f77a1806cfed9abc2bbf3522a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 13 Feb 2025 16:04:01 +0100 Subject: [PATCH 125/157] Pin Rust version to 1.82.0 by adding rust-toolchain.toml file, to avoid compiler warnings for new compiler versions (2) --- rust-toolchain.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 30e035b8e74..8b6ca9a2b78 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,4 @@ +# FIXME: This file does not exist in the original Zebra repo - consider removing it before the final merge. [toolchain] channel = "1.82.0" components = [ "clippy", "rustfmt" ] From d8dfb7d384ae3718cd26d42dc71da29bc8279132 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 08:59:47 +0100 Subject: [PATCH 126/157] Add lints.rust/unexpected_cfgs into zebra-network Cargo.toml to avoid compiler warnings about zcash_unstable cfg --- zebra-network/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zebra-network/Cargo.toml b/zebra-network/Cargo.toml index 77eb565c0d1..aca4b02bd6c 100644 --- a/zebra-network/Cargo.toml +++ b/zebra-network/Cargo.toml @@ -95,3 +95,6 @@ toml = "0.8.19" zebra-chain = { path = "../zebra-chain", features = ["proptest-impl"] } zebra-test = { path = "../zebra-test/" } + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("nu6"))'] } From 7b590548b7a1a4700a60d5245c4176c2078227df Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 09:02:30 +0100 Subject: [PATCH 127/157] Change a way of const CURRENT_NETWORK_PROTOCOL_VERSION with cfg definition to avoid a need of the doc duplication --- zebra-network/src/constants.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/zebra-network/src/constants.rs b/zebra-network/src/constants.rs index a879a4562bf..cc44c868da0 100644 --- a/zebra-network/src/constants.rs +++ b/zebra-network/src/constants.rs @@ -340,10 +340,16 @@ pub const TIMESTAMP_TRUNCATION_SECONDS: u32 = 30 * 60; /// /// This version of Zebra draws the current network protocol version from /// [ZIP-253](https://zips.z.cash/zip-0253). -#[cfg(not(zcash_unstable = "nu6" /* TODO nu7 */ ))] -pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_120); -#[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] -pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = Version(170_140); +pub const CURRENT_NETWORK_PROTOCOL_VERSION: Version = { + #[cfg(not(zcash_unstable = "nu6" /* TODO nu7 */))] + { + Version(170_120) + } + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */)] + { + Version(170_140) + } +}; /// The default RTT estimate for peer responses. /// From 0dd30f3f365ff0d8ac36000480632fe0a146b02d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 10:31:46 +0100 Subject: [PATCH 128/157] Update OrchardZSA test vectors to use new TX_V6_VERSION_GROUP_ID and consensus group id --- zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs | 8 ++++---- zebra-test/src/vectors/zsa.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs index 324f270c04d..f62f401209d 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -110,7 +110,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x77, 0x77, 0x77, 0x77, 0xd8, 0x0a, 0x19, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x40, 0xa8, 0x86, 0x5d, 0x61, 0x39, 0xb3, 0x39, 0x62, 0x94, 0xee, 0x42, 0xc5, 0xa6, 0x0b, 0x63, 0x57, 0xca, 0x65, 0x8b, 0xa6, 0x76, 0xf2, 0xd6, 0xda, 0x8e, 0x00, 0xcf, 0x60, 0xe8, @@ -860,7 +860,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x77, 0x77, 0x77, 0x77, 0xd8, 0x0a, 0x19, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x57, 0x6a, 0xc2, 0x2a, 0x5e, 0xe1, 0xc1, 0x53, 0x80, 0x98, 0x98, 0x9d, 0x4e, 0xe3, 0x6a, 0x88, 0xb9, 0x25, 0xea, 0xdd, 0xc9, 0x0b, 0x5c, 0x14, 0xbb, 0xc9, 0xf1, 0x0a, 0xa0, 0x22, 0x46, @@ -1594,7 +1594,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x77, 0x77, 0x77, 0x77, 0xd8, 0x0a, 0x19, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0xca, 0xe4, 0xbf, 0xa4, 0xba, 0xfc, 0x37, 0x22, 0xd8, 0xf9, 0x3c, 0x6c, 0xfb, 0xcc, 0xba, 0xd7, 0x94, 0x44, 0x58, 0x85, 0x10, 0xba, 0x7a, 0x9d, 0x8e, 0xa3, 0x90, 0x6e, 0x7f, 0xdc, @@ -2221,7 +2221,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0xb8, 0x40, 0xa0, 0xd0, 0x5b, 0x7e, 0x8e, 0x35, 0xfd, 0x0a, 0xf3, 0x08, 0xe3, 0x37, 0xfa, 0xd8, 0xb9, 0x08, 0x94, 0x79, 0xdd, 0x35, 0x73, 0x05, 0x8e, 0x64, 0x48, 0x82, 0xe9, 0xb0, 0x49, 0x1d, 0x06, 0x89, 0x26, 0xc4, 0x8c, 0x06, 0x52, 0xad, 0xd9, 0x32, 0x00, 0x06, 0x00, - 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x80, 0x77, 0x77, 0x77, 0x77, 0xd8, 0x0a, 0x19, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x56, 0x90, 0xe6, 0xfe, 0xfc, 0x61, 0x4c, 0xd6, 0x40, 0xc0, 0xfc, 0x9c, 0x69, 0x91, 0x0d, 0x55, 0xd2, 0x0f, 0x25, 0xad, 0xfe, 0x3e, 0x4c, 0x9c, 0x06, 0x96, 0x9a, 0xe3, 0x2a, 0x51, 0xbe, 0x9a, 0x7a, 0x06, 0x13, 0x03, 0x39, diff --git a/zebra-test/src/vectors/zsa.rs b/zebra-test/src/vectors/zsa.rs index f4caefb4afd..61e9183774b 100644 --- a/zebra-test/src/vectors/zsa.rs +++ b/zebra-test/src/vectors/zsa.rs @@ -8,8 +8,8 @@ use lazy_static::lazy_static; lazy_static! { pub static ref ZSA_WORKFLOW_BLOCKS: [Vec; 3] = [ - "0400000027e30134d620e9fe61f719938320bab63e7e72c91b5e23025676f90ed8119f02c71c7ffa660028b5f3bc0b0bedf9b76a829ce8f2ef82c2c69ab6948bc9fd00a80000000000000000000000000000000000000000000000000000000000000000f2fa494d3fa60c200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025100ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000001000000000000000000000000000006000080f8694a1277777777000000001c1d1c000000000002000adfbfe7961473dc7f8ffd411b3e2eeb005a37342e6081d5121f18f5648c8480adb28949796e09a38118152905839afc125618be1fdaf921d188488b607f2544e12a249ab310f17a9349bfe463c7de09d2b822ab0efa88b6d32f77d7c38793192b944aeec0ca94918390dbe44c50e706407692e348ed9b7cedd231941a673722ef1e7e74888672b2b2d08c97a9ac114b7039feffbeb8bbe197db4a0bca8d395cd40551c1d5d788acc2ad09eddda73a5948de2d9e2d82aa638dad6f5dc61042d6850b926d944f29f17e96eca84684252c97ce4382f2642e54208929a4b37954e8e386c677f2aee3e8f4f4aee9f76a87d868fa2210445c09b927b842485918c869a23be8213ae21937a8ca83406fab193cecfd3fcf3b1c698e8057a6c87c059dc6f4ccb30af8e608a7c04088cf3ca32ab20cd780da9443606b092c8b5d85c9a76433c0993e3eee385884ce1f3890abf95462c49bed01a3a5c09df98cb7082e9770bdee196f8b968003f5cc76d82bf575f01da3ed40e44b3b15721f4a9dd5ecd14fb71a42b24ccb7d7e6a3bc10b53ebcb7e0ec6ace91dbc19801eff0c76ec0c10602bca2cfce9f3e79536a25143d351ed2894b4eb4e549960f212f0787057ab1ac8b249c3d3ff8652cb3fb17d7656d50c5e6833b056feb26855332f60e7b8d1ebba32df63d8561fd7d209a1e5adb9853bb5b5d6a41bf1ec52d348023e945bc02e8d6ae8d5b6c7a9225991cca4aa0b41861f237b3bf545220799f152767c7fdcc693a989057e119c18a96007c69c8fe5751a4258ec3f0f99c1aea8dbbaf4df9953ccf6b42cf2f4265011ca89ec7b9ef2c6e9410886291054f50db6310b225ddf32f9db26416da6ca9ef6e3198db36ebab9802517aeaf628d41358fd141dda8fab32fcded20707abc3d00191e0b2690a1e2fa044814191323155fb21e3da8798e0bafef8c2da4c73f967504f51e716cf87117f90fd028df17f3ea26aebeda7f5b3192cd5f4855044e9a41bbfb817074ca1680a458338b191a9619dd337bd0335cb1896d79c79cce10e454b58fecb1cf10da9f53129bbf3cae2bde82007ed98505f16922b6ae53a3a709c2e01ff7e529925d6069807c06bb0c73abf8d463b2a944a97d150935cc76e1ae1f8f95159a928a5afbf76d54544a771fd4bc482ca522274b94c87b4f1c7cc3399709b5572c5133bc945cca63bad59b454ee301e3582f09c5c31f326a59705a2b534d8e9a79835bf767ea563b0aa74d3301c40a303f6fc04ba0f3807c5decb6743aabfed1a092f88975820c324e2229829462e4985e299c2415eccbdbb4ff26789b74e91db286e6a4af023e8a18e826e930d9d4ac8d92cd8a1098d0705852cda367ba067e723ace9ea8b9502e20e6519dc72b1cb477c4f3091ae4d20eb7401acac77d923eaf5de00ecbb61baa3aca9044f3e66262245aa9f3dce1d02a88e8c26b34e3c27b4e4e5f91cb633c9b6e098063d052dd6883d4c2b153c739ef78c5f375c640ff747adc1110de2f9d011118f3208bee2f3af9990d56ecddab1cfde0c053020b1116afdec7a3303fffe6f6880072482f95aa3115724814aa5fad017e3b7637f3dba509f1e371c9b87a275cfceb68aa5317dbac0e1959367d124935c76631b8aeb532d99c393374f214af2d6a3a5bf4071d97b6ad39b5b2ec03f1feb520ce467808eb2cedb3ec933c20322bcd4511b838de111f9faafb5d45ffd8edbb1fe8f0928d535ab9809b4cbf588af635419b10f7ad9f4418c766d88526215b74518cb6554e833ada2dea5e57776a09541d76ba545f8a727bbe7722912cf00da4a48a462a5b7b13c88941762462142f97e8da2b358435c9cb53d24b6443ea2e1bdaaf6ce58dbd0bcc598cf170a193e14e76ca8bde66ccc786bd330c6ce61db5f202b01c7faf185877e3614c1a1b4484cae6dbef080142f8c45e3e48485746fd3505bba099ae7b37b96e22b2cfe6a0dea5b017974126259d5055a28ad510b3b7116c27287fb7e635f1918d5a9ca2529b1741c9e86c59ddf11c3f70a56fac7c9607eb9bb36612494ed1ae819c092cfff73b7c9c5d3e8680dbe73f92b749c84363c374d80632fc488d0b7d35f25ecac1c151ad8427d7a4eacf24fa6937fd5c416776654bcfae92d999b51c49d76bd53a9d5600b40915acab5d31f0ea3f7a68adccbb72cb454164beb35819af0e9e06ecb40e96c9c2aa8018883301f65cfbaa7ea894737d49b44aa5d76c4b26bbb6de7126bf785fc2a8760ce1664150be0b6828659513561b52906e6a4782732749897a41ffce670736ce0baf5730fce9bcb50a44e1e9bba166f4812ecfdbc2ddd8483405cd2bc68ac179177e1713220348da35c7b2a30c9ad9670d99a53a3c4c4a611fcefe9e39024732d6996568f2fd8eca433a41664b070000000000000000ae2935f1dfd8a24aed7c70df7de3a668eb7a49b1319880dde2bbd9031ae5d82ffde01c599a33ae69b9dcc093a546efd4cdc2c8daa0479ccdc63123cbd0622fa54f8c15ce9a049727b659c998b2fc935ddfae5788c51772e00dd8fafb91e7b9e7b9d4a34efad77ea3f54eaf8bb5bfd4c5d5ec6761689042ec6b1639e79d2628e712669e32f33d058707141549b0a0fc31d9fe4a633871d1ca48096cd8272f735a0838bc1a440947547ce52183863bf080eba73bb36f5130d7dc8676be2e28d00714dc36ccc580d88f6d878357e7121a811a03eb12faddcb75c9c3703ccc4afdaa85101244e619f565a5635e6b8c856fda2edfc27b5c06a711730beb1c361a6a916fd713ba64385734b8563775d66adace055205c6cf9a6c90faca0629e7b93511d0e51e3405210bc3d3c590ead6671e57af44a9418a5d3c6369d5b6d294032f1592c601c2782f5e5fb7ef820f548a7e21661944982f5b04f8722ebf42456df6748a2f9ba2b816bfdfe1432f6c4911daec2b75802d43000403272e1de73bfd625b9742b8970133c0599a17cb7fd7984d6a3da82e845e179ea888019c6d86016cbef610a7a0e3409f0a2bac1181ce62a22fe3fdad2708225ec503077caf354dc5c12f6fad975509172383e2f87405fc7c387b1de333f435426fa3b8a524cea377f3c24690918a4ea2dbf4940ded498169b9b85adcd9d37175ac43897abea5d629775f4f9792d2ece6ff69dec38e38d0c1c9e40dd2967aa103a20a148290a9b89ea82e1bb5235bfd29d260862365933e19f81eb19be2c775707433d66c15f68e5bb8a578a925f20e9d1bc34132c5a214ade50ff48489b89cb674fd3a9c787d0ab539849aa19486e3d4081d4f361517f45fa35168e0432fbb69251a6a7e8f5d33b30564338f693e636d04203502588b4e9128744f49005a77e5de0f79e06053c01e82f4bc29f0bdaf3292c300030eb758fe2a7e98f41f0db618ecb99924e25084b0e69da78bb4918b365b8c613ff5e033d4994e176b5abe710fa552b3e5e21f59a33e4e0aad74c0504c2eeffcf213301b35d9b0bd3c7d140c849012b1fa7ee177e994366b9b278afd94f6bf9a65bbd1cfcf5f3525512e5b257f6a5cd61c43ff2c695cd9571d8d0e24bff92a5ace203d9a643b7c52d794b3a6a2f0cdc6c8c1527e51b32847935dd0c12b1f1aef49cc40d4318b5b067ab9d238e7dc4a8903d8ed224c15ed66b11043fb6ca6109587b6210027df615ef57125d696d0de758be6e4b1693e260589e441ebb020177a4bc7c577a7f2c7d415e00fe93cf1436bf13f738f0cb7d0448074f1436457dfdc03217b585d133dd44928779072129072c0cf0ad9ff3fdbc686f12d219313ceb77e01846f030d631c8014987081a1e3659239e009105143ff3fd3d999fb10e1a1b8f0adce31db881d5da746138462e5a1b45d47862fff760d3b1ae1de946257f2f0edd1bb911495fe1a24ec3a7cd5285e5bb25ac1d206d2f926f9dfd574758a6eb2ee5faed26e5a8e07dbeb11ba4dcfad69d93cc718fca7658b97384a243589699547d476887de967e325ba5e3b982b079eddf83998849579a849dbd3f2f487eaf9242512899756352f3680f334e0585bd43a3439bd62404297912e545e7c18e0c2e19714752b7525bebea1d83222648bc9457ff3fed4c91b1fabc6c88b5c3805dde0267f72a0abba1715fcbacce4253881625026ec2e240e8bb98c5316d28d361a91a1a572caa057492fec8d5e8d8b51f5890515186f7c97ba4a3810f40e9916567ea7a1980fd806d295c73a8b1243b538c373f531994507ae50889cddbe473a8dac128c98eeaa965cb0cdec2dce36fae175334b1dccd48839b7d28292a7c753cf23990d111e518a4260631d5a99a28f3bfd01db75d8271d08556abef553106fdc472ae97b5f4d2d3741a5104d06560d85f48d3e3acb040c3264d37f370f2acbff61ed733f655d8815983c7e78942131b41645f1ddcb24711ef39dede1317c4d7dd9b01f77066b9f3714b5f09dbb35e8341188e4384bad7238d9ef7d73e2055bb9e6706a90348ae9e5057780666f3642d7a18085e115e5ea3447fdd013a7d976d00e39edee09b271286c1a325161d3d6eac566cb86c5af3d287b5a56dcc48faec1d8342bf3c5436ccf03c0b47cb880aa7001e2c5464a406e24dfd9d021e62558e3cc9ae3228f03ddab021d5519fb426551e0a39ad08f68229662f16b79b7653b8f827a8527f1dc556a02f9e3c7d0f3872467a60340dbb0641d91d6956a33f5c905069ac39e67b40fc8d5dc617e00e89dd926bac628eb187ca1d0c41972b73b628f18159633c6d4697893bab32cb760a193b57034804a66381e62bebd6b729294bb14a113c5750a2bbdb57d40ec9e37ce7f3a486b920bf2972779b88d4ffd3136e2c10286682a4c413ed2991ce333060be5e348dde9eaded10e4cfc84ab1b157713936149239477a0b5a437574a45f24843ec4a525a71813c05c2524b92c893cb6aa0dda8df21d550371f5ac622038baef7071007a31cc486158ca1a8ec2a0c274ea26100fcfa5a3991b6f79384ae487975207d2b0b068df60c7bd63c014d13d2b5215ba7be1802b78742cee248c07cb00f3d5472dde9f85a1a9a323125a3cca08fe5c8d89f73c3fb600a4a3c7f28f12ccdac1e911c8d62242deb1ceb63eb40ffad0ae8845cc9efe69e9f5a7d2cb9910306e16b529d8e16e235e8e54eb84859d4346bfbfbefd453f9a4c8f4cc5c6c80a616433dbbcbb512651578d1d2736f513afa0fc68b401b53086d4a32d2a73100b59f8c07c06f43d17d2021fdc15410e22b5911b3572d5f7996703e97d24699da3fe7714ce74a1daa802609cc631db787abb71504d8c016cb7f5973c0d5f91899bbb100b97d4063ca590d15f176612d2e8779f89132428c6a17ce0dcab8ca081b9d891d3d0cd0bc755a193c5d5180d28d917ea7c5121c702e7c66a58b5499ba4fae3336a2040c986afd2f44d92047b338db4b6b3b6c176d88c641a6d9b4d4749654d55785002b3201ba3eb86562adf07f94b3e39bb3304a2d022a872ae74cbf27f0194c5c73037bca2d3daf1150aee2f81991aecca23660de5072568652037ce13944ec9d75f7cf424607e36233008df0a9707913985b837c631288ac62c253c9cc1586706b9e8238bb0d3d14fcfad900dff65772b36ca252d9f81450ec29d6be025262bc1104a1643c099b3bae8914c8c78cf39d09907d725a52f3ef3a9981c2dec6cccb88017805cf2163e8909eb0822c34d2b42ed08af78dbae9484e7e4faaf2a40b0762f23b491a2ccbdb5cdb4df184b2b70cd39b0fd39b8a50e4cc527f4c6169e79e9c1cca54900a1624e198a0214d8013c017a2dad0aea1521269505213c1c873cb5531b6dcaf1c5430d741514e49e7f3c0f7bea8c9e3ecddacc99e2a8e729f8a0e9c87687f11158aaa9a7159ca567598add54fdb1a58eb08da87154c59bb9214e9d63fc280ce2fe1300b12d4b805d2d992a5e5f74b04e6b41ef9e4f364aaf3f90aad6435d7662d5639882f9edf5dc7ae1e5623fb1cfd9578fbe00cf82353ecf865d9ea24b5d5050e6f7609205b2ef209c57df854ab27f2dbf047e69666ecb731f0b11e540edc105301dd9b915fb4fb1d96f4f8b99b9c42f55f99cedb22638167927766642f0c1f6c4038d4ebc8dfacf6a3ea59532d6275fa5947cc80f44650719be2802f83f62b86776c7a8ac0b92305c69583eb7b1457e21760890e8b9f42f0043af46d07f82f8aab3168ea992bb165dc7396aef85646148b9e9fa88735bcc4f2f94d70fe02200480795aed487d24810b4875284d8e51e25493075e17b7f9f319da50e339a61412cee460382cef9feefa131bb3038360535c5593039fe5fa3795bdff94b1d41e0538536a9e6de8e4a9228d65bdc5cf6868680f452599112cbb3750f9f167ed33017d61dc6b6b374d87384d3a81e74289bd5253ebd20edd58d54bd3711fed8b2273d5c39ab91cfa21b2d3a901891eff40eefd70b8d0d55c1c33a9bbbf2e0dfa2430c736a18addf449dbaa6ed37f04b5a921f945bca6bda7cc75fe47f4c8395918236dbd810406e684aec3eca46c8079dc76defdd90c746859df26c661e746260ec99f15b3bcef2d4eba263d6563f305d522b58f2a39d9f420625b2da43f7dab24c63ac0cd79078a56156ddb4a295057c02dfd02bb52511d08547ec1c0be7a7a1ffdeb550551cf0170e89d9ccf024e862eb9df3458bede7e0bc7060860bcefe43e526edc7ed295f331d5167705f7f32da9721abf972e7eb1235344776ac19bc23e6b916d3a5e54f6863dfe0f46b17800ca77c07f80f0fbe0b2a39fdd2e0107e53148182c577a60a52ce377947c1c44f9264db8fe29b5d9943ec70997fbd1759539f1c5c279f645b68a856d58571bd99d0589f444f239f194c9e73e1606f8affd027a78fec78b8ce11a3871e416307c4357e761b6836be85570d3f155e9d19db103d148cf9dd8b51faabd6157e5e80c9b78e19501489fb6fabc2c1b7de2d9f480006f0b5858eae39893f9ec8a36ed92f2d6e64a31a7c1b13dfa8540d3176e2d451b09237feca9752c8e14b48eee5dec0cc314a00cf41303c8af57c727140be157376f5182e5bd20ef43bfb73077f388b2152c79b40c7bd7360aa0da790677535a1e1ea76528a51b5ea8ceecf9babab979606945dc154ab3269d729996e6f7ed843e8207cd7893e5f8be32fecbcae63474a8f3d3e66f5ad3be91ebd42319d4d4e81377d3531f4bbb7279ba63403c9d827875d7c244a9e7a7c83818af42fee45603039becb40982e1ec43e71c919a409cebd605b865e99936dac09953b4be63ee592eb0f1bc6c8a0fb156bde6c4e05df97253dfa07ad950253f18e0bde6eb9baaad215c785a73750c6f30b36acff3e760abd513258e60d80770b4116cc7f925f34b286649676697b49fecdc8e99c6fe3311d34fcc8c4cc1f066ce680bbf9c9fc32722c858204e9f8201dab9bd6639830830e9a24830a2dfc02f767eea40019df8d41f2e0f63562cdbe55f71b136d52a61b271a24e5992a123f08babf356fd83468d20ecb634bb0ad02be4af5fa5163445cf5ae233804ea209f5c279c726db78f1c81974fb8cabc783e54ee537c9bc3c83370bba589e1389bb1e63ecf59250dcc2752fe0e1081cffb2e7f4c62d44e54a46480a809d383e81106a1b06165f419a8f3502cc7fef7c9067599af2f049fac6ee80b15122555362f7419ab7f3379cf9f27503c503eacc8e94bde23efcd0257fca4da1ac39ad5f580174c42860c91be20a8b1b95c2ccd2a51466da013a02d728d54c168eb50c064b30da49f272f08ca19099058805f91afce70776194f24a151fe36c2619df9fab6760554cbb58781514f131f1ec127a06d98e5ce4ba82fcf1165937ed258ddc9ace565827b6b8cc009b87b083119fc093a106d5f5c679e7a145b619e34f69ac0531a9d7e17ece8e335b66f14fa874dafa045603e127954d89dfcc0994581a48f54fec32d4228831dabe01d0d9f887f4604e975326e8cda35e2151a452be21a4f7117740e70bfb98cbbdaba32795fae8150ab9be24746faf5c8a9ab253cf34f2807e30a238a3ce2aa5de2691371c49b1475e62444947f632da3da60786d0f1f52a8ddb0f69bb293540830f10cf70b3d84609d16fb1c6285a4ca9ab615ea8b0aa6274317dc9c06fba50e001d00fb9db760fe6e4e751a720bb33cfa914fd5ccd5a5e5ee325805cabfbdbfdbe82a45aa53570a50fc22573e6bbf7fb641f16d01f44b9176f965b1ae610b0bf2a73fa1125b14bded8008d3d1617951e19f225d0698241746b651e003fafa16764506610fd92caf131e8c278fece483410fc3e2c6f2cc76d4a9b66028ff3aa83d4a074cce66ef035e8f2186d2ff9ed2615b0c451c8564b812f225feecf9cbbb2de6238dc4c8770a0e17feb7cb02217da98318414257c4dbf3022d8f1e5ad79fea78168c8f1771affdf4597994697e6cece2e6bfc7219d3018e3ac49549e37b8a57e0e69ef51c8944a3ed215f36c15a2883aceab247dac03ef5a82f235fea559e6b42cccd5eafc30066a3a3173bcf2f7ad34004071bd080e69c7ad3f514c62c928e63457afd2973142069ea68111c6820af10202db0396474cb2a78e1a7121ec04900d9f4ebbadf3d306273afaeaaaaf0d882dbd511146f009b748c2e093f02baac204a3b4ebd4bee5aedc3935775b9d01cab2723ce0c06ccfd5e2a8a2c8fc467c9a06ff3964e96e104890097d00a99811114179536be5457dc37864f4b5f848d27d28a6143b90bc2ae09b218e867fbd6791404ccb662fb779119b8cd2472d1f9e360ccc37f39f2019c79f365c813fd80faf189985f1704016f096acfc6bc0b674fb117ba7eab0f4138791416638ba365c546180b8d5662bfe157f3f63430198548216d7cec0ec8724ebde55883b2c384cbb67b2d7179362f9114dbbe561c8acb3d40ccde56ea66cd7c832b299a96f3a0e0aebb57e9246068d5fbdb126e6a149f7ef2214c35f30409f1b44de792cd741df0cf48f273f6dcafd69547fde219908a75b3b594f45a382ffda619f7e1378df37a8b2a25aad273329002ef931a95a0a7b670dba6dcfc08119783f60b84aba6ba878de6158e689ab051e5ed1743f6fe28a3c061198e7a49d08a68271205e4151c49264929d9ba38dcb2559f45658ce96b2c232cdf40e63bd8828794ef664543bc2f700a65d7c86f218a9b76ad0391906f4480f5563b434403e35eca1079d8c1f906a271ffa21d669a27883108ee78a4fceaa056c0bd5aa4496ec5f37b2dab8b19abc88c61ec5891759c6fb2263f534df3d7116d6874f42d8bc3a1ff9383a68ef3955295b5478c28308c79ab25ae9ca31544427a2cde901ea588ba872f37cedac395f6661ec659f1bcde925f6a82502b32fbb07d4356efda64e82c35356f9abaf5d3f0abbcbf0b0fcc2191501aeb7b59b21e00858b19492aaab25c62afc3b0cecd3d7746eb6cb1edb0cdc569602791a17911802c9f5ccca92717ac661cfd4d4dd8bcdec75492a64bdd2150c2235e7d87759e137b213cb3ab4e275a99e4ac77fda073e2870b6486ba384c44b4f59b382847a5d0a4f87198a996e639f51246014a0d9751db9f85bcbea056a7609332bb1e7ffee3baf262a346e45697d9c97c5ef099e109251368b5a807e6b69c1247e8430d2ac2261aab0ef2a0f695c22086b86fee0adb6bdc8a14af3d02ea0effac0f6f55e8203503b48deb8c8673b92c499284b935abd06352b391c253e35870f024bcbec4332f578a74d4ab0be09e73e3cbf5e1ed7e53eceeeff4ec26941dec578ce3a33f701bb540da65f810e7f4df368804cfcb6078c99d45e4f15ee1d1ad6831c3e6e01102e6ebeed1f86940de0759b256594c9f91041716bd57ea464e77cca292090f612bd7daf20e9b534bacf13ca7d940c90fa9c18b188fbcc17e282edb1156cf5c1351a9f118dcbc5cc720c5c6dad1ccfd04f1beab7817561e86442665b841c97150d10395fd842b54d025a221d81f05c820474e492341a0c6dff31f4a38ee089082f7bfb17b9d8c8355dc76bcefcf0c7692ece39649e85ddf7e395f1baf893eb960d8e1374e84a1d32fc1924ec5808c1255b34946db13ada6163b368754820d519197aceb746d33f556f9932aa775b5547d4b42ab6433e4adfea54bbd7d173e622229660e74ec486937fba081cbb26de3ce7f6f76e070cf54315f18b03675cee1c06fc765f145b7fe4fd12f897c83e21c299fb9614533e163564b9d3090cb00f253029a3a4042e2047cead0dcd42969685de183ded532773056cebbe0242e9bdbf079eb9c8b0a64df4833ad35fc40a317e99070683255e7087a0896b20e0b483410f9e4913bf36cd028555302162a6c6152803b31b8dede9717b80947efaa233f6324941e0714473c92da512fbec873e4b745505a5e691e2f1b6dc2e98d1cacf4c1a42dff6e360909bb82027b6ad070f34ea2d1bea39653da363b2dd14633f5d0f11cc1617ab8239e9832b162b2bc18d8703a39a21ac2ce9b1f23395225f6b34671d5e7679459e7f86391c80e2e3c350220f3f3cb40e575fd8afae3bbe1104246b092e405bb740e213734a5a171aeb6d82b185973a797cf3f17d77cee462e4f3032d053044aa6d8060928f6227bee4a2ad6f7cc6bf49df364cc75fdb9c9aefda07130967032ecb5a29b38bafd4e6755e2427585746460d696c9481db581ccd583311b68da1e80fc45b330e7fc6744105cf7f329effa8d05e5f04f891e6a45c0f620a1c516f22c796523a325d03aa141674b2d257074a20a7b14308310c73ccefa815f73715282cb467a763532504523a1b1fdcf2ed3af8381fa967e02294195a9d0eb43a1f5413be08d6e9ac6e95ebddb34f6962bb64dbde6e94bf734cca4cd1d70feb5b3525d1a4f8551facc79b5f00732cb252e9df686627a56b80b13fd033cf279cfc12ae321a0fa58da9df8da8e6f9f64214e40c22334f13bf1f6da122b4673deedbff3f98958b53af0f4b40158d79e63778123cc6dfd55f43f4bce42f318b0ac418dac56dd9436e78bb527c37dfc28180fed5c439f952931b29e271d83b633effe9809a6399282048357028ab1b540cc0510ee6b19a63643714857fe51c2b1b2963b7964cb602861e81eb52348453e9bc497c447e8a8eb73c79f3997ba17f35f32121ac7b0172845bd8caed56a79285e97d17aa467312c4d10b8bce1d18e416c383b128ded04fd1724a29cd8fe9377ead625ae91efff1a562e03d382e4b4621b28f717ac6fa928dac4a086aea4e122d59f28c961ace3dea0bfc79eb62a5702870bb86a8d82e6284b39f61d2c39b7d99eb65f319cce48af91a9028a48cae8c3c08134f7285c9e7161a570947fab3497f00476f9ede57415cf5889ec18501783af4c371a24560a3046a2683741e851ec1c34fe45c777ed5cb03dfb8ae6648a1224bfbc723f1a69a9edc5ef37147baa1a84b199be1dd645dcc0fba7ca9e8365309f3669b6d1d2e8a47e21d34d1405e6530e0d200dd9997ad72de1e70e660dcf53a6bc4bccd999214ef9206af79b44915e9956f8a019919290066728eb9ae5ccf073eefa4b9f771f584c03648cccfbc1823d118326d7488e2fdb2319df94a593ab0bb34c9970d038dddf2c174631f7b73eba3e6fdae9edee2ead25e57f4c498c32a567c546f089930cabc63db6421a25915714aeef8d9ccd320237cb0e4d302fe1c964c4aaa604714105a1228fe5ad6ca7f42fb2e07c7d6b0bae5f3b320f59e9821d0f66b702e0bef73c4f3d891454e90599f033a96da7df2faf22455f49e28b10ca126096573ceb1d4154791bd607ab67ddc372cdc3da2957e67ce2c599d50b90710895a934fe744c3cb75b1836eed5ac9a549c28930a6388a7c993c7d5a5aa302ee7bf08d177548ecd98c65152d6197286f52b57a3f918218fda1241e28c86201d6e3b6ca12d8e6756223bf9b19387c321db1a0ea2fdcb7a7705f7e8c81a998368a1cdb7788be5629a43704d8e91662b3e1a5ab205f85a27a139a5dd5e40cab92e6dcadb5be50ca3343905fd10ba97df8aa658634c914db6389809d9b18f59fbe371733e5ae1fb35f0f6230a2394119aca72cb11db8a0d0c82a0313562b97528fb50b99f21e3c4097366b763b0325a2f8875b32cd4beadb07925be74aa54aa89f9b52eb1394e1863899f04d7fb451fdb81fc4360a3320dc2a24b3b2c0fd463d9906b0797c3215595d59e5350da3a8cd519d51e76904a80d73a163b384fa68002516c7d7efb1f14aee9258b3aab9c5033b8d929430ef742cc88665799fb1207f2c8d333db1ac85d4c15235103d28b3769df98a763426546b21a8eb0f67872edc8c9d448b8c70d6f7af172d13c3aac5d4ae5bfc8ca9c891e501f2c473eac63cdc16a96b0f74cffb89211a411b0e6b4a0d794b5be83a7cdde651573a142789aaa6aaf76c7f6ba4851d1eedce7feb5f7a2c1179e351a6d97620395b96850238967e8264f581ba4ad4dc85933c874e30fa3adf74901f6ece0504879356a835eb019e12e5761f5555f63c91142c59cb32515de844c0284a31d5e148b694c53e3c69378a1c2880e893fce50f5ebb5b46b7ddc8753e7104f5effea9b0c36e3720469c3f20b8d97cd39c06cecf7881d20032be0f23ed939613cb0dc5ac81ece654aaf5ec36ba427cda4a0031328afc840ffda24b1829153682cbee0da142cfac74394c073def27b4b38f5cdc1c7b699d281d1fd41ac559410cba3330d16c74c8d035ef0210c8dd151a3850db594502d1d50c2959301c384da313611e361e71e937a5d1799d1a45398ce25b1111c86177152676d64393e6ed1f11821c1fb5dca4cddce3a3b1e28975d80dca762c79210222f6771d20ac64da695035d00dae321be393b17008e5f0037f4c1733e4a9f17ce275a85fb44ba59edf9e20403843b11863e4db333233314661bfaf853d6269b187bbb6c0eb0f510d4912645056813ad34cf3bfe5277c589a0314bae0aa802cff46b510c6c76938cb84e921f7b4cf4200da1a82942a807a2075c0f7dfebf768b54b2e308dc49488c4080d6c71c0bf8d773d5de3cd112c588a8ffe11d7a17534a6c7fef432c380ccf252a10d8cd1fa13a5cea6e546349923de83cceee44f2981984fef7144be4e72ea0c149458a7aa6648c9f658622c00be9d0074d3b0d498e475c8e4bfdc9ed4ce81d3aba532aabf7e18d5097ce37505c2dfe9df59a6bb30fe45d62c8a1f2b065ca8bf74f81bc3da5ea3bc5fe855ed0f0104574554480151238458b0d0dd6d493ec964a7462117237ea214ab8bb54b5a7d9e005f5606865f5c7c04adb7149725e02ae803000000000000c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945862d09879b6ff8bdded4f70af68cd3e81dc71a4c671032da6cd9224a5c6c1a660aa1393872b9170453d05c1f40ee3bcb8f727b3e196cbb9c72e7f12ea97080f67e003c99764d0dda139b3165da5dc4bf9700c6a563fcd0543f549e7b19d4cc4caf777c3aac4386f3bb692fd45d7197df5894f1c9545709c9c2255a3b6ed950385ba5a7c9c5fe91bfc671695898f78518380e34231b3e36a49b641cb3e940beec0062", - "040000007d24b5bfe1999a3b21189a3c4d4867784bc2105a0196aba2ba6fd1c9a63e22e1be3fd8ef559f3e7d94c5da9f3ffdb276804f413014d8bf07fe14907d6a37659320e538c79c0033eb2537c88a69d77f048cf4cc4fadd09c9bbb91b4d965ac8f2e0a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025200ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000002000000000000000000000000000006000080f8694a1277777777000000001c1d1c000000000002ef753da29c8538cbe9669c722c10bec5663e07d101f0a6c3f1f86440a7b00dbe374e5118632c4075f9e84b6c62791de12f1ec0e70e7d415d61c6639d786b1a0c0289051e9e5ef26a5dcbceee48051ae1ee91d70e02022fcf954f3d1190186523ec4cb0ad65db85d28e247bc1daf3fa5b111983e5d328166df852374f3efa9430f7e7d5ef94c51c82437ac68d11f78c190ff7314fdfe4fe007c0be3aeae7bc1094c0be2db5c7d2b24faddb22ac70bfa8499783f312f0bec068f8c09483f7b7edb6e63753d60feb460e2ea1f683740eded3d994f602670d174d38dd95b2a151d0b1d5f2592bd522084eba11fe9f8fb1eac057b84bde9119816ff74790db723529e8713c8daf25996fad08f2a78ceff248ccc91a83402b94311946343866a6dace2226d246cb8226f2bf7555640d4891457a7f6bb6c85962a5e482ec760b6d6483a15f6b44108c2096492765fea12c37da638a7add8d0b74b1bbeb5784c3712349881b78d229a682f024cb21c0c3961704a71ebd54be06a17f44b1fb1926844f14c3a9eceb626fcacc77ddb138846bb40f28daaf7e431d5d09d6f2be928bd09b03f6ee2302cf572c781cda2167d7d8e9b1f4667c8b3f7621c0cf85aeb45462eebe743a33bebb34a9d118cb2d4a69d2038d591e3266e77e122f9fb889ab83325e5d2ab3bea0e85e10cfdd1508d3233ede0b9de84634972e6d3cbcf9325407c43fba5c9dd30a70aece3ac6ac3d5598fd2dd29907584b85398cf21879b4e9ca3c2066e65fad046e788e56fd4a9098b5a4b0fbbe12c0f7c0b5caffbbfa69e4289c9cca89ffb3158dabeb2952a6af2bac251010a3644c01918e0198b835da28e26f694ca21d897785240d0477cadd8bd03bad34639189525c02fea6172168722cf2ae9a6b51412b4f9b24495b9b2852cf045c1acc6d97dd0d6746dd116cf8bbce3258c862e1fb18a4e91d9118c5741a38d6a7aed613910b11cb881cb6d1437669ad853512778ced215ff5b460a47cbfd30e86f9eec227fc123262d73f45d71e66f17492af0457191e797ac9fe6149f4b3cd631dce8f9844bf16588f55003371165f0e48562a11799c33c5b4e4dd390b3943fddf0162c033f0751530acaf5ac2530f320c157c498452ac5012adbde2cc19339fe82e1ee6245dcea9f587a40f3b78600de1209ef9eb6a903d267a95742c856aab1829fc8974731e49b6e8f674eefa81b23026d0bcb1d770c31a60232798a8828fecba930b51b80ae6b98645be3c5b80b195828dfab3bf8763ae660dbe4f02ed5b52abb301b18f3ebf8f1f81b8feeeed620809673472aedf9d70ac86268b7a162d0f46c0ff6bf52bf5dd289a9f34c19632198cf15730427971369cebadb6e943a6d8dfa84f83f2f6451e9d155449f6ff1b41f538eb760edccc3697ef679a586c8295afff2cd8de2ddcaabecdd1c0b41e8db2790ca35e263372e2aadc2b579fcd47d74bcfa188dabae48a78eb8e32e403a3f4bbf86b8535c568a332e0b64de3b3ba0e75a2ce01deefb1b1faa6fc59cf602d1359180616258847d458d03990f158398018e63abf87086caacdeeabf6daf6965d184bf8dac33b1c5af2223168e023a2f5021874300012761f400e35e341e3b54683442a1bbf7907060b54181d27021ea69caefe8326414462f03c44eacac9f26c8a37a8eae78c76dbe19d33f6b198e8a2f4d77a2d50bdc9785518a1e210fea6451bc05e85bd106737ad37e9c96105db1b9bb09bd7cecc45960de0bd6d803913fa43935a8c17de7bf573089ec323b1aba8f6eaf0603b91e53c540305cefe8361dfe47b787257add20569bcb7aad355d93dfe9d28443da5662fd1030a8e251fef553877edd1e1559bba63ebcec258035548d037eb34276f4b256b22631489e8f7201c86537a53502b6f9b4ae7c2a7272459a4df0d203b7399ca1bae6b5260566332b955e342132535e527fa207f8ec9b0bcf9442b7794160497121720d2fd698e3eee28fa34de2321afe580958dd133b1dd2b36afa84dbd004c4a571afa48466d3b7915c84753186b5a3e7b724a8fb8e411f8732b963fe81bbaa48b247330eec8a0897ebd64a25032e8aa4c987ff8153bb447308bb3cf5ab699504746794711928457df6e10d689d81cd6a846123375f5c46ed603f14b0ac6c9729075873179c3bae9740c273d0ec9e1ce060285211c4e60fbd2801cae6c7337570601712fb81abfc25d9a43464541e13bc42b02f01f8ec78a7e5dd3e84fa9576891397106427a6ef262e11f24a55af39caf98130c69bb042475834753518d2f67f66c04d81c574eaf7d8b83bb029f037c4999159186e170752880638619096dd852f29994be72f3a6922a97610fa11085d4288214fe131d2243929d40dd5915a6789c77a499f43489ec2a0b7ad37e7b5070000000000000000dcdeed4e7121d043c65c8049da787baf0bb29c59b75e9608dc59b97fb001c92ffde01cdc9b9d97951e4247bb513ff71eff5413fda3522232fb7d7bc48429bf301c3bbf60c1e5346e6b2412ec70d7ec4091384f5a9cd1feddbf9b02fa15e591c1f86bb9ee9b65bccc11ed903646e771b8d252e63306498d3b325c7cf46dd9e4f8e1e385bd5631b11f427848e7fa3bb78f8f97d090ff15457ddb0030fa9a8332dd2ed68ec267909771b6ee3edd3370ba34516a4a7171680d2d912e2fa4c966942b231609e3a4f5860f35991d117445464ebf6049e31d0b0eacd23a11122c2cce82c6f72a160e131c588770bc6df3888503df8add4f1285f1417543f380479052a2bf8597f56b0d5587578c3b896ed7bf0e057b9a39ca8ee3b1abc2bb967bf5fd7064150871024113211114f203ce5f150e30ff55747a6ecd17a342b77fc7c41ba70e1a216112048b26bea002606abde584d49e7cd633b7a5391290e7808978100e2d5f955cda22772bf642aa0e3b4e8f30edc8c9e6dc1d4952160377205a83730dc58516ad5d5f1b121f397aa2d43f47ff7a09b602b9c61958a3317d2316b9c8db14e40a53e88f1744655a81b850ed7c9388c5388da56e36ed67ec15e15b52cac4bf47a088df916d2c70c9bb348640cb429cbed26810d8fe2218424a6c63f1dfb5bfd3277bc64dd12ae6c088d7f55c4804f6c8bcfd6332bf4d6edbce09574a9c64d3fdb1e41c4d17a403646efc749f7ca43eaf94b014dd269c833ac3e19bc7442ab86b815a9eaa9efa44d01e69c77f73f600c5a911f6e50b5713d079c855ddcc2ba6462077f5d170cda9bf0eb8e477095aad7cd5c081864b328a9cefe21b44b53ae46d38a66f6aeded011536310c3bc0dcf64d2dd0c9015c6c2f83d36d146f9bc9f5a627dca73c5e092953815715ce9ad107d5450b84d449e0e93bf16a4e03d8b15d8b938216cd6c0bc08ccbba0658391f8d8cccfcecf77a85778b9904105bce80cd8c15e38114a80fb6e6870fbc92af588a905da1de9cd58d7c288e7cf406ef916c27b1b4b61fac457fa6390d7a7b6c14256c7a87fd510806be27244e778173f993bf86ff5cbe48b85178c8ba1d529a974a00995ccaf42b64d4e714fb5df79980d79492002f7e220dceb7a14769cff9c1dba91247cb300eb8bfcfc3a85e360266fc4b9f328ba12a6098aeebc67e4fc9aae6762defa078251a0d9653cdbec24fbe31ffa3ef322e6ba7c7114d0f642b72c7ea2688505047248fb18b8321959dec8693a1ab349c16770aaf10889e46d8d8f508f3233a69c9a820b88fce5d5ed044b9cd7420f456459d3ae87a23cc72d3d9c770f94c82224d95426e10107ceb351676c1dea9f252470ec81a9825bf0c2b4a3342ffd702cdb306a351ef3bdb56539da5022b878e08549a6ec8d8773b44c19281da0e307614f72a30e46b73f8db627c4ae9f530c0ea6ea523a6b857f96acdf37b42808ffd31fccef667f92d7ae7ee853233308d0e6a61fb0f78f1d0ee35278788dc3f7585fff3688ce16d40da875b756b2cf4aa33875e01404fe7c74614f184a5eb458acd986abc580f0cf2517110b9f1239615194055de68c7925573faef91ec11706d27b7b672b42b323c32b25a796e795baa58a7dcf5e19a46f21b27bb14e2db080ea704f7a1d15c2ff114964a65bb7429a216ff96939999a743316b073d63cf87ec39d924f6e7658f325dd6a77c9921b2b21f49a22b1d96155d1dc9a206a9d521a5b3372c397556febe9495bbad48c1d9a50f0578bf5e0fdaf8d0276c1fbcd0eda0a5b72ced1fcddd7f6dc0df854aae139d42527db885aaed6998cfe1daef4865a39fccbf57673eae767a975e43f1b198185b1e37a7d1afe476cc35602f148cfee549147584f19255d6cb3e31def73cef31e3adff8184109cffcb6aba6e268367a2f1d803604aefe48404ec5b431c13dbb14374dc9e118736b43f342a3c93f57c707f58dab5f2359f88b48eb85c37d052105bdabb93a8e1f2866330f5548252ffbfd62b448fdeb777168701bdc6136a22bcc048e3679f6098c00ca7151267a4bb1c6561685f5f6fba0d1976a6b7999257a1e4d5155020b124f65e43dc06da593c7fdd96c6fd84afe493d2ade3624fd7672fc0fa7c77d97bea5be3c865655cc77440c7d28ea2cff6eb9bcf85780f2ff0e4215c8c18f63012aa4067fc1524e81c1b9d2e08975b0305c2a1add51a9471c9181835d923cf51b854cc659616fc1932e4997b2b3b737e661945abeb0d9b1fe3c113c2b2a8b371d8630927bcc23c21faff67fc6680ea0b3468b8a0279e3e160629bfccc7f1aac37b5aba4e275cb9cb8ada5c99361c70125a45c0536a9467343dbf1a22610ee2da7ab15fb8d3c5680cc447458f81523ee75668a3f75302693169b7a20349c35b77ef8e99cd3c8b852e4d1871972415de7b9bc9859697d7eab02e559f03cd57fae9e5d3d692e617a2cfbdc34eee3c9db4efdad6f1fb19a7c4907db5173f80ec204fe16919bcca832722c58273f8fb67f69e5d8b24c285aa1a74581f0f9d1fc11b42f578a1eafe7a7dc2c6f11065697d3207585344122314bcd914733132cd0bf5a661eb329dae384c0a85f559932a49d31facb17189716a38b20e3f0c0f30ab4686e79cfe9ad03c00fb0d726991869b6c89ea25da9450c3d6cc5bba1bb17c7a3c38962361890e3f7e24ce94253f63e12dcff3e2c3d045ad05f45ad9349575c7ccd0cd82fdf1e083c56dfed867382a4cf758decef9c05bea3138ca4507b7f638edbfe8f1512911ec00d4379fa996b4d64060078b95064cc81e92aff21e4b30d0b848a8d8d5ceab8f665e686881a79bb390d75f94c593be007bcd38d10de1e750df1a9256375c15e2bed4da66082248abb6d6660ec9ef6351125c245527c3b13e22d77ab516f2457d890f9dd5a6c8d0a21a4d626a5fcfc4bc3a427b5d3581830e070fc6b4c0ac8038bfa1aa52b12b0329410b6b8d0d78407817ec0cd708eaa5215921b14e113e8ceee38318fe47f3cf5a58c1ab86a6eb7734170e55b5002ab3a48cefe62fc6c897aeae4ef82eee968be5b59bf329cca3d03ad5dd38dc287eeda31de96cfb4ee94eca046b1d9e83632f1ce043b7c65782940b60bc0f9f35cde82d5623c83c6d3540139ba820af7bdada01c22a2531b1e3171e6befc5b8289868ccceedb49fe28a32bee69055d5e167eeaeb320832e0da67d6f536b7ea5226e86420f72ee68978a460d1a5f5d0f22e7b3fb59f68489f757581bb4fa107c14829bf5b93ee95f76a84c2f08514f73aa5c062585b57b02de19dd4039afc4480d8666cef6de93ea111a934295350433ecb4d7cd9957a0cc739439bd5308449d3ab744b76f429b3997611e9edfcc49f021f65645ac5524ddbc8fe9f49d8820633ea37d9e9dd5bfef0912fdc1ba80500df637ca3701122f543e99df4f528519c6233fe9cc94e5d2591124212b6a7711cb083018647b0e7200811aa58b82b5fbb10d347fb64ddf7ecc1e526d69bf7d0bf9ac4287ac42db1e4e1d9037ed3d9624cd19c590c460c87c71e7c5055cf0b78318761a5e5b8ea36978ac18275470e04d8e3da440cc7fda0b2fb7857bc2a0bda4843a60d21c3bfaaf7e32f16de155a161e01392be4ef0ab5df2bf0b18a0aaddcc364acf987c625c20fcb90b22e3a0bd6fdd161780a58517012cbfd7086a042f1e13b3f337ed2dfb4f66635d188287bfdadc3bab7a139c3ed8d784c2773836618e440f2f5ecabb712c9116a0d8536419ce663402b427556e899d12be13a588c66565c60fa3ee42f5b21cd3a8febc2b906eb91a778baf31aceeb53acb3556007cd7752fcda896c3a4a41cee337e5e63a5bd7d3d9be234295ccc93a1cd3b4c171f3a7210306901bcaabea6776909baa057ec840813de6ca414318b10d18787403f9ae1a57d671cecb824163683d2e8f3d40cd916a9e6d63aaf5f69dac13bf6cbcf9562a915febaf7d95e8fdc956018e42276703719e4f0d7c698051290d59531e034f884fe7794175006fa69b6b09897979881187a31d33c3728eb87e0562213ae81f502108314c35d590b02b4484caf58925d3f9620e89d5e4272be9fc2bcd587d337de2b815b64ebb3dc542dda0e64ff6d6037fff10941f565cb6814ac3058945d4fdd79c3f97819906551441b1914a4b6c4346a34d7d05315eeffa813cf95b83767317386bc21f1456ccf52cc983777764c02dd9c5ebf3940c19c8d4cd2c1e6366935211884e8aee011aac2fddcb0646cfb290d3f7ac0ea8fd1ec20b57f67a28a470673c4c202eb57409ca729c4ffadcb1828daed09ec1223d758548e477e7e06f8d9015df9a40b964438b2c59261a8527d0755b468601d381e60826627dad42f680f33a83027246eaa154ae2cf04ce7cfd0eae34735da1ecd1b408f4d41a9278115695b16a248cb697366105585a863b4629f6a6899d77dca911091f73e33a812f5baa98b3460edecd6cf2bda734810a7412943426e8d8e00e24afacc681379b92978ec8e049f34b22de5488e9ab25a7bd135ddcb766dcc95ee688268ef957b83130c6869bcf0bf43d606209c5071b00e32a20cd6da4bd4cc5492f435a62561348e3769093639c533570f22b9ecda5aa7c2773753211c68672101694fa491eaec2005a9cc439f773801afe423675efc54e302fdb5e09b895316e7ac8898343bcdd91ad238211e3318ddfe0d86c5ae1c6d83d791c52d9b35496b8ed9978a1c7b5dd00bc6c9697f39247238c2042258025121816660ef0c53a49995cd9b45ba1712d45695472b69d6757e56c572c0f290ad6225d35ca5e5f564ad2c3ac7fb0aa41ac346ec3036adaab5000b9c58d8861aed031b0e627a1e665c36dfceebc558f59df5b6235ee823de9d185d171a9237a20811d9b5e4efe508fb9907d25b6849dedff9e8d71fd0b2cff2f8ea8cc1a7e98b204295f267dae98a6476d99f9eb73499fc918e2db191b9decac79eef1b046e9958c32ff1c8bca28c125b2b2340f980219d5cc979eeabf2b2dadec09e43ea4bb67b136dd30cfcda9dbb611d899e5c3656d46bca5b43affc771c9eb1697b10936d6922c17baf10888d8fc10b4a891d4bfe5ead9136c4f79215c61d4796897fb39834f0440db29202211d82d2b16e69d9398fe33e22959a4310d274c67a4dc9ae6acf72abd13a1afb5fc319c3d5ae89933158c91ffc851e5e5fc854b102a047a0d30211afda1cb548d279fc894f1002c3721e3229519b560f0a71bb648149bc763b3401b9ad57704139a85d936bd0879a820f90be6ea7d78b6fe1679d336dcc2f776a3373e473ab5ee54f5e0a8df6114fd0e2d88ed6e7035d232eae1e4d785b417a43e06bdf7bfc3509bb4ad808d39ca785673436a1009dcce6cd055f10439de64652c31dcac2b65ec47264fec73581f8598f8c318bc0f8d0eb929e7c4d6e5f012238e01e19b1fd6b54feb463912e6557b65741ff8919434e44e04e41a5caadb74f3cc0254541c06faa480499326b7146499b55a2fced4dd416d5a31779c8de5dea938385217832cbc605788ff4fa96e24fdc3875b52769db18abdc76a687974925a52081043864ee8e39574d7f27fac30650eabb1fe70d5d7bab946b234d1b8ee449f08654ac868a22839924b9e7b94175e60c5b575263089b525f40d6f76570d2740095a43696a90f486332f45f4f6ee2d1d55d4b3f2311637a9e73f921a56ea0529104573b25b2c48307adcbe3b2232cc04933dae07c34c491099c57dd7e4b393fe34db10623bb35b74ce92f8b1892d24b9fd88eb7cfc3d1791b0bc3bddebcf42592093e6ffde9f40766ad3c21a67caed25b8b250946ec46773565fdcc6305803362274e612308b8b767423afffdb27239f3b9bcb8e70bf0ee68cc8a1af4e59f6972d7c90b182d862066d1b83ec044b259b398840cc736ece77dac61d07e4b338083a97146137dce132a2a8a0255d1c5aea80b5e0095b6181dbdf1fa23317c74c0e25cb86b08c4136065729777527f49f407256d36049e4c236201174b312e80090376a2113d62058b659f63de5b8695e52fd178c573ae0e14f205cb2fd929c9f09079930738deea7a2090288911af17e157d6c9ea4bc04f6264c81e4f3b5b087fd17a7c0b7eb631c1d1476ddce8be398fb7f576f3f01f98b823b7e8eca7cb3831c0ed3c036219c94ecf5a0c2d112f788d73a432394247fc0244de10e28d4577ecc084c521f0007f3a6215a549abb3091e59c6d6cd674c8e5775acd276c980033df3c2143be0589f65da81bfab1dff81e6783f814980bed3cf47e51dda6424ff43c2a82e966c7ec5b197a73cc580919db591cc522f87a561ca46753679b8d26110d1667bbcc24706633f219617f620958cfc35c1d70e034c0555bf76d9d854f8e5a0a973b88cd6096e5f3d2a72f3196f4bd42b32d6849fd37d10df37225b0cfe05c1005ff528c59352ad6e319f77da2ddf1c94b8b7e7c7a25c7cd15121540f31ec51725e71924c3616257756be8d404b53cb3091c6c3a11940c44cc8808426305550f35f9a4c5322222e661561bdecd8ace024f4c2fffeb3bc1bfa7f69454f6699d36dc42f35d78130f04b39ef392c5969a4d8de6d5271ee7a32af3f311386857fc0c21d053bae00a066ada63a28fd84b0fae439f1060a7b633ea07813863162195125e00d9c2aa7f25c11c981794cc97718f22e3cdbd21701d6f6f5fc25885be6330ac8b8266bd64a227535648a926a002345e224cb6bb4ec6767c1f1511c2c1753def927f97f9fd620c27eae292cca484472b6fe5d68aa58d3fbc772153043073308ec7c0a37c5355c0bdd43179025aa0e8d492353849fd7accf1a0acb7507f11281ab671d69ceaabbf539eae572f0015426f5e9a57e8c4d4d92216a93027572c11172cfb505e590e4d5899aa663a5ea32d5cc163ebef26c92908e15fe3c0705d06e32504c7901bebbbe7de2bb3f5ec28dd50299d941b24242ea0e151d747e129357f4fd6c98876dd0779fe40a7cd386f198150b43d5fced11d2906915937905f104a9ab5f0d05ddf227110e72a6c80a7878e559b5d8b1fd632e851633256254a22608358228feba5055a91dcfa6f702d55b8a463f0e0dd4af11872694e1b38ce25e8f8b4ec993d38223eba5dbc585fdd5ba53b179c20a278181fe3a0d13a7feb333941b59748b2b06b2c51d6c52d0a8bdcf833628cc30787d9d16c0991bb5a523a92da788563800133ac376a6feb09a8ce1de5c1ac1ce128272cdacb42b9592611e34bb0848a05f3c69e274b33481fd2b351ce7562413c2b2eee4cde66944b64103734d44e69b9187d0c98ee204f539c59b2374eef044e731b1bb3d06465f37d16634579e24f7ba512a29204e0e3fe7d89809914e41b7ad8d17e5ac11af5246b2192c833af76bad3906f95683240ea619360d9a0ad9e7e97777e2797180447e13067cdd4efb5ee7429fc5b97e80d3f9b8396b8d2df51ac47b434ee0109b0eaa22f854d4de4ada9dcc003a4a8e147ceed375d607922b59a50312813519571e2a526774b1241513f77d2b53d3d435f141c55eddad14021ccc542ac37aea8e24b9331fcceaa35dec147c114e181e9a6800f1748c3aa1b425d532da7ed19bf10ec5304900d6f685acba0fed0d7bde86d5d5dab0fe046efe66fe78b886d24c097fa252a7a9151e7ba2cf15798d1cdc07904c8f32c1853b8e79be4d344b6d8820005ff2e11ceaa7833e1de67fa3f64637bf20963bea0a981ee810562a0b8b2dd532e01140421a975d2e7f39c3988e99e5cc8116cd9462e2f405121dea5a03616d7fcad17ba0956b84671d94c524efaa13b6b0bcc15b98b6433619bbfc9736d5432fc5237b9a018b716c2e08e4eac57d2b7c33ffd813816a0b01f7d09a5afa082e1d10a327247e0f086f3360dd6b9b736903a518390b887a6dd2f5cfa65322e5fe6dd801ce6ff44388ecfcc02ab12c562f55484cbda45465049da5aba32131491f3bfd92a1f9e85fef13e622e06445252fe64b42680ba24d09d0cf28c9f517a24ac14322d57761c1d53491940ce65df7c1ce7b6f766409f66f6ab4a9b455df1de0316ea2281d48f8f2bfa74f001509e7d2222b7931453759b1cb0ef887335e62bf97aeb1fae49095be74c11f89ae74297e22a342f60ff851f43c1e695080527747f9326097ef0a6838a1f46daab1f109c4e921beb2ea1cb6a334dedc57e55e58469aea61a185933a8a4c5fcb5366487d36541c46f12d8b830ab05c415cdafeb875eb2031e154fdde2d07437c0297ba56e4416cab08544013b2728a42ac6daac513c436f3e07dc6aeee0957297b17c242e221c41187df1fe919602d84805486c0dfe8ba108bc4c5b95c300bf121307d465a3b69f99fece83b1ddba11e3a8ebde80cedaa52c7b5acc9d0417064415bfb6d8ff6ff46444a62619c9321171883977194fddaa0fb059c29139fea48955b1ceddae3ac8051923472d23f06773f49e6624a8f2ba23b36a6c574d85b40f701d705c983ad5bce01bb2d031617bf8b2769ffc90d2ef086be32b2e84cad752afdee010c8e26ee09ea95e963b57e93188d4af84a71a5224e383a0dde184ed343fc59f77620045b9d6cffdb1a89ef0d5cb7e853810f24523a211f2a2fc19a49729d02fbc51b9674783ed4c7c0ef070c6b47413681ee65934cbc65777f92d13f01879a5851ca57501b5cd016cce8e9902f4379997d5c75b3558161552ebe9eb325a3ee76fe87bfde3d2cb44fb9009bcf14ea07900a9e120367d6a0253fba1b57f388efab647bcbad82a4ef8b5a7158c3d0ddfd134e568c937375a9df0304080a5ae883ec3661b176c272c7dd87aa40f209c9fef9d07bd102818b55f3e7a8c0e06dad914acae44f9023a04395e12b1d41b7d425634c748713a709547376cff51e864654c3b24b19d294b99c5e61abbc2f270163995512a5d042d94e1df1b49bc9f2fc814d7409f97758487ea49b276ce60ba980b9e2df67e1a186a18ea60ac743f45714b80eeb90cc06d7158f6cf09c54a858fef698ffe7032c22de1618bfd90bbe8dd7db0aba29f53abf0aca67e1471bee1c871bf3595f423213645b9dd88a4153c7dee3845194b496abcc0104997fc89eebd4fc72c5ca73cb5789cbbec9cdd9cb0cf9117718041860fb2073fb3842c45cd1a8e44a295b3166e1ab0a5a18aaf22575454d4d3750aa838944d1f5caf671d9402cf331785d83c50c29b2e49d402ce4ba32516fe1b37c463359d7cb780d3561ac8c6ecf1626d33aa1b482f343086e740be27175fbe1cc6ff2f798b9cc96e2d88baa6d80b0e443374cdc7f11cda7def2a1875595f6980d0779641c9777632f7a5aebeb48f3e9d01c187695217de185ea6c99cd47b321c53c26a83cd2f749612ca143a2a3a594c2e80c1ec90d98564f2a69e579f9713c20af6a559f541514a7514b8fd88165be486e825c3de6899e97f9e39a1654e51ed9690cefd5e225602e68480e9f2346b3f8d61268dc5f6add54484b7f4bf8fe086110f74183a0bc2515056f9a0bad6f4dbbd848d80df7a24d5d92a6b6b2b16fabc0486028a13b67a2bbe17f9812ccf6692327e78a5dfeb56feb6dda38c9ff2360062cf7128f357ab4b395b26880fdf80dd889ab809da70b1f58f5c1005a3e054f9c40691c287163f445610bdf0f14e6cb73e0eac5ab2fa5a9db4a9774c135e92200c27a34aaa2f3b9e2d568d28ae69652f1a351636492a590f79df0d4f9d589ba0651aa572a6cf9070a873ce75a200506ca74339dafbf0da6add65d5b5594b5b49bb0b63b398b44ff5f996115ce0d1b6f220b7b7b20049f5fc9f26e4fd8b7668578c4dda8365a9e79db99378091b3572473747ca3b4104e7b7bb1bc22988df73cc1e6fdb242c78804b4334550788a3e6a50a17fd8a0985f2449eb8554bc28c989cc1d9755aac8b33482d2c70525e102b4518f7aed260cbc6d6e7317a22e92b776183ccd105ac9bfbed1bbf0da4be0c0203a390cb9b488ed0aaa098ba8d5ebb9659fbf19b8cbc1b4d78edae8f5f272d2bf0303fdedd0e3de90ec360fced0ebbc85d612a9c396ba66cde481b92efc7ac9a1381dea34d170791896ea030cfce7234a0a2d2301bc79043aa7dfed6f3ea7bbe28a344a274fd9b9670b70cd74379a6fa1849a26609f1ef892c0073b7db34f09b8631af1884552a234f7f37263e04c61418b602bddc8561c0e097c5767fdeddc5deabac6308e5ae1c41565baa4d0bb33718486f3c655245f26b26a12becdc95a31819afa5729cbf3127bca5596f9d409301a32e80a3b7ec270b9387e88e9e1422b9ac903aab06f29970b50673222a3460acc1ed2a6ed45d10d3b42887d803e880f39141ce63b8d3fcaf49d87a9ec7f9720808aeaf8eab0ab37ab690f97cbc125be08fd6cd41df957059878d19b106b39e06bf30cc9d3c85f25de650f4afd295dc11025f9a72a5e46422d88c01972e22bf024fe61e0dfb824df1bf44d1f77db0118127ae48e2a145d82bcb537cc4be81e7bbe0e1d3e19b56537e7bee8931d4fc38a03d1c387079b64590d1f775566cf0a16ca2bbad3409c29ca616d8f91040a3ef52bd0b7fb2dea0b65f0841a03fcf8d25a6d7a0904a74ca61835e3e0734e4addddd167cbe9d3ccc89a0965191fd70065b0fc48f450ebd036f9c15039393ebd191a982fff506847cb3de8eed4cb8074da6076302b1e7623cbf5bb1ac4d6af09fad853100eb1aeb302717031608283897f3edb7e5b7f5768a363eb2bfe951b6a9c470d9abfad6ebabd17dadc0ec021684726a3f7daceb4acfed42084e70c8e721034f481300", - "04000000821ccb50796e05b15fde182e6e3170ad072e8c43cd976e191b214cc0b1bd9957f972fed3d6ea50bc8dc07827d9314a989ff91fdf51efc2506c098a000b9675c3e2ce3df4527cec45858a7a5313b87d0ee29b8e001768bc64da9b0416a06ec0210a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025300ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000003000000000000000000000000000006000080f8694a1277777777000000001c1d1c0000000000025ffd47baa3f5a5b90eeff3e0779f2d3563860fd5b9d7666cc06abf31b105a8140643a0cc5b44e881a3eead60361c59cc283f1fad00138eb02268408b29029232df48832e00e32157fd299f16bfd4482cc933ab2ff4cb953b162c8998e03a4d05bb13c472eb737e2e3cff834999cb5438003c74df6993c0579033e56a1fade81706ac0a77b99cb933f66906bfd2a2402c8739f844ee72d34ba50a1e1e9486a73e4c7a063267570a483bac82673d954ab903345b291266f89526184c5633a54bfaebc05f6cea64c403025806e65d8e89cbb0ca967dbefb653063a35597715c488891d19d68a5b7f0b74ca44b7552aea2308e325c71f7199ed497deb6c755c6727993f4d218e3128bbef26bd03941a19b344e8e629d81f15559abb7f6881ef7c688146640b02a0e5a9a78e8c587006eccd05bb1d5ee2ab8d1c743391970a0cfe2da89d18fbb51bf3d6b9fb9aa1818619406b89b53200b86d8b3094e46a01a67d63ff2b113b266cd38203f05bd01cce4e4f39a0072baf5f582315a98575332523e967e353cc3ef8d1df1d26dd79e5375cf9bd93f804e4d709004967bc70b3ae79bd7a9cb67cd273bf3df4e1218ec3f67dd9254b589fc73d5ce565e106eb6c6621a5c2438fe784eb5d95efff8e3b008a63bb1c329c5bba077bc756f875acc5d0eb0d02d67f2aa04738c8c625b56c82cab932b05ae2e50092322887318df508180080e1c7b80cf66894cac8de85931e7fedef575e2f7146ecc4658ae936a722548c527593bfdc59acb58ab6c4f360bc0ef75e3bd171c1c730a51749bc95bc2ab4eb7cc3792e107c31239e3711f35b3094c207d73cb0ceea7643d175cf97ae6d8d221f48fd048236449a28b497b36ed3c817c161d4ea89b7bae5170dfc9c33b3b08f0a38e964eabde9f4020eac2a7b480b9dbc7111d67b45997fb94f4244cb8bfefd0d6326a9da5203ad489ebb4e66f382a5bf82e9011e8d3a44cd8b6eaa60662d20be380bb5f474e5f8d70585cef0c5e490254ae896caa9bdc42b85c4fc0cdaace29679ade3adb96628241c509aa1adf1bdd633850f4df4b24765fc4dda5feddcaa6de3a55d58978cd71c9fdc5bfc77b33506ff8b198dbb4ba4cf3d6d4da3db5b76cfdb26379050cec5d43ecc5edb79d046e56ce8582078f6dae1f9802665db37c5285ab13076b7910c0d230f090375c46e44b0f142d540e32b8020f271de3f8ffcd2a9c8cbc1a7f5db56852ec2e9078731d724824ef0db06e8eebd7f111b7326a751086cde390eb42268a8dd44b7b9b1362a594858308abe397b2abc43a57612f98d027afbe7a5d3035c418bc32f556c8564c0901f9aa322de146697139f8801fe1f4836a800dd0eb2033d3b1c79b4f1b630b85a57a009c887eb4faaa0ae71aa5a1b9ce1dedecd5a9aeee985941c39fd28e2412193dbcd3a941c7d20e6ae310ed6082184c17dd2fca5fb27a1985843a6d92bfbea1c0ca8f7aa583e0336cb786cf38b893deef8f5d9a7ad8b096013090ce9224270c5ca0ed72961b44a2749eb99c23089258895392fc65c6181e59bdf0284a08b6bbcac67a394d3b73185f1c454ac279da8c360bd816131add0e86431a2f4bd018bf1e558bb79761851f9b6b1c198ece4e6ea28d4650ca1f5fbf1401306709d11c65829df6ff7b6a4b8bb55921ec2a3bd146728b717f31681c355cdcbd551e6f310a85ec235ba6014dd384c0118d9aec510c0ff524cc07a525b4e80cd1d2d51649cc6889b2240672cf91d9270ce131b10e839c5ba8dd5ae0bdfc943f9052aaf4e838cd0ad9074d845312f17f33a1333c5e580f48dd93b4c013ce245e807acc8e9bc89429027b3e782bd1054c1ed0b81c6f5b54184e7c0c3289dda890f9d5c21cbf13660d4a5634777d00944d6e9a91a560a7422b354fa46282871b9f29bf0dc7cba8547b19c53c16c5e9cf9986701d8d15ac5893d6f5827bb02e0eae3f589f4fcf153515406a1804d2cf8f62d765eb65e09d16c6dd3acca553ff0083ca089e62fa06898a1859d224d8f823f01ff17a2a53d2e27ba6eb1ace30b7f9a97049c581b912645ca1337d449fef95b61cee2b825716f8db4defd52709f08214e1be87c2a1fdce6c3225c10e72b0e8137dd99e2080a033af6eeb1ab4734cd25b822c7b6ab2060774df62fce9bdc9d238b679514b336dda53a630aaa419af1b4df7489bf0fa054c82bbcdded5f01eba9137164a023f495ddaaa883bc42edcc05c2361488731d9352278c9f9075197db5e29a1c87add4cadfe063c6a072f6e1fa9f8b1ddb2a5e46c7b3120627845eb9891cd09b299270c63f0147376065b406b531dbb2283bfbbd7f793de7f627685263d89308ac3896d62920ac548a7f97681b9c0b48671dbe6b6cdff66b3c80dd90b7f5aea8f2616a57f0c47f2375f070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c4e5f35dd019ce932c8d81f52f6ac4b4c7ad62d1513e1c5c445d10faaf17053387812744aea4097a7d1707dd944080558fe3569fccc6920fcc5edee87764c76b69c14f4fd2f140a5aa80078ac3bafab06214182cd9e26ab213ef6a424b4752d8b8b2b693f46bdd24a46bea270af5a4ff7fa74189ebcb1163d359d3dbfa7042509689bc397969857751feed4314241810eeccfd63998768b5a811277d852abb5a1e88196c0e6f98596ff2ecb67af89c3dd6568a4fc2e495559d85d9a043c117615fdc8135207ea0cac2c99648e6047226055013ba411abbe71fed3f3fb678bf99ac4d44d51224662036ac1be7e71d203934498d1f0489bd4e9f8463ce20e381a31cab6da793065a53353682f60fa162048ec3c278685200128c45ed315900a3111b2a3f36810bf78e75a36765a59b3e618177b61f6a90944e0e5973a573c9f048f17f1acb7a5e29889ceaa14f78ffcdbf9b83a3a8ee5233dde72047074853d78a6b7f5de7b73d0b861dfdedb8f2719ac647a67161803b611e5b80338be8f0012bbcbf1f5f05558b742a7d4271865a4e3c1fe55489ced6624aa329fedced737980ebcccee2210078dc20db162ee0da6d8f12d6293b9079bcd29416068e738f129991e084f498a98b41c4c7a8430ab26e0e06ed6115ff86611a29893b50c4190322ab26aa6a3ea878671fadb3b77b694dfb541dfd52d8e199569c800b003931def1aa79159208545edab077606d0f61947a571b6e7c0551002d739157c6f5fc1fd81a2e7172e9f480f0499f9162ff55146ea147508098c2ae0c723d8f113a9fc8db656a25264b4d4f1ff86acaa7498f351934e3fd113c2f8e45488360a40b0cd1e8be9ef9c323cad2df8c077fdb1ca88159d3339818c557e4ce14e8efa0a60f9ec0e474f05cf1478643238fe22a7ea8c74c555d37bb9555e9e733e07cbd25a3446847a3ed44d0390261cae0a92841eb6c49b20dba2869f3cdd0f33754e813f8b270d8d7c8c7a605541067e929ee330f34ee19f5de779bd0d74c4f82d97e0d794afac96f3184bf7456e8a6a1ae576889b198fe9d619425b3378e2b8cc97caae0497a3730f2adc1642f039a99b7df9d68e080e9ae10dfb93da507276b50644d8a963a0f381f5f2970725ce544f384ef4797e5cf686a0e242621501b3b5b58caeb4ce31d8dc19de210ac4744180a3698c1ccd5b68ba48edd1d242764e287d1b22262ca260c8e5d4c031a798684aaa48b739b19ea140db60fcc23cd4849deb5c3b3137331f2504ac002856a0e2a18bc613f2de3b0b615335755d9a7de9cf27d1ab273b93c87e0c03af4414f1586512fba9bba193ae17f636dbc8f2957bf28f31b2f7f53d3e4dd6f1ce49137a89a55549f23445de2650e4f1c00b22c6396c08a49e803505406be93b90080bc7e1317a4040810726d775090a6b8ff2ced7e1d150b21d3990d64cd3f943db519722fb8b4bc68656188e109fa6670235ff5f2261e4819b0a3ba1d15be9a6b39a07f579923924d4fecf753ff918356801b662ed3071753bc110adf8ace113d4bd09634b88a48095caa9ba92b2dc5bf8a59a2b7964861493ab25fc0e588f29bf7dc2b08fc95b27d8673685d313551aa6869ddf013253c6ccca39ca9bd71e3f31c77efb8b7a8a5d05afee6d24c027e0ceab5b3159632de281253ec3bbdffea8a9e761b4f1ee56047dbacbbf7d3c88240d18e4d2f625e24d2fd4922f81cd50895c276a738557723711934ea1705ef98a29d87527af74fabf3bee87f2813ded83917d8ebc2890f9dd3fe5d988aca61f771aba9df9455e22fff03e8565feafdb0619706f36b9dca969747e4061be9248ac3a23add9452f9830849e3e72c8a1b13873ed3759589e03f800f9209df6ff23edfedf91fb8eb35db90a1e31305ba079f6cfd6751c036a050c091081a7cd92f6a0b9099e3deba523218be28c11da50788de3f60ee17d78cb8d9f210365f94a9b938f37a5f4aa1c1637c596a04ac232242d6725b6b49b12208d10a47d8264c2346b598935fe0f43eb56e0361eea0a8a631562defff77b502e1cf0359bd42f1bf330664217a637476406e402ab0bcdada496cc5527f74b911a96d7b4b927a80fd918255830fcda63832500e53c4b5cdb90bc83099b65f18f4b84561aa54c7d2d969aa3464eaa220c59669baf9d7e08216d3b33c39f5573c41411f1a0a10c43eab6cb39be9baae5f828ce41e50352863a60c4575a4863482939f2d3e2db6414b0cf533468ca0f547d02030ec80c58632311a48ffe647a6ff5bf0defddee45927b9c888a8307ea592a3037261215036fd0b441aa141c7356d91031919b2f8e2f92af9134b9e42df419bd91cb582984da871da855643b4ff5bb4c5cd16a773c99688817fdd76b7faa1b0b1341de20e35209ab6a1016197fe373807f9e406214c7b9c0ae7aa8e4412c7330f88d053056363d0cb4ffe3c34b05727144ba6e418ff0c5236ff9a4bb716986c86694990d1887982d0d8c1caa1c471c793cea11b5fda1d346da4caa12e74f36a0fd8af52d743b9aabb1262ca1295342cef187f3fb13c1e565f7bb85863f86f93dddeb2613dc2aa2db4259e9c086ae837c4e8655a7e37a6e3801c6811718bf76704804fe276aaefa402ffbb5394227225f69e1adcc7556936bac642048dd86b35effc30b0723034ad8fac787a99022903d8b074cf8fdadb8ed3b8cbf75006acebf1d110534f3f533ae921c0b78ce67452adc26124ae25dd9bfaba7d4914b379360a812813d3f5743f889a442d4b6d437b1558b97e15a5db16296f36cf499417a484b4eed0ad96a626149a4d847df37d7a88f7e1773f89a26ff26e90b930fc2a8494cd6170479e0457a55b481b045dddf6e7362c99ab049d097d3251431e61242c819b4d22f70db675f50a7dea683a71b66f7f91c6ecb99c019d207a6edb7ca4f9ffeab7e29aaa723bb87f14efb2fdce5eca874cbe2e6f8a1801d1f7faad249cd9bbe72913f121b8ac6fe1446a0b182d661b0d8594f52e971955322c9c6595840aee5178518853df56c9676206ebaba2aa04f8a20960e2b5cc3be71681e85d686ee75cb2a39cb9b6eb6b0933f34a49487839995931a1c0c4f804c1f9dbc45c9996811926a0e8f9cddda2e7d6c946d70ccb58717660a1c8bbc7bdf868849de9198995148b210c81081f7515983e9e7cb807dad9da48aab614439811826d84a1f97515f915109383260e314f80fbf1f5606509db8f2103ea1788570dd8d452a8b2dd13fbf1538fa9cf2e9c9fa3d12362fa93d496d1d770c71516c794fa7a442c2fb0395afc70d900847ca74b989a9e400d3fd4c5ca81c2211c856126b72a296513fb401aeed0892efad767e23594b6c4da91e8e45779c76c6c94cd9a02d0adf3b9ded9bed2520064891d9fa14d4e26a311910148f057bfa59684b73813264a2a901d4f953040e2a277a15089841f12882b2e069f913787a37f7f9671be7747f7abce6a97e16183d03c5ca8f71f38824c0b2e197b57f5aab474201cfe23f90ca1e7a4f11e3733b1dcefd8652a7cf727c5ee648caaca370a20ef0e658334520c38d3c78870a9b3824ae09f4d0452dc5adfe57192007c4ee608e8594e7bcb5a8983004f2f0271b1a129b5c0f9a9a5435c9116c86bc33b1a2cca7b104cccd8e96a31618aa869f011056e5b876f257bf9557381e4e812ff830ed34ae2bfaab746c49e65b0811dab906967440a6850c570aa0a80f3bfe70996d14a1a9a3b356562a2bed99c40acaf107eae6809d0adfd64bbeb5045ba87073ed5714a13839906f11a0263fa078420606787ee1d0c1fd90dd8cd8f2f1c796604d54826d472df55ab8d72d20fafad1ae39c3dbf0d54c1b38d84e8ad9dccf402c27448364a7c30c169367386b9795f27e0b0b56b00facc89636a1b1391ca960f8e0fac566eadfe44aabdb359c9efa8d3d331b2b6105d5403730d9d180a6c65658565a1723d858425a078e6cd8d9a73c3e1fff7f57c2e12ba17ffa065efdefb1b78bd8f9221aaa227eb21bc4dec5d0d01011711bce5dfb699f2810f2fa15d955c9b71934b28e2bc0b1e37b075515690f870ca8324ffbb1ccce79a1fc706e78bbb465bc37034cd5d5dc6c390f1b41cbfb94256b64253f2f43657968313cb6908d8061db87209cf3da1050bb8a757dc765243e42590255037bfbec6701406049e81a5326d5f423a0f189ff94c32a333221882636fd5b98cdc9c14731eb93e9e3564b3b93ea155faf3eabafa21126a0d52c8c3b514080698bee3bba11f5ae26b5d20fc7f0ab3319bc5d6b5ff6d63a781cf1d02c570ad8d007a7c27e495437a2f6fa86f38e9343363ff315ebd95e23d57414a50dd97bb934b3ac9bc5b5cb6742c2f50d746590cdbec2cc2c025a1b6abcac53171c04ee700a6ea6096d462801d172680cdd919b21c80d7b0730642cdd53f10b420799c09b8e03e5a0ce59f1870fd90a5ea31dba28da6d43b278b39f0edd2d9fc82929e2f41d737dd9ad010c1bc06ecac08030713bbf9abd30e7f7bea89bf50f8020530dea34e2127c58e35d9268c1e7267cb00bfa9ebdbd929d5eb0f686d8927f28cd8e2d6487a99523fb8704f426d68d27fd8e843b880d5e1830d94c66537c36263e231c78baee3d32836658aa0cfa222377bed6912e61c6bf920e28421062dd1df2ca1fd3524ad599ed2ebf7ea512b7326e2b86a2724c74977cbcde823d5f1128c8061a4e6edd0e180ff55de5b77f37cf6c7b50f1be0b4d1d8b6ea176e14ef03593024fa9a801677a3ce854d53fb7dd0041f47c5c466a1ca103238ff5648bf52fccc159b34e16196d3e91ab6a92571211f3154ab9b44e25d546c0539e2c59b428d36e5c2cd272ed254500c49a6d09984e221fac248325ad848c01ade7319a3520c83cad8fade9995048fc2e377b91a0522200c1d3d38e54ce2315dba3d792c12d6759f17eef0edb7d502572f6e3f1bbddf2002e2807afe73cbcc481572ed55f11b920e0d25bfa52f10c00c175605eaeac91308d0512e298a055e05de156f0d633c3a0c73525e62d7e5c61edb032139f9aa7d55902a0fda39066fd662b782f4405041e3f54f29781b264c4194d1464335fea1e618ba2a6e5ba4b62c8a5f0d694254379ef615bbe3a66d75cc329f68aeeed52693d63a0f66f794d700f72d2edc303a6e57ae7f4c0987da01d7de8c60c263ffc64c01a92dc1f4d066e525ef07c602af211d442c45e23c1f78b9060a95f3f102b3557dd3fdf5e673b02a23f81d91639a936a656c0c877ea8ba7d235c78a91b09ee51db1e5e9919cac5febcbd39cb70c95ac9efb1c547e9a7f88399e5362dac5136b3fb3581cefb79994c01f07ce2434d891d7831fefbef2bc7983e7dbd9dcd83d8de60d0c68536e8fd5ea14f5d33b27fd3e2ba87cce7f94d9421210fc1989758efcfd4bb6ab8dac93be06477bf57c02840a3a6c7252a91bd612007b1e0568b0829ab2d41347594017d337f06db94c11c35ded31fa365b0874cbee6000b9ab06eecddaca8d0c8fc064e4ec96efdd9e2b6cc3992bc48220f8f1f6ef697063d0c46a617246641a73c6c3ab3d26bfaf8706dfd89adbee69abdd9f198419b0ea1e8510de1b92c616ee2eb2725334bbfee90c13fb8742087c0c70cde18a8576166601332aa002a347e65452e2a2237cee6705cec7a1e2425fa6044339b63bf5a047ba52a49ed6bd1e88e4d6ffce458480df30afaf3ac08037e0dbe7a6cc95c7842909db75c6d8e1731eefbe358d7773c71b1aeeb77c102780d48018f417edc1429ee3f3d18cdba62e6b0b4488684967e79520b4a1ba5a8df08f892253e1fed1915cdd201e87d75c6d1d2554a99a341e487a1654eda35019c7c38c86f5c75020f7f9619a61150d213b99b756924f5f9895e71f49d172a31028270f39dcc1ddf929992a516e4c270ac591674e6ba2c13dd06e0b506041e8942778deca31ddc84f4262ff4ad4d81e531cf16d4d041f3911441c12c77ed92459409ab65ed1949920a684e729d0904593d7a42ffbceed454a9cd23eb7e1742bbf6effde398f122a8443e86c272fdb97ef9455f33ec1161b73013800c40bda9d301d96758c6de69d103c430ee0192f74956b3d73cdf3cff36850d0192633385b19d546bc8f0b1f9e3524757f2d4245646a218b78e6a9f4e289b7882910167b2cca4ac0b90203e5ccf084ca174b16b6c0570f6d9c4e5f08815017f92a4aedd6d5cc3f40a4b9384a77405efb4b87a15caf74bc5d04197ca425592c0900484b814b3d1926954716e1df3b7017a22951344fdf52496f797562f397be1a3ef6bab299a518e7ccda7e5fdd166a6c3e94debb1930febcdc609b93dea783be0d009656909f18ed83eeac7cfdb0a5954dc8b9d604db26c6904d8ce0abbef49d005d2b718f92cb54a7adad0d106a0400ba35808525068312f938a58963d7266f1829495bce11d4c0c05073ff5a72bb508eee9fcf3bcaeba833bd03edd36a49272a1bd479d2408c272e3badb2ff2e6e036aae1ed1667b8bfd538889f705c624b93f37293759a9bc6b57833ea34b0973dfa3171bd9c81715bdcdd39a1a5a16645532b276af5eb53fa910f837f367301e75c8eaaf25dc6842212f5a43b71a6f76c92d600408f82c64dadddd2e72075a070e7e62baabb69fd006132d441c4f184c5d0f869993de13d03ae69b61956f37f191f05b24d242c23bcee76e5ae1726a296b1b15bae2365e9379db640dfeda8d9c7d12a653252a104891a78fd4aa3971af9731c00ee4e0c2f2a4e4fc6e50d67ab75024acfde2fcba159829904f9b27982f2e251f941d897bcec7ce91edf7156cb1754e27813c59d3bfae136b5fdc4ec32e7f17f5d4c4d078f68e91ead670d0cbb30054f2e90fcdf204ac0b99c8c435d932c10ba9267de7a61d791731e0d39b6927f8d8c4b395e03f239d84b717021375480b2c36e3b110777eda7b9e67fbeadb56cbd75ae21d5bbe2f95bd5a2d21ec1a5a403c619e55e46f332c9f98368823f03e4bbf12041f138dcdf2423400dd940062381e75ed02772618afbcf1bcdd949e34afa5bdd0c25b0addc12c1bff4e7faf0a1608d0a36b250d7997bb5711e1b6c74fbf391bff697982fa2b388f1c1934483517257f23bc65aa0e32b5631cb27606e552c49d8376d70c7dbd53570b8d92ea893d3c7b1bc8f62c174ac33faf08269b8d173605aa9a18d81fdbec0e392a6b0910443c504165eee0571388028e1512b8384f60cfcdaf2ea17b7e9c1be172676062a02de0409faeb6f0594e0fb6e696d6605dcf8a5be6115589e2322d7c838bb06f7908aab838bd06e720a051d07233bc7bda3bf1dd16820777d5f57d15d8ce486c9c0081681824871c37c137be3355e8587d12417caa506e3c14caf7a1e9f2d94d6c15e4fc132b2a62f4fef4d12d118ba9d39313a212980dd0f4d7a177cee3ed87f02812f6c2546004e10249c06aaa49a01657c7c7d2ef5c155310e2b69bf2e2b5ac3beea29add230e49ab31149447760e2c54745a77fc33127beb384adea5efd15e17aec6db9af767f1c1d5d7b2cb07c3b193acf0ab44c5804ae5c3e382538cbafa1ddfc31f1448eaea7b0a7504e9fc5256e4dfff39ee61145fe246856fc4fa93d22154068a45c9c12234f6e4aa3748b0a5418e4992a22eb18bb8033793715318370834424065bd4cab694acffa6f0448a61844d4328eb406b72b3c9b2b610b5eb50007bdfc74c7feade19a2459ac4b21856868aa06a2d175589dc86345b311df552ab8a56a724630d565e4ba55a1abb0946a0a8d6e2bc453d4dcebf1159c82b98816c8584ef251cacd77c3ffa104ffbaa96a90d876145fa73fc5fff5f5570a6d8d1580e1c4cce5b5f8e8a5d2b1d20b41b4009c79ebfd4a8e1636f6f93f12593f0532d565ccdf90ed011e0ab0fcb3db28f10535ef5e93f59851db610641feb3bba4190f3074e4257bdfed4f05a52c98c380a471bb3b952488283be1f14fcad4a3d219765b4b2b3421d5ef845f6c7b9ad6af6b66a75ef0c03ab4f2c5150c078068943d1e89d298524d9e9cc5b20c3bd03d89d7a6d3cf30b02e17516e0001b071b92a35d245e0c596071fb8dc53e53159eead8cf86441e0348a0a951d4a2ce30274b423bf3cef4e5969077107e166199d2c5714e25e2e0bbd8db356fcdcfb3d3b8b04066c193c83903ab0f0eb18d2faa428f3104af484d07a96e43ec593a5a9bc6d9c2176535fd5727a3acb3ab4b2e9e9a570f06455bf2b68cbe461743af5466bf7f8050f5c7710b8cd086922c098d4c9c26e53708c5523c0739705505aac79ef65781f226761215eec4cb44f8317b2fffdb15dec242532c0cc8db35c117a35278c54034cdb69bb5df20b8cc8f1eff23bb6e8b929a130e44e0b0812e937fc89b3de0a13afe080628083e386b703ff58a07fb599b66605d12342bcd8fbe69ef239f3ec30bb2fba014ab66bd3344d60786edcd434fd3a19f46353cc0c7901e051405544028bb9dbb1ba427c4b6e6b5a3ec8a593f0832d6a61692d72bc6faf044ee5664b1a7b5a3d38fd1a1b436b833287a162ae7851085a1f63bae8f2fe18b09c603ff33bf0b5ddd6cee3a4b4275348c9835ef59b44f2db1f828f77d0b7d8df70487c91205dd731d9d516d9cb6fd88080f45312c10edc4cb8729c7e71fc9fa87808bf3a3099918984a60eccb1ce433aef537927236f3e0f59fc922b0ff7d0b39fa53f7c19b5048f8fd2e9a3cbdb8e6d7d156b697bd7242355bce57cb3d94d16a5f9adc607288f3ec2641d42eb3303e0344ffe4e4cad5d58be766687da989e8448a5cc7c1ca4ddb0e6cb4f4d22104b1d32f6dc3632fa7012ed5e9d5a2111dcfb62c7666e1bedb86bd966f9caadc2ba81da0488c78352f7d3ad94f35fb75a12272754630a20e42a38a52c4934c5d3bea8631f590e31ac72b485478b7d8ba786e2bbdcff8d22a0082034283aad9f28adf92604124062230891d81f71872c135d234bcb76e82dcfaa6969b84c9171805683b4a419f41a830bd88a76618ae387e3a69254ee920a1375d8362b4e038a2e2b4a98b1c181ae9e5f24b19b07c5d46bd50d0e1e37502646eceabe404904f3813c243675a8322f853d45614c7d56fb8667badf80b87b10ca9d2363e37281fbebfaa303a7366de81d92fdb81edae1f057fd933523dd0a0b88f33140db7acf9131d23420c2b976156d2bfd785e9c8c7c7a520abf8b58d204ef04b5f5f9424c5f305ec6d97f582627a9f7b1d124dbbe6bbd4a36340292b70be4278a0bf1833f90bec6598d3a85fd10c37d2c7fccb02e440deaf2f191492c242d84f09ec1e0a034843a5fffa7c63cca1be0c6c378ce3ca56bde144d25b52412b27185ea5d4a3f4764ee54f0bc70c489f6d81e8a9c7208638f9a3a0bac5ff8b857a74cf8363d05ee1d8f3a166cd50701e0fe692879ce79a3d691424066b749abc3e738d5647bb844731b409cde36b48e420348197710106d7cc0d216cdc677b81c4300b93de75630c4b3e117cf10b678e538db372b2304f314a19d41b5534d9213d408155635a716fe42fa7a03ad90cf8866c124e99a66405883e8bb6f9a502937e18db7c266d8cdd119d12c7121c580f83c2be68d9a65744d77e15c337fe898e1b2fadd3b48b4e03d08d4cbb2bd50f567c1913084eeb5dd249c81b71a1d3a20e2c0d6a8fb7f2099c60904310e9416d9b34407ab6d32fe2bba4cfcf688c5c92b34fa937b7c5345fc8724085c893a5ee567bf6e3b2c1adae130a72f2a3a16d8920cd7e6b93ddd1352a13b1505cc0cf4b00a3ae34a00cb2f85591672068027403537fd0721374d5936ac968952ce66bdf64318c927bb6c184a880fa15e384a3112b78c3969161d05b00c431ff94c55f794c150ff7bcb35265782fbc6ef4903632144809ddbbe3d801f67d840f06a15f966775826cc19fd1f431d9b2dc8b552ba3b28eb47a6b96a038432ce40c84eec8854e48d1172af6aa5719778915b64cbf2bdfd1df50cc32b2736181d4664ed8bfae97f49c20e30bf9c4ea8e67b53fe74afb41c63b12c30eae8c890a5ca1bebc6ea3d553f500b755430896246cf8f4577b3975759e150ec920229f0909348a612900466b5d66e5e2d331d6d9aafabb50bdab70c93cb2d3f6647ff3e399e06946844e96897d74d22795ed647aef1526ccf5dace92d9f5578c19b0d4747d50ab9442ccbd04807a28a35e0df84cd1d4e9c8dc025717871bf8a9f9495ea8d6f6d1687cb1b3c2a6ccb25924ea8c6ad9dc62bd510325df9f6c52c391218b8fb35468e6a855878f17f6d83f866cffa34a2d1f3c21e17cf28514bc1b80740721f43424681e4b421367c296b90a75a116d59c3bc06aa93cf2d809158a67ce2ae3ce452706f919af9669e0f7ed795a3c0316b4ad876d292063107e29e7374826e95233a7e66a89cc7fb4a6d96487f2f2fb1d68df0c0092201b68d49a7d03461d3fd5927b89fe693bbdd3cd201155aef2f533edd651b1802f530b807760dfe1b4385c3ed4000f6a8118b0a3df4c412e79944e444fe063d340f4871ba816c772ce322db4e55348b6e5046b1e6cdb665ef7731e4dc58c93a21102ead248952e94d44bd8357a49f2641bb636285ea307eebf48939441ee1e31a03adf3198df993b59a995d271e9b851fdeac457d6355f9c207292515c0ac2b3801c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce9458607000000000000009ff3604b2c9238c3575aaba36bf28511d83a0aaf443d53981899c20be308112327ed070500b374e359a90435a60363235ca445da700abc2c3b962e89ddae24040006000080f8694a1277777777000000001c1d1c00000000000234ba607b674dd1faf18173ab52cb86ada65b24659b7ab0db262a4d46ef6307813610d535a38b024b19e566c3d73cb49c5dc6a73457c658fa61aa19c9a669d70823c009c26d2c4c5949f83ffb187b8d03a7e05970d87668b9ebb172e5b44c4f300bffbdba179aceb954a3d6da0cc8e9f59587e9a4ab1e9578466bc9eb508b791bc0497d33ffab8b845eed45ec6d6d9072da6064b0afe5eca2b8e3caa4801e04990e2ce95ee1594a1f922a2ad1e0550fa5268c2e1486785a68ad25200e0d1a1fff176fbd7f928197be17c9ea0d4b2f1987cb4c5d4e62ddd8001803e1672d2509ce5607d0ada2ebfd792a4eada56d50babab5b04f4999d97a78f2fc35e1ff001aef6c11bca252ab1f6959508604fd29f29642562b862c9d326655c735e7e9ff0e5b539d819b0ff9b7594947225abffd69d94748a59b5e4798eb4f0d9f41848da1acc1c42ba1af1a4e69227887f00de8aad96af6043998f72164b95e9157ef40f3253d38dd577c636fb694a49fbbeb14a153d3615454c5ed2913c49454efa45880b7e81c288c34793ab18eb68dddb3b5eb8c6f9ef4889d0fb8d3a2dd58164e5edb536fc705b63b194f2dcf384c026004d3aff29e11cdd17ac5c71c26d30ef20b5c157fa9c1c4b33d9bb95cc5882bd36d990fb12700baf432d820f66283742ef447d962088dddc54a21b162d0ed191f12d4b335b4227aef5583bd2a7639a275dd3c6397d11baf62a2983eb982d0d4e5bc64f8bdfb72a5b7f99c81c4af1395d153c9535ae61358ea5fd933e1ca35dfb4344a3a096236e9c777626575f9773f1ed0e64c7e67616b36b48d9f481453f8815d4e48601961cce17d7e5cb37be71839a205a208fd7d35652247b32d384453f30376c2b0dde5d64285c86ea396bf919978de33d5959c7a2bf9fb5e15da56ba2b11b805789d994dd44b5b39952d90bb9cbe0209c63123cec7ff2f2da1c1ebc0930b0e3a03b90dd6e58bf83187e7b71a9a5264fbbfeb90c57647c5d6de4752ccdf657a95007a21a6d8e4910ae99c90e98bef3ba13ae57614499747369bae218a8fcbdf074b48a5f374f74e769d02af067b82283116764abbd30fdc9923a3995d144bf1033ab26d3197ab184748b4992bfb51b0ea22cf3bb574236f2209a2e1391f153b706d5b7640e8a23778332fbdcb1e35cdee0bdfa55c35b02b793b6f2fb01893363d01388391479aee427cc977bef4cdd250e78a7f0f39e711aeb13be5f9a895792dae2657ac2789d2f0a5b0b7a9093fdafe072883f6842e377b05a046488db93fc23002a40a7315e284aa164b2e144cd5ffc6afc8584eb5d52b21b48a924e257b72a180792eb6f8f0a5220c0db0fdf5f5d0a0aecdde7f194e88369ee5d2efda82edf85e8d20b69680c677a4ed53eb33475b9beca2c560386cceb4ddfbd30292b111c37530ae6ee207b87fe5b67b5a90943e2a3c43c66eb8f9b1b006fe008f9da8791e71915349b9a9652d9c508adab7668438eafbfb46288de70ea1f96a32d36ea48e0dfc3fbafa1ea69d28f2b3b1e291a02823229ab70510e1fc102e5df0f6160c7af5ce67e8a6dbdf5e486d285f2b4ebcfcf2c10426ec94e0886edbcc0727b0703ee6ba3a1f7d4a5ceab9386123e531cab919407eba95c72314e0237e4208e22981b912ed9c2b4cac88a8592fb62d648846bf411b886a6b89b83ad03210cf072b00019dc6d0e541b6bb9a22ac9b3603ac0ede0b27cf0998333446344fa2cb44350f9dbc5d557cbdb74d335c6bb398ecd2eef9686763c1f21a34970e810a8eff7b37947fd455ada6010eb00ed5f1f92395ff7d1fa77b05beac74c53db704530f54a5947187366dedae6d48386d68c303b5eeac6e4848607890ad4c4ec6fe25251b4727e8cd22d8fc8972840fc8d5887ce647ad628b298e15f9cdd49b917887e0f8e8ebe0312fd04f3871c68f402f8dcfee60e81283a66f1725ce579861c999ede9f9e2d976a83253ea608b66ccd6ac83359bae0d060adb0f5573ca385446cf54f14fa3231830ba0243fd574aa8ab787ef0150be0cb9c38970043d6fe200fbb6d03158f33f5e3a811887ca482b83122242d228451449593c8dfb33190298e873d49c01b8d0b9ce8851e60e65308325bf3a934054fcc53e791fb117dec249e9836d466ec94188df94077762d8c12e8cfcbac6a9af9741395ee566c26f9e5ef21d7e08a0453fd22ed3228f9118bf2606e87e0e0d1e495075f348b16701162640d2b805fd4d2d3890cd6bfd5afb790ee9163e30d55f8015ee86b07d063dd0398366e4cea8379c951160896d3374b1c39093954117d7e3840715e3018b917c6ddf9c47869bb01a71793b2d414c252cf62e9d781e29137f59978d39b8ff60d45540bdd2dfc73dd0bacb811267b486783e9e9a0d0d5a2a161e082adaa070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c02f3f899fc0cfbb1beb2f0a6b1364b43fbfd5e372a1b64b90685c1b0750cf93993917608f18aca5ec561fec653860b83841a345f03b0e9ad5360c2616b8b511f973cb8eaa583b1e65825fb0cde26316a897f759b9c79d96d4bcaec217948791d524ca3ba26457a5b6f5278171729abc58fcfc844a5e2e9ff048bb334bd46692d97beb0e892e144acb380a1a2810048d5b4226ce2b4f9bd020ae4b26ef3d03419236d3862dde808d4fbc7187da8d7a63c5154c369f26a905f355469a0db4e562de2ead4d75b8693256748db27c5d041f6bd93bc97c7cf7a6f2c2966c29817bc398cf4a61ff5c81b66a7c725dc820e24ccbb2402b16e8a5a9e0d676193924ecb3a48bed2157a84205b689c5f673b45f5cf8589d2e048366b6e3ef58a6cfab7781e90d5f0f2922fa407d0882daf4644908abfbc5da2bc90c09be46ecd7667947d00094c2024142dc31a072b758c2b4c5306e458256fda993ea15295f970f480cd333f986e7f633ba84f8981266e9db3b78a3fa87052a648fa99c4dcb5d1420da4bac5c6ffe822276ffdd6de43f39987e9ffb1562c8e136ec163623c1ef0b957bfb67cd4af92e6433d2b3c757be0b74d7053fee3d1833bea1b076b4e2e878b68be8b661b0c54f6cf9e3bec410ee0a65c0371b4cee0f3cf196d88ac4ef5ca02a42e352785e77307367dbdeb20cc0aaf0be2f72ddb4b12cb9d1e7ed530eeef35a44daf8d80446626e90ff4d6705317ddea944a45e094901680b89133957343b5209a0146722d0d494c9fa805231b072740b15fdb7a1e0dba39015437cb2e61f0cca0179c0128c874cdcb3e4c377925a097d46a2ea86ebcb2aaac4e69b8d93f3f813fa110857017ec1126b0f48e1b61ef1ee9f2d3288a1ba037b28294d381855a9db1a44f6aa83f17773222761fad2add32acb500f060e76600b50779934496796f4c86114c123c55b42ce44d600055e9e249fe7d5f1a80f54d49e5b0dfd71518a7669538471b5e759dfb425c51d742df88cd4237000e0989d5e554f698d0112bd61a33a307b36b22a76aa8e2938e884191321c09c1d90a5678e903a5b76446698e5031233ad87218bf81d1f49cac719c2b27afcc4a191daca45a1c9f51425cf48008a1a569e2adae4627c233bbd024ef0f7c3973ba5bbf9fa0704e111223cce823d50b5d91fc0d805e0bc51daf91f0375b6feb67ed3a729933f275fdde5f8c1885cb9275fbfe2796b9cb4dc5d3eedd1044ffe62bb5a4f20c0969ecce5a0233c5a7740f9f18ba0a6c9a38ffe4b0e5377e6e84e659ece4b09a516f1f5e158f633a18b527ae8cb2813b6fc27f5108a7230bb2ccd25f9934b0899ce9c8cb3d5afa146791b52509aa6f78f02904882b0730d1a8630eb2c3e408aed611ab9cdede995bd2ab2940dcb74cbad21b1a8c27bcdd2b3758c61e5c0d271dda23139fdfa17fe97f19358fd6e4e6efcf71996b359eaea79979375a010436dc45f4ab138d7426f806450b624c14febce156041a32539494b096a3210d114d203df26b1cc826fa2946f53b2521ddeffc30550bb2d26dbd6900c912852b1741e76aa7f77b6c4aaafd16760429d5ce5d3cecaa3e1ff1d3399dd2e4bb0123d668b63b61bed7b097daf5a4710e82dcae3e2db6fd652bcfa527938559d83ae86982f26cffd2be75bb6f842883ac73819dc831dac60616f3c85011bc5139d67254cee29b964ab71fce45fba367356f2122a61544345df6d07f423d13bb32c328125323ff62ec30d67cfafde6eb20c8bf832b8a51e3de2726ba66fb6a0224da5f79286ab7861dac4d7fcc85c62f85fe476216c55ee4e5ebb7ecd3f642c547ec45844ec95586eac20c1834a5abb0ab3901c50deeee97ebd64d9980c53e0b8ff88e2273331b1484adc54fd459eaed17ade204477a17b54cfac56fd8d05f3ff4edc2e473295817cc00ab5c34806f1e370a9f97dc474e0d4e6955f915cd6d2069df587eb0650c72b4d2454142230623070f6d21be2bdd0173bb0a959990d9d250e47a2148b42030900e9e7014806e22ae690eafac7a2b3fbf45d6b51dfecbbd21993a12e057c82425533990c8b5c238a6d329c4c41387bd693ec77f1d6d200f17a86063111051f7090c2bfa3ed2a58ea8d22015a2cff83e127edc0383eac49c3b6caf9b5e0ab4abe911658ab63925d60842f70fe83f9ce4258bb79b6311bff08b231078eb8eff59e9dbc955af596ea7acd15fa8b8e1ba88e110ac383eeecca4340797afebeca8fa7c5839a3a306d4bb8004cdcd0372d83cf4e2214394cc2a09252971cd530af7802ac06d57fa0784500c40581efce6bcc497fae84e8bbdfaac727bac1cc0d49c0fadd64639c6c839f6b3e4735074e5f2cd2b5fe6fc9cc34152d723f1e1ef3fede91d41cf39a8207ad69044d14925961ca8b535362da356e419de13adc49ddf8708b82e6ba3b5609ae6110f28333601eed005b94b0d31699c8a687ae732b7d7bb263081cdabb462241911bba94585d0e20c9b41f4d8d5565e70bf351ea95382544864f4a960b8850fd5095213c2bb602338ab2a3f9b1fd97e8d42f68f2f943441ded01beb76f463997f1709e92c9e6df0341cc64ce46bee5ae1ccf0037b77ea00edf62f5f545d16bd063bd9097ef8eaa34d9dd1cb7b2d7f080fe56d14e4eb521da00c7c1d19c13e934601f963f80fe122c184cbc0047fd38cc0a7b4389debb41f44c7cccb596c41936e2fc672796877e1f0d013df6aa65a8d39c60e49eaaaf4bbcab70fa97a0b864aad214ba57bf5ba65abe585e52fec23b33a8fec951699fa4ef19e4af9e7c237248e1f4a71e6166133b2f1b6949d70f072170002b3d38dfaccb3843e641e85bedcde02e289d94ab76f935ced360b5b4abcd503d274923c222d757f8436e97156e067037c7c984ebb22b836bde9b5aefd12b6f079dbab91f69bd904facc456154ca3a1730b6fc7095af42e8e20d0b94ee3c797049971d28d583d5d1d7b539e8794a7710c2de9d2a9db9e6842f7a6a410b9df0f16fdf6bb58c35ca3a7d44b965f04e5e0391f7ab9789ca3f88973b59f50cf46f0d472e4cf49cd81c1b05d8640d625d601155db952b3544d54e5742be75a4bc9cf0d1084bc141b76cbb06290971fa526001e135397dfaadbb5865bb00fc424700901c4e50c7aa4db925b9b7fb0d8631b311fb820bceed1f83a6c166f78819a059017c7e7bc0b134aafbcb063ed15ff67f165441f7015d9a3514ad604c82e400703302c8e2e2bfbf738ef380e6f690392712d64c59fca62f638f2dd8edbb842a7ceafc4926febecfe42d5327af88fa21a9320d1f590803f35b2ecae7e605f0aaf99504537de024e600435f4963aae484cc3f6620243c307ad03f87bbb60696bf1b66409b143dd80362b48e74627ba790e700b4a6d10a4961fd6e4d954af5e585e44a02dc9137a9f2c5b2f09c5edd52924a0f62e0db46f2eb9c15ce3e9940f16a4c7c4be030c02182b2aef10f01de089f380e8afe59f6ace4c9f34738d041cfa61e19a64156a675832d16f4ee54526e0b7c39a8f48dbba330e8ef36b5564d263060c90009a367bfc4a9d1fa7e7903d0de3b2a68de720b8bf070f456306084485cb3858e98004be70aea72b6d0200def4f340ec415fdd2bcaf28eb60a1c2854fe016de38232c721b6d3f3325a101b77ded810b660a83f31c46a5f13a5a08aa6df7da23d0eba9fcbb45ff299761741ca950e12f2f1881946ed0c16f62139d03b430d1dedc3e7f7c68f2bd50993adeeeaad42315b36e0e592b42f1caa568156ea7aaba4072425cc227be504ae30f50335793483ae94a208efe33d61a1bd8cf95db05914e3b732a6c2ea57180dd5421a85a94ca2a97c80a41c04484c5552bd6489ca235c28d773a4d5122d93fbbcfcf8707b88f3d2604da1a47cee05bb3a9fce7528905b5a279a51b44a72a7bfcc9d1769db1813e161dee4387ebefb87805c1bc133b7cf56d549d165356bd3c24b4fd4cbb7a920cca8bd5e43b14557d48c1131a5ec93b3dd64a8d0791d9e50f4f501a5c858f2110418e110a74f7469c1b2ecb54c929d4c08927ff36c4106d696b6758823b235b2a0704d52ad4da79b09c140c266153e7e54ffe69776b2fb97ae8d605c37142c40bd45690f4207e4d3905cc0e69f548c9ec024a2ddddff639d148577de8be4a322d756efa88eaa2e92f2edf13a664924d341a8f95760db3d00329c8f882c24ced3ae07c89e35d51b7e11b0d1e53270bb0523ddde6e95ef8a0c05d2d2b6ba7c6ec169202e6102335e193e302b8c460ed998878abfb1db24e1797d1e7605e13598923a088f38ee8d824d556ebca3d36311acdc402555cc962cdd10936bb4e1ece2e39a6078516e98169fc31fabca7a0edacc689d6a5b4fe2475c0c73ce3d8510bb903260e1e381fc5fa6ea920c8bd2a8ec145eb778f9891d840ba5a3f08b0f6dd3f07e753899c30fe2b565e821fefe44cadf2117d358a2447b0d8ce48f742325b7d358a96536be71ba650ebc36783be0ecd540fb04bdd6a4cc39073df2b9a5ed9b23a4e2cd9ffdbc2967e690188dfc052f21bc49e9c81be87d12b4ea1a770e108d50de901bbb0d046c50a4228254aa095f0cef9d608b0ef50208b0eed938cc7d136207105030c72580f3d5c707b62090a29415e32af9066217272ea6cd498b5c1a81d06314c21406328037ddfa23222cc84c3afbf8cd1c3762faf04352bc37910971404fd446bc4beaa71b98135724118a1dc65ffb937d5310fe1f40c307095f0d3314199773a33bd6e2c89405f48bf12d6651d789e66f1820cdabb6107bdb309b937d8e0f513fef644f96b702e509903ce203c95a10ec4c9f4a71e75c9495038b423de361a86cea19cc2cb4f1f1874e672b2b2e97ee9462090f0639864e95331262a4a560c9948f3c74db29b1d979b7648a7a18536d7f6d8d2fd422f7070756835185866ac588a4daa8094185982d0879768320c5a05a95f1a761a9042efb4e291395bcfe4924fd4df12b131c3520fa984499532946adcfe20cd2fa56d8d44296926284e91509bf8ae72338c28b93974700af04d3ca38f55824ad9f52bd0e6b05f2c7bd8d324b4bfd657855c8cd458baea1bac09386c4444cff7594a870650c1e524230b2a26d865605eee5a016efeedc957effda3d1c145ad66982ad9188bb80c2d1546650750c7e79416c80d7ac102b47bc7798048489afde2f8461a9162997824253047f3d0b0148160aca7c533bdb6710281b42e64ab5eb5194a78d4244e601b67451ddf954d429fa006f25e09ef2a78388c6dca6228f17e3fe61510038f162626435783cba9d6809fb7b50fc1bcfb6231466454b5925c32d04c02e5bac1903df02e8b2ef25e64fb78d7daba63afe4bce774148ae824c62d778d88b6d6c7723cd5d56278b36058f492e4dcd6cb898414f521d9a21cde732aceb5a62adb996f1e18d950a982f9fee6c02750b13965ee93d80751116df1a5884ee24d05f0a74a3faee0198fa1f42bc5241dcdc623ab172dacf6108535f92e0279b9ceb96395073a5b009395aaf3ce8df09add65b351f341d2600351d24d3474f7d123fa7e51f017b0a0b90c4cdcc5db57927d8e87319914fb60ca897c7642e0e323376070cd6f05fec5e74c88c3175010761c7f1ac3c00e263611050c29a932af6cc7908eea6d1e2cefe518c6092cbf7fe7a6c5b0b821aadf6f4c504a1de79e723b5c17bd68d634d7b18b4b9955b37d765c464dcaaab31b9613567d37640e3b7ba9c2abc9b8ad3fbe2ee8b62b4ec7223792f76658bccff7069454442873c81104f5859de761160347deb9e1390544369afd02640ad5f6868e92c2d576a13808199a53fcff7863344ece1634086ca08e72b8d8dad0c11744ca5889437dc482375b6371f12853a22b37ee12ac0bf851194eca88f4e711d6c010135c46cac6c4b6d4d22ded888f4306369c5e7b716720ddcfd1550760b2674eae607713c5696f43d84af2d853505636f0aa30d128cd5ea230bff5a9322b0f38fc998eb902fa2e66a5cdf573b67faf264bd8aee6a7baaa4607ca070939347511a3e7fcc1c2aed75942bf4b02a7a3680f21e60ba2c3fb198e823ef8742241a5193df74d2fd25e4d28080588ed992440022cac1c026a3bf2c1de232751ee2c56381cc320b8511846093b8c82c3b69bee0a5703ebce82d93c99555970e5f192bf4c1438ef3d583f40e8b4042138963b862055a0a8b1df6cad65b82d57850dc251e50508dcf9d58c60b4d6d5f706b10bbb25717263300d3b432ccb759ddbd52e5dc847469dbe7db86ed6d35997f93f8cc939ea38e0eefecedb429e6ed8b028a6ba59954ad0b1345816bb14ef04d6d922770d40b19adfd065256ac351479ec65435951bb014a5fdee04be55231894b9390a28c7823bcb54409faa06f1c3da22ec89f0f9421fa9a33bc840a1362863b549360829e94a149010328b366b45d94e44b03182eb30c63fc967159c1df1386350c53d8f249a1d5cf7529434d61cf0085c59fd02171e5af8f1c82f63d8fbabf8f07622899eb8d01eca1fc6e242d202799005db7e6d26f734d6963a81ab2cf54936440914330b0a7a64f4c785c0958d72e82720124629c630ebe6c2fa7efa9e2272c234db67c5049db7b62f7e1eb3bbbdbfb842fa3df06ac020f84fac21207504412516cf601b65700c971606725d4fc31c4ef15a6635efde36696e339f2cfd775184233eba170149c0d215428706551ada80a5e9509949d22eeb0ff390d1d172b7033c153fadbd3f158b87cb300dea6364874ae86b93e5863f46d3fa2a0c507b4c382a46e0f953854689ce9b7f2a30945ac9ab4848297b833b4fedd6f839ef106a7028f1469d0950628256fec62aa432d6c0a85c3c4f5a6b792c12992a84ce000e6c1aeb6bd6c354960d9a741e0ef483a723762006e291f5950075e35b4223c471cd23733b1dddf91eeca80a4535db48fea257297e0b02eeeeb3da56c2b7acc338240f0e1eff611efae168d566dcb55b9a9d569539031fc4100eb6ca194a369c1330395dfc82e506d8669ae0b80d185a1f037fea20a2cc16da225b6e3ebe2dea684a032dd222dc5df9679f927887e0323e2be5c6b5db8b45640bc9fa099432d28c833a00b04697cd0817b118b78aa4a1ed51dcfe3fc69560b06c859284c8581b6ba223af7d55a3c623400aa0a30fbf3756e3d167100f5739ec9f7fcab49e5164b08b3628f9de44f0e7fd887a88b54305cd1c57a7b9b4ae5547dc617b4aa616b02fd638f4d030b7d9394929abe4264653c79bab88d1210197fe186b41c32c4ffe2827174edabc9cb926173a4afcfdc16e9386d2c2867d9d07d014161ba69169d51d61056d0e3d4c6f7e2fd93d244df132e72f560569889d635cd192f7c6c75fa777570aa806c5c9ec31b9432ad8070eb1474e9d685eb85116aef47ec47eb621c33a38301ae2348233d3b49ac13e64c70d4c4d594927cf3508f8ca6c040e71c95963820d7a70f22fe3120ad893234799be5de84d096b5b8961cdf8b09a52eefb994f433ee5b57ed74f1eda8d6894d2d19fd1faec1d6f34aa175e4b3a8298159f8a6e4130c3d2100d2c9ba994be1e20367f5d587d34ad6c2b00078ae1fc589c77ef3c3d2f0819eeccff1e7b686308122d9d8504b39be1bc01425d29147ad7e24db8c1c132b955ab073d37fc1a83a12d4155f747ffb33779b2f58e4c862d97bfee479631188a1c888ae437b39bf9f197fda0ce1708be825c4eb5bcf8c419b7f44d1be60c224b70e8536ba3f0eb79d6255438988b420f80a81c2f986a8abc2a7c60bf54f0027e1c190c4a8711fbc8551441c6640130372c515be3f22cb10fb9b53223096821a135a309f40922d5cbc2acd57e0d7cbec9d47837ae1465312424a77c6be3451090277f17d6225a0d634455659903b1bc51e79c1330a70d6139e9d7fac08e5928f23d2c10c6268ebbfda4cc45948a33a263f672a523125d188f64c9c01b2ef801686f5fd26321808e96e07433968d05a44864eddc2d190155cd3266c23778dd1cf843a779f77919c8e7a5560dfebc817d703f3eeaa802c613992e5ee2ba6ae90600125b1aa07f04902c524d3cf57e1461d9895461117ec413fb3537752d755737738bebbe1135afa71db91e93f33771d16ab3134f0d6d588dfe23ec6661698421c010d43df3dd7e9c422f8b1e34ad0953e9fe8d7ce81f4b0a62334f5229c6b11fbf5889642660619a2c1f0e98fc561836f62f61861712455a193e54e7c4fe6f1052296ee852b33ded957545dea80dc5f0c97cbda1d7a6a74ae0f482a59e8cb33bb42522b6652eae4ffa1184a2de0e215a662edc4731a0e6042a69f93fa68cc9088fca3e3d8473d5aaabc62ee5956144fd68eacf289eabfe35e6112e919837b82d7084db1a4cfd8e1a86c4ea3b90b890aac23156b50e21f293d0091cb71822592ff9c0493c1dbfd67640a5da51820cbdf5b86bdfcf47065c715bdf265190284a0b73ae525c70e05f0b35f67f8d8652f31cb650c02195c931546a32dc64207c2e0bc73fc8158e7188e8dcb8e258236356ebe5e35361b0bd759fc8652773690a2908ccc0ebd47a889f3ab783f4f3cf12738b7b2323680c69eb1f28688820c02c601f93ccb28717da6b6e5ac20fbaf7fb283784370fd30fed3aa8e0b485027dda030449a6abeb922c705c903a2f349dfb075b9ce0c18e90df690fad3177e02ee6ef19ce602f6cf463ca06a38203017ebfd02519b5b607a11718243b01084656792f3bec57956232f1c5f6ea03fe34bed97e55a8ab67741617263ab232293b19fac40daa9688655da4d37882b0b21980dd5201b4fcef42e0c038e8033a024c787ec218988b08396e9a621ac4374b10bd13d521b52f0afccb3efa4681e8f6ca1fd2152142c89c09aa954cf4c5e4073fdc99cb6cd151458b59552f0ac5f61888679ffc3711d4b806e756a77f31c993ec9239927414ec4fe996e7fc498cecacc56b30440add6f71b02bc34f3705681e7e19cd3722febf38b6ecc25398bb9b527c77fce532371b2463d4fd5a8d0f1dbf97b95eb59acf0281d7805f99e519aa4efb65699a2b2ed89cc8af53bc305bc1a4f750a953086fab18a36eace7e0311de9a6d400042c17846ede3f280a7ab4dda32bbf364fad1722b5bbdc0bab21aba5e4f43b243b2165258d04633957684ae38ab2b101914a21dc1bdc31423f7748d0e36ba5d3201552a2aa76507dc1d4b4d92c4f16329c00c167765ee4f340a281f1f3d73478bd1a0d31ad5bc40969f7ae3cfed770c1b9eea1d75b8b655bfb6932610eec0d5ab113b12dd78802355c2cc8e71427ddbed5ce2cf37d454fe788c09772ce1668b9d120d1cf5f9b0503b193b2378df3b292666df3df011ec6b94271a61fae493f6f92a7308f733d9a12fd7b5596db6a6285d44ea2a0ad64d329ceeff2296a403a730c2a18881d32ebfd93d502d54021471ab8f9473af265b6e42c1fb98c1767a92d5613e29d270a27af9fa8a71f666fe1766d071813b2156e912182a7aa914439c96ab469a576c17510f1617b4536f69c2ded22c1d50d7482cb7fbcde67af59ea734f3742a0e375c7e0210ae4ecff0f818f71b270d49137e46a6ab38afffc1e24cbbd1719870d3e86dc6ff5d1bd5411bb64dd569d593e4c248415f7d59339ff83a749b6a05dd86280bab71b975247de7eb838de56281ca26849ecb8e86cf7bf9a0cae3d93acb75b4af9a46f93c830ccb8c922facef21700878b23cd313fedda6ab91908b77f5142bd60e02deb87c4a2e80b25fc7c51982d1a700fc827a45cf4114305bbb485f8a04e9a4c576365222319432630051ceea8dbcbd0513366fe622b7c15b9c5b9c7697fa7ee201eae4aad0423bb61b96652b3f1e19a5670bad143d6d8b90a9472a2f0177fae07a68dce0172384663be8e4099ec3c154e81a0a2a42363569f8f4030ab4bba6ecede9447835cd97adce8f030e3abf7fe531c9b63a81a5285bf7b45c1f3599a59c5a6ecb70cd6a747b61245e673243b55bf0bf824bc01b754810a19812c082b2252e891d98896999590ce20c9cf78be0e86967f099849b7613ac45084d0c4b7490389500f296efcc38e69fccacd8a9cb3df706bc09c399886164afd22de21676d0fdb93fee1efaf2d363e2ee83295c2bfcdfd4bcce1f0197c9052a92b3ad4032d871562d7c46a0d7deb229244414be672c0dd9a0de1cdd818b8b498ecbf1c786d53e82bb1dfa187d22b4bae3179d56ca4fdd6f8f2d4c81df80726dfcf243829c33d23b77b8d039b0d169c5613ecde639a30eec12dbd364bdca747e8bbf610033c8a02b1f2763aa9a63806d07364d24228d7ba621133ec01c79059f65c54748703fc60eecc810382fbd160a8df4dcd47aa57f640f5ffd74a1f94f9a56156f7c0c6e34fdd6e43a5a0ac46b71474140fb8f16c10aab75678875f19fa82dad79a6cd284c78488aee66c5279d16acb21b8db2df30327783b64335934d7db219dc6846d9199329fa8f8e8a949863b39c03bbf8d83850920f4e87f41bc8f14c5fe3541444af632f5df9866dcae93493fae87809f16ee551bac8c4ddd0bce15ff7be0e573cd46fbac5fc7f4b764f46fd3bb09ab24bbbd9c38ee0f648386d892a90165e2acc2e5057c7aef96648ae013178932d6eab4b60d94555a7f380201c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945860300000000000000af3ce8279bc3e39954527b6314ce47076c97b16c3577c2e7ef014a9f62bb1e248ebb21fb1ca0aea57f0a3df15877c9de9751b1767d705d511fb67eec61dfd42f00" + "0400000027e30134d620e9fe61f719938320bab63e7e72c91b5e23025676f90ed8119f02c71c7ffa660028b5f3bc0b0bedf9b76a829ce8f2ef82c2c69ab6948bc9fd00a80000000000000000000000000000000000000000000000000000000000000000f2fa494d3fa60c200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025100ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac000000000100000000000000000000000000000600008077777777d80a1977000000001c1d1c000000000002000adfbfe7961473dc7f8ffd411b3e2eeb005a37342e6081d5121f18f5648c8480adb28949796e09a38118152905839afc125618be1fdaf921d188488b607f2544e12a249ab310f17a9349bfe463c7de09d2b822ab0efa88b6d32f77d7c38793192b944aeec0ca94918390dbe44c50e706407692e348ed9b7cedd231941a673722ef1e7e74888672b2b2d08c97a9ac114b7039feffbeb8bbe197db4a0bca8d395cd40551c1d5d788acc2ad09eddda73a5948de2d9e2d82aa638dad6f5dc61042d6850b926d944f29f17e96eca84684252c97ce4382f2642e54208929a4b37954e8e386c677f2aee3e8f4f4aee9f76a87d868fa2210445c09b927b842485918c869a23be8213ae21937a8ca83406fab193cecfd3fcf3b1c698e8057a6c87c059dc6f4ccb30af8e608a7c04088cf3ca32ab20cd780da9443606b092c8b5d85c9a76433c0993e3eee385884ce1f3890abf95462c49bed01a3a5c09df98cb7082e9770bdee196f8b968003f5cc76d82bf575f01da3ed40e44b3b15721f4a9dd5ecd14fb71a42b24ccb7d7e6a3bc10b53ebcb7e0ec6ace91dbc19801eff0c76ec0c10602bca2cfce9f3e79536a25143d351ed2894b4eb4e549960f212f0787057ab1ac8b249c3d3ff8652cb3fb17d7656d50c5e6833b056feb26855332f60e7b8d1ebba32df63d8561fd7d209a1e5adb9853bb5b5d6a41bf1ec52d348023e945bc02e8d6ae8d5b6c7a9225991cca4aa0b41861f237b3bf545220799f152767c7fdcc693a989057e119c18a96007c69c8fe5751a4258ec3f0f99c1aea8dbbaf4df9953ccf6b42cf2f4265011ca89ec7b9ef2c6e9410886291054f50db6310b225ddf32f9db26416da6ca9ef6e3198db36ebab9802517aeaf628d41358fd141dda8fab32fcded20707abc3d00191e0b2690a1e2fa044814191323155fb21e3da8798e0bafef8c2da4c73f967504f51e716cf87117f90fd028df17f3ea26aebeda7f5b3192cd5f4855044e9a41bbfb817074ca1680a458338b191a9619dd337bd0335cb1896d79c79cce10e454b58fecb1cf10da9f53129bbf3cae2bde82007ed98505f16922b6ae53a3a709c2e01ff7e529925d6069807c06bb0c73abf8d463b2a944a97d150935cc76e1ae1f8f95159a928a5afbf76d54544a771fd4bc482ca522274b94c87b4f1c7cc3399709b5572c5133bc945cca63bad59b454ee301e3582f09c5c31f326a59705a2b534d8e9a79835bf767ea563b0aa74d3301c40a303f6fc04ba0f3807c5decb6743aabfed1a092f88975820c324e2229829462e4985e299c2415eccbdbb4ff26789b74e91db286e6a4af023e8a18e826e930d9d4ac8d92cd8a1098d0705852cda367ba067e723ace9ea8b9502e20e6519dc72b1cb477c4f3091ae4d20eb7401acac77d923eaf5de00ecbb61baa3aca9044f3e66262245aa9f3dce1d02a88e8c26b34e3c27b4e4e5f91cb633c9b6e098063d052dd6883d4c2b153c739ef78c5f375c640ff747adc1110de2f9d011118f3208bee2f3af9990d56ecddab1cfde0c053020b1116afdec7a3303fffe6f6880072482f95aa3115724814aa5fad017e3b7637f3dba509f1e371c9b87a275cfceb68aa5317dbac0e1959367d124935c76631b8aeb532d99c393374f214af2d6a3a5bf4071d97b6ad39b5b2ec03f1feb520ce467808eb2cedb3ec933c20322bcd4511b838de111f9faafb5d45ffd8edbb1fe8f0928d535ab9809b4cbf588af635419b10f7ad9f4418c766d88526215b74518cb6554e833ada2dea5e57776a09541d76ba545f8a727bbe7722912cf00da4a48a462a5b7b13c88941762462142f97e8da2b358435c9cb53d24b6443ea2e1bdaaf6ce58dbd0bcc598cf170a193e14e76ca8bde66ccc786bd330c6ce61db5f202b01c7faf185877e3614c1a1b4484cae6dbef080142f8c45e3e48485746fd3505bba099ae7b37b96e22b2cfe6a0dea5b017974126259d5055a28ad510b3b7116c27287fb7e635f1918d5a9ca2529b1741c9e86c59ddf11c3f70a56fac7c9607eb9bb36612494ed1ae819c092cfff73b7c9c5d3e8680dbe73f92b749c84363c374d80632fc488d0b7d35f25ecac1c151ad8427d7a4eacf24fa6937fd5c416776654bcfae92d999b51c49d76bd53a9d5600b40915acab5d31f0ea3f7a68adccbb72cb454164beb35819af0e9e06ecb40e96c9c2aa8018883301f65cfbaa7ea894737d49b44aa5d76c4b26bbb6de7126bf785fc2a8760ce1664150be0b6828659513561b52906e6a4782732749897a41ffce670736ce0baf5730fce9bcb50a44e1e9bba166f4812ecfdbc2ddd8483405cd2bc68ac179177e1713220348da35c7b2a30c9ad9670d99a53a3c4c4a611fcefe9e39024732d6996568f2fd8eca433a41664b070000000000000000ae2935f1dfd8a24aed7c70df7de3a668eb7a49b1319880dde2bbd9031ae5d82ffde01c599a33ae69b9dcc093a546efd4cdc2c8daa0479ccdc63123cbd0622fa54f8c15ce9a049727b659c998b2fc935ddfae5788c51772e00dd8fafb91e7b9e7b9d4a34efad77ea3f54eaf8bb5bfd4c5d5ec6761689042ec6b1639e79d2628e712669e32f33d058707141549b0a0fc31d9fe4a633871d1ca48096cd8272f735a0838bc1a440947547ce52183863bf080eba73bb36f5130d7dc8676be2e28d00714dc36ccc580d88f6d878357e7121a811a03eb12faddcb75c9c3703ccc4afdaa85101244e619f565a5635e6b8c856fda2edfc27b5c06a711730beb1c361a6a916fd713ba64385734b8563775d66adace055205c6cf9a6c90faca0629e7b93511d0e51e3405210bc3d3c590ead6671e57af44a9418a5d3c6369d5b6d294032f1592c601c2782f5e5fb7ef820f548a7e21661944982f5b04f8722ebf42456df6748a2f9ba2b816bfdfe1432f6c4911daec2b75802d43000403272e1de73bfd625b9742b8970133c0599a17cb7fd7984d6a3da82e845e179ea888019c6d86016cbef610a7a0e3409f0a2bac1181ce62a22fe3fdad2708225ec503077caf354dc5c12f6fad975509172383e2f87405fc7c387b1de333f435426fa3b8a524cea377f3c24690918a4ea2dbf4940ded498169b9b85adcd9d37175ac43897abea5d629775f4f9792d2ece6ff69dec38e38d0c1c9e40dd2967aa103a20a148290a9b89ea82e1bb5235bfd29d260862365933e19f81eb19be2c775707433d66c15f68e5bb8a578a925f20e9d1bc34132c5a214ade50ff48489b89cb674fd3a9c787d0ab539849aa19486e3d4081d4f361517f45fa35168e0432fbb69251a6a7e8f5d33b30564338f693e636d04203502588b4e9128744f49005a77e5de0f79e06053c01e82f4bc29f0bdaf3292c300030eb758fe2a7e98f41f0db618ecb99924e25084b0e69da78bb4918b365b8c613ff5e033d4994e176b5abe710fa552b3e5e21f59a33e4e0aad74c0504c2eeffcf213301b35d9b0bd3c7d140c849012b1fa7ee177e994366b9b278afd94f6bf9a65bbd1cfcf5f3525512e5b257f6a5cd61c43ff2c695cd9571d8d0e24bff92a5ace203d9a643b7c52d794b3a6a2f0cdc6c8c1527e51b32847935dd0c12b1f1aef49cc40d4318b5b067ab9d238e7dc4a8903d8ed224c15ed66b11043fb6ca6109587b6210027df615ef57125d696d0de758be6e4b1693e260589e441ebb020177a4bc7c577a7f2c7d415e00fe93cf1436bf13f738f0cb7d0448074f1436457dfdc03217b585d133dd44928779072129072c0cf0ad9ff3fdbc686f12d219313ceb77e01846f030d631c8014987081a1e3659239e009105143ff3fd3d999fb10e1a1b8f0adce31db881d5da746138462e5a1b45d47862fff760d3b1ae1de946257f2f0edd1bb911495fe1a24ec3a7cd5285e5bb25ac1d206d2f926f9dfd574758a6eb2ee5faed26e5a8e07dbeb11ba4dcfad69d93cc718fca7658b97384a243589699547d476887de967e325ba5e3b982b079eddf83998849579a849dbd3f2f487eaf9242512899756352f3680f334e0585bd43a3439bd62404297912e545e7c18e0c2e19714752b7525bebea1d83222648bc9457ff3fed4c91b1fabc6c88b5c3805dde0267f72a0abba1715fcbacce4253881625026ec2e240e8bb98c5316d28d361a91a1a572caa057492fec8d5e8d8b51f5890515186f7c97ba4a3810f40e9916567ea7a1980fd806d295c73a8b1243b538c373f531994507ae50889cddbe473a8dac128c98eeaa965cb0cdec2dce36fae175334b1dccd48839b7d28292a7c753cf23990d111e518a4260631d5a99a28f3bfd01db75d8271d08556abef553106fdc472ae97b5f4d2d3741a5104d06560d85f48d3e3acb040c3264d37f370f2acbff61ed733f655d8815983c7e78942131b41645f1ddcb24711ef39dede1317c4d7dd9b01f77066b9f3714b5f09dbb35e8341188e4384bad7238d9ef7d73e2055bb9e6706a90348ae9e5057780666f3642d7a18085e115e5ea3447fdd013a7d976d00e39edee09b271286c1a325161d3d6eac566cb86c5af3d287b5a56dcc48faec1d8342bf3c5436ccf03c0b47cb880aa7001e2c5464a406e24dfd9d021e62558e3cc9ae3228f03ddab021d5519fb426551e0a39ad08f68229662f16b79b7653b8f827a8527f1dc556a02f9e3c7d0f3872467a60340dbb0641d91d6956a33f5c905069ac39e67b40fc8d5dc617e00e89dd926bac628eb187ca1d0c41972b73b628f18159633c6d4697893bab32cb760a193b57034804a66381e62bebd6b729294bb14a113c5750a2bbdb57d40ec9e37ce7f3a486b920bf2972779b88d4ffd3136e2c10286682a4c413ed2991ce333060be5e348dde9eaded10e4cfc84ab1b157713936149239477a0b5a437574a45f24843ec4a525a71813c05c2524b92c893cb6aa0dda8df21d550371f5ac622038baef7071007a31cc486158ca1a8ec2a0c274ea26100fcfa5a3991b6f79384ae487975207d2b0b068df60c7bd63c014d13d2b5215ba7be1802b78742cee248c07cb00f3d5472dde9f85a1a9a323125a3cca08fe5c8d89f73c3fb600a4a3c7f28f12ccdac1e911c8d62242deb1ceb63eb40ffad0ae8845cc9efe69e9f5a7d2cb9910306e16b529d8e16e235e8e54eb84859d4346bfbfbefd453f9a4c8f4cc5c6c80a616433dbbcbb512651578d1d2736f513afa0fc68b401b53086d4a32d2a73100b59f8c07c06f43d17d2021fdc15410e22b5911b3572d5f7996703e97d24699da3fe7714ce74a1daa802609cc631db787abb71504d8c016cb7f5973c0d5f91899bbb100b97d4063ca590d15f176612d2e8779f89132428c6a17ce0dcab8ca081b9d891d3d0cd0bc755a193c5d5180d28d917ea7c5121c702e7c66a58b5499ba4fae3336a2040c986afd2f44d92047b338db4b6b3b6c176d88c641a6d9b4d4749654d55785002b3201ba3eb86562adf07f94b3e39bb3304a2d022a872ae74cbf27f0194c5c73037bca2d3daf1150aee2f81991aecca23660de5072568652037ce13944ec9d75f7cf424607e36233008df0a9707913985b837c631288ac62c253c9cc1586706b9e8238bb0d3d14fcfad900dff65772b36ca252d9f81450ec29d6be025262bc1104a1643c099b3bae8914c8c78cf39d09907d725a52f3ef3a9981c2dec6cccb88017805cf2163e8909eb0822c34d2b42ed08af78dbae9484e7e4faaf2a40b0762f23b491a2ccbdb5cdb4df184b2b70cd39b0fd39b8a50e4cc527f4c6169e79e9c1cca54900a1624e198a0214d8013c017a2dad0aea1521269505213c1c873cb5531b6dcaf1c5430d741514e49e7f3c0f7bea8c9e3ecddacc99e2a8e729f8a0e9c87687f11158aaa9a7159ca567598add54fdb1a58eb08da87154c59bb9214e9d63fc280ce2fe1300b12d4b805d2d992a5e5f74b04e6b41ef9e4f364aaf3f90aad6435d7662d5639882f9edf5dc7ae1e5623fb1cfd9578fbe00cf82353ecf865d9ea24b5d5050e6f7609205b2ef209c57df854ab27f2dbf047e69666ecb731f0b11e540edc105301dd9b915fb4fb1d96f4f8b99b9c42f55f99cedb22638167927766642f0c1f6c4038d4ebc8dfacf6a3ea59532d6275fa5947cc80f44650719be2802f83f62b86776c7a8ac0b92305c69583eb7b1457e21760890e8b9f42f0043af46d07f82f8aab3168ea992bb165dc7396aef85646148b9e9fa88735bcc4f2f94d70fe02200480795aed487d24810b4875284d8e51e25493075e17b7f9f319da50e339a61412cee460382cef9feefa131bb3038360535c5593039fe5fa3795bdff94b1d41e0538536a9e6de8e4a9228d65bdc5cf6868680f452599112cbb3750f9f167ed33017d61dc6b6b374d87384d3a81e74289bd5253ebd20edd58d54bd3711fed8b2273d5c39ab91cfa21b2d3a901891eff40eefd70b8d0d55c1c33a9bbbf2e0dfa2430c736a18addf449dbaa6ed37f04b5a921f945bca6bda7cc75fe47f4c8395918236dbd810406e684aec3eca46c8079dc76defdd90c746859df26c661e746260ec99f15b3bcef2d4eba263d6563f305d522b58f2a39d9f420625b2da43f7dab24c63ac0cd79078a56156ddb4a295057c02dfd02bb52511d08547ec1c0be7a7a1ffdeb550551cf0170e89d9ccf024e862eb9df3458bede7e0bc7060860bcefe43e526edc7ed295f331d5167705f7f32da9721abf972e7eb1235344776ac19bc23e6b916d3a5e54f6863dfe0f46b17800ca77c07f80f0fbe0b2a39fdd2e0107e53148182c577a60a52ce377947c1c44f9264db8fe29b5d9943ec70997fbd1759539f1c5c279f645b68a856d58571bd99d0589f444f239f194c9e73e1606f8affd027a78fec78b8ce11a3871e416307c4357e761b6836be85570d3f155e9d19db103d148cf9dd8b51faabd6157e5e80c9b78e19501489fb6fabc2c1b7de2d9f480006f0b5858eae39893f9ec8a36ed92f2d6e64a31a7c1b13dfa8540d3176e2d451b09237feca9752c8e14b48eee5dec0cc314a00cf41303c8af57c727140be157376f5182e5bd20ef43bfb73077f388b2152c79b40c7bd7360aa0da790677535a1e1ea76528a51b5ea8ceecf9babab979606945dc154ab3269d729996e6f7ed843e8207cd7893e5f8be32fecbcae63474a8f3d3e66f5ad3be91ebd42319d4d4e81377d3531f4bbb7279ba63403c9d827875d7c244a9e7a7c83818af42fee45603039becb40982e1ec43e71c919a409cebd605b865e99936dac09953b4be63ee592eb0f1bc6c8a0fb156bde6c4e05df97253dfa07ad950253f18e0bde6eb9baaad215c785a73750c6f30b36acff3e760abd513258e60d80770b4116cc7f925f34b286649676697b49fecdc8e99c6fe3311d34fcc8c4cc1f066ce680bbf9c9fc32722c858204e9f8201dab9bd6639830830e9a24830a2dfc02f767eea40019df8d41f2e0f63562cdbe55f71b136d52a61b271a24e5992a123f08babf356fd83468d20ecb634bb0ad02be4af5fa5163445cf5ae233804ea209f5c279c726db78f1c81974fb8cabc783e54ee537c9bc3c83370bba589e1389bb1e63ecf59250dcc2752fe0e1081cffb2e7f4c62d44e54a46480a809d383e81106a1b06165f419a8f3502cc7fef7c9067599af2f049fac6ee80b15122555362f7419ab7f3379cf9f27503c503eacc8e94bde23efcd0257fca4da1ac39ad5f580174c42860c91be20a8b1b95c2ccd2a51466da013a02d728d54c168eb50c064b30da49f272f08ca19099058805f91afce70776194f24a151fe36c2619df9fab6760554cbb58781514f131f1ec127a06d98e5ce4ba82fcf1165937ed258ddc9ace565827b6b8cc009b87b083119fc093a106d5f5c679e7a145b619e34f69ac0531a9d7e17ece8e335b66f14fa874dafa045603e127954d89dfcc0994581a48f54fec32d4228831dabe01d0d9f887f4604e975326e8cda35e2151a452be21a4f7117740e70bfb98cbbdaba32795fae8150ab9be24746faf5c8a9ab253cf34f2807e30a238a3ce2aa5de2691371c49b1475e62444947f632da3da60786d0f1f52a8ddb0f69bb293540830f10cf70b3d84609d16fb1c6285a4ca9ab615ea8b0aa6274317dc9c06fba50e001d00fb9db760fe6e4e751a720bb33cfa914fd5ccd5a5e5ee325805cabfbdbfdbe82a45aa53570a50fc22573e6bbf7fb641f16d01f44b9176f965b1ae610b0bf2a73fa1125b14bded8008d3d1617951e19f225d0698241746b651e003fafa16764506610fd92caf131e8c278fece483410fc3e2c6f2cc76d4a9b66028ff3aa83d4a074cce66ef035e8f2186d2ff9ed2615b0c451c8564b812f225feecf9cbbb2de6238dc4c8770a0e17feb7cb02217da98318414257c4dbf3022d8f1e5ad79fea78168c8f1771affdf4597994697e6cece2e6bfc7219d3018e3ac49549e37b8a57e0e69ef51c8944a3ed215f36c15a2883aceab247dac03ef5a82f235fea559e6b42cccd5eafc30066a3a3173bcf2f7ad34004071bd080e69c7ad3f514c62c928e63457afd2973142069ea68111c6820af10202db0396474cb2a78e1a7121ec04900d9f4ebbadf3d306273afaeaaaaf0d882dbd511146f009b748c2e093f02baac204a3b4ebd4bee5aedc3935775b9d01cab2723ce0c06ccfd5e2a8a2c8fc467c9a06ff3964e96e104890097d00a99811114179536be5457dc37864f4b5f848d27d28a6143b90bc2ae09b218e867fbd6791404ccb662fb779119b8cd2472d1f9e360ccc37f39f2019c79f365c813fd80faf189985f1704016f096acfc6bc0b674fb117ba7eab0f4138791416638ba365c546180b8d5662bfe157f3f63430198548216d7cec0ec8724ebde55883b2c384cbb67b2d7179362f9114dbbe561c8acb3d40ccde56ea66cd7c832b299a96f3a0e0aebb57e9246068d5fbdb126e6a149f7ef2214c35f30409f1b44de792cd741df0cf48f273f6dcafd69547fde219908a75b3b594f45a382ffda619f7e1378df37a8b2a25aad273329002ef931a95a0a7b670dba6dcfc08119783f60b84aba6ba878de6158e689ab051e5ed1743f6fe28a3c061198e7a49d08a68271205e4151c49264929d9ba38dcb2559f45658ce96b2c232cdf40e63bd8828794ef664543bc2f700a65d7c86f218a9b76ad0391906f4480f5563b434403e35eca1079d8c1f906a271ffa21d669a27883108ee78a4fceaa056c0bd5aa4496ec5f37b2dab8b19abc88c61ec5891759c6fb2263f534df3d7116d6874f42d8bc3a1ff9383a68ef3955295b5478c28308c79ab25ae9ca31544427a2cde901ea588ba872f37cedac395f6661ec659f1bcde925f6a82502b32fbb07d4356efda64e82c35356f9abaf5d3f0abbcbf0b0fcc2191501aeb7b59b21e00858b19492aaab25c62afc3b0cecd3d7746eb6cb1edb0cdc569602791a17911802c9f5ccca92717ac661cfd4d4dd8bcdec75492a64bdd2150c2235e7d87759e137b213cb3ab4e275a99e4ac77fda073e2870b6486ba384c44b4f59b382847a5d0a4f87198a996e639f51246014a0d9751db9f85bcbea056a7609332bb1e7ffee3baf262a346e45697d9c97c5ef099e109251368b5a807e6b69c1247e8430d2ac2261aab0ef2a0f695c22086b86fee0adb6bdc8a14af3d02ea0effac0f6f55e8203503b48deb8c8673b92c499284b935abd06352b391c253e35870f024bcbec4332f578a74d4ab0be09e73e3cbf5e1ed7e53eceeeff4ec26941dec578ce3a33f701bb540da65f810e7f4df368804cfcb6078c99d45e4f15ee1d1ad6831c3e6e01102e6ebeed1f86940de0759b256594c9f91041716bd57ea464e77cca292090f612bd7daf20e9b534bacf13ca7d940c90fa9c18b188fbcc17e282edb1156cf5c1351a9f118dcbc5cc720c5c6dad1ccfd04f1beab7817561e86442665b841c97150d10395fd842b54d025a221d81f05c820474e492341a0c6dff31f4a38ee089082f7bfb17b9d8c8355dc76bcefcf0c7692ece39649e85ddf7e395f1baf893eb960d8e1374e84a1d32fc1924ec5808c1255b34946db13ada6163b368754820d519197aceb746d33f556f9932aa775b5547d4b42ab6433e4adfea54bbd7d173e622229660e74ec486937fba081cbb26de3ce7f6f76e070cf54315f18b03675cee1c06fc765f145b7fe4fd12f897c83e21c299fb9614533e163564b9d3090cb00f253029a3a4042e2047cead0dcd42969685de183ded532773056cebbe0242e9bdbf079eb9c8b0a64df4833ad35fc40a317e99070683255e7087a0896b20e0b483410f9e4913bf36cd028555302162a6c6152803b31b8dede9717b80947efaa233f6324941e0714473c92da512fbec873e4b745505a5e691e2f1b6dc2e98d1cacf4c1a42dff6e360909bb82027b6ad070f34ea2d1bea39653da363b2dd14633f5d0f11cc1617ab8239e9832b162b2bc18d8703a39a21ac2ce9b1f23395225f6b34671d5e7679459e7f86391c80e2e3c350220f3f3cb40e575fd8afae3bbe1104246b092e405bb740e213734a5a171aeb6d82b185973a797cf3f17d77cee462e4f3032d053044aa6d8060928f6227bee4a2ad6f7cc6bf49df364cc75fdb9c9aefda07130967032ecb5a29b38bafd4e6755e2427585746460d696c9481db581ccd583311b68da1e80fc45b330e7fc6744105cf7f329effa8d05e5f04f891e6a45c0f620a1c516f22c796523a325d03aa141674b2d257074a20a7b14308310c73ccefa815f73715282cb467a763532504523a1b1fdcf2ed3af8381fa967e02294195a9d0eb43a1f5413be08d6e9ac6e95ebddb34f6962bb64dbde6e94bf734cca4cd1d70feb5b3525d1a4f8551facc79b5f00732cb252e9df686627a56b80b13fd033cf279cfc12ae321a0fa58da9df8da8e6f9f64214e40c22334f13bf1f6da122b4673deedbff3f98958b53af0f4b40158d79e63778123cc6dfd55f43f4bce42f318b0ac418dac56dd9436e78bb527c37dfc28180fed5c439f952931b29e271d83b633effe9809a6399282048357028ab1b540cc0510ee6b19a63643714857fe51c2b1b2963b7964cb602861e81eb52348453e9bc497c447e8a8eb73c79f3997ba17f35f32121ac7b0172845bd8caed56a79285e97d17aa467312c4d10b8bce1d18e416c383b128ded04fd1724a29cd8fe9377ead625ae91efff1a562e03d382e4b4621b28f717ac6fa928dac4a086aea4e122d59f28c961ace3dea0bfc79eb62a5702870bb86a8d82e6284b39f61d2c39b7d99eb65f319cce48af91a9028a48cae8c3c08134f7285c9e7161a570947fab3497f00476f9ede57415cf5889ec18501783af4c371a24560a3046a2683741e851ec1c34fe45c777ed5cb03dfb8ae6648a1224bfbc723f1a69a9edc5ef37147baa1a84b199be1dd645dcc0fba7ca9e8365309f3669b6d1d2e8a47e21d34d1405e6530e0d200dd9997ad72de1e70e660dcf53a6bc4bccd999214ef9206af79b44915e9956f8a019919290066728eb9ae5ccf073eefa4b9f771f584c03648cccfbc1823d118326d7488e2fdb2319df94a593ab0bb34c9970d038dddf2c174631f7b73eba3e6fdae9edee2ead25e57f4c498c32a567c546f089930cabc63db6421a25915714aeef8d9ccd320237cb0e4d302fe1c964c4aaa604714105a1228fe5ad6ca7f42fb2e07c7d6b0bae5f3b320f59e9821d0f66b702e0bef73c4f3d891454e90599f033a96da7df2faf22455f49e28b10ca126096573ceb1d4154791bd607ab67ddc372cdc3da2957e67ce2c599d50b90710895a934fe744c3cb75b1836eed5ac9a549c28930a6388a7c993c7d5a5aa302ee7bf08d177548ecd98c65152d6197286f52b57a3f918218fda1241e28c86201d6e3b6ca12d8e6756223bf9b19387c321db1a0ea2fdcb7a7705f7e8c81a998368a1cdb7788be5629a43704d8e91662b3e1a5ab205f85a27a139a5dd5e40cab92e6dcadb5be50ca3343905fd10ba97df8aa658634c914db6389809d9b18f59fbe371733e5ae1fb35f0f6230a2394119aca72cb11db8a0d0c82a0313562b97528fb50b99f21e3c4097366b763b0325a2f8875b32cd4beadb07925be74aa54aa89f9b52eb1394e1863899f04d7fb451fdb81fc4360a3320dc2a24b3b2c0fd463d9906b0797c3215595d59e5350da3a8cd519d51e76904a80d73a163b384fa68002516c7d7efb1f14aee9258b3aab9c5033b8d929430ef742cc88665799fb1207f2c8d333db1ac85d4c15235103d28b3769df98a763426546b21a8eb0f67872edc8c9d448b8c70d6f7af172d13c3aac5d4ae5bfc8ca9c891e501f2c473eac63cdc16a96b0f74cffb89211a411b0e6b4a0d794b5be83a7cdde651573a142789aaa6aaf76c7f6ba4851d1eedce7feb5f7a2c1179e351a6d97620395b96850238967e8264f581ba4ad4dc85933c874e30fa3adf74901f6ece0504879356a835eb019e12e5761f5555f63c91142c59cb32515de844c0284a31d5e148b694c53e3c69378a1c2880e893fce50f5ebb5b46b7ddc8753e7104f5effea9b0c36e3720469c3f20b8d97cd39c06cecf7881d20032be0f23ed939613cb0dc5ac81ece654aaf5ec36ba427cda4a0031328afc840ffda24b1829153682cbee0da142cfac74394c073def27b4b38f5cdc1c7b699d281d1fd41ac559410cba3330d16c74c8d035ef0210c8dd151a3850db594502d1d50c2959301c384da313611e361e71e937a5d1799d1a45398ce25b1111c86177152676d64393e6ed1f11821c1fb5dca4cddce3a3b1e28975d80dca762c79210222f6771d20ac64da695035d00dae321be393b17008e5f0037f4c1733e4a9f17ce275a85fb44ba59edf9e20403843b11863e4db333233314661bfaf853d6269b187bbb6c0eb0f510d4912645056813ad34cf3bfe5277c589a0314bae0aa802cff46b510c6c76938cb84e921f7b4cf4200da1a82942a807a2075c0f7dfebf768b54b2e308dc49488c4080d6c71c0bf8d773d5de3cd112c588a8ffe11d7a17534a6c7fef432c380ccf252a10d8cd1fa13a5cea6e546349923de83cceee44f2981984fef7144be4e72ea0c149458a7aa6648c9f658622c00be9d0074d3b0d498e475c8e4bfdc9ed4ce81d3aba532aabf7e18d5097ce37505c2dfe9df59a6bb30fe45d62c8a1f2b065ca8bf74f81bc3da5ea3bc5fe855ed0f0104574554480151238458b0d0dd6d493ec964a7462117237ea214ab8bb54b5a7d9e005f5606865f5c7c04adb7149725e02ae803000000000000c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945862d09879b6ff8bdded4f70af68cd3e81dc71a4c671032da6cd9224a5c6c1a660aa1393872b9170453d05c1f40ee3bcb8f727b3e196cbb9c72e7f12ea97080f67e003c99764d0dda139b3165da5dc4bf9700c6a563fcd0543f549e7b19d4cc4caf777c3aac4386f3bb692fd45d7197df5894f1c9545709c9c2255a3b6ed950385ba5a7c9c5fe91bfc671695898f78518380e34231b3e36a49b641cb3e940beec0062", + "040000007d24b5bfe1999a3b21189a3c4d4867784bc2105a0196aba2ba6fd1c9a63e22e1be3fd8ef559f3e7d94c5da9f3ffdb276804f413014d8bf07fe14907d6a37659320e538c79c0033eb2537c88a69d77f048cf4cc4fadd09c9bbb91b4d965ac8f2e0a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025200ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac000000000200000000000000000000000000000600008077777777d80a1977000000001c1d1c000000000002ef753da29c8538cbe9669c722c10bec5663e07d101f0a6c3f1f86440a7b00dbe374e5118632c4075f9e84b6c62791de12f1ec0e70e7d415d61c6639d786b1a0c0289051e9e5ef26a5dcbceee48051ae1ee91d70e02022fcf954f3d1190186523ec4cb0ad65db85d28e247bc1daf3fa5b111983e5d328166df852374f3efa9430f7e7d5ef94c51c82437ac68d11f78c190ff7314fdfe4fe007c0be3aeae7bc1094c0be2db5c7d2b24faddb22ac70bfa8499783f312f0bec068f8c09483f7b7edb6e63753d60feb460e2ea1f683740eded3d994f602670d174d38dd95b2a151d0b1d5f2592bd522084eba11fe9f8fb1eac057b84bde9119816ff74790db723529e8713c8daf25996fad08f2a78ceff248ccc91a83402b94311946343866a6dace2226d246cb8226f2bf7555640d4891457a7f6bb6c85962a5e482ec760b6d6483a15f6b44108c2096492765fea12c37da638a7add8d0b74b1bbeb5784c3712349881b78d229a682f024cb21c0c3961704a71ebd54be06a17f44b1fb1926844f14c3a9eceb626fcacc77ddb138846bb40f28daaf7e431d5d09d6f2be928bd09b03f6ee2302cf572c781cda2167d7d8e9b1f4667c8b3f7621c0cf85aeb45462eebe743a33bebb34a9d118cb2d4a69d2038d591e3266e77e122f9fb889ab83325e5d2ab3bea0e85e10cfdd1508d3233ede0b9de84634972e6d3cbcf9325407c43fba5c9dd30a70aece3ac6ac3d5598fd2dd29907584b85398cf21879b4e9ca3c2066e65fad046e788e56fd4a9098b5a4b0fbbe12c0f7c0b5caffbbfa69e4289c9cca89ffb3158dabeb2952a6af2bac251010a3644c01918e0198b835da28e26f694ca21d897785240d0477cadd8bd03bad34639189525c02fea6172168722cf2ae9a6b51412b4f9b24495b9b2852cf045c1acc6d97dd0d6746dd116cf8bbce3258c862e1fb18a4e91d9118c5741a38d6a7aed613910b11cb881cb6d1437669ad853512778ced215ff5b460a47cbfd30e86f9eec227fc123262d73f45d71e66f17492af0457191e797ac9fe6149f4b3cd631dce8f9844bf16588f55003371165f0e48562a11799c33c5b4e4dd390b3943fddf0162c033f0751530acaf5ac2530f320c157c498452ac5012adbde2cc19339fe82e1ee6245dcea9f587a40f3b78600de1209ef9eb6a903d267a95742c856aab1829fc8974731e49b6e8f674eefa81b23026d0bcb1d770c31a60232798a8828fecba930b51b80ae6b98645be3c5b80b195828dfab3bf8763ae660dbe4f02ed5b52abb301b18f3ebf8f1f81b8feeeed620809673472aedf9d70ac86268b7a162d0f46c0ff6bf52bf5dd289a9f34c19632198cf15730427971369cebadb6e943a6d8dfa84f83f2f6451e9d155449f6ff1b41f538eb760edccc3697ef679a586c8295afff2cd8de2ddcaabecdd1c0b41e8db2790ca35e263372e2aadc2b579fcd47d74bcfa188dabae48a78eb8e32e403a3f4bbf86b8535c568a332e0b64de3b3ba0e75a2ce01deefb1b1faa6fc59cf602d1359180616258847d458d03990f158398018e63abf87086caacdeeabf6daf6965d184bf8dac33b1c5af2223168e023a2f5021874300012761f400e35e341e3b54683442a1bbf7907060b54181d27021ea69caefe8326414462f03c44eacac9f26c8a37a8eae78c76dbe19d33f6b198e8a2f4d77a2d50bdc9785518a1e210fea6451bc05e85bd106737ad37e9c96105db1b9bb09bd7cecc45960de0bd6d803913fa43935a8c17de7bf573089ec323b1aba8f6eaf0603b91e53c540305cefe8361dfe47b787257add20569bcb7aad355d93dfe9d28443da5662fd1030a8e251fef553877edd1e1559bba63ebcec258035548d037eb34276f4b256b22631489e8f7201c86537a53502b6f9b4ae7c2a7272459a4df0d203b7399ca1bae6b5260566332b955e342132535e527fa207f8ec9b0bcf9442b7794160497121720d2fd698e3eee28fa34de2321afe580958dd133b1dd2b36afa84dbd004c4a571afa48466d3b7915c84753186b5a3e7b724a8fb8e411f8732b963fe81bbaa48b247330eec8a0897ebd64a25032e8aa4c987ff8153bb447308bb3cf5ab699504746794711928457df6e10d689d81cd6a846123375f5c46ed603f14b0ac6c9729075873179c3bae9740c273d0ec9e1ce060285211c4e60fbd2801cae6c7337570601712fb81abfc25d9a43464541e13bc42b02f01f8ec78a7e5dd3e84fa9576891397106427a6ef262e11f24a55af39caf98130c69bb042475834753518d2f67f66c04d81c574eaf7d8b83bb029f037c4999159186e170752880638619096dd852f29994be72f3a6922a97610fa11085d4288214fe131d2243929d40dd5915a6789c77a499f43489ec2a0b7ad37e7b5070000000000000000dcdeed4e7121d043c65c8049da787baf0bb29c59b75e9608dc59b97fb001c92ffde01cdc9b9d97951e4247bb513ff71eff5413fda3522232fb7d7bc48429bf301c3bbf60c1e5346e6b2412ec70d7ec4091384f5a9cd1feddbf9b02fa15e591c1f86bb9ee9b65bccc11ed903646e771b8d252e63306498d3b325c7cf46dd9e4f8e1e385bd5631b11f427848e7fa3bb78f8f97d090ff15457ddb0030fa9a8332dd2ed68ec267909771b6ee3edd3370ba34516a4a7171680d2d912e2fa4c966942b231609e3a4f5860f35991d117445464ebf6049e31d0b0eacd23a11122c2cce82c6f72a160e131c588770bc6df3888503df8add4f1285f1417543f380479052a2bf8597f56b0d5587578c3b896ed7bf0e057b9a39ca8ee3b1abc2bb967bf5fd7064150871024113211114f203ce5f150e30ff55747a6ecd17a342b77fc7c41ba70e1a216112048b26bea002606abde584d49e7cd633b7a5391290e7808978100e2d5f955cda22772bf642aa0e3b4e8f30edc8c9e6dc1d4952160377205a83730dc58516ad5d5f1b121f397aa2d43f47ff7a09b602b9c61958a3317d2316b9c8db14e40a53e88f1744655a81b850ed7c9388c5388da56e36ed67ec15e15b52cac4bf47a088df916d2c70c9bb348640cb429cbed26810d8fe2218424a6c63f1dfb5bfd3277bc64dd12ae6c088d7f55c4804f6c8bcfd6332bf4d6edbce09574a9c64d3fdb1e41c4d17a403646efc749f7ca43eaf94b014dd269c833ac3e19bc7442ab86b815a9eaa9efa44d01e69c77f73f600c5a911f6e50b5713d079c855ddcc2ba6462077f5d170cda9bf0eb8e477095aad7cd5c081864b328a9cefe21b44b53ae46d38a66f6aeded011536310c3bc0dcf64d2dd0c9015c6c2f83d36d146f9bc9f5a627dca73c5e092953815715ce9ad107d5450b84d449e0e93bf16a4e03d8b15d8b938216cd6c0bc08ccbba0658391f8d8cccfcecf77a85778b9904105bce80cd8c15e38114a80fb6e6870fbc92af588a905da1de9cd58d7c288e7cf406ef916c27b1b4b61fac457fa6390d7a7b6c14256c7a87fd510806be27244e778173f993bf86ff5cbe48b85178c8ba1d529a974a00995ccaf42b64d4e714fb5df79980d79492002f7e220dceb7a14769cff9c1dba91247cb300eb8bfcfc3a85e360266fc4b9f328ba12a6098aeebc67e4fc9aae6762defa078251a0d9653cdbec24fbe31ffa3ef322e6ba7c7114d0f642b72c7ea2688505047248fb18b8321959dec8693a1ab349c16770aaf10889e46d8d8f508f3233a69c9a820b88fce5d5ed044b9cd7420f456459d3ae87a23cc72d3d9c770f94c82224d95426e10107ceb351676c1dea9f252470ec81a9825bf0c2b4a3342ffd702cdb306a351ef3bdb56539da5022b878e08549a6ec8d8773b44c19281da0e307614f72a30e46b73f8db627c4ae9f530c0ea6ea523a6b857f96acdf37b42808ffd31fccef667f92d7ae7ee853233308d0e6a61fb0f78f1d0ee35278788dc3f7585fff3688ce16d40da875b756b2cf4aa33875e01404fe7c74614f184a5eb458acd986abc580f0cf2517110b9f1239615194055de68c7925573faef91ec11706d27b7b672b42b323c32b25a796e795baa58a7dcf5e19a46f21b27bb14e2db080ea704f7a1d15c2ff114964a65bb7429a216ff96939999a743316b073d63cf87ec39d924f6e7658f325dd6a77c9921b2b21f49a22b1d96155d1dc9a206a9d521a5b3372c397556febe9495bbad48c1d9a50f0578bf5e0fdaf8d0276c1fbcd0eda0a5b72ced1fcddd7f6dc0df854aae139d42527db885aaed6998cfe1daef4865a39fccbf57673eae767a975e43f1b198185b1e37a7d1afe476cc35602f148cfee549147584f19255d6cb3e31def73cef31e3adff8184109cffcb6aba6e268367a2f1d803604aefe48404ec5b431c13dbb14374dc9e118736b43f342a3c93f57c707f58dab5f2359f88b48eb85c37d052105bdabb93a8e1f2866330f5548252ffbfd62b448fdeb777168701bdc6136a22bcc048e3679f6098c00ca7151267a4bb1c6561685f5f6fba0d1976a6b7999257a1e4d5155020b124f65e43dc06da593c7fdd96c6fd84afe493d2ade3624fd7672fc0fa7c77d97bea5be3c865655cc77440c7d28ea2cff6eb9bcf85780f2ff0e4215c8c18f63012aa4067fc1524e81c1b9d2e08975b0305c2a1add51a9471c9181835d923cf51b854cc659616fc1932e4997b2b3b737e661945abeb0d9b1fe3c113c2b2a8b371d8630927bcc23c21faff67fc6680ea0b3468b8a0279e3e160629bfccc7f1aac37b5aba4e275cb9cb8ada5c99361c70125a45c0536a9467343dbf1a22610ee2da7ab15fb8d3c5680cc447458f81523ee75668a3f75302693169b7a20349c35b77ef8e99cd3c8b852e4d1871972415de7b9bc9859697d7eab02e559f03cd57fae9e5d3d692e617a2cfbdc34eee3c9db4efdad6f1fb19a7c4907db5173f80ec204fe16919bcca832722c58273f8fb67f69e5d8b24c285aa1a74581f0f9d1fc11b42f578a1eafe7a7dc2c6f11065697d3207585344122314bcd914733132cd0bf5a661eb329dae384c0a85f559932a49d31facb17189716a38b20e3f0c0f30ab4686e79cfe9ad03c00fb0d726991869b6c89ea25da9450c3d6cc5bba1bb17c7a3c38962361890e3f7e24ce94253f63e12dcff3e2c3d045ad05f45ad9349575c7ccd0cd82fdf1e083c56dfed867382a4cf758decef9c05bea3138ca4507b7f638edbfe8f1512911ec00d4379fa996b4d64060078b95064cc81e92aff21e4b30d0b848a8d8d5ceab8f665e686881a79bb390d75f94c593be007bcd38d10de1e750df1a9256375c15e2bed4da66082248abb6d6660ec9ef6351125c245527c3b13e22d77ab516f2457d890f9dd5a6c8d0a21a4d626a5fcfc4bc3a427b5d3581830e070fc6b4c0ac8038bfa1aa52b12b0329410b6b8d0d78407817ec0cd708eaa5215921b14e113e8ceee38318fe47f3cf5a58c1ab86a6eb7734170e55b5002ab3a48cefe62fc6c897aeae4ef82eee968be5b59bf329cca3d03ad5dd38dc287eeda31de96cfb4ee94eca046b1d9e83632f1ce043b7c65782940b60bc0f9f35cde82d5623c83c6d3540139ba820af7bdada01c22a2531b1e3171e6befc5b8289868ccceedb49fe28a32bee69055d5e167eeaeb320832e0da67d6f536b7ea5226e86420f72ee68978a460d1a5f5d0f22e7b3fb59f68489f757581bb4fa107c14829bf5b93ee95f76a84c2f08514f73aa5c062585b57b02de19dd4039afc4480d8666cef6de93ea111a934295350433ecb4d7cd9957a0cc739439bd5308449d3ab744b76f429b3997611e9edfcc49f021f65645ac5524ddbc8fe9f49d8820633ea37d9e9dd5bfef0912fdc1ba80500df637ca3701122f543e99df4f528519c6233fe9cc94e5d2591124212b6a7711cb083018647b0e7200811aa58b82b5fbb10d347fb64ddf7ecc1e526d69bf7d0bf9ac4287ac42db1e4e1d9037ed3d9624cd19c590c460c87c71e7c5055cf0b78318761a5e5b8ea36978ac18275470e04d8e3da440cc7fda0b2fb7857bc2a0bda4843a60d21c3bfaaf7e32f16de155a161e01392be4ef0ab5df2bf0b18a0aaddcc364acf987c625c20fcb90b22e3a0bd6fdd161780a58517012cbfd7086a042f1e13b3f337ed2dfb4f66635d188287bfdadc3bab7a139c3ed8d784c2773836618e440f2f5ecabb712c9116a0d8536419ce663402b427556e899d12be13a588c66565c60fa3ee42f5b21cd3a8febc2b906eb91a778baf31aceeb53acb3556007cd7752fcda896c3a4a41cee337e5e63a5bd7d3d9be234295ccc93a1cd3b4c171f3a7210306901bcaabea6776909baa057ec840813de6ca414318b10d18787403f9ae1a57d671cecb824163683d2e8f3d40cd916a9e6d63aaf5f69dac13bf6cbcf9562a915febaf7d95e8fdc956018e42276703719e4f0d7c698051290d59531e034f884fe7794175006fa69b6b09897979881187a31d33c3728eb87e0562213ae81f502108314c35d590b02b4484caf58925d3f9620e89d5e4272be9fc2bcd587d337de2b815b64ebb3dc542dda0e64ff6d6037fff10941f565cb6814ac3058945d4fdd79c3f97819906551441b1914a4b6c4346a34d7d05315eeffa813cf95b83767317386bc21f1456ccf52cc983777764c02dd9c5ebf3940c19c8d4cd2c1e6366935211884e8aee011aac2fddcb0646cfb290d3f7ac0ea8fd1ec20b57f67a28a470673c4c202eb57409ca729c4ffadcb1828daed09ec1223d758548e477e7e06f8d9015df9a40b964438b2c59261a8527d0755b468601d381e60826627dad42f680f33a83027246eaa154ae2cf04ce7cfd0eae34735da1ecd1b408f4d41a9278115695b16a248cb697366105585a863b4629f6a6899d77dca911091f73e33a812f5baa98b3460edecd6cf2bda734810a7412943426e8d8e00e24afacc681379b92978ec8e049f34b22de5488e9ab25a7bd135ddcb766dcc95ee688268ef957b83130c6869bcf0bf43d606209c5071b00e32a20cd6da4bd4cc5492f435a62561348e3769093639c533570f22b9ecda5aa7c2773753211c68672101694fa491eaec2005a9cc439f773801afe423675efc54e302fdb5e09b895316e7ac8898343bcdd91ad238211e3318ddfe0d86c5ae1c6d83d791c52d9b35496b8ed9978a1c7b5dd00bc6c9697f39247238c2042258025121816660ef0c53a49995cd9b45ba1712d45695472b69d6757e56c572c0f290ad6225d35ca5e5f564ad2c3ac7fb0aa41ac346ec3036adaab5000b9c58d8861aed031b0e627a1e665c36dfceebc558f59df5b6235ee823de9d185d171a9237a20811d9b5e4efe508fb9907d25b6849dedff9e8d71fd0b2cff2f8ea8cc1a7e98b204295f267dae98a6476d99f9eb73499fc918e2db191b9decac79eef1b046e9958c32ff1c8bca28c125b2b2340f980219d5cc979eeabf2b2dadec09e43ea4bb67b136dd30cfcda9dbb611d899e5c3656d46bca5b43affc771c9eb1697b10936d6922c17baf10888d8fc10b4a891d4bfe5ead9136c4f79215c61d4796897fb39834f0440db29202211d82d2b16e69d9398fe33e22959a4310d274c67a4dc9ae6acf72abd13a1afb5fc319c3d5ae89933158c91ffc851e5e5fc854b102a047a0d30211afda1cb548d279fc894f1002c3721e3229519b560f0a71bb648149bc763b3401b9ad57704139a85d936bd0879a820f90be6ea7d78b6fe1679d336dcc2f776a3373e473ab5ee54f5e0a8df6114fd0e2d88ed6e7035d232eae1e4d785b417a43e06bdf7bfc3509bb4ad808d39ca785673436a1009dcce6cd055f10439de64652c31dcac2b65ec47264fec73581f8598f8c318bc0f8d0eb929e7c4d6e5f012238e01e19b1fd6b54feb463912e6557b65741ff8919434e44e04e41a5caadb74f3cc0254541c06faa480499326b7146499b55a2fced4dd416d5a31779c8de5dea938385217832cbc605788ff4fa96e24fdc3875b52769db18abdc76a687974925a52081043864ee8e39574d7f27fac30650eabb1fe70d5d7bab946b234d1b8ee449f08654ac868a22839924b9e7b94175e60c5b575263089b525f40d6f76570d2740095a43696a90f486332f45f4f6ee2d1d55d4b3f2311637a9e73f921a56ea0529104573b25b2c48307adcbe3b2232cc04933dae07c34c491099c57dd7e4b393fe34db10623bb35b74ce92f8b1892d24b9fd88eb7cfc3d1791b0bc3bddebcf42592093e6ffde9f40766ad3c21a67caed25b8b250946ec46773565fdcc6305803362274e612308b8b767423afffdb27239f3b9bcb8e70bf0ee68cc8a1af4e59f6972d7c90b182d862066d1b83ec044b259b398840cc736ece77dac61d07e4b338083a97146137dce132a2a8a0255d1c5aea80b5e0095b6181dbdf1fa23317c74c0e25cb86b08c4136065729777527f49f407256d36049e4c236201174b312e80090376a2113d62058b659f63de5b8695e52fd178c573ae0e14f205cb2fd929c9f09079930738deea7a2090288911af17e157d6c9ea4bc04f6264c81e4f3b5b087fd17a7c0b7eb631c1d1476ddce8be398fb7f576f3f01f98b823b7e8eca7cb3831c0ed3c036219c94ecf5a0c2d112f788d73a432394247fc0244de10e28d4577ecc084c521f0007f3a6215a549abb3091e59c6d6cd674c8e5775acd276c980033df3c2143be0589f65da81bfab1dff81e6783f814980bed3cf47e51dda6424ff43c2a82e966c7ec5b197a73cc580919db591cc522f87a561ca46753679b8d26110d1667bbcc24706633f219617f620958cfc35c1d70e034c0555bf76d9d854f8e5a0a973b88cd6096e5f3d2a72f3196f4bd42b32d6849fd37d10df37225b0cfe05c1005ff528c59352ad6e319f77da2ddf1c94b8b7e7c7a25c7cd15121540f31ec51725e71924c3616257756be8d404b53cb3091c6c3a11940c44cc8808426305550f35f9a4c5322222e661561bdecd8ace024f4c2fffeb3bc1bfa7f69454f6699d36dc42f35d78130f04b39ef392c5969a4d8de6d5271ee7a32af3f311386857fc0c21d053bae00a066ada63a28fd84b0fae439f1060a7b633ea07813863162195125e00d9c2aa7f25c11c981794cc97718f22e3cdbd21701d6f6f5fc25885be6330ac8b8266bd64a227535648a926a002345e224cb6bb4ec6767c1f1511c2c1753def927f97f9fd620c27eae292cca484472b6fe5d68aa58d3fbc772153043073308ec7c0a37c5355c0bdd43179025aa0e8d492353849fd7accf1a0acb7507f11281ab671d69ceaabbf539eae572f0015426f5e9a57e8c4d4d92216a93027572c11172cfb505e590e4d5899aa663a5ea32d5cc163ebef26c92908e15fe3c0705d06e32504c7901bebbbe7de2bb3f5ec28dd50299d941b24242ea0e151d747e129357f4fd6c98876dd0779fe40a7cd386f198150b43d5fced11d2906915937905f104a9ab5f0d05ddf227110e72a6c80a7878e559b5d8b1fd632e851633256254a22608358228feba5055a91dcfa6f702d55b8a463f0e0dd4af11872694e1b38ce25e8f8b4ec993d38223eba5dbc585fdd5ba53b179c20a278181fe3a0d13a7feb333941b59748b2b06b2c51d6c52d0a8bdcf833628cc30787d9d16c0991bb5a523a92da788563800133ac376a6feb09a8ce1de5c1ac1ce128272cdacb42b9592611e34bb0848a05f3c69e274b33481fd2b351ce7562413c2b2eee4cde66944b64103734d44e69b9187d0c98ee204f539c59b2374eef044e731b1bb3d06465f37d16634579e24f7ba512a29204e0e3fe7d89809914e41b7ad8d17e5ac11af5246b2192c833af76bad3906f95683240ea619360d9a0ad9e7e97777e2797180447e13067cdd4efb5ee7429fc5b97e80d3f9b8396b8d2df51ac47b434ee0109b0eaa22f854d4de4ada9dcc003a4a8e147ceed375d607922b59a50312813519571e2a526774b1241513f77d2b53d3d435f141c55eddad14021ccc542ac37aea8e24b9331fcceaa35dec147c114e181e9a6800f1748c3aa1b425d532da7ed19bf10ec5304900d6f685acba0fed0d7bde86d5d5dab0fe046efe66fe78b886d24c097fa252a7a9151e7ba2cf15798d1cdc07904c8f32c1853b8e79be4d344b6d8820005ff2e11ceaa7833e1de67fa3f64637bf20963bea0a981ee810562a0b8b2dd532e01140421a975d2e7f39c3988e99e5cc8116cd9462e2f405121dea5a03616d7fcad17ba0956b84671d94c524efaa13b6b0bcc15b98b6433619bbfc9736d5432fc5237b9a018b716c2e08e4eac57d2b7c33ffd813816a0b01f7d09a5afa082e1d10a327247e0f086f3360dd6b9b736903a518390b887a6dd2f5cfa65322e5fe6dd801ce6ff44388ecfcc02ab12c562f55484cbda45465049da5aba32131491f3bfd92a1f9e85fef13e622e06445252fe64b42680ba24d09d0cf28c9f517a24ac14322d57761c1d53491940ce65df7c1ce7b6f766409f66f6ab4a9b455df1de0316ea2281d48f8f2bfa74f001509e7d2222b7931453759b1cb0ef887335e62bf97aeb1fae49095be74c11f89ae74297e22a342f60ff851f43c1e695080527747f9326097ef0a6838a1f46daab1f109c4e921beb2ea1cb6a334dedc57e55e58469aea61a185933a8a4c5fcb5366487d36541c46f12d8b830ab05c415cdafeb875eb2031e154fdde2d07437c0297ba56e4416cab08544013b2728a42ac6daac513c436f3e07dc6aeee0957297b17c242e221c41187df1fe919602d84805486c0dfe8ba108bc4c5b95c300bf121307d465a3b69f99fece83b1ddba11e3a8ebde80cedaa52c7b5acc9d0417064415bfb6d8ff6ff46444a62619c9321171883977194fddaa0fb059c29139fea48955b1ceddae3ac8051923472d23f06773f49e6624a8f2ba23b36a6c574d85b40f701d705c983ad5bce01bb2d031617bf8b2769ffc90d2ef086be32b2e84cad752afdee010c8e26ee09ea95e963b57e93188d4af84a71a5224e383a0dde184ed343fc59f77620045b9d6cffdb1a89ef0d5cb7e853810f24523a211f2a2fc19a49729d02fbc51b9674783ed4c7c0ef070c6b47413681ee65934cbc65777f92d13f01879a5851ca57501b5cd016cce8e9902f4379997d5c75b3558161552ebe9eb325a3ee76fe87bfde3d2cb44fb9009bcf14ea07900a9e120367d6a0253fba1b57f388efab647bcbad82a4ef8b5a7158c3d0ddfd134e568c937375a9df0304080a5ae883ec3661b176c272c7dd87aa40f209c9fef9d07bd102818b55f3e7a8c0e06dad914acae44f9023a04395e12b1d41b7d425634c748713a709547376cff51e864654c3b24b19d294b99c5e61abbc2f270163995512a5d042d94e1df1b49bc9f2fc814d7409f97758487ea49b276ce60ba980b9e2df67e1a186a18ea60ac743f45714b80eeb90cc06d7158f6cf09c54a858fef698ffe7032c22de1618bfd90bbe8dd7db0aba29f53abf0aca67e1471bee1c871bf3595f423213645b9dd88a4153c7dee3845194b496abcc0104997fc89eebd4fc72c5ca73cb5789cbbec9cdd9cb0cf9117718041860fb2073fb3842c45cd1a8e44a295b3166e1ab0a5a18aaf22575454d4d3750aa838944d1f5caf671d9402cf331785d83c50c29b2e49d402ce4ba32516fe1b37c463359d7cb780d3561ac8c6ecf1626d33aa1b482f343086e740be27175fbe1cc6ff2f798b9cc96e2d88baa6d80b0e443374cdc7f11cda7def2a1875595f6980d0779641c9777632f7a5aebeb48f3e9d01c187695217de185ea6c99cd47b321c53c26a83cd2f749612ca143a2a3a594c2e80c1ec90d98564f2a69e579f9713c20af6a559f541514a7514b8fd88165be486e825c3de6899e97f9e39a1654e51ed9690cefd5e225602e68480e9f2346b3f8d61268dc5f6add54484b7f4bf8fe086110f74183a0bc2515056f9a0bad6f4dbbd848d80df7a24d5d92a6b6b2b16fabc0486028a13b67a2bbe17f9812ccf6692327e78a5dfeb56feb6dda38c9ff2360062cf7128f357ab4b395b26880fdf80dd889ab809da70b1f58f5c1005a3e054f9c40691c287163f445610bdf0f14e6cb73e0eac5ab2fa5a9db4a9774c135e92200c27a34aaa2f3b9e2d568d28ae69652f1a351636492a590f79df0d4f9d589ba0651aa572a6cf9070a873ce75a200506ca74339dafbf0da6add65d5b5594b5b49bb0b63b398b44ff5f996115ce0d1b6f220b7b7b20049f5fc9f26e4fd8b7668578c4dda8365a9e79db99378091b3572473747ca3b4104e7b7bb1bc22988df73cc1e6fdb242c78804b4334550788a3e6a50a17fd8a0985f2449eb8554bc28c989cc1d9755aac8b33482d2c70525e102b4518f7aed260cbc6d6e7317a22e92b776183ccd105ac9bfbed1bbf0da4be0c0203a390cb9b488ed0aaa098ba8d5ebb9659fbf19b8cbc1b4d78edae8f5f272d2bf0303fdedd0e3de90ec360fced0ebbc85d612a9c396ba66cde481b92efc7ac9a1381dea34d170791896ea030cfce7234a0a2d2301bc79043aa7dfed6f3ea7bbe28a344a274fd9b9670b70cd74379a6fa1849a26609f1ef892c0073b7db34f09b8631af1884552a234f7f37263e04c61418b602bddc8561c0e097c5767fdeddc5deabac6308e5ae1c41565baa4d0bb33718486f3c655245f26b26a12becdc95a31819afa5729cbf3127bca5596f9d409301a32e80a3b7ec270b9387e88e9e1422b9ac903aab06f29970b50673222a3460acc1ed2a6ed45d10d3b42887d803e880f39141ce63b8d3fcaf49d87a9ec7f9720808aeaf8eab0ab37ab690f97cbc125be08fd6cd41df957059878d19b106b39e06bf30cc9d3c85f25de650f4afd295dc11025f9a72a5e46422d88c01972e22bf024fe61e0dfb824df1bf44d1f77db0118127ae48e2a145d82bcb537cc4be81e7bbe0e1d3e19b56537e7bee8931d4fc38a03d1c387079b64590d1f775566cf0a16ca2bbad3409c29ca616d8f91040a3ef52bd0b7fb2dea0b65f0841a03fcf8d25a6d7a0904a74ca61835e3e0734e4addddd167cbe9d3ccc89a0965191fd70065b0fc48f450ebd036f9c15039393ebd191a982fff506847cb3de8eed4cb8074da6076302b1e7623cbf5bb1ac4d6af09fad853100eb1aeb302717031608283897f3edb7e5b7f5768a363eb2bfe951b6a9c470d9abfad6ebabd17dadc0ec021684726a3f7daceb4acfed42084e70c8e721034f481300", + "04000000821ccb50796e05b15fde182e6e3170ad072e8c43cd976e191b214cc0b1bd9957f972fed3d6ea50bc8dc07827d9314a989ff91fdf51efc2506c098a000b9675c3e2ce3df4527cec45858a7a5313b87d0ee29b8e001768bc64da9b0416a06ec0210a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025300ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac000000000300000000000000000000000000000600008077777777d80a1977000000001c1d1c0000000000025ffd47baa3f5a5b90eeff3e0779f2d3563860fd5b9d7666cc06abf31b105a8140643a0cc5b44e881a3eead60361c59cc283f1fad00138eb02268408b29029232df48832e00e32157fd299f16bfd4482cc933ab2ff4cb953b162c8998e03a4d05bb13c472eb737e2e3cff834999cb5438003c74df6993c0579033e56a1fade81706ac0a77b99cb933f66906bfd2a2402c8739f844ee72d34ba50a1e1e9486a73e4c7a063267570a483bac82673d954ab903345b291266f89526184c5633a54bfaebc05f6cea64c403025806e65d8e89cbb0ca967dbefb653063a35597715c488891d19d68a5b7f0b74ca44b7552aea2308e325c71f7199ed497deb6c755c6727993f4d218e3128bbef26bd03941a19b344e8e629d81f15559abb7f6881ef7c688146640b02a0e5a9a78e8c587006eccd05bb1d5ee2ab8d1c743391970a0cfe2da89d18fbb51bf3d6b9fb9aa1818619406b89b53200b86d8b3094e46a01a67d63ff2b113b266cd38203f05bd01cce4e4f39a0072baf5f582315a98575332523e967e353cc3ef8d1df1d26dd79e5375cf9bd93f804e4d709004967bc70b3ae79bd7a9cb67cd273bf3df4e1218ec3f67dd9254b589fc73d5ce565e106eb6c6621a5c2438fe784eb5d95efff8e3b008a63bb1c329c5bba077bc756f875acc5d0eb0d02d67f2aa04738c8c625b56c82cab932b05ae2e50092322887318df508180080e1c7b80cf66894cac8de85931e7fedef575e2f7146ecc4658ae936a722548c527593bfdc59acb58ab6c4f360bc0ef75e3bd171c1c730a51749bc95bc2ab4eb7cc3792e107c31239e3711f35b3094c207d73cb0ceea7643d175cf97ae6d8d221f48fd048236449a28b497b36ed3c817c161d4ea89b7bae5170dfc9c33b3b08f0a38e964eabde9f4020eac2a7b480b9dbc7111d67b45997fb94f4244cb8bfefd0d6326a9da5203ad489ebb4e66f382a5bf82e9011e8d3a44cd8b6eaa60662d20be380bb5f474e5f8d70585cef0c5e490254ae896caa9bdc42b85c4fc0cdaace29679ade3adb96628241c509aa1adf1bdd633850f4df4b24765fc4dda5feddcaa6de3a55d58978cd71c9fdc5bfc77b33506ff8b198dbb4ba4cf3d6d4da3db5b76cfdb26379050cec5d43ecc5edb79d046e56ce8582078f6dae1f9802665db37c5285ab13076b7910c0d230f090375c46e44b0f142d540e32b8020f271de3f8ffcd2a9c8cbc1a7f5db56852ec2e9078731d724824ef0db06e8eebd7f111b7326a751086cde390eb42268a8dd44b7b9b1362a594858308abe397b2abc43a57612f98d027afbe7a5d3035c418bc32f556c8564c0901f9aa322de146697139f8801fe1f4836a800dd0eb2033d3b1c79b4f1b630b85a57a009c887eb4faaa0ae71aa5a1b9ce1dedecd5a9aeee985941c39fd28e2412193dbcd3a941c7d20e6ae310ed6082184c17dd2fca5fb27a1985843a6d92bfbea1c0ca8f7aa583e0336cb786cf38b893deef8f5d9a7ad8b096013090ce9224270c5ca0ed72961b44a2749eb99c23089258895392fc65c6181e59bdf0284a08b6bbcac67a394d3b73185f1c454ac279da8c360bd816131add0e86431a2f4bd018bf1e558bb79761851f9b6b1c198ece4e6ea28d4650ca1f5fbf1401306709d11c65829df6ff7b6a4b8bb55921ec2a3bd146728b717f31681c355cdcbd551e6f310a85ec235ba6014dd384c0118d9aec510c0ff524cc07a525b4e80cd1d2d51649cc6889b2240672cf91d9270ce131b10e839c5ba8dd5ae0bdfc943f9052aaf4e838cd0ad9074d845312f17f33a1333c5e580f48dd93b4c013ce245e807acc8e9bc89429027b3e782bd1054c1ed0b81c6f5b54184e7c0c3289dda890f9d5c21cbf13660d4a5634777d00944d6e9a91a560a7422b354fa46282871b9f29bf0dc7cba8547b19c53c16c5e9cf9986701d8d15ac5893d6f5827bb02e0eae3f589f4fcf153515406a1804d2cf8f62d765eb65e09d16c6dd3acca553ff0083ca089e62fa06898a1859d224d8f823f01ff17a2a53d2e27ba6eb1ace30b7f9a97049c581b912645ca1337d449fef95b61cee2b825716f8db4defd52709f08214e1be87c2a1fdce6c3225c10e72b0e8137dd99e2080a033af6eeb1ab4734cd25b822c7b6ab2060774df62fce9bdc9d238b679514b336dda53a630aaa419af1b4df7489bf0fa054c82bbcdded5f01eba9137164a023f495ddaaa883bc42edcc05c2361488731d9352278c9f9075197db5e29a1c87add4cadfe063c6a072f6e1fa9f8b1ddb2a5e46c7b3120627845eb9891cd09b299270c63f0147376065b406b531dbb2283bfbbd7f793de7f627685263d89308ac3896d62920ac548a7f97681b9c0b48671dbe6b6cdff66b3c80dd90b7f5aea8f2616a57f0c47f2375f070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c4e5f35dd019ce932c8d81f52f6ac4b4c7ad62d1513e1c5c445d10faaf17053387812744aea4097a7d1707dd944080558fe3569fccc6920fcc5edee87764c76b69c14f4fd2f140a5aa80078ac3bafab06214182cd9e26ab213ef6a424b4752d8b8b2b693f46bdd24a46bea270af5a4ff7fa74189ebcb1163d359d3dbfa7042509689bc397969857751feed4314241810eeccfd63998768b5a811277d852abb5a1e88196c0e6f98596ff2ecb67af89c3dd6568a4fc2e495559d85d9a043c117615fdc8135207ea0cac2c99648e6047226055013ba411abbe71fed3f3fb678bf99ac4d44d51224662036ac1be7e71d203934498d1f0489bd4e9f8463ce20e381a31cab6da793065a53353682f60fa162048ec3c278685200128c45ed315900a3111b2a3f36810bf78e75a36765a59b3e618177b61f6a90944e0e5973a573c9f048f17f1acb7a5e29889ceaa14f78ffcdbf9b83a3a8ee5233dde72047074853d78a6b7f5de7b73d0b861dfdedb8f2719ac647a67161803b611e5b80338be8f0012bbcbf1f5f05558b742a7d4271865a4e3c1fe55489ced6624aa329fedced737980ebcccee2210078dc20db162ee0da6d8f12d6293b9079bcd29416068e738f129991e084f498a98b41c4c7a8430ab26e0e06ed6115ff86611a29893b50c4190322ab26aa6a3ea878671fadb3b77b694dfb541dfd52d8e199569c800b003931def1aa79159208545edab077606d0f61947a571b6e7c0551002d739157c6f5fc1fd81a2e7172e9f480f0499f9162ff55146ea147508098c2ae0c723d8f113a9fc8db656a25264b4d4f1ff86acaa7498f351934e3fd113c2f8e45488360a40b0cd1e8be9ef9c323cad2df8c077fdb1ca88159d3339818c557e4ce14e8efa0a60f9ec0e474f05cf1478643238fe22a7ea8c74c555d37bb9555e9e733e07cbd25a3446847a3ed44d0390261cae0a92841eb6c49b20dba2869f3cdd0f33754e813f8b270d8d7c8c7a605541067e929ee330f34ee19f5de779bd0d74c4f82d97e0d794afac96f3184bf7456e8a6a1ae576889b198fe9d619425b3378e2b8cc97caae0497a3730f2adc1642f039a99b7df9d68e080e9ae10dfb93da507276b50644d8a963a0f381f5f2970725ce544f384ef4797e5cf686a0e242621501b3b5b58caeb4ce31d8dc19de210ac4744180a3698c1ccd5b68ba48edd1d242764e287d1b22262ca260c8e5d4c031a798684aaa48b739b19ea140db60fcc23cd4849deb5c3b3137331f2504ac002856a0e2a18bc613f2de3b0b615335755d9a7de9cf27d1ab273b93c87e0c03af4414f1586512fba9bba193ae17f636dbc8f2957bf28f31b2f7f53d3e4dd6f1ce49137a89a55549f23445de2650e4f1c00b22c6396c08a49e803505406be93b90080bc7e1317a4040810726d775090a6b8ff2ced7e1d150b21d3990d64cd3f943db519722fb8b4bc68656188e109fa6670235ff5f2261e4819b0a3ba1d15be9a6b39a07f579923924d4fecf753ff918356801b662ed3071753bc110adf8ace113d4bd09634b88a48095caa9ba92b2dc5bf8a59a2b7964861493ab25fc0e588f29bf7dc2b08fc95b27d8673685d313551aa6869ddf013253c6ccca39ca9bd71e3f31c77efb8b7a8a5d05afee6d24c027e0ceab5b3159632de281253ec3bbdffea8a9e761b4f1ee56047dbacbbf7d3c88240d18e4d2f625e24d2fd4922f81cd50895c276a738557723711934ea1705ef98a29d87527af74fabf3bee87f2813ded83917d8ebc2890f9dd3fe5d988aca61f771aba9df9455e22fff03e8565feafdb0619706f36b9dca969747e4061be9248ac3a23add9452f9830849e3e72c8a1b13873ed3759589e03f800f9209df6ff23edfedf91fb8eb35db90a1e31305ba079f6cfd6751c036a050c091081a7cd92f6a0b9099e3deba523218be28c11da50788de3f60ee17d78cb8d9f210365f94a9b938f37a5f4aa1c1637c596a04ac232242d6725b6b49b12208d10a47d8264c2346b598935fe0f43eb56e0361eea0a8a631562defff77b502e1cf0359bd42f1bf330664217a637476406e402ab0bcdada496cc5527f74b911a96d7b4b927a80fd918255830fcda63832500e53c4b5cdb90bc83099b65f18f4b84561aa54c7d2d969aa3464eaa220c59669baf9d7e08216d3b33c39f5573c41411f1a0a10c43eab6cb39be9baae5f828ce41e50352863a60c4575a4863482939f2d3e2db6414b0cf533468ca0f547d02030ec80c58632311a48ffe647a6ff5bf0defddee45927b9c888a8307ea592a3037261215036fd0b441aa141c7356d91031919b2f8e2f92af9134b9e42df419bd91cb582984da871da855643b4ff5bb4c5cd16a773c99688817fdd76b7faa1b0b1341de20e35209ab6a1016197fe373807f9e406214c7b9c0ae7aa8e4412c7330f88d053056363d0cb4ffe3c34b05727144ba6e418ff0c5236ff9a4bb716986c86694990d1887982d0d8c1caa1c471c793cea11b5fda1d346da4caa12e74f36a0fd8af52d743b9aabb1262ca1295342cef187f3fb13c1e565f7bb85863f86f93dddeb2613dc2aa2db4259e9c086ae837c4e8655a7e37a6e3801c6811718bf76704804fe276aaefa402ffbb5394227225f69e1adcc7556936bac642048dd86b35effc30b0723034ad8fac787a99022903d8b074cf8fdadb8ed3b8cbf75006acebf1d110534f3f533ae921c0b78ce67452adc26124ae25dd9bfaba7d4914b379360a812813d3f5743f889a442d4b6d437b1558b97e15a5db16296f36cf499417a484b4eed0ad96a626149a4d847df37d7a88f7e1773f89a26ff26e90b930fc2a8494cd6170479e0457a55b481b045dddf6e7362c99ab049d097d3251431e61242c819b4d22f70db675f50a7dea683a71b66f7f91c6ecb99c019d207a6edb7ca4f9ffeab7e29aaa723bb87f14efb2fdce5eca874cbe2e6f8a1801d1f7faad249cd9bbe72913f121b8ac6fe1446a0b182d661b0d8594f52e971955322c9c6595840aee5178518853df56c9676206ebaba2aa04f8a20960e2b5cc3be71681e85d686ee75cb2a39cb9b6eb6b0933f34a49487839995931a1c0c4f804c1f9dbc45c9996811926a0e8f9cddda2e7d6c946d70ccb58717660a1c8bbc7bdf868849de9198995148b210c81081f7515983e9e7cb807dad9da48aab614439811826d84a1f97515f915109383260e314f80fbf1f5606509db8f2103ea1788570dd8d452a8b2dd13fbf1538fa9cf2e9c9fa3d12362fa93d496d1d770c71516c794fa7a442c2fb0395afc70d900847ca74b989a9e400d3fd4c5ca81c2211c856126b72a296513fb401aeed0892efad767e23594b6c4da91e8e45779c76c6c94cd9a02d0adf3b9ded9bed2520064891d9fa14d4e26a311910148f057bfa59684b73813264a2a901d4f953040e2a277a15089841f12882b2e069f913787a37f7f9671be7747f7abce6a97e16183d03c5ca8f71f38824c0b2e197b57f5aab474201cfe23f90ca1e7a4f11e3733b1dcefd8652a7cf727c5ee648caaca370a20ef0e658334520c38d3c78870a9b3824ae09f4d0452dc5adfe57192007c4ee608e8594e7bcb5a8983004f2f0271b1a129b5c0f9a9a5435c9116c86bc33b1a2cca7b104cccd8e96a31618aa869f011056e5b876f257bf9557381e4e812ff830ed34ae2bfaab746c49e65b0811dab906967440a6850c570aa0a80f3bfe70996d14a1a9a3b356562a2bed99c40acaf107eae6809d0adfd64bbeb5045ba87073ed5714a13839906f11a0263fa078420606787ee1d0c1fd90dd8cd8f2f1c796604d54826d472df55ab8d72d20fafad1ae39c3dbf0d54c1b38d84e8ad9dccf402c27448364a7c30c169367386b9795f27e0b0b56b00facc89636a1b1391ca960f8e0fac566eadfe44aabdb359c9efa8d3d331b2b6105d5403730d9d180a6c65658565a1723d858425a078e6cd8d9a73c3e1fff7f57c2e12ba17ffa065efdefb1b78bd8f9221aaa227eb21bc4dec5d0d01011711bce5dfb699f2810f2fa15d955c9b71934b28e2bc0b1e37b075515690f870ca8324ffbb1ccce79a1fc706e78bbb465bc37034cd5d5dc6c390f1b41cbfb94256b64253f2f43657968313cb6908d8061db87209cf3da1050bb8a757dc765243e42590255037bfbec6701406049e81a5326d5f423a0f189ff94c32a333221882636fd5b98cdc9c14731eb93e9e3564b3b93ea155faf3eabafa21126a0d52c8c3b514080698bee3bba11f5ae26b5d20fc7f0ab3319bc5d6b5ff6d63a781cf1d02c570ad8d007a7c27e495437a2f6fa86f38e9343363ff315ebd95e23d57414a50dd97bb934b3ac9bc5b5cb6742c2f50d746590cdbec2cc2c025a1b6abcac53171c04ee700a6ea6096d462801d172680cdd919b21c80d7b0730642cdd53f10b420799c09b8e03e5a0ce59f1870fd90a5ea31dba28da6d43b278b39f0edd2d9fc82929e2f41d737dd9ad010c1bc06ecac08030713bbf9abd30e7f7bea89bf50f8020530dea34e2127c58e35d9268c1e7267cb00bfa9ebdbd929d5eb0f686d8927f28cd8e2d6487a99523fb8704f426d68d27fd8e843b880d5e1830d94c66537c36263e231c78baee3d32836658aa0cfa222377bed6912e61c6bf920e28421062dd1df2ca1fd3524ad599ed2ebf7ea512b7326e2b86a2724c74977cbcde823d5f1128c8061a4e6edd0e180ff55de5b77f37cf6c7b50f1be0b4d1d8b6ea176e14ef03593024fa9a801677a3ce854d53fb7dd0041f47c5c466a1ca103238ff5648bf52fccc159b34e16196d3e91ab6a92571211f3154ab9b44e25d546c0539e2c59b428d36e5c2cd272ed254500c49a6d09984e221fac248325ad848c01ade7319a3520c83cad8fade9995048fc2e377b91a0522200c1d3d38e54ce2315dba3d792c12d6759f17eef0edb7d502572f6e3f1bbddf2002e2807afe73cbcc481572ed55f11b920e0d25bfa52f10c00c175605eaeac91308d0512e298a055e05de156f0d633c3a0c73525e62d7e5c61edb032139f9aa7d55902a0fda39066fd662b782f4405041e3f54f29781b264c4194d1464335fea1e618ba2a6e5ba4b62c8a5f0d694254379ef615bbe3a66d75cc329f68aeeed52693d63a0f66f794d700f72d2edc303a6e57ae7f4c0987da01d7de8c60c263ffc64c01a92dc1f4d066e525ef07c602af211d442c45e23c1f78b9060a95f3f102b3557dd3fdf5e673b02a23f81d91639a936a656c0c877ea8ba7d235c78a91b09ee51db1e5e9919cac5febcbd39cb70c95ac9efb1c547e9a7f88399e5362dac5136b3fb3581cefb79994c01f07ce2434d891d7831fefbef2bc7983e7dbd9dcd83d8de60d0c68536e8fd5ea14f5d33b27fd3e2ba87cce7f94d9421210fc1989758efcfd4bb6ab8dac93be06477bf57c02840a3a6c7252a91bd612007b1e0568b0829ab2d41347594017d337f06db94c11c35ded31fa365b0874cbee6000b9ab06eecddaca8d0c8fc064e4ec96efdd9e2b6cc3992bc48220f8f1f6ef697063d0c46a617246641a73c6c3ab3d26bfaf8706dfd89adbee69abdd9f198419b0ea1e8510de1b92c616ee2eb2725334bbfee90c13fb8742087c0c70cde18a8576166601332aa002a347e65452e2a2237cee6705cec7a1e2425fa6044339b63bf5a047ba52a49ed6bd1e88e4d6ffce458480df30afaf3ac08037e0dbe7a6cc95c7842909db75c6d8e1731eefbe358d7773c71b1aeeb77c102780d48018f417edc1429ee3f3d18cdba62e6b0b4488684967e79520b4a1ba5a8df08f892253e1fed1915cdd201e87d75c6d1d2554a99a341e487a1654eda35019c7c38c86f5c75020f7f9619a61150d213b99b756924f5f9895e71f49d172a31028270f39dcc1ddf929992a516e4c270ac591674e6ba2c13dd06e0b506041e8942778deca31ddc84f4262ff4ad4d81e531cf16d4d041f3911441c12c77ed92459409ab65ed1949920a684e729d0904593d7a42ffbceed454a9cd23eb7e1742bbf6effde398f122a8443e86c272fdb97ef9455f33ec1161b73013800c40bda9d301d96758c6de69d103c430ee0192f74956b3d73cdf3cff36850d0192633385b19d546bc8f0b1f9e3524757f2d4245646a218b78e6a9f4e289b7882910167b2cca4ac0b90203e5ccf084ca174b16b6c0570f6d9c4e5f08815017f92a4aedd6d5cc3f40a4b9384a77405efb4b87a15caf74bc5d04197ca425592c0900484b814b3d1926954716e1df3b7017a22951344fdf52496f797562f397be1a3ef6bab299a518e7ccda7e5fdd166a6c3e94debb1930febcdc609b93dea783be0d009656909f18ed83eeac7cfdb0a5954dc8b9d604db26c6904d8ce0abbef49d005d2b718f92cb54a7adad0d106a0400ba35808525068312f938a58963d7266f1829495bce11d4c0c05073ff5a72bb508eee9fcf3bcaeba833bd03edd36a49272a1bd479d2408c272e3badb2ff2e6e036aae1ed1667b8bfd538889f705c624b93f37293759a9bc6b57833ea34b0973dfa3171bd9c81715bdcdd39a1a5a16645532b276af5eb53fa910f837f367301e75c8eaaf25dc6842212f5a43b71a6f76c92d600408f82c64dadddd2e72075a070e7e62baabb69fd006132d441c4f184c5d0f869993de13d03ae69b61956f37f191f05b24d242c23bcee76e5ae1726a296b1b15bae2365e9379db640dfeda8d9c7d12a653252a104891a78fd4aa3971af9731c00ee4e0c2f2a4e4fc6e50d67ab75024acfde2fcba159829904f9b27982f2e251f941d897bcec7ce91edf7156cb1754e27813c59d3bfae136b5fdc4ec32e7f17f5d4c4d078f68e91ead670d0cbb30054f2e90fcdf204ac0b99c8c435d932c10ba9267de7a61d791731e0d39b6927f8d8c4b395e03f239d84b717021375480b2c36e3b110777eda7b9e67fbeadb56cbd75ae21d5bbe2f95bd5a2d21ec1a5a403c619e55e46f332c9f98368823f03e4bbf12041f138dcdf2423400dd940062381e75ed02772618afbcf1bcdd949e34afa5bdd0c25b0addc12c1bff4e7faf0a1608d0a36b250d7997bb5711e1b6c74fbf391bff697982fa2b388f1c1934483517257f23bc65aa0e32b5631cb27606e552c49d8376d70c7dbd53570b8d92ea893d3c7b1bc8f62c174ac33faf08269b8d173605aa9a18d81fdbec0e392a6b0910443c504165eee0571388028e1512b8384f60cfcdaf2ea17b7e9c1be172676062a02de0409faeb6f0594e0fb6e696d6605dcf8a5be6115589e2322d7c838bb06f7908aab838bd06e720a051d07233bc7bda3bf1dd16820777d5f57d15d8ce486c9c0081681824871c37c137be3355e8587d12417caa506e3c14caf7a1e9f2d94d6c15e4fc132b2a62f4fef4d12d118ba9d39313a212980dd0f4d7a177cee3ed87f02812f6c2546004e10249c06aaa49a01657c7c7d2ef5c155310e2b69bf2e2b5ac3beea29add230e49ab31149447760e2c54745a77fc33127beb384adea5efd15e17aec6db9af767f1c1d5d7b2cb07c3b193acf0ab44c5804ae5c3e382538cbafa1ddfc31f1448eaea7b0a7504e9fc5256e4dfff39ee61145fe246856fc4fa93d22154068a45c9c12234f6e4aa3748b0a5418e4992a22eb18bb8033793715318370834424065bd4cab694acffa6f0448a61844d4328eb406b72b3c9b2b610b5eb50007bdfc74c7feade19a2459ac4b21856868aa06a2d175589dc86345b311df552ab8a56a724630d565e4ba55a1abb0946a0a8d6e2bc453d4dcebf1159c82b98816c8584ef251cacd77c3ffa104ffbaa96a90d876145fa73fc5fff5f5570a6d8d1580e1c4cce5b5f8e8a5d2b1d20b41b4009c79ebfd4a8e1636f6f93f12593f0532d565ccdf90ed011e0ab0fcb3db28f10535ef5e93f59851db610641feb3bba4190f3074e4257bdfed4f05a52c98c380a471bb3b952488283be1f14fcad4a3d219765b4b2b3421d5ef845f6c7b9ad6af6b66a75ef0c03ab4f2c5150c078068943d1e89d298524d9e9cc5b20c3bd03d89d7a6d3cf30b02e17516e0001b071b92a35d245e0c596071fb8dc53e53159eead8cf86441e0348a0a951d4a2ce30274b423bf3cef4e5969077107e166199d2c5714e25e2e0bbd8db356fcdcfb3d3b8b04066c193c83903ab0f0eb18d2faa428f3104af484d07a96e43ec593a5a9bc6d9c2176535fd5727a3acb3ab4b2e9e9a570f06455bf2b68cbe461743af5466bf7f8050f5c7710b8cd086922c098d4c9c26e53708c5523c0739705505aac79ef65781f226761215eec4cb44f8317b2fffdb15dec242532c0cc8db35c117a35278c54034cdb69bb5df20b8cc8f1eff23bb6e8b929a130e44e0b0812e937fc89b3de0a13afe080628083e386b703ff58a07fb599b66605d12342bcd8fbe69ef239f3ec30bb2fba014ab66bd3344d60786edcd434fd3a19f46353cc0c7901e051405544028bb9dbb1ba427c4b6e6b5a3ec8a593f0832d6a61692d72bc6faf044ee5664b1a7b5a3d38fd1a1b436b833287a162ae7851085a1f63bae8f2fe18b09c603ff33bf0b5ddd6cee3a4b4275348c9835ef59b44f2db1f828f77d0b7d8df70487c91205dd731d9d516d9cb6fd88080f45312c10edc4cb8729c7e71fc9fa87808bf3a3099918984a60eccb1ce433aef537927236f3e0f59fc922b0ff7d0b39fa53f7c19b5048f8fd2e9a3cbdb8e6d7d156b697bd7242355bce57cb3d94d16a5f9adc607288f3ec2641d42eb3303e0344ffe4e4cad5d58be766687da989e8448a5cc7c1ca4ddb0e6cb4f4d22104b1d32f6dc3632fa7012ed5e9d5a2111dcfb62c7666e1bedb86bd966f9caadc2ba81da0488c78352f7d3ad94f35fb75a12272754630a20e42a38a52c4934c5d3bea8631f590e31ac72b485478b7d8ba786e2bbdcff8d22a0082034283aad9f28adf92604124062230891d81f71872c135d234bcb76e82dcfaa6969b84c9171805683b4a419f41a830bd88a76618ae387e3a69254ee920a1375d8362b4e038a2e2b4a98b1c181ae9e5f24b19b07c5d46bd50d0e1e37502646eceabe404904f3813c243675a8322f853d45614c7d56fb8667badf80b87b10ca9d2363e37281fbebfaa303a7366de81d92fdb81edae1f057fd933523dd0a0b88f33140db7acf9131d23420c2b976156d2bfd785e9c8c7c7a520abf8b58d204ef04b5f5f9424c5f305ec6d97f582627a9f7b1d124dbbe6bbd4a36340292b70be4278a0bf1833f90bec6598d3a85fd10c37d2c7fccb02e440deaf2f191492c242d84f09ec1e0a034843a5fffa7c63cca1be0c6c378ce3ca56bde144d25b52412b27185ea5d4a3f4764ee54f0bc70c489f6d81e8a9c7208638f9a3a0bac5ff8b857a74cf8363d05ee1d8f3a166cd50701e0fe692879ce79a3d691424066b749abc3e738d5647bb844731b409cde36b48e420348197710106d7cc0d216cdc677b81c4300b93de75630c4b3e117cf10b678e538db372b2304f314a19d41b5534d9213d408155635a716fe42fa7a03ad90cf8866c124e99a66405883e8bb6f9a502937e18db7c266d8cdd119d12c7121c580f83c2be68d9a65744d77e15c337fe898e1b2fadd3b48b4e03d08d4cbb2bd50f567c1913084eeb5dd249c81b71a1d3a20e2c0d6a8fb7f2099c60904310e9416d9b34407ab6d32fe2bba4cfcf688c5c92b34fa937b7c5345fc8724085c893a5ee567bf6e3b2c1adae130a72f2a3a16d8920cd7e6b93ddd1352a13b1505cc0cf4b00a3ae34a00cb2f85591672068027403537fd0721374d5936ac968952ce66bdf64318c927bb6c184a880fa15e384a3112b78c3969161d05b00c431ff94c55f794c150ff7bcb35265782fbc6ef4903632144809ddbbe3d801f67d840f06a15f966775826cc19fd1f431d9b2dc8b552ba3b28eb47a6b96a038432ce40c84eec8854e48d1172af6aa5719778915b64cbf2bdfd1df50cc32b2736181d4664ed8bfae97f49c20e30bf9c4ea8e67b53fe74afb41c63b12c30eae8c890a5ca1bebc6ea3d553f500b755430896246cf8f4577b3975759e150ec920229f0909348a612900466b5d66e5e2d331d6d9aafabb50bdab70c93cb2d3f6647ff3e399e06946844e96897d74d22795ed647aef1526ccf5dace92d9f5578c19b0d4747d50ab9442ccbd04807a28a35e0df84cd1d4e9c8dc025717871bf8a9f9495ea8d6f6d1687cb1b3c2a6ccb25924ea8c6ad9dc62bd510325df9f6c52c391218b8fb35468e6a855878f17f6d83f866cffa34a2d1f3c21e17cf28514bc1b80740721f43424681e4b421367c296b90a75a116d59c3bc06aa93cf2d809158a67ce2ae3ce452706f919af9669e0f7ed795a3c0316b4ad876d292063107e29e7374826e95233a7e66a89cc7fb4a6d96487f2f2fb1d68df0c0092201b68d49a7d03461d3fd5927b89fe693bbdd3cd201155aef2f533edd651b1802f530b807760dfe1b4385c3ed4000f6a8118b0a3df4c412e79944e444fe063d340f4871ba816c772ce322db4e55348b6e5046b1e6cdb665ef7731e4dc58c93a21102ead248952e94d44bd8357a49f2641bb636285ea307eebf48939441ee1e31a03adf3198df993b59a995d271e9b851fdeac457d6355f9c207292515c0ac2b3801c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce9458607000000000000009ff3604b2c9238c3575aaba36bf28511d83a0aaf443d53981899c20be308112327ed070500b374e359a90435a60363235ca445da700abc2c3b962e89ddae2404000600008077777777d80a1977000000001c1d1c00000000000234ba607b674dd1faf18173ab52cb86ada65b24659b7ab0db262a4d46ef6307813610d535a38b024b19e566c3d73cb49c5dc6a73457c658fa61aa19c9a669d70823c009c26d2c4c5949f83ffb187b8d03a7e05970d87668b9ebb172e5b44c4f300bffbdba179aceb954a3d6da0cc8e9f59587e9a4ab1e9578466bc9eb508b791bc0497d33ffab8b845eed45ec6d6d9072da6064b0afe5eca2b8e3caa4801e04990e2ce95ee1594a1f922a2ad1e0550fa5268c2e1486785a68ad25200e0d1a1fff176fbd7f928197be17c9ea0d4b2f1987cb4c5d4e62ddd8001803e1672d2509ce5607d0ada2ebfd792a4eada56d50babab5b04f4999d97a78f2fc35e1ff001aef6c11bca252ab1f6959508604fd29f29642562b862c9d326655c735e7e9ff0e5b539d819b0ff9b7594947225abffd69d94748a59b5e4798eb4f0d9f41848da1acc1c42ba1af1a4e69227887f00de8aad96af6043998f72164b95e9157ef40f3253d38dd577c636fb694a49fbbeb14a153d3615454c5ed2913c49454efa45880b7e81c288c34793ab18eb68dddb3b5eb8c6f9ef4889d0fb8d3a2dd58164e5edb536fc705b63b194f2dcf384c026004d3aff29e11cdd17ac5c71c26d30ef20b5c157fa9c1c4b33d9bb95cc5882bd36d990fb12700baf432d820f66283742ef447d962088dddc54a21b162d0ed191f12d4b335b4227aef5583bd2a7639a275dd3c6397d11baf62a2983eb982d0d4e5bc64f8bdfb72a5b7f99c81c4af1395d153c9535ae61358ea5fd933e1ca35dfb4344a3a096236e9c777626575f9773f1ed0e64c7e67616b36b48d9f481453f8815d4e48601961cce17d7e5cb37be71839a205a208fd7d35652247b32d384453f30376c2b0dde5d64285c86ea396bf919978de33d5959c7a2bf9fb5e15da56ba2b11b805789d994dd44b5b39952d90bb9cbe0209c63123cec7ff2f2da1c1ebc0930b0e3a03b90dd6e58bf83187e7b71a9a5264fbbfeb90c57647c5d6de4752ccdf657a95007a21a6d8e4910ae99c90e98bef3ba13ae57614499747369bae218a8fcbdf074b48a5f374f74e769d02af067b82283116764abbd30fdc9923a3995d144bf1033ab26d3197ab184748b4992bfb51b0ea22cf3bb574236f2209a2e1391f153b706d5b7640e8a23778332fbdcb1e35cdee0bdfa55c35b02b793b6f2fb01893363d01388391479aee427cc977bef4cdd250e78a7f0f39e711aeb13be5f9a895792dae2657ac2789d2f0a5b0b7a9093fdafe072883f6842e377b05a046488db93fc23002a40a7315e284aa164b2e144cd5ffc6afc8584eb5d52b21b48a924e257b72a180792eb6f8f0a5220c0db0fdf5f5d0a0aecdde7f194e88369ee5d2efda82edf85e8d20b69680c677a4ed53eb33475b9beca2c560386cceb4ddfbd30292b111c37530ae6ee207b87fe5b67b5a90943e2a3c43c66eb8f9b1b006fe008f9da8791e71915349b9a9652d9c508adab7668438eafbfb46288de70ea1f96a32d36ea48e0dfc3fbafa1ea69d28f2b3b1e291a02823229ab70510e1fc102e5df0f6160c7af5ce67e8a6dbdf5e486d285f2b4ebcfcf2c10426ec94e0886edbcc0727b0703ee6ba3a1f7d4a5ceab9386123e531cab919407eba95c72314e0237e4208e22981b912ed9c2b4cac88a8592fb62d648846bf411b886a6b89b83ad03210cf072b00019dc6d0e541b6bb9a22ac9b3603ac0ede0b27cf0998333446344fa2cb44350f9dbc5d557cbdb74d335c6bb398ecd2eef9686763c1f21a34970e810a8eff7b37947fd455ada6010eb00ed5f1f92395ff7d1fa77b05beac74c53db704530f54a5947187366dedae6d48386d68c303b5eeac6e4848607890ad4c4ec6fe25251b4727e8cd22d8fc8972840fc8d5887ce647ad628b298e15f9cdd49b917887e0f8e8ebe0312fd04f3871c68f402f8dcfee60e81283a66f1725ce579861c999ede9f9e2d976a83253ea608b66ccd6ac83359bae0d060adb0f5573ca385446cf54f14fa3231830ba0243fd574aa8ab787ef0150be0cb9c38970043d6fe200fbb6d03158f33f5e3a811887ca482b83122242d228451449593c8dfb33190298e873d49c01b8d0b9ce8851e60e65308325bf3a934054fcc53e791fb117dec249e9836d466ec94188df94077762d8c12e8cfcbac6a9af9741395ee566c26f9e5ef21d7e08a0453fd22ed3228f9118bf2606e87e0e0d1e495075f348b16701162640d2b805fd4d2d3890cd6bfd5afb790ee9163e30d55f8015ee86b07d063dd0398366e4cea8379c951160896d3374b1c39093954117d7e3840715e3018b917c6ddf9c47869bb01a71793b2d414c252cf62e9d781e29137f59978d39b8ff60d45540bdd2dfc73dd0bacb811267b486783e9e9a0d0d5a2a161e082adaa070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c02f3f899fc0cfbb1beb2f0a6b1364b43fbfd5e372a1b64b90685c1b0750cf93993917608f18aca5ec561fec653860b83841a345f03b0e9ad5360c2616b8b511f973cb8eaa583b1e65825fb0cde26316a897f759b9c79d96d4bcaec217948791d524ca3ba26457a5b6f5278171729abc58fcfc844a5e2e9ff048bb334bd46692d97beb0e892e144acb380a1a2810048d5b4226ce2b4f9bd020ae4b26ef3d03419236d3862dde808d4fbc7187da8d7a63c5154c369f26a905f355469a0db4e562de2ead4d75b8693256748db27c5d041f6bd93bc97c7cf7a6f2c2966c29817bc398cf4a61ff5c81b66a7c725dc820e24ccbb2402b16e8a5a9e0d676193924ecb3a48bed2157a84205b689c5f673b45f5cf8589d2e048366b6e3ef58a6cfab7781e90d5f0f2922fa407d0882daf4644908abfbc5da2bc90c09be46ecd7667947d00094c2024142dc31a072b758c2b4c5306e458256fda993ea15295f970f480cd333f986e7f633ba84f8981266e9db3b78a3fa87052a648fa99c4dcb5d1420da4bac5c6ffe822276ffdd6de43f39987e9ffb1562c8e136ec163623c1ef0b957bfb67cd4af92e6433d2b3c757be0b74d7053fee3d1833bea1b076b4e2e878b68be8b661b0c54f6cf9e3bec410ee0a65c0371b4cee0f3cf196d88ac4ef5ca02a42e352785e77307367dbdeb20cc0aaf0be2f72ddb4b12cb9d1e7ed530eeef35a44daf8d80446626e90ff4d6705317ddea944a45e094901680b89133957343b5209a0146722d0d494c9fa805231b072740b15fdb7a1e0dba39015437cb2e61f0cca0179c0128c874cdcb3e4c377925a097d46a2ea86ebcb2aaac4e69b8d93f3f813fa110857017ec1126b0f48e1b61ef1ee9f2d3288a1ba037b28294d381855a9db1a44f6aa83f17773222761fad2add32acb500f060e76600b50779934496796f4c86114c123c55b42ce44d600055e9e249fe7d5f1a80f54d49e5b0dfd71518a7669538471b5e759dfb425c51d742df88cd4237000e0989d5e554f698d0112bd61a33a307b36b22a76aa8e2938e884191321c09c1d90a5678e903a5b76446698e5031233ad87218bf81d1f49cac719c2b27afcc4a191daca45a1c9f51425cf48008a1a569e2adae4627c233bbd024ef0f7c3973ba5bbf9fa0704e111223cce823d50b5d91fc0d805e0bc51daf91f0375b6feb67ed3a729933f275fdde5f8c1885cb9275fbfe2796b9cb4dc5d3eedd1044ffe62bb5a4f20c0969ecce5a0233c5a7740f9f18ba0a6c9a38ffe4b0e5377e6e84e659ece4b09a516f1f5e158f633a18b527ae8cb2813b6fc27f5108a7230bb2ccd25f9934b0899ce9c8cb3d5afa146791b52509aa6f78f02904882b0730d1a8630eb2c3e408aed611ab9cdede995bd2ab2940dcb74cbad21b1a8c27bcdd2b3758c61e5c0d271dda23139fdfa17fe97f19358fd6e4e6efcf71996b359eaea79979375a010436dc45f4ab138d7426f806450b624c14febce156041a32539494b096a3210d114d203df26b1cc826fa2946f53b2521ddeffc30550bb2d26dbd6900c912852b1741e76aa7f77b6c4aaafd16760429d5ce5d3cecaa3e1ff1d3399dd2e4bb0123d668b63b61bed7b097daf5a4710e82dcae3e2db6fd652bcfa527938559d83ae86982f26cffd2be75bb6f842883ac73819dc831dac60616f3c85011bc5139d67254cee29b964ab71fce45fba367356f2122a61544345df6d07f423d13bb32c328125323ff62ec30d67cfafde6eb20c8bf832b8a51e3de2726ba66fb6a0224da5f79286ab7861dac4d7fcc85c62f85fe476216c55ee4e5ebb7ecd3f642c547ec45844ec95586eac20c1834a5abb0ab3901c50deeee97ebd64d9980c53e0b8ff88e2273331b1484adc54fd459eaed17ade204477a17b54cfac56fd8d05f3ff4edc2e473295817cc00ab5c34806f1e370a9f97dc474e0d4e6955f915cd6d2069df587eb0650c72b4d2454142230623070f6d21be2bdd0173bb0a959990d9d250e47a2148b42030900e9e7014806e22ae690eafac7a2b3fbf45d6b51dfecbbd21993a12e057c82425533990c8b5c238a6d329c4c41387bd693ec77f1d6d200f17a86063111051f7090c2bfa3ed2a58ea8d22015a2cff83e127edc0383eac49c3b6caf9b5e0ab4abe911658ab63925d60842f70fe83f9ce4258bb79b6311bff08b231078eb8eff59e9dbc955af596ea7acd15fa8b8e1ba88e110ac383eeecca4340797afebeca8fa7c5839a3a306d4bb8004cdcd0372d83cf4e2214394cc2a09252971cd530af7802ac06d57fa0784500c40581efce6bcc497fae84e8bbdfaac727bac1cc0d49c0fadd64639c6c839f6b3e4735074e5f2cd2b5fe6fc9cc34152d723f1e1ef3fede91d41cf39a8207ad69044d14925961ca8b535362da356e419de13adc49ddf8708b82e6ba3b5609ae6110f28333601eed005b94b0d31699c8a687ae732b7d7bb263081cdabb462241911bba94585d0e20c9b41f4d8d5565e70bf351ea95382544864f4a960b8850fd5095213c2bb602338ab2a3f9b1fd97e8d42f68f2f943441ded01beb76f463997f1709e92c9e6df0341cc64ce46bee5ae1ccf0037b77ea00edf62f5f545d16bd063bd9097ef8eaa34d9dd1cb7b2d7f080fe56d14e4eb521da00c7c1d19c13e934601f963f80fe122c184cbc0047fd38cc0a7b4389debb41f44c7cccb596c41936e2fc672796877e1f0d013df6aa65a8d39c60e49eaaaf4bbcab70fa97a0b864aad214ba57bf5ba65abe585e52fec23b33a8fec951699fa4ef19e4af9e7c237248e1f4a71e6166133b2f1b6949d70f072170002b3d38dfaccb3843e641e85bedcde02e289d94ab76f935ced360b5b4abcd503d274923c222d757f8436e97156e067037c7c984ebb22b836bde9b5aefd12b6f079dbab91f69bd904facc456154ca3a1730b6fc7095af42e8e20d0b94ee3c797049971d28d583d5d1d7b539e8794a7710c2de9d2a9db9e6842f7a6a410b9df0f16fdf6bb58c35ca3a7d44b965f04e5e0391f7ab9789ca3f88973b59f50cf46f0d472e4cf49cd81c1b05d8640d625d601155db952b3544d54e5742be75a4bc9cf0d1084bc141b76cbb06290971fa526001e135397dfaadbb5865bb00fc424700901c4e50c7aa4db925b9b7fb0d8631b311fb820bceed1f83a6c166f78819a059017c7e7bc0b134aafbcb063ed15ff67f165441f7015d9a3514ad604c82e400703302c8e2e2bfbf738ef380e6f690392712d64c59fca62f638f2dd8edbb842a7ceafc4926febecfe42d5327af88fa21a9320d1f590803f35b2ecae7e605f0aaf99504537de024e600435f4963aae484cc3f6620243c307ad03f87bbb60696bf1b66409b143dd80362b48e74627ba790e700b4a6d10a4961fd6e4d954af5e585e44a02dc9137a9f2c5b2f09c5edd52924a0f62e0db46f2eb9c15ce3e9940f16a4c7c4be030c02182b2aef10f01de089f380e8afe59f6ace4c9f34738d041cfa61e19a64156a675832d16f4ee54526e0b7c39a8f48dbba330e8ef36b5564d263060c90009a367bfc4a9d1fa7e7903d0de3b2a68de720b8bf070f456306084485cb3858e98004be70aea72b6d0200def4f340ec415fdd2bcaf28eb60a1c2854fe016de38232c721b6d3f3325a101b77ded810b660a83f31c46a5f13a5a08aa6df7da23d0eba9fcbb45ff299761741ca950e12f2f1881946ed0c16f62139d03b430d1dedc3e7f7c68f2bd50993adeeeaad42315b36e0e592b42f1caa568156ea7aaba4072425cc227be504ae30f50335793483ae94a208efe33d61a1bd8cf95db05914e3b732a6c2ea57180dd5421a85a94ca2a97c80a41c04484c5552bd6489ca235c28d773a4d5122d93fbbcfcf8707b88f3d2604da1a47cee05bb3a9fce7528905b5a279a51b44a72a7bfcc9d1769db1813e161dee4387ebefb87805c1bc133b7cf56d549d165356bd3c24b4fd4cbb7a920cca8bd5e43b14557d48c1131a5ec93b3dd64a8d0791d9e50f4f501a5c858f2110418e110a74f7469c1b2ecb54c929d4c08927ff36c4106d696b6758823b235b2a0704d52ad4da79b09c140c266153e7e54ffe69776b2fb97ae8d605c37142c40bd45690f4207e4d3905cc0e69f548c9ec024a2ddddff639d148577de8be4a322d756efa88eaa2e92f2edf13a664924d341a8f95760db3d00329c8f882c24ced3ae07c89e35d51b7e11b0d1e53270bb0523ddde6e95ef8a0c05d2d2b6ba7c6ec169202e6102335e193e302b8c460ed998878abfb1db24e1797d1e7605e13598923a088f38ee8d824d556ebca3d36311acdc402555cc962cdd10936bb4e1ece2e39a6078516e98169fc31fabca7a0edacc689d6a5b4fe2475c0c73ce3d8510bb903260e1e381fc5fa6ea920c8bd2a8ec145eb778f9891d840ba5a3f08b0f6dd3f07e753899c30fe2b565e821fefe44cadf2117d358a2447b0d8ce48f742325b7d358a96536be71ba650ebc36783be0ecd540fb04bdd6a4cc39073df2b9a5ed9b23a4e2cd9ffdbc2967e690188dfc052f21bc49e9c81be87d12b4ea1a770e108d50de901bbb0d046c50a4228254aa095f0cef9d608b0ef50208b0eed938cc7d136207105030c72580f3d5c707b62090a29415e32af9066217272ea6cd498b5c1a81d06314c21406328037ddfa23222cc84c3afbf8cd1c3762faf04352bc37910971404fd446bc4beaa71b98135724118a1dc65ffb937d5310fe1f40c307095f0d3314199773a33bd6e2c89405f48bf12d6651d789e66f1820cdabb6107bdb309b937d8e0f513fef644f96b702e509903ce203c95a10ec4c9f4a71e75c9495038b423de361a86cea19cc2cb4f1f1874e672b2b2e97ee9462090f0639864e95331262a4a560c9948f3c74db29b1d979b7648a7a18536d7f6d8d2fd422f7070756835185866ac588a4daa8094185982d0879768320c5a05a95f1a761a9042efb4e291395bcfe4924fd4df12b131c3520fa984499532946adcfe20cd2fa56d8d44296926284e91509bf8ae72338c28b93974700af04d3ca38f55824ad9f52bd0e6b05f2c7bd8d324b4bfd657855c8cd458baea1bac09386c4444cff7594a870650c1e524230b2a26d865605eee5a016efeedc957effda3d1c145ad66982ad9188bb80c2d1546650750c7e79416c80d7ac102b47bc7798048489afde2f8461a9162997824253047f3d0b0148160aca7c533bdb6710281b42e64ab5eb5194a78d4244e601b67451ddf954d429fa006f25e09ef2a78388c6dca6228f17e3fe61510038f162626435783cba9d6809fb7b50fc1bcfb6231466454b5925c32d04c02e5bac1903df02e8b2ef25e64fb78d7daba63afe4bce774148ae824c62d778d88b6d6c7723cd5d56278b36058f492e4dcd6cb898414f521d9a21cde732aceb5a62adb996f1e18d950a982f9fee6c02750b13965ee93d80751116df1a5884ee24d05f0a74a3faee0198fa1f42bc5241dcdc623ab172dacf6108535f92e0279b9ceb96395073a5b009395aaf3ce8df09add65b351f341d2600351d24d3474f7d123fa7e51f017b0a0b90c4cdcc5db57927d8e87319914fb60ca897c7642e0e323376070cd6f05fec5e74c88c3175010761c7f1ac3c00e263611050c29a932af6cc7908eea6d1e2cefe518c6092cbf7fe7a6c5b0b821aadf6f4c504a1de79e723b5c17bd68d634d7b18b4b9955b37d765c464dcaaab31b9613567d37640e3b7ba9c2abc9b8ad3fbe2ee8b62b4ec7223792f76658bccff7069454442873c81104f5859de761160347deb9e1390544369afd02640ad5f6868e92c2d576a13808199a53fcff7863344ece1634086ca08e72b8d8dad0c11744ca5889437dc482375b6371f12853a22b37ee12ac0bf851194eca88f4e711d6c010135c46cac6c4b6d4d22ded888f4306369c5e7b716720ddcfd1550760b2674eae607713c5696f43d84af2d853505636f0aa30d128cd5ea230bff5a9322b0f38fc998eb902fa2e66a5cdf573b67faf264bd8aee6a7baaa4607ca070939347511a3e7fcc1c2aed75942bf4b02a7a3680f21e60ba2c3fb198e823ef8742241a5193df74d2fd25e4d28080588ed992440022cac1c026a3bf2c1de232751ee2c56381cc320b8511846093b8c82c3b69bee0a5703ebce82d93c99555970e5f192bf4c1438ef3d583f40e8b4042138963b862055a0a8b1df6cad65b82d57850dc251e50508dcf9d58c60b4d6d5f706b10bbb25717263300d3b432ccb759ddbd52e5dc847469dbe7db86ed6d35997f93f8cc939ea38e0eefecedb429e6ed8b028a6ba59954ad0b1345816bb14ef04d6d922770d40b19adfd065256ac351479ec65435951bb014a5fdee04be55231894b9390a28c7823bcb54409faa06f1c3da22ec89f0f9421fa9a33bc840a1362863b549360829e94a149010328b366b45d94e44b03182eb30c63fc967159c1df1386350c53d8f249a1d5cf7529434d61cf0085c59fd02171e5af8f1c82f63d8fbabf8f07622899eb8d01eca1fc6e242d202799005db7e6d26f734d6963a81ab2cf54936440914330b0a7a64f4c785c0958d72e82720124629c630ebe6c2fa7efa9e2272c234db67c5049db7b62f7e1eb3bbbdbfb842fa3df06ac020f84fac21207504412516cf601b65700c971606725d4fc31c4ef15a6635efde36696e339f2cfd775184233eba170149c0d215428706551ada80a5e9509949d22eeb0ff390d1d172b7033c153fadbd3f158b87cb300dea6364874ae86b93e5863f46d3fa2a0c507b4c382a46e0f953854689ce9b7f2a30945ac9ab4848297b833b4fedd6f839ef106a7028f1469d0950628256fec62aa432d6c0a85c3c4f5a6b792c12992a84ce000e6c1aeb6bd6c354960d9a741e0ef483a723762006e291f5950075e35b4223c471cd23733b1dddf91eeca80a4535db48fea257297e0b02eeeeb3da56c2b7acc338240f0e1eff611efae168d566dcb55b9a9d569539031fc4100eb6ca194a369c1330395dfc82e506d8669ae0b80d185a1f037fea20a2cc16da225b6e3ebe2dea684a032dd222dc5df9679f927887e0323e2be5c6b5db8b45640bc9fa099432d28c833a00b04697cd0817b118b78aa4a1ed51dcfe3fc69560b06c859284c8581b6ba223af7d55a3c623400aa0a30fbf3756e3d167100f5739ec9f7fcab49e5164b08b3628f9de44f0e7fd887a88b54305cd1c57a7b9b4ae5547dc617b4aa616b02fd638f4d030b7d9394929abe4264653c79bab88d1210197fe186b41c32c4ffe2827174edabc9cb926173a4afcfdc16e9386d2c2867d9d07d014161ba69169d51d61056d0e3d4c6f7e2fd93d244df132e72f560569889d635cd192f7c6c75fa777570aa806c5c9ec31b9432ad8070eb1474e9d685eb85116aef47ec47eb621c33a38301ae2348233d3b49ac13e64c70d4c4d594927cf3508f8ca6c040e71c95963820d7a70f22fe3120ad893234799be5de84d096b5b8961cdf8b09a52eefb994f433ee5b57ed74f1eda8d6894d2d19fd1faec1d6f34aa175e4b3a8298159f8a6e4130c3d2100d2c9ba994be1e20367f5d587d34ad6c2b00078ae1fc589c77ef3c3d2f0819eeccff1e7b686308122d9d8504b39be1bc01425d29147ad7e24db8c1c132b955ab073d37fc1a83a12d4155f747ffb33779b2f58e4c862d97bfee479631188a1c888ae437b39bf9f197fda0ce1708be825c4eb5bcf8c419b7f44d1be60c224b70e8536ba3f0eb79d6255438988b420f80a81c2f986a8abc2a7c60bf54f0027e1c190c4a8711fbc8551441c6640130372c515be3f22cb10fb9b53223096821a135a309f40922d5cbc2acd57e0d7cbec9d47837ae1465312424a77c6be3451090277f17d6225a0d634455659903b1bc51e79c1330a70d6139e9d7fac08e5928f23d2c10c6268ebbfda4cc45948a33a263f672a523125d188f64c9c01b2ef801686f5fd26321808e96e07433968d05a44864eddc2d190155cd3266c23778dd1cf843a779f77919c8e7a5560dfebc817d703f3eeaa802c613992e5ee2ba6ae90600125b1aa07f04902c524d3cf57e1461d9895461117ec413fb3537752d755737738bebbe1135afa71db91e93f33771d16ab3134f0d6d588dfe23ec6661698421c010d43df3dd7e9c422f8b1e34ad0953e9fe8d7ce81f4b0a62334f5229c6b11fbf5889642660619a2c1f0e98fc561836f62f61861712455a193e54e7c4fe6f1052296ee852b33ded957545dea80dc5f0c97cbda1d7a6a74ae0f482a59e8cb33bb42522b6652eae4ffa1184a2de0e215a662edc4731a0e6042a69f93fa68cc9088fca3e3d8473d5aaabc62ee5956144fd68eacf289eabfe35e6112e919837b82d7084db1a4cfd8e1a86c4ea3b90b890aac23156b50e21f293d0091cb71822592ff9c0493c1dbfd67640a5da51820cbdf5b86bdfcf47065c715bdf265190284a0b73ae525c70e05f0b35f67f8d8652f31cb650c02195c931546a32dc64207c2e0bc73fc8158e7188e8dcb8e258236356ebe5e35361b0bd759fc8652773690a2908ccc0ebd47a889f3ab783f4f3cf12738b7b2323680c69eb1f28688820c02c601f93ccb28717da6b6e5ac20fbaf7fb283784370fd30fed3aa8e0b485027dda030449a6abeb922c705c903a2f349dfb075b9ce0c18e90df690fad3177e02ee6ef19ce602f6cf463ca06a38203017ebfd02519b5b607a11718243b01084656792f3bec57956232f1c5f6ea03fe34bed97e55a8ab67741617263ab232293b19fac40daa9688655da4d37882b0b21980dd5201b4fcef42e0c038e8033a024c787ec218988b08396e9a621ac4374b10bd13d521b52f0afccb3efa4681e8f6ca1fd2152142c89c09aa954cf4c5e4073fdc99cb6cd151458b59552f0ac5f61888679ffc3711d4b806e756a77f31c993ec9239927414ec4fe996e7fc498cecacc56b30440add6f71b02bc34f3705681e7e19cd3722febf38b6ecc25398bb9b527c77fce532371b2463d4fd5a8d0f1dbf97b95eb59acf0281d7805f99e519aa4efb65699a2b2ed89cc8af53bc305bc1a4f750a953086fab18a36eace7e0311de9a6d400042c17846ede3f280a7ab4dda32bbf364fad1722b5bbdc0bab21aba5e4f43b243b2165258d04633957684ae38ab2b101914a21dc1bdc31423f7748d0e36ba5d3201552a2aa76507dc1d4b4d92c4f16329c00c167765ee4f340a281f1f3d73478bd1a0d31ad5bc40969f7ae3cfed770c1b9eea1d75b8b655bfb6932610eec0d5ab113b12dd78802355c2cc8e71427ddbed5ce2cf37d454fe788c09772ce1668b9d120d1cf5f9b0503b193b2378df3b292666df3df011ec6b94271a61fae493f6f92a7308f733d9a12fd7b5596db6a6285d44ea2a0ad64d329ceeff2296a403a730c2a18881d32ebfd93d502d54021471ab8f9473af265b6e42c1fb98c1767a92d5613e29d270a27af9fa8a71f666fe1766d071813b2156e912182a7aa914439c96ab469a576c17510f1617b4536f69c2ded22c1d50d7482cb7fbcde67af59ea734f3742a0e375c7e0210ae4ecff0f818f71b270d49137e46a6ab38afffc1e24cbbd1719870d3e86dc6ff5d1bd5411bb64dd569d593e4c248415f7d59339ff83a749b6a05dd86280bab71b975247de7eb838de56281ca26849ecb8e86cf7bf9a0cae3d93acb75b4af9a46f93c830ccb8c922facef21700878b23cd313fedda6ab91908b77f5142bd60e02deb87c4a2e80b25fc7c51982d1a700fc827a45cf4114305bbb485f8a04e9a4c576365222319432630051ceea8dbcbd0513366fe622b7c15b9c5b9c7697fa7ee201eae4aad0423bb61b96652b3f1e19a5670bad143d6d8b90a9472a2f0177fae07a68dce0172384663be8e4099ec3c154e81a0a2a42363569f8f4030ab4bba6ecede9447835cd97adce8f030e3abf7fe531c9b63a81a5285bf7b45c1f3599a59c5a6ecb70cd6a747b61245e673243b55bf0bf824bc01b754810a19812c082b2252e891d98896999590ce20c9cf78be0e86967f099849b7613ac45084d0c4b7490389500f296efcc38e69fccacd8a9cb3df706bc09c399886164afd22de21676d0fdb93fee1efaf2d363e2ee83295c2bfcdfd4bcce1f0197c9052a92b3ad4032d871562d7c46a0d7deb229244414be672c0dd9a0de1cdd818b8b498ecbf1c786d53e82bb1dfa187d22b4bae3179d56ca4fdd6f8f2d4c81df80726dfcf243829c33d23b77b8d039b0d169c5613ecde639a30eec12dbd364bdca747e8bbf610033c8a02b1f2763aa9a63806d07364d24228d7ba621133ec01c79059f65c54748703fc60eecc810382fbd160a8df4dcd47aa57f640f5ffd74a1f94f9a56156f7c0c6e34fdd6e43a5a0ac46b71474140fb8f16c10aab75678875f19fa82dad79a6cd284c78488aee66c5279d16acb21b8db2df30327783b64335934d7db219dc6846d9199329fa8f8e8a949863b39c03bbf8d83850920f4e87f41bc8f14c5fe3541444af632f5df9866dcae93493fae87809f16ee551bac8c4ddd0bce15ff7be0e573cd46fbac5fc7f4b764f46fd3bb09ab24bbbd9c38ee0f648386d892a90165e2acc2e5057c7aef96648ae013178932d6eab4b60d94555a7f380201c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945860300000000000000af3ce8279bc3e39954527b6314ce47076c97b16c3577c2e7ef014a9f62bb1e248ebb21fb1ca0aea57f0a3df15877c9de9751b1767d705d511fb67eec61dfd42f00" ].map(|hex| >::from_hex(hex).expect("Block bytes are in valid hex representation")); } From 4ad68ae9b08588acc499bb2b1484347e10328cf5 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 12:03:27 +0100 Subject: [PATCH 129/157] Revert "Update zebra-chain to sync with the updated librustzcash (zcash_primitives) interface (OrchardBundle enum etc.)" This reverts commit 998a2c7046a257b8a34d6d2ac10557e34ef135f6. --- .../src/primitives/zcash_note_encryption.rs | 44 +++++-------------- .../src/primitives/zcash_primitives.rs | 14 ++++-- 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/zebra-chain/src/primitives/zcash_note_encryption.rs b/zebra-chain/src/primitives/zcash_note_encryption.rs index 1b6673d5e11..20270117003 100644 --- a/zebra-chain/src/primitives/zcash_note_encryption.rs +++ b/zebra-chain/src/primitives/zcash_note_encryption.rs @@ -8,33 +8,6 @@ use crate::{ transaction::Transaction, }; -use orchard::{ - bundle::{Authorization, Bundle}, - domain::OrchardDomainCommon, -}; - -use zcash_primitives::transaction::OrchardBundle; - -fn orchard_bundle_decrypts_successfully( - bundle: &Bundle, -) -> bool { - for act in bundle.actions() { - if zcash_note_encryption::try_output_recovery_with_ovk( - &orchard::domain::OrchardDomain::for_action(act), - &orchard::keys::OutgoingViewingKey::from([0u8; 32]), - act, - act.cv_net(), - &act.encrypted_note().out_ciphertext, - ) - .is_none() - { - return false; - } - } - - true -} - /// Returns true if all Sapling or Orchard outputs, if any, decrypt successfully with /// an all-zeroes outgoing viewing key. /// @@ -76,11 +49,18 @@ pub fn decrypts_successfully(transaction: &Transaction, network: &Network, heigh } if let Some(bundle) = alt_tx.orchard_bundle() { - if !match bundle { - OrchardBundle::OrchardVanilla(bundle) => orchard_bundle_decrypts_successfully(bundle), - OrchardBundle::OrchardZSA(bundle) => orchard_bundle_decrypts_successfully(bundle), - } { - return false; + for act in bundle.actions() { + if zcash_note_encryption::try_output_recovery_with_ovk( + &orchard::domain::OrchardDomain::for_action(act), + &orchard::keys::OutgoingViewingKey::from([0u8; 32]), + act, + act.cv_net(), + &act.encrypted_note().out_ciphertext, + ) + .is_none() + { + return false; + } } } diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 596eec2430a..906475cf2bb 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -156,6 +156,9 @@ impl<'a> zp_tx::Authorization for PrecomputedAuth<'a> { type SaplingAuth = sapling_crypto::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + type OrchardZsaAuth = orchard::bundle::Authorized; + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type IssueAuth = orchard::issuance::Signed; } @@ -288,9 +291,14 @@ impl<'a> PrecomputedTxData<'a> { all_prev_outputs: all_previous_outputs, }, }; - let tx_data: zp_tx::TransactionData = alt_tx - .into_data() - .map_authorization(f_transparent, IdentityMap, IdentityMap, IdentityMap); + let tx_data: zp_tx::TransactionData = + alt_tx.into_data().map_authorization( + f_transparent, + IdentityMap, + IdentityMap, + IdentityMap, + IdentityMap, + ); PrecomputedTxData { tx_data, From a999d70578feb26e302b22fd9b3c895b94d44702 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 12:05:03 +0100 Subject: [PATCH 130/157] Revert "Update zebra-chain to sync with the updated librustzcash (zcash_primitives) interface (OrchardBundle enum etc.)" This reverts commit 998a2c7046a257b8a34d6d2ac10557e34ef135f6. --- .../src/primitives/zcash_note_encryption.rs | 44 +++++-------------- .../src/primitives/zcash_primitives.rs | 14 ++++-- 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/zebra-chain/src/primitives/zcash_note_encryption.rs b/zebra-chain/src/primitives/zcash_note_encryption.rs index 1b6673d5e11..20270117003 100644 --- a/zebra-chain/src/primitives/zcash_note_encryption.rs +++ b/zebra-chain/src/primitives/zcash_note_encryption.rs @@ -8,33 +8,6 @@ use crate::{ transaction::Transaction, }; -use orchard::{ - bundle::{Authorization, Bundle}, - domain::OrchardDomainCommon, -}; - -use zcash_primitives::transaction::OrchardBundle; - -fn orchard_bundle_decrypts_successfully( - bundle: &Bundle, -) -> bool { - for act in bundle.actions() { - if zcash_note_encryption::try_output_recovery_with_ovk( - &orchard::domain::OrchardDomain::for_action(act), - &orchard::keys::OutgoingViewingKey::from([0u8; 32]), - act, - act.cv_net(), - &act.encrypted_note().out_ciphertext, - ) - .is_none() - { - return false; - } - } - - true -} - /// Returns true if all Sapling or Orchard outputs, if any, decrypt successfully with /// an all-zeroes outgoing viewing key. /// @@ -76,11 +49,18 @@ pub fn decrypts_successfully(transaction: &Transaction, network: &Network, heigh } if let Some(bundle) = alt_tx.orchard_bundle() { - if !match bundle { - OrchardBundle::OrchardVanilla(bundle) => orchard_bundle_decrypts_successfully(bundle), - OrchardBundle::OrchardZSA(bundle) => orchard_bundle_decrypts_successfully(bundle), - } { - return false; + for act in bundle.actions() { + if zcash_note_encryption::try_output_recovery_with_ovk( + &orchard::domain::OrchardDomain::for_action(act), + &orchard::keys::OutgoingViewingKey::from([0u8; 32]), + act, + act.cv_net(), + &act.encrypted_note().out_ciphertext, + ) + .is_none() + { + return false; + } } } diff --git a/zebra-chain/src/primitives/zcash_primitives.rs b/zebra-chain/src/primitives/zcash_primitives.rs index 9aba76215f2..67cef7716a2 100644 --- a/zebra-chain/src/primitives/zcash_primitives.rs +++ b/zebra-chain/src/primitives/zcash_primitives.rs @@ -156,6 +156,9 @@ impl<'a> zp_tx::Authorization for PrecomputedAuth<'a> { type SaplingAuth = sapling_crypto::bundle::Authorized; type OrchardAuth = orchard::bundle::Authorized; + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] + type OrchardZsaAuth = orchard::bundle::Authorized; + #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] type IssueAuth = orchard::issuance::Signed; } @@ -285,9 +288,14 @@ impl<'a> PrecomputedTxData<'a> { all_prev_outputs: all_previous_outputs, }, }; - let tx_data: zp_tx::TransactionData = alt_tx - .into_data() - .map_authorization(f_transparent, IdentityMap, IdentityMap, IdentityMap); + let tx_data: zp_tx::TransactionData = + alt_tx.into_data().map_authorization( + f_transparent, + IdentityMap, + IdentityMap, + IdentityMap, + IdentityMap, + ); PrecomputedTxData { tx_data, From daeb0f06c9650eb63daee30a7e5eb091cb04d2bc Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 12:13:10 +0100 Subject: [PATCH 131/157] Revert "Update librustzcash and orchard version hashes in Cargo.lock, make a minorr fix in code to sync with that" This reverts commit cfaac4b1c0f6e86a4e0de40e3be849e0411546ef. --- Cargo.lock | 22 +++++++++---------- .../src/primitives/zcash_note_encryption.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c700474b30a..cc94ff2101b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1372,7 +1372,7 @@ dependencies = [ [[package]] name = "equihash" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "blake2b_simd", "byteorder", @@ -1407,7 +1407,7 @@ dependencies = [ [[package]] name = "f4jumble" version = "0.1.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "blake2b_simd", ] @@ -2878,7 +2878,7 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orchard" version = "0.8.0" -source = "git+https://github.com/QED-it/orchard?branch=zsa1#3dbdbc52c6e2ffeca015ae6eb80ad7f1c870384d" +source = "git+https://github.com/QED-it/orchard?branch=zsa1#a7c02d22a1e2f4310130ae2e7b9813136071bc75" dependencies = [ "aes", "bitvec", @@ -5814,7 +5814,7 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "zcash_address" version = "0.3.2" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "bech32", "bs58", @@ -5826,7 +5826,7 @@ dependencies = [ [[package]] name = "zcash_client_backend" version = "0.12.1" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "base64 0.21.7", "bech32", @@ -5865,7 +5865,7 @@ dependencies = [ [[package]] name = "zcash_encoding" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "byteorder", "nonempty", @@ -5874,7 +5874,7 @@ dependencies = [ [[package]] name = "zcash_history" version = "0.4.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "blake2b_simd", "byteorder", @@ -5910,7 +5910,7 @@ dependencies = [ [[package]] name = "zcash_keys" version = "0.2.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "bech32", "blake2b_simd", @@ -5947,7 +5947,7 @@ dependencies = [ [[package]] name = "zcash_primitives" version = "0.15.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "aes", "bip0039", @@ -6008,7 +6008,7 @@ dependencies = [ [[package]] name = "zcash_protocol" version = "0.1.1" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "document-features", "memuse", @@ -6548,7 +6548,7 @@ dependencies = [ [[package]] name = "zip321" version = "0.0.0" -source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#6e5a4130f5e7fbd6f195d89d34ed9669686f7635" +source = "git+https://github.com/QED-it/librustzcash?branch=zsa1#b61b7f2ae05648da97edd4ad513fead707274563" dependencies = [ "base64 0.21.7", "nom", diff --git a/zebra-chain/src/primitives/zcash_note_encryption.rs b/zebra-chain/src/primitives/zcash_note_encryption.rs index 20270117003..cbc19afc5d2 100644 --- a/zebra-chain/src/primitives/zcash_note_encryption.rs +++ b/zebra-chain/src/primitives/zcash_note_encryption.rs @@ -51,7 +51,7 @@ pub fn decrypts_successfully(transaction: &Transaction, network: &Network, heigh if let Some(bundle) = alt_tx.orchard_bundle() { for act in bundle.actions() { if zcash_note_encryption::try_output_recovery_with_ovk( - &orchard::domain::OrchardDomain::for_action(act), + &orchard::note_encryption::OrchardDomain::for_action(act), &orchard::keys::OutgoingViewingKey::from([0u8; 32]), act, act.cv_net(), From e0653ccba01e4689c36decb4ca15890594d39205 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 12:17:12 +0100 Subject: [PATCH 132/157] Change ConsensusBranchId value back to a temporary 0x77777777, to aling with the one used in OLD librustzcash --- zebra-chain/src/parameters/network_upgrade.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index fe9eb672c01..ae9d28eab9b 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -230,7 +230,7 @@ pub(crate) const CONSENSUS_BRANCH_IDS: &[(NetworkUpgrade, ConsensusBranchId)] = (Nu6, ConsensusBranchId(0xc8e71055)), // FIXME: TODO: Use a proper value below. #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] - (Nu7, ConsensusBranchId(0x77190ad8)), + (Nu7, ConsensusBranchId(0x77777777)), ]; /// The target block spacing before Blossom. From 08de3de071695c1babfa881335952df0e3cfee9b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 12:21:29 +0100 Subject: [PATCH 133/157] Change TX_V6_VERSION_GROUP_ID value back to 0x124A_69F8, to aling with the one used in OLD librustzcash --- zebra-chain/src/parameters/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index 0eb6f04ff66..f775f2c4bb2 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -17,4 +17,4 @@ pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; /// Orchard transactions must use transaction version 5 and this version /// group ID. // FIXME: use a proper value! -pub const TX_V6_VERSION_GROUP_ID: u32 = 0x7777_7777; +pub const TX_V6_VERSION_GROUP_ID: u32 = 0x124A_69F8; From 49f0a9cac3a111265b1b01c39b29eca4c29f19b3 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 12:23:58 +0100 Subject: [PATCH 134/157] Revert "Fix consenus test to use the new orchard builder return type" This reverts commit 6b7e6655034a8aab6e544b5443fd97694a85409c. --- zebra-consensus/src/primitives/halo2/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index fc4a7aeba5c..d5768709681 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -63,7 +63,7 @@ fn generate_test_vectors() { .unwrap(); } - let bundle: Bundle<_, i64, OrchardVanilla> = builder.build(rng).unwrap().0; + let bundle: Bundle<_, i64, OrchardVanilla> = builder.build(rng).unwrap().unwrap().0; let bundle = bundle .create_proof(&proving_key, rng) From 12ad26aa9355cd0d8083b14064e4a5633ce1cab8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 13:05:15 +0100 Subject: [PATCH 135/157] Revert zebra-rpc test snapshots to use a temporary consensus branch id (0x77777777) to syn with an OLD version of librustzcash --- .../methods/tests/snapshots/get_blockchain_info@mainnet_10.snap | 2 +- .../methods/tests/snapshots/get_blockchain_info@testnet_10.snap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap index 9fadb83a0fb..9ec46ee6a75 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@mainnet_10.snap @@ -71,7 +71,7 @@ expression: info "activationheight": 2726400, "status": "pending" }, - "77190ad8": { + "77777777": { "name": "NU7", "activationheight": 3111000, "status": "pending" diff --git a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap index 14085ee0770..41ba65fcf65 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_blockchain_info@testnet_10.snap @@ -71,7 +71,7 @@ expression: info "activationheight": 2976000, "status": "pending" }, - "77190ad8": { + "77777777": { "name": "NU7", "activationheight": 3222000, "status": "pending" From 53b657d67b8dc807aeb2177a7384fb075412bb15 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 14:25:07 +0100 Subject: [PATCH 136/157] Revert "Update OrchardZSA test vectors to use new TX_V6_VERSION_GROUP_ID and consensus group id" This reverts commit 0dd30f3f365ff0d8ac36000480632fe0a146b02d. --- zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs | 8 ++++---- zebra-test/src/vectors/zsa.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs index f62f401209d..324f270c04d 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -110,7 +110,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x77, 0x77, 0x77, 0x77, 0xd8, 0x0a, 0x19, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x40, 0xa8, 0x86, 0x5d, 0x61, 0x39, 0xb3, 0x39, 0x62, 0x94, 0xee, 0x42, 0xc5, 0xa6, 0x0b, 0x63, 0x57, 0xca, 0x65, 0x8b, 0xa6, 0x76, 0xf2, 0xd6, 0xda, 0x8e, 0x00, 0xcf, 0x60, 0xe8, @@ -860,7 +860,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x77, 0x77, 0x77, 0x77, 0xd8, 0x0a, 0x19, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x57, 0x6a, 0xc2, 0x2a, 0x5e, 0xe1, 0xc1, 0x53, 0x80, 0x98, 0x98, 0x9d, 0x4e, 0xe3, 0x6a, 0x88, 0xb9, 0x25, 0xea, 0xdd, 0xc9, 0x0b, 0x5c, 0x14, 0xbb, 0xc9, 0xf1, 0x0a, 0xa0, 0x22, 0x46, @@ -1594,7 +1594,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0x75, 0xdd, 0x6d, 0x7f, 0x4b, 0xef, 0x95, 0xaa, 0x1f, 0xf1, 0xa7, 0x11, 0xe5, 0xbf, 0xd8, 0x53, 0xb4, 0xc6, 0xaa, 0xf8, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x77, 0x77, 0x77, 0x77, 0xd8, 0x0a, 0x19, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0xca, 0xe4, 0xbf, 0xa4, 0xba, 0xfc, 0x37, 0x22, 0xd8, 0xf9, 0x3c, 0x6c, 0xfb, 0xcc, 0xba, 0xd7, 0x94, 0x44, 0x58, 0x85, 0x10, 0xba, 0x7a, 0x9d, 0x8e, 0xa3, 0x90, 0x6e, 0x7f, 0xdc, @@ -2221,7 +2221,7 @@ pub const BLOCKS: [&[u8]; 4] = [ 0xb8, 0x40, 0xa0, 0xd0, 0x5b, 0x7e, 0x8e, 0x35, 0xfd, 0x0a, 0xf3, 0x08, 0xe3, 0x37, 0xfa, 0xd8, 0xb9, 0x08, 0x94, 0x79, 0xdd, 0x35, 0x73, 0x05, 0x8e, 0x64, 0x48, 0x82, 0xe9, 0xb0, 0x49, 0x1d, 0x06, 0x89, 0x26, 0xc4, 0x8c, 0x06, 0x52, 0xad, 0xd9, 0x32, 0x00, 0x06, 0x00, - 0x00, 0x80, 0x77, 0x77, 0x77, 0x77, 0xd8, 0x0a, 0x19, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x80, 0xf8, 0x69, 0x4a, 0x12, 0x77, 0x77, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x56, 0x90, 0xe6, 0xfe, 0xfc, 0x61, 0x4c, 0xd6, 0x40, 0xc0, 0xfc, 0x9c, 0x69, 0x91, 0x0d, 0x55, 0xd2, 0x0f, 0x25, 0xad, 0xfe, 0x3e, 0x4c, 0x9c, 0x06, 0x96, 0x9a, 0xe3, 0x2a, 0x51, 0xbe, 0x9a, 0x7a, 0x06, 0x13, 0x03, 0x39, diff --git a/zebra-test/src/vectors/zsa.rs b/zebra-test/src/vectors/zsa.rs index 61e9183774b..f4caefb4afd 100644 --- a/zebra-test/src/vectors/zsa.rs +++ b/zebra-test/src/vectors/zsa.rs @@ -8,8 +8,8 @@ use lazy_static::lazy_static; lazy_static! { pub static ref ZSA_WORKFLOW_BLOCKS: [Vec; 3] = [ - "0400000027e30134d620e9fe61f719938320bab63e7e72c91b5e23025676f90ed8119f02c71c7ffa660028b5f3bc0b0bedf9b76a829ce8f2ef82c2c69ab6948bc9fd00a80000000000000000000000000000000000000000000000000000000000000000f2fa494d3fa60c200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025100ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac000000000100000000000000000000000000000600008077777777d80a1977000000001c1d1c000000000002000adfbfe7961473dc7f8ffd411b3e2eeb005a37342e6081d5121f18f5648c8480adb28949796e09a38118152905839afc125618be1fdaf921d188488b607f2544e12a249ab310f17a9349bfe463c7de09d2b822ab0efa88b6d32f77d7c38793192b944aeec0ca94918390dbe44c50e706407692e348ed9b7cedd231941a673722ef1e7e74888672b2b2d08c97a9ac114b7039feffbeb8bbe197db4a0bca8d395cd40551c1d5d788acc2ad09eddda73a5948de2d9e2d82aa638dad6f5dc61042d6850b926d944f29f17e96eca84684252c97ce4382f2642e54208929a4b37954e8e386c677f2aee3e8f4f4aee9f76a87d868fa2210445c09b927b842485918c869a23be8213ae21937a8ca83406fab193cecfd3fcf3b1c698e8057a6c87c059dc6f4ccb30af8e608a7c04088cf3ca32ab20cd780da9443606b092c8b5d85c9a76433c0993e3eee385884ce1f3890abf95462c49bed01a3a5c09df98cb7082e9770bdee196f8b968003f5cc76d82bf575f01da3ed40e44b3b15721f4a9dd5ecd14fb71a42b24ccb7d7e6a3bc10b53ebcb7e0ec6ace91dbc19801eff0c76ec0c10602bca2cfce9f3e79536a25143d351ed2894b4eb4e549960f212f0787057ab1ac8b249c3d3ff8652cb3fb17d7656d50c5e6833b056feb26855332f60e7b8d1ebba32df63d8561fd7d209a1e5adb9853bb5b5d6a41bf1ec52d348023e945bc02e8d6ae8d5b6c7a9225991cca4aa0b41861f237b3bf545220799f152767c7fdcc693a989057e119c18a96007c69c8fe5751a4258ec3f0f99c1aea8dbbaf4df9953ccf6b42cf2f4265011ca89ec7b9ef2c6e9410886291054f50db6310b225ddf32f9db26416da6ca9ef6e3198db36ebab9802517aeaf628d41358fd141dda8fab32fcded20707abc3d00191e0b2690a1e2fa044814191323155fb21e3da8798e0bafef8c2da4c73f967504f51e716cf87117f90fd028df17f3ea26aebeda7f5b3192cd5f4855044e9a41bbfb817074ca1680a458338b191a9619dd337bd0335cb1896d79c79cce10e454b58fecb1cf10da9f53129bbf3cae2bde82007ed98505f16922b6ae53a3a709c2e01ff7e529925d6069807c06bb0c73abf8d463b2a944a97d150935cc76e1ae1f8f95159a928a5afbf76d54544a771fd4bc482ca522274b94c87b4f1c7cc3399709b5572c5133bc945cca63bad59b454ee301e3582f09c5c31f326a59705a2b534d8e9a79835bf767ea563b0aa74d3301c40a303f6fc04ba0f3807c5decb6743aabfed1a092f88975820c324e2229829462e4985e299c2415eccbdbb4ff26789b74e91db286e6a4af023e8a18e826e930d9d4ac8d92cd8a1098d0705852cda367ba067e723ace9ea8b9502e20e6519dc72b1cb477c4f3091ae4d20eb7401acac77d923eaf5de00ecbb61baa3aca9044f3e66262245aa9f3dce1d02a88e8c26b34e3c27b4e4e5f91cb633c9b6e098063d052dd6883d4c2b153c739ef78c5f375c640ff747adc1110de2f9d011118f3208bee2f3af9990d56ecddab1cfde0c053020b1116afdec7a3303fffe6f6880072482f95aa3115724814aa5fad017e3b7637f3dba509f1e371c9b87a275cfceb68aa5317dbac0e1959367d124935c76631b8aeb532d99c393374f214af2d6a3a5bf4071d97b6ad39b5b2ec03f1feb520ce467808eb2cedb3ec933c20322bcd4511b838de111f9faafb5d45ffd8edbb1fe8f0928d535ab9809b4cbf588af635419b10f7ad9f4418c766d88526215b74518cb6554e833ada2dea5e57776a09541d76ba545f8a727bbe7722912cf00da4a48a462a5b7b13c88941762462142f97e8da2b358435c9cb53d24b6443ea2e1bdaaf6ce58dbd0bcc598cf170a193e14e76ca8bde66ccc786bd330c6ce61db5f202b01c7faf185877e3614c1a1b4484cae6dbef080142f8c45e3e48485746fd3505bba099ae7b37b96e22b2cfe6a0dea5b017974126259d5055a28ad510b3b7116c27287fb7e635f1918d5a9ca2529b1741c9e86c59ddf11c3f70a56fac7c9607eb9bb36612494ed1ae819c092cfff73b7c9c5d3e8680dbe73f92b749c84363c374d80632fc488d0b7d35f25ecac1c151ad8427d7a4eacf24fa6937fd5c416776654bcfae92d999b51c49d76bd53a9d5600b40915acab5d31f0ea3f7a68adccbb72cb454164beb35819af0e9e06ecb40e96c9c2aa8018883301f65cfbaa7ea894737d49b44aa5d76c4b26bbb6de7126bf785fc2a8760ce1664150be0b6828659513561b52906e6a4782732749897a41ffce670736ce0baf5730fce9bcb50a44e1e9bba166f4812ecfdbc2ddd8483405cd2bc68ac179177e1713220348da35c7b2a30c9ad9670d99a53a3c4c4a611fcefe9e39024732d6996568f2fd8eca433a41664b070000000000000000ae2935f1dfd8a24aed7c70df7de3a668eb7a49b1319880dde2bbd9031ae5d82ffde01c599a33ae69b9dcc093a546efd4cdc2c8daa0479ccdc63123cbd0622fa54f8c15ce9a049727b659c998b2fc935ddfae5788c51772e00dd8fafb91e7b9e7b9d4a34efad77ea3f54eaf8bb5bfd4c5d5ec6761689042ec6b1639e79d2628e712669e32f33d058707141549b0a0fc31d9fe4a633871d1ca48096cd8272f735a0838bc1a440947547ce52183863bf080eba73bb36f5130d7dc8676be2e28d00714dc36ccc580d88f6d878357e7121a811a03eb12faddcb75c9c3703ccc4afdaa85101244e619f565a5635e6b8c856fda2edfc27b5c06a711730beb1c361a6a916fd713ba64385734b8563775d66adace055205c6cf9a6c90faca0629e7b93511d0e51e3405210bc3d3c590ead6671e57af44a9418a5d3c6369d5b6d294032f1592c601c2782f5e5fb7ef820f548a7e21661944982f5b04f8722ebf42456df6748a2f9ba2b816bfdfe1432f6c4911daec2b75802d43000403272e1de73bfd625b9742b8970133c0599a17cb7fd7984d6a3da82e845e179ea888019c6d86016cbef610a7a0e3409f0a2bac1181ce62a22fe3fdad2708225ec503077caf354dc5c12f6fad975509172383e2f87405fc7c387b1de333f435426fa3b8a524cea377f3c24690918a4ea2dbf4940ded498169b9b85adcd9d37175ac43897abea5d629775f4f9792d2ece6ff69dec38e38d0c1c9e40dd2967aa103a20a148290a9b89ea82e1bb5235bfd29d260862365933e19f81eb19be2c775707433d66c15f68e5bb8a578a925f20e9d1bc34132c5a214ade50ff48489b89cb674fd3a9c787d0ab539849aa19486e3d4081d4f361517f45fa35168e0432fbb69251a6a7e8f5d33b30564338f693e636d04203502588b4e9128744f49005a77e5de0f79e06053c01e82f4bc29f0bdaf3292c300030eb758fe2a7e98f41f0db618ecb99924e25084b0e69da78bb4918b365b8c613ff5e033d4994e176b5abe710fa552b3e5e21f59a33e4e0aad74c0504c2eeffcf213301b35d9b0bd3c7d140c849012b1fa7ee177e994366b9b278afd94f6bf9a65bbd1cfcf5f3525512e5b257f6a5cd61c43ff2c695cd9571d8d0e24bff92a5ace203d9a643b7c52d794b3a6a2f0cdc6c8c1527e51b32847935dd0c12b1f1aef49cc40d4318b5b067ab9d238e7dc4a8903d8ed224c15ed66b11043fb6ca6109587b6210027df615ef57125d696d0de758be6e4b1693e260589e441ebb020177a4bc7c577a7f2c7d415e00fe93cf1436bf13f738f0cb7d0448074f1436457dfdc03217b585d133dd44928779072129072c0cf0ad9ff3fdbc686f12d219313ceb77e01846f030d631c8014987081a1e3659239e009105143ff3fd3d999fb10e1a1b8f0adce31db881d5da746138462e5a1b45d47862fff760d3b1ae1de946257f2f0edd1bb911495fe1a24ec3a7cd5285e5bb25ac1d206d2f926f9dfd574758a6eb2ee5faed26e5a8e07dbeb11ba4dcfad69d93cc718fca7658b97384a243589699547d476887de967e325ba5e3b982b079eddf83998849579a849dbd3f2f487eaf9242512899756352f3680f334e0585bd43a3439bd62404297912e545e7c18e0c2e19714752b7525bebea1d83222648bc9457ff3fed4c91b1fabc6c88b5c3805dde0267f72a0abba1715fcbacce4253881625026ec2e240e8bb98c5316d28d361a91a1a572caa057492fec8d5e8d8b51f5890515186f7c97ba4a3810f40e9916567ea7a1980fd806d295c73a8b1243b538c373f531994507ae50889cddbe473a8dac128c98eeaa965cb0cdec2dce36fae175334b1dccd48839b7d28292a7c753cf23990d111e518a4260631d5a99a28f3bfd01db75d8271d08556abef553106fdc472ae97b5f4d2d3741a5104d06560d85f48d3e3acb040c3264d37f370f2acbff61ed733f655d8815983c7e78942131b41645f1ddcb24711ef39dede1317c4d7dd9b01f77066b9f3714b5f09dbb35e8341188e4384bad7238d9ef7d73e2055bb9e6706a90348ae9e5057780666f3642d7a18085e115e5ea3447fdd013a7d976d00e39edee09b271286c1a325161d3d6eac566cb86c5af3d287b5a56dcc48faec1d8342bf3c5436ccf03c0b47cb880aa7001e2c5464a406e24dfd9d021e62558e3cc9ae3228f03ddab021d5519fb426551e0a39ad08f68229662f16b79b7653b8f827a8527f1dc556a02f9e3c7d0f3872467a60340dbb0641d91d6956a33f5c905069ac39e67b40fc8d5dc617e00e89dd926bac628eb187ca1d0c41972b73b628f18159633c6d4697893bab32cb760a193b57034804a66381e62bebd6b729294bb14a113c5750a2bbdb57d40ec9e37ce7f3a486b920bf2972779b88d4ffd3136e2c10286682a4c413ed2991ce333060be5e348dde9eaded10e4cfc84ab1b157713936149239477a0b5a437574a45f24843ec4a525a71813c05c2524b92c893cb6aa0dda8df21d550371f5ac622038baef7071007a31cc486158ca1a8ec2a0c274ea26100fcfa5a3991b6f79384ae487975207d2b0b068df60c7bd63c014d13d2b5215ba7be1802b78742cee248c07cb00f3d5472dde9f85a1a9a323125a3cca08fe5c8d89f73c3fb600a4a3c7f28f12ccdac1e911c8d62242deb1ceb63eb40ffad0ae8845cc9efe69e9f5a7d2cb9910306e16b529d8e16e235e8e54eb84859d4346bfbfbefd453f9a4c8f4cc5c6c80a616433dbbcbb512651578d1d2736f513afa0fc68b401b53086d4a32d2a73100b59f8c07c06f43d17d2021fdc15410e22b5911b3572d5f7996703e97d24699da3fe7714ce74a1daa802609cc631db787abb71504d8c016cb7f5973c0d5f91899bbb100b97d4063ca590d15f176612d2e8779f89132428c6a17ce0dcab8ca081b9d891d3d0cd0bc755a193c5d5180d28d917ea7c5121c702e7c66a58b5499ba4fae3336a2040c986afd2f44d92047b338db4b6b3b6c176d88c641a6d9b4d4749654d55785002b3201ba3eb86562adf07f94b3e39bb3304a2d022a872ae74cbf27f0194c5c73037bca2d3daf1150aee2f81991aecca23660de5072568652037ce13944ec9d75f7cf424607e36233008df0a9707913985b837c631288ac62c253c9cc1586706b9e8238bb0d3d14fcfad900dff65772b36ca252d9f81450ec29d6be025262bc1104a1643c099b3bae8914c8c78cf39d09907d725a52f3ef3a9981c2dec6cccb88017805cf2163e8909eb0822c34d2b42ed08af78dbae9484e7e4faaf2a40b0762f23b491a2ccbdb5cdb4df184b2b70cd39b0fd39b8a50e4cc527f4c6169e79e9c1cca54900a1624e198a0214d8013c017a2dad0aea1521269505213c1c873cb5531b6dcaf1c5430d741514e49e7f3c0f7bea8c9e3ecddacc99e2a8e729f8a0e9c87687f11158aaa9a7159ca567598add54fdb1a58eb08da87154c59bb9214e9d63fc280ce2fe1300b12d4b805d2d992a5e5f74b04e6b41ef9e4f364aaf3f90aad6435d7662d5639882f9edf5dc7ae1e5623fb1cfd9578fbe00cf82353ecf865d9ea24b5d5050e6f7609205b2ef209c57df854ab27f2dbf047e69666ecb731f0b11e540edc105301dd9b915fb4fb1d96f4f8b99b9c42f55f99cedb22638167927766642f0c1f6c4038d4ebc8dfacf6a3ea59532d6275fa5947cc80f44650719be2802f83f62b86776c7a8ac0b92305c69583eb7b1457e21760890e8b9f42f0043af46d07f82f8aab3168ea992bb165dc7396aef85646148b9e9fa88735bcc4f2f94d70fe02200480795aed487d24810b4875284d8e51e25493075e17b7f9f319da50e339a61412cee460382cef9feefa131bb3038360535c5593039fe5fa3795bdff94b1d41e0538536a9e6de8e4a9228d65bdc5cf6868680f452599112cbb3750f9f167ed33017d61dc6b6b374d87384d3a81e74289bd5253ebd20edd58d54bd3711fed8b2273d5c39ab91cfa21b2d3a901891eff40eefd70b8d0d55c1c33a9bbbf2e0dfa2430c736a18addf449dbaa6ed37f04b5a921f945bca6bda7cc75fe47f4c8395918236dbd810406e684aec3eca46c8079dc76defdd90c746859df26c661e746260ec99f15b3bcef2d4eba263d6563f305d522b58f2a39d9f420625b2da43f7dab24c63ac0cd79078a56156ddb4a295057c02dfd02bb52511d08547ec1c0be7a7a1ffdeb550551cf0170e89d9ccf024e862eb9df3458bede7e0bc7060860bcefe43e526edc7ed295f331d5167705f7f32da9721abf972e7eb1235344776ac19bc23e6b916d3a5e54f6863dfe0f46b17800ca77c07f80f0fbe0b2a39fdd2e0107e53148182c577a60a52ce377947c1c44f9264db8fe29b5d9943ec70997fbd1759539f1c5c279f645b68a856d58571bd99d0589f444f239f194c9e73e1606f8affd027a78fec78b8ce11a3871e416307c4357e761b6836be85570d3f155e9d19db103d148cf9dd8b51faabd6157e5e80c9b78e19501489fb6fabc2c1b7de2d9f480006f0b5858eae39893f9ec8a36ed92f2d6e64a31a7c1b13dfa8540d3176e2d451b09237feca9752c8e14b48eee5dec0cc314a00cf41303c8af57c727140be157376f5182e5bd20ef43bfb73077f388b2152c79b40c7bd7360aa0da790677535a1e1ea76528a51b5ea8ceecf9babab979606945dc154ab3269d729996e6f7ed843e8207cd7893e5f8be32fecbcae63474a8f3d3e66f5ad3be91ebd42319d4d4e81377d3531f4bbb7279ba63403c9d827875d7c244a9e7a7c83818af42fee45603039becb40982e1ec43e71c919a409cebd605b865e99936dac09953b4be63ee592eb0f1bc6c8a0fb156bde6c4e05df97253dfa07ad950253f18e0bde6eb9baaad215c785a73750c6f30b36acff3e760abd513258e60d80770b4116cc7f925f34b286649676697b49fecdc8e99c6fe3311d34fcc8c4cc1f066ce680bbf9c9fc32722c858204e9f8201dab9bd6639830830e9a24830a2dfc02f767eea40019df8d41f2e0f63562cdbe55f71b136d52a61b271a24e5992a123f08babf356fd83468d20ecb634bb0ad02be4af5fa5163445cf5ae233804ea209f5c279c726db78f1c81974fb8cabc783e54ee537c9bc3c83370bba589e1389bb1e63ecf59250dcc2752fe0e1081cffb2e7f4c62d44e54a46480a809d383e81106a1b06165f419a8f3502cc7fef7c9067599af2f049fac6ee80b15122555362f7419ab7f3379cf9f27503c503eacc8e94bde23efcd0257fca4da1ac39ad5f580174c42860c91be20a8b1b95c2ccd2a51466da013a02d728d54c168eb50c064b30da49f272f08ca19099058805f91afce70776194f24a151fe36c2619df9fab6760554cbb58781514f131f1ec127a06d98e5ce4ba82fcf1165937ed258ddc9ace565827b6b8cc009b87b083119fc093a106d5f5c679e7a145b619e34f69ac0531a9d7e17ece8e335b66f14fa874dafa045603e127954d89dfcc0994581a48f54fec32d4228831dabe01d0d9f887f4604e975326e8cda35e2151a452be21a4f7117740e70bfb98cbbdaba32795fae8150ab9be24746faf5c8a9ab253cf34f2807e30a238a3ce2aa5de2691371c49b1475e62444947f632da3da60786d0f1f52a8ddb0f69bb293540830f10cf70b3d84609d16fb1c6285a4ca9ab615ea8b0aa6274317dc9c06fba50e001d00fb9db760fe6e4e751a720bb33cfa914fd5ccd5a5e5ee325805cabfbdbfdbe82a45aa53570a50fc22573e6bbf7fb641f16d01f44b9176f965b1ae610b0bf2a73fa1125b14bded8008d3d1617951e19f225d0698241746b651e003fafa16764506610fd92caf131e8c278fece483410fc3e2c6f2cc76d4a9b66028ff3aa83d4a074cce66ef035e8f2186d2ff9ed2615b0c451c8564b812f225feecf9cbbb2de6238dc4c8770a0e17feb7cb02217da98318414257c4dbf3022d8f1e5ad79fea78168c8f1771affdf4597994697e6cece2e6bfc7219d3018e3ac49549e37b8a57e0e69ef51c8944a3ed215f36c15a2883aceab247dac03ef5a82f235fea559e6b42cccd5eafc30066a3a3173bcf2f7ad34004071bd080e69c7ad3f514c62c928e63457afd2973142069ea68111c6820af10202db0396474cb2a78e1a7121ec04900d9f4ebbadf3d306273afaeaaaaf0d882dbd511146f009b748c2e093f02baac204a3b4ebd4bee5aedc3935775b9d01cab2723ce0c06ccfd5e2a8a2c8fc467c9a06ff3964e96e104890097d00a99811114179536be5457dc37864f4b5f848d27d28a6143b90bc2ae09b218e867fbd6791404ccb662fb779119b8cd2472d1f9e360ccc37f39f2019c79f365c813fd80faf189985f1704016f096acfc6bc0b674fb117ba7eab0f4138791416638ba365c546180b8d5662bfe157f3f63430198548216d7cec0ec8724ebde55883b2c384cbb67b2d7179362f9114dbbe561c8acb3d40ccde56ea66cd7c832b299a96f3a0e0aebb57e9246068d5fbdb126e6a149f7ef2214c35f30409f1b44de792cd741df0cf48f273f6dcafd69547fde219908a75b3b594f45a382ffda619f7e1378df37a8b2a25aad273329002ef931a95a0a7b670dba6dcfc08119783f60b84aba6ba878de6158e689ab051e5ed1743f6fe28a3c061198e7a49d08a68271205e4151c49264929d9ba38dcb2559f45658ce96b2c232cdf40e63bd8828794ef664543bc2f700a65d7c86f218a9b76ad0391906f4480f5563b434403e35eca1079d8c1f906a271ffa21d669a27883108ee78a4fceaa056c0bd5aa4496ec5f37b2dab8b19abc88c61ec5891759c6fb2263f534df3d7116d6874f42d8bc3a1ff9383a68ef3955295b5478c28308c79ab25ae9ca31544427a2cde901ea588ba872f37cedac395f6661ec659f1bcde925f6a82502b32fbb07d4356efda64e82c35356f9abaf5d3f0abbcbf0b0fcc2191501aeb7b59b21e00858b19492aaab25c62afc3b0cecd3d7746eb6cb1edb0cdc569602791a17911802c9f5ccca92717ac661cfd4d4dd8bcdec75492a64bdd2150c2235e7d87759e137b213cb3ab4e275a99e4ac77fda073e2870b6486ba384c44b4f59b382847a5d0a4f87198a996e639f51246014a0d9751db9f85bcbea056a7609332bb1e7ffee3baf262a346e45697d9c97c5ef099e109251368b5a807e6b69c1247e8430d2ac2261aab0ef2a0f695c22086b86fee0adb6bdc8a14af3d02ea0effac0f6f55e8203503b48deb8c8673b92c499284b935abd06352b391c253e35870f024bcbec4332f578a74d4ab0be09e73e3cbf5e1ed7e53eceeeff4ec26941dec578ce3a33f701bb540da65f810e7f4df368804cfcb6078c99d45e4f15ee1d1ad6831c3e6e01102e6ebeed1f86940de0759b256594c9f91041716bd57ea464e77cca292090f612bd7daf20e9b534bacf13ca7d940c90fa9c18b188fbcc17e282edb1156cf5c1351a9f118dcbc5cc720c5c6dad1ccfd04f1beab7817561e86442665b841c97150d10395fd842b54d025a221d81f05c820474e492341a0c6dff31f4a38ee089082f7bfb17b9d8c8355dc76bcefcf0c7692ece39649e85ddf7e395f1baf893eb960d8e1374e84a1d32fc1924ec5808c1255b34946db13ada6163b368754820d519197aceb746d33f556f9932aa775b5547d4b42ab6433e4adfea54bbd7d173e622229660e74ec486937fba081cbb26de3ce7f6f76e070cf54315f18b03675cee1c06fc765f145b7fe4fd12f897c83e21c299fb9614533e163564b9d3090cb00f253029a3a4042e2047cead0dcd42969685de183ded532773056cebbe0242e9bdbf079eb9c8b0a64df4833ad35fc40a317e99070683255e7087a0896b20e0b483410f9e4913bf36cd028555302162a6c6152803b31b8dede9717b80947efaa233f6324941e0714473c92da512fbec873e4b745505a5e691e2f1b6dc2e98d1cacf4c1a42dff6e360909bb82027b6ad070f34ea2d1bea39653da363b2dd14633f5d0f11cc1617ab8239e9832b162b2bc18d8703a39a21ac2ce9b1f23395225f6b34671d5e7679459e7f86391c80e2e3c350220f3f3cb40e575fd8afae3bbe1104246b092e405bb740e213734a5a171aeb6d82b185973a797cf3f17d77cee462e4f3032d053044aa6d8060928f6227bee4a2ad6f7cc6bf49df364cc75fdb9c9aefda07130967032ecb5a29b38bafd4e6755e2427585746460d696c9481db581ccd583311b68da1e80fc45b330e7fc6744105cf7f329effa8d05e5f04f891e6a45c0f620a1c516f22c796523a325d03aa141674b2d257074a20a7b14308310c73ccefa815f73715282cb467a763532504523a1b1fdcf2ed3af8381fa967e02294195a9d0eb43a1f5413be08d6e9ac6e95ebddb34f6962bb64dbde6e94bf734cca4cd1d70feb5b3525d1a4f8551facc79b5f00732cb252e9df686627a56b80b13fd033cf279cfc12ae321a0fa58da9df8da8e6f9f64214e40c22334f13bf1f6da122b4673deedbff3f98958b53af0f4b40158d79e63778123cc6dfd55f43f4bce42f318b0ac418dac56dd9436e78bb527c37dfc28180fed5c439f952931b29e271d83b633effe9809a6399282048357028ab1b540cc0510ee6b19a63643714857fe51c2b1b2963b7964cb602861e81eb52348453e9bc497c447e8a8eb73c79f3997ba17f35f32121ac7b0172845bd8caed56a79285e97d17aa467312c4d10b8bce1d18e416c383b128ded04fd1724a29cd8fe9377ead625ae91efff1a562e03d382e4b4621b28f717ac6fa928dac4a086aea4e122d59f28c961ace3dea0bfc79eb62a5702870bb86a8d82e6284b39f61d2c39b7d99eb65f319cce48af91a9028a48cae8c3c08134f7285c9e7161a570947fab3497f00476f9ede57415cf5889ec18501783af4c371a24560a3046a2683741e851ec1c34fe45c777ed5cb03dfb8ae6648a1224bfbc723f1a69a9edc5ef37147baa1a84b199be1dd645dcc0fba7ca9e8365309f3669b6d1d2e8a47e21d34d1405e6530e0d200dd9997ad72de1e70e660dcf53a6bc4bccd999214ef9206af79b44915e9956f8a019919290066728eb9ae5ccf073eefa4b9f771f584c03648cccfbc1823d118326d7488e2fdb2319df94a593ab0bb34c9970d038dddf2c174631f7b73eba3e6fdae9edee2ead25e57f4c498c32a567c546f089930cabc63db6421a25915714aeef8d9ccd320237cb0e4d302fe1c964c4aaa604714105a1228fe5ad6ca7f42fb2e07c7d6b0bae5f3b320f59e9821d0f66b702e0bef73c4f3d891454e90599f033a96da7df2faf22455f49e28b10ca126096573ceb1d4154791bd607ab67ddc372cdc3da2957e67ce2c599d50b90710895a934fe744c3cb75b1836eed5ac9a549c28930a6388a7c993c7d5a5aa302ee7bf08d177548ecd98c65152d6197286f52b57a3f918218fda1241e28c86201d6e3b6ca12d8e6756223bf9b19387c321db1a0ea2fdcb7a7705f7e8c81a998368a1cdb7788be5629a43704d8e91662b3e1a5ab205f85a27a139a5dd5e40cab92e6dcadb5be50ca3343905fd10ba97df8aa658634c914db6389809d9b18f59fbe371733e5ae1fb35f0f6230a2394119aca72cb11db8a0d0c82a0313562b97528fb50b99f21e3c4097366b763b0325a2f8875b32cd4beadb07925be74aa54aa89f9b52eb1394e1863899f04d7fb451fdb81fc4360a3320dc2a24b3b2c0fd463d9906b0797c3215595d59e5350da3a8cd519d51e76904a80d73a163b384fa68002516c7d7efb1f14aee9258b3aab9c5033b8d929430ef742cc88665799fb1207f2c8d333db1ac85d4c15235103d28b3769df98a763426546b21a8eb0f67872edc8c9d448b8c70d6f7af172d13c3aac5d4ae5bfc8ca9c891e501f2c473eac63cdc16a96b0f74cffb89211a411b0e6b4a0d794b5be83a7cdde651573a142789aaa6aaf76c7f6ba4851d1eedce7feb5f7a2c1179e351a6d97620395b96850238967e8264f581ba4ad4dc85933c874e30fa3adf74901f6ece0504879356a835eb019e12e5761f5555f63c91142c59cb32515de844c0284a31d5e148b694c53e3c69378a1c2880e893fce50f5ebb5b46b7ddc8753e7104f5effea9b0c36e3720469c3f20b8d97cd39c06cecf7881d20032be0f23ed939613cb0dc5ac81ece654aaf5ec36ba427cda4a0031328afc840ffda24b1829153682cbee0da142cfac74394c073def27b4b38f5cdc1c7b699d281d1fd41ac559410cba3330d16c74c8d035ef0210c8dd151a3850db594502d1d50c2959301c384da313611e361e71e937a5d1799d1a45398ce25b1111c86177152676d64393e6ed1f11821c1fb5dca4cddce3a3b1e28975d80dca762c79210222f6771d20ac64da695035d00dae321be393b17008e5f0037f4c1733e4a9f17ce275a85fb44ba59edf9e20403843b11863e4db333233314661bfaf853d6269b187bbb6c0eb0f510d4912645056813ad34cf3bfe5277c589a0314bae0aa802cff46b510c6c76938cb84e921f7b4cf4200da1a82942a807a2075c0f7dfebf768b54b2e308dc49488c4080d6c71c0bf8d773d5de3cd112c588a8ffe11d7a17534a6c7fef432c380ccf252a10d8cd1fa13a5cea6e546349923de83cceee44f2981984fef7144be4e72ea0c149458a7aa6648c9f658622c00be9d0074d3b0d498e475c8e4bfdc9ed4ce81d3aba532aabf7e18d5097ce37505c2dfe9df59a6bb30fe45d62c8a1f2b065ca8bf74f81bc3da5ea3bc5fe855ed0f0104574554480151238458b0d0dd6d493ec964a7462117237ea214ab8bb54b5a7d9e005f5606865f5c7c04adb7149725e02ae803000000000000c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945862d09879b6ff8bdded4f70af68cd3e81dc71a4c671032da6cd9224a5c6c1a660aa1393872b9170453d05c1f40ee3bcb8f727b3e196cbb9c72e7f12ea97080f67e003c99764d0dda139b3165da5dc4bf9700c6a563fcd0543f549e7b19d4cc4caf777c3aac4386f3bb692fd45d7197df5894f1c9545709c9c2255a3b6ed950385ba5a7c9c5fe91bfc671695898f78518380e34231b3e36a49b641cb3e940beec0062", - "040000007d24b5bfe1999a3b21189a3c4d4867784bc2105a0196aba2ba6fd1c9a63e22e1be3fd8ef559f3e7d94c5da9f3ffdb276804f413014d8bf07fe14907d6a37659320e538c79c0033eb2537c88a69d77f048cf4cc4fadd09c9bbb91b4d965ac8f2e0a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025200ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac000000000200000000000000000000000000000600008077777777d80a1977000000001c1d1c000000000002ef753da29c8538cbe9669c722c10bec5663e07d101f0a6c3f1f86440a7b00dbe374e5118632c4075f9e84b6c62791de12f1ec0e70e7d415d61c6639d786b1a0c0289051e9e5ef26a5dcbceee48051ae1ee91d70e02022fcf954f3d1190186523ec4cb0ad65db85d28e247bc1daf3fa5b111983e5d328166df852374f3efa9430f7e7d5ef94c51c82437ac68d11f78c190ff7314fdfe4fe007c0be3aeae7bc1094c0be2db5c7d2b24faddb22ac70bfa8499783f312f0bec068f8c09483f7b7edb6e63753d60feb460e2ea1f683740eded3d994f602670d174d38dd95b2a151d0b1d5f2592bd522084eba11fe9f8fb1eac057b84bde9119816ff74790db723529e8713c8daf25996fad08f2a78ceff248ccc91a83402b94311946343866a6dace2226d246cb8226f2bf7555640d4891457a7f6bb6c85962a5e482ec760b6d6483a15f6b44108c2096492765fea12c37da638a7add8d0b74b1bbeb5784c3712349881b78d229a682f024cb21c0c3961704a71ebd54be06a17f44b1fb1926844f14c3a9eceb626fcacc77ddb138846bb40f28daaf7e431d5d09d6f2be928bd09b03f6ee2302cf572c781cda2167d7d8e9b1f4667c8b3f7621c0cf85aeb45462eebe743a33bebb34a9d118cb2d4a69d2038d591e3266e77e122f9fb889ab83325e5d2ab3bea0e85e10cfdd1508d3233ede0b9de84634972e6d3cbcf9325407c43fba5c9dd30a70aece3ac6ac3d5598fd2dd29907584b85398cf21879b4e9ca3c2066e65fad046e788e56fd4a9098b5a4b0fbbe12c0f7c0b5caffbbfa69e4289c9cca89ffb3158dabeb2952a6af2bac251010a3644c01918e0198b835da28e26f694ca21d897785240d0477cadd8bd03bad34639189525c02fea6172168722cf2ae9a6b51412b4f9b24495b9b2852cf045c1acc6d97dd0d6746dd116cf8bbce3258c862e1fb18a4e91d9118c5741a38d6a7aed613910b11cb881cb6d1437669ad853512778ced215ff5b460a47cbfd30e86f9eec227fc123262d73f45d71e66f17492af0457191e797ac9fe6149f4b3cd631dce8f9844bf16588f55003371165f0e48562a11799c33c5b4e4dd390b3943fddf0162c033f0751530acaf5ac2530f320c157c498452ac5012adbde2cc19339fe82e1ee6245dcea9f587a40f3b78600de1209ef9eb6a903d267a95742c856aab1829fc8974731e49b6e8f674eefa81b23026d0bcb1d770c31a60232798a8828fecba930b51b80ae6b98645be3c5b80b195828dfab3bf8763ae660dbe4f02ed5b52abb301b18f3ebf8f1f81b8feeeed620809673472aedf9d70ac86268b7a162d0f46c0ff6bf52bf5dd289a9f34c19632198cf15730427971369cebadb6e943a6d8dfa84f83f2f6451e9d155449f6ff1b41f538eb760edccc3697ef679a586c8295afff2cd8de2ddcaabecdd1c0b41e8db2790ca35e263372e2aadc2b579fcd47d74bcfa188dabae48a78eb8e32e403a3f4bbf86b8535c568a332e0b64de3b3ba0e75a2ce01deefb1b1faa6fc59cf602d1359180616258847d458d03990f158398018e63abf87086caacdeeabf6daf6965d184bf8dac33b1c5af2223168e023a2f5021874300012761f400e35e341e3b54683442a1bbf7907060b54181d27021ea69caefe8326414462f03c44eacac9f26c8a37a8eae78c76dbe19d33f6b198e8a2f4d77a2d50bdc9785518a1e210fea6451bc05e85bd106737ad37e9c96105db1b9bb09bd7cecc45960de0bd6d803913fa43935a8c17de7bf573089ec323b1aba8f6eaf0603b91e53c540305cefe8361dfe47b787257add20569bcb7aad355d93dfe9d28443da5662fd1030a8e251fef553877edd1e1559bba63ebcec258035548d037eb34276f4b256b22631489e8f7201c86537a53502b6f9b4ae7c2a7272459a4df0d203b7399ca1bae6b5260566332b955e342132535e527fa207f8ec9b0bcf9442b7794160497121720d2fd698e3eee28fa34de2321afe580958dd133b1dd2b36afa84dbd004c4a571afa48466d3b7915c84753186b5a3e7b724a8fb8e411f8732b963fe81bbaa48b247330eec8a0897ebd64a25032e8aa4c987ff8153bb447308bb3cf5ab699504746794711928457df6e10d689d81cd6a846123375f5c46ed603f14b0ac6c9729075873179c3bae9740c273d0ec9e1ce060285211c4e60fbd2801cae6c7337570601712fb81abfc25d9a43464541e13bc42b02f01f8ec78a7e5dd3e84fa9576891397106427a6ef262e11f24a55af39caf98130c69bb042475834753518d2f67f66c04d81c574eaf7d8b83bb029f037c4999159186e170752880638619096dd852f29994be72f3a6922a97610fa11085d4288214fe131d2243929d40dd5915a6789c77a499f43489ec2a0b7ad37e7b5070000000000000000dcdeed4e7121d043c65c8049da787baf0bb29c59b75e9608dc59b97fb001c92ffde01cdc9b9d97951e4247bb513ff71eff5413fda3522232fb7d7bc48429bf301c3bbf60c1e5346e6b2412ec70d7ec4091384f5a9cd1feddbf9b02fa15e591c1f86bb9ee9b65bccc11ed903646e771b8d252e63306498d3b325c7cf46dd9e4f8e1e385bd5631b11f427848e7fa3bb78f8f97d090ff15457ddb0030fa9a8332dd2ed68ec267909771b6ee3edd3370ba34516a4a7171680d2d912e2fa4c966942b231609e3a4f5860f35991d117445464ebf6049e31d0b0eacd23a11122c2cce82c6f72a160e131c588770bc6df3888503df8add4f1285f1417543f380479052a2bf8597f56b0d5587578c3b896ed7bf0e057b9a39ca8ee3b1abc2bb967bf5fd7064150871024113211114f203ce5f150e30ff55747a6ecd17a342b77fc7c41ba70e1a216112048b26bea002606abde584d49e7cd633b7a5391290e7808978100e2d5f955cda22772bf642aa0e3b4e8f30edc8c9e6dc1d4952160377205a83730dc58516ad5d5f1b121f397aa2d43f47ff7a09b602b9c61958a3317d2316b9c8db14e40a53e88f1744655a81b850ed7c9388c5388da56e36ed67ec15e15b52cac4bf47a088df916d2c70c9bb348640cb429cbed26810d8fe2218424a6c63f1dfb5bfd3277bc64dd12ae6c088d7f55c4804f6c8bcfd6332bf4d6edbce09574a9c64d3fdb1e41c4d17a403646efc749f7ca43eaf94b014dd269c833ac3e19bc7442ab86b815a9eaa9efa44d01e69c77f73f600c5a911f6e50b5713d079c855ddcc2ba6462077f5d170cda9bf0eb8e477095aad7cd5c081864b328a9cefe21b44b53ae46d38a66f6aeded011536310c3bc0dcf64d2dd0c9015c6c2f83d36d146f9bc9f5a627dca73c5e092953815715ce9ad107d5450b84d449e0e93bf16a4e03d8b15d8b938216cd6c0bc08ccbba0658391f8d8cccfcecf77a85778b9904105bce80cd8c15e38114a80fb6e6870fbc92af588a905da1de9cd58d7c288e7cf406ef916c27b1b4b61fac457fa6390d7a7b6c14256c7a87fd510806be27244e778173f993bf86ff5cbe48b85178c8ba1d529a974a00995ccaf42b64d4e714fb5df79980d79492002f7e220dceb7a14769cff9c1dba91247cb300eb8bfcfc3a85e360266fc4b9f328ba12a6098aeebc67e4fc9aae6762defa078251a0d9653cdbec24fbe31ffa3ef322e6ba7c7114d0f642b72c7ea2688505047248fb18b8321959dec8693a1ab349c16770aaf10889e46d8d8f508f3233a69c9a820b88fce5d5ed044b9cd7420f456459d3ae87a23cc72d3d9c770f94c82224d95426e10107ceb351676c1dea9f252470ec81a9825bf0c2b4a3342ffd702cdb306a351ef3bdb56539da5022b878e08549a6ec8d8773b44c19281da0e307614f72a30e46b73f8db627c4ae9f530c0ea6ea523a6b857f96acdf37b42808ffd31fccef667f92d7ae7ee853233308d0e6a61fb0f78f1d0ee35278788dc3f7585fff3688ce16d40da875b756b2cf4aa33875e01404fe7c74614f184a5eb458acd986abc580f0cf2517110b9f1239615194055de68c7925573faef91ec11706d27b7b672b42b323c32b25a796e795baa58a7dcf5e19a46f21b27bb14e2db080ea704f7a1d15c2ff114964a65bb7429a216ff96939999a743316b073d63cf87ec39d924f6e7658f325dd6a77c9921b2b21f49a22b1d96155d1dc9a206a9d521a5b3372c397556febe9495bbad48c1d9a50f0578bf5e0fdaf8d0276c1fbcd0eda0a5b72ced1fcddd7f6dc0df854aae139d42527db885aaed6998cfe1daef4865a39fccbf57673eae767a975e43f1b198185b1e37a7d1afe476cc35602f148cfee549147584f19255d6cb3e31def73cef31e3adff8184109cffcb6aba6e268367a2f1d803604aefe48404ec5b431c13dbb14374dc9e118736b43f342a3c93f57c707f58dab5f2359f88b48eb85c37d052105bdabb93a8e1f2866330f5548252ffbfd62b448fdeb777168701bdc6136a22bcc048e3679f6098c00ca7151267a4bb1c6561685f5f6fba0d1976a6b7999257a1e4d5155020b124f65e43dc06da593c7fdd96c6fd84afe493d2ade3624fd7672fc0fa7c77d97bea5be3c865655cc77440c7d28ea2cff6eb9bcf85780f2ff0e4215c8c18f63012aa4067fc1524e81c1b9d2e08975b0305c2a1add51a9471c9181835d923cf51b854cc659616fc1932e4997b2b3b737e661945abeb0d9b1fe3c113c2b2a8b371d8630927bcc23c21faff67fc6680ea0b3468b8a0279e3e160629bfccc7f1aac37b5aba4e275cb9cb8ada5c99361c70125a45c0536a9467343dbf1a22610ee2da7ab15fb8d3c5680cc447458f81523ee75668a3f75302693169b7a20349c35b77ef8e99cd3c8b852e4d1871972415de7b9bc9859697d7eab02e559f03cd57fae9e5d3d692e617a2cfbdc34eee3c9db4efdad6f1fb19a7c4907db5173f80ec204fe16919bcca832722c58273f8fb67f69e5d8b24c285aa1a74581f0f9d1fc11b42f578a1eafe7a7dc2c6f11065697d3207585344122314bcd914733132cd0bf5a661eb329dae384c0a85f559932a49d31facb17189716a38b20e3f0c0f30ab4686e79cfe9ad03c00fb0d726991869b6c89ea25da9450c3d6cc5bba1bb17c7a3c38962361890e3f7e24ce94253f63e12dcff3e2c3d045ad05f45ad9349575c7ccd0cd82fdf1e083c56dfed867382a4cf758decef9c05bea3138ca4507b7f638edbfe8f1512911ec00d4379fa996b4d64060078b95064cc81e92aff21e4b30d0b848a8d8d5ceab8f665e686881a79bb390d75f94c593be007bcd38d10de1e750df1a9256375c15e2bed4da66082248abb6d6660ec9ef6351125c245527c3b13e22d77ab516f2457d890f9dd5a6c8d0a21a4d626a5fcfc4bc3a427b5d3581830e070fc6b4c0ac8038bfa1aa52b12b0329410b6b8d0d78407817ec0cd708eaa5215921b14e113e8ceee38318fe47f3cf5a58c1ab86a6eb7734170e55b5002ab3a48cefe62fc6c897aeae4ef82eee968be5b59bf329cca3d03ad5dd38dc287eeda31de96cfb4ee94eca046b1d9e83632f1ce043b7c65782940b60bc0f9f35cde82d5623c83c6d3540139ba820af7bdada01c22a2531b1e3171e6befc5b8289868ccceedb49fe28a32bee69055d5e167eeaeb320832e0da67d6f536b7ea5226e86420f72ee68978a460d1a5f5d0f22e7b3fb59f68489f757581bb4fa107c14829bf5b93ee95f76a84c2f08514f73aa5c062585b57b02de19dd4039afc4480d8666cef6de93ea111a934295350433ecb4d7cd9957a0cc739439bd5308449d3ab744b76f429b3997611e9edfcc49f021f65645ac5524ddbc8fe9f49d8820633ea37d9e9dd5bfef0912fdc1ba80500df637ca3701122f543e99df4f528519c6233fe9cc94e5d2591124212b6a7711cb083018647b0e7200811aa58b82b5fbb10d347fb64ddf7ecc1e526d69bf7d0bf9ac4287ac42db1e4e1d9037ed3d9624cd19c590c460c87c71e7c5055cf0b78318761a5e5b8ea36978ac18275470e04d8e3da440cc7fda0b2fb7857bc2a0bda4843a60d21c3bfaaf7e32f16de155a161e01392be4ef0ab5df2bf0b18a0aaddcc364acf987c625c20fcb90b22e3a0bd6fdd161780a58517012cbfd7086a042f1e13b3f337ed2dfb4f66635d188287bfdadc3bab7a139c3ed8d784c2773836618e440f2f5ecabb712c9116a0d8536419ce663402b427556e899d12be13a588c66565c60fa3ee42f5b21cd3a8febc2b906eb91a778baf31aceeb53acb3556007cd7752fcda896c3a4a41cee337e5e63a5bd7d3d9be234295ccc93a1cd3b4c171f3a7210306901bcaabea6776909baa057ec840813de6ca414318b10d18787403f9ae1a57d671cecb824163683d2e8f3d40cd916a9e6d63aaf5f69dac13bf6cbcf9562a915febaf7d95e8fdc956018e42276703719e4f0d7c698051290d59531e034f884fe7794175006fa69b6b09897979881187a31d33c3728eb87e0562213ae81f502108314c35d590b02b4484caf58925d3f9620e89d5e4272be9fc2bcd587d337de2b815b64ebb3dc542dda0e64ff6d6037fff10941f565cb6814ac3058945d4fdd79c3f97819906551441b1914a4b6c4346a34d7d05315eeffa813cf95b83767317386bc21f1456ccf52cc983777764c02dd9c5ebf3940c19c8d4cd2c1e6366935211884e8aee011aac2fddcb0646cfb290d3f7ac0ea8fd1ec20b57f67a28a470673c4c202eb57409ca729c4ffadcb1828daed09ec1223d758548e477e7e06f8d9015df9a40b964438b2c59261a8527d0755b468601d381e60826627dad42f680f33a83027246eaa154ae2cf04ce7cfd0eae34735da1ecd1b408f4d41a9278115695b16a248cb697366105585a863b4629f6a6899d77dca911091f73e33a812f5baa98b3460edecd6cf2bda734810a7412943426e8d8e00e24afacc681379b92978ec8e049f34b22de5488e9ab25a7bd135ddcb766dcc95ee688268ef957b83130c6869bcf0bf43d606209c5071b00e32a20cd6da4bd4cc5492f435a62561348e3769093639c533570f22b9ecda5aa7c2773753211c68672101694fa491eaec2005a9cc439f773801afe423675efc54e302fdb5e09b895316e7ac8898343bcdd91ad238211e3318ddfe0d86c5ae1c6d83d791c52d9b35496b8ed9978a1c7b5dd00bc6c9697f39247238c2042258025121816660ef0c53a49995cd9b45ba1712d45695472b69d6757e56c572c0f290ad6225d35ca5e5f564ad2c3ac7fb0aa41ac346ec3036adaab5000b9c58d8861aed031b0e627a1e665c36dfceebc558f59df5b6235ee823de9d185d171a9237a20811d9b5e4efe508fb9907d25b6849dedff9e8d71fd0b2cff2f8ea8cc1a7e98b204295f267dae98a6476d99f9eb73499fc918e2db191b9decac79eef1b046e9958c32ff1c8bca28c125b2b2340f980219d5cc979eeabf2b2dadec09e43ea4bb67b136dd30cfcda9dbb611d899e5c3656d46bca5b43affc771c9eb1697b10936d6922c17baf10888d8fc10b4a891d4bfe5ead9136c4f79215c61d4796897fb39834f0440db29202211d82d2b16e69d9398fe33e22959a4310d274c67a4dc9ae6acf72abd13a1afb5fc319c3d5ae89933158c91ffc851e5e5fc854b102a047a0d30211afda1cb548d279fc894f1002c3721e3229519b560f0a71bb648149bc763b3401b9ad57704139a85d936bd0879a820f90be6ea7d78b6fe1679d336dcc2f776a3373e473ab5ee54f5e0a8df6114fd0e2d88ed6e7035d232eae1e4d785b417a43e06bdf7bfc3509bb4ad808d39ca785673436a1009dcce6cd055f10439de64652c31dcac2b65ec47264fec73581f8598f8c318bc0f8d0eb929e7c4d6e5f012238e01e19b1fd6b54feb463912e6557b65741ff8919434e44e04e41a5caadb74f3cc0254541c06faa480499326b7146499b55a2fced4dd416d5a31779c8de5dea938385217832cbc605788ff4fa96e24fdc3875b52769db18abdc76a687974925a52081043864ee8e39574d7f27fac30650eabb1fe70d5d7bab946b234d1b8ee449f08654ac868a22839924b9e7b94175e60c5b575263089b525f40d6f76570d2740095a43696a90f486332f45f4f6ee2d1d55d4b3f2311637a9e73f921a56ea0529104573b25b2c48307adcbe3b2232cc04933dae07c34c491099c57dd7e4b393fe34db10623bb35b74ce92f8b1892d24b9fd88eb7cfc3d1791b0bc3bddebcf42592093e6ffde9f40766ad3c21a67caed25b8b250946ec46773565fdcc6305803362274e612308b8b767423afffdb27239f3b9bcb8e70bf0ee68cc8a1af4e59f6972d7c90b182d862066d1b83ec044b259b398840cc736ece77dac61d07e4b338083a97146137dce132a2a8a0255d1c5aea80b5e0095b6181dbdf1fa23317c74c0e25cb86b08c4136065729777527f49f407256d36049e4c236201174b312e80090376a2113d62058b659f63de5b8695e52fd178c573ae0e14f205cb2fd929c9f09079930738deea7a2090288911af17e157d6c9ea4bc04f6264c81e4f3b5b087fd17a7c0b7eb631c1d1476ddce8be398fb7f576f3f01f98b823b7e8eca7cb3831c0ed3c036219c94ecf5a0c2d112f788d73a432394247fc0244de10e28d4577ecc084c521f0007f3a6215a549abb3091e59c6d6cd674c8e5775acd276c980033df3c2143be0589f65da81bfab1dff81e6783f814980bed3cf47e51dda6424ff43c2a82e966c7ec5b197a73cc580919db591cc522f87a561ca46753679b8d26110d1667bbcc24706633f219617f620958cfc35c1d70e034c0555bf76d9d854f8e5a0a973b88cd6096e5f3d2a72f3196f4bd42b32d6849fd37d10df37225b0cfe05c1005ff528c59352ad6e319f77da2ddf1c94b8b7e7c7a25c7cd15121540f31ec51725e71924c3616257756be8d404b53cb3091c6c3a11940c44cc8808426305550f35f9a4c5322222e661561bdecd8ace024f4c2fffeb3bc1bfa7f69454f6699d36dc42f35d78130f04b39ef392c5969a4d8de6d5271ee7a32af3f311386857fc0c21d053bae00a066ada63a28fd84b0fae439f1060a7b633ea07813863162195125e00d9c2aa7f25c11c981794cc97718f22e3cdbd21701d6f6f5fc25885be6330ac8b8266bd64a227535648a926a002345e224cb6bb4ec6767c1f1511c2c1753def927f97f9fd620c27eae292cca484472b6fe5d68aa58d3fbc772153043073308ec7c0a37c5355c0bdd43179025aa0e8d492353849fd7accf1a0acb7507f11281ab671d69ceaabbf539eae572f0015426f5e9a57e8c4d4d92216a93027572c11172cfb505e590e4d5899aa663a5ea32d5cc163ebef26c92908e15fe3c0705d06e32504c7901bebbbe7de2bb3f5ec28dd50299d941b24242ea0e151d747e129357f4fd6c98876dd0779fe40a7cd386f198150b43d5fced11d2906915937905f104a9ab5f0d05ddf227110e72a6c80a7878e559b5d8b1fd632e851633256254a22608358228feba5055a91dcfa6f702d55b8a463f0e0dd4af11872694e1b38ce25e8f8b4ec993d38223eba5dbc585fdd5ba53b179c20a278181fe3a0d13a7feb333941b59748b2b06b2c51d6c52d0a8bdcf833628cc30787d9d16c0991bb5a523a92da788563800133ac376a6feb09a8ce1de5c1ac1ce128272cdacb42b9592611e34bb0848a05f3c69e274b33481fd2b351ce7562413c2b2eee4cde66944b64103734d44e69b9187d0c98ee204f539c59b2374eef044e731b1bb3d06465f37d16634579e24f7ba512a29204e0e3fe7d89809914e41b7ad8d17e5ac11af5246b2192c833af76bad3906f95683240ea619360d9a0ad9e7e97777e2797180447e13067cdd4efb5ee7429fc5b97e80d3f9b8396b8d2df51ac47b434ee0109b0eaa22f854d4de4ada9dcc003a4a8e147ceed375d607922b59a50312813519571e2a526774b1241513f77d2b53d3d435f141c55eddad14021ccc542ac37aea8e24b9331fcceaa35dec147c114e181e9a6800f1748c3aa1b425d532da7ed19bf10ec5304900d6f685acba0fed0d7bde86d5d5dab0fe046efe66fe78b886d24c097fa252a7a9151e7ba2cf15798d1cdc07904c8f32c1853b8e79be4d344b6d8820005ff2e11ceaa7833e1de67fa3f64637bf20963bea0a981ee810562a0b8b2dd532e01140421a975d2e7f39c3988e99e5cc8116cd9462e2f405121dea5a03616d7fcad17ba0956b84671d94c524efaa13b6b0bcc15b98b6433619bbfc9736d5432fc5237b9a018b716c2e08e4eac57d2b7c33ffd813816a0b01f7d09a5afa082e1d10a327247e0f086f3360dd6b9b736903a518390b887a6dd2f5cfa65322e5fe6dd801ce6ff44388ecfcc02ab12c562f55484cbda45465049da5aba32131491f3bfd92a1f9e85fef13e622e06445252fe64b42680ba24d09d0cf28c9f517a24ac14322d57761c1d53491940ce65df7c1ce7b6f766409f66f6ab4a9b455df1de0316ea2281d48f8f2bfa74f001509e7d2222b7931453759b1cb0ef887335e62bf97aeb1fae49095be74c11f89ae74297e22a342f60ff851f43c1e695080527747f9326097ef0a6838a1f46daab1f109c4e921beb2ea1cb6a334dedc57e55e58469aea61a185933a8a4c5fcb5366487d36541c46f12d8b830ab05c415cdafeb875eb2031e154fdde2d07437c0297ba56e4416cab08544013b2728a42ac6daac513c436f3e07dc6aeee0957297b17c242e221c41187df1fe919602d84805486c0dfe8ba108bc4c5b95c300bf121307d465a3b69f99fece83b1ddba11e3a8ebde80cedaa52c7b5acc9d0417064415bfb6d8ff6ff46444a62619c9321171883977194fddaa0fb059c29139fea48955b1ceddae3ac8051923472d23f06773f49e6624a8f2ba23b36a6c574d85b40f701d705c983ad5bce01bb2d031617bf8b2769ffc90d2ef086be32b2e84cad752afdee010c8e26ee09ea95e963b57e93188d4af84a71a5224e383a0dde184ed343fc59f77620045b9d6cffdb1a89ef0d5cb7e853810f24523a211f2a2fc19a49729d02fbc51b9674783ed4c7c0ef070c6b47413681ee65934cbc65777f92d13f01879a5851ca57501b5cd016cce8e9902f4379997d5c75b3558161552ebe9eb325a3ee76fe87bfde3d2cb44fb9009bcf14ea07900a9e120367d6a0253fba1b57f388efab647bcbad82a4ef8b5a7158c3d0ddfd134e568c937375a9df0304080a5ae883ec3661b176c272c7dd87aa40f209c9fef9d07bd102818b55f3e7a8c0e06dad914acae44f9023a04395e12b1d41b7d425634c748713a709547376cff51e864654c3b24b19d294b99c5e61abbc2f270163995512a5d042d94e1df1b49bc9f2fc814d7409f97758487ea49b276ce60ba980b9e2df67e1a186a18ea60ac743f45714b80eeb90cc06d7158f6cf09c54a858fef698ffe7032c22de1618bfd90bbe8dd7db0aba29f53abf0aca67e1471bee1c871bf3595f423213645b9dd88a4153c7dee3845194b496abcc0104997fc89eebd4fc72c5ca73cb5789cbbec9cdd9cb0cf9117718041860fb2073fb3842c45cd1a8e44a295b3166e1ab0a5a18aaf22575454d4d3750aa838944d1f5caf671d9402cf331785d83c50c29b2e49d402ce4ba32516fe1b37c463359d7cb780d3561ac8c6ecf1626d33aa1b482f343086e740be27175fbe1cc6ff2f798b9cc96e2d88baa6d80b0e443374cdc7f11cda7def2a1875595f6980d0779641c9777632f7a5aebeb48f3e9d01c187695217de185ea6c99cd47b321c53c26a83cd2f749612ca143a2a3a594c2e80c1ec90d98564f2a69e579f9713c20af6a559f541514a7514b8fd88165be486e825c3de6899e97f9e39a1654e51ed9690cefd5e225602e68480e9f2346b3f8d61268dc5f6add54484b7f4bf8fe086110f74183a0bc2515056f9a0bad6f4dbbd848d80df7a24d5d92a6b6b2b16fabc0486028a13b67a2bbe17f9812ccf6692327e78a5dfeb56feb6dda38c9ff2360062cf7128f357ab4b395b26880fdf80dd889ab809da70b1f58f5c1005a3e054f9c40691c287163f445610bdf0f14e6cb73e0eac5ab2fa5a9db4a9774c135e92200c27a34aaa2f3b9e2d568d28ae69652f1a351636492a590f79df0d4f9d589ba0651aa572a6cf9070a873ce75a200506ca74339dafbf0da6add65d5b5594b5b49bb0b63b398b44ff5f996115ce0d1b6f220b7b7b20049f5fc9f26e4fd8b7668578c4dda8365a9e79db99378091b3572473747ca3b4104e7b7bb1bc22988df73cc1e6fdb242c78804b4334550788a3e6a50a17fd8a0985f2449eb8554bc28c989cc1d9755aac8b33482d2c70525e102b4518f7aed260cbc6d6e7317a22e92b776183ccd105ac9bfbed1bbf0da4be0c0203a390cb9b488ed0aaa098ba8d5ebb9659fbf19b8cbc1b4d78edae8f5f272d2bf0303fdedd0e3de90ec360fced0ebbc85d612a9c396ba66cde481b92efc7ac9a1381dea34d170791896ea030cfce7234a0a2d2301bc79043aa7dfed6f3ea7bbe28a344a274fd9b9670b70cd74379a6fa1849a26609f1ef892c0073b7db34f09b8631af1884552a234f7f37263e04c61418b602bddc8561c0e097c5767fdeddc5deabac6308e5ae1c41565baa4d0bb33718486f3c655245f26b26a12becdc95a31819afa5729cbf3127bca5596f9d409301a32e80a3b7ec270b9387e88e9e1422b9ac903aab06f29970b50673222a3460acc1ed2a6ed45d10d3b42887d803e880f39141ce63b8d3fcaf49d87a9ec7f9720808aeaf8eab0ab37ab690f97cbc125be08fd6cd41df957059878d19b106b39e06bf30cc9d3c85f25de650f4afd295dc11025f9a72a5e46422d88c01972e22bf024fe61e0dfb824df1bf44d1f77db0118127ae48e2a145d82bcb537cc4be81e7bbe0e1d3e19b56537e7bee8931d4fc38a03d1c387079b64590d1f775566cf0a16ca2bbad3409c29ca616d8f91040a3ef52bd0b7fb2dea0b65f0841a03fcf8d25a6d7a0904a74ca61835e3e0734e4addddd167cbe9d3ccc89a0965191fd70065b0fc48f450ebd036f9c15039393ebd191a982fff506847cb3de8eed4cb8074da6076302b1e7623cbf5bb1ac4d6af09fad853100eb1aeb302717031608283897f3edb7e5b7f5768a363eb2bfe951b6a9c470d9abfad6ebabd17dadc0ec021684726a3f7daceb4acfed42084e70c8e721034f481300", - "04000000821ccb50796e05b15fde182e6e3170ad072e8c43cd976e191b214cc0b1bd9957f972fed3d6ea50bc8dc07827d9314a989ff91fdf51efc2506c098a000b9675c3e2ce3df4527cec45858a7a5313b87d0ee29b8e001768bc64da9b0416a06ec0210a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025300ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac000000000300000000000000000000000000000600008077777777d80a1977000000001c1d1c0000000000025ffd47baa3f5a5b90eeff3e0779f2d3563860fd5b9d7666cc06abf31b105a8140643a0cc5b44e881a3eead60361c59cc283f1fad00138eb02268408b29029232df48832e00e32157fd299f16bfd4482cc933ab2ff4cb953b162c8998e03a4d05bb13c472eb737e2e3cff834999cb5438003c74df6993c0579033e56a1fade81706ac0a77b99cb933f66906bfd2a2402c8739f844ee72d34ba50a1e1e9486a73e4c7a063267570a483bac82673d954ab903345b291266f89526184c5633a54bfaebc05f6cea64c403025806e65d8e89cbb0ca967dbefb653063a35597715c488891d19d68a5b7f0b74ca44b7552aea2308e325c71f7199ed497deb6c755c6727993f4d218e3128bbef26bd03941a19b344e8e629d81f15559abb7f6881ef7c688146640b02a0e5a9a78e8c587006eccd05bb1d5ee2ab8d1c743391970a0cfe2da89d18fbb51bf3d6b9fb9aa1818619406b89b53200b86d8b3094e46a01a67d63ff2b113b266cd38203f05bd01cce4e4f39a0072baf5f582315a98575332523e967e353cc3ef8d1df1d26dd79e5375cf9bd93f804e4d709004967bc70b3ae79bd7a9cb67cd273bf3df4e1218ec3f67dd9254b589fc73d5ce565e106eb6c6621a5c2438fe784eb5d95efff8e3b008a63bb1c329c5bba077bc756f875acc5d0eb0d02d67f2aa04738c8c625b56c82cab932b05ae2e50092322887318df508180080e1c7b80cf66894cac8de85931e7fedef575e2f7146ecc4658ae936a722548c527593bfdc59acb58ab6c4f360bc0ef75e3bd171c1c730a51749bc95bc2ab4eb7cc3792e107c31239e3711f35b3094c207d73cb0ceea7643d175cf97ae6d8d221f48fd048236449a28b497b36ed3c817c161d4ea89b7bae5170dfc9c33b3b08f0a38e964eabde9f4020eac2a7b480b9dbc7111d67b45997fb94f4244cb8bfefd0d6326a9da5203ad489ebb4e66f382a5bf82e9011e8d3a44cd8b6eaa60662d20be380bb5f474e5f8d70585cef0c5e490254ae896caa9bdc42b85c4fc0cdaace29679ade3adb96628241c509aa1adf1bdd633850f4df4b24765fc4dda5feddcaa6de3a55d58978cd71c9fdc5bfc77b33506ff8b198dbb4ba4cf3d6d4da3db5b76cfdb26379050cec5d43ecc5edb79d046e56ce8582078f6dae1f9802665db37c5285ab13076b7910c0d230f090375c46e44b0f142d540e32b8020f271de3f8ffcd2a9c8cbc1a7f5db56852ec2e9078731d724824ef0db06e8eebd7f111b7326a751086cde390eb42268a8dd44b7b9b1362a594858308abe397b2abc43a57612f98d027afbe7a5d3035c418bc32f556c8564c0901f9aa322de146697139f8801fe1f4836a800dd0eb2033d3b1c79b4f1b630b85a57a009c887eb4faaa0ae71aa5a1b9ce1dedecd5a9aeee985941c39fd28e2412193dbcd3a941c7d20e6ae310ed6082184c17dd2fca5fb27a1985843a6d92bfbea1c0ca8f7aa583e0336cb786cf38b893deef8f5d9a7ad8b096013090ce9224270c5ca0ed72961b44a2749eb99c23089258895392fc65c6181e59bdf0284a08b6bbcac67a394d3b73185f1c454ac279da8c360bd816131add0e86431a2f4bd018bf1e558bb79761851f9b6b1c198ece4e6ea28d4650ca1f5fbf1401306709d11c65829df6ff7b6a4b8bb55921ec2a3bd146728b717f31681c355cdcbd551e6f310a85ec235ba6014dd384c0118d9aec510c0ff524cc07a525b4e80cd1d2d51649cc6889b2240672cf91d9270ce131b10e839c5ba8dd5ae0bdfc943f9052aaf4e838cd0ad9074d845312f17f33a1333c5e580f48dd93b4c013ce245e807acc8e9bc89429027b3e782bd1054c1ed0b81c6f5b54184e7c0c3289dda890f9d5c21cbf13660d4a5634777d00944d6e9a91a560a7422b354fa46282871b9f29bf0dc7cba8547b19c53c16c5e9cf9986701d8d15ac5893d6f5827bb02e0eae3f589f4fcf153515406a1804d2cf8f62d765eb65e09d16c6dd3acca553ff0083ca089e62fa06898a1859d224d8f823f01ff17a2a53d2e27ba6eb1ace30b7f9a97049c581b912645ca1337d449fef95b61cee2b825716f8db4defd52709f08214e1be87c2a1fdce6c3225c10e72b0e8137dd99e2080a033af6eeb1ab4734cd25b822c7b6ab2060774df62fce9bdc9d238b679514b336dda53a630aaa419af1b4df7489bf0fa054c82bbcdded5f01eba9137164a023f495ddaaa883bc42edcc05c2361488731d9352278c9f9075197db5e29a1c87add4cadfe063c6a072f6e1fa9f8b1ddb2a5e46c7b3120627845eb9891cd09b299270c63f0147376065b406b531dbb2283bfbbd7f793de7f627685263d89308ac3896d62920ac548a7f97681b9c0b48671dbe6b6cdff66b3c80dd90b7f5aea8f2616a57f0c47f2375f070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c4e5f35dd019ce932c8d81f52f6ac4b4c7ad62d1513e1c5c445d10faaf17053387812744aea4097a7d1707dd944080558fe3569fccc6920fcc5edee87764c76b69c14f4fd2f140a5aa80078ac3bafab06214182cd9e26ab213ef6a424b4752d8b8b2b693f46bdd24a46bea270af5a4ff7fa74189ebcb1163d359d3dbfa7042509689bc397969857751feed4314241810eeccfd63998768b5a811277d852abb5a1e88196c0e6f98596ff2ecb67af89c3dd6568a4fc2e495559d85d9a043c117615fdc8135207ea0cac2c99648e6047226055013ba411abbe71fed3f3fb678bf99ac4d44d51224662036ac1be7e71d203934498d1f0489bd4e9f8463ce20e381a31cab6da793065a53353682f60fa162048ec3c278685200128c45ed315900a3111b2a3f36810bf78e75a36765a59b3e618177b61f6a90944e0e5973a573c9f048f17f1acb7a5e29889ceaa14f78ffcdbf9b83a3a8ee5233dde72047074853d78a6b7f5de7b73d0b861dfdedb8f2719ac647a67161803b611e5b80338be8f0012bbcbf1f5f05558b742a7d4271865a4e3c1fe55489ced6624aa329fedced737980ebcccee2210078dc20db162ee0da6d8f12d6293b9079bcd29416068e738f129991e084f498a98b41c4c7a8430ab26e0e06ed6115ff86611a29893b50c4190322ab26aa6a3ea878671fadb3b77b694dfb541dfd52d8e199569c800b003931def1aa79159208545edab077606d0f61947a571b6e7c0551002d739157c6f5fc1fd81a2e7172e9f480f0499f9162ff55146ea147508098c2ae0c723d8f113a9fc8db656a25264b4d4f1ff86acaa7498f351934e3fd113c2f8e45488360a40b0cd1e8be9ef9c323cad2df8c077fdb1ca88159d3339818c557e4ce14e8efa0a60f9ec0e474f05cf1478643238fe22a7ea8c74c555d37bb9555e9e733e07cbd25a3446847a3ed44d0390261cae0a92841eb6c49b20dba2869f3cdd0f33754e813f8b270d8d7c8c7a605541067e929ee330f34ee19f5de779bd0d74c4f82d97e0d794afac96f3184bf7456e8a6a1ae576889b198fe9d619425b3378e2b8cc97caae0497a3730f2adc1642f039a99b7df9d68e080e9ae10dfb93da507276b50644d8a963a0f381f5f2970725ce544f384ef4797e5cf686a0e242621501b3b5b58caeb4ce31d8dc19de210ac4744180a3698c1ccd5b68ba48edd1d242764e287d1b22262ca260c8e5d4c031a798684aaa48b739b19ea140db60fcc23cd4849deb5c3b3137331f2504ac002856a0e2a18bc613f2de3b0b615335755d9a7de9cf27d1ab273b93c87e0c03af4414f1586512fba9bba193ae17f636dbc8f2957bf28f31b2f7f53d3e4dd6f1ce49137a89a55549f23445de2650e4f1c00b22c6396c08a49e803505406be93b90080bc7e1317a4040810726d775090a6b8ff2ced7e1d150b21d3990d64cd3f943db519722fb8b4bc68656188e109fa6670235ff5f2261e4819b0a3ba1d15be9a6b39a07f579923924d4fecf753ff918356801b662ed3071753bc110adf8ace113d4bd09634b88a48095caa9ba92b2dc5bf8a59a2b7964861493ab25fc0e588f29bf7dc2b08fc95b27d8673685d313551aa6869ddf013253c6ccca39ca9bd71e3f31c77efb8b7a8a5d05afee6d24c027e0ceab5b3159632de281253ec3bbdffea8a9e761b4f1ee56047dbacbbf7d3c88240d18e4d2f625e24d2fd4922f81cd50895c276a738557723711934ea1705ef98a29d87527af74fabf3bee87f2813ded83917d8ebc2890f9dd3fe5d988aca61f771aba9df9455e22fff03e8565feafdb0619706f36b9dca969747e4061be9248ac3a23add9452f9830849e3e72c8a1b13873ed3759589e03f800f9209df6ff23edfedf91fb8eb35db90a1e31305ba079f6cfd6751c036a050c091081a7cd92f6a0b9099e3deba523218be28c11da50788de3f60ee17d78cb8d9f210365f94a9b938f37a5f4aa1c1637c596a04ac232242d6725b6b49b12208d10a47d8264c2346b598935fe0f43eb56e0361eea0a8a631562defff77b502e1cf0359bd42f1bf330664217a637476406e402ab0bcdada496cc5527f74b911a96d7b4b927a80fd918255830fcda63832500e53c4b5cdb90bc83099b65f18f4b84561aa54c7d2d969aa3464eaa220c59669baf9d7e08216d3b33c39f5573c41411f1a0a10c43eab6cb39be9baae5f828ce41e50352863a60c4575a4863482939f2d3e2db6414b0cf533468ca0f547d02030ec80c58632311a48ffe647a6ff5bf0defddee45927b9c888a8307ea592a3037261215036fd0b441aa141c7356d91031919b2f8e2f92af9134b9e42df419bd91cb582984da871da855643b4ff5bb4c5cd16a773c99688817fdd76b7faa1b0b1341de20e35209ab6a1016197fe373807f9e406214c7b9c0ae7aa8e4412c7330f88d053056363d0cb4ffe3c34b05727144ba6e418ff0c5236ff9a4bb716986c86694990d1887982d0d8c1caa1c471c793cea11b5fda1d346da4caa12e74f36a0fd8af52d743b9aabb1262ca1295342cef187f3fb13c1e565f7bb85863f86f93dddeb2613dc2aa2db4259e9c086ae837c4e8655a7e37a6e3801c6811718bf76704804fe276aaefa402ffbb5394227225f69e1adcc7556936bac642048dd86b35effc30b0723034ad8fac787a99022903d8b074cf8fdadb8ed3b8cbf75006acebf1d110534f3f533ae921c0b78ce67452adc26124ae25dd9bfaba7d4914b379360a812813d3f5743f889a442d4b6d437b1558b97e15a5db16296f36cf499417a484b4eed0ad96a626149a4d847df37d7a88f7e1773f89a26ff26e90b930fc2a8494cd6170479e0457a55b481b045dddf6e7362c99ab049d097d3251431e61242c819b4d22f70db675f50a7dea683a71b66f7f91c6ecb99c019d207a6edb7ca4f9ffeab7e29aaa723bb87f14efb2fdce5eca874cbe2e6f8a1801d1f7faad249cd9bbe72913f121b8ac6fe1446a0b182d661b0d8594f52e971955322c9c6595840aee5178518853df56c9676206ebaba2aa04f8a20960e2b5cc3be71681e85d686ee75cb2a39cb9b6eb6b0933f34a49487839995931a1c0c4f804c1f9dbc45c9996811926a0e8f9cddda2e7d6c946d70ccb58717660a1c8bbc7bdf868849de9198995148b210c81081f7515983e9e7cb807dad9da48aab614439811826d84a1f97515f915109383260e314f80fbf1f5606509db8f2103ea1788570dd8d452a8b2dd13fbf1538fa9cf2e9c9fa3d12362fa93d496d1d770c71516c794fa7a442c2fb0395afc70d900847ca74b989a9e400d3fd4c5ca81c2211c856126b72a296513fb401aeed0892efad767e23594b6c4da91e8e45779c76c6c94cd9a02d0adf3b9ded9bed2520064891d9fa14d4e26a311910148f057bfa59684b73813264a2a901d4f953040e2a277a15089841f12882b2e069f913787a37f7f9671be7747f7abce6a97e16183d03c5ca8f71f38824c0b2e197b57f5aab474201cfe23f90ca1e7a4f11e3733b1dcefd8652a7cf727c5ee648caaca370a20ef0e658334520c38d3c78870a9b3824ae09f4d0452dc5adfe57192007c4ee608e8594e7bcb5a8983004f2f0271b1a129b5c0f9a9a5435c9116c86bc33b1a2cca7b104cccd8e96a31618aa869f011056e5b876f257bf9557381e4e812ff830ed34ae2bfaab746c49e65b0811dab906967440a6850c570aa0a80f3bfe70996d14a1a9a3b356562a2bed99c40acaf107eae6809d0adfd64bbeb5045ba87073ed5714a13839906f11a0263fa078420606787ee1d0c1fd90dd8cd8f2f1c796604d54826d472df55ab8d72d20fafad1ae39c3dbf0d54c1b38d84e8ad9dccf402c27448364a7c30c169367386b9795f27e0b0b56b00facc89636a1b1391ca960f8e0fac566eadfe44aabdb359c9efa8d3d331b2b6105d5403730d9d180a6c65658565a1723d858425a078e6cd8d9a73c3e1fff7f57c2e12ba17ffa065efdefb1b78bd8f9221aaa227eb21bc4dec5d0d01011711bce5dfb699f2810f2fa15d955c9b71934b28e2bc0b1e37b075515690f870ca8324ffbb1ccce79a1fc706e78bbb465bc37034cd5d5dc6c390f1b41cbfb94256b64253f2f43657968313cb6908d8061db87209cf3da1050bb8a757dc765243e42590255037bfbec6701406049e81a5326d5f423a0f189ff94c32a333221882636fd5b98cdc9c14731eb93e9e3564b3b93ea155faf3eabafa21126a0d52c8c3b514080698bee3bba11f5ae26b5d20fc7f0ab3319bc5d6b5ff6d63a781cf1d02c570ad8d007a7c27e495437a2f6fa86f38e9343363ff315ebd95e23d57414a50dd97bb934b3ac9bc5b5cb6742c2f50d746590cdbec2cc2c025a1b6abcac53171c04ee700a6ea6096d462801d172680cdd919b21c80d7b0730642cdd53f10b420799c09b8e03e5a0ce59f1870fd90a5ea31dba28da6d43b278b39f0edd2d9fc82929e2f41d737dd9ad010c1bc06ecac08030713bbf9abd30e7f7bea89bf50f8020530dea34e2127c58e35d9268c1e7267cb00bfa9ebdbd929d5eb0f686d8927f28cd8e2d6487a99523fb8704f426d68d27fd8e843b880d5e1830d94c66537c36263e231c78baee3d32836658aa0cfa222377bed6912e61c6bf920e28421062dd1df2ca1fd3524ad599ed2ebf7ea512b7326e2b86a2724c74977cbcde823d5f1128c8061a4e6edd0e180ff55de5b77f37cf6c7b50f1be0b4d1d8b6ea176e14ef03593024fa9a801677a3ce854d53fb7dd0041f47c5c466a1ca103238ff5648bf52fccc159b34e16196d3e91ab6a92571211f3154ab9b44e25d546c0539e2c59b428d36e5c2cd272ed254500c49a6d09984e221fac248325ad848c01ade7319a3520c83cad8fade9995048fc2e377b91a0522200c1d3d38e54ce2315dba3d792c12d6759f17eef0edb7d502572f6e3f1bbddf2002e2807afe73cbcc481572ed55f11b920e0d25bfa52f10c00c175605eaeac91308d0512e298a055e05de156f0d633c3a0c73525e62d7e5c61edb032139f9aa7d55902a0fda39066fd662b782f4405041e3f54f29781b264c4194d1464335fea1e618ba2a6e5ba4b62c8a5f0d694254379ef615bbe3a66d75cc329f68aeeed52693d63a0f66f794d700f72d2edc303a6e57ae7f4c0987da01d7de8c60c263ffc64c01a92dc1f4d066e525ef07c602af211d442c45e23c1f78b9060a95f3f102b3557dd3fdf5e673b02a23f81d91639a936a656c0c877ea8ba7d235c78a91b09ee51db1e5e9919cac5febcbd39cb70c95ac9efb1c547e9a7f88399e5362dac5136b3fb3581cefb79994c01f07ce2434d891d7831fefbef2bc7983e7dbd9dcd83d8de60d0c68536e8fd5ea14f5d33b27fd3e2ba87cce7f94d9421210fc1989758efcfd4bb6ab8dac93be06477bf57c02840a3a6c7252a91bd612007b1e0568b0829ab2d41347594017d337f06db94c11c35ded31fa365b0874cbee6000b9ab06eecddaca8d0c8fc064e4ec96efdd9e2b6cc3992bc48220f8f1f6ef697063d0c46a617246641a73c6c3ab3d26bfaf8706dfd89adbee69abdd9f198419b0ea1e8510de1b92c616ee2eb2725334bbfee90c13fb8742087c0c70cde18a8576166601332aa002a347e65452e2a2237cee6705cec7a1e2425fa6044339b63bf5a047ba52a49ed6bd1e88e4d6ffce458480df30afaf3ac08037e0dbe7a6cc95c7842909db75c6d8e1731eefbe358d7773c71b1aeeb77c102780d48018f417edc1429ee3f3d18cdba62e6b0b4488684967e79520b4a1ba5a8df08f892253e1fed1915cdd201e87d75c6d1d2554a99a341e487a1654eda35019c7c38c86f5c75020f7f9619a61150d213b99b756924f5f9895e71f49d172a31028270f39dcc1ddf929992a516e4c270ac591674e6ba2c13dd06e0b506041e8942778deca31ddc84f4262ff4ad4d81e531cf16d4d041f3911441c12c77ed92459409ab65ed1949920a684e729d0904593d7a42ffbceed454a9cd23eb7e1742bbf6effde398f122a8443e86c272fdb97ef9455f33ec1161b73013800c40bda9d301d96758c6de69d103c430ee0192f74956b3d73cdf3cff36850d0192633385b19d546bc8f0b1f9e3524757f2d4245646a218b78e6a9f4e289b7882910167b2cca4ac0b90203e5ccf084ca174b16b6c0570f6d9c4e5f08815017f92a4aedd6d5cc3f40a4b9384a77405efb4b87a15caf74bc5d04197ca425592c0900484b814b3d1926954716e1df3b7017a22951344fdf52496f797562f397be1a3ef6bab299a518e7ccda7e5fdd166a6c3e94debb1930febcdc609b93dea783be0d009656909f18ed83eeac7cfdb0a5954dc8b9d604db26c6904d8ce0abbef49d005d2b718f92cb54a7adad0d106a0400ba35808525068312f938a58963d7266f1829495bce11d4c0c05073ff5a72bb508eee9fcf3bcaeba833bd03edd36a49272a1bd479d2408c272e3badb2ff2e6e036aae1ed1667b8bfd538889f705c624b93f37293759a9bc6b57833ea34b0973dfa3171bd9c81715bdcdd39a1a5a16645532b276af5eb53fa910f837f367301e75c8eaaf25dc6842212f5a43b71a6f76c92d600408f82c64dadddd2e72075a070e7e62baabb69fd006132d441c4f184c5d0f869993de13d03ae69b61956f37f191f05b24d242c23bcee76e5ae1726a296b1b15bae2365e9379db640dfeda8d9c7d12a653252a104891a78fd4aa3971af9731c00ee4e0c2f2a4e4fc6e50d67ab75024acfde2fcba159829904f9b27982f2e251f941d897bcec7ce91edf7156cb1754e27813c59d3bfae136b5fdc4ec32e7f17f5d4c4d078f68e91ead670d0cbb30054f2e90fcdf204ac0b99c8c435d932c10ba9267de7a61d791731e0d39b6927f8d8c4b395e03f239d84b717021375480b2c36e3b110777eda7b9e67fbeadb56cbd75ae21d5bbe2f95bd5a2d21ec1a5a403c619e55e46f332c9f98368823f03e4bbf12041f138dcdf2423400dd940062381e75ed02772618afbcf1bcdd949e34afa5bdd0c25b0addc12c1bff4e7faf0a1608d0a36b250d7997bb5711e1b6c74fbf391bff697982fa2b388f1c1934483517257f23bc65aa0e32b5631cb27606e552c49d8376d70c7dbd53570b8d92ea893d3c7b1bc8f62c174ac33faf08269b8d173605aa9a18d81fdbec0e392a6b0910443c504165eee0571388028e1512b8384f60cfcdaf2ea17b7e9c1be172676062a02de0409faeb6f0594e0fb6e696d6605dcf8a5be6115589e2322d7c838bb06f7908aab838bd06e720a051d07233bc7bda3bf1dd16820777d5f57d15d8ce486c9c0081681824871c37c137be3355e8587d12417caa506e3c14caf7a1e9f2d94d6c15e4fc132b2a62f4fef4d12d118ba9d39313a212980dd0f4d7a177cee3ed87f02812f6c2546004e10249c06aaa49a01657c7c7d2ef5c155310e2b69bf2e2b5ac3beea29add230e49ab31149447760e2c54745a77fc33127beb384adea5efd15e17aec6db9af767f1c1d5d7b2cb07c3b193acf0ab44c5804ae5c3e382538cbafa1ddfc31f1448eaea7b0a7504e9fc5256e4dfff39ee61145fe246856fc4fa93d22154068a45c9c12234f6e4aa3748b0a5418e4992a22eb18bb8033793715318370834424065bd4cab694acffa6f0448a61844d4328eb406b72b3c9b2b610b5eb50007bdfc74c7feade19a2459ac4b21856868aa06a2d175589dc86345b311df552ab8a56a724630d565e4ba55a1abb0946a0a8d6e2bc453d4dcebf1159c82b98816c8584ef251cacd77c3ffa104ffbaa96a90d876145fa73fc5fff5f5570a6d8d1580e1c4cce5b5f8e8a5d2b1d20b41b4009c79ebfd4a8e1636f6f93f12593f0532d565ccdf90ed011e0ab0fcb3db28f10535ef5e93f59851db610641feb3bba4190f3074e4257bdfed4f05a52c98c380a471bb3b952488283be1f14fcad4a3d219765b4b2b3421d5ef845f6c7b9ad6af6b66a75ef0c03ab4f2c5150c078068943d1e89d298524d9e9cc5b20c3bd03d89d7a6d3cf30b02e17516e0001b071b92a35d245e0c596071fb8dc53e53159eead8cf86441e0348a0a951d4a2ce30274b423bf3cef4e5969077107e166199d2c5714e25e2e0bbd8db356fcdcfb3d3b8b04066c193c83903ab0f0eb18d2faa428f3104af484d07a96e43ec593a5a9bc6d9c2176535fd5727a3acb3ab4b2e9e9a570f06455bf2b68cbe461743af5466bf7f8050f5c7710b8cd086922c098d4c9c26e53708c5523c0739705505aac79ef65781f226761215eec4cb44f8317b2fffdb15dec242532c0cc8db35c117a35278c54034cdb69bb5df20b8cc8f1eff23bb6e8b929a130e44e0b0812e937fc89b3de0a13afe080628083e386b703ff58a07fb599b66605d12342bcd8fbe69ef239f3ec30bb2fba014ab66bd3344d60786edcd434fd3a19f46353cc0c7901e051405544028bb9dbb1ba427c4b6e6b5a3ec8a593f0832d6a61692d72bc6faf044ee5664b1a7b5a3d38fd1a1b436b833287a162ae7851085a1f63bae8f2fe18b09c603ff33bf0b5ddd6cee3a4b4275348c9835ef59b44f2db1f828f77d0b7d8df70487c91205dd731d9d516d9cb6fd88080f45312c10edc4cb8729c7e71fc9fa87808bf3a3099918984a60eccb1ce433aef537927236f3e0f59fc922b0ff7d0b39fa53f7c19b5048f8fd2e9a3cbdb8e6d7d156b697bd7242355bce57cb3d94d16a5f9adc607288f3ec2641d42eb3303e0344ffe4e4cad5d58be766687da989e8448a5cc7c1ca4ddb0e6cb4f4d22104b1d32f6dc3632fa7012ed5e9d5a2111dcfb62c7666e1bedb86bd966f9caadc2ba81da0488c78352f7d3ad94f35fb75a12272754630a20e42a38a52c4934c5d3bea8631f590e31ac72b485478b7d8ba786e2bbdcff8d22a0082034283aad9f28adf92604124062230891d81f71872c135d234bcb76e82dcfaa6969b84c9171805683b4a419f41a830bd88a76618ae387e3a69254ee920a1375d8362b4e038a2e2b4a98b1c181ae9e5f24b19b07c5d46bd50d0e1e37502646eceabe404904f3813c243675a8322f853d45614c7d56fb8667badf80b87b10ca9d2363e37281fbebfaa303a7366de81d92fdb81edae1f057fd933523dd0a0b88f33140db7acf9131d23420c2b976156d2bfd785e9c8c7c7a520abf8b58d204ef04b5f5f9424c5f305ec6d97f582627a9f7b1d124dbbe6bbd4a36340292b70be4278a0bf1833f90bec6598d3a85fd10c37d2c7fccb02e440deaf2f191492c242d84f09ec1e0a034843a5fffa7c63cca1be0c6c378ce3ca56bde144d25b52412b27185ea5d4a3f4764ee54f0bc70c489f6d81e8a9c7208638f9a3a0bac5ff8b857a74cf8363d05ee1d8f3a166cd50701e0fe692879ce79a3d691424066b749abc3e738d5647bb844731b409cde36b48e420348197710106d7cc0d216cdc677b81c4300b93de75630c4b3e117cf10b678e538db372b2304f314a19d41b5534d9213d408155635a716fe42fa7a03ad90cf8866c124e99a66405883e8bb6f9a502937e18db7c266d8cdd119d12c7121c580f83c2be68d9a65744d77e15c337fe898e1b2fadd3b48b4e03d08d4cbb2bd50f567c1913084eeb5dd249c81b71a1d3a20e2c0d6a8fb7f2099c60904310e9416d9b34407ab6d32fe2bba4cfcf688c5c92b34fa937b7c5345fc8724085c893a5ee567bf6e3b2c1adae130a72f2a3a16d8920cd7e6b93ddd1352a13b1505cc0cf4b00a3ae34a00cb2f85591672068027403537fd0721374d5936ac968952ce66bdf64318c927bb6c184a880fa15e384a3112b78c3969161d05b00c431ff94c55f794c150ff7bcb35265782fbc6ef4903632144809ddbbe3d801f67d840f06a15f966775826cc19fd1f431d9b2dc8b552ba3b28eb47a6b96a038432ce40c84eec8854e48d1172af6aa5719778915b64cbf2bdfd1df50cc32b2736181d4664ed8bfae97f49c20e30bf9c4ea8e67b53fe74afb41c63b12c30eae8c890a5ca1bebc6ea3d553f500b755430896246cf8f4577b3975759e150ec920229f0909348a612900466b5d66e5e2d331d6d9aafabb50bdab70c93cb2d3f6647ff3e399e06946844e96897d74d22795ed647aef1526ccf5dace92d9f5578c19b0d4747d50ab9442ccbd04807a28a35e0df84cd1d4e9c8dc025717871bf8a9f9495ea8d6f6d1687cb1b3c2a6ccb25924ea8c6ad9dc62bd510325df9f6c52c391218b8fb35468e6a855878f17f6d83f866cffa34a2d1f3c21e17cf28514bc1b80740721f43424681e4b421367c296b90a75a116d59c3bc06aa93cf2d809158a67ce2ae3ce452706f919af9669e0f7ed795a3c0316b4ad876d292063107e29e7374826e95233a7e66a89cc7fb4a6d96487f2f2fb1d68df0c0092201b68d49a7d03461d3fd5927b89fe693bbdd3cd201155aef2f533edd651b1802f530b807760dfe1b4385c3ed4000f6a8118b0a3df4c412e79944e444fe063d340f4871ba816c772ce322db4e55348b6e5046b1e6cdb665ef7731e4dc58c93a21102ead248952e94d44bd8357a49f2641bb636285ea307eebf48939441ee1e31a03adf3198df993b59a995d271e9b851fdeac457d6355f9c207292515c0ac2b3801c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce9458607000000000000009ff3604b2c9238c3575aaba36bf28511d83a0aaf443d53981899c20be308112327ed070500b374e359a90435a60363235ca445da700abc2c3b962e89ddae2404000600008077777777d80a1977000000001c1d1c00000000000234ba607b674dd1faf18173ab52cb86ada65b24659b7ab0db262a4d46ef6307813610d535a38b024b19e566c3d73cb49c5dc6a73457c658fa61aa19c9a669d70823c009c26d2c4c5949f83ffb187b8d03a7e05970d87668b9ebb172e5b44c4f300bffbdba179aceb954a3d6da0cc8e9f59587e9a4ab1e9578466bc9eb508b791bc0497d33ffab8b845eed45ec6d6d9072da6064b0afe5eca2b8e3caa4801e04990e2ce95ee1594a1f922a2ad1e0550fa5268c2e1486785a68ad25200e0d1a1fff176fbd7f928197be17c9ea0d4b2f1987cb4c5d4e62ddd8001803e1672d2509ce5607d0ada2ebfd792a4eada56d50babab5b04f4999d97a78f2fc35e1ff001aef6c11bca252ab1f6959508604fd29f29642562b862c9d326655c735e7e9ff0e5b539d819b0ff9b7594947225abffd69d94748a59b5e4798eb4f0d9f41848da1acc1c42ba1af1a4e69227887f00de8aad96af6043998f72164b95e9157ef40f3253d38dd577c636fb694a49fbbeb14a153d3615454c5ed2913c49454efa45880b7e81c288c34793ab18eb68dddb3b5eb8c6f9ef4889d0fb8d3a2dd58164e5edb536fc705b63b194f2dcf384c026004d3aff29e11cdd17ac5c71c26d30ef20b5c157fa9c1c4b33d9bb95cc5882bd36d990fb12700baf432d820f66283742ef447d962088dddc54a21b162d0ed191f12d4b335b4227aef5583bd2a7639a275dd3c6397d11baf62a2983eb982d0d4e5bc64f8bdfb72a5b7f99c81c4af1395d153c9535ae61358ea5fd933e1ca35dfb4344a3a096236e9c777626575f9773f1ed0e64c7e67616b36b48d9f481453f8815d4e48601961cce17d7e5cb37be71839a205a208fd7d35652247b32d384453f30376c2b0dde5d64285c86ea396bf919978de33d5959c7a2bf9fb5e15da56ba2b11b805789d994dd44b5b39952d90bb9cbe0209c63123cec7ff2f2da1c1ebc0930b0e3a03b90dd6e58bf83187e7b71a9a5264fbbfeb90c57647c5d6de4752ccdf657a95007a21a6d8e4910ae99c90e98bef3ba13ae57614499747369bae218a8fcbdf074b48a5f374f74e769d02af067b82283116764abbd30fdc9923a3995d144bf1033ab26d3197ab184748b4992bfb51b0ea22cf3bb574236f2209a2e1391f153b706d5b7640e8a23778332fbdcb1e35cdee0bdfa55c35b02b793b6f2fb01893363d01388391479aee427cc977bef4cdd250e78a7f0f39e711aeb13be5f9a895792dae2657ac2789d2f0a5b0b7a9093fdafe072883f6842e377b05a046488db93fc23002a40a7315e284aa164b2e144cd5ffc6afc8584eb5d52b21b48a924e257b72a180792eb6f8f0a5220c0db0fdf5f5d0a0aecdde7f194e88369ee5d2efda82edf85e8d20b69680c677a4ed53eb33475b9beca2c560386cceb4ddfbd30292b111c37530ae6ee207b87fe5b67b5a90943e2a3c43c66eb8f9b1b006fe008f9da8791e71915349b9a9652d9c508adab7668438eafbfb46288de70ea1f96a32d36ea48e0dfc3fbafa1ea69d28f2b3b1e291a02823229ab70510e1fc102e5df0f6160c7af5ce67e8a6dbdf5e486d285f2b4ebcfcf2c10426ec94e0886edbcc0727b0703ee6ba3a1f7d4a5ceab9386123e531cab919407eba95c72314e0237e4208e22981b912ed9c2b4cac88a8592fb62d648846bf411b886a6b89b83ad03210cf072b00019dc6d0e541b6bb9a22ac9b3603ac0ede0b27cf0998333446344fa2cb44350f9dbc5d557cbdb74d335c6bb398ecd2eef9686763c1f21a34970e810a8eff7b37947fd455ada6010eb00ed5f1f92395ff7d1fa77b05beac74c53db704530f54a5947187366dedae6d48386d68c303b5eeac6e4848607890ad4c4ec6fe25251b4727e8cd22d8fc8972840fc8d5887ce647ad628b298e15f9cdd49b917887e0f8e8ebe0312fd04f3871c68f402f8dcfee60e81283a66f1725ce579861c999ede9f9e2d976a83253ea608b66ccd6ac83359bae0d060adb0f5573ca385446cf54f14fa3231830ba0243fd574aa8ab787ef0150be0cb9c38970043d6fe200fbb6d03158f33f5e3a811887ca482b83122242d228451449593c8dfb33190298e873d49c01b8d0b9ce8851e60e65308325bf3a934054fcc53e791fb117dec249e9836d466ec94188df94077762d8c12e8cfcbac6a9af9741395ee566c26f9e5ef21d7e08a0453fd22ed3228f9118bf2606e87e0e0d1e495075f348b16701162640d2b805fd4d2d3890cd6bfd5afb790ee9163e30d55f8015ee86b07d063dd0398366e4cea8379c951160896d3374b1c39093954117d7e3840715e3018b917c6ddf9c47869bb01a71793b2d414c252cf62e9d781e29137f59978d39b8ff60d45540bdd2dfc73dd0bacb811267b486783e9e9a0d0d5a2a161e082adaa070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c02f3f899fc0cfbb1beb2f0a6b1364b43fbfd5e372a1b64b90685c1b0750cf93993917608f18aca5ec561fec653860b83841a345f03b0e9ad5360c2616b8b511f973cb8eaa583b1e65825fb0cde26316a897f759b9c79d96d4bcaec217948791d524ca3ba26457a5b6f5278171729abc58fcfc844a5e2e9ff048bb334bd46692d97beb0e892e144acb380a1a2810048d5b4226ce2b4f9bd020ae4b26ef3d03419236d3862dde808d4fbc7187da8d7a63c5154c369f26a905f355469a0db4e562de2ead4d75b8693256748db27c5d041f6bd93bc97c7cf7a6f2c2966c29817bc398cf4a61ff5c81b66a7c725dc820e24ccbb2402b16e8a5a9e0d676193924ecb3a48bed2157a84205b689c5f673b45f5cf8589d2e048366b6e3ef58a6cfab7781e90d5f0f2922fa407d0882daf4644908abfbc5da2bc90c09be46ecd7667947d00094c2024142dc31a072b758c2b4c5306e458256fda993ea15295f970f480cd333f986e7f633ba84f8981266e9db3b78a3fa87052a648fa99c4dcb5d1420da4bac5c6ffe822276ffdd6de43f39987e9ffb1562c8e136ec163623c1ef0b957bfb67cd4af92e6433d2b3c757be0b74d7053fee3d1833bea1b076b4e2e878b68be8b661b0c54f6cf9e3bec410ee0a65c0371b4cee0f3cf196d88ac4ef5ca02a42e352785e77307367dbdeb20cc0aaf0be2f72ddb4b12cb9d1e7ed530eeef35a44daf8d80446626e90ff4d6705317ddea944a45e094901680b89133957343b5209a0146722d0d494c9fa805231b072740b15fdb7a1e0dba39015437cb2e61f0cca0179c0128c874cdcb3e4c377925a097d46a2ea86ebcb2aaac4e69b8d93f3f813fa110857017ec1126b0f48e1b61ef1ee9f2d3288a1ba037b28294d381855a9db1a44f6aa83f17773222761fad2add32acb500f060e76600b50779934496796f4c86114c123c55b42ce44d600055e9e249fe7d5f1a80f54d49e5b0dfd71518a7669538471b5e759dfb425c51d742df88cd4237000e0989d5e554f698d0112bd61a33a307b36b22a76aa8e2938e884191321c09c1d90a5678e903a5b76446698e5031233ad87218bf81d1f49cac719c2b27afcc4a191daca45a1c9f51425cf48008a1a569e2adae4627c233bbd024ef0f7c3973ba5bbf9fa0704e111223cce823d50b5d91fc0d805e0bc51daf91f0375b6feb67ed3a729933f275fdde5f8c1885cb9275fbfe2796b9cb4dc5d3eedd1044ffe62bb5a4f20c0969ecce5a0233c5a7740f9f18ba0a6c9a38ffe4b0e5377e6e84e659ece4b09a516f1f5e158f633a18b527ae8cb2813b6fc27f5108a7230bb2ccd25f9934b0899ce9c8cb3d5afa146791b52509aa6f78f02904882b0730d1a8630eb2c3e408aed611ab9cdede995bd2ab2940dcb74cbad21b1a8c27bcdd2b3758c61e5c0d271dda23139fdfa17fe97f19358fd6e4e6efcf71996b359eaea79979375a010436dc45f4ab138d7426f806450b624c14febce156041a32539494b096a3210d114d203df26b1cc826fa2946f53b2521ddeffc30550bb2d26dbd6900c912852b1741e76aa7f77b6c4aaafd16760429d5ce5d3cecaa3e1ff1d3399dd2e4bb0123d668b63b61bed7b097daf5a4710e82dcae3e2db6fd652bcfa527938559d83ae86982f26cffd2be75bb6f842883ac73819dc831dac60616f3c85011bc5139d67254cee29b964ab71fce45fba367356f2122a61544345df6d07f423d13bb32c328125323ff62ec30d67cfafde6eb20c8bf832b8a51e3de2726ba66fb6a0224da5f79286ab7861dac4d7fcc85c62f85fe476216c55ee4e5ebb7ecd3f642c547ec45844ec95586eac20c1834a5abb0ab3901c50deeee97ebd64d9980c53e0b8ff88e2273331b1484adc54fd459eaed17ade204477a17b54cfac56fd8d05f3ff4edc2e473295817cc00ab5c34806f1e370a9f97dc474e0d4e6955f915cd6d2069df587eb0650c72b4d2454142230623070f6d21be2bdd0173bb0a959990d9d250e47a2148b42030900e9e7014806e22ae690eafac7a2b3fbf45d6b51dfecbbd21993a12e057c82425533990c8b5c238a6d329c4c41387bd693ec77f1d6d200f17a86063111051f7090c2bfa3ed2a58ea8d22015a2cff83e127edc0383eac49c3b6caf9b5e0ab4abe911658ab63925d60842f70fe83f9ce4258bb79b6311bff08b231078eb8eff59e9dbc955af596ea7acd15fa8b8e1ba88e110ac383eeecca4340797afebeca8fa7c5839a3a306d4bb8004cdcd0372d83cf4e2214394cc2a09252971cd530af7802ac06d57fa0784500c40581efce6bcc497fae84e8bbdfaac727bac1cc0d49c0fadd64639c6c839f6b3e4735074e5f2cd2b5fe6fc9cc34152d723f1e1ef3fede91d41cf39a8207ad69044d14925961ca8b535362da356e419de13adc49ddf8708b82e6ba3b5609ae6110f28333601eed005b94b0d31699c8a687ae732b7d7bb263081cdabb462241911bba94585d0e20c9b41f4d8d5565e70bf351ea95382544864f4a960b8850fd5095213c2bb602338ab2a3f9b1fd97e8d42f68f2f943441ded01beb76f463997f1709e92c9e6df0341cc64ce46bee5ae1ccf0037b77ea00edf62f5f545d16bd063bd9097ef8eaa34d9dd1cb7b2d7f080fe56d14e4eb521da00c7c1d19c13e934601f963f80fe122c184cbc0047fd38cc0a7b4389debb41f44c7cccb596c41936e2fc672796877e1f0d013df6aa65a8d39c60e49eaaaf4bbcab70fa97a0b864aad214ba57bf5ba65abe585e52fec23b33a8fec951699fa4ef19e4af9e7c237248e1f4a71e6166133b2f1b6949d70f072170002b3d38dfaccb3843e641e85bedcde02e289d94ab76f935ced360b5b4abcd503d274923c222d757f8436e97156e067037c7c984ebb22b836bde9b5aefd12b6f079dbab91f69bd904facc456154ca3a1730b6fc7095af42e8e20d0b94ee3c797049971d28d583d5d1d7b539e8794a7710c2de9d2a9db9e6842f7a6a410b9df0f16fdf6bb58c35ca3a7d44b965f04e5e0391f7ab9789ca3f88973b59f50cf46f0d472e4cf49cd81c1b05d8640d625d601155db952b3544d54e5742be75a4bc9cf0d1084bc141b76cbb06290971fa526001e135397dfaadbb5865bb00fc424700901c4e50c7aa4db925b9b7fb0d8631b311fb820bceed1f83a6c166f78819a059017c7e7bc0b134aafbcb063ed15ff67f165441f7015d9a3514ad604c82e400703302c8e2e2bfbf738ef380e6f690392712d64c59fca62f638f2dd8edbb842a7ceafc4926febecfe42d5327af88fa21a9320d1f590803f35b2ecae7e605f0aaf99504537de024e600435f4963aae484cc3f6620243c307ad03f87bbb60696bf1b66409b143dd80362b48e74627ba790e700b4a6d10a4961fd6e4d954af5e585e44a02dc9137a9f2c5b2f09c5edd52924a0f62e0db46f2eb9c15ce3e9940f16a4c7c4be030c02182b2aef10f01de089f380e8afe59f6ace4c9f34738d041cfa61e19a64156a675832d16f4ee54526e0b7c39a8f48dbba330e8ef36b5564d263060c90009a367bfc4a9d1fa7e7903d0de3b2a68de720b8bf070f456306084485cb3858e98004be70aea72b6d0200def4f340ec415fdd2bcaf28eb60a1c2854fe016de38232c721b6d3f3325a101b77ded810b660a83f31c46a5f13a5a08aa6df7da23d0eba9fcbb45ff299761741ca950e12f2f1881946ed0c16f62139d03b430d1dedc3e7f7c68f2bd50993adeeeaad42315b36e0e592b42f1caa568156ea7aaba4072425cc227be504ae30f50335793483ae94a208efe33d61a1bd8cf95db05914e3b732a6c2ea57180dd5421a85a94ca2a97c80a41c04484c5552bd6489ca235c28d773a4d5122d93fbbcfcf8707b88f3d2604da1a47cee05bb3a9fce7528905b5a279a51b44a72a7bfcc9d1769db1813e161dee4387ebefb87805c1bc133b7cf56d549d165356bd3c24b4fd4cbb7a920cca8bd5e43b14557d48c1131a5ec93b3dd64a8d0791d9e50f4f501a5c858f2110418e110a74f7469c1b2ecb54c929d4c08927ff36c4106d696b6758823b235b2a0704d52ad4da79b09c140c266153e7e54ffe69776b2fb97ae8d605c37142c40bd45690f4207e4d3905cc0e69f548c9ec024a2ddddff639d148577de8be4a322d756efa88eaa2e92f2edf13a664924d341a8f95760db3d00329c8f882c24ced3ae07c89e35d51b7e11b0d1e53270bb0523ddde6e95ef8a0c05d2d2b6ba7c6ec169202e6102335e193e302b8c460ed998878abfb1db24e1797d1e7605e13598923a088f38ee8d824d556ebca3d36311acdc402555cc962cdd10936bb4e1ece2e39a6078516e98169fc31fabca7a0edacc689d6a5b4fe2475c0c73ce3d8510bb903260e1e381fc5fa6ea920c8bd2a8ec145eb778f9891d840ba5a3f08b0f6dd3f07e753899c30fe2b565e821fefe44cadf2117d358a2447b0d8ce48f742325b7d358a96536be71ba650ebc36783be0ecd540fb04bdd6a4cc39073df2b9a5ed9b23a4e2cd9ffdbc2967e690188dfc052f21bc49e9c81be87d12b4ea1a770e108d50de901bbb0d046c50a4228254aa095f0cef9d608b0ef50208b0eed938cc7d136207105030c72580f3d5c707b62090a29415e32af9066217272ea6cd498b5c1a81d06314c21406328037ddfa23222cc84c3afbf8cd1c3762faf04352bc37910971404fd446bc4beaa71b98135724118a1dc65ffb937d5310fe1f40c307095f0d3314199773a33bd6e2c89405f48bf12d6651d789e66f1820cdabb6107bdb309b937d8e0f513fef644f96b702e509903ce203c95a10ec4c9f4a71e75c9495038b423de361a86cea19cc2cb4f1f1874e672b2b2e97ee9462090f0639864e95331262a4a560c9948f3c74db29b1d979b7648a7a18536d7f6d8d2fd422f7070756835185866ac588a4daa8094185982d0879768320c5a05a95f1a761a9042efb4e291395bcfe4924fd4df12b131c3520fa984499532946adcfe20cd2fa56d8d44296926284e91509bf8ae72338c28b93974700af04d3ca38f55824ad9f52bd0e6b05f2c7bd8d324b4bfd657855c8cd458baea1bac09386c4444cff7594a870650c1e524230b2a26d865605eee5a016efeedc957effda3d1c145ad66982ad9188bb80c2d1546650750c7e79416c80d7ac102b47bc7798048489afde2f8461a9162997824253047f3d0b0148160aca7c533bdb6710281b42e64ab5eb5194a78d4244e601b67451ddf954d429fa006f25e09ef2a78388c6dca6228f17e3fe61510038f162626435783cba9d6809fb7b50fc1bcfb6231466454b5925c32d04c02e5bac1903df02e8b2ef25e64fb78d7daba63afe4bce774148ae824c62d778d88b6d6c7723cd5d56278b36058f492e4dcd6cb898414f521d9a21cde732aceb5a62adb996f1e18d950a982f9fee6c02750b13965ee93d80751116df1a5884ee24d05f0a74a3faee0198fa1f42bc5241dcdc623ab172dacf6108535f92e0279b9ceb96395073a5b009395aaf3ce8df09add65b351f341d2600351d24d3474f7d123fa7e51f017b0a0b90c4cdcc5db57927d8e87319914fb60ca897c7642e0e323376070cd6f05fec5e74c88c3175010761c7f1ac3c00e263611050c29a932af6cc7908eea6d1e2cefe518c6092cbf7fe7a6c5b0b821aadf6f4c504a1de79e723b5c17bd68d634d7b18b4b9955b37d765c464dcaaab31b9613567d37640e3b7ba9c2abc9b8ad3fbe2ee8b62b4ec7223792f76658bccff7069454442873c81104f5859de761160347deb9e1390544369afd02640ad5f6868e92c2d576a13808199a53fcff7863344ece1634086ca08e72b8d8dad0c11744ca5889437dc482375b6371f12853a22b37ee12ac0bf851194eca88f4e711d6c010135c46cac6c4b6d4d22ded888f4306369c5e7b716720ddcfd1550760b2674eae607713c5696f43d84af2d853505636f0aa30d128cd5ea230bff5a9322b0f38fc998eb902fa2e66a5cdf573b67faf264bd8aee6a7baaa4607ca070939347511a3e7fcc1c2aed75942bf4b02a7a3680f21e60ba2c3fb198e823ef8742241a5193df74d2fd25e4d28080588ed992440022cac1c026a3bf2c1de232751ee2c56381cc320b8511846093b8c82c3b69bee0a5703ebce82d93c99555970e5f192bf4c1438ef3d583f40e8b4042138963b862055a0a8b1df6cad65b82d57850dc251e50508dcf9d58c60b4d6d5f706b10bbb25717263300d3b432ccb759ddbd52e5dc847469dbe7db86ed6d35997f93f8cc939ea38e0eefecedb429e6ed8b028a6ba59954ad0b1345816bb14ef04d6d922770d40b19adfd065256ac351479ec65435951bb014a5fdee04be55231894b9390a28c7823bcb54409faa06f1c3da22ec89f0f9421fa9a33bc840a1362863b549360829e94a149010328b366b45d94e44b03182eb30c63fc967159c1df1386350c53d8f249a1d5cf7529434d61cf0085c59fd02171e5af8f1c82f63d8fbabf8f07622899eb8d01eca1fc6e242d202799005db7e6d26f734d6963a81ab2cf54936440914330b0a7a64f4c785c0958d72e82720124629c630ebe6c2fa7efa9e2272c234db67c5049db7b62f7e1eb3bbbdbfb842fa3df06ac020f84fac21207504412516cf601b65700c971606725d4fc31c4ef15a6635efde36696e339f2cfd775184233eba170149c0d215428706551ada80a5e9509949d22eeb0ff390d1d172b7033c153fadbd3f158b87cb300dea6364874ae86b93e5863f46d3fa2a0c507b4c382a46e0f953854689ce9b7f2a30945ac9ab4848297b833b4fedd6f839ef106a7028f1469d0950628256fec62aa432d6c0a85c3c4f5a6b792c12992a84ce000e6c1aeb6bd6c354960d9a741e0ef483a723762006e291f5950075e35b4223c471cd23733b1dddf91eeca80a4535db48fea257297e0b02eeeeb3da56c2b7acc338240f0e1eff611efae168d566dcb55b9a9d569539031fc4100eb6ca194a369c1330395dfc82e506d8669ae0b80d185a1f037fea20a2cc16da225b6e3ebe2dea684a032dd222dc5df9679f927887e0323e2be5c6b5db8b45640bc9fa099432d28c833a00b04697cd0817b118b78aa4a1ed51dcfe3fc69560b06c859284c8581b6ba223af7d55a3c623400aa0a30fbf3756e3d167100f5739ec9f7fcab49e5164b08b3628f9de44f0e7fd887a88b54305cd1c57a7b9b4ae5547dc617b4aa616b02fd638f4d030b7d9394929abe4264653c79bab88d1210197fe186b41c32c4ffe2827174edabc9cb926173a4afcfdc16e9386d2c2867d9d07d014161ba69169d51d61056d0e3d4c6f7e2fd93d244df132e72f560569889d635cd192f7c6c75fa777570aa806c5c9ec31b9432ad8070eb1474e9d685eb85116aef47ec47eb621c33a38301ae2348233d3b49ac13e64c70d4c4d594927cf3508f8ca6c040e71c95963820d7a70f22fe3120ad893234799be5de84d096b5b8961cdf8b09a52eefb994f433ee5b57ed74f1eda8d6894d2d19fd1faec1d6f34aa175e4b3a8298159f8a6e4130c3d2100d2c9ba994be1e20367f5d587d34ad6c2b00078ae1fc589c77ef3c3d2f0819eeccff1e7b686308122d9d8504b39be1bc01425d29147ad7e24db8c1c132b955ab073d37fc1a83a12d4155f747ffb33779b2f58e4c862d97bfee479631188a1c888ae437b39bf9f197fda0ce1708be825c4eb5bcf8c419b7f44d1be60c224b70e8536ba3f0eb79d6255438988b420f80a81c2f986a8abc2a7c60bf54f0027e1c190c4a8711fbc8551441c6640130372c515be3f22cb10fb9b53223096821a135a309f40922d5cbc2acd57e0d7cbec9d47837ae1465312424a77c6be3451090277f17d6225a0d634455659903b1bc51e79c1330a70d6139e9d7fac08e5928f23d2c10c6268ebbfda4cc45948a33a263f672a523125d188f64c9c01b2ef801686f5fd26321808e96e07433968d05a44864eddc2d190155cd3266c23778dd1cf843a779f77919c8e7a5560dfebc817d703f3eeaa802c613992e5ee2ba6ae90600125b1aa07f04902c524d3cf57e1461d9895461117ec413fb3537752d755737738bebbe1135afa71db91e93f33771d16ab3134f0d6d588dfe23ec6661698421c010d43df3dd7e9c422f8b1e34ad0953e9fe8d7ce81f4b0a62334f5229c6b11fbf5889642660619a2c1f0e98fc561836f62f61861712455a193e54e7c4fe6f1052296ee852b33ded957545dea80dc5f0c97cbda1d7a6a74ae0f482a59e8cb33bb42522b6652eae4ffa1184a2de0e215a662edc4731a0e6042a69f93fa68cc9088fca3e3d8473d5aaabc62ee5956144fd68eacf289eabfe35e6112e919837b82d7084db1a4cfd8e1a86c4ea3b90b890aac23156b50e21f293d0091cb71822592ff9c0493c1dbfd67640a5da51820cbdf5b86bdfcf47065c715bdf265190284a0b73ae525c70e05f0b35f67f8d8652f31cb650c02195c931546a32dc64207c2e0bc73fc8158e7188e8dcb8e258236356ebe5e35361b0bd759fc8652773690a2908ccc0ebd47a889f3ab783f4f3cf12738b7b2323680c69eb1f28688820c02c601f93ccb28717da6b6e5ac20fbaf7fb283784370fd30fed3aa8e0b485027dda030449a6abeb922c705c903a2f349dfb075b9ce0c18e90df690fad3177e02ee6ef19ce602f6cf463ca06a38203017ebfd02519b5b607a11718243b01084656792f3bec57956232f1c5f6ea03fe34bed97e55a8ab67741617263ab232293b19fac40daa9688655da4d37882b0b21980dd5201b4fcef42e0c038e8033a024c787ec218988b08396e9a621ac4374b10bd13d521b52f0afccb3efa4681e8f6ca1fd2152142c89c09aa954cf4c5e4073fdc99cb6cd151458b59552f0ac5f61888679ffc3711d4b806e756a77f31c993ec9239927414ec4fe996e7fc498cecacc56b30440add6f71b02bc34f3705681e7e19cd3722febf38b6ecc25398bb9b527c77fce532371b2463d4fd5a8d0f1dbf97b95eb59acf0281d7805f99e519aa4efb65699a2b2ed89cc8af53bc305bc1a4f750a953086fab18a36eace7e0311de9a6d400042c17846ede3f280a7ab4dda32bbf364fad1722b5bbdc0bab21aba5e4f43b243b2165258d04633957684ae38ab2b101914a21dc1bdc31423f7748d0e36ba5d3201552a2aa76507dc1d4b4d92c4f16329c00c167765ee4f340a281f1f3d73478bd1a0d31ad5bc40969f7ae3cfed770c1b9eea1d75b8b655bfb6932610eec0d5ab113b12dd78802355c2cc8e71427ddbed5ce2cf37d454fe788c09772ce1668b9d120d1cf5f9b0503b193b2378df3b292666df3df011ec6b94271a61fae493f6f92a7308f733d9a12fd7b5596db6a6285d44ea2a0ad64d329ceeff2296a403a730c2a18881d32ebfd93d502d54021471ab8f9473af265b6e42c1fb98c1767a92d5613e29d270a27af9fa8a71f666fe1766d071813b2156e912182a7aa914439c96ab469a576c17510f1617b4536f69c2ded22c1d50d7482cb7fbcde67af59ea734f3742a0e375c7e0210ae4ecff0f818f71b270d49137e46a6ab38afffc1e24cbbd1719870d3e86dc6ff5d1bd5411bb64dd569d593e4c248415f7d59339ff83a749b6a05dd86280bab71b975247de7eb838de56281ca26849ecb8e86cf7bf9a0cae3d93acb75b4af9a46f93c830ccb8c922facef21700878b23cd313fedda6ab91908b77f5142bd60e02deb87c4a2e80b25fc7c51982d1a700fc827a45cf4114305bbb485f8a04e9a4c576365222319432630051ceea8dbcbd0513366fe622b7c15b9c5b9c7697fa7ee201eae4aad0423bb61b96652b3f1e19a5670bad143d6d8b90a9472a2f0177fae07a68dce0172384663be8e4099ec3c154e81a0a2a42363569f8f4030ab4bba6ecede9447835cd97adce8f030e3abf7fe531c9b63a81a5285bf7b45c1f3599a59c5a6ecb70cd6a747b61245e673243b55bf0bf824bc01b754810a19812c082b2252e891d98896999590ce20c9cf78be0e86967f099849b7613ac45084d0c4b7490389500f296efcc38e69fccacd8a9cb3df706bc09c399886164afd22de21676d0fdb93fee1efaf2d363e2ee83295c2bfcdfd4bcce1f0197c9052a92b3ad4032d871562d7c46a0d7deb229244414be672c0dd9a0de1cdd818b8b498ecbf1c786d53e82bb1dfa187d22b4bae3179d56ca4fdd6f8f2d4c81df80726dfcf243829c33d23b77b8d039b0d169c5613ecde639a30eec12dbd364bdca747e8bbf610033c8a02b1f2763aa9a63806d07364d24228d7ba621133ec01c79059f65c54748703fc60eecc810382fbd160a8df4dcd47aa57f640f5ffd74a1f94f9a56156f7c0c6e34fdd6e43a5a0ac46b71474140fb8f16c10aab75678875f19fa82dad79a6cd284c78488aee66c5279d16acb21b8db2df30327783b64335934d7db219dc6846d9199329fa8f8e8a949863b39c03bbf8d83850920f4e87f41bc8f14c5fe3541444af632f5df9866dcae93493fae87809f16ee551bac8c4ddd0bce15ff7be0e573cd46fbac5fc7f4b764f46fd3bb09ab24bbbd9c38ee0f648386d892a90165e2acc2e5057c7aef96648ae013178932d6eab4b60d94555a7f380201c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945860300000000000000af3ce8279bc3e39954527b6314ce47076c97b16c3577c2e7ef014a9f62bb1e248ebb21fb1ca0aea57f0a3df15877c9de9751b1767d705d511fb67eec61dfd42f00" + "0400000027e30134d620e9fe61f719938320bab63e7e72c91b5e23025676f90ed8119f02c71c7ffa660028b5f3bc0b0bedf9b76a829ce8f2ef82c2c69ab6948bc9fd00a80000000000000000000000000000000000000000000000000000000000000000f2fa494d3fa60c200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025100ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000001000000000000000000000000000006000080f8694a1277777777000000001c1d1c000000000002000adfbfe7961473dc7f8ffd411b3e2eeb005a37342e6081d5121f18f5648c8480adb28949796e09a38118152905839afc125618be1fdaf921d188488b607f2544e12a249ab310f17a9349bfe463c7de09d2b822ab0efa88b6d32f77d7c38793192b944aeec0ca94918390dbe44c50e706407692e348ed9b7cedd231941a673722ef1e7e74888672b2b2d08c97a9ac114b7039feffbeb8bbe197db4a0bca8d395cd40551c1d5d788acc2ad09eddda73a5948de2d9e2d82aa638dad6f5dc61042d6850b926d944f29f17e96eca84684252c97ce4382f2642e54208929a4b37954e8e386c677f2aee3e8f4f4aee9f76a87d868fa2210445c09b927b842485918c869a23be8213ae21937a8ca83406fab193cecfd3fcf3b1c698e8057a6c87c059dc6f4ccb30af8e608a7c04088cf3ca32ab20cd780da9443606b092c8b5d85c9a76433c0993e3eee385884ce1f3890abf95462c49bed01a3a5c09df98cb7082e9770bdee196f8b968003f5cc76d82bf575f01da3ed40e44b3b15721f4a9dd5ecd14fb71a42b24ccb7d7e6a3bc10b53ebcb7e0ec6ace91dbc19801eff0c76ec0c10602bca2cfce9f3e79536a25143d351ed2894b4eb4e549960f212f0787057ab1ac8b249c3d3ff8652cb3fb17d7656d50c5e6833b056feb26855332f60e7b8d1ebba32df63d8561fd7d209a1e5adb9853bb5b5d6a41bf1ec52d348023e945bc02e8d6ae8d5b6c7a9225991cca4aa0b41861f237b3bf545220799f152767c7fdcc693a989057e119c18a96007c69c8fe5751a4258ec3f0f99c1aea8dbbaf4df9953ccf6b42cf2f4265011ca89ec7b9ef2c6e9410886291054f50db6310b225ddf32f9db26416da6ca9ef6e3198db36ebab9802517aeaf628d41358fd141dda8fab32fcded20707abc3d00191e0b2690a1e2fa044814191323155fb21e3da8798e0bafef8c2da4c73f967504f51e716cf87117f90fd028df17f3ea26aebeda7f5b3192cd5f4855044e9a41bbfb817074ca1680a458338b191a9619dd337bd0335cb1896d79c79cce10e454b58fecb1cf10da9f53129bbf3cae2bde82007ed98505f16922b6ae53a3a709c2e01ff7e529925d6069807c06bb0c73abf8d463b2a944a97d150935cc76e1ae1f8f95159a928a5afbf76d54544a771fd4bc482ca522274b94c87b4f1c7cc3399709b5572c5133bc945cca63bad59b454ee301e3582f09c5c31f326a59705a2b534d8e9a79835bf767ea563b0aa74d3301c40a303f6fc04ba0f3807c5decb6743aabfed1a092f88975820c324e2229829462e4985e299c2415eccbdbb4ff26789b74e91db286e6a4af023e8a18e826e930d9d4ac8d92cd8a1098d0705852cda367ba067e723ace9ea8b9502e20e6519dc72b1cb477c4f3091ae4d20eb7401acac77d923eaf5de00ecbb61baa3aca9044f3e66262245aa9f3dce1d02a88e8c26b34e3c27b4e4e5f91cb633c9b6e098063d052dd6883d4c2b153c739ef78c5f375c640ff747adc1110de2f9d011118f3208bee2f3af9990d56ecddab1cfde0c053020b1116afdec7a3303fffe6f6880072482f95aa3115724814aa5fad017e3b7637f3dba509f1e371c9b87a275cfceb68aa5317dbac0e1959367d124935c76631b8aeb532d99c393374f214af2d6a3a5bf4071d97b6ad39b5b2ec03f1feb520ce467808eb2cedb3ec933c20322bcd4511b838de111f9faafb5d45ffd8edbb1fe8f0928d535ab9809b4cbf588af635419b10f7ad9f4418c766d88526215b74518cb6554e833ada2dea5e57776a09541d76ba545f8a727bbe7722912cf00da4a48a462a5b7b13c88941762462142f97e8da2b358435c9cb53d24b6443ea2e1bdaaf6ce58dbd0bcc598cf170a193e14e76ca8bde66ccc786bd330c6ce61db5f202b01c7faf185877e3614c1a1b4484cae6dbef080142f8c45e3e48485746fd3505bba099ae7b37b96e22b2cfe6a0dea5b017974126259d5055a28ad510b3b7116c27287fb7e635f1918d5a9ca2529b1741c9e86c59ddf11c3f70a56fac7c9607eb9bb36612494ed1ae819c092cfff73b7c9c5d3e8680dbe73f92b749c84363c374d80632fc488d0b7d35f25ecac1c151ad8427d7a4eacf24fa6937fd5c416776654bcfae92d999b51c49d76bd53a9d5600b40915acab5d31f0ea3f7a68adccbb72cb454164beb35819af0e9e06ecb40e96c9c2aa8018883301f65cfbaa7ea894737d49b44aa5d76c4b26bbb6de7126bf785fc2a8760ce1664150be0b6828659513561b52906e6a4782732749897a41ffce670736ce0baf5730fce9bcb50a44e1e9bba166f4812ecfdbc2ddd8483405cd2bc68ac179177e1713220348da35c7b2a30c9ad9670d99a53a3c4c4a611fcefe9e39024732d6996568f2fd8eca433a41664b070000000000000000ae2935f1dfd8a24aed7c70df7de3a668eb7a49b1319880dde2bbd9031ae5d82ffde01c599a33ae69b9dcc093a546efd4cdc2c8daa0479ccdc63123cbd0622fa54f8c15ce9a049727b659c998b2fc935ddfae5788c51772e00dd8fafb91e7b9e7b9d4a34efad77ea3f54eaf8bb5bfd4c5d5ec6761689042ec6b1639e79d2628e712669e32f33d058707141549b0a0fc31d9fe4a633871d1ca48096cd8272f735a0838bc1a440947547ce52183863bf080eba73bb36f5130d7dc8676be2e28d00714dc36ccc580d88f6d878357e7121a811a03eb12faddcb75c9c3703ccc4afdaa85101244e619f565a5635e6b8c856fda2edfc27b5c06a711730beb1c361a6a916fd713ba64385734b8563775d66adace055205c6cf9a6c90faca0629e7b93511d0e51e3405210bc3d3c590ead6671e57af44a9418a5d3c6369d5b6d294032f1592c601c2782f5e5fb7ef820f548a7e21661944982f5b04f8722ebf42456df6748a2f9ba2b816bfdfe1432f6c4911daec2b75802d43000403272e1de73bfd625b9742b8970133c0599a17cb7fd7984d6a3da82e845e179ea888019c6d86016cbef610a7a0e3409f0a2bac1181ce62a22fe3fdad2708225ec503077caf354dc5c12f6fad975509172383e2f87405fc7c387b1de333f435426fa3b8a524cea377f3c24690918a4ea2dbf4940ded498169b9b85adcd9d37175ac43897abea5d629775f4f9792d2ece6ff69dec38e38d0c1c9e40dd2967aa103a20a148290a9b89ea82e1bb5235bfd29d260862365933e19f81eb19be2c775707433d66c15f68e5bb8a578a925f20e9d1bc34132c5a214ade50ff48489b89cb674fd3a9c787d0ab539849aa19486e3d4081d4f361517f45fa35168e0432fbb69251a6a7e8f5d33b30564338f693e636d04203502588b4e9128744f49005a77e5de0f79e06053c01e82f4bc29f0bdaf3292c300030eb758fe2a7e98f41f0db618ecb99924e25084b0e69da78bb4918b365b8c613ff5e033d4994e176b5abe710fa552b3e5e21f59a33e4e0aad74c0504c2eeffcf213301b35d9b0bd3c7d140c849012b1fa7ee177e994366b9b278afd94f6bf9a65bbd1cfcf5f3525512e5b257f6a5cd61c43ff2c695cd9571d8d0e24bff92a5ace203d9a643b7c52d794b3a6a2f0cdc6c8c1527e51b32847935dd0c12b1f1aef49cc40d4318b5b067ab9d238e7dc4a8903d8ed224c15ed66b11043fb6ca6109587b6210027df615ef57125d696d0de758be6e4b1693e260589e441ebb020177a4bc7c577a7f2c7d415e00fe93cf1436bf13f738f0cb7d0448074f1436457dfdc03217b585d133dd44928779072129072c0cf0ad9ff3fdbc686f12d219313ceb77e01846f030d631c8014987081a1e3659239e009105143ff3fd3d999fb10e1a1b8f0adce31db881d5da746138462e5a1b45d47862fff760d3b1ae1de946257f2f0edd1bb911495fe1a24ec3a7cd5285e5bb25ac1d206d2f926f9dfd574758a6eb2ee5faed26e5a8e07dbeb11ba4dcfad69d93cc718fca7658b97384a243589699547d476887de967e325ba5e3b982b079eddf83998849579a849dbd3f2f487eaf9242512899756352f3680f334e0585bd43a3439bd62404297912e545e7c18e0c2e19714752b7525bebea1d83222648bc9457ff3fed4c91b1fabc6c88b5c3805dde0267f72a0abba1715fcbacce4253881625026ec2e240e8bb98c5316d28d361a91a1a572caa057492fec8d5e8d8b51f5890515186f7c97ba4a3810f40e9916567ea7a1980fd806d295c73a8b1243b538c373f531994507ae50889cddbe473a8dac128c98eeaa965cb0cdec2dce36fae175334b1dccd48839b7d28292a7c753cf23990d111e518a4260631d5a99a28f3bfd01db75d8271d08556abef553106fdc472ae97b5f4d2d3741a5104d06560d85f48d3e3acb040c3264d37f370f2acbff61ed733f655d8815983c7e78942131b41645f1ddcb24711ef39dede1317c4d7dd9b01f77066b9f3714b5f09dbb35e8341188e4384bad7238d9ef7d73e2055bb9e6706a90348ae9e5057780666f3642d7a18085e115e5ea3447fdd013a7d976d00e39edee09b271286c1a325161d3d6eac566cb86c5af3d287b5a56dcc48faec1d8342bf3c5436ccf03c0b47cb880aa7001e2c5464a406e24dfd9d021e62558e3cc9ae3228f03ddab021d5519fb426551e0a39ad08f68229662f16b79b7653b8f827a8527f1dc556a02f9e3c7d0f3872467a60340dbb0641d91d6956a33f5c905069ac39e67b40fc8d5dc617e00e89dd926bac628eb187ca1d0c41972b73b628f18159633c6d4697893bab32cb760a193b57034804a66381e62bebd6b729294bb14a113c5750a2bbdb57d40ec9e37ce7f3a486b920bf2972779b88d4ffd3136e2c10286682a4c413ed2991ce333060be5e348dde9eaded10e4cfc84ab1b157713936149239477a0b5a437574a45f24843ec4a525a71813c05c2524b92c893cb6aa0dda8df21d550371f5ac622038baef7071007a31cc486158ca1a8ec2a0c274ea26100fcfa5a3991b6f79384ae487975207d2b0b068df60c7bd63c014d13d2b5215ba7be1802b78742cee248c07cb00f3d5472dde9f85a1a9a323125a3cca08fe5c8d89f73c3fb600a4a3c7f28f12ccdac1e911c8d62242deb1ceb63eb40ffad0ae8845cc9efe69e9f5a7d2cb9910306e16b529d8e16e235e8e54eb84859d4346bfbfbefd453f9a4c8f4cc5c6c80a616433dbbcbb512651578d1d2736f513afa0fc68b401b53086d4a32d2a73100b59f8c07c06f43d17d2021fdc15410e22b5911b3572d5f7996703e97d24699da3fe7714ce74a1daa802609cc631db787abb71504d8c016cb7f5973c0d5f91899bbb100b97d4063ca590d15f176612d2e8779f89132428c6a17ce0dcab8ca081b9d891d3d0cd0bc755a193c5d5180d28d917ea7c5121c702e7c66a58b5499ba4fae3336a2040c986afd2f44d92047b338db4b6b3b6c176d88c641a6d9b4d4749654d55785002b3201ba3eb86562adf07f94b3e39bb3304a2d022a872ae74cbf27f0194c5c73037bca2d3daf1150aee2f81991aecca23660de5072568652037ce13944ec9d75f7cf424607e36233008df0a9707913985b837c631288ac62c253c9cc1586706b9e8238bb0d3d14fcfad900dff65772b36ca252d9f81450ec29d6be025262bc1104a1643c099b3bae8914c8c78cf39d09907d725a52f3ef3a9981c2dec6cccb88017805cf2163e8909eb0822c34d2b42ed08af78dbae9484e7e4faaf2a40b0762f23b491a2ccbdb5cdb4df184b2b70cd39b0fd39b8a50e4cc527f4c6169e79e9c1cca54900a1624e198a0214d8013c017a2dad0aea1521269505213c1c873cb5531b6dcaf1c5430d741514e49e7f3c0f7bea8c9e3ecddacc99e2a8e729f8a0e9c87687f11158aaa9a7159ca567598add54fdb1a58eb08da87154c59bb9214e9d63fc280ce2fe1300b12d4b805d2d992a5e5f74b04e6b41ef9e4f364aaf3f90aad6435d7662d5639882f9edf5dc7ae1e5623fb1cfd9578fbe00cf82353ecf865d9ea24b5d5050e6f7609205b2ef209c57df854ab27f2dbf047e69666ecb731f0b11e540edc105301dd9b915fb4fb1d96f4f8b99b9c42f55f99cedb22638167927766642f0c1f6c4038d4ebc8dfacf6a3ea59532d6275fa5947cc80f44650719be2802f83f62b86776c7a8ac0b92305c69583eb7b1457e21760890e8b9f42f0043af46d07f82f8aab3168ea992bb165dc7396aef85646148b9e9fa88735bcc4f2f94d70fe02200480795aed487d24810b4875284d8e51e25493075e17b7f9f319da50e339a61412cee460382cef9feefa131bb3038360535c5593039fe5fa3795bdff94b1d41e0538536a9e6de8e4a9228d65bdc5cf6868680f452599112cbb3750f9f167ed33017d61dc6b6b374d87384d3a81e74289bd5253ebd20edd58d54bd3711fed8b2273d5c39ab91cfa21b2d3a901891eff40eefd70b8d0d55c1c33a9bbbf2e0dfa2430c736a18addf449dbaa6ed37f04b5a921f945bca6bda7cc75fe47f4c8395918236dbd810406e684aec3eca46c8079dc76defdd90c746859df26c661e746260ec99f15b3bcef2d4eba263d6563f305d522b58f2a39d9f420625b2da43f7dab24c63ac0cd79078a56156ddb4a295057c02dfd02bb52511d08547ec1c0be7a7a1ffdeb550551cf0170e89d9ccf024e862eb9df3458bede7e0bc7060860bcefe43e526edc7ed295f331d5167705f7f32da9721abf972e7eb1235344776ac19bc23e6b916d3a5e54f6863dfe0f46b17800ca77c07f80f0fbe0b2a39fdd2e0107e53148182c577a60a52ce377947c1c44f9264db8fe29b5d9943ec70997fbd1759539f1c5c279f645b68a856d58571bd99d0589f444f239f194c9e73e1606f8affd027a78fec78b8ce11a3871e416307c4357e761b6836be85570d3f155e9d19db103d148cf9dd8b51faabd6157e5e80c9b78e19501489fb6fabc2c1b7de2d9f480006f0b5858eae39893f9ec8a36ed92f2d6e64a31a7c1b13dfa8540d3176e2d451b09237feca9752c8e14b48eee5dec0cc314a00cf41303c8af57c727140be157376f5182e5bd20ef43bfb73077f388b2152c79b40c7bd7360aa0da790677535a1e1ea76528a51b5ea8ceecf9babab979606945dc154ab3269d729996e6f7ed843e8207cd7893e5f8be32fecbcae63474a8f3d3e66f5ad3be91ebd42319d4d4e81377d3531f4bbb7279ba63403c9d827875d7c244a9e7a7c83818af42fee45603039becb40982e1ec43e71c919a409cebd605b865e99936dac09953b4be63ee592eb0f1bc6c8a0fb156bde6c4e05df97253dfa07ad950253f18e0bde6eb9baaad215c785a73750c6f30b36acff3e760abd513258e60d80770b4116cc7f925f34b286649676697b49fecdc8e99c6fe3311d34fcc8c4cc1f066ce680bbf9c9fc32722c858204e9f8201dab9bd6639830830e9a24830a2dfc02f767eea40019df8d41f2e0f63562cdbe55f71b136d52a61b271a24e5992a123f08babf356fd83468d20ecb634bb0ad02be4af5fa5163445cf5ae233804ea209f5c279c726db78f1c81974fb8cabc783e54ee537c9bc3c83370bba589e1389bb1e63ecf59250dcc2752fe0e1081cffb2e7f4c62d44e54a46480a809d383e81106a1b06165f419a8f3502cc7fef7c9067599af2f049fac6ee80b15122555362f7419ab7f3379cf9f27503c503eacc8e94bde23efcd0257fca4da1ac39ad5f580174c42860c91be20a8b1b95c2ccd2a51466da013a02d728d54c168eb50c064b30da49f272f08ca19099058805f91afce70776194f24a151fe36c2619df9fab6760554cbb58781514f131f1ec127a06d98e5ce4ba82fcf1165937ed258ddc9ace565827b6b8cc009b87b083119fc093a106d5f5c679e7a145b619e34f69ac0531a9d7e17ece8e335b66f14fa874dafa045603e127954d89dfcc0994581a48f54fec32d4228831dabe01d0d9f887f4604e975326e8cda35e2151a452be21a4f7117740e70bfb98cbbdaba32795fae8150ab9be24746faf5c8a9ab253cf34f2807e30a238a3ce2aa5de2691371c49b1475e62444947f632da3da60786d0f1f52a8ddb0f69bb293540830f10cf70b3d84609d16fb1c6285a4ca9ab615ea8b0aa6274317dc9c06fba50e001d00fb9db760fe6e4e751a720bb33cfa914fd5ccd5a5e5ee325805cabfbdbfdbe82a45aa53570a50fc22573e6bbf7fb641f16d01f44b9176f965b1ae610b0bf2a73fa1125b14bded8008d3d1617951e19f225d0698241746b651e003fafa16764506610fd92caf131e8c278fece483410fc3e2c6f2cc76d4a9b66028ff3aa83d4a074cce66ef035e8f2186d2ff9ed2615b0c451c8564b812f225feecf9cbbb2de6238dc4c8770a0e17feb7cb02217da98318414257c4dbf3022d8f1e5ad79fea78168c8f1771affdf4597994697e6cece2e6bfc7219d3018e3ac49549e37b8a57e0e69ef51c8944a3ed215f36c15a2883aceab247dac03ef5a82f235fea559e6b42cccd5eafc30066a3a3173bcf2f7ad34004071bd080e69c7ad3f514c62c928e63457afd2973142069ea68111c6820af10202db0396474cb2a78e1a7121ec04900d9f4ebbadf3d306273afaeaaaaf0d882dbd511146f009b748c2e093f02baac204a3b4ebd4bee5aedc3935775b9d01cab2723ce0c06ccfd5e2a8a2c8fc467c9a06ff3964e96e104890097d00a99811114179536be5457dc37864f4b5f848d27d28a6143b90bc2ae09b218e867fbd6791404ccb662fb779119b8cd2472d1f9e360ccc37f39f2019c79f365c813fd80faf189985f1704016f096acfc6bc0b674fb117ba7eab0f4138791416638ba365c546180b8d5662bfe157f3f63430198548216d7cec0ec8724ebde55883b2c384cbb67b2d7179362f9114dbbe561c8acb3d40ccde56ea66cd7c832b299a96f3a0e0aebb57e9246068d5fbdb126e6a149f7ef2214c35f30409f1b44de792cd741df0cf48f273f6dcafd69547fde219908a75b3b594f45a382ffda619f7e1378df37a8b2a25aad273329002ef931a95a0a7b670dba6dcfc08119783f60b84aba6ba878de6158e689ab051e5ed1743f6fe28a3c061198e7a49d08a68271205e4151c49264929d9ba38dcb2559f45658ce96b2c232cdf40e63bd8828794ef664543bc2f700a65d7c86f218a9b76ad0391906f4480f5563b434403e35eca1079d8c1f906a271ffa21d669a27883108ee78a4fceaa056c0bd5aa4496ec5f37b2dab8b19abc88c61ec5891759c6fb2263f534df3d7116d6874f42d8bc3a1ff9383a68ef3955295b5478c28308c79ab25ae9ca31544427a2cde901ea588ba872f37cedac395f6661ec659f1bcde925f6a82502b32fbb07d4356efda64e82c35356f9abaf5d3f0abbcbf0b0fcc2191501aeb7b59b21e00858b19492aaab25c62afc3b0cecd3d7746eb6cb1edb0cdc569602791a17911802c9f5ccca92717ac661cfd4d4dd8bcdec75492a64bdd2150c2235e7d87759e137b213cb3ab4e275a99e4ac77fda073e2870b6486ba384c44b4f59b382847a5d0a4f87198a996e639f51246014a0d9751db9f85bcbea056a7609332bb1e7ffee3baf262a346e45697d9c97c5ef099e109251368b5a807e6b69c1247e8430d2ac2261aab0ef2a0f695c22086b86fee0adb6bdc8a14af3d02ea0effac0f6f55e8203503b48deb8c8673b92c499284b935abd06352b391c253e35870f024bcbec4332f578a74d4ab0be09e73e3cbf5e1ed7e53eceeeff4ec26941dec578ce3a33f701bb540da65f810e7f4df368804cfcb6078c99d45e4f15ee1d1ad6831c3e6e01102e6ebeed1f86940de0759b256594c9f91041716bd57ea464e77cca292090f612bd7daf20e9b534bacf13ca7d940c90fa9c18b188fbcc17e282edb1156cf5c1351a9f118dcbc5cc720c5c6dad1ccfd04f1beab7817561e86442665b841c97150d10395fd842b54d025a221d81f05c820474e492341a0c6dff31f4a38ee089082f7bfb17b9d8c8355dc76bcefcf0c7692ece39649e85ddf7e395f1baf893eb960d8e1374e84a1d32fc1924ec5808c1255b34946db13ada6163b368754820d519197aceb746d33f556f9932aa775b5547d4b42ab6433e4adfea54bbd7d173e622229660e74ec486937fba081cbb26de3ce7f6f76e070cf54315f18b03675cee1c06fc765f145b7fe4fd12f897c83e21c299fb9614533e163564b9d3090cb00f253029a3a4042e2047cead0dcd42969685de183ded532773056cebbe0242e9bdbf079eb9c8b0a64df4833ad35fc40a317e99070683255e7087a0896b20e0b483410f9e4913bf36cd028555302162a6c6152803b31b8dede9717b80947efaa233f6324941e0714473c92da512fbec873e4b745505a5e691e2f1b6dc2e98d1cacf4c1a42dff6e360909bb82027b6ad070f34ea2d1bea39653da363b2dd14633f5d0f11cc1617ab8239e9832b162b2bc18d8703a39a21ac2ce9b1f23395225f6b34671d5e7679459e7f86391c80e2e3c350220f3f3cb40e575fd8afae3bbe1104246b092e405bb740e213734a5a171aeb6d82b185973a797cf3f17d77cee462e4f3032d053044aa6d8060928f6227bee4a2ad6f7cc6bf49df364cc75fdb9c9aefda07130967032ecb5a29b38bafd4e6755e2427585746460d696c9481db581ccd583311b68da1e80fc45b330e7fc6744105cf7f329effa8d05e5f04f891e6a45c0f620a1c516f22c796523a325d03aa141674b2d257074a20a7b14308310c73ccefa815f73715282cb467a763532504523a1b1fdcf2ed3af8381fa967e02294195a9d0eb43a1f5413be08d6e9ac6e95ebddb34f6962bb64dbde6e94bf734cca4cd1d70feb5b3525d1a4f8551facc79b5f00732cb252e9df686627a56b80b13fd033cf279cfc12ae321a0fa58da9df8da8e6f9f64214e40c22334f13bf1f6da122b4673deedbff3f98958b53af0f4b40158d79e63778123cc6dfd55f43f4bce42f318b0ac418dac56dd9436e78bb527c37dfc28180fed5c439f952931b29e271d83b633effe9809a6399282048357028ab1b540cc0510ee6b19a63643714857fe51c2b1b2963b7964cb602861e81eb52348453e9bc497c447e8a8eb73c79f3997ba17f35f32121ac7b0172845bd8caed56a79285e97d17aa467312c4d10b8bce1d18e416c383b128ded04fd1724a29cd8fe9377ead625ae91efff1a562e03d382e4b4621b28f717ac6fa928dac4a086aea4e122d59f28c961ace3dea0bfc79eb62a5702870bb86a8d82e6284b39f61d2c39b7d99eb65f319cce48af91a9028a48cae8c3c08134f7285c9e7161a570947fab3497f00476f9ede57415cf5889ec18501783af4c371a24560a3046a2683741e851ec1c34fe45c777ed5cb03dfb8ae6648a1224bfbc723f1a69a9edc5ef37147baa1a84b199be1dd645dcc0fba7ca9e8365309f3669b6d1d2e8a47e21d34d1405e6530e0d200dd9997ad72de1e70e660dcf53a6bc4bccd999214ef9206af79b44915e9956f8a019919290066728eb9ae5ccf073eefa4b9f771f584c03648cccfbc1823d118326d7488e2fdb2319df94a593ab0bb34c9970d038dddf2c174631f7b73eba3e6fdae9edee2ead25e57f4c498c32a567c546f089930cabc63db6421a25915714aeef8d9ccd320237cb0e4d302fe1c964c4aaa604714105a1228fe5ad6ca7f42fb2e07c7d6b0bae5f3b320f59e9821d0f66b702e0bef73c4f3d891454e90599f033a96da7df2faf22455f49e28b10ca126096573ceb1d4154791bd607ab67ddc372cdc3da2957e67ce2c599d50b90710895a934fe744c3cb75b1836eed5ac9a549c28930a6388a7c993c7d5a5aa302ee7bf08d177548ecd98c65152d6197286f52b57a3f918218fda1241e28c86201d6e3b6ca12d8e6756223bf9b19387c321db1a0ea2fdcb7a7705f7e8c81a998368a1cdb7788be5629a43704d8e91662b3e1a5ab205f85a27a139a5dd5e40cab92e6dcadb5be50ca3343905fd10ba97df8aa658634c914db6389809d9b18f59fbe371733e5ae1fb35f0f6230a2394119aca72cb11db8a0d0c82a0313562b97528fb50b99f21e3c4097366b763b0325a2f8875b32cd4beadb07925be74aa54aa89f9b52eb1394e1863899f04d7fb451fdb81fc4360a3320dc2a24b3b2c0fd463d9906b0797c3215595d59e5350da3a8cd519d51e76904a80d73a163b384fa68002516c7d7efb1f14aee9258b3aab9c5033b8d929430ef742cc88665799fb1207f2c8d333db1ac85d4c15235103d28b3769df98a763426546b21a8eb0f67872edc8c9d448b8c70d6f7af172d13c3aac5d4ae5bfc8ca9c891e501f2c473eac63cdc16a96b0f74cffb89211a411b0e6b4a0d794b5be83a7cdde651573a142789aaa6aaf76c7f6ba4851d1eedce7feb5f7a2c1179e351a6d97620395b96850238967e8264f581ba4ad4dc85933c874e30fa3adf74901f6ece0504879356a835eb019e12e5761f5555f63c91142c59cb32515de844c0284a31d5e148b694c53e3c69378a1c2880e893fce50f5ebb5b46b7ddc8753e7104f5effea9b0c36e3720469c3f20b8d97cd39c06cecf7881d20032be0f23ed939613cb0dc5ac81ece654aaf5ec36ba427cda4a0031328afc840ffda24b1829153682cbee0da142cfac74394c073def27b4b38f5cdc1c7b699d281d1fd41ac559410cba3330d16c74c8d035ef0210c8dd151a3850db594502d1d50c2959301c384da313611e361e71e937a5d1799d1a45398ce25b1111c86177152676d64393e6ed1f11821c1fb5dca4cddce3a3b1e28975d80dca762c79210222f6771d20ac64da695035d00dae321be393b17008e5f0037f4c1733e4a9f17ce275a85fb44ba59edf9e20403843b11863e4db333233314661bfaf853d6269b187bbb6c0eb0f510d4912645056813ad34cf3bfe5277c589a0314bae0aa802cff46b510c6c76938cb84e921f7b4cf4200da1a82942a807a2075c0f7dfebf768b54b2e308dc49488c4080d6c71c0bf8d773d5de3cd112c588a8ffe11d7a17534a6c7fef432c380ccf252a10d8cd1fa13a5cea6e546349923de83cceee44f2981984fef7144be4e72ea0c149458a7aa6648c9f658622c00be9d0074d3b0d498e475c8e4bfdc9ed4ce81d3aba532aabf7e18d5097ce37505c2dfe9df59a6bb30fe45d62c8a1f2b065ca8bf74f81bc3da5ea3bc5fe855ed0f0104574554480151238458b0d0dd6d493ec964a7462117237ea214ab8bb54b5a7d9e005f5606865f5c7c04adb7149725e02ae803000000000000c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945862d09879b6ff8bdded4f70af68cd3e81dc71a4c671032da6cd9224a5c6c1a660aa1393872b9170453d05c1f40ee3bcb8f727b3e196cbb9c72e7f12ea97080f67e003c99764d0dda139b3165da5dc4bf9700c6a563fcd0543f549e7b19d4cc4caf777c3aac4386f3bb692fd45d7197df5894f1c9545709c9c2255a3b6ed950385ba5a7c9c5fe91bfc671695898f78518380e34231b3e36a49b641cb3e940beec0062", + "040000007d24b5bfe1999a3b21189a3c4d4867784bc2105a0196aba2ba6fd1c9a63e22e1be3fd8ef559f3e7d94c5da9f3ffdb276804f413014d8bf07fe14907d6a37659320e538c79c0033eb2537c88a69d77f048cf4cc4fadd09c9bbb91b4d965ac8f2e0a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025200ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000002000000000000000000000000000006000080f8694a1277777777000000001c1d1c000000000002ef753da29c8538cbe9669c722c10bec5663e07d101f0a6c3f1f86440a7b00dbe374e5118632c4075f9e84b6c62791de12f1ec0e70e7d415d61c6639d786b1a0c0289051e9e5ef26a5dcbceee48051ae1ee91d70e02022fcf954f3d1190186523ec4cb0ad65db85d28e247bc1daf3fa5b111983e5d328166df852374f3efa9430f7e7d5ef94c51c82437ac68d11f78c190ff7314fdfe4fe007c0be3aeae7bc1094c0be2db5c7d2b24faddb22ac70bfa8499783f312f0bec068f8c09483f7b7edb6e63753d60feb460e2ea1f683740eded3d994f602670d174d38dd95b2a151d0b1d5f2592bd522084eba11fe9f8fb1eac057b84bde9119816ff74790db723529e8713c8daf25996fad08f2a78ceff248ccc91a83402b94311946343866a6dace2226d246cb8226f2bf7555640d4891457a7f6bb6c85962a5e482ec760b6d6483a15f6b44108c2096492765fea12c37da638a7add8d0b74b1bbeb5784c3712349881b78d229a682f024cb21c0c3961704a71ebd54be06a17f44b1fb1926844f14c3a9eceb626fcacc77ddb138846bb40f28daaf7e431d5d09d6f2be928bd09b03f6ee2302cf572c781cda2167d7d8e9b1f4667c8b3f7621c0cf85aeb45462eebe743a33bebb34a9d118cb2d4a69d2038d591e3266e77e122f9fb889ab83325e5d2ab3bea0e85e10cfdd1508d3233ede0b9de84634972e6d3cbcf9325407c43fba5c9dd30a70aece3ac6ac3d5598fd2dd29907584b85398cf21879b4e9ca3c2066e65fad046e788e56fd4a9098b5a4b0fbbe12c0f7c0b5caffbbfa69e4289c9cca89ffb3158dabeb2952a6af2bac251010a3644c01918e0198b835da28e26f694ca21d897785240d0477cadd8bd03bad34639189525c02fea6172168722cf2ae9a6b51412b4f9b24495b9b2852cf045c1acc6d97dd0d6746dd116cf8bbce3258c862e1fb18a4e91d9118c5741a38d6a7aed613910b11cb881cb6d1437669ad853512778ced215ff5b460a47cbfd30e86f9eec227fc123262d73f45d71e66f17492af0457191e797ac9fe6149f4b3cd631dce8f9844bf16588f55003371165f0e48562a11799c33c5b4e4dd390b3943fddf0162c033f0751530acaf5ac2530f320c157c498452ac5012adbde2cc19339fe82e1ee6245dcea9f587a40f3b78600de1209ef9eb6a903d267a95742c856aab1829fc8974731e49b6e8f674eefa81b23026d0bcb1d770c31a60232798a8828fecba930b51b80ae6b98645be3c5b80b195828dfab3bf8763ae660dbe4f02ed5b52abb301b18f3ebf8f1f81b8feeeed620809673472aedf9d70ac86268b7a162d0f46c0ff6bf52bf5dd289a9f34c19632198cf15730427971369cebadb6e943a6d8dfa84f83f2f6451e9d155449f6ff1b41f538eb760edccc3697ef679a586c8295afff2cd8de2ddcaabecdd1c0b41e8db2790ca35e263372e2aadc2b579fcd47d74bcfa188dabae48a78eb8e32e403a3f4bbf86b8535c568a332e0b64de3b3ba0e75a2ce01deefb1b1faa6fc59cf602d1359180616258847d458d03990f158398018e63abf87086caacdeeabf6daf6965d184bf8dac33b1c5af2223168e023a2f5021874300012761f400e35e341e3b54683442a1bbf7907060b54181d27021ea69caefe8326414462f03c44eacac9f26c8a37a8eae78c76dbe19d33f6b198e8a2f4d77a2d50bdc9785518a1e210fea6451bc05e85bd106737ad37e9c96105db1b9bb09bd7cecc45960de0bd6d803913fa43935a8c17de7bf573089ec323b1aba8f6eaf0603b91e53c540305cefe8361dfe47b787257add20569bcb7aad355d93dfe9d28443da5662fd1030a8e251fef553877edd1e1559bba63ebcec258035548d037eb34276f4b256b22631489e8f7201c86537a53502b6f9b4ae7c2a7272459a4df0d203b7399ca1bae6b5260566332b955e342132535e527fa207f8ec9b0bcf9442b7794160497121720d2fd698e3eee28fa34de2321afe580958dd133b1dd2b36afa84dbd004c4a571afa48466d3b7915c84753186b5a3e7b724a8fb8e411f8732b963fe81bbaa48b247330eec8a0897ebd64a25032e8aa4c987ff8153bb447308bb3cf5ab699504746794711928457df6e10d689d81cd6a846123375f5c46ed603f14b0ac6c9729075873179c3bae9740c273d0ec9e1ce060285211c4e60fbd2801cae6c7337570601712fb81abfc25d9a43464541e13bc42b02f01f8ec78a7e5dd3e84fa9576891397106427a6ef262e11f24a55af39caf98130c69bb042475834753518d2f67f66c04d81c574eaf7d8b83bb029f037c4999159186e170752880638619096dd852f29994be72f3a6922a97610fa11085d4288214fe131d2243929d40dd5915a6789c77a499f43489ec2a0b7ad37e7b5070000000000000000dcdeed4e7121d043c65c8049da787baf0bb29c59b75e9608dc59b97fb001c92ffde01cdc9b9d97951e4247bb513ff71eff5413fda3522232fb7d7bc48429bf301c3bbf60c1e5346e6b2412ec70d7ec4091384f5a9cd1feddbf9b02fa15e591c1f86bb9ee9b65bccc11ed903646e771b8d252e63306498d3b325c7cf46dd9e4f8e1e385bd5631b11f427848e7fa3bb78f8f97d090ff15457ddb0030fa9a8332dd2ed68ec267909771b6ee3edd3370ba34516a4a7171680d2d912e2fa4c966942b231609e3a4f5860f35991d117445464ebf6049e31d0b0eacd23a11122c2cce82c6f72a160e131c588770bc6df3888503df8add4f1285f1417543f380479052a2bf8597f56b0d5587578c3b896ed7bf0e057b9a39ca8ee3b1abc2bb967bf5fd7064150871024113211114f203ce5f150e30ff55747a6ecd17a342b77fc7c41ba70e1a216112048b26bea002606abde584d49e7cd633b7a5391290e7808978100e2d5f955cda22772bf642aa0e3b4e8f30edc8c9e6dc1d4952160377205a83730dc58516ad5d5f1b121f397aa2d43f47ff7a09b602b9c61958a3317d2316b9c8db14e40a53e88f1744655a81b850ed7c9388c5388da56e36ed67ec15e15b52cac4bf47a088df916d2c70c9bb348640cb429cbed26810d8fe2218424a6c63f1dfb5bfd3277bc64dd12ae6c088d7f55c4804f6c8bcfd6332bf4d6edbce09574a9c64d3fdb1e41c4d17a403646efc749f7ca43eaf94b014dd269c833ac3e19bc7442ab86b815a9eaa9efa44d01e69c77f73f600c5a911f6e50b5713d079c855ddcc2ba6462077f5d170cda9bf0eb8e477095aad7cd5c081864b328a9cefe21b44b53ae46d38a66f6aeded011536310c3bc0dcf64d2dd0c9015c6c2f83d36d146f9bc9f5a627dca73c5e092953815715ce9ad107d5450b84d449e0e93bf16a4e03d8b15d8b938216cd6c0bc08ccbba0658391f8d8cccfcecf77a85778b9904105bce80cd8c15e38114a80fb6e6870fbc92af588a905da1de9cd58d7c288e7cf406ef916c27b1b4b61fac457fa6390d7a7b6c14256c7a87fd510806be27244e778173f993bf86ff5cbe48b85178c8ba1d529a974a00995ccaf42b64d4e714fb5df79980d79492002f7e220dceb7a14769cff9c1dba91247cb300eb8bfcfc3a85e360266fc4b9f328ba12a6098aeebc67e4fc9aae6762defa078251a0d9653cdbec24fbe31ffa3ef322e6ba7c7114d0f642b72c7ea2688505047248fb18b8321959dec8693a1ab349c16770aaf10889e46d8d8f508f3233a69c9a820b88fce5d5ed044b9cd7420f456459d3ae87a23cc72d3d9c770f94c82224d95426e10107ceb351676c1dea9f252470ec81a9825bf0c2b4a3342ffd702cdb306a351ef3bdb56539da5022b878e08549a6ec8d8773b44c19281da0e307614f72a30e46b73f8db627c4ae9f530c0ea6ea523a6b857f96acdf37b42808ffd31fccef667f92d7ae7ee853233308d0e6a61fb0f78f1d0ee35278788dc3f7585fff3688ce16d40da875b756b2cf4aa33875e01404fe7c74614f184a5eb458acd986abc580f0cf2517110b9f1239615194055de68c7925573faef91ec11706d27b7b672b42b323c32b25a796e795baa58a7dcf5e19a46f21b27bb14e2db080ea704f7a1d15c2ff114964a65bb7429a216ff96939999a743316b073d63cf87ec39d924f6e7658f325dd6a77c9921b2b21f49a22b1d96155d1dc9a206a9d521a5b3372c397556febe9495bbad48c1d9a50f0578bf5e0fdaf8d0276c1fbcd0eda0a5b72ced1fcddd7f6dc0df854aae139d42527db885aaed6998cfe1daef4865a39fccbf57673eae767a975e43f1b198185b1e37a7d1afe476cc35602f148cfee549147584f19255d6cb3e31def73cef31e3adff8184109cffcb6aba6e268367a2f1d803604aefe48404ec5b431c13dbb14374dc9e118736b43f342a3c93f57c707f58dab5f2359f88b48eb85c37d052105bdabb93a8e1f2866330f5548252ffbfd62b448fdeb777168701bdc6136a22bcc048e3679f6098c00ca7151267a4bb1c6561685f5f6fba0d1976a6b7999257a1e4d5155020b124f65e43dc06da593c7fdd96c6fd84afe493d2ade3624fd7672fc0fa7c77d97bea5be3c865655cc77440c7d28ea2cff6eb9bcf85780f2ff0e4215c8c18f63012aa4067fc1524e81c1b9d2e08975b0305c2a1add51a9471c9181835d923cf51b854cc659616fc1932e4997b2b3b737e661945abeb0d9b1fe3c113c2b2a8b371d8630927bcc23c21faff67fc6680ea0b3468b8a0279e3e160629bfccc7f1aac37b5aba4e275cb9cb8ada5c99361c70125a45c0536a9467343dbf1a22610ee2da7ab15fb8d3c5680cc447458f81523ee75668a3f75302693169b7a20349c35b77ef8e99cd3c8b852e4d1871972415de7b9bc9859697d7eab02e559f03cd57fae9e5d3d692e617a2cfbdc34eee3c9db4efdad6f1fb19a7c4907db5173f80ec204fe16919bcca832722c58273f8fb67f69e5d8b24c285aa1a74581f0f9d1fc11b42f578a1eafe7a7dc2c6f11065697d3207585344122314bcd914733132cd0bf5a661eb329dae384c0a85f559932a49d31facb17189716a38b20e3f0c0f30ab4686e79cfe9ad03c00fb0d726991869b6c89ea25da9450c3d6cc5bba1bb17c7a3c38962361890e3f7e24ce94253f63e12dcff3e2c3d045ad05f45ad9349575c7ccd0cd82fdf1e083c56dfed867382a4cf758decef9c05bea3138ca4507b7f638edbfe8f1512911ec00d4379fa996b4d64060078b95064cc81e92aff21e4b30d0b848a8d8d5ceab8f665e686881a79bb390d75f94c593be007bcd38d10de1e750df1a9256375c15e2bed4da66082248abb6d6660ec9ef6351125c245527c3b13e22d77ab516f2457d890f9dd5a6c8d0a21a4d626a5fcfc4bc3a427b5d3581830e070fc6b4c0ac8038bfa1aa52b12b0329410b6b8d0d78407817ec0cd708eaa5215921b14e113e8ceee38318fe47f3cf5a58c1ab86a6eb7734170e55b5002ab3a48cefe62fc6c897aeae4ef82eee968be5b59bf329cca3d03ad5dd38dc287eeda31de96cfb4ee94eca046b1d9e83632f1ce043b7c65782940b60bc0f9f35cde82d5623c83c6d3540139ba820af7bdada01c22a2531b1e3171e6befc5b8289868ccceedb49fe28a32bee69055d5e167eeaeb320832e0da67d6f536b7ea5226e86420f72ee68978a460d1a5f5d0f22e7b3fb59f68489f757581bb4fa107c14829bf5b93ee95f76a84c2f08514f73aa5c062585b57b02de19dd4039afc4480d8666cef6de93ea111a934295350433ecb4d7cd9957a0cc739439bd5308449d3ab744b76f429b3997611e9edfcc49f021f65645ac5524ddbc8fe9f49d8820633ea37d9e9dd5bfef0912fdc1ba80500df637ca3701122f543e99df4f528519c6233fe9cc94e5d2591124212b6a7711cb083018647b0e7200811aa58b82b5fbb10d347fb64ddf7ecc1e526d69bf7d0bf9ac4287ac42db1e4e1d9037ed3d9624cd19c590c460c87c71e7c5055cf0b78318761a5e5b8ea36978ac18275470e04d8e3da440cc7fda0b2fb7857bc2a0bda4843a60d21c3bfaaf7e32f16de155a161e01392be4ef0ab5df2bf0b18a0aaddcc364acf987c625c20fcb90b22e3a0bd6fdd161780a58517012cbfd7086a042f1e13b3f337ed2dfb4f66635d188287bfdadc3bab7a139c3ed8d784c2773836618e440f2f5ecabb712c9116a0d8536419ce663402b427556e899d12be13a588c66565c60fa3ee42f5b21cd3a8febc2b906eb91a778baf31aceeb53acb3556007cd7752fcda896c3a4a41cee337e5e63a5bd7d3d9be234295ccc93a1cd3b4c171f3a7210306901bcaabea6776909baa057ec840813de6ca414318b10d18787403f9ae1a57d671cecb824163683d2e8f3d40cd916a9e6d63aaf5f69dac13bf6cbcf9562a915febaf7d95e8fdc956018e42276703719e4f0d7c698051290d59531e034f884fe7794175006fa69b6b09897979881187a31d33c3728eb87e0562213ae81f502108314c35d590b02b4484caf58925d3f9620e89d5e4272be9fc2bcd587d337de2b815b64ebb3dc542dda0e64ff6d6037fff10941f565cb6814ac3058945d4fdd79c3f97819906551441b1914a4b6c4346a34d7d05315eeffa813cf95b83767317386bc21f1456ccf52cc983777764c02dd9c5ebf3940c19c8d4cd2c1e6366935211884e8aee011aac2fddcb0646cfb290d3f7ac0ea8fd1ec20b57f67a28a470673c4c202eb57409ca729c4ffadcb1828daed09ec1223d758548e477e7e06f8d9015df9a40b964438b2c59261a8527d0755b468601d381e60826627dad42f680f33a83027246eaa154ae2cf04ce7cfd0eae34735da1ecd1b408f4d41a9278115695b16a248cb697366105585a863b4629f6a6899d77dca911091f73e33a812f5baa98b3460edecd6cf2bda734810a7412943426e8d8e00e24afacc681379b92978ec8e049f34b22de5488e9ab25a7bd135ddcb766dcc95ee688268ef957b83130c6869bcf0bf43d606209c5071b00e32a20cd6da4bd4cc5492f435a62561348e3769093639c533570f22b9ecda5aa7c2773753211c68672101694fa491eaec2005a9cc439f773801afe423675efc54e302fdb5e09b895316e7ac8898343bcdd91ad238211e3318ddfe0d86c5ae1c6d83d791c52d9b35496b8ed9978a1c7b5dd00bc6c9697f39247238c2042258025121816660ef0c53a49995cd9b45ba1712d45695472b69d6757e56c572c0f290ad6225d35ca5e5f564ad2c3ac7fb0aa41ac346ec3036adaab5000b9c58d8861aed031b0e627a1e665c36dfceebc558f59df5b6235ee823de9d185d171a9237a20811d9b5e4efe508fb9907d25b6849dedff9e8d71fd0b2cff2f8ea8cc1a7e98b204295f267dae98a6476d99f9eb73499fc918e2db191b9decac79eef1b046e9958c32ff1c8bca28c125b2b2340f980219d5cc979eeabf2b2dadec09e43ea4bb67b136dd30cfcda9dbb611d899e5c3656d46bca5b43affc771c9eb1697b10936d6922c17baf10888d8fc10b4a891d4bfe5ead9136c4f79215c61d4796897fb39834f0440db29202211d82d2b16e69d9398fe33e22959a4310d274c67a4dc9ae6acf72abd13a1afb5fc319c3d5ae89933158c91ffc851e5e5fc854b102a047a0d30211afda1cb548d279fc894f1002c3721e3229519b560f0a71bb648149bc763b3401b9ad57704139a85d936bd0879a820f90be6ea7d78b6fe1679d336dcc2f776a3373e473ab5ee54f5e0a8df6114fd0e2d88ed6e7035d232eae1e4d785b417a43e06bdf7bfc3509bb4ad808d39ca785673436a1009dcce6cd055f10439de64652c31dcac2b65ec47264fec73581f8598f8c318bc0f8d0eb929e7c4d6e5f012238e01e19b1fd6b54feb463912e6557b65741ff8919434e44e04e41a5caadb74f3cc0254541c06faa480499326b7146499b55a2fced4dd416d5a31779c8de5dea938385217832cbc605788ff4fa96e24fdc3875b52769db18abdc76a687974925a52081043864ee8e39574d7f27fac30650eabb1fe70d5d7bab946b234d1b8ee449f08654ac868a22839924b9e7b94175e60c5b575263089b525f40d6f76570d2740095a43696a90f486332f45f4f6ee2d1d55d4b3f2311637a9e73f921a56ea0529104573b25b2c48307adcbe3b2232cc04933dae07c34c491099c57dd7e4b393fe34db10623bb35b74ce92f8b1892d24b9fd88eb7cfc3d1791b0bc3bddebcf42592093e6ffde9f40766ad3c21a67caed25b8b250946ec46773565fdcc6305803362274e612308b8b767423afffdb27239f3b9bcb8e70bf0ee68cc8a1af4e59f6972d7c90b182d862066d1b83ec044b259b398840cc736ece77dac61d07e4b338083a97146137dce132a2a8a0255d1c5aea80b5e0095b6181dbdf1fa23317c74c0e25cb86b08c4136065729777527f49f407256d36049e4c236201174b312e80090376a2113d62058b659f63de5b8695e52fd178c573ae0e14f205cb2fd929c9f09079930738deea7a2090288911af17e157d6c9ea4bc04f6264c81e4f3b5b087fd17a7c0b7eb631c1d1476ddce8be398fb7f576f3f01f98b823b7e8eca7cb3831c0ed3c036219c94ecf5a0c2d112f788d73a432394247fc0244de10e28d4577ecc084c521f0007f3a6215a549abb3091e59c6d6cd674c8e5775acd276c980033df3c2143be0589f65da81bfab1dff81e6783f814980bed3cf47e51dda6424ff43c2a82e966c7ec5b197a73cc580919db591cc522f87a561ca46753679b8d26110d1667bbcc24706633f219617f620958cfc35c1d70e034c0555bf76d9d854f8e5a0a973b88cd6096e5f3d2a72f3196f4bd42b32d6849fd37d10df37225b0cfe05c1005ff528c59352ad6e319f77da2ddf1c94b8b7e7c7a25c7cd15121540f31ec51725e71924c3616257756be8d404b53cb3091c6c3a11940c44cc8808426305550f35f9a4c5322222e661561bdecd8ace024f4c2fffeb3bc1bfa7f69454f6699d36dc42f35d78130f04b39ef392c5969a4d8de6d5271ee7a32af3f311386857fc0c21d053bae00a066ada63a28fd84b0fae439f1060a7b633ea07813863162195125e00d9c2aa7f25c11c981794cc97718f22e3cdbd21701d6f6f5fc25885be6330ac8b8266bd64a227535648a926a002345e224cb6bb4ec6767c1f1511c2c1753def927f97f9fd620c27eae292cca484472b6fe5d68aa58d3fbc772153043073308ec7c0a37c5355c0bdd43179025aa0e8d492353849fd7accf1a0acb7507f11281ab671d69ceaabbf539eae572f0015426f5e9a57e8c4d4d92216a93027572c11172cfb505e590e4d5899aa663a5ea32d5cc163ebef26c92908e15fe3c0705d06e32504c7901bebbbe7de2bb3f5ec28dd50299d941b24242ea0e151d747e129357f4fd6c98876dd0779fe40a7cd386f198150b43d5fced11d2906915937905f104a9ab5f0d05ddf227110e72a6c80a7878e559b5d8b1fd632e851633256254a22608358228feba5055a91dcfa6f702d55b8a463f0e0dd4af11872694e1b38ce25e8f8b4ec993d38223eba5dbc585fdd5ba53b179c20a278181fe3a0d13a7feb333941b59748b2b06b2c51d6c52d0a8bdcf833628cc30787d9d16c0991bb5a523a92da788563800133ac376a6feb09a8ce1de5c1ac1ce128272cdacb42b9592611e34bb0848a05f3c69e274b33481fd2b351ce7562413c2b2eee4cde66944b64103734d44e69b9187d0c98ee204f539c59b2374eef044e731b1bb3d06465f37d16634579e24f7ba512a29204e0e3fe7d89809914e41b7ad8d17e5ac11af5246b2192c833af76bad3906f95683240ea619360d9a0ad9e7e97777e2797180447e13067cdd4efb5ee7429fc5b97e80d3f9b8396b8d2df51ac47b434ee0109b0eaa22f854d4de4ada9dcc003a4a8e147ceed375d607922b59a50312813519571e2a526774b1241513f77d2b53d3d435f141c55eddad14021ccc542ac37aea8e24b9331fcceaa35dec147c114e181e9a6800f1748c3aa1b425d532da7ed19bf10ec5304900d6f685acba0fed0d7bde86d5d5dab0fe046efe66fe78b886d24c097fa252a7a9151e7ba2cf15798d1cdc07904c8f32c1853b8e79be4d344b6d8820005ff2e11ceaa7833e1de67fa3f64637bf20963bea0a981ee810562a0b8b2dd532e01140421a975d2e7f39c3988e99e5cc8116cd9462e2f405121dea5a03616d7fcad17ba0956b84671d94c524efaa13b6b0bcc15b98b6433619bbfc9736d5432fc5237b9a018b716c2e08e4eac57d2b7c33ffd813816a0b01f7d09a5afa082e1d10a327247e0f086f3360dd6b9b736903a518390b887a6dd2f5cfa65322e5fe6dd801ce6ff44388ecfcc02ab12c562f55484cbda45465049da5aba32131491f3bfd92a1f9e85fef13e622e06445252fe64b42680ba24d09d0cf28c9f517a24ac14322d57761c1d53491940ce65df7c1ce7b6f766409f66f6ab4a9b455df1de0316ea2281d48f8f2bfa74f001509e7d2222b7931453759b1cb0ef887335e62bf97aeb1fae49095be74c11f89ae74297e22a342f60ff851f43c1e695080527747f9326097ef0a6838a1f46daab1f109c4e921beb2ea1cb6a334dedc57e55e58469aea61a185933a8a4c5fcb5366487d36541c46f12d8b830ab05c415cdafeb875eb2031e154fdde2d07437c0297ba56e4416cab08544013b2728a42ac6daac513c436f3e07dc6aeee0957297b17c242e221c41187df1fe919602d84805486c0dfe8ba108bc4c5b95c300bf121307d465a3b69f99fece83b1ddba11e3a8ebde80cedaa52c7b5acc9d0417064415bfb6d8ff6ff46444a62619c9321171883977194fddaa0fb059c29139fea48955b1ceddae3ac8051923472d23f06773f49e6624a8f2ba23b36a6c574d85b40f701d705c983ad5bce01bb2d031617bf8b2769ffc90d2ef086be32b2e84cad752afdee010c8e26ee09ea95e963b57e93188d4af84a71a5224e383a0dde184ed343fc59f77620045b9d6cffdb1a89ef0d5cb7e853810f24523a211f2a2fc19a49729d02fbc51b9674783ed4c7c0ef070c6b47413681ee65934cbc65777f92d13f01879a5851ca57501b5cd016cce8e9902f4379997d5c75b3558161552ebe9eb325a3ee76fe87bfde3d2cb44fb9009bcf14ea07900a9e120367d6a0253fba1b57f388efab647bcbad82a4ef8b5a7158c3d0ddfd134e568c937375a9df0304080a5ae883ec3661b176c272c7dd87aa40f209c9fef9d07bd102818b55f3e7a8c0e06dad914acae44f9023a04395e12b1d41b7d425634c748713a709547376cff51e864654c3b24b19d294b99c5e61abbc2f270163995512a5d042d94e1df1b49bc9f2fc814d7409f97758487ea49b276ce60ba980b9e2df67e1a186a18ea60ac743f45714b80eeb90cc06d7158f6cf09c54a858fef698ffe7032c22de1618bfd90bbe8dd7db0aba29f53abf0aca67e1471bee1c871bf3595f423213645b9dd88a4153c7dee3845194b496abcc0104997fc89eebd4fc72c5ca73cb5789cbbec9cdd9cb0cf9117718041860fb2073fb3842c45cd1a8e44a295b3166e1ab0a5a18aaf22575454d4d3750aa838944d1f5caf671d9402cf331785d83c50c29b2e49d402ce4ba32516fe1b37c463359d7cb780d3561ac8c6ecf1626d33aa1b482f343086e740be27175fbe1cc6ff2f798b9cc96e2d88baa6d80b0e443374cdc7f11cda7def2a1875595f6980d0779641c9777632f7a5aebeb48f3e9d01c187695217de185ea6c99cd47b321c53c26a83cd2f749612ca143a2a3a594c2e80c1ec90d98564f2a69e579f9713c20af6a559f541514a7514b8fd88165be486e825c3de6899e97f9e39a1654e51ed9690cefd5e225602e68480e9f2346b3f8d61268dc5f6add54484b7f4bf8fe086110f74183a0bc2515056f9a0bad6f4dbbd848d80df7a24d5d92a6b6b2b16fabc0486028a13b67a2bbe17f9812ccf6692327e78a5dfeb56feb6dda38c9ff2360062cf7128f357ab4b395b26880fdf80dd889ab809da70b1f58f5c1005a3e054f9c40691c287163f445610bdf0f14e6cb73e0eac5ab2fa5a9db4a9774c135e92200c27a34aaa2f3b9e2d568d28ae69652f1a351636492a590f79df0d4f9d589ba0651aa572a6cf9070a873ce75a200506ca74339dafbf0da6add65d5b5594b5b49bb0b63b398b44ff5f996115ce0d1b6f220b7b7b20049f5fc9f26e4fd8b7668578c4dda8365a9e79db99378091b3572473747ca3b4104e7b7bb1bc22988df73cc1e6fdb242c78804b4334550788a3e6a50a17fd8a0985f2449eb8554bc28c989cc1d9755aac8b33482d2c70525e102b4518f7aed260cbc6d6e7317a22e92b776183ccd105ac9bfbed1bbf0da4be0c0203a390cb9b488ed0aaa098ba8d5ebb9659fbf19b8cbc1b4d78edae8f5f272d2bf0303fdedd0e3de90ec360fced0ebbc85d612a9c396ba66cde481b92efc7ac9a1381dea34d170791896ea030cfce7234a0a2d2301bc79043aa7dfed6f3ea7bbe28a344a274fd9b9670b70cd74379a6fa1849a26609f1ef892c0073b7db34f09b8631af1884552a234f7f37263e04c61418b602bddc8561c0e097c5767fdeddc5deabac6308e5ae1c41565baa4d0bb33718486f3c655245f26b26a12becdc95a31819afa5729cbf3127bca5596f9d409301a32e80a3b7ec270b9387e88e9e1422b9ac903aab06f29970b50673222a3460acc1ed2a6ed45d10d3b42887d803e880f39141ce63b8d3fcaf49d87a9ec7f9720808aeaf8eab0ab37ab690f97cbc125be08fd6cd41df957059878d19b106b39e06bf30cc9d3c85f25de650f4afd295dc11025f9a72a5e46422d88c01972e22bf024fe61e0dfb824df1bf44d1f77db0118127ae48e2a145d82bcb537cc4be81e7bbe0e1d3e19b56537e7bee8931d4fc38a03d1c387079b64590d1f775566cf0a16ca2bbad3409c29ca616d8f91040a3ef52bd0b7fb2dea0b65f0841a03fcf8d25a6d7a0904a74ca61835e3e0734e4addddd167cbe9d3ccc89a0965191fd70065b0fc48f450ebd036f9c15039393ebd191a982fff506847cb3de8eed4cb8074da6076302b1e7623cbf5bb1ac4d6af09fad853100eb1aeb302717031608283897f3edb7e5b7f5768a363eb2bfe951b6a9c470d9abfad6ebabd17dadc0ec021684726a3f7daceb4acfed42084e70c8e721034f481300", + "04000000821ccb50796e05b15fde182e6e3170ad072e8c43cd976e191b214cc0b1bd9957f972fed3d6ea50bc8dc07827d9314a989ff91fdf51efc2506c098a000b9675c3e2ce3df4527cec45858a7a5313b87d0ee29b8e001768bc64da9b0416a06ec0210a104a4d0f0f0f200202020202020202020202020202020202020202020202020202020202020202fd4005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff025300ffffffff0140be4025000000001976a91475dd6d7f4bef95aa1ff1a711e5bfd853b4c6aaf888ac0000000003000000000000000000000000000006000080f8694a1277777777000000001c1d1c0000000000025ffd47baa3f5a5b90eeff3e0779f2d3563860fd5b9d7666cc06abf31b105a8140643a0cc5b44e881a3eead60361c59cc283f1fad00138eb02268408b29029232df48832e00e32157fd299f16bfd4482cc933ab2ff4cb953b162c8998e03a4d05bb13c472eb737e2e3cff834999cb5438003c74df6993c0579033e56a1fade81706ac0a77b99cb933f66906bfd2a2402c8739f844ee72d34ba50a1e1e9486a73e4c7a063267570a483bac82673d954ab903345b291266f89526184c5633a54bfaebc05f6cea64c403025806e65d8e89cbb0ca967dbefb653063a35597715c488891d19d68a5b7f0b74ca44b7552aea2308e325c71f7199ed497deb6c755c6727993f4d218e3128bbef26bd03941a19b344e8e629d81f15559abb7f6881ef7c688146640b02a0e5a9a78e8c587006eccd05bb1d5ee2ab8d1c743391970a0cfe2da89d18fbb51bf3d6b9fb9aa1818619406b89b53200b86d8b3094e46a01a67d63ff2b113b266cd38203f05bd01cce4e4f39a0072baf5f582315a98575332523e967e353cc3ef8d1df1d26dd79e5375cf9bd93f804e4d709004967bc70b3ae79bd7a9cb67cd273bf3df4e1218ec3f67dd9254b589fc73d5ce565e106eb6c6621a5c2438fe784eb5d95efff8e3b008a63bb1c329c5bba077bc756f875acc5d0eb0d02d67f2aa04738c8c625b56c82cab932b05ae2e50092322887318df508180080e1c7b80cf66894cac8de85931e7fedef575e2f7146ecc4658ae936a722548c527593bfdc59acb58ab6c4f360bc0ef75e3bd171c1c730a51749bc95bc2ab4eb7cc3792e107c31239e3711f35b3094c207d73cb0ceea7643d175cf97ae6d8d221f48fd048236449a28b497b36ed3c817c161d4ea89b7bae5170dfc9c33b3b08f0a38e964eabde9f4020eac2a7b480b9dbc7111d67b45997fb94f4244cb8bfefd0d6326a9da5203ad489ebb4e66f382a5bf82e9011e8d3a44cd8b6eaa60662d20be380bb5f474e5f8d70585cef0c5e490254ae896caa9bdc42b85c4fc0cdaace29679ade3adb96628241c509aa1adf1bdd633850f4df4b24765fc4dda5feddcaa6de3a55d58978cd71c9fdc5bfc77b33506ff8b198dbb4ba4cf3d6d4da3db5b76cfdb26379050cec5d43ecc5edb79d046e56ce8582078f6dae1f9802665db37c5285ab13076b7910c0d230f090375c46e44b0f142d540e32b8020f271de3f8ffcd2a9c8cbc1a7f5db56852ec2e9078731d724824ef0db06e8eebd7f111b7326a751086cde390eb42268a8dd44b7b9b1362a594858308abe397b2abc43a57612f98d027afbe7a5d3035c418bc32f556c8564c0901f9aa322de146697139f8801fe1f4836a800dd0eb2033d3b1c79b4f1b630b85a57a009c887eb4faaa0ae71aa5a1b9ce1dedecd5a9aeee985941c39fd28e2412193dbcd3a941c7d20e6ae310ed6082184c17dd2fca5fb27a1985843a6d92bfbea1c0ca8f7aa583e0336cb786cf38b893deef8f5d9a7ad8b096013090ce9224270c5ca0ed72961b44a2749eb99c23089258895392fc65c6181e59bdf0284a08b6bbcac67a394d3b73185f1c454ac279da8c360bd816131add0e86431a2f4bd018bf1e558bb79761851f9b6b1c198ece4e6ea28d4650ca1f5fbf1401306709d11c65829df6ff7b6a4b8bb55921ec2a3bd146728b717f31681c355cdcbd551e6f310a85ec235ba6014dd384c0118d9aec510c0ff524cc07a525b4e80cd1d2d51649cc6889b2240672cf91d9270ce131b10e839c5ba8dd5ae0bdfc943f9052aaf4e838cd0ad9074d845312f17f33a1333c5e580f48dd93b4c013ce245e807acc8e9bc89429027b3e782bd1054c1ed0b81c6f5b54184e7c0c3289dda890f9d5c21cbf13660d4a5634777d00944d6e9a91a560a7422b354fa46282871b9f29bf0dc7cba8547b19c53c16c5e9cf9986701d8d15ac5893d6f5827bb02e0eae3f589f4fcf153515406a1804d2cf8f62d765eb65e09d16c6dd3acca553ff0083ca089e62fa06898a1859d224d8f823f01ff17a2a53d2e27ba6eb1ace30b7f9a97049c581b912645ca1337d449fef95b61cee2b825716f8db4defd52709f08214e1be87c2a1fdce6c3225c10e72b0e8137dd99e2080a033af6eeb1ab4734cd25b822c7b6ab2060774df62fce9bdc9d238b679514b336dda53a630aaa419af1b4df7489bf0fa054c82bbcdded5f01eba9137164a023f495ddaaa883bc42edcc05c2361488731d9352278c9f9075197db5e29a1c87add4cadfe063c6a072f6e1fa9f8b1ddb2a5e46c7b3120627845eb9891cd09b299270c63f0147376065b406b531dbb2283bfbbd7f793de7f627685263d89308ac3896d62920ac548a7f97681b9c0b48671dbe6b6cdff66b3c80dd90b7f5aea8f2616a57f0c47f2375f070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c4e5f35dd019ce932c8d81f52f6ac4b4c7ad62d1513e1c5c445d10faaf17053387812744aea4097a7d1707dd944080558fe3569fccc6920fcc5edee87764c76b69c14f4fd2f140a5aa80078ac3bafab06214182cd9e26ab213ef6a424b4752d8b8b2b693f46bdd24a46bea270af5a4ff7fa74189ebcb1163d359d3dbfa7042509689bc397969857751feed4314241810eeccfd63998768b5a811277d852abb5a1e88196c0e6f98596ff2ecb67af89c3dd6568a4fc2e495559d85d9a043c117615fdc8135207ea0cac2c99648e6047226055013ba411abbe71fed3f3fb678bf99ac4d44d51224662036ac1be7e71d203934498d1f0489bd4e9f8463ce20e381a31cab6da793065a53353682f60fa162048ec3c278685200128c45ed315900a3111b2a3f36810bf78e75a36765a59b3e618177b61f6a90944e0e5973a573c9f048f17f1acb7a5e29889ceaa14f78ffcdbf9b83a3a8ee5233dde72047074853d78a6b7f5de7b73d0b861dfdedb8f2719ac647a67161803b611e5b80338be8f0012bbcbf1f5f05558b742a7d4271865a4e3c1fe55489ced6624aa329fedced737980ebcccee2210078dc20db162ee0da6d8f12d6293b9079bcd29416068e738f129991e084f498a98b41c4c7a8430ab26e0e06ed6115ff86611a29893b50c4190322ab26aa6a3ea878671fadb3b77b694dfb541dfd52d8e199569c800b003931def1aa79159208545edab077606d0f61947a571b6e7c0551002d739157c6f5fc1fd81a2e7172e9f480f0499f9162ff55146ea147508098c2ae0c723d8f113a9fc8db656a25264b4d4f1ff86acaa7498f351934e3fd113c2f8e45488360a40b0cd1e8be9ef9c323cad2df8c077fdb1ca88159d3339818c557e4ce14e8efa0a60f9ec0e474f05cf1478643238fe22a7ea8c74c555d37bb9555e9e733e07cbd25a3446847a3ed44d0390261cae0a92841eb6c49b20dba2869f3cdd0f33754e813f8b270d8d7c8c7a605541067e929ee330f34ee19f5de779bd0d74c4f82d97e0d794afac96f3184bf7456e8a6a1ae576889b198fe9d619425b3378e2b8cc97caae0497a3730f2adc1642f039a99b7df9d68e080e9ae10dfb93da507276b50644d8a963a0f381f5f2970725ce544f384ef4797e5cf686a0e242621501b3b5b58caeb4ce31d8dc19de210ac4744180a3698c1ccd5b68ba48edd1d242764e287d1b22262ca260c8e5d4c031a798684aaa48b739b19ea140db60fcc23cd4849deb5c3b3137331f2504ac002856a0e2a18bc613f2de3b0b615335755d9a7de9cf27d1ab273b93c87e0c03af4414f1586512fba9bba193ae17f636dbc8f2957bf28f31b2f7f53d3e4dd6f1ce49137a89a55549f23445de2650e4f1c00b22c6396c08a49e803505406be93b90080bc7e1317a4040810726d775090a6b8ff2ced7e1d150b21d3990d64cd3f943db519722fb8b4bc68656188e109fa6670235ff5f2261e4819b0a3ba1d15be9a6b39a07f579923924d4fecf753ff918356801b662ed3071753bc110adf8ace113d4bd09634b88a48095caa9ba92b2dc5bf8a59a2b7964861493ab25fc0e588f29bf7dc2b08fc95b27d8673685d313551aa6869ddf013253c6ccca39ca9bd71e3f31c77efb8b7a8a5d05afee6d24c027e0ceab5b3159632de281253ec3bbdffea8a9e761b4f1ee56047dbacbbf7d3c88240d18e4d2f625e24d2fd4922f81cd50895c276a738557723711934ea1705ef98a29d87527af74fabf3bee87f2813ded83917d8ebc2890f9dd3fe5d988aca61f771aba9df9455e22fff03e8565feafdb0619706f36b9dca969747e4061be9248ac3a23add9452f9830849e3e72c8a1b13873ed3759589e03f800f9209df6ff23edfedf91fb8eb35db90a1e31305ba079f6cfd6751c036a050c091081a7cd92f6a0b9099e3deba523218be28c11da50788de3f60ee17d78cb8d9f210365f94a9b938f37a5f4aa1c1637c596a04ac232242d6725b6b49b12208d10a47d8264c2346b598935fe0f43eb56e0361eea0a8a631562defff77b502e1cf0359bd42f1bf330664217a637476406e402ab0bcdada496cc5527f74b911a96d7b4b927a80fd918255830fcda63832500e53c4b5cdb90bc83099b65f18f4b84561aa54c7d2d969aa3464eaa220c59669baf9d7e08216d3b33c39f5573c41411f1a0a10c43eab6cb39be9baae5f828ce41e50352863a60c4575a4863482939f2d3e2db6414b0cf533468ca0f547d02030ec80c58632311a48ffe647a6ff5bf0defddee45927b9c888a8307ea592a3037261215036fd0b441aa141c7356d91031919b2f8e2f92af9134b9e42df419bd91cb582984da871da855643b4ff5bb4c5cd16a773c99688817fdd76b7faa1b0b1341de20e35209ab6a1016197fe373807f9e406214c7b9c0ae7aa8e4412c7330f88d053056363d0cb4ffe3c34b05727144ba6e418ff0c5236ff9a4bb716986c86694990d1887982d0d8c1caa1c471c793cea11b5fda1d346da4caa12e74f36a0fd8af52d743b9aabb1262ca1295342cef187f3fb13c1e565f7bb85863f86f93dddeb2613dc2aa2db4259e9c086ae837c4e8655a7e37a6e3801c6811718bf76704804fe276aaefa402ffbb5394227225f69e1adcc7556936bac642048dd86b35effc30b0723034ad8fac787a99022903d8b074cf8fdadb8ed3b8cbf75006acebf1d110534f3f533ae921c0b78ce67452adc26124ae25dd9bfaba7d4914b379360a812813d3f5743f889a442d4b6d437b1558b97e15a5db16296f36cf499417a484b4eed0ad96a626149a4d847df37d7a88f7e1773f89a26ff26e90b930fc2a8494cd6170479e0457a55b481b045dddf6e7362c99ab049d097d3251431e61242c819b4d22f70db675f50a7dea683a71b66f7f91c6ecb99c019d207a6edb7ca4f9ffeab7e29aaa723bb87f14efb2fdce5eca874cbe2e6f8a1801d1f7faad249cd9bbe72913f121b8ac6fe1446a0b182d661b0d8594f52e971955322c9c6595840aee5178518853df56c9676206ebaba2aa04f8a20960e2b5cc3be71681e85d686ee75cb2a39cb9b6eb6b0933f34a49487839995931a1c0c4f804c1f9dbc45c9996811926a0e8f9cddda2e7d6c946d70ccb58717660a1c8bbc7bdf868849de9198995148b210c81081f7515983e9e7cb807dad9da48aab614439811826d84a1f97515f915109383260e314f80fbf1f5606509db8f2103ea1788570dd8d452a8b2dd13fbf1538fa9cf2e9c9fa3d12362fa93d496d1d770c71516c794fa7a442c2fb0395afc70d900847ca74b989a9e400d3fd4c5ca81c2211c856126b72a296513fb401aeed0892efad767e23594b6c4da91e8e45779c76c6c94cd9a02d0adf3b9ded9bed2520064891d9fa14d4e26a311910148f057bfa59684b73813264a2a901d4f953040e2a277a15089841f12882b2e069f913787a37f7f9671be7747f7abce6a97e16183d03c5ca8f71f38824c0b2e197b57f5aab474201cfe23f90ca1e7a4f11e3733b1dcefd8652a7cf727c5ee648caaca370a20ef0e658334520c38d3c78870a9b3824ae09f4d0452dc5adfe57192007c4ee608e8594e7bcb5a8983004f2f0271b1a129b5c0f9a9a5435c9116c86bc33b1a2cca7b104cccd8e96a31618aa869f011056e5b876f257bf9557381e4e812ff830ed34ae2bfaab746c49e65b0811dab906967440a6850c570aa0a80f3bfe70996d14a1a9a3b356562a2bed99c40acaf107eae6809d0adfd64bbeb5045ba87073ed5714a13839906f11a0263fa078420606787ee1d0c1fd90dd8cd8f2f1c796604d54826d472df55ab8d72d20fafad1ae39c3dbf0d54c1b38d84e8ad9dccf402c27448364a7c30c169367386b9795f27e0b0b56b00facc89636a1b1391ca960f8e0fac566eadfe44aabdb359c9efa8d3d331b2b6105d5403730d9d180a6c65658565a1723d858425a078e6cd8d9a73c3e1fff7f57c2e12ba17ffa065efdefb1b78bd8f9221aaa227eb21bc4dec5d0d01011711bce5dfb699f2810f2fa15d955c9b71934b28e2bc0b1e37b075515690f870ca8324ffbb1ccce79a1fc706e78bbb465bc37034cd5d5dc6c390f1b41cbfb94256b64253f2f43657968313cb6908d8061db87209cf3da1050bb8a757dc765243e42590255037bfbec6701406049e81a5326d5f423a0f189ff94c32a333221882636fd5b98cdc9c14731eb93e9e3564b3b93ea155faf3eabafa21126a0d52c8c3b514080698bee3bba11f5ae26b5d20fc7f0ab3319bc5d6b5ff6d63a781cf1d02c570ad8d007a7c27e495437a2f6fa86f38e9343363ff315ebd95e23d57414a50dd97bb934b3ac9bc5b5cb6742c2f50d746590cdbec2cc2c025a1b6abcac53171c04ee700a6ea6096d462801d172680cdd919b21c80d7b0730642cdd53f10b420799c09b8e03e5a0ce59f1870fd90a5ea31dba28da6d43b278b39f0edd2d9fc82929e2f41d737dd9ad010c1bc06ecac08030713bbf9abd30e7f7bea89bf50f8020530dea34e2127c58e35d9268c1e7267cb00bfa9ebdbd929d5eb0f686d8927f28cd8e2d6487a99523fb8704f426d68d27fd8e843b880d5e1830d94c66537c36263e231c78baee3d32836658aa0cfa222377bed6912e61c6bf920e28421062dd1df2ca1fd3524ad599ed2ebf7ea512b7326e2b86a2724c74977cbcde823d5f1128c8061a4e6edd0e180ff55de5b77f37cf6c7b50f1be0b4d1d8b6ea176e14ef03593024fa9a801677a3ce854d53fb7dd0041f47c5c466a1ca103238ff5648bf52fccc159b34e16196d3e91ab6a92571211f3154ab9b44e25d546c0539e2c59b428d36e5c2cd272ed254500c49a6d09984e221fac248325ad848c01ade7319a3520c83cad8fade9995048fc2e377b91a0522200c1d3d38e54ce2315dba3d792c12d6759f17eef0edb7d502572f6e3f1bbddf2002e2807afe73cbcc481572ed55f11b920e0d25bfa52f10c00c175605eaeac91308d0512e298a055e05de156f0d633c3a0c73525e62d7e5c61edb032139f9aa7d55902a0fda39066fd662b782f4405041e3f54f29781b264c4194d1464335fea1e618ba2a6e5ba4b62c8a5f0d694254379ef615bbe3a66d75cc329f68aeeed52693d63a0f66f794d700f72d2edc303a6e57ae7f4c0987da01d7de8c60c263ffc64c01a92dc1f4d066e525ef07c602af211d442c45e23c1f78b9060a95f3f102b3557dd3fdf5e673b02a23f81d91639a936a656c0c877ea8ba7d235c78a91b09ee51db1e5e9919cac5febcbd39cb70c95ac9efb1c547e9a7f88399e5362dac5136b3fb3581cefb79994c01f07ce2434d891d7831fefbef2bc7983e7dbd9dcd83d8de60d0c68536e8fd5ea14f5d33b27fd3e2ba87cce7f94d9421210fc1989758efcfd4bb6ab8dac93be06477bf57c02840a3a6c7252a91bd612007b1e0568b0829ab2d41347594017d337f06db94c11c35ded31fa365b0874cbee6000b9ab06eecddaca8d0c8fc064e4ec96efdd9e2b6cc3992bc48220f8f1f6ef697063d0c46a617246641a73c6c3ab3d26bfaf8706dfd89adbee69abdd9f198419b0ea1e8510de1b92c616ee2eb2725334bbfee90c13fb8742087c0c70cde18a8576166601332aa002a347e65452e2a2237cee6705cec7a1e2425fa6044339b63bf5a047ba52a49ed6bd1e88e4d6ffce458480df30afaf3ac08037e0dbe7a6cc95c7842909db75c6d8e1731eefbe358d7773c71b1aeeb77c102780d48018f417edc1429ee3f3d18cdba62e6b0b4488684967e79520b4a1ba5a8df08f892253e1fed1915cdd201e87d75c6d1d2554a99a341e487a1654eda35019c7c38c86f5c75020f7f9619a61150d213b99b756924f5f9895e71f49d172a31028270f39dcc1ddf929992a516e4c270ac591674e6ba2c13dd06e0b506041e8942778deca31ddc84f4262ff4ad4d81e531cf16d4d041f3911441c12c77ed92459409ab65ed1949920a684e729d0904593d7a42ffbceed454a9cd23eb7e1742bbf6effde398f122a8443e86c272fdb97ef9455f33ec1161b73013800c40bda9d301d96758c6de69d103c430ee0192f74956b3d73cdf3cff36850d0192633385b19d546bc8f0b1f9e3524757f2d4245646a218b78e6a9f4e289b7882910167b2cca4ac0b90203e5ccf084ca174b16b6c0570f6d9c4e5f08815017f92a4aedd6d5cc3f40a4b9384a77405efb4b87a15caf74bc5d04197ca425592c0900484b814b3d1926954716e1df3b7017a22951344fdf52496f797562f397be1a3ef6bab299a518e7ccda7e5fdd166a6c3e94debb1930febcdc609b93dea783be0d009656909f18ed83eeac7cfdb0a5954dc8b9d604db26c6904d8ce0abbef49d005d2b718f92cb54a7adad0d106a0400ba35808525068312f938a58963d7266f1829495bce11d4c0c05073ff5a72bb508eee9fcf3bcaeba833bd03edd36a49272a1bd479d2408c272e3badb2ff2e6e036aae1ed1667b8bfd538889f705c624b93f37293759a9bc6b57833ea34b0973dfa3171bd9c81715bdcdd39a1a5a16645532b276af5eb53fa910f837f367301e75c8eaaf25dc6842212f5a43b71a6f76c92d600408f82c64dadddd2e72075a070e7e62baabb69fd006132d441c4f184c5d0f869993de13d03ae69b61956f37f191f05b24d242c23bcee76e5ae1726a296b1b15bae2365e9379db640dfeda8d9c7d12a653252a104891a78fd4aa3971af9731c00ee4e0c2f2a4e4fc6e50d67ab75024acfde2fcba159829904f9b27982f2e251f941d897bcec7ce91edf7156cb1754e27813c59d3bfae136b5fdc4ec32e7f17f5d4c4d078f68e91ead670d0cbb30054f2e90fcdf204ac0b99c8c435d932c10ba9267de7a61d791731e0d39b6927f8d8c4b395e03f239d84b717021375480b2c36e3b110777eda7b9e67fbeadb56cbd75ae21d5bbe2f95bd5a2d21ec1a5a403c619e55e46f332c9f98368823f03e4bbf12041f138dcdf2423400dd940062381e75ed02772618afbcf1bcdd949e34afa5bdd0c25b0addc12c1bff4e7faf0a1608d0a36b250d7997bb5711e1b6c74fbf391bff697982fa2b388f1c1934483517257f23bc65aa0e32b5631cb27606e552c49d8376d70c7dbd53570b8d92ea893d3c7b1bc8f62c174ac33faf08269b8d173605aa9a18d81fdbec0e392a6b0910443c504165eee0571388028e1512b8384f60cfcdaf2ea17b7e9c1be172676062a02de0409faeb6f0594e0fb6e696d6605dcf8a5be6115589e2322d7c838bb06f7908aab838bd06e720a051d07233bc7bda3bf1dd16820777d5f57d15d8ce486c9c0081681824871c37c137be3355e8587d12417caa506e3c14caf7a1e9f2d94d6c15e4fc132b2a62f4fef4d12d118ba9d39313a212980dd0f4d7a177cee3ed87f02812f6c2546004e10249c06aaa49a01657c7c7d2ef5c155310e2b69bf2e2b5ac3beea29add230e49ab31149447760e2c54745a77fc33127beb384adea5efd15e17aec6db9af767f1c1d5d7b2cb07c3b193acf0ab44c5804ae5c3e382538cbafa1ddfc31f1448eaea7b0a7504e9fc5256e4dfff39ee61145fe246856fc4fa93d22154068a45c9c12234f6e4aa3748b0a5418e4992a22eb18bb8033793715318370834424065bd4cab694acffa6f0448a61844d4328eb406b72b3c9b2b610b5eb50007bdfc74c7feade19a2459ac4b21856868aa06a2d175589dc86345b311df552ab8a56a724630d565e4ba55a1abb0946a0a8d6e2bc453d4dcebf1159c82b98816c8584ef251cacd77c3ffa104ffbaa96a90d876145fa73fc5fff5f5570a6d8d1580e1c4cce5b5f8e8a5d2b1d20b41b4009c79ebfd4a8e1636f6f93f12593f0532d565ccdf90ed011e0ab0fcb3db28f10535ef5e93f59851db610641feb3bba4190f3074e4257bdfed4f05a52c98c380a471bb3b952488283be1f14fcad4a3d219765b4b2b3421d5ef845f6c7b9ad6af6b66a75ef0c03ab4f2c5150c078068943d1e89d298524d9e9cc5b20c3bd03d89d7a6d3cf30b02e17516e0001b071b92a35d245e0c596071fb8dc53e53159eead8cf86441e0348a0a951d4a2ce30274b423bf3cef4e5969077107e166199d2c5714e25e2e0bbd8db356fcdcfb3d3b8b04066c193c83903ab0f0eb18d2faa428f3104af484d07a96e43ec593a5a9bc6d9c2176535fd5727a3acb3ab4b2e9e9a570f06455bf2b68cbe461743af5466bf7f8050f5c7710b8cd086922c098d4c9c26e53708c5523c0739705505aac79ef65781f226761215eec4cb44f8317b2fffdb15dec242532c0cc8db35c117a35278c54034cdb69bb5df20b8cc8f1eff23bb6e8b929a130e44e0b0812e937fc89b3de0a13afe080628083e386b703ff58a07fb599b66605d12342bcd8fbe69ef239f3ec30bb2fba014ab66bd3344d60786edcd434fd3a19f46353cc0c7901e051405544028bb9dbb1ba427c4b6e6b5a3ec8a593f0832d6a61692d72bc6faf044ee5664b1a7b5a3d38fd1a1b436b833287a162ae7851085a1f63bae8f2fe18b09c603ff33bf0b5ddd6cee3a4b4275348c9835ef59b44f2db1f828f77d0b7d8df70487c91205dd731d9d516d9cb6fd88080f45312c10edc4cb8729c7e71fc9fa87808bf3a3099918984a60eccb1ce433aef537927236f3e0f59fc922b0ff7d0b39fa53f7c19b5048f8fd2e9a3cbdb8e6d7d156b697bd7242355bce57cb3d94d16a5f9adc607288f3ec2641d42eb3303e0344ffe4e4cad5d58be766687da989e8448a5cc7c1ca4ddb0e6cb4f4d22104b1d32f6dc3632fa7012ed5e9d5a2111dcfb62c7666e1bedb86bd966f9caadc2ba81da0488c78352f7d3ad94f35fb75a12272754630a20e42a38a52c4934c5d3bea8631f590e31ac72b485478b7d8ba786e2bbdcff8d22a0082034283aad9f28adf92604124062230891d81f71872c135d234bcb76e82dcfaa6969b84c9171805683b4a419f41a830bd88a76618ae387e3a69254ee920a1375d8362b4e038a2e2b4a98b1c181ae9e5f24b19b07c5d46bd50d0e1e37502646eceabe404904f3813c243675a8322f853d45614c7d56fb8667badf80b87b10ca9d2363e37281fbebfaa303a7366de81d92fdb81edae1f057fd933523dd0a0b88f33140db7acf9131d23420c2b976156d2bfd785e9c8c7c7a520abf8b58d204ef04b5f5f9424c5f305ec6d97f582627a9f7b1d124dbbe6bbd4a36340292b70be4278a0bf1833f90bec6598d3a85fd10c37d2c7fccb02e440deaf2f191492c242d84f09ec1e0a034843a5fffa7c63cca1be0c6c378ce3ca56bde144d25b52412b27185ea5d4a3f4764ee54f0bc70c489f6d81e8a9c7208638f9a3a0bac5ff8b857a74cf8363d05ee1d8f3a166cd50701e0fe692879ce79a3d691424066b749abc3e738d5647bb844731b409cde36b48e420348197710106d7cc0d216cdc677b81c4300b93de75630c4b3e117cf10b678e538db372b2304f314a19d41b5534d9213d408155635a716fe42fa7a03ad90cf8866c124e99a66405883e8bb6f9a502937e18db7c266d8cdd119d12c7121c580f83c2be68d9a65744d77e15c337fe898e1b2fadd3b48b4e03d08d4cbb2bd50f567c1913084eeb5dd249c81b71a1d3a20e2c0d6a8fb7f2099c60904310e9416d9b34407ab6d32fe2bba4cfcf688c5c92b34fa937b7c5345fc8724085c893a5ee567bf6e3b2c1adae130a72f2a3a16d8920cd7e6b93ddd1352a13b1505cc0cf4b00a3ae34a00cb2f85591672068027403537fd0721374d5936ac968952ce66bdf64318c927bb6c184a880fa15e384a3112b78c3969161d05b00c431ff94c55f794c150ff7bcb35265782fbc6ef4903632144809ddbbe3d801f67d840f06a15f966775826cc19fd1f431d9b2dc8b552ba3b28eb47a6b96a038432ce40c84eec8854e48d1172af6aa5719778915b64cbf2bdfd1df50cc32b2736181d4664ed8bfae97f49c20e30bf9c4ea8e67b53fe74afb41c63b12c30eae8c890a5ca1bebc6ea3d553f500b755430896246cf8f4577b3975759e150ec920229f0909348a612900466b5d66e5e2d331d6d9aafabb50bdab70c93cb2d3f6647ff3e399e06946844e96897d74d22795ed647aef1526ccf5dace92d9f5578c19b0d4747d50ab9442ccbd04807a28a35e0df84cd1d4e9c8dc025717871bf8a9f9495ea8d6f6d1687cb1b3c2a6ccb25924ea8c6ad9dc62bd510325df9f6c52c391218b8fb35468e6a855878f17f6d83f866cffa34a2d1f3c21e17cf28514bc1b80740721f43424681e4b421367c296b90a75a116d59c3bc06aa93cf2d809158a67ce2ae3ce452706f919af9669e0f7ed795a3c0316b4ad876d292063107e29e7374826e95233a7e66a89cc7fb4a6d96487f2f2fb1d68df0c0092201b68d49a7d03461d3fd5927b89fe693bbdd3cd201155aef2f533edd651b1802f530b807760dfe1b4385c3ed4000f6a8118b0a3df4c412e79944e444fe063d340f4871ba816c772ce322db4e55348b6e5046b1e6cdb665ef7731e4dc58c93a21102ead248952e94d44bd8357a49f2641bb636285ea307eebf48939441ee1e31a03adf3198df993b59a995d271e9b851fdeac457d6355f9c207292515c0ac2b3801c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce9458607000000000000009ff3604b2c9238c3575aaba36bf28511d83a0aaf443d53981899c20be308112327ed070500b374e359a90435a60363235ca445da700abc2c3b962e89ddae24040006000080f8694a1277777777000000001c1d1c00000000000234ba607b674dd1faf18173ab52cb86ada65b24659b7ab0db262a4d46ef6307813610d535a38b024b19e566c3d73cb49c5dc6a73457c658fa61aa19c9a669d70823c009c26d2c4c5949f83ffb187b8d03a7e05970d87668b9ebb172e5b44c4f300bffbdba179aceb954a3d6da0cc8e9f59587e9a4ab1e9578466bc9eb508b791bc0497d33ffab8b845eed45ec6d6d9072da6064b0afe5eca2b8e3caa4801e04990e2ce95ee1594a1f922a2ad1e0550fa5268c2e1486785a68ad25200e0d1a1fff176fbd7f928197be17c9ea0d4b2f1987cb4c5d4e62ddd8001803e1672d2509ce5607d0ada2ebfd792a4eada56d50babab5b04f4999d97a78f2fc35e1ff001aef6c11bca252ab1f6959508604fd29f29642562b862c9d326655c735e7e9ff0e5b539d819b0ff9b7594947225abffd69d94748a59b5e4798eb4f0d9f41848da1acc1c42ba1af1a4e69227887f00de8aad96af6043998f72164b95e9157ef40f3253d38dd577c636fb694a49fbbeb14a153d3615454c5ed2913c49454efa45880b7e81c288c34793ab18eb68dddb3b5eb8c6f9ef4889d0fb8d3a2dd58164e5edb536fc705b63b194f2dcf384c026004d3aff29e11cdd17ac5c71c26d30ef20b5c157fa9c1c4b33d9bb95cc5882bd36d990fb12700baf432d820f66283742ef447d962088dddc54a21b162d0ed191f12d4b335b4227aef5583bd2a7639a275dd3c6397d11baf62a2983eb982d0d4e5bc64f8bdfb72a5b7f99c81c4af1395d153c9535ae61358ea5fd933e1ca35dfb4344a3a096236e9c777626575f9773f1ed0e64c7e67616b36b48d9f481453f8815d4e48601961cce17d7e5cb37be71839a205a208fd7d35652247b32d384453f30376c2b0dde5d64285c86ea396bf919978de33d5959c7a2bf9fb5e15da56ba2b11b805789d994dd44b5b39952d90bb9cbe0209c63123cec7ff2f2da1c1ebc0930b0e3a03b90dd6e58bf83187e7b71a9a5264fbbfeb90c57647c5d6de4752ccdf657a95007a21a6d8e4910ae99c90e98bef3ba13ae57614499747369bae218a8fcbdf074b48a5f374f74e769d02af067b82283116764abbd30fdc9923a3995d144bf1033ab26d3197ab184748b4992bfb51b0ea22cf3bb574236f2209a2e1391f153b706d5b7640e8a23778332fbdcb1e35cdee0bdfa55c35b02b793b6f2fb01893363d01388391479aee427cc977bef4cdd250e78a7f0f39e711aeb13be5f9a895792dae2657ac2789d2f0a5b0b7a9093fdafe072883f6842e377b05a046488db93fc23002a40a7315e284aa164b2e144cd5ffc6afc8584eb5d52b21b48a924e257b72a180792eb6f8f0a5220c0db0fdf5f5d0a0aecdde7f194e88369ee5d2efda82edf85e8d20b69680c677a4ed53eb33475b9beca2c560386cceb4ddfbd30292b111c37530ae6ee207b87fe5b67b5a90943e2a3c43c66eb8f9b1b006fe008f9da8791e71915349b9a9652d9c508adab7668438eafbfb46288de70ea1f96a32d36ea48e0dfc3fbafa1ea69d28f2b3b1e291a02823229ab70510e1fc102e5df0f6160c7af5ce67e8a6dbdf5e486d285f2b4ebcfcf2c10426ec94e0886edbcc0727b0703ee6ba3a1f7d4a5ceab9386123e531cab919407eba95c72314e0237e4208e22981b912ed9c2b4cac88a8592fb62d648846bf411b886a6b89b83ad03210cf072b00019dc6d0e541b6bb9a22ac9b3603ac0ede0b27cf0998333446344fa2cb44350f9dbc5d557cbdb74d335c6bb398ecd2eef9686763c1f21a34970e810a8eff7b37947fd455ada6010eb00ed5f1f92395ff7d1fa77b05beac74c53db704530f54a5947187366dedae6d48386d68c303b5eeac6e4848607890ad4c4ec6fe25251b4727e8cd22d8fc8972840fc8d5887ce647ad628b298e15f9cdd49b917887e0f8e8ebe0312fd04f3871c68f402f8dcfee60e81283a66f1725ce579861c999ede9f9e2d976a83253ea608b66ccd6ac83359bae0d060adb0f5573ca385446cf54f14fa3231830ba0243fd574aa8ab787ef0150be0cb9c38970043d6fe200fbb6d03158f33f5e3a811887ca482b83122242d228451449593c8dfb33190298e873d49c01b8d0b9ce8851e60e65308325bf3a934054fcc53e791fb117dec249e9836d466ec94188df94077762d8c12e8cfcbac6a9af9741395ee566c26f9e5ef21d7e08a0453fd22ed3228f9118bf2606e87e0e0d1e495075f348b16701162640d2b805fd4d2d3890cd6bfd5afb790ee9163e30d55f8015ee86b07d063dd0398366e4cea8379c951160896d3374b1c39093954117d7e3840715e3018b917c6ddf9c47869bb01a71793b2d414c252cf62e9d781e29137f59978d39b8ff60d45540bdd2dfc73dd0bacb811267b486783e9e9a0d0d5a2a161e082adaa070000000000000000c099e097f2395a8b9005d009285daeb45a1d7b6803b4ca77f140f451a575d518fde01c02f3f899fc0cfbb1beb2f0a6b1364b43fbfd5e372a1b64b90685c1b0750cf93993917608f18aca5ec561fec653860b83841a345f03b0e9ad5360c2616b8b511f973cb8eaa583b1e65825fb0cde26316a897f759b9c79d96d4bcaec217948791d524ca3ba26457a5b6f5278171729abc58fcfc844a5e2e9ff048bb334bd46692d97beb0e892e144acb380a1a2810048d5b4226ce2b4f9bd020ae4b26ef3d03419236d3862dde808d4fbc7187da8d7a63c5154c369f26a905f355469a0db4e562de2ead4d75b8693256748db27c5d041f6bd93bc97c7cf7a6f2c2966c29817bc398cf4a61ff5c81b66a7c725dc820e24ccbb2402b16e8a5a9e0d676193924ecb3a48bed2157a84205b689c5f673b45f5cf8589d2e048366b6e3ef58a6cfab7781e90d5f0f2922fa407d0882daf4644908abfbc5da2bc90c09be46ecd7667947d00094c2024142dc31a072b758c2b4c5306e458256fda993ea15295f970f480cd333f986e7f633ba84f8981266e9db3b78a3fa87052a648fa99c4dcb5d1420da4bac5c6ffe822276ffdd6de43f39987e9ffb1562c8e136ec163623c1ef0b957bfb67cd4af92e6433d2b3c757be0b74d7053fee3d1833bea1b076b4e2e878b68be8b661b0c54f6cf9e3bec410ee0a65c0371b4cee0f3cf196d88ac4ef5ca02a42e352785e77307367dbdeb20cc0aaf0be2f72ddb4b12cb9d1e7ed530eeef35a44daf8d80446626e90ff4d6705317ddea944a45e094901680b89133957343b5209a0146722d0d494c9fa805231b072740b15fdb7a1e0dba39015437cb2e61f0cca0179c0128c874cdcb3e4c377925a097d46a2ea86ebcb2aaac4e69b8d93f3f813fa110857017ec1126b0f48e1b61ef1ee9f2d3288a1ba037b28294d381855a9db1a44f6aa83f17773222761fad2add32acb500f060e76600b50779934496796f4c86114c123c55b42ce44d600055e9e249fe7d5f1a80f54d49e5b0dfd71518a7669538471b5e759dfb425c51d742df88cd4237000e0989d5e554f698d0112bd61a33a307b36b22a76aa8e2938e884191321c09c1d90a5678e903a5b76446698e5031233ad87218bf81d1f49cac719c2b27afcc4a191daca45a1c9f51425cf48008a1a569e2adae4627c233bbd024ef0f7c3973ba5bbf9fa0704e111223cce823d50b5d91fc0d805e0bc51daf91f0375b6feb67ed3a729933f275fdde5f8c1885cb9275fbfe2796b9cb4dc5d3eedd1044ffe62bb5a4f20c0969ecce5a0233c5a7740f9f18ba0a6c9a38ffe4b0e5377e6e84e659ece4b09a516f1f5e158f633a18b527ae8cb2813b6fc27f5108a7230bb2ccd25f9934b0899ce9c8cb3d5afa146791b52509aa6f78f02904882b0730d1a8630eb2c3e408aed611ab9cdede995bd2ab2940dcb74cbad21b1a8c27bcdd2b3758c61e5c0d271dda23139fdfa17fe97f19358fd6e4e6efcf71996b359eaea79979375a010436dc45f4ab138d7426f806450b624c14febce156041a32539494b096a3210d114d203df26b1cc826fa2946f53b2521ddeffc30550bb2d26dbd6900c912852b1741e76aa7f77b6c4aaafd16760429d5ce5d3cecaa3e1ff1d3399dd2e4bb0123d668b63b61bed7b097daf5a4710e82dcae3e2db6fd652bcfa527938559d83ae86982f26cffd2be75bb6f842883ac73819dc831dac60616f3c85011bc5139d67254cee29b964ab71fce45fba367356f2122a61544345df6d07f423d13bb32c328125323ff62ec30d67cfafde6eb20c8bf832b8a51e3de2726ba66fb6a0224da5f79286ab7861dac4d7fcc85c62f85fe476216c55ee4e5ebb7ecd3f642c547ec45844ec95586eac20c1834a5abb0ab3901c50deeee97ebd64d9980c53e0b8ff88e2273331b1484adc54fd459eaed17ade204477a17b54cfac56fd8d05f3ff4edc2e473295817cc00ab5c34806f1e370a9f97dc474e0d4e6955f915cd6d2069df587eb0650c72b4d2454142230623070f6d21be2bdd0173bb0a959990d9d250e47a2148b42030900e9e7014806e22ae690eafac7a2b3fbf45d6b51dfecbbd21993a12e057c82425533990c8b5c238a6d329c4c41387bd693ec77f1d6d200f17a86063111051f7090c2bfa3ed2a58ea8d22015a2cff83e127edc0383eac49c3b6caf9b5e0ab4abe911658ab63925d60842f70fe83f9ce4258bb79b6311bff08b231078eb8eff59e9dbc955af596ea7acd15fa8b8e1ba88e110ac383eeecca4340797afebeca8fa7c5839a3a306d4bb8004cdcd0372d83cf4e2214394cc2a09252971cd530af7802ac06d57fa0784500c40581efce6bcc497fae84e8bbdfaac727bac1cc0d49c0fadd64639c6c839f6b3e4735074e5f2cd2b5fe6fc9cc34152d723f1e1ef3fede91d41cf39a8207ad69044d14925961ca8b535362da356e419de13adc49ddf8708b82e6ba3b5609ae6110f28333601eed005b94b0d31699c8a687ae732b7d7bb263081cdabb462241911bba94585d0e20c9b41f4d8d5565e70bf351ea95382544864f4a960b8850fd5095213c2bb602338ab2a3f9b1fd97e8d42f68f2f943441ded01beb76f463997f1709e92c9e6df0341cc64ce46bee5ae1ccf0037b77ea00edf62f5f545d16bd063bd9097ef8eaa34d9dd1cb7b2d7f080fe56d14e4eb521da00c7c1d19c13e934601f963f80fe122c184cbc0047fd38cc0a7b4389debb41f44c7cccb596c41936e2fc672796877e1f0d013df6aa65a8d39c60e49eaaaf4bbcab70fa97a0b864aad214ba57bf5ba65abe585e52fec23b33a8fec951699fa4ef19e4af9e7c237248e1f4a71e6166133b2f1b6949d70f072170002b3d38dfaccb3843e641e85bedcde02e289d94ab76f935ced360b5b4abcd503d274923c222d757f8436e97156e067037c7c984ebb22b836bde9b5aefd12b6f079dbab91f69bd904facc456154ca3a1730b6fc7095af42e8e20d0b94ee3c797049971d28d583d5d1d7b539e8794a7710c2de9d2a9db9e6842f7a6a410b9df0f16fdf6bb58c35ca3a7d44b965f04e5e0391f7ab9789ca3f88973b59f50cf46f0d472e4cf49cd81c1b05d8640d625d601155db952b3544d54e5742be75a4bc9cf0d1084bc141b76cbb06290971fa526001e135397dfaadbb5865bb00fc424700901c4e50c7aa4db925b9b7fb0d8631b311fb820bceed1f83a6c166f78819a059017c7e7bc0b134aafbcb063ed15ff67f165441f7015d9a3514ad604c82e400703302c8e2e2bfbf738ef380e6f690392712d64c59fca62f638f2dd8edbb842a7ceafc4926febecfe42d5327af88fa21a9320d1f590803f35b2ecae7e605f0aaf99504537de024e600435f4963aae484cc3f6620243c307ad03f87bbb60696bf1b66409b143dd80362b48e74627ba790e700b4a6d10a4961fd6e4d954af5e585e44a02dc9137a9f2c5b2f09c5edd52924a0f62e0db46f2eb9c15ce3e9940f16a4c7c4be030c02182b2aef10f01de089f380e8afe59f6ace4c9f34738d041cfa61e19a64156a675832d16f4ee54526e0b7c39a8f48dbba330e8ef36b5564d263060c90009a367bfc4a9d1fa7e7903d0de3b2a68de720b8bf070f456306084485cb3858e98004be70aea72b6d0200def4f340ec415fdd2bcaf28eb60a1c2854fe016de38232c721b6d3f3325a101b77ded810b660a83f31c46a5f13a5a08aa6df7da23d0eba9fcbb45ff299761741ca950e12f2f1881946ed0c16f62139d03b430d1dedc3e7f7c68f2bd50993adeeeaad42315b36e0e592b42f1caa568156ea7aaba4072425cc227be504ae30f50335793483ae94a208efe33d61a1bd8cf95db05914e3b732a6c2ea57180dd5421a85a94ca2a97c80a41c04484c5552bd6489ca235c28d773a4d5122d93fbbcfcf8707b88f3d2604da1a47cee05bb3a9fce7528905b5a279a51b44a72a7bfcc9d1769db1813e161dee4387ebefb87805c1bc133b7cf56d549d165356bd3c24b4fd4cbb7a920cca8bd5e43b14557d48c1131a5ec93b3dd64a8d0791d9e50f4f501a5c858f2110418e110a74f7469c1b2ecb54c929d4c08927ff36c4106d696b6758823b235b2a0704d52ad4da79b09c140c266153e7e54ffe69776b2fb97ae8d605c37142c40bd45690f4207e4d3905cc0e69f548c9ec024a2ddddff639d148577de8be4a322d756efa88eaa2e92f2edf13a664924d341a8f95760db3d00329c8f882c24ced3ae07c89e35d51b7e11b0d1e53270bb0523ddde6e95ef8a0c05d2d2b6ba7c6ec169202e6102335e193e302b8c460ed998878abfb1db24e1797d1e7605e13598923a088f38ee8d824d556ebca3d36311acdc402555cc962cdd10936bb4e1ece2e39a6078516e98169fc31fabca7a0edacc689d6a5b4fe2475c0c73ce3d8510bb903260e1e381fc5fa6ea920c8bd2a8ec145eb778f9891d840ba5a3f08b0f6dd3f07e753899c30fe2b565e821fefe44cadf2117d358a2447b0d8ce48f742325b7d358a96536be71ba650ebc36783be0ecd540fb04bdd6a4cc39073df2b9a5ed9b23a4e2cd9ffdbc2967e690188dfc052f21bc49e9c81be87d12b4ea1a770e108d50de901bbb0d046c50a4228254aa095f0cef9d608b0ef50208b0eed938cc7d136207105030c72580f3d5c707b62090a29415e32af9066217272ea6cd498b5c1a81d06314c21406328037ddfa23222cc84c3afbf8cd1c3762faf04352bc37910971404fd446bc4beaa71b98135724118a1dc65ffb937d5310fe1f40c307095f0d3314199773a33bd6e2c89405f48bf12d6651d789e66f1820cdabb6107bdb309b937d8e0f513fef644f96b702e509903ce203c95a10ec4c9f4a71e75c9495038b423de361a86cea19cc2cb4f1f1874e672b2b2e97ee9462090f0639864e95331262a4a560c9948f3c74db29b1d979b7648a7a18536d7f6d8d2fd422f7070756835185866ac588a4daa8094185982d0879768320c5a05a95f1a761a9042efb4e291395bcfe4924fd4df12b131c3520fa984499532946adcfe20cd2fa56d8d44296926284e91509bf8ae72338c28b93974700af04d3ca38f55824ad9f52bd0e6b05f2c7bd8d324b4bfd657855c8cd458baea1bac09386c4444cff7594a870650c1e524230b2a26d865605eee5a016efeedc957effda3d1c145ad66982ad9188bb80c2d1546650750c7e79416c80d7ac102b47bc7798048489afde2f8461a9162997824253047f3d0b0148160aca7c533bdb6710281b42e64ab5eb5194a78d4244e601b67451ddf954d429fa006f25e09ef2a78388c6dca6228f17e3fe61510038f162626435783cba9d6809fb7b50fc1bcfb6231466454b5925c32d04c02e5bac1903df02e8b2ef25e64fb78d7daba63afe4bce774148ae824c62d778d88b6d6c7723cd5d56278b36058f492e4dcd6cb898414f521d9a21cde732aceb5a62adb996f1e18d950a982f9fee6c02750b13965ee93d80751116df1a5884ee24d05f0a74a3faee0198fa1f42bc5241dcdc623ab172dacf6108535f92e0279b9ceb96395073a5b009395aaf3ce8df09add65b351f341d2600351d24d3474f7d123fa7e51f017b0a0b90c4cdcc5db57927d8e87319914fb60ca897c7642e0e323376070cd6f05fec5e74c88c3175010761c7f1ac3c00e263611050c29a932af6cc7908eea6d1e2cefe518c6092cbf7fe7a6c5b0b821aadf6f4c504a1de79e723b5c17bd68d634d7b18b4b9955b37d765c464dcaaab31b9613567d37640e3b7ba9c2abc9b8ad3fbe2ee8b62b4ec7223792f76658bccff7069454442873c81104f5859de761160347deb9e1390544369afd02640ad5f6868e92c2d576a13808199a53fcff7863344ece1634086ca08e72b8d8dad0c11744ca5889437dc482375b6371f12853a22b37ee12ac0bf851194eca88f4e711d6c010135c46cac6c4b6d4d22ded888f4306369c5e7b716720ddcfd1550760b2674eae607713c5696f43d84af2d853505636f0aa30d128cd5ea230bff5a9322b0f38fc998eb902fa2e66a5cdf573b67faf264bd8aee6a7baaa4607ca070939347511a3e7fcc1c2aed75942bf4b02a7a3680f21e60ba2c3fb198e823ef8742241a5193df74d2fd25e4d28080588ed992440022cac1c026a3bf2c1de232751ee2c56381cc320b8511846093b8c82c3b69bee0a5703ebce82d93c99555970e5f192bf4c1438ef3d583f40e8b4042138963b862055a0a8b1df6cad65b82d57850dc251e50508dcf9d58c60b4d6d5f706b10bbb25717263300d3b432ccb759ddbd52e5dc847469dbe7db86ed6d35997f93f8cc939ea38e0eefecedb429e6ed8b028a6ba59954ad0b1345816bb14ef04d6d922770d40b19adfd065256ac351479ec65435951bb014a5fdee04be55231894b9390a28c7823bcb54409faa06f1c3da22ec89f0f9421fa9a33bc840a1362863b549360829e94a149010328b366b45d94e44b03182eb30c63fc967159c1df1386350c53d8f249a1d5cf7529434d61cf0085c59fd02171e5af8f1c82f63d8fbabf8f07622899eb8d01eca1fc6e242d202799005db7e6d26f734d6963a81ab2cf54936440914330b0a7a64f4c785c0958d72e82720124629c630ebe6c2fa7efa9e2272c234db67c5049db7b62f7e1eb3bbbdbfb842fa3df06ac020f84fac21207504412516cf601b65700c971606725d4fc31c4ef15a6635efde36696e339f2cfd775184233eba170149c0d215428706551ada80a5e9509949d22eeb0ff390d1d172b7033c153fadbd3f158b87cb300dea6364874ae86b93e5863f46d3fa2a0c507b4c382a46e0f953854689ce9b7f2a30945ac9ab4848297b833b4fedd6f839ef106a7028f1469d0950628256fec62aa432d6c0a85c3c4f5a6b792c12992a84ce000e6c1aeb6bd6c354960d9a741e0ef483a723762006e291f5950075e35b4223c471cd23733b1dddf91eeca80a4535db48fea257297e0b02eeeeb3da56c2b7acc338240f0e1eff611efae168d566dcb55b9a9d569539031fc4100eb6ca194a369c1330395dfc82e506d8669ae0b80d185a1f037fea20a2cc16da225b6e3ebe2dea684a032dd222dc5df9679f927887e0323e2be5c6b5db8b45640bc9fa099432d28c833a00b04697cd0817b118b78aa4a1ed51dcfe3fc69560b06c859284c8581b6ba223af7d55a3c623400aa0a30fbf3756e3d167100f5739ec9f7fcab49e5164b08b3628f9de44f0e7fd887a88b54305cd1c57a7b9b4ae5547dc617b4aa616b02fd638f4d030b7d9394929abe4264653c79bab88d1210197fe186b41c32c4ffe2827174edabc9cb926173a4afcfdc16e9386d2c2867d9d07d014161ba69169d51d61056d0e3d4c6f7e2fd93d244df132e72f560569889d635cd192f7c6c75fa777570aa806c5c9ec31b9432ad8070eb1474e9d685eb85116aef47ec47eb621c33a38301ae2348233d3b49ac13e64c70d4c4d594927cf3508f8ca6c040e71c95963820d7a70f22fe3120ad893234799be5de84d096b5b8961cdf8b09a52eefb994f433ee5b57ed74f1eda8d6894d2d19fd1faec1d6f34aa175e4b3a8298159f8a6e4130c3d2100d2c9ba994be1e20367f5d587d34ad6c2b00078ae1fc589c77ef3c3d2f0819eeccff1e7b686308122d9d8504b39be1bc01425d29147ad7e24db8c1c132b955ab073d37fc1a83a12d4155f747ffb33779b2f58e4c862d97bfee479631188a1c888ae437b39bf9f197fda0ce1708be825c4eb5bcf8c419b7f44d1be60c224b70e8536ba3f0eb79d6255438988b420f80a81c2f986a8abc2a7c60bf54f0027e1c190c4a8711fbc8551441c6640130372c515be3f22cb10fb9b53223096821a135a309f40922d5cbc2acd57e0d7cbec9d47837ae1465312424a77c6be3451090277f17d6225a0d634455659903b1bc51e79c1330a70d6139e9d7fac08e5928f23d2c10c6268ebbfda4cc45948a33a263f672a523125d188f64c9c01b2ef801686f5fd26321808e96e07433968d05a44864eddc2d190155cd3266c23778dd1cf843a779f77919c8e7a5560dfebc817d703f3eeaa802c613992e5ee2ba6ae90600125b1aa07f04902c524d3cf57e1461d9895461117ec413fb3537752d755737738bebbe1135afa71db91e93f33771d16ab3134f0d6d588dfe23ec6661698421c010d43df3dd7e9c422f8b1e34ad0953e9fe8d7ce81f4b0a62334f5229c6b11fbf5889642660619a2c1f0e98fc561836f62f61861712455a193e54e7c4fe6f1052296ee852b33ded957545dea80dc5f0c97cbda1d7a6a74ae0f482a59e8cb33bb42522b6652eae4ffa1184a2de0e215a662edc4731a0e6042a69f93fa68cc9088fca3e3d8473d5aaabc62ee5956144fd68eacf289eabfe35e6112e919837b82d7084db1a4cfd8e1a86c4ea3b90b890aac23156b50e21f293d0091cb71822592ff9c0493c1dbfd67640a5da51820cbdf5b86bdfcf47065c715bdf265190284a0b73ae525c70e05f0b35f67f8d8652f31cb650c02195c931546a32dc64207c2e0bc73fc8158e7188e8dcb8e258236356ebe5e35361b0bd759fc8652773690a2908ccc0ebd47a889f3ab783f4f3cf12738b7b2323680c69eb1f28688820c02c601f93ccb28717da6b6e5ac20fbaf7fb283784370fd30fed3aa8e0b485027dda030449a6abeb922c705c903a2f349dfb075b9ce0c18e90df690fad3177e02ee6ef19ce602f6cf463ca06a38203017ebfd02519b5b607a11718243b01084656792f3bec57956232f1c5f6ea03fe34bed97e55a8ab67741617263ab232293b19fac40daa9688655da4d37882b0b21980dd5201b4fcef42e0c038e8033a024c787ec218988b08396e9a621ac4374b10bd13d521b52f0afccb3efa4681e8f6ca1fd2152142c89c09aa954cf4c5e4073fdc99cb6cd151458b59552f0ac5f61888679ffc3711d4b806e756a77f31c993ec9239927414ec4fe996e7fc498cecacc56b30440add6f71b02bc34f3705681e7e19cd3722febf38b6ecc25398bb9b527c77fce532371b2463d4fd5a8d0f1dbf97b95eb59acf0281d7805f99e519aa4efb65699a2b2ed89cc8af53bc305bc1a4f750a953086fab18a36eace7e0311de9a6d400042c17846ede3f280a7ab4dda32bbf364fad1722b5bbdc0bab21aba5e4f43b243b2165258d04633957684ae38ab2b101914a21dc1bdc31423f7748d0e36ba5d3201552a2aa76507dc1d4b4d92c4f16329c00c167765ee4f340a281f1f3d73478bd1a0d31ad5bc40969f7ae3cfed770c1b9eea1d75b8b655bfb6932610eec0d5ab113b12dd78802355c2cc8e71427ddbed5ce2cf37d454fe788c09772ce1668b9d120d1cf5f9b0503b193b2378df3b292666df3df011ec6b94271a61fae493f6f92a7308f733d9a12fd7b5596db6a6285d44ea2a0ad64d329ceeff2296a403a730c2a18881d32ebfd93d502d54021471ab8f9473af265b6e42c1fb98c1767a92d5613e29d270a27af9fa8a71f666fe1766d071813b2156e912182a7aa914439c96ab469a576c17510f1617b4536f69c2ded22c1d50d7482cb7fbcde67af59ea734f3742a0e375c7e0210ae4ecff0f818f71b270d49137e46a6ab38afffc1e24cbbd1719870d3e86dc6ff5d1bd5411bb64dd569d593e4c248415f7d59339ff83a749b6a05dd86280bab71b975247de7eb838de56281ca26849ecb8e86cf7bf9a0cae3d93acb75b4af9a46f93c830ccb8c922facef21700878b23cd313fedda6ab91908b77f5142bd60e02deb87c4a2e80b25fc7c51982d1a700fc827a45cf4114305bbb485f8a04e9a4c576365222319432630051ceea8dbcbd0513366fe622b7c15b9c5b9c7697fa7ee201eae4aad0423bb61b96652b3f1e19a5670bad143d6d8b90a9472a2f0177fae07a68dce0172384663be8e4099ec3c154e81a0a2a42363569f8f4030ab4bba6ecede9447835cd97adce8f030e3abf7fe531c9b63a81a5285bf7b45c1f3599a59c5a6ecb70cd6a747b61245e673243b55bf0bf824bc01b754810a19812c082b2252e891d98896999590ce20c9cf78be0e86967f099849b7613ac45084d0c4b7490389500f296efcc38e69fccacd8a9cb3df706bc09c399886164afd22de21676d0fdb93fee1efaf2d363e2ee83295c2bfcdfd4bcce1f0197c9052a92b3ad4032d871562d7c46a0d7deb229244414be672c0dd9a0de1cdd818b8b498ecbf1c786d53e82bb1dfa187d22b4bae3179d56ca4fdd6f8f2d4c81df80726dfcf243829c33d23b77b8d039b0d169c5613ecde639a30eec12dbd364bdca747e8bbf610033c8a02b1f2763aa9a63806d07364d24228d7ba621133ec01c79059f65c54748703fc60eecc810382fbd160a8df4dcd47aa57f640f5ffd74a1f94f9a56156f7c0c6e34fdd6e43a5a0ac46b71474140fb8f16c10aab75678875f19fa82dad79a6cd284c78488aee66c5279d16acb21b8db2df30327783b64335934d7db219dc6846d9199329fa8f8e8a949863b39c03bbf8d83850920f4e87f41bc8f14c5fe3541444af632f5df9866dcae93493fae87809f16ee551bac8c4ddd0bce15ff7be0e573cd46fbac5fc7f4b764f46fd3bb09ab24bbbd9c38ee0f648386d892a90165e2acc2e5057c7aef96648ae013178932d6eab4b60d94555a7f380201c9cd432edea87319b8bdf5b400d17cb0d4743f2174c15037c7fd9e5cdce945860300000000000000af3ce8279bc3e39954527b6314ce47076c97b16c3577c2e7ef014a9f62bb1e248ebb21fb1ca0aea57f0a3df15877c9de9751b1767d705d511fb67eec61dfd42f00" ].map(|hex| >::from_hex(hex).expect("Block bytes are in valid hex representation")); } From d102b13c384c7bf68c2f203260976a78405384ae Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 14:27:36 +0100 Subject: [PATCH 137/157] Revert "Minor fix to align with orchard changes" This reverts commit 225dac1a303adc30ddd43446cd3d96767d6aa2ca. --- zebra-chain/src/orchard/orchard_flavor_ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index 7721d303b3b..0ade1c75d39 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -7,7 +7,7 @@ use serde::{de::DeserializeOwned, Serialize}; #[cfg(any(test, feature = "proptest-impl"))] use proptest_derive::Arbitrary; -use orchard::{domain::OrchardDomainCommon, orchard_flavor}; +use orchard::{note_encryption::OrchardDomainCommon, orchard_flavor}; use crate::{ orchard::ValueCommitment, From 0b24a2b4d901977dc2b93ae99cc3ebc310c19eb1 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 14 Feb 2025 14:46:29 +0100 Subject: [PATCH 138/157] Revert "Minor fix to align with orchard changes" This reverts commit 225dac1a303adc30ddd43446cd3d96767d6aa2ca. --- zebra-chain/src/orchard/orchard_flavor_ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index ea8931130a1..f8ce25d0ed5 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -7,7 +7,7 @@ use serde::{de::DeserializeOwned, Serialize}; #[cfg(any(test, feature = "proptest-impl"))] use proptest_derive::Arbitrary; -use orchard::{domain::OrchardDomainCommon, orchard_flavor}; +use orchard::{note_encryption::OrchardDomainCommon, orchard_flavor}; use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}; From 7691e795df61bdbb8f4fc79bceb400e01f285304 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 17 Feb 2025 09:39:33 +0100 Subject: [PATCH 139/157] Remove RUSTFLAGS and RUSTDOCFLAGS from CI config as they override .cargo/config.toml settings --- .github/workflows/ci-basic.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index ed66ba1e586..d8ca56bd4cc 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -16,9 +16,6 @@ jobs: ROCKSDB_LIB_DIR: /usr/lib # Use system-installed Snappy library for compression in RocksDB SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu - # Enable the `nu6` feature in `zcash_protocol` - RUSTFLAGS: '--cfg zcash_unstable="nu6"' - RUSTDOCFLAGS: '--cfg zcash_unstable="nu6"' steps: - uses: actions/checkout@v4 From 7d8956dbf23ed73b4d6c85dba842448a261fad20 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 17 Feb 2025 12:35:16 +0100 Subject: [PATCH 140/157] Secure .cargo config in ci-basic.yml CI to apply custom rustflags --- .github/workflows/ci-basic.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index d8ca56bd4cc..a5e339f176b 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -22,6 +22,9 @@ jobs: - name: Install dependencies on Ubuntu #run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev run: sudo apt-get update && sudo apt-get install -y protobuf-compiler librocksdb-dev + # Remove group/world write permissions so Cargo loads the config (insecure files are ignored) + - name: Secure .cargo config + run: chmod -R go-w .cargo - name: Run tests run: cargo test --verbose - name: Verify working directory is clean From 7dfd07ed8e494d0d82a50b93aeef922f71041b15 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 17 Feb 2025 13:16:56 +0100 Subject: [PATCH 141/157] Revert "Secure .cargo config in ci-basic.yml CI to apply custom rustflags" This reverts commit 7d8956dbf23ed73b4d6c85dba842448a261fad20. --- .github/workflows/ci-basic.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index a5e339f176b..d8ca56bd4cc 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -22,9 +22,6 @@ jobs: - name: Install dependencies on Ubuntu #run: sudo apt-get update && sudo apt-get install -y protobuf-compiler build-essential librocksdb-dev run: sudo apt-get update && sudo apt-get install -y protobuf-compiler librocksdb-dev - # Remove group/world write permissions so Cargo loads the config (insecure files are ignored) - - name: Secure .cargo config - run: chmod -R go-w .cargo - name: Run tests run: cargo test --verbose - name: Verify working directory is clean From 72092f5560fe9c3b1ac8a0444e8167f62a6c64d8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 17 Feb 2025 13:20:58 +0100 Subject: [PATCH 142/157] Add --cfg zcash_unstable flag to rustdocflags of .cargo/config.toml --- .cargo/config.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index ab7095e21bd..c2a4131abc9 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -85,6 +85,9 @@ rustflags = [ [build] rustdocflags = [ + # FIXME: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) + "--cfg", "zcash_unstable=\"nu6\"", + # The -A and -W settings must be the same as the `RUSTDOCFLAGS` in: # https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/docs-deploy-firebase.yml#L68 From de8dab52033f0585b09b6a02bc17955f86871467 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 17 Feb 2025 13:20:58 +0100 Subject: [PATCH 143/157] Add --cfg zcash_unstable flag to rustdocflags of .cargo/config.toml --- .cargo/config.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index ab7095e21bd..c2a4131abc9 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -85,6 +85,9 @@ rustflags = [ [build] rustdocflags = [ + # FIXME: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) + "--cfg", "zcash_unstable=\"nu6\"", + # The -A and -W settings must be the same as the `RUSTDOCFLAGS` in: # https://github.com/ZcashFoundation/zebra/blob/main/.github/workflows/docs-deploy-firebase.yml#L68 From 944df50c5d4ddd1c7116cbc348dcef3ca62e2bdd Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 17 Feb 2025 09:39:33 +0100 Subject: [PATCH 144/157] Remove RUSTFLAGS and RUSTDOCFLAGS from CI config as they override .cargo/config.toml settings --- .github/workflows/ci-basic.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci-basic.yml b/.github/workflows/ci-basic.yml index c2cde8686bf..1759ff184c6 100644 --- a/.github/workflows/ci-basic.yml +++ b/.github/workflows/ci-basic.yml @@ -16,9 +16,6 @@ jobs: ROCKSDB_LIB_DIR: /usr/lib # Use system-installed Snappy library for compression in RocksDB SNAPPY_LIB_DIR: /usr/lib/x86_64-linux-gnu - # Enable the `nu6` feature in `zcash_protocol` - RUSTFLAGS: '--cfg zcash_unstable="nu6"' - RUSTDOCFLAGS: '--cfg zcash_unstable="nu6"' steps: - uses: actions/checkout@v4 From ddadae90e2a54107cd9eac165acc63d4f3bdc7a1 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 18 Feb 2025 13:13:50 +0100 Subject: [PATCH 145/157] Change unfixed FIXMEs to TODOs --- .cargo/config.toml | 4 ++-- rust-toolchain.toml | 2 +- zebra-chain/src/parameters/network_upgrade.rs | 2 +- zebra-consensus/src/primitives/halo2/tests.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index c2a4131abc9..83f31157547 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -3,7 +3,7 @@ # Flags that apply to all Zebra crates and configurations [target.'cfg(all())'] rustflags = [ - # FIXME: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) + # TODO: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) "--cfg", "zcash_unstable=\"nu6\"", # Zebra standard lints for Rust 1.65+ @@ -85,7 +85,7 @@ rustflags = [ [build] rustdocflags = [ - # FIXME: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) + # TODO: Consider removing this line later (it's needed for the ZSA version of librustzcash crates) "--cfg", "zcash_unstable=\"nu6\"", # The -A and -W settings must be the same as the `RUSTDOCFLAGS` in: diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8b6ca9a2b78..f4478060854 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ -# FIXME: This file does not exist in the original Zebra repo - consider removing it before the final merge. +# TODO: This file does not exist in the original Zebra repo - consider removing it before the final merge. [toolchain] channel = "1.82.0" components = [ "clippy", "rustfmt" ] diff --git a/zebra-chain/src/parameters/network_upgrade.rs b/zebra-chain/src/parameters/network_upgrade.rs index 49a76d0a449..dea69eb3773 100644 --- a/zebra-chain/src/parameters/network_upgrade.rs +++ b/zebra-chain/src/parameters/network_upgrade.rs @@ -531,7 +531,7 @@ impl From for NetworkUpgrade { zcash_protocol::consensus::NetworkUpgrade::Canopy => Self::Canopy, zcash_protocol::consensus::NetworkUpgrade::Nu5 => Self::Nu5, zcash_protocol::consensus::NetworkUpgrade::Nu6 => Self::Nu6, - // FIXME: TODO: Use a proper value below. + // TODO: Use a proper value below. #[cfg(zcash_unstable = "nu6" /* TODO nu7 */ )] zcash_protocol::consensus::NetworkUpgrade::Nu7 => Self::Nu6, } diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index d5768709681..e5afdacfc58 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -25,7 +25,7 @@ use zebra_chain::{ use crate::primitives::halo2::*; -// FIXME: add support for OrchardZSA (see OrchardVanilla and AssetBase::native() usage below) +// TODO: Add support for OrchardZSA (see OrchardVanilla and AssetBase::native() usage below) #[allow(dead_code, clippy::print_stdout)] fn generate_test_vectors() { let proving_key = ProvingKey::build::(); From 47ac4e00aab859713ddcd07ca0880def4e2fe4e7 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 24 Feb 2025 08:50:47 +0100 Subject: [PATCH 146/157] Fix typos in comments --- zebra-chain/src/transaction.rs | 8 ++++---- zebra-state/src/service/check/utxo.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index ada329140f1..0e73f51467e 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -142,8 +142,8 @@ pub enum Transaction { /// The orchard data for this transaction, if any. orchard_shielded_data: Option, }, - // FIXME: implement V6 properly (now it's just a coipy of V5) - /// A `version = 6` transaction , which supports Orchard ZSA, Orchard Vanille, Sapling and + // FIXME: implement V6 properly (now it's just a copy of V5) + /// A `version = 6` transaction , which supports Orchard ZSA, Orchard Vanilla, Sapling and /// transparent, but not Sprout. V6 { /// The Network Upgrade for this transaction. @@ -1027,7 +1027,7 @@ impl Transaction { .. } => orchard_shielded_data.as_ref(), - // FIXME: Support V6/OrchardZSA propetly. + // FIXME: Support V6/OrchardZSA properly. Transaction::V6 { orchard_shielded_data, .. @@ -1051,7 +1051,7 @@ impl Transaction { .. } => Some(orchard_shielded_data), - // FIXME: Support V6/OrchardZSA propetly. + // FIXME: Support V6/OrchardZSA properly. Transaction::V6 { orchard_shielded_data: Some(orchard_shielded_data), .. diff --git a/zebra-state/src/service/check/utxo.rs b/zebra-state/src/service/check/utxo.rs index b856a616dd5..c6327787d32 100644 --- a/zebra-state/src/service/check/utxo.rs +++ b/zebra-state/src/service/check/utxo.rs @@ -63,7 +63,7 @@ pub fn transparent_spend( finalized_state, )?; - // FIXME: what about v6? + // FIXME: what about V6? // The state service returns UTXOs from pending blocks, // which can be rejected by later contextual checks. // This is a particular issue for v5 transactions, From 708844ce704ddb36c749213d0abf5ee034ac1948 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 24 Feb 2025 09:10:59 +0100 Subject: [PATCH 147/157] Rename txid_v5_v6 to txid_v5_to_v6, minor fixes in comments --- zebra-chain/src/transaction.rs | 3 +-- zebra-chain/src/transaction/txid.rs | 9 +++------ zebra-state/src/service/check/utxo.rs | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index 0e73f51467e..a960947ad40 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -143,8 +143,7 @@ pub enum Transaction { orchard_shielded_data: Option, }, // FIXME: implement V6 properly (now it's just a copy of V5) - /// A `version = 6` transaction , which supports Orchard ZSA, Orchard Vanilla, Sapling and - /// transparent, but not Sprout. + /// A `version = 6` transaction , OrchardZSA, Orchard, Sapling and transparent, but not Sprout. V6 { /// The Network Upgrade for this transaction. /// diff --git a/zebra-chain/src/transaction/txid.rs b/zebra-chain/src/transaction/txid.rs index eb05fd6edb3..e32912162bd 100644 --- a/zebra-chain/src/transaction/txid.rs +++ b/zebra-chain/src/transaction/txid.rs @@ -28,7 +28,7 @@ impl<'a> TxIdBuilder<'a> { | Transaction::V2 { .. } | Transaction::V3 { .. } | Transaction::V4 { .. } => self.txid_v1_to_v4(), - Transaction::V5 { .. } | Transaction::V6 { .. } => self.txid_v5_v6(), + Transaction::V5 { .. } | Transaction::V6 { .. } => self.txid_v5_to_v6(), } } @@ -43,14 +43,11 @@ impl<'a> TxIdBuilder<'a> { Ok(Hash(hash_writer.finish())) } - // FIXME: it looks like the updated zcash_primitives in librustzcash - // auto-detects the transaction version by the first byte, so the same function - // can be used here for both V5 and V6. // FIXME: fix spec refs below for V6 - /// Compute the Transaction ID for a V5/V6 transaction in the given network upgrade. + /// Compute the Transaction ID for transactions V5 to V6. /// In this case it's the hash of a tree of hashes of specific parts of the /// transaction, as specified in ZIP-244 and ZIP-225. - fn txid_v5_v6(self) -> Result { + fn txid_v5_to_v6(self) -> Result { // The v5 txid (from ZIP-244) is computed using librustzcash. Convert the zebra // transaction to a librustzcash transaction. let alt_tx: zcash_primitives::transaction::Transaction = self.trans.try_into()?; diff --git a/zebra-state/src/service/check/utxo.rs b/zebra-state/src/service/check/utxo.rs index c6327787d32..9e2c0618ac0 100644 --- a/zebra-state/src/service/check/utxo.rs +++ b/zebra-state/src/service/check/utxo.rs @@ -63,10 +63,9 @@ pub fn transparent_spend( finalized_state, )?; - // FIXME: what about V6? // The state service returns UTXOs from pending blocks, // which can be rejected by later contextual checks. - // This is a particular issue for v5 transactions, + // This is a particular issue for v5 and v6 transactions, // because their authorizing data is only bound to the block data // during contextual validation (#2336). // From 4fd7f88a9b8162e3135e51b0bf70597d9ee71684 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 24 Feb 2025 09:24:43 +0100 Subject: [PATCH 148/157] Rename transaction_to_fake_v5 function to transaction_to_fake_min_v5 and panic if V6 passed into it --- zebra-chain/src/transaction/arbitrary.rs | 22 ++++---------------- zebra-chain/src/transaction/tests/vectors.rs | 4 ++-- zebra-consensus/src/block/tests.rs | 4 ++-- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 73aac10a23d..8712b5b2f65 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -849,7 +849,7 @@ impl Arbitrary for VerifiedUnminedTx { /// Convert `trans` into a fake v5 transaction, /// converting sapling shielded data from v4 to v5 if possible. -pub fn transaction_to_fake_v5( +pub fn transaction_to_fake_min_v5( trans: &Transaction, network: &Network, height: block::Height, @@ -918,22 +918,8 @@ pub fn transaction_to_fake_v5( orchard_shielded_data: None, }, v5 @ V5 { .. } => v5.clone(), - V6 { - inputs, - outputs, - lock_time, - sapling_shielded_data, - orchard_shielded_data, - .. - } => V5 { - network_upgrade: block_nu, - inputs: inputs.clone(), - outputs: outputs.clone(), - lock_time: *lock_time, - expiry_height: height, - sapling_shielded_data: sapling_shielded_data.clone(), - orchard_shielded_data: orchard_shielded_data.clone(), - }, + #[cfg(feature = "tx-v6")] + V6 => panic!("V6 transactions are not supported in this test!"), } } @@ -1017,7 +1003,7 @@ pub fn fake_v5_transactions_for_network<'b>( blocks: impl DoubleEndedIterator + 'b, ) -> impl DoubleEndedIterator + 'b { transactions_from_blocks(blocks) - .map(move |(height, transaction)| transaction_to_fake_v5(&transaction, network, height)) + .map(move |(height, transaction)| transaction_to_fake_min_v5(&transaction, network, height)) } /// Generate an iterator over ([`block::Height`], [`Arc`]). diff --git a/zebra-chain/src/transaction/tests/vectors.rs b/zebra-chain/src/transaction/tests/vectors.rs index f20bfaef455..ca3e9a6493c 100644 --- a/zebra-chain/src/transaction/tests/vectors.rs +++ b/zebra-chain/src/transaction/tests/vectors.rs @@ -371,7 +371,7 @@ fn fake_v5_round_trip_for_network(network: Network) { .transactions .iter() .map(AsRef::as_ref) - .map(|t| arbitrary::transaction_to_fake_v5(t, &network, Height(*height))) + .map(|t| arbitrary::transaction_to_fake_min_v5(t, &network, Height(*height))) .map(Into::into) .collect(); @@ -516,7 +516,7 @@ fn fake_v5_librustzcash_round_trip_for_network(network: Network) { .transactions .iter() .map(AsRef::as_ref) - .map(|t| arbitrary::transaction_to_fake_v5(t, &network, Height(*height))) + .map(|t| arbitrary::transaction_to_fake_min_v5(t, &network, Height(*height))) .map(Into::into) .collect(); diff --git a/zebra-consensus/src/block/tests.rs b/zebra-consensus/src/block/tests.rs index e6eb6f2c4b9..7f42801a4ff 100644 --- a/zebra-consensus/src/block/tests.rs +++ b/zebra-consensus/src/block/tests.rs @@ -14,7 +14,7 @@ use zebra_chain::{ }, parameters::NetworkUpgrade, serialization::{ZcashDeserialize, ZcashDeserializeInto}, - transaction::{arbitrary::transaction_to_fake_v5, LockTime, Transaction}, + transaction::{arbitrary::transaction_to_fake_min_v5, LockTime, Transaction}, work::difficulty::{ParameterDifficulty as _, INVALID_COMPACT_DIFFICULTY}, }; use zebra_script::CachedFfiTransaction; @@ -664,7 +664,7 @@ fn merkle_root_fake_v5_for_network(network: Network) -> Result<(), Report> { .transactions .iter() .map(AsRef::as_ref) - .map(|t| transaction_to_fake_v5(t, &network, Height(*height))) + .map(|t| transaction_to_fake_min_v5(t, &network, Height(*height))) .map(Into::into) .collect(); From a597c4e780b1d87b52d643f4fd5bedd20f6579da Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 24 Feb 2025 09:19:45 +0100 Subject: [PATCH 149/157] Minor fix in comments --- zebra-chain/src/parameters/transaction.rs | 2 +- zebrad/src/components/mempool/storage/tests/prop.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/parameters/transaction.rs b/zebra-chain/src/parameters/transaction.rs index f775f2c4bb2..729cb82cf11 100644 --- a/zebra-chain/src/parameters/transaction.rs +++ b/zebra-chain/src/parameters/transaction.rs @@ -14,7 +14,7 @@ pub const TX_V5_VERSION_GROUP_ID: u32 = 0x26A7_270A; /// The version group ID for version 6 transactions. /// -/// Orchard transactions must use transaction version 5 and this version +/// Orchard ZSA transactions must use transaction version 6 and this version /// group ID. // FIXME: use a proper value! pub const TX_V6_VERSION_GROUP_ID: u32 = 0x124A_69F8; diff --git a/zebrad/src/components/mempool/storage/tests/prop.rs b/zebrad/src/components/mempool/storage/tests/prop.rs index 98abdb2b8e8..ed67312bf2c 100644 --- a/zebrad/src/components/mempool/storage/tests/prop.rs +++ b/zebrad/src/components/mempool/storage/tests/prop.rs @@ -446,7 +446,7 @@ enum SpendConflictTestInput { conflict: SpendConflictForTransactionV5, }, - // FIXME: add and use V6? + // FIXME: add V6 test } impl SpendConflictTestInput { From 0498e067cc924be48228a6a175b1cbf6cfdcb0d4 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 24 Feb 2025 10:23:01 +0100 Subject: [PATCH 150/157] Temporary comment of #[cfg(feature = tx-v6)] in zebra-chain/src/transaction/arbitrary.rs --- zebra-chain/src/transaction/arbitrary.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 8712b5b2f65..de5763844a1 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -918,7 +918,7 @@ pub fn transaction_to_fake_min_v5( orchard_shielded_data: None, }, v5 @ V5 { .. } => v5.clone(), - #[cfg(feature = "tx-v6")] + // FIXME: add #[cfg(feature = "tx-v6")] V6 => panic!("V6 transactions are not supported in this test!"), } } From 77350506be10f3ebbb6f0fb0134207071a68fe1c Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 25 Feb 2025 14:41:03 +0100 Subject: [PATCH 151/157] Make changes according to #17 PR review (partially) --- zebra-chain/src/orchard/action.rs | 1 - zebra-chain/src/orchard/orchard_flavor_ext.rs | 9 ++-- zebra-chain/src/orchard/shielded_data.rs | 46 ++++--------------- zebra-chain/src/orchard_zsa.rs | 2 +- zebra-chain/src/orchard_zsa/burn.rs | 13 ++---- zebra-chain/src/orchard_zsa/issuance.rs | 8 +--- zebra-chain/src/transaction.rs | 8 ++-- zebra-consensus/src/primitives/halo2/tests.rs | 18 ++++---- 8 files changed, 32 insertions(+), 73 deletions(-) diff --git a/zebra-chain/src/orchard/action.rs b/zebra-chain/src/orchard/action.rs index 4f256408f11..c8161246efb 100644 --- a/zebra-chain/src/orchard/action.rs +++ b/zebra-chain/src/orchard/action.rs @@ -94,7 +94,6 @@ impl ZcashDeserialize for Action { // https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to // 580 bytes in https://zips.z.cash/protocol/protocol.pdf#outputencodingandconsensus // See [`note::EncryptedNote::zcash_deserialize`]. - // FIXME: don't mention about 580 here as this should work for OrchardZSA too? enc_ciphertext: V::EncryptedNote::zcash_deserialize(&mut reader)?, // Type is `Sym.C`, i.e. `𝔹^Y^{\[N\]}`, i.e. arbitrary-sized byte arrays // https://zips.z.cash/protocol/protocol.pdf#concretesym but fixed to diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index f8ce25d0ed5..a9255d33ef8 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -19,7 +19,6 @@ use crate::orchard_zsa::burn::BurnItem; /// A trait representing compile-time settings of Orchard Shielded Protocol used in /// the transactions `V5` and `V6`. pub trait OrchardFlavorExt: Clone + Debug { - /// A type representing an encrypted note for this protocol version. /// A type representing an encrypted note for this protocol version. type EncryptedNote: Clone + Debug @@ -59,26 +58,26 @@ pub struct OrchardZSA; pub struct NoBurn; impl ZcashSerialize for NoBurn { - fn zcash_serialize(&self, mut _writer: W) -> Result<(), io::Error> { + fn zcash_serialize(&self, _writer: W) -> Result<(), io::Error> { Ok(()) } } impl ZcashDeserialize for NoBurn { - fn zcash_deserialize(mut _reader: R) -> Result { + fn zcash_deserialize(_reader: R) -> Result { Ok(Self) } } impl OrchardFlavorExt for OrchardVanilla { - type Flavor = orchard_flavor::OrchardVanilla; type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; + type Flavor = orchard_flavor::OrchardVanilla; type BurnType = NoBurn; } #[cfg(feature = "tx-v6")] impl OrchardFlavorExt for OrchardZSA { - type Flavor = orchard_flavor::OrchardZSA; type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; + type Flavor = orchard_flavor::OrchardZSA; type BurnType = Vec; } diff --git a/zebra-chain/src/orchard/shielded_data.rs b/zebra-chain/src/orchard/shielded_data.rs index b766f86acab..82124b4a143 100644 --- a/zebra-chain/src/orchard/shielded_data.rs +++ b/zebra-chain/src/orchard/shielded_data.rs @@ -20,13 +20,7 @@ use crate::{ }, }; -use super::OrchardFlavorExt; - -#[cfg(not(feature = "tx-v6"))] -use super::OrchardVanilla; - -#[cfg(feature = "tx-v6")] -use super::OrchardZSA; +use super::{OrchardFlavorExt, OrchardVanilla}; /// A bundle of [`Action`] descriptions and signature data. #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] @@ -79,7 +73,8 @@ impl ShieldedData { self.actions.actions() } - /// FIXME: add a doc comment + /// Return an iterator for the [`ActionCommon`] copy of the Actions in this + /// transaction, in the order they appear in it. pub fn action_commons(&self) -> impl Iterator + '_ { self.actions.actions().map(|action| action.into()) } @@ -214,19 +209,15 @@ impl AuthorizedAction { } } -// TODO: FIXME: Consider moving it to transaction.rs as it's not used here. Or move its usage here from transaction.rs. -/// A struct that contains values of several fields of an `Action` struct. -/// Those fields are used in other parts of the code that call the `orchard_actions()` method of the `Transaction`. -/// The goal of using `ActionCommon` is that it's not a generic, unlike `Action`, so it can be returned from Transaction methods -/// (the fields of `ActionCommon` do not depend on the generic parameter `Version` of `Action`). +/// Non-generic fields of an `Action` used in `Transaction` methods. pub struct ActionCommon { - /// A reference to the value commitment to the net value of the input note minus the output note. - pub cv: super::commitment::ValueCommitment, - /// A reference to the nullifier of the input note being spent. + /// A value commitment to net value of the input note minus the output note + pub cv: ValueCommitment, + /// The nullifier of the input note being spent. pub nullifier: super::note::Nullifier, - /// A reference to the randomized validating key for `spendAuthSig`. + /// The randomized validating key for spendAuthSig, pub rk: reddsa::VerificationKeyBytes, - /// A reference to the x-coordinate of the note commitment for the output note. + /// The x-coordinate of the note commitment for the output note. pub cm_x: pallas::Base, } @@ -241,14 +232,6 @@ impl From<&Action> for ActionCommon { } } -/* -struct AssertBlockSizeLimit; - -impl AssertBlockSizeLimit { - const OK: () = assert!(N < (1 << 16), "must be less than 2^16"); -} -*/ - /// The maximum number of orchard actions in a valid Zcash on-chain transaction V5. /// /// If a transaction contains more actions than can fit in maximally large block, it might be @@ -277,16 +260,7 @@ impl TrustedPreallocate for Action { impl TrustedPreallocate for Signature { fn max_allocation() -> u64 { - // Each signature must have a corresponding action. - #[cfg(not(feature = "tx-v6"))] - let result = Action::::max_allocation(); - - // TODO: FIXME: Check this: V6 is used as it provides the max size of the action. - // So it's used even for V5 - is this correct? - #[cfg(feature = "tx-v6")] - let result = Action::::max_allocation(); - - result + Action::::max_allocation() } } diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index 9806850daf9..1921629541f 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -1,4 +1,4 @@ -//! Orchard ZSA related functionality. +//! OrchardZSA related functionality. pub mod burn; pub mod issuance; diff --git a/zebra-chain/src/orchard_zsa/burn.rs b/zebra-chain/src/orchard_zsa/burn.rs index 04c878feb49..03f75f5dba7 100644 --- a/zebra-chain/src/orchard_zsa/burn.rs +++ b/zebra-chain/src/orchard_zsa/burn.rs @@ -12,12 +12,12 @@ use orchard::note::AssetBase; use super::serialize::ASSET_BASE_SIZE; -// Sizes of the serialized values for types in bytes (used for TrustedPreallocate impls) +// The size of the Amount type, in bytes const AMOUNT_SIZE: u64 = 8; -// FIXME: is this a correct way to calculate (simple sum of sizes of components)? + const BURN_ITEM_SIZE: u64 = ASSET_BASE_SIZE + AMOUNT_SIZE; -/// Represents an Orchard ZSA burn item. +/// Represents an OrchardZSA burn item. #[derive(Clone, Debug, PartialEq, Eq)] pub struct BurnItem(AssetBase, Amount); @@ -43,9 +43,6 @@ impl ZcashDeserialize for BurnItem { impl TrustedPreallocate for BurnItem { fn max_allocation() -> u64 { - // FIXME: is this a correct calculation way? - // The longest Vec we receive from an honest peer must fit inside a valid block. - // Since encoding the length of the vec takes at least one byte, we use MAX_BLOCK_BYTES - 1 (MAX_BLOCK_BYTES - 1) / BURN_ITEM_SIZE } } @@ -56,7 +53,6 @@ impl serde::Serialize for BurnItem { where S: serde::Serializer, { - // FIXME: return custom error with a meaningful description? (self.0.to_bytes(), &self.1).serialize(serializer) } } @@ -67,11 +63,8 @@ impl<'de> serde::Deserialize<'de> for BurnItem { where D: serde::Deserializer<'de>, { - // FIXME: consider another implementation (explicit specifying of [u8; 32] may not look perfect) let (asset_base_bytes, amount) = <([u8; 32], Amount)>::deserialize(deserializer)?; - // FIXME: return custom error with a meaningful description? Ok(BurnItem( - // FIXME: duplicates the body of AssetBase::zcash_deserialize? Option::from(AssetBase::from_bytes(&asset_base_bytes)) .ok_or_else(|| serde::de::Error::custom("Invalid orchard_zsa AssetBase"))?, amount, diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index 9d31276072c..a761342955b 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -1,4 +1,4 @@ -//! Orchard ZSA issuance related functionality. +//! OrchardZSA issuance related functionality. use std::{fmt::Debug, io}; @@ -33,9 +33,8 @@ use super::serialize::ASSET_BASE_SIZE; #[derive(Clone, Debug, PartialEq, Eq)] pub struct IssueData(IssueBundle); -// Sizes of the serialized values for types in bytes (used for TrustedPreallocate impls) +// Sizes of the types, in bytes // FIXME: are those values correct (43, 32 etc.)? -//const ISSUANCE_VALIDATING_KEY_SIZE: u64 = 32; const ADDRESS_SIZE: u64 = 43; const NULLIFIER_SIZE: u64 = 32; const NOTE_VALUE_SIZE: u64 = 4; @@ -166,9 +165,6 @@ impl ZcashDeserialize for Note { impl TrustedPreallocate for Note { fn max_allocation() -> u64 { - // FIXME: is this a correct calculation way? - // The longest Vec we receive from an honest peer must fit inside a valid block. - // Since encoding the length of the vec takes at least one byte, we use MAX_BLOCK_BYTES - 1 (MAX_BLOCK_BYTES - 1) / NOTE_SIZE } } diff --git a/zebra-chain/src/transaction.rs b/zebra-chain/src/transaction.rs index f42d8876a91..c9741e62dd6 100644 --- a/zebra-chain/src/transaction.rs +++ b/zebra-chain/src/transaction.rs @@ -229,9 +229,9 @@ pub enum Transaction { outputs: Vec, /// The sapling shielded data for this transaction, if any. sapling_shielded_data: Option>, - /// The ZSA orchard shielded data for this transaction, if any. + /// The OrchardZSA shielded data for this transaction, if any. orchard_shielded_data: Option>, - /// The ZSA issuance data for this transaction, if any. + /// The OrchardZSA issuance data for this transaction, if any. orchard_zsa_issue_data: Option, }, } @@ -1040,11 +1040,11 @@ impl Transaction { /// Access the [`orchard::Flags`] in this transaction, if there is any, /// regardless of version. pub fn orchard_flags(&self) -> Option { - // FIXME: remove this line with_shielded_data!(self, |data: impl orchard::ShieldedDataCommon| data.flags) orchard_shielded_data_field!(self, flags) } - /// FIXME: add doc + /// Access the [`orchard::tree::Root`] in this transaction, if there is any, + /// regardless of version. pub fn orchard_shared_anchor(&self) -> Option { orchard_shielded_data_field!(self, shared_anchor) } diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs index 4c0e6b8afa8..284b157ca7a 100644 --- a/zebra-consensus/src/primitives/halo2/tests.rs +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -40,7 +40,7 @@ fn generate_test_vectors() { let anchor_bytes = [0; 32]; let note_value = 10; - let shielded_data: Vec> = (1..=4) + let shielded_data: Vec> = (1..=4) .map(|num_recipients| { let mut builder = Builder::new( BundleType::Transactional { @@ -71,7 +71,7 @@ fn generate_test_vectors() { .apply_signatures(rng, [0; 32], &[]) .unwrap(); - zebra_chain::orchard::ShieldedData:: { + ShieldedData:: { flags, value_balance: note_value.try_into().unwrap(), shared_anchor: anchor_bytes.try_into().unwrap(), @@ -150,10 +150,9 @@ async fn verify_generated_halo2_proofs() { .clone() .iter() .map(|bytes| { - let maybe_shielded_data: Option> = - bytes - .zcash_deserialize_into() - .expect("a valid orchard::ShieldedData instance"); + let maybe_shielded_data: Option> = bytes + .zcash_deserialize_into() + .expect("a valid orchard::ShieldedData instance"); maybe_shielded_data.unwrap() }) .collect(); @@ -218,10 +217,9 @@ async fn correctly_err_on_invalid_halo2_proofs() { .clone() .iter() .map(|bytes| { - let maybe_shielded_data: Option> = - bytes - .zcash_deserialize_into() - .expect("a valid orchard::ShieldedData instance"); + let maybe_shielded_data: Option> = bytes + .zcash_deserialize_into() + .expect("a valid orchard::ShieldedData instance"); maybe_shielded_data.unwrap() }) .collect(); From 25a44a2fd314fdaa120c3e86a692d158035ed83e Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 25 Feb 2025 15:25:26 +0100 Subject: [PATCH 152/157] Derive Copy, Clone, Debug, Eq, PartialEq for EncryptedNote instead of explicit imlps as const generic are stabilized --- zebra-chain/src/orchard/note/ciphertexts.rs | 29 +-------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index 68f92dc667d..33ab9b4f660 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -9,30 +9,9 @@ use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize} /// A ciphertext component for encrypted output notes. /// /// Corresponds to the Orchard 'encCiphertext's -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, Copy, Clone, Debug, Eq, PartialEq)] pub struct EncryptedNote(#[serde(with = "BigArray")] pub(crate) [u8; N]); -// These impls all only exist because of array length restrictions. -// TODO: use const generics https://github.com/ZcashFoundation/zebra/issues/2042 - -impl Copy for EncryptedNote {} - -impl Clone for EncryptedNote { - fn clone(&self) -> Self { - *self - } -} - -impl fmt::Debug for EncryptedNote { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("EncryptedNote") - .field(&hex::encode(&self.0[..])) - .finish() - } -} - -impl Eq for EncryptedNote {} - impl From<[u8; N]> for EncryptedNote { fn from(bytes: [u8; N]) -> Self { EncryptedNote(bytes) @@ -45,12 +24,6 @@ impl From> for [u8; N] { } } -impl PartialEq for EncryptedNote { - fn eq(&self, other: &Self) -> bool { - self.0[..] == other.0[..] - } -} - impl ZcashSerialize for EncryptedNote { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { writer.write_all(&self.0[..])?; From 600571d841ea20e0129fd8086ea8a9c8f2dcbda9 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 25 Feb 2025 15:47:09 +0100 Subject: [PATCH 153/157] Make changes according to #17 PR review --- zebra-chain/src/orchard/orchard_flavor_ext.rs | 6 +++--- zebra-chain/src/orchard_zsa/issuance.rs | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index a9255d33ef8..c396c10d2f1 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -39,13 +39,13 @@ pub trait OrchardFlavorExt: Clone + Debug { type BurnType: Clone + Debug + Default + ZcashDeserialize + ZcashSerialize; } -/// A structure representing a tag for Orchard protocol variant used for the transaction version `V5`. +/// A structure representing a tag for Orchard protocol variant used for the transaction version 5. #[derive(Clone, Debug, PartialEq, Eq, Serialize)] #[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] pub struct OrchardVanilla; -/// A structure representing a tag for Orchard protocol variant used for the transaction version `V6` -/// (which ZSA features support). +/// A structure representing a tag for Orchard protocol variant used for the transaction version 6 +/// (which support for ZSAs). #[cfg(feature = "tx-v6")] #[derive(Clone, Debug, PartialEq, Eq, Serialize)] #[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index a761342955b..abbdfb5a2e2 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -189,8 +189,7 @@ impl ZcashDeserialize for IssueAction { impl TrustedPreallocate for IssueAction { fn max_allocation() -> u64 { - // FIXME: impl correct calculation - 10 + (MAX_BLOCK_BYTES - 1) / 3 } } From 3ac784a16b41c61addbf15665bd1958ea9e3c6ab Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 26 Feb 2025 15:17:08 +0100 Subject: [PATCH 154/157] Fix wrong resolving of merge conflict in the previous commit --- zebra-chain/src/orchard/orchard_flavor_ext.rs | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/zebra-chain/src/orchard/orchard_flavor_ext.rs b/zebra-chain/src/orchard/orchard_flavor_ext.rs index 8f8e423e9a0..c1422547409 100644 --- a/zebra-chain/src/orchard/orchard_flavor_ext.rs +++ b/zebra-chain/src/orchard/orchard_flavor_ext.rs @@ -65,29 +65,9 @@ pub struct OrchardVanilla; #[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))] pub struct OrchardZSA; -/// A special marker type indicating the absence of a burn field in Orchard ShieldedData for `V5` transactions. -/// Useful for unifying ShieldedData serialization and deserialization implementations across various -/// Orchard protocol variants (i.e. various transaction versions). -#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize)] -pub struct NoBurn; - -impl ZcashSerialize for NoBurn { - fn zcash_serialize(&self, _writer: W) -> Result<(), io::Error> { - Ok(()) - } -} - -impl ZcashDeserialize for NoBurn { - fn zcash_deserialize(_reader: R) -> Result { - Ok(Self) - } -} - impl OrchardFlavorExt for OrchardVanilla { type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; - type Flavor = orchard_flavor::OrchardVanilla; - #[cfg(feature = "tx-v6")] type BurnType = NoBurn; } @@ -95,7 +75,6 @@ impl OrchardFlavorExt for OrchardVanilla { #[cfg(feature = "tx-v6")] impl OrchardFlavorExt for OrchardZSA { type EncryptedNote = note::EncryptedNote<{ Self::ENCRYPTED_NOTE_SIZE }>; - type Flavor = orchard_flavor::OrchardZSA; - type BurnType = Vec; + type BurnType = Burn; } From 757a789a7b407267d14ef766e669776d4768e242 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 26 Feb 2025 15:23:35 +0100 Subject: [PATCH 155/157] Minor fix in FIXME comment --- zebra-chain/src/orchard_zsa/issuance.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/orchard_zsa/issuance.rs b/zebra-chain/src/orchard_zsa/issuance.rs index abbdfb5a2e2..70de9658d8a 100644 --- a/zebra-chain/src/orchard_zsa/issuance.rs +++ b/zebra-chain/src/orchard_zsa/issuance.rs @@ -34,7 +34,7 @@ use super::serialize::ASSET_BASE_SIZE; pub struct IssueData(IssueBundle); // Sizes of the types, in bytes -// FIXME: are those values correct (43, 32 etc.)? +// FIXME: import from orchard const ADDRESS_SIZE: u64 = 43; const NULLIFIER_SIZE: u64 = 32; const NOTE_VALUE_SIZE: u64 = 4; From bfe8f6f56408c0f8d18fadfe842e0a24e1d0263a Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 26 Feb 2025 15:46:37 +0100 Subject: [PATCH 156/157] Minor spelling fixes in comments --- zebra-chain/src/orchard_zsa.rs | 2 +- zebra-chain/src/orchard_zsa/tests.rs | 2 +- zebra-chain/src/orchard_zsa/tests/vectors.rs | 2 +- zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zebra-chain/src/orchard_zsa.rs b/zebra-chain/src/orchard_zsa.rs index dd2d0652732..abfd8952f2a 100644 --- a/zebra-chain/src/orchard_zsa.rs +++ b/zebra-chain/src/orchard_zsa.rs @@ -4,7 +4,7 @@ #[cfg(any(test, feature = "proptest-impl"))] pub(crate) mod arbitrary; -/// FIXME: feature = "proptest-impl" and pub are needed to access test vectors from another crates, +/// FIXME: feature = "proptest-impl" and pub are needed to access test vectors from other crates, /// remove it then #[cfg(any(test, feature = "proptest-impl"))] pub mod tests; diff --git a/zebra-chain/src/orchard_zsa/tests.rs b/zebra-chain/src/orchard_zsa/tests.rs index 2a757269874..6d78193546a 100644 --- a/zebra-chain/src/orchard_zsa/tests.rs +++ b/zebra-chain/src/orchard_zsa/tests.rs @@ -2,5 +2,5 @@ #[cfg(test)] mod blocks; -/// FIXME: pub is needed to access test vectors from another crates, remove it then +/// FIXME: pub is needed to access test vectors from other crates, remove it then pub mod vectors; diff --git a/zebra-chain/src/orchard_zsa/tests/vectors.rs b/zebra-chain/src/orchard_zsa/tests/vectors.rs index 0f7c4eceb48..b893aa78dff 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors.rs @@ -1,4 +1,4 @@ mod blocks; -// FIXME: pub is needed to access test vectors from another crates, change it to pub(crate) then +// FIXME: pub is needed to access test vectors from other crates, change it to pub(crate) then pub use blocks::BLOCKS; diff --git a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs index 324f270c04d..e2c32f1a79e 100644 --- a/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs +++ b/zebra-chain/src/orchard_zsa/tests/vectors/blocks.rs @@ -1,4 +1,4 @@ -/// FIXME: pub is needed to access test vectors from another crates, change it to pub(crate) then +/// FIXME: pub is needed to access test vectors from other crates, change it to pub(crate) then pub const BLOCKS: [&[u8]; 4] = [ // Genesis block &[], From 850ebf2760b48f0ad2b0f054aa0d35763fbbc4cf Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 26 Feb 2025 17:08:06 +0100 Subject: [PATCH 157/157] Fix compilation error in tests --- zebra-chain/src/transaction/arbitrary.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-chain/src/transaction/arbitrary.rs b/zebra-chain/src/transaction/arbitrary.rs index 4c26019f8b4..91d0bd0fd4e 100644 --- a/zebra-chain/src/transaction/arbitrary.rs +++ b/zebra-chain/src/transaction/arbitrary.rs @@ -1023,7 +1023,7 @@ pub fn transaction_to_fake_min_v5( }, v5 @ V5 { .. } => v5.clone(), #[cfg(feature = "tx-v6")] - V6 => panic!("V6 transactions are not supported in this test!"), + _v6 @ V6 { .. } => panic!("V6 transactions are not supported in this test!"), } }