diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 428c38194..0f5d6126d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ # Global rule: * @xmtp/Engineering -*.md @fabriguespe +*.md @xmtp/documentation diff --git a/.github/workflows/lint-ffi-bindings.yaml b/.github/workflows/lint-ffi-bindings.yaml index 38865cdb4..12c45958d 100644 --- a/.github/workflows/lint-ffi-bindings.yaml +++ b/.github/workflows/lint-ffi-bindings.yaml @@ -1,16 +1,15 @@ name: Lint FFI Bindings - on: push: branches: - main - pull_request: paths: - "bindings_ffi/**" - ".github/workflows/lint-ffi-bindings.yaml" - "rustfmt.toml" - +env: + CARGO_TERM_COLOR: always jobs: lint: name: Lint @@ -18,19 +17,15 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Update rust toolchains run: rustup update - - name: Cache uses: Swatinem/rust-cache@v2 with: workspaces: | . bindings_ffi - - name: Run clippy and fail on warnings run: cargo clippy --manifest-path bindings_ffi/Cargo.toml --all-features --all-targets --no-deps -- -Dwarnings - - name: Run format check run: cargo fmt --manifest-path bindings_ffi/Cargo.toml --check diff --git a/.github/workflows/lint-node-bindings.yaml b/.github/workflows/lint-node-bindings.yaml index 547152a01..fb317f1db 100644 --- a/.github/workflows/lint-node-bindings.yaml +++ b/.github/workflows/lint-node-bindings.yaml @@ -6,7 +6,8 @@ on: - "bindings_node/**" - ".github/workflows/lint-node-bindings.yaml" - "rustfmt.toml" - +env: + CARGO_TERM_COLOR: always jobs: lint: name: Lint diff --git a/.github/workflows/lint-workspace.yaml b/.github/workflows/lint-workspace.yaml index de69824e8..cbdaaeaff 100644 --- a/.github/workflows/lint-workspace.yaml +++ b/.github/workflows/lint-workspace.yaml @@ -18,6 +18,8 @@ on: - "Cargo.lock" - "rust-toolchain" - "rustfmt.toml" +env: + CARGO_TERM_COLOR: always jobs: lint: name: Lint diff --git a/.github/workflows/nightly-protos.yml b/.github/workflows/nightly-protos.yml new file mode 100644 index 000000000..58b8de22c --- /dev/null +++ b/.github/workflows/nightly-protos.yml @@ -0,0 +1,35 @@ +name: Nightly Automation +on: + schedule: + - cron: '0 10 * * 1' + workflow_dispatch: +jobs: + nightly-protos: + permissions: + contents: write + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: bufbuild/buf-setup-action@v1.40.1 + - name: Update rust toolchains + run: rustup update + - name: Cache + uses: Swatinem/rust-cache@v2 + with: + workspaces: | + . + - name: Generate Protos + run: dev/gen_protos.sh + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + commit-message: Nightly Protos + title: Update Protos + body: | + - Nightly Proto Update + + Auto-generated by [create-pull-request][1] + + [1]: https://github.com/peter-evans/create-pull-request + branch: nightly-proto \ No newline at end of file diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index b570daeaa..3129591fb 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -5,7 +5,8 @@ on: branches: - main workflow_dispatch: - +env: + CARGO_TERM_COLOR: always jobs: build: strategy: diff --git a/.github/workflows/test-ffi-bindings.yml b/.github/workflows/test-ffi-bindings.yml index e6ebac803..43b4cc61e 100644 --- a/.github/workflows/test-ffi-bindings.yml +++ b/.github/workflows/test-ffi-bindings.yml @@ -1,10 +1,8 @@ name: Test FFI Bindings - on: push: branches: - main - pull_request: # only run tests when related changes are made paths: @@ -21,7 +19,8 @@ on: - "Cargo.toml" - "Cargo.lock" - "rust-toolchain" - +env: + CARGO_TERM_COLOR: always jobs: test: name: Test @@ -29,19 +28,15 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Update rust toolchains run: rustup update - - uses: Swatinem/rust-cache@v2 with: workspaces: | . bindings_ffi - - name: Start Docker containers run: dev/up - - name: Setup Kotlin run: | sudo apt update -q @@ -50,8 +45,9 @@ jobs: cd bindings_ffi make install-jar echo "$(make echo-jar | tail -n 1 | sed -e 's/\.*export //')" >> "$GITHUB_ENV" - - - name: Run cargo test on FFI bindings + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Run cargo nextest on FFI bindings run: | export CLASSPATH="${{ env.CLASSPATH }}" - cargo test --manifest-path bindings_ffi/Cargo.toml -- --test-threads=2 + cargo nextest run --manifest-path bindings_ffi/Cargo.toml --test-threads 2 diff --git a/.github/workflows/test-http-api.yml b/.github/workflows/test-http-api.yml index 360408735..22cf3e268 100644 --- a/.github/workflows/test-http-api.yml +++ b/.github/workflows/test-http-api.yml @@ -18,6 +18,8 @@ on: - "Cargo.toml" - "Cargo.lock" - "rust-toolchain" +env: + CARGO_TERM_COLOR: always jobs: test: name: Test @@ -36,5 +38,7 @@ jobs: . - name: Start Docker containers run: dev/up - - name: Run cargo test on main workspace - run: cargo test --workspace --exclude xmtp_api_grpc --features http-api -- --test-threads=2 + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Run cargo nextest on main workspace + run: cargo nextest run --workspace --exclude xmtp_api_grpc --features http-api --test-threads 2 diff --git a/.github/workflows/test-workspace.yml b/.github/workflows/test-workspace.yml index 17428fe37..7c006d02f 100644 --- a/.github/workflows/test-workspace.yml +++ b/.github/workflows/test-workspace.yml @@ -18,6 +18,8 @@ on: - "Cargo.toml" - "Cargo.lock" - "rust-toolchain" +env: + CARGO_TERM_COLOR: always jobs: test: name: Test @@ -36,5 +38,7 @@ jobs: . - name: Start Docker containers run: dev/up - - name: Run cargo test on main workspace - run: cargo test -- --test-threads=2 + - name: Install nextest + uses: taiki-e/install-action@nextest + - name: Run cargo nextest on main workspace + run: cargo nextest run --test-threads 2 diff --git a/.gitignore b/.gitignore index 6dff7d3cd..335703a8f 100644 --- a/.gitignore +++ b/.gitignore @@ -164,3 +164,5 @@ ecies_bindings_wasm/ **/test_output.jsonl **/tracing.folded **/tracing-flamegraph.svg + +chain_urls.json diff --git a/Cargo.lock b/Cargo.lock index dcfbe4341..95d07c956 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1197,6 +1197,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.15.1" @@ -1339,29 +1345,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "env_filter" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1799,18 +1782,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "spin 0.9.8", -] - [[package]] name = "fnv" version = "1.0.7" @@ -2331,12 +2302,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.30" @@ -2646,15 +2611,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -2988,11 +2944,9 @@ dependencies = [ "anyhow", "clap", "ed25519-dalek", - "env_logger", "ethers", "futures", "hex", - "log", "openmls", "openmls_basic_credential", "openmls_rust_crypto", @@ -3004,7 +2958,10 @@ dependencies = [ "thiserror", "tokio", "tonic", + "tracing", + "tracing-subscriber", "warp", + "xmtp_cryptography", "xmtp_id", "xmtp_mls", "xmtp_proto", @@ -3084,15 +3041,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - [[package]] name = "native-tls" version = "0.2.12" @@ -3902,7 +3850,7 @@ checksum = "5bb182580f71dd070f88d01ce3de9f4da5021db7115d2e1c3605a754153b77c1" dependencies = [ "bytes", "heck", - "itertools 0.12.1", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -3922,7 +3870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.72", @@ -4764,17 +4712,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "smart-default" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - [[package]] name = "socket2" version = "0.5.7" @@ -4810,9 +4747,6 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] [[package]] name = "spki" @@ -5511,22 +5445,12 @@ dependencies = [ ] [[package]] -name = "tracing-test" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" -dependencies = [ - "tracing-core", - "tracing-subscriber", - "tracing-test-macro", -] - -[[package]] -name = "tracing-test-macro" -version = "0.2.5" +name = "trait-variant" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" dependencies = [ + "proc-macro2", "quote", "syn 2.0.72", ] @@ -5679,6 +5603,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -6225,9 +6150,6 @@ dependencies = [ "base64 0.22.1", "futures", "hex", - "log", - "pbjson", - "pbjson-types", "prost", "serde", "tokio", @@ -6243,16 +6165,12 @@ name = "xmtp_api_http" version = "0.0.1" dependencies = [ "async-stream", - "async-trait", - "bytes", "futures", - "log", "reqwest 0.12.5", "serde", "serde_json", "thiserror", "tokio", - "tokio-stream", "tracing", "xmtp_proto", ] @@ -6263,7 +6181,6 @@ version = "0.1.0" dependencies = [ "clap", "ethers", - "ethers-core", "femme", "futures", "hex", @@ -6275,8 +6192,6 @@ dependencies = [ "thiserror", "timeago", "tokio", - "tokio-stream", - "url", "xmtp_api_grpc", "xmtp_cryptography", "xmtp_id", @@ -6291,11 +6206,9 @@ dependencies = [ "curve25519-dalek", "ecdsa 0.16.9", "ethers", - "ethers-core", "getrandom", "hex", "k256 0.13.3", - "log", "rand", "rand_chacha", "rustc-hex", @@ -6304,6 +6217,7 @@ dependencies = [ "sha3", "thiserror", "tokio", + "tracing", ] [[package]] @@ -6313,22 +6227,18 @@ dependencies = [ "async-trait", "chrono", "ctor", - "ed25519", + "dyn-clone", "ed25519-dalek", "ethers", - "ethers-core", "futures", "hex", - "log", - "openmls", - "openmls_basic_credential", - "openmls_rust_crypto", "openmls_traits", "prost", "rand", "regex", "rustc-hex", "serde", + "serde_json", "sha2 0.10.8", "thiserror", "tokio", @@ -6347,22 +6257,17 @@ dependencies = [ "anyhow", "async-barrier", "async-stream", - "async-trait", "bincode", - "chrono", "criterion", "ctor", "diesel", "diesel_migrations", "ed25519-dalek", "ethers", - "ethers-core", - "flume", "futures", "hex", "indicatif", "libsqlite3-sys", - "log", "mockall", "mockito", "once_cell", @@ -6377,7 +6282,6 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", - "smart-default", "tempfile", "thiserror", "tls_codec", @@ -6386,41 +6290,36 @@ dependencies = [ "toml", "tracing", "tracing-flame", - "tracing-log", "tracing-subscriber", - "tracing-test", + "trait-variant", "xmtp_api_grpc", "xmtp_api_http", "xmtp_cryptography", "xmtp_id", "xmtp_proto", - "xmtp_v2", ] [[package]] name = "xmtp_proto" version = "0.0.1" dependencies = [ - "async-trait", "futures", - "futures-core", "openmls", - "openmls_basic_credential", "pbjson", "pbjson-types", "prost", "prost-types", "serde", "tonic", + "trait-variant", ] [[package]] name = "xmtp_user_preferences" version = "0.0.1" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "libsecp256k1", - "once_cell", "prost", "rand", "xmtp_proto", diff --git a/Cargo.toml b/Cargo.toml index cefde727d..a54c14d6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,17 +26,16 @@ version = "0.0.1" anyhow = "1.0" async-stream = "0.3" async-trait = "0.1.77" +trait-variant = "0.1.2" chrono = "0.4.38" ctor = "0.2" ed25519 = "2.2.3" ed25519-dalek = "2.1.1" ethers = "2.0.11" -ethers-core = "2.0.4" futures = "0.3.30" futures-core = "0.3.30" getrandom = { version = "0.2", default-features = false } hex = "0.4.3" -log = { version = "0.4" } openmls = { git = "https://github.com/xmtp/openmls", rev = "87e7e257d8eb15d6662b104518becfc75ef6db76", default-features = false } openmls_basic_credential = { git = "https://github.com/xmtp/openmls", rev = "87e7e257d8eb15d6662b104518becfc75ef6db76" } openmls_rust_crypto = { git = "https://github.com/xmtp/openmls", rev = "87e7e257d8eb15d6662b104518becfc75ef6db76" } @@ -55,7 +54,7 @@ thiserror = "1.0" tls_codec = "0.4.1" tokio = { version = "1.35.1", default-features = false } tonic = "^0.12" -tracing = { version = "0.1" } +tracing = { version = "0.1", features = ["log"] } tracing-subscriber = "0.3" url = "2.5.0" diff --git a/Dockerfile b/Dockerfile index a2744c2d4..1d594a6ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,7 @@ COPY --chown=xmtp:xmtp rust-toolchain . ENV RUSTUP_PERMIT_COPY_RENAME "yes" RUN rustup update +RUN curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin LABEL org.label-schema.build-date=$BUILD_DATE \ org.label-schema.name="rustdev" \ diff --git a/bindings_ffi/Cargo.lock b/bindings_ffi/Cargo.lock index 5a3700f04..c1a6357b7 100644 --- a/bindings_ffi/Cargo.lock +++ b/bindings_ffi/Cargo.lock @@ -1102,6 +1102,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.15.1" @@ -1238,29 +1244,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "env_filter" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -2150,12 +2133,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.28" @@ -2595,15 +2572,6 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - [[package]] name = "matchit" version = "0.7.3" @@ -2728,16 +2696,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - [[package]] name = "num-bigint" version = "0.4.4" @@ -3009,12 +2967,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "p256" version = "0.13.2" @@ -3502,7 +3454,7 @@ checksum = "5bb182580f71dd070f88d01ce3de9f4da5021db7115d2e1c3605a754153b77c1" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.11.0", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -3522,7 +3474,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.48", @@ -3650,19 +3602,10 @@ checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.4", + "regex-automata", "regex-syntax 0.8.2", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - [[package]] name = "regex-automata" version = "0.4.4" @@ -3674,12 +3617,6 @@ dependencies = [ "regex-syntax 0.8.2", ] -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.7.5" @@ -4298,15 +4235,6 @@ dependencies = [ "keccak", ] -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -4359,17 +4287,6 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" -[[package]] -name = "smart-default" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "smawk" version = "0.3.2" @@ -4635,16 +4552,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - [[package]] name = "time" version = "0.3.36" @@ -4975,6 +4882,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4998,7 +4906,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", - "valuable", ] [[package]] @@ -5012,32 +4919,14 @@ dependencies = [ ] [[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" +name = "trait-variant" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", + "proc-macro2", + "quote", + "syn 2.0.48", ] [[package]] @@ -5289,6 +5178,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -5323,12 +5213,6 @@ dependencies = [ "rand", ] -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - [[package]] name = "vcpkg" version = "0.2.15" @@ -5753,9 +5637,6 @@ dependencies = [ "base64 0.22.1", "futures", "hex", - "log", - "pbjson", - "pbjson-types", "prost", "serde", "tokio", @@ -5772,11 +5653,9 @@ dependencies = [ "curve25519-dalek", "ecdsa 0.16.9", "ethers", - "ethers-core", "getrandom", "hex", "k256 0.13.3", - "log", "rand", "rand_chacha", "rustc-hex", @@ -5784,6 +5663,7 @@ dependencies = [ "sha2", "sha3", "thiserror", + "tracing", ] [[package]] @@ -5792,22 +5672,18 @@ version = "0.0.1" dependencies = [ "async-trait", "chrono", - "ed25519", + "dyn-clone", "ed25519-dalek", "ethers", - "ethers-core", "futures", "hex", - "log", - "openmls", - "openmls_basic_credential", - "openmls_rust_crypto", "openmls_traits", "prost", "rand", "regex", "rustc-hex", "serde", + "serde_json", "sha2", "thiserror", "tokio", @@ -5823,18 +5699,13 @@ version = "0.0.1" dependencies = [ "aes-gcm", "async-stream", - "async-trait", "bincode", - "chrono", "diesel", "diesel_migrations", "ed25519-dalek", - "ethers", - "ethers-core", "futures", "hex", "libsqlite3-sys", - "log", "openmls", "openmls_basic_credential", "openmls_rust_crypto", @@ -5846,42 +5717,39 @@ dependencies = [ "serde", "serde_json", "sha2", - "smart-default", "thiserror", "tls_codec", "tokio", "tokio-stream", "toml 0.8.8", "tracing", + "trait-variant", + "xmtp_api_grpc", "xmtp_cryptography", "xmtp_id", "xmtp_proto", - "xmtp_v2", ] [[package]] name = "xmtp_proto" version = "0.0.1" dependencies = [ - "async-trait", "futures", - "futures-core", "openmls", - "openmls_basic_credential", "pbjson", "pbjson-types", "prost", "prost-types", "serde", "tonic", + "trait-variant", ] [[package]] name = "xmtp_user_preferences" version = "0.0.1" dependencies = [ - "base64 0.21.7", - "once_cell", + "base64 0.22.1", "prost", "xmtp_proto", "xmtp_v2", @@ -5908,20 +5776,17 @@ dependencies = [ name = "xmtpv3" version = "0.0.1" dependencies = [ - "env_logger", "ethers", - "ethers-core", "futures", "log", "parking_lot", + "rand", "tempfile", "thiserror", "thread-id", "tokio", "tokio-test", - "tracing-subscriber", "uniffi", - "uniffi_macros", "uuid 1.9.1", "xmtp_api_grpc", "xmtp_cryptography", diff --git a/bindings_ffi/Cargo.toml b/bindings_ffi/Cargo.toml index 4685dcb6f..bedcdc1ce 100644 --- a/bindings_ffi/Cargo.toml +++ b/bindings_ffi/Cargo.toml @@ -7,7 +7,6 @@ version = "0.0.1" crate-type = ["lib", "cdylib", "staticlib"] [dependencies] -env_logger = "0.11.3" futures = "0.3.28" log = { version = "0.4", features = ["std"] } parking_lot = "0.12.3" @@ -15,17 +14,15 @@ thiserror = "1.0" thread-id = "4.2.1" tokio = { version = "1.28.1", features = ["macros"] } uniffi = { version = "0.28.0", features = ["tokio", "cli"] } -uniffi_macros = "0.28.0" xmtp_api_grpc = { path = "../xmtp_api_grpc" } xmtp_cryptography = { path = "../xmtp_cryptography" } xmtp_id = { path = "../xmtp_id" } -xmtp_mls = { path = "../xmtp_mls", features = ["native"] } +xmtp_mls = { path = "../xmtp_mls", features = ["native", "message-history"] } xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } xmtp_user_preferences = { path = "../xmtp_user_preferences" } xmtp_v2 = { path = "../xmtp_v2" } -tracing-subscriber = { version = "0.3", features = ["env-filter"] } -# NOTE: A regression in openssl-sys exists where libatomic is dynamically linked +# NOTE: A regression in openssl-sys exists where libatomic is dynamically linked # for i686-linux-android targets. https://github.com/sfackler/rust-openssl/issues/2163 # # This is fixed in the openssl-sys fork at @@ -43,13 +40,13 @@ path = "src/bin.rs" [dev-dependencies] ethers = "2.0.13" -ethers-core = "2.0.13" +rand = "0.8.5" tempfile = "3.5.0" tokio = { version = "1.28.1", features = ["full"] } tokio-test = "0.4" -tracing-subscriber = "0.3" uniffi = { version = "0.28.0", features = ["bindgen-tests"] } uuid = { version = "1.9", features = ["v4", "fast-rng"] } +xmtp_mls = { path = "../xmtp_mls", features = ["native", "test-utils"] } # NOTE: The release profile reduces bundle size from 230M to 41M - may have performance impliciations # https://stackoverflow.com/a/54842093 diff --git a/bindings_ffi/src/lib.rs b/bindings_ffi/src/lib.rs index 2faef1ae2..60aa0f4c8 100755 --- a/bindings_ffi/src/lib.rs +++ b/bindings_ffi/src/lib.rs @@ -40,6 +40,8 @@ pub enum GenericError { SignatureRequestError(#[from] xmtp_id::associations::builder::SignatureRequestError), #[error(transparent)] Erc1271SignatureError(#[from] xmtp_id::associations::signature::SignatureError), + #[error(transparent)] + Verifier(#[from] xmtp_id::scw_verifier::VerifierError), } impl From for GenericError { diff --git a/bindings_ffi/src/mls.rs b/bindings_ffi/src/mls.rs index 8f4a4121b..e0dd1fd64 100644 --- a/bindings_ffi/src/mls.rs +++ b/bindings_ffi/src/mls.rs @@ -7,14 +7,16 @@ use std::convert::TryInto; use std::sync::Arc; use tokio::{sync::Mutex, task::AbortHandle}; use xmtp_api_grpc::grpc_api_helper::Client as TonicApiClient; +use xmtp_id::associations::unverified::UnverifiedSignature; +use xmtp_id::associations::AccountId; use xmtp_id::associations::AssociationState; +use xmtp_id::associations::MemberIdentifier; +use xmtp_id::scw_verifier::SmartContractSignatureVerifier; use xmtp_id::{ - associations::{ - builder::SignatureRequest, generate_inbox_id as xmtp_id_generate_inbox_id, - RecoverableEcdsaSignature, SmartContractWalletSignature, - }, + associations::{builder::SignatureRequest, generate_inbox_id as xmtp_id_generate_inbox_id}, InboxId, }; +use xmtp_mls::client::FindGroupParams; use xmtp_mls::groups::group_mutable_metadata::MetadataField; use xmtp_mls::groups::group_permissions::BasePolicies; use xmtp_mls::groups::group_permissions::GroupMutablePermissionsError; @@ -27,6 +29,9 @@ use xmtp_mls::groups::group_permissions::PolicySet; use xmtp_mls::groups::intents::PermissionPolicyOption; use xmtp_mls::groups::intents::PermissionUpdateType; use xmtp_mls::groups::GroupMetadataOptions; +use xmtp_mls::storage::consent_record::ConsentState; +use xmtp_mls::storage::consent_record::ConsentType; +use xmtp_mls::storage::consent_record::StoredConsentRecord; use xmtp_mls::{ api::ApiClientWrapper, builder::ClientBuilder, @@ -177,6 +182,7 @@ pub fn generate_inbox_id(account_address: String, nonce: u64) -> String { #[derive(uniffi::Object)] pub struct FfiSignatureRequest { inner: Arc>, + scw_verifier: Box, } #[uniffi::export(async_runtime = "tokio")] @@ -184,12 +190,11 @@ impl FfiSignatureRequest { // Signature that's signed by EOA wallet pub async fn add_ecdsa_signature(&self, signature_bytes: Vec) -> Result<(), GenericError> { let mut inner = self.inner.lock().await; - let signature_text = inner.signature_text(); inner - .add_signature(Box::new(RecoverableEcdsaSignature::new( - signature_text, - signature_bytes, - ))) + .add_signature( + UnverifiedSignature::new_recoverable_ecdsa(signature_bytes), + self.scw_verifier.clone().as_ref(), + ) .await?; Ok(()) @@ -200,17 +205,31 @@ impl FfiSignatureRequest { &self, signature_bytes: Vec, address: String, - chain_rpc_url: String, + chain_id: u64, + block_number: Option, ) -> Result<(), GenericError> { let mut inner = self.inner.lock().await; - let signature = SmartContractWalletSignature::new_with_rpc( - inner.signature_text(), + let account_id = AccountId::new_evm(chain_id, address); + + let block_number = match block_number { + Some(bn) => bn, + None => { + self.scw_verifier + .current_block_number(&chain_id.to_string()) + .await + .map_err(GenericError::Verifier)? + .0[0] + } + }; + + let signature = UnverifiedSignature::new_smart_contract_wallet( signature_bytes, - address, - chain_rpc_url, - ) - .await?; - inner.add_signature(Box::new(signature)).await?; + account_id, + block_number, + ); + inner + .add_signature(signature, self.scw_verifier.clone().as_ref()) + .await?; Ok(()) } @@ -320,17 +339,39 @@ impl FfiXmtpClient { .await?; Ok(state.into()) } + + pub async fn set_consent_states(&self, records: Vec) -> Result<(), GenericError> { + let inner = self.inner_client.as_ref(); + let stored_records: Vec = + records.into_iter().map(StoredConsentRecord::from).collect(); + + inner.set_consent_states(stored_records).await?; + Ok(()) + } + + pub async fn get_consent_state( + &self, + entity_type: FfiConsentEntityType, + entity: String, + ) -> Result { + let inner = self.inner_client.as_ref(); + let result = inner.get_consent_state(entity_type.into(), entity).await?; + + Ok(result.into()) + } } #[uniffi::export(async_runtime = "tokio")] impl FfiXmtpClient { pub fn signature_request(&self) -> Option> { + let scw_verifier = self.inner_client.context().scw_verifier.clone(); self.inner_client .identity() .signature_request() .map(|request| { Arc::new(FfiSignatureRequest { inner: Arc::new(Mutex::new(request)), + scw_verifier, }) }) } @@ -367,6 +408,7 @@ impl FfiXmtpClient { let request = Arc::new(FfiSignatureRequest { inner: Arc::new(tokio::sync::Mutex::new(signature_request)), + scw_verifier: self.inner_client.context().scw_verifier.clone(), }); Ok(request) @@ -396,6 +438,7 @@ impl FfiXmtpClient { let request = Arc::new(FfiSignatureRequest { inner: Arc::new(tokio::sync::Mutex::new(signature_request)), + scw_verifier: self.inner_client.context().scw_verifier.clone(), }); Ok(request) @@ -422,6 +465,7 @@ impl FfiXmtpClient { Ok(Arc::new(FfiSignatureRequest { inner: Arc::new(tokio::sync::Mutex::new(signature_request)), + scw_verifier: self.inner_client.context().scw_verifier.clone(), })) } } @@ -430,16 +474,32 @@ impl FfiXmtpClient { pub struct FfiInboxState { pub inbox_id: String, pub recovery_address: String, - pub installation_ids: Vec>, + pub installations: Vec, pub account_addresses: Vec, } +#[derive(uniffi::Record)] +pub struct FfiInstallation { + pub id: Vec, + pub client_timestamp_ns: Option, +} + impl From for FfiInboxState { fn from(state: AssociationState) -> Self { Self { inbox_id: state.inbox_id().to_string(), recovery_address: state.recovery_address().to_string(), - installation_ids: state.installation_ids(), + installations: state + .members() + .into_iter() + .filter_map(|m| match m.identifier { + MemberIdentifier::Address(_) => None, + MemberIdentifier::Installation(inst) => Some(FfiInstallation { + id: inst, + client_timestamp_ns: m.client_timestamp_ns, + }), + }) + .collect(), account_addresses: state.account_addresses(), } } @@ -732,6 +792,20 @@ impl FfiConversations { Ok(out) } + pub async fn create_dm(&self, account_address: String) -> Result, GenericError> { + log::info!("creating dm with target address: {}", account_address); + + let convo = self.inner_client.create_dm(account_address).await?; + + let out = Arc::new(FfiGroup { + inner_client: self.inner_client.clone(), + group_id: convo.group_id, + created_at_ns: convo.created_at_ns, + }); + + Ok(out) + } + pub async fn process_streamed_welcome_message( &self, envelope_bytes: Vec, @@ -756,7 +830,16 @@ impl FfiConversations { pub async fn sync_all_groups(&self) -> Result { let inner = self.inner_client.as_ref(); - let groups = inner.find_groups(None, None, None, None)?; + let groups = inner.find_groups(FindGroupParams { + include_dm_groups: true, + ..FindGroupParams::default() + })?; + + log::info!( + "groups for client inbox id {:?}: {:?}", + self.inner_client.inbox_id(), + groups.len() + ); let num_groups_synced: usize = inner.sync_all_groups(groups).await?; // Uniffi does not work with usize, so we need to convert to u32 @@ -776,12 +859,13 @@ impl FfiConversations { ) -> Result>, GenericError> { let inner = self.inner_client.as_ref(); let convo_list: Vec> = inner - .find_groups( - None, - opts.created_after_ns, - opts.created_before_ns, - opts.limit, - )? + .find_groups(FindGroupParams { + allowed_states: None, + created_after_ns: opts.created_after_ns, + created_before_ns: opts.created_before_ns, + limit: opts.limit, + include_dm_groups: false, + })? .into_iter() .map(|group| { Arc::new(FfiGroup { @@ -797,14 +881,17 @@ impl FfiConversations { pub async fn stream(&self, callback: Box) -> FfiStreamCloser { let client = self.inner_client.clone(); - let handle = - RustXmtpClient::stream_conversations_with_callback(client.clone(), move |convo| { + let handle = RustXmtpClient::stream_conversations_with_callback( + client.clone(), + move |convo| { callback.on_conversation(Arc::new(FfiGroup { inner_client: client.clone(), group_id: convo.group_id, created_at_ns: convo.created_at_ns, })) - }); + }, + false, + ); FfiStreamCloser::new(handle) } @@ -835,6 +922,7 @@ pub struct FfiGroupMember { pub account_addresses: Vec, pub installation_ids: Vec>, pub permission_level: FfiPermissionLevel, + pub consent_state: FfiConsentState, } #[derive(uniffi::Enum)] @@ -844,6 +932,50 @@ pub enum FfiPermissionLevel { SuperAdmin, } +#[derive(uniffi::Enum, PartialEq, Debug)] +pub enum FfiConsentState { + Unknown, + Allowed, + Denied, +} + +impl From for FfiConsentState { + fn from(state: ConsentState) -> Self { + match state { + ConsentState::Unknown => FfiConsentState::Unknown, + ConsentState::Allowed => FfiConsentState::Allowed, + ConsentState::Denied => FfiConsentState::Denied, + } + } +} + +impl From for ConsentState { + fn from(state: FfiConsentState) -> Self { + match state { + FfiConsentState::Unknown => ConsentState::Unknown, + FfiConsentState::Allowed => ConsentState::Allowed, + FfiConsentState::Denied => ConsentState::Denied, + } + } +} + +#[derive(uniffi::Enum)] +pub enum FfiConsentEntityType { + GroupId, + InboxId, + Address, +} + +impl From for ConsentType { + fn from(entity_type: FfiConsentEntityType) -> Self { + match entity_type { + FfiConsentEntityType::GroupId => ConsentType::GroupId, + FfiConsentEntityType::InboxId => ConsentType::InboxId, + FfiConsentEntityType::Address => ConsentType::Address, + } + } +} + #[derive(uniffi::Record, Clone, Default)] pub struct FfiListMessagesOptions { pub sent_before_ns: Option, @@ -961,14 +1093,14 @@ impl FfiGroup { self.created_at_ns, ); let message = group - .process_streamed_group_message(envelope_bytes, self.inner_client.clone()) + .process_streamed_group_message(envelope_bytes, &self.inner_client) .await?; let ffi_message = message.into(); Ok(ffi_message) } - pub fn list_members(&self) -> Result, GenericError> { + pub async fn list_members(&self) -> Result, GenericError> { let group = MlsGroup::new( self.inner_client.context().clone(), self.group_id.clone(), @@ -976,7 +1108,8 @@ impl FfiGroup { ); let members: Vec = group - .members()? + .members(&self.inner_client) + .await? .into_iter() .map(|member| FfiGroupMember { inbox_id: member.inbox_id, @@ -987,6 +1120,7 @@ impl FfiGroup { PermissionLevel::Admin => FfiPermissionLevel::Admin, PermissionLevel::SuperAdmin => FfiPermissionLevel::SuperAdmin, }, + consent_state: member.consent_state.into(), }) .collect(); @@ -1325,6 +1459,30 @@ impl FfiGroup { Ok(group.is_active(group.mls_provider()?)?) } + pub fn consent_state(&self) -> Result { + let group = MlsGroup::new( + self.inner_client.context().clone(), + self.group_id.clone(), + self.created_at_ns, + ); + + let state = group.consent_state()?; + + Ok(state.into()) + } + + pub fn update_consent_state(&self, state: FfiConsentState) -> Result<(), GenericError> { + let group = MlsGroup::new( + self.inner_client.context().clone(), + self.group_id.clone(), + self.created_at_ns, + ); + + group.update_consent_state(state.into())?; + + Ok(()) + } + pub fn added_by_inbox_id(&self) -> Result { let group = MlsGroup::new( self.inner_client.context().clone(), @@ -1423,6 +1581,23 @@ impl From for FfiMessage { } } +#[derive(uniffi::Record)] +pub struct FfiConsent { + pub entity_type: FfiConsentEntityType, + pub state: FfiConsentState, + pub entity: String, +} + +impl From for StoredConsentRecord { + fn from(consent: FfiConsent) -> Self { + Self { + entity_type: consent.entity_type.into(), + state: consent.state.into(), + entity: consent.entity, + } + } +} + #[derive(uniffi::Object, Clone, Debug)] pub struct FfiStreamCloser { #[allow(clippy::type_complexity)] @@ -1560,13 +1735,16 @@ impl FfiGroupPermissions { #[cfg(test)] mod tests { + use super::{create_client, FfiMessage, FfiMessageCallback, FfiXmtpClient}; use crate::{ - get_inbox_id_for_address, inbox_owner::SigningError, logger::FfiLogger, - FfiConversationCallback, FfiCreateGroupOptions, FfiGroup, FfiGroupMessageKind, - FfiGroupPermissionsOptions, FfiInboxOwner, FfiListConversationsOptions, - FfiListMessagesOptions, FfiMetadataField, FfiPermissionPolicy, FfiPermissionPolicySet, - FfiPermissionUpdateType, + get_inbox_id_for_address, inbox_owner::SigningError, logger::FfiLogger, FfiConsent, + FfiConsentEntityType, FfiConsentState, FfiConversationCallback, FfiCreateGroupOptions, + FfiGroup, FfiGroupMessageKind, FfiGroupPermissionsOptions, FfiInboxOwner, + FfiListConversationsOptions, FfiListMessagesOptions, FfiMetadataField, FfiPermissionPolicy, + FfiPermissionPolicySet, FfiPermissionUpdateType, }; + use ethers::utils::hex; + use rand::distributions::{Alphanumeric, DistString}; use std::{ env, sync::{ @@ -1574,16 +1752,12 @@ mod tests { Arc, Mutex, }, }; - - use super::{create_client, FfiMessage, FfiMessageCallback, FfiXmtpClient}; - use ethers::utils::hex; - use ethers_core::rand::{ - self, - distributions::{Alphanumeric, DistString}, - }; use tokio::{sync::Notify, time::error::Elapsed}; use xmtp_cryptography::{signature::RecoverableSignature, utils::rng}; - use xmtp_id::associations::generate_inbox_id; + use xmtp_id::associations::{ + generate_inbox_id, + unverified::{UnverifiedRecoverableEcdsaSignature, UnverifiedSignature}, + }; use xmtp_mls::{ groups::{GroupError, MlsGroup}, storage::EncryptionKey, @@ -1713,7 +1887,7 @@ mod tests { xmtp_api_grpc::LOCALHOST_ADDRESS.to_string(), false, Some(tmp_path()), - None, + Some(xmtp_mls::storage::EncryptedMessageStore::generate_enc_key().into()), &inbox_id, ffi_inbox_owner.get_address(), nonce, @@ -1764,13 +1938,6 @@ mod tests { assert_eq!(real_inbox_id, from_network); } - // Try a query on a test topic, and make sure we get a response - #[tokio::test] - async fn test_client_creation() { - let client = new_test_client().await; - assert!(client.signature_request().is_some()); - } - #[tokio::test] #[ignore] async fn test_legacy_identity() { @@ -1901,6 +2068,7 @@ mod tests { wallet: &xmtp_cryptography::utils::LocalWallet, signature_request: &FfiSignatureRequest, ) { + let scw_verifier = signature_request.scw_verifier.clone(); let signature_text = signature_request.inner.lock().await.signature_text(); let wallet_signature: Vec = wallet.sign(&signature_text.clone()).unwrap().into(); @@ -1908,12 +2076,12 @@ mod tests { .inner .lock() .await - .add_signature(Box::new( - xmtp_id::associations::RecoverableEcdsaSignature::new( - signature_text, + .add_signature( + UnverifiedSignature::RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature::new( wallet_signature, - ), - )) + )), + scw_verifier.clone().as_ref(), + ) .await .unwrap(); } @@ -1944,9 +2112,8 @@ mod tests { .await .unwrap(); - register_client(&ffi_inbox_owner, &client).await; - let signature_request = client.signature_request().unwrap().clone(); + register_client(&ffi_inbox_owner, &client).await; sign_with_wallet(&ffi_inbox_owner.wallet, &signature_request).await; @@ -2011,9 +2178,8 @@ mod tests { .await .unwrap(); - register_client(&ffi_inbox_owner, &client).await; - let signature_request = client.signature_request().unwrap().clone(); + register_client(&ffi_inbox_owner, &client).await; sign_with_wallet(&ffi_inbox_owner.wallet, &signature_request).await; @@ -2181,7 +2347,7 @@ mod tests { .await .unwrap(); - let members = group.list_members().unwrap(); + let members = group.list_members().await.unwrap(); assert_eq!(members.len(), 2); } @@ -2206,7 +2372,7 @@ mod tests { .await .unwrap(); - let members = group.list_members().unwrap(); + let members = group.list_members().await.unwrap(); assert_eq!(members.len(), 2); assert_eq!(group.group_name().unwrap(), "Group Name"); assert_eq!(group.group_image_url_square().unwrap(), "url"); @@ -2470,10 +2636,10 @@ mod tests { client2_group.sync().await.unwrap(); // Assert both clients see 2 members - let client1_members = client1_group.list_members().unwrap(); + let client1_members = client1_group.list_members().await.unwrap(); assert_eq!(client1_members.len(), 2); - let client2_members = client2_group.list_members().unwrap(); + let client2_members = client2_group.list_members().await.unwrap(); assert_eq!(client2_members.len(), 2); // Drop and delete local database for client2 @@ -2491,12 +2657,12 @@ mod tests { .unwrap(); // Assert client1 still sees 2 members - let client1_members = client1_group.list_members().unwrap(); + let client1_members = client1_group.list_members().await.unwrap(); assert_eq!(client1_members.len(), 2); client2.conversations().sync().await.unwrap(); let client2_group = client2.group(group.id()).unwrap(); - let client2_members = client2_group.list_members().unwrap(); + let client2_members = client2_group.list_members().await.unwrap(); assert_eq!(client2_members.len(), 2); } @@ -2744,11 +2910,11 @@ mod tests { .unwrap(); bo_group.sync().await.unwrap(); - let bo_members = bo_group.list_members().unwrap(); + let bo_members = bo_group.list_members().await.unwrap(); assert_eq!(bo_members.len(), 4); alix_group.sync().await.unwrap(); - let alix_members = alix_group.list_members().unwrap(); + let alix_members = alix_group.list_members().await.unwrap(); assert_eq!(alix_members.len(), 4); } @@ -2770,11 +2936,11 @@ mod tests { let bo_group = bo.group(alix_group.id()).unwrap(); alix_group.sync().await.unwrap(); - let alix_members = alix_group.list_members().unwrap(); + let alix_members = alix_group.list_members().await.unwrap(); assert_eq!(alix_members.len(), 2); bo_group.sync().await.unwrap(); - let bo_members = bo_group.list_members().unwrap(); + let bo_members = bo_group.list_members().await.unwrap(); assert_eq!(bo_members.len(), 2); let bo_messages = bo_group @@ -2798,11 +2964,11 @@ mod tests { assert!(bo_messages.first().unwrap().kind == FfiGroupMessageKind::MembershipChange); assert_eq!(bo_messages.len(), 1); - let bo_members = bo_group.list_members().unwrap(); + let bo_members = bo_group.list_members().await.unwrap(); assert_eq!(bo_members.len(), 1); alix_group.sync().await.unwrap(); - let alix_members = alix_group.list_members().unwrap(); + let alix_members = alix_group.list_members().await.unwrap(); assert_eq!(alix_members.len(), 1); } @@ -3542,8 +3708,8 @@ mod tests { let client_1_state = client_1.inbox_state(true).await.unwrap(); let client_2_state = client_2.inbox_state(true).await.unwrap(); - assert_eq!(client_1_state.installation_ids.len(), 2); - assert_eq!(client_2_state.installation_ids.len(), 2); + assert_eq!(client_1_state.installations.len(), 2); + assert_eq!(client_2_state.installations.len(), 2); let signature_request = client_1.revoke_all_other_installations().await.unwrap(); sign_with_wallet(&wallet, &signature_request).await; @@ -3554,23 +3720,132 @@ mod tests { let client_1_state_after_revoke = client_1.inbox_state(true).await.unwrap(); let client_2_state_after_revoke = client_2.inbox_state(true).await.unwrap(); - assert_eq!(client_1_state_after_revoke.installation_ids.len(), 1); - assert_eq!(client_2_state_after_revoke.installation_ids.len(), 1); + assert_eq!(client_1_state_after_revoke.installations.len(), 1); + assert_eq!(client_2_state_after_revoke.installations.len(), 1); assert_eq!( client_1_state_after_revoke - .installation_ids + .installations .first() .unwrap() - .clone(), + .id, client_1.installation_id() ); assert_eq!( client_2_state_after_revoke - .installation_ids + .installations .first() .unwrap() - .clone(), + .id, client_1.installation_id() ); } + + #[tokio::test(flavor = "multi_thread", worker_threads = 5)] + async fn test_dms_sync_but_do_not_list() { + let alix = new_test_client().await; + let bola = new_test_client().await; + + let alix_conversations = alix.conversations(); + let bola_conversations = bola.conversations(); + + let _alix_group = alix_conversations + .create_dm(bola.account_address.clone()) + .await + .unwrap(); + let alix_num_sync = alix_conversations.sync_all_groups().await.unwrap(); + bola_conversations.sync().await.unwrap(); + let bola_num_sync = bola_conversations.sync_all_groups().await.unwrap(); + assert_eq!(alix_num_sync, 1); + assert_eq!(bola_num_sync, 1); + + let alix_groups = alix_conversations + .list(FfiListConversationsOptions::default()) + .await + .unwrap(); + assert_eq!(alix_groups.len(), 0); + + let bola_groups = bola_conversations + .list(FfiListConversationsOptions::default()) + .await + .unwrap(); + assert_eq!(bola_groups.len(), 0); + } + + #[tokio::test(flavor = "multi_thread", worker_threads = 5)] + async fn test_set_and_get_group_consent() { + let alix = new_test_client().await; + let bo = new_test_client().await; + + let alix_group = alix + .conversations() + .create_group( + vec![bo.account_address.clone()], + FfiCreateGroupOptions::default(), + ) + .await + .unwrap(); + + let alix_initial_consent = alix_group.consent_state().unwrap(); + assert_eq!(alix_initial_consent, FfiConsentState::Allowed); + + bo.conversations().sync().await.unwrap(); + let bo_group = bo.group(alix_group.id()).unwrap(); + + let bo_initial_consent = bo_group.consent_state().unwrap(); + assert_eq!(bo_initial_consent, FfiConsentState::Unknown); + + alix_group + .update_consent_state(FfiConsentState::Denied) + .unwrap(); + let alix_updated_consent = alix_group.consent_state().unwrap(); + assert_eq!(alix_updated_consent, FfiConsentState::Denied); + bo.set_consent_states(vec![FfiConsent { + state: FfiConsentState::Allowed, + entity_type: FfiConsentEntityType::GroupId, + entity: hex::encode(bo_group.id()), + }]) + .await + .unwrap(); + let bo_updated_consent = bo_group.consent_state().unwrap(); + assert_eq!(bo_updated_consent, FfiConsentState::Allowed); + } + + #[tokio::test(flavor = "multi_thread", worker_threads = 5)] + async fn test_set_and_get_member_consent() { + let alix = new_test_client().await; + let bo = new_test_client().await; + + let alix_group = alix + .conversations() + .create_group( + vec![bo.account_address.clone()], + FfiCreateGroupOptions::default(), + ) + .await + .unwrap(); + alix.set_consent_states(vec![FfiConsent { + state: FfiConsentState::Allowed, + entity_type: FfiConsentEntityType::Address, + entity: bo.account_address.clone(), + }]) + .await + .unwrap(); + let bo_consent = alix + .get_consent_state(FfiConsentEntityType::Address, bo.account_address.clone()) + .await + .unwrap(); + assert_eq!(bo_consent, FfiConsentState::Allowed); + + if let Some(member) = alix_group + .list_members() + .await + .unwrap() + .iter() + .find(|&m| m.inbox_id == bo.inbox_id()) + { + assert_eq!(member.consent_state, FfiConsentState::Allowed); + } else { + panic!("Error: No member found with the given inbox_id."); + } + } } diff --git a/bindings_ffi/src/v2.rs b/bindings_ffi/src/v2.rs index 090306e97..f98a9a803 100644 --- a/bindings_ffi/src/v2.rs +++ b/bindings_ffi/src/v2.rs @@ -591,7 +591,7 @@ mod tests { let msg = "TestVector1"; let sig_hash = "19d6bec562518e365d07ba3cce26d08a5fffa2cbb1e7fe03c1f2d6a722fd3a5e544097b91f8f8cd11d43b032659f30529139ab1a9ecb6c81ed4a762179e87db81c"; - let sig_bytes = ethers_core::utils::hex::decode(sig_hash).unwrap(); + let sig_bytes = ethers::core::utils::hex::decode(sig_hash).unwrap(); let recovered_addr = crate::v2::recover_address(sig_bytes, msg.to_string()).unwrap(); assert_eq!(recovered_addr, addr.to_lowercase()); } diff --git a/bindings_node/CHANGELOG.md b/bindings_node/CHANGELOG.md index c143fedf2..530e8cdbd 100644 --- a/bindings_node/CHANGELOG.md +++ b/bindings_node/CHANGELOG.md @@ -1,5 +1,20 @@ # @xmtp/mls-client-bindings-node +## 0.0.12 + +- Added ability to add wallet associations to a client +- Added ability to revoke wallet associations from a client +- Added ability to revoke all installation IDs from a client +- Added `getLatestInboxState` to client +- Added installation timestamps to `inboxState` +- Updated `send_optimistic` to return the message ID as a hex string +- Added consent state methods to groups and client + +## 0.0.11 + +- Added `inboxState` to client +- Skip duplicate message processing when streaming + ## 0.0.10 - Fixed several group syncing issues @@ -24,8 +39,8 @@ - Improved streaming welcomes - Improved DB retries - Changed encoding of the MLS database to `bincode` for performance -- Added `find_inbox_id_by_address` to client -- Added `find_group_by_id` and `find_message_by_id` to conversations +- Added `findInboxIdByAddress` to client +- Added `findGroupById` and `findMessageById` to conversations ## 0.0.6 @@ -35,11 +50,11 @@ - Added ability to set group name and image URL during creation - Added getter and setter for group image URL -- Renamed `add_erc1271_signature` to `add_scw_signature` +- Renamed `addErc1271Signature` to `addScwSignature` ## 0.0.4 -- Added `stream_all_messages` +- Added `streamAllMessages` ## 0.0.3 diff --git a/bindings_node/Cargo.lock b/bindings_node/Cargo.lock index e5c2040a8..02e159081 100644 --- a/bindings_node/Cargo.lock +++ b/bindings_node/Cargo.lock @@ -302,7 +302,6 @@ version = "0.0.1" dependencies = [ "futures", "hex", - "log", "napi", "napi-build", "napi-derive", @@ -310,6 +309,7 @@ dependencies = [ "rand", "tokio", "tonic", + "tracing", "xmtp_api_grpc", "xmtp_cryptography", "xmtp_id", @@ -965,6 +965,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.15.1" @@ -2223,15 +2229,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -3275,7 +3272,7 @@ checksum = "5bb182580f71dd070f88d01ce3de9f4da5021db7115d2e1c3605a754153b77c1" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.12.1", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -3295,7 +3292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", "syn 2.0.64", @@ -4074,17 +4071,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "smart-default" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.64", -] - [[package]] name = "socket2" version = "0.5.7" @@ -4612,6 +4598,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4647,6 +4634,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "trait-variant" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.64", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -4761,6 +4759,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -5210,9 +5209,6 @@ dependencies = [ "base64 0.22.1", "futures", "hex", - "log", - "pbjson", - "pbjson-types", "prost", "serde", "tokio", @@ -5229,11 +5225,9 @@ dependencies = [ "curve25519-dalek", "ecdsa 0.16.9", "ethers", - "ethers-core", "getrandom", "hex", "k256 0.13.3", - "log", "rand", "rand_chacha", "rustc-hex", @@ -5241,6 +5235,7 @@ dependencies = [ "sha2", "sha3", "thiserror", + "tracing", ] [[package]] @@ -5249,22 +5244,18 @@ version = "0.0.1" dependencies = [ "async-trait", "chrono", - "ed25519", + "dyn-clone", "ed25519-dalek", "ethers", - "ethers-core", "futures", "hex", - "log", - "openmls", - "openmls_basic_credential", - "openmls_rust_crypto", "openmls_traits", "prost", "rand", "regex", "rustc-hex", "serde", + "serde_json", "sha2", "thiserror", "tokio", @@ -5280,18 +5271,13 @@ version = "0.0.1" dependencies = [ "aes-gcm", "async-stream", - "async-trait", "bincode", - "chrono", "diesel", "diesel_migrations", "ed25519-dalek", - "ethers", - "ethers-core", "futures", "hex", "libsqlite3-sys", - "log", "openmls", "openmls_basic_credential", "openmls_rust_crypto", @@ -5303,34 +5289,32 @@ dependencies = [ "serde", "serde_json", "sha2", - "smart-default", "thiserror", "tls_codec", "tokio", "tokio-stream", "toml", "tracing", + "trait-variant", + "xmtp_api_grpc", "xmtp_cryptography", "xmtp_id", "xmtp_proto", - "xmtp_v2", ] [[package]] name = "xmtp_proto" version = "0.0.1" dependencies = [ - "async-trait", "futures", - "futures-core", "openmls", - "openmls_basic_credential", "pbjson", "pbjson-types", "prost", "prost-types", "serde", "tonic", + "trait-variant", ] [[package]] diff --git a/bindings_node/Cargo.toml b/bindings_node/Cargo.toml index 9d10429ad..b53058bf4 100644 --- a/bindings_node/Cargo.toml +++ b/bindings_node/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["cdylib"] # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix futures = "0.3.30" hex = "0.4.3" -log = { version = "0.4", features = ["release_max_level_debug"] } +tracing = { version = "0.1", features = ["release_max_level_debug"] } napi = { version = "2.12.2", default-features = false, features = [ "napi4", "napi6", @@ -24,7 +24,7 @@ tonic = { version = "^0.12", features = ["tls"] } xmtp_api_grpc = { path = "../xmtp_api_grpc" } xmtp_cryptography = { path = "../xmtp_cryptography" } xmtp_id = { path = "../xmtp_id" } -xmtp_mls = { path = "../xmtp_mls", features = ["native"] } +xmtp_mls = { path = "../xmtp_mls", features = ["native", "message-history"] } xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } [build-dependencies] diff --git a/bindings_node/package.json b/bindings_node/package.json index 429a798c7..17d1c0206 100644 --- a/bindings_node/package.json +++ b/bindings_node/package.json @@ -1,6 +1,6 @@ { "name": "@xmtp/mls-client-bindings-node", - "version": "0.0.10", + "version": "0.0.12", "repository": { "type": "git", "url": "git+https://git@github.com/xmtp/libxmtp.git", @@ -35,9 +35,11 @@ "@ianvs/prettier-plugin-sort-imports": "^4.2.1", "@napi-rs/cli": "^3.0.0-alpha.55", "@types/node": "^20.14.2", + "@types/uuid": "^10", "prettier": "^3.3.2", "prettier-plugin-packagejson": "^2.5.0", "typescript": "^5.4.5", + "uuid": "^10.0.0", "viem": "^2.11.1", "vite": "^5.2.13", "vite-tsconfig-paths": "^4.3.2", diff --git a/bindings_node/src/consent_state.rs b/bindings_node/src/consent_state.rs new file mode 100644 index 000000000..ecc1ba8a7 --- /dev/null +++ b/bindings_node/src/consent_state.rs @@ -0,0 +1,63 @@ +use napi_derive::napi; +use xmtp_mls::storage::consent_record::{ConsentState, ConsentType, StoredConsentRecord}; + +#[napi] +pub enum NapiConsentState { + Unknown, + Allowed, + Denied, +} + +impl From for NapiConsentState { + fn from(state: ConsentState) -> Self { + match state { + ConsentState::Unknown => NapiConsentState::Unknown, + ConsentState::Allowed => NapiConsentState::Allowed, + ConsentState::Denied => NapiConsentState::Denied, + } + } +} + +impl From for ConsentState { + fn from(state: NapiConsentState) -> Self { + match state { + NapiConsentState::Unknown => ConsentState::Unknown, + NapiConsentState::Allowed => ConsentState::Allowed, + NapiConsentState::Denied => ConsentState::Denied, + } + } +} + +#[napi] +pub enum NapiConsentEntityType { + GroupId, + InboxId, + Address, +} + +impl From for ConsentType { + fn from(entity_type: NapiConsentEntityType) -> Self { + match entity_type { + NapiConsentEntityType::GroupId => ConsentType::GroupId, + NapiConsentEntityType::InboxId => ConsentType::InboxId, + NapiConsentEntityType::Address => ConsentType::Address, + } + } +} + +#[napi(object)] +pub struct NapiConsent { + pub entity_type: NapiConsentEntityType, + pub state: NapiConsentState, + pub entity: String, +} + +impl From for StoredConsentRecord { + fn from(consent: NapiConsent) -> Self { + Self { + entity_type: consent.entity_type.into(), + state: consent.state.into(), + entity: consent.entity, + } + } +} diff --git a/bindings_node/src/conversations.rs b/bindings_node/src/conversations.rs index 21a5dae60..c3ae47033 100644 --- a/bindings_node/src/conversations.rs +++ b/bindings_node/src/conversations.rs @@ -6,10 +6,12 @@ use napi::bindgen_prelude::{Error, Result, Uint8Array}; use napi::threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode}; use napi::JsFunction; use napi_derive::napi; +use xmtp_mls::client::FindGroupParams; use xmtp_mls::groups::{GroupMetadataOptions, PreconfiguredPolicies}; use crate::messages::NapiMessage; use crate::permissions::NapiGroupPermissionsOptions; +use crate::ErrorWrapper; use crate::{groups::NapiGroup, mls_client::RustXmtpClient, streams::NapiStreamCloser}; #[napi(object)] @@ -20,6 +22,7 @@ pub struct NapiListConversationsOptions { } #[napi(object)] +#[derive(Clone)] pub struct NapiCreateGroupOptions { pub permissions: Option, pub group_name: Option, @@ -77,16 +80,21 @@ impl NapiConversations { _ => None, }; - let convo = self - .inner_client - .create_group(group_permissions, options.into_group_metadata_options()) - .map_err(|e| Error::from_reason(format!("ClientError: {}", e)))?; - if !account_addresses.is_empty() { - convo - .add_members(&self.inner_client, account_addresses) + let metadata_options = options.clone().into_group_metadata_options(); + + let convo = if account_addresses.is_empty() { + self + .inner_client + .create_group(group_permissions, metadata_options) + .map_err(|e| Error::from_reason(format!("ClientError: {}", e)))? + } else { + self + .inner_client + .create_group_with_members(account_addresses, group_permissions, metadata_options) .await - .map_err(|e| Error::from_reason(format!("GroupError: {}", e)))?; - } + .map_err(|e| Error::from_reason(format!("ClientError: {}", e)))? + }; + let out = NapiGroup::new( self.inner_client.clone(), convo.group_id, @@ -98,12 +106,12 @@ impl NapiConversations { #[napi] pub fn find_group_by_id(&self, group_id: String) -> Result { - let group_id = hex::decode(group_id).map_err(|e| Error::from_reason(format!("{}", e)))?; + let group_id = hex::decode(group_id).map_err(ErrorWrapper::from)?; let group = self .inner_client .group(group_id) - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; Ok(NapiGroup::new( self.inner_client.clone(), @@ -114,12 +122,12 @@ impl NapiConversations { #[napi] pub fn find_message_by_id(&self, message_id: String) -> Result { - let message_id = hex::decode(message_id).map_err(|e| Error::from_reason(format!("{}", e)))?; + let message_id = hex::decode(message_id).map_err(ErrorWrapper::from)?; let message = self .inner_client .message(message_id) - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; Ok(NapiMessage::from(message)) } @@ -134,7 +142,7 @@ impl NapiConversations { .inner_client .process_streamed_welcome_message(envelope_bytes) .await - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; let out = NapiGroup::new( self.inner_client.clone(), group.group_id, @@ -149,7 +157,7 @@ impl NapiConversations { .inner_client .sync_welcomes() .await - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; Ok(()) } @@ -165,13 +173,13 @@ impl NapiConversations { }; let convo_list: Vec = self .inner_client - .find_groups( - None, - opts.created_after_ns, - opts.created_before_ns, - opts.limit, - ) - .map_err(|e| Error::from_reason(format!("{}", e)))? + .find_groups(FindGroupParams { + created_after_ns: opts.created_after_ns, + created_before_ns: opts.created_before_ns, + limit: opts.limit, + ..FindGroupParams::default() + }) + .map_err(ErrorWrapper::from)? .into_iter() .map(|group| { NapiGroup::new( @@ -190,8 +198,9 @@ impl NapiConversations { let tsfn: ThreadsafeFunction = callback.create_threadsafe_function(0, |ctx| Ok(vec![ctx.value]))?; let client = self.inner_client.clone(); - let stream_closer = - RustXmtpClient::stream_conversations_with_callback(client.clone(), move |convo| { + let stream_closer = RustXmtpClient::stream_conversations_with_callback( + client.clone(), + move |convo| { tsfn.call( Ok(NapiGroup::new( client.clone(), @@ -200,7 +209,9 @@ impl NapiConversations { )), ThreadsafeFunctionCallMode::Blocking, ); - }); + }, + false, + ); Ok(NapiStreamCloser::new(stream_closer)) } diff --git a/bindings_node/src/groups.rs b/bindings_node/src/groups.rs index acf79323a..31dbda2ce 100644 --- a/bindings_node/src/groups.rs +++ b/bindings_node/src/groups.rs @@ -1,7 +1,7 @@ use std::{ops::Deref, sync::Arc}; use napi::{ - bindgen_prelude::{Error, Result, Uint8Array}, + bindgen_prelude::{Result, Uint8Array}, threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode}, JsFunction, }; @@ -14,6 +14,7 @@ use xmtp_mls::groups::{ use xmtp_proto::xmtp::mls::message_contents::EncodedContent; use crate::{ + consent_state::NapiConsentState, encoded_content::NapiEncodedContent, messages::{NapiListMessagesOptions, NapiMessage}, mls_client::RustXmtpClient, @@ -61,9 +62,9 @@ pub struct NapiGroupMember { pub account_addresses: Vec, pub installation_ids: Vec, pub permission_level: NapiPermissionLevel, + pub consent_state: NapiConsentState, } -#[derive(Debug)] #[napi] pub struct NapiGroup { inner_client: Arc, @@ -107,7 +108,7 @@ impl NapiGroup { /// send a message without immediately publishing to the delivery service. #[napi] - pub fn send_optimistic(&self, encoded_content: NapiEncodedContent) -> Result> { + pub fn send_optimistic(&self, encoded_content: NapiEncodedContent) -> Result { let encoded_content: EncodedContent = encoded_content.into(); let group = MlsGroup::new( self.inner_client.context().clone(), @@ -119,7 +120,7 @@ impl NapiGroup { .send_message_optimistic(encoded_content.encode_to_vec().as_slice()) .map_err(ErrorWrapper::from)?; - Ok(id) + Ok(hex::encode(id.clone())) } /// Publish all unpublished messages @@ -201,7 +202,7 @@ impl NapiGroup { ); let envelope_bytes: Vec = envelope_bytes.deref().to_vec(); let message = group - .process_streamed_group_message(envelope_bytes, self.inner_client.clone()) + .process_streamed_group_message(envelope_bytes, &self.inner_client) .await .map_err(ErrorWrapper::from)?; @@ -209,7 +210,7 @@ impl NapiGroup { } #[napi] - pub fn list_members(&self) -> Result> { + pub async fn list_members(&self) -> Result> { let group = MlsGroup::new( self.inner_client.context().clone(), self.group_id.clone(), @@ -217,7 +218,8 @@ impl NapiGroup { ); let members: Vec = group - .members() + .members(&self.inner_client) + .await .map_err(ErrorWrapper::from)? .into_iter() .map(|member| NapiGroupMember { @@ -233,6 +235,7 @@ impl NapiGroup { PermissionLevel::Admin => NapiPermissionLevel::Admin, PermissionLevel::SuperAdmin => NapiPermissionLevel::SuperAdmin, }, + consent_state: member.consent_state.into(), }) .collect(); @@ -541,7 +544,7 @@ impl NapiGroup { let group_pinned_frame_url = group .group_pinned_frame_url(group.mls_provider().map_err(ErrorWrapper::from)?) - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; Ok(group_pinned_frame_url) } @@ -607,4 +610,32 @@ impl NapiGroup { Ok(NapiGroupMetadata { inner: metadata }) } + + #[napi] + pub fn consent_state(&self) -> Result { + let group = MlsGroup::new( + self.inner_client.context().clone(), + self.group_id.clone(), + self.created_at_ns, + ); + + let state = group.consent_state().map_err(ErrorWrapper::from)?; + + Ok(state.into()) + } + + #[napi] + pub fn update_consent_state(&self, state: NapiConsentState) -> Result<()> { + let group = MlsGroup::new( + self.inner_client.context().clone(), + self.group_id.clone(), + self.created_at_ns, + ); + + group + .update_consent_state(state.into()) + .map_err(ErrorWrapper::from)?; + + Ok(()) + } } diff --git a/bindings_node/src/inbox_state.rs b/bindings_node/src/inbox_state.rs new file mode 100644 index 000000000..cd56a804d --- /dev/null +++ b/bindings_node/src/inbox_state.rs @@ -0,0 +1,39 @@ +use napi::bindgen_prelude::BigInt; +use napi_derive::napi; +use xmtp_cryptography::signature::ed25519_public_key_to_address; +use xmtp_id::associations::{AssociationState, MemberIdentifier}; + +#[napi(object)] +pub struct NapiInstallation { + pub id: String, + pub client_timestamp_ns: Option, +} + +#[napi(object)] +pub struct NapiInboxState { + pub inbox_id: String, + pub recovery_address: String, + pub installations: Vec, + pub account_addresses: Vec, +} + +impl From for NapiInboxState { + fn from(state: AssociationState) -> Self { + Self { + inbox_id: state.inbox_id().to_string(), + recovery_address: state.recovery_address().to_string(), + installations: state + .members() + .into_iter() + .filter_map(|m| match m.identifier { + MemberIdentifier::Address(_) => None, + MemberIdentifier::Installation(inst) => Some(NapiInstallation { + id: ed25519_public_key_to_address(inst.as_slice()), + client_timestamp_ns: m.client_timestamp_ns.map(BigInt::from), + }), + }) + .collect(), + account_addresses: state.account_addresses(), + } + } +} diff --git a/bindings_node/src/lib.rs b/bindings_node/src/lib.rs index 0dea07153..6d660a59a 100755 --- a/bindings_node/src/lib.rs +++ b/bindings_node/src/lib.rs @@ -1,9 +1,11 @@ #![recursion_limit = "256"] #![warn(clippy::unwrap_used)] +mod consent_state; mod conversations; -pub mod encoded_content; +mod encoded_content; mod groups; +mod inbox_state; mod messages; pub mod mls_client; mod permissions; diff --git a/bindings_node/src/mls_client.rs b/bindings_node/src/mls_client.rs index bf5af92e4..c1c3f8499 100644 --- a/bindings_node/src/mls_client.rs +++ b/bindings_node/src/mls_client.rs @@ -1,28 +1,41 @@ +use crate::consent_state::{NapiConsent, NapiConsentEntityType, NapiConsentState}; use crate::conversations::NapiConversations; -use napi::bindgen_prelude::{BigInt, Error, Result, Uint8Array}; +use crate::inbox_state::NapiInboxState; +use crate::ErrorWrapper; +use napi::bindgen_prelude::{Error, Result, Uint8Array}; use napi_derive::napi; use std::collections::HashMap; use std::ops::Deref; use std::sync::Arc; +use tokio::sync::Mutex; pub use xmtp_api_grpc::grpc_api_helper::Client as TonicApiClient; use xmtp_cryptography::signature::ed25519_public_key_to_address; +use xmtp_id::associations::builder::SignatureRequest; use xmtp_id::associations::generate_inbox_id as xmtp_id_generate_inbox_id; -use xmtp_id::associations::{ - AccountId, MemberIdentifier, RecoverableEcdsaSignature, Signature, SmartContractWalletSignature, -}; +use xmtp_id::associations::unverified::UnverifiedSignature; use xmtp_mls::api::ApiClientWrapper; use xmtp_mls::builder::ClientBuilder; use xmtp_mls::identity::IdentityStrategy; use xmtp_mls::retry::Retry; +use xmtp_mls::storage::consent_record::StoredConsentRecord; use xmtp_mls::storage::{EncryptedMessageStore, EncryptionKey, StorageOption}; use xmtp_mls::Client as MlsClient; pub type RustXmtpClient = MlsClient; +#[napi] +#[derive(Eq, Hash, PartialEq)] +pub enum NapiSignatureRequestType { + AddWallet, + CreateInbox, + RevokeWallet, + RevokeInstallations, +} + #[napi] pub struct NapiClient { inner_client: Arc, - signatures: HashMap>, + signature_requests: Arc>>, pub account_address: String, } @@ -70,19 +83,19 @@ pub async fn create_client( .history_sync_url(&url) .build() .await - .map_err(|e| Error::from_reason(format!("{}", e)))?, + .map_err(ErrorWrapper::from)?, None => ClientBuilder::new(identity_strategy) .api_client(api_client) .store(store) .build() .await - .map_err(|e| Error::from_reason(format!("{}", e)))?, + .map_err(ErrorWrapper::from)?, }; Ok(NapiClient { inner_client: Arc::new(xmtp_client), account_address, - signatures: HashMap::new(), + signature_requests: Arc::new(Mutex::new(HashMap::new())), }) } @@ -96,14 +109,14 @@ pub async fn get_inbox_id_for_address( let api_client = ApiClientWrapper::new( TonicApiClient::create(host.clone(), is_secure) .await - .map_err(|e| Error::from_reason(format!("{}", e)))?, + .map_err(ErrorWrapper::from)?, Retry::default(), ); let results = api_client .get_inbox_ids(vec![account_address.clone()]) .await - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; Ok(results.get(&account_address).cloned()) } @@ -125,7 +138,7 @@ impl NapiClient { #[napi] pub fn is_registered(&self) -> bool { - self.inner_client.identity().signature_request().is_none() + self.inner_client.identity().is_ready() } #[napi] @@ -139,145 +152,253 @@ impl NapiClient { .inner_client .can_message(account_addresses) .await - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; Ok(results) } #[napi] - pub fn add_ecdsa_signature(&mut self, signature_bytes: Uint8Array) -> Result<()> { + pub async fn register_identity(&self) -> Result<()> { if self.is_registered() { return Err(Error::from_reason( "An identity is already registered with this client", )); } - let signature_text = match self.signature_text() { - Some(text) => text, - None => return Err(Error::from_reason("No signature text found")), - }; + let mut signature_requests = self.signature_requests.lock().await; - let signature = Box::new(RecoverableEcdsaSignature::new( - signature_text, - signature_bytes.deref().to_vec(), - )); + let signature_request = signature_requests + .get(&NapiSignatureRequestType::CreateInbox) + .ok_or(Error::from_reason("No signature request found"))?; - self.signatures.insert( - MemberIdentifier::Address(self.account_address.clone().to_lowercase()), - signature, - ); + self + .inner_client + .register_identity(signature_request.clone()) + .await + .map_err(ErrorWrapper::from)?; + + signature_requests.remove(&NapiSignatureRequestType::CreateInbox); Ok(()) } #[napi] - pub fn add_scw_signature( - &mut self, - signature_bytes: Uint8Array, - chain_id: String, - account_address: String, - chain_rpc_url: String, - block_number: BigInt, - ) -> Result<()> { - if self.is_registered() { - return Err(Error::from_reason( - "An identity is already registered with this client", - )); - } - - let signature_text = match self.signature_text() { - Some(text) => text, - None => return Err(Error::from_reason("No signature text found")), + pub async fn create_inbox_signature_text(&self) -> Result> { + let signature_request = match self.inner_client.identity().signature_request() { + Some(signature_req) => signature_req, + // this should never happen since we're checking for it above in is_registered + None => return Err(Error::from_reason("No signature request found")), }; + let signature_text = signature_request.signature_text(); + let mut signature_requests = self.signature_requests.lock().await; - let account_id = AccountId::new(chain_id, account_address.clone()); + signature_requests.insert(NapiSignatureRequestType::CreateInbox, signature_request); - let signature = Box::new(SmartContractWalletSignature::new( - signature_text, - signature_bytes.deref().to_vec(), - account_id, - chain_rpc_url, - block_number.get_u64().1, - )); - - self.signatures.insert( - MemberIdentifier::Address(account_address.clone().to_lowercase()), - signature, - ); + Ok(Some(signature_text)) + } - Ok(()) + #[napi] + pub fn conversations(&self) -> NapiConversations { + NapiConversations::new(self.inner_client.clone()) } #[napi] - pub async fn register_identity(&self) -> Result<()> { - if self.is_registered() { - return Err(Error::from_reason( - "An identity is already registered with this client", - )); - } + pub async fn request_history_sync(&self) -> Result<()> { + let _ = self + .inner_client + .send_history_request() + .await + .map_err(ErrorWrapper::from); - if self.signatures.is_empty() { - return Err(Error::from_reason( - "No client signatures found, add at least 1 before registering", - )); - } + Ok(()) + } - let mut signature_request = match self.inner_client.identity().signature_request() { - Some(signature_req) => signature_req, - // this should never happen since we're checking for it above in is_registered - None => return Err(Error::from_reason("No signature request found")), - }; + #[napi] + pub async fn find_inbox_id_by_address(&self, address: String) -> Result> { + let inbox_id = self + .inner_client + .find_inbox_id_from_address(address) + .await + .map_err(ErrorWrapper::from)?; - // apply added signatures to the signature request - for signature in self.signatures.values() { - signature_request - .add_signature(signature.clone()) - .await - .map_err(|e| Error::from_reason(format!("{}", e)))?; - } + Ok(inbox_id) + } - self + /** + * Get the client's inbox state. + * + * If `refresh_from_network` is true, the client will go to the network first to refresh the state. + * Otherwise, the state will be read from the local database. + */ + #[napi] + pub async fn inbox_state(&self, refresh_from_network: bool) -> Result { + let state = self .inner_client - .register_identity(signature_request) + .inbox_state(refresh_from_network) .await - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; + Ok(state.into()) + } - Ok(()) + #[napi] + pub async fn get_latest_inbox_state(&self, inbox_id: String) -> Result { + let conn = self + .inner_client + .store() + .conn() + .map_err(ErrorWrapper::from)?; + let state = self + .inner_client + .get_latest_association_state(&conn, &inbox_id) + .await + .map_err(ErrorWrapper::from)?; + Ok(state.into()) } #[napi] - pub fn signature_text(&self) -> Option { - self + pub async fn add_wallet_signature_text( + &self, + existing_wallet_address: String, + new_wallet_address: String, + ) -> Result { + let signature_request = self .inner_client - .identity() - .signature_request() - .map(|signature_req| signature_req.signature_text()) + .associate_wallet( + existing_wallet_address.to_lowercase(), + new_wallet_address.to_lowercase(), + ) + .map_err(ErrorWrapper::from)?; + let signature_text = signature_request.signature_text(); + let mut signature_requests = self.signature_requests.lock().await; + + signature_requests.insert(NapiSignatureRequestType::AddWallet, signature_request); + + Ok(signature_text) } #[napi] - pub fn conversations(&self) -> NapiConversations { - NapiConversations::new(self.inner_client.clone()) + pub async fn revoke_wallet_signature_text(&self, wallet_address: String) -> Result { + let signature_request = self + .inner_client + .revoke_wallets(vec![wallet_address.to_lowercase()]) + .await + .map_err(ErrorWrapper::from)?; + let signature_text = signature_request.signature_text(); + let mut signature_requests = self.signature_requests.lock().await; + + signature_requests.insert(NapiSignatureRequestType::RevokeWallet, signature_request); + + Ok(signature_text) } #[napi] - pub async fn request_history_sync(&self) -> Result<()> { - let _ = self + pub async fn revoke_installations_signature_text(&self) -> Result { + let installation_id = self.inner_client.installation_public_key(); + let inbox_state = self .inner_client - .send_history_request() + .inbox_state(true) + .await + .map_err(ErrorWrapper::from)?; + let other_installation_ids = inbox_state + .installation_ids() + .into_iter() + .filter(|id| id != &installation_id) + .collect(); + let signature_request = self + .inner_client + .revoke_installations(other_installation_ids) .await - .map_err(|e| Error::from_reason(format!("{}", e))); + .map_err(ErrorWrapper::from)?; + let signature_text = signature_request.signature_text(); + let mut signature_requests = self.signature_requests.lock().await; + + signature_requests.insert( + NapiSignatureRequestType::RevokeInstallations, + signature_request, + ); + + Ok(signature_text) + } + + #[napi] + pub async fn add_signature( + &self, + signature_type: NapiSignatureRequestType, + signature_bytes: Uint8Array, + ) -> Result<()> { + let mut signature_requests = self.signature_requests.lock().await; + + if let Some(signature_request) = signature_requests.get_mut(&signature_type) { + let signature = UnverifiedSignature::new_recoverable_ecdsa(signature_bytes.deref().to_vec()); + + signature_request + .add_signature( + signature, + self + .inner_client + .smart_contract_signature_verifier() + .as_ref(), + ) + .await + .map_err(ErrorWrapper::from)?; + } else { + return Err(Error::from_reason("Signature request not found")); + } Ok(()) } #[napi] - pub async fn find_inbox_id_by_address(&self, address: String) -> Result> { - let inbox_id = self - .inner_client - .find_inbox_id_from_address(address) + pub async fn apply_signature_requests(&self) -> Result<()> { + let mut signature_requests = self.signature_requests.lock().await; + + let request_types: Vec = signature_requests.keys().cloned().collect(); + for signature_request_type in request_types { + // ignore the create inbox request since it's applied with register_identity + if signature_request_type == NapiSignatureRequestType::CreateInbox { + continue; + } + + if let Some(signature_request) = signature_requests.get(&signature_request_type) { + self + .inner_client + .apply_signature_request(signature_request.clone()) + .await + .map_err(ErrorWrapper::from)?; + + // remove the signature request after applying it + signature_requests.remove(&signature_request_type); + } + } + + Ok(()) + } + + #[napi] + pub async fn set_consent_states(&self, records: Vec) -> Result<()> { + let inner = self.inner_client.as_ref(); + let stored_records: Vec = + records.into_iter().map(StoredConsentRecord::from).collect(); + + inner + .set_consent_states(stored_records) .await - .map_err(|e| Error::from_reason(format!("{}", e)))?; + .map_err(ErrorWrapper::from)?; + Ok(()) + } - Ok(inbox_id) + #[napi] + pub async fn get_consent_state( + &self, + entity_type: NapiConsentEntityType, + entity: String, + ) -> Result { + let inner = self.inner_client.as_ref(); + let result = inner + .get_consent_state(entity_type.into(), entity) + .await + .map_err(ErrorWrapper::from)?; + + Ok(result.into()) } } diff --git a/bindings_node/src/streams.rs b/bindings_node/src/streams.rs index c12301239..cc00d3b6d 100644 --- a/bindings_node/src/streams.rs +++ b/bindings_node/src/streams.rs @@ -60,7 +60,7 @@ impl NapiStreamCloser { Err(e) => Err(Error::from_reason(format!("error joining task {}", e))), } } else { - log::warn!("subscription already closed"); + tracing::warn!("subscription already closed"); Ok(()) } } diff --git a/bindings_node/test/Client.test.ts b/bindings_node/test/Client.test.ts index 6b97f8c80..9144f8d08 100644 --- a/bindings_node/test/Client.test.ts +++ b/bindings_node/test/Client.test.ts @@ -1,5 +1,12 @@ +import { v4 } from 'uuid' +import { toBytes } from 'viem' import { describe, expect, it } from 'vitest' import { createClient, createRegisteredClient, createUser } from '@test/helpers' +import { + NapiConsentEntityType, + NapiConsentState, + NapiSignatureRequestType, +} from '../dist' describe('Client', () => { it('should not be registered at first', async () => { @@ -8,7 +15,7 @@ describe('Client', () => { expect(client.isRegistered()).toBe(false) }) - it('should be registered aafter registration', async () => { + it('should be registered after registration', async () => { const user = createUser() // must create 2 clients to get the expected value // this is currently a limitation in the rust implementation as the @@ -31,4 +38,187 @@ describe('Client', () => { const inboxId = await client.findInboxIdByAddress(user.account.address) expect(inboxId).toBe(client.inboxId()) }) + + it('should return the correct inbox state', async () => { + const user = createUser() + const client = await createRegisteredClient(user) + const inboxState = await client.inboxState(false) + expect(inboxState.inboxId).toBe(client.inboxId()) + expect(inboxState.installations.length).toBe(1) + expect(inboxState.installations[0].id).toBe(client.installationId()) + expect(inboxState.accountAddresses).toEqual([ + user.account.address.toLowerCase(), + ]) + expect(inboxState.recoveryAddress).toBe(user.account.address.toLowerCase()) + + const user2 = createUser() + const client2 = await createClient(user2) + const inboxState2 = await client2.getLatestInboxState(client.inboxId()) + expect(inboxState2.inboxId).toBe(client.inboxId()) + expect(inboxState.installations.length).toBe(1) + expect(inboxState.installations[0].id).toBe(client.installationId()) + expect(inboxState2.accountAddresses).toEqual([ + user.account.address.toLowerCase(), + ]) + expect(inboxState2.recoveryAddress).toBe(user.account.address.toLowerCase()) + }) + + it('should add a wallet association to the client', async () => { + const user = createUser() + const user2 = createUser() + const client = await createRegisteredClient(user) + const signatureText = await client.addWalletSignatureText( + user.account.address, + user2.account.address + ) + expect(signatureText).toBeDefined() + + // sign message + const signature = await user.wallet.signMessage({ + message: signatureText, + }) + const signature2 = await user2.wallet.signMessage({ + message: signatureText, + }) + + await client.addSignature( + NapiSignatureRequestType.AddWallet, + toBytes(signature) + ) + await client.addSignature( + NapiSignatureRequestType.AddWallet, + toBytes(signature2) + ) + await client.applySignatureRequests() + const inboxState = await client.inboxState(false) + expect(inboxState.accountAddresses.length).toEqual(2) + expect(inboxState.accountAddresses).toContain( + user.account.address.toLowerCase() + ) + expect(inboxState.accountAddresses).toContain( + user2.account.address.toLowerCase() + ) + }) + + it('should revoke a wallet association from the client', async () => { + const user = createUser() + const user2 = createUser() + const client = await createRegisteredClient(user) + const signatureText = await client.addWalletSignatureText( + user.account.address, + user2.account.address + ) + expect(signatureText).toBeDefined() + + // sign message + const signature = await user.wallet.signMessage({ + message: signatureText, + }) + const signature2 = await user2.wallet.signMessage({ + message: signatureText, + }) + + await client.addSignature( + NapiSignatureRequestType.AddWallet, + toBytes(signature) + ) + await client.addSignature( + NapiSignatureRequestType.AddWallet, + toBytes(signature2) + ) + await client.applySignatureRequests() + + const signatureText2 = await client.revokeWalletSignatureText( + user2.account.address + ) + expect(signatureText2).toBeDefined() + + // sign message + const signature3 = await user.wallet.signMessage({ + message: signatureText2, + }) + + await client.addSignature( + NapiSignatureRequestType.RevokeWallet, + toBytes(signature3) + ) + await client.applySignatureRequests() + const inboxState = await client.inboxState(false) + expect(inboxState.accountAddresses).toEqual([ + user.account.address.toLowerCase(), + ]) + }) + + it('should revoke all installations', async () => { + const user = createUser() + + const client = await createRegisteredClient(user) + user.uuid = v4() + const client2 = await createRegisteredClient(user) + user.uuid = v4() + const client3 = await createRegisteredClient(user) + + const inboxState = await client3.inboxState(true) + expect(inboxState.installations.length).toBe(3) + + const installationIds = inboxState.installations.map((i) => i.id) + expect(installationIds).toContain(client.installationId()) + expect(installationIds).toContain(client2.installationId()) + expect(installationIds).toContain(client3.installationId()) + + const signatureText = await client3.revokeInstallationsSignatureText() + expect(signatureText).toBeDefined() + + // sign message + const signature = await user.wallet.signMessage({ + message: signatureText, + }) + + await client3.addSignature( + NapiSignatureRequestType.RevokeInstallations, + toBytes(signature) + ) + await client3.applySignatureRequests() + const inboxState2 = await client3.inboxState(true) + + expect(inboxState2.installations.length).toBe(1) + expect(inboxState2.installations[0].id).toBe(client3.installationId()) + }) + + it('should manage consent states', async () => { + const user1 = createUser() + const user2 = createUser() + const client1 = await createRegisteredClient(user1) + const client2 = await createRegisteredClient(user2) + const group = await client1 + .conversations() + .createGroup([user2.account.address]) + + await client2.conversations().sync() + const group2 = client2.conversations().findGroupById(group.id()) + + expect( + await client2.getConsentState(NapiConsentEntityType.GroupId, group2.id()) + ).toBe(NapiConsentState.Unknown) + + await client2.setConsentStates([ + { + entityType: NapiConsentEntityType.GroupId, + entity: group2.id(), + state: NapiConsentState.Allowed, + }, + ]) + + expect( + await client2.getConsentState(NapiConsentEntityType.GroupId, group2.id()) + ).toBe(NapiConsentState.Allowed) + + expect(group2.consentState()).toBe(NapiConsentState.Allowed) + + group2.updateConsentState(NapiConsentState.Denied) + + expect( + await client2.getConsentState(NapiConsentEntityType.GroupId, group2.id()) + ).toBe(NapiConsentState.Denied) + }) }) diff --git a/bindings_node/test/Conversations.test.ts b/bindings_node/test/Conversations.test.ts index e9e3c5c1d..00edabdca 100644 --- a/bindings_node/test/Conversations.test.ts +++ b/bindings_node/test/Conversations.test.ts @@ -5,14 +5,19 @@ import { createUser, encodeTextMessage, } from '@test/helpers' -import { NapiGroup, NapiGroupPermissionsOptions, NapiMessage } from '../dist' +import { + NapiConsentState, + NapiGroup, + NapiGroupPermissionsOptions, + NapiMessage, +} from '../dist' describe('Conversations', () => { it('should not have initial conversations', async () => { const user = createUser() const client = await createRegisteredClient(user) - const conversations = client.conversations().list() - expect((await conversations).length).toBe(0) + const conversations = await client.conversations().list() + expect(conversations.length).toBe(0) }) it('should create a new group', async () => { @@ -43,7 +48,7 @@ describe('Conversations', () => { }) expect(group.addedByInboxId()).toBe(client1.inboxId()) expect(group.findMessages().length).toBe(1) - const members = group.listMembers() + const members = await group.listMembers() expect(members.length).toBe(2) const memberInboxIds = members.map((member) => member.inboxId) expect(memberInboxIds).toContain(client1.inboxId()) @@ -51,6 +56,8 @@ describe('Conversations', () => { expect(group.groupMetadata().conversationType()).toBe('group') expect(group.groupMetadata().creatorInboxId()).toBe(client1.inboxId()) + expect(group.consentState()).toBe(NapiConsentState.Allowed) + const group1 = await client1.conversations().list() expect(group1.length).toBe(1) expect(group1[0].id).toBe(group.id) @@ -278,4 +285,22 @@ describe('Conversations', () => { asyncStream.stop() stream.end() }) + + it('should manage group consent state', async () => { + const user1 = createUser() + const user2 = createUser() + const client1 = await createRegisteredClient(user1) + const client2 = await createRegisteredClient(user2) + const group = await client1 + .conversations() + .createGroup([user2.account.address]) + expect(group).toBeDefined() + + await client2.conversations().sync() + const group2 = client2.conversations().findGroupById(group.id()) + expect(group2).toBeDefined() + expect(group2.consentState()).toBe(NapiConsentState.Unknown) + await group2.send(encodeTextMessage('gm!')) + expect(group2.consentState()).toBe(NapiConsentState.Allowed) + }) }) diff --git a/bindings_node/test/helpers.ts b/bindings_node/test/helpers.ts index e9336a844..ca96b8721 100644 --- a/bindings_node/test/helpers.ts +++ b/bindings_node/test/helpers.ts @@ -1,5 +1,6 @@ import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' +import { v4 } from 'uuid' import { createWalletClient, http, toBytes } from 'viem' import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts' import { sepolia } from 'viem/chains' @@ -7,6 +8,7 @@ import { createClient as create, generateInboxId, getInboxIdForAddress, + NapiSignatureRequestType, } from '../dist/index' const __dirname = dirname(fileURLToPath(import.meta.url)) @@ -23,13 +25,14 @@ export const createUser = () => { chain: sepolia, transport: http(), }), + uuid: v4(), } } export type User = ReturnType export const createClient = async (user: User) => { - const dbPath = join(__dirname, `${user.account.address}.db3`) + const dbPath = join(__dirname, `${user.uuid}.db3`) const inboxId = (await getInboxIdForAddress(TEST_API_URL, false, user.account.address)) || generateInboxId(user.account.address) @@ -39,12 +42,15 @@ export const createClient = async (user: User) => { export const createRegisteredClient = async (user: User) => { const client = await createClient(user) if (!client.isRegistered()) { - const signatureText = client.signatureText() + const signatureText = await client.createInboxSignatureText() if (signatureText) { const signature = await user.wallet.signMessage({ message: signatureText, }) - client.addEcdsaSignature(toBytes(signature)) + await client.addSignature( + NapiSignatureRequestType.CreateInbox, + toBytes(signature) + ) } await client.registerIdentity() } diff --git a/bindings_node/yarn.lock b/bindings_node/yarn.lock index a8913e6c3..be8e242b9 100644 --- a/bindings_node/yarn.lock +++ b/bindings_node/yarn.lock @@ -1442,6 +1442,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^10": + version: 10.0.0 + resolution: "@types/uuid@npm:10.0.0" + checksum: 10/e3958f8b0fe551c86c14431f5940c3470127293280830684154b91dc7eb3514aeb79fe3216968833cf79d4d1c67f580f054b5be2cd562bebf4f728913e73e944 + languageName: node + linkType: hard + "@vitest/expect@npm:1.6.0": version: 1.6.0 resolution: "@vitest/expect@npm:1.6.0" @@ -1503,9 +1510,11 @@ __metadata: "@ianvs/prettier-plugin-sort-imports": "npm:^4.2.1" "@napi-rs/cli": "npm:^3.0.0-alpha.55" "@types/node": "npm:^20.14.2" + "@types/uuid": "npm:^10" prettier: "npm:^3.3.2" prettier-plugin-packagejson: "npm:^2.5.0" typescript: "npm:^5.4.5" + uuid: "npm:^10.0.0" viem: "npm:^2.11.1" vite: "npm:^5.2.13" vite-tsconfig-paths: "npm:^4.3.2" @@ -3882,6 +3891,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "uuid@npm:10.0.0" + bin: + uuid: dist/bin/uuid + checksum: 10/35aa60614811a201ff90f8ca5e9ecb7076a75c3821e17f0f5ff72d44e36c2d35fcbc2ceee9c4ac7317f4cc41895da30e74f3885e30313bee48fda6338f250538 + languageName: node + linkType: hard + "viem@npm:^2.11.1": version: 2.11.1 resolution: "viem@npm:2.11.1" diff --git a/bindings_wasm/Cargo.toml b/bindings_wasm/Cargo.toml index eeb652421..d8efd3557 100644 --- a/bindings_wasm/Cargo.toml +++ b/bindings_wasm/Cargo.toml @@ -15,7 +15,7 @@ wasm-bindgen-futures = "0.4.41" xmtp_api_http = { path = "../xmtp_api_http" } xmtp_cryptography = { path = "../xmtp_cryptography" } xmtp_id = { path = "../xmtp_id" } -xmtp_mls = { path = "../xmtp_mls", features = [] } +xmtp_mls = { path = "../xmtp_mls", features = ["message-history"] } xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } [dev-dependencies] diff --git a/bindings_wasm/src/mls_client.rs b/bindings_wasm/src/mls_client.rs index 2afad6c74..eae529139 100644 --- a/bindings_wasm/src/mls_client.rs +++ b/bindings_wasm/src/mls_client.rs @@ -5,9 +5,9 @@ use wasm_bindgen::prelude::{wasm_bindgen, JsError}; use wasm_bindgen::JsValue; use xmtp_api_http::XmtpHttpApiClient; use xmtp_cryptography::signature::ed25519_public_key_to_address; -use xmtp_id::associations::generate_inbox_id as xmtp_id_generate_inbox_id; use xmtp_id::associations::{ - AccountId, MemberIdentifier, RecoverableEcdsaSignature, Signature, SmartContractWalletSignature, + generate_inbox_id as xmtp_id_generate_inbox_id, unverified::UnverifiedSignature, AccountId, + MemberIdentifier, }; use xmtp_mls::api::ApiClientWrapper; use xmtp_mls::builder::ClientBuilder; @@ -22,7 +22,7 @@ pub type RustXmtpClient = MlsClient; pub struct WasmClient { account_address: String, inner_client: Arc, - signatures: HashMap>, + signatures: HashMap, } #[wasm_bindgen] @@ -148,15 +148,7 @@ impl WasmClient { )); } - let signature_text = match self.signature_text() { - Some(text) => text, - None => return Err(JsError::new("No signature text found")), - }; - - let signature = Box::new(RecoverableEcdsaSignature::new( - signature_text.into(), - signature_bytes.to_vec(), - )); + let signature = UnverifiedSignature::new_recoverable_ecdsa(signature_bytes.to_vec()); self.signatures.insert( MemberIdentifier::Address(self.account_address.clone().to_lowercase()), @@ -170,9 +162,8 @@ impl WasmClient { pub fn add_scw_signature( &mut self, signature_bytes: Uint8Array, - chain_id: String, + chain_id: u64, account_address: String, - chain_rpc_url: String, block_number: u64, ) -> Result<(), JsError> { if self.is_registered() { @@ -181,20 +172,13 @@ impl WasmClient { )); } - let signature_text = match self.signature_text() { - Some(text) => text, - None => return Err(JsError::new("No signature text found")), - }; - - let account_id = AccountId::new(chain_id, account_address.clone()); + let account_id = AccountId::new_evm(chain_id, account_address.clone()); - let signature = Box::new(SmartContractWalletSignature::new( - signature_text, + let signature = UnverifiedSignature::new_smart_contract_wallet( signature_bytes.to_vec(), account_id, - chain_rpc_url, block_number, - )); + ); self.signatures.insert( MemberIdentifier::Address(account_address.clone().to_lowercase()), @@ -227,7 +211,13 @@ impl WasmClient { // apply added signatures to the signature request for signature in self.signatures.values() { signature_request - .add_signature(signature.clone()) + .add_signature( + signature.clone(), + self + .inner_client + .smart_contract_signature_verifier() + .as_ref(), + ) .await .map_err(|e| JsError::new(format!("{}", e).as_str()))?; } diff --git a/dev/validation_service/Dockerfile b/dev/validation_service/Dockerfile index fbb8cf630..6549ab50c 100644 --- a/dev/validation_service/Dockerfile +++ b/dev/validation_service/Dockerfile @@ -4,7 +4,7 @@ COPY . . RUN cargo build --release --package mls_validation_service FROM debian:bullseye-slim -RUN apt-get update && apt-get install -y sqlite3 +RUN apt-get update && apt-get install -y sqlite3 curl COPY --from=builder /code/target/release/mls-validation-service /usr/local/bin/mls-validation-service ENV RUST_LOG=info CMD ["mls-validation-service"] \ No newline at end of file diff --git a/examples/cli/Cargo.toml b/examples/cli/Cargo.toml index 861e168a0..f53c4b81e 100644 --- a/examples/cli/Cargo.toml +++ b/examples/cli/Cargo.toml @@ -15,12 +15,11 @@ path = "cli-client.rs" [dependencies] clap = { version = "4.4.6", features = ["derive"] } ethers = "2.0.4" -ethers-core = "2.0.4" femme = "2.2.1" -futures = "0.3.28" +futures.workspace = true hex = "0.4.3" kv-log-macro = "1.0.7" -log = { workspace = true, features = [ +log = { version = "0.4", features = [ "kv_unstable", "std", "kv_unstable_serde", @@ -31,10 +30,8 @@ serde_json.workspace = true thiserror.workspace = true timeago = "0.4.1" tokio = "1.28.1" -tokio-stream = "0.1.15" -url = "2.3.1" xmtp_api_grpc = { path = "../../xmtp_api_grpc" } xmtp_cryptography = { path = "../../xmtp_cryptography" } xmtp_id = { path = "../../xmtp_id" } -xmtp_mls = { path = "../../xmtp_mls", features = ["native"] } +xmtp_mls = { path = "../../xmtp_mls", features = ["native", "message-history"] } xmtp_proto = { path = "../../xmtp_proto", features = ["proto_full"] } diff --git a/examples/cli/cli-client.rs b/examples/cli/cli-client.rs index 2319916ec..9125e2ff6 100755 --- a/examples/cli/cli-client.rs +++ b/examples/cli/cli-client.rs @@ -15,9 +15,11 @@ use std::{fs, path::PathBuf, time::Duration}; use clap::{Parser, Subcommand, ValueEnum}; use ethers::signers::{coins_bip39::English, LocalWallet, MnemonicBuilder}; +use futures::future::join_all; use kv_log_macro::{error, info}; use prost::Message; -use xmtp_id::associations::RecoverableEcdsaSignature; +use xmtp_id::associations::unverified::{UnverifiedRecoverableEcdsaSignature, UnverifiedSignature}; +use xmtp_mls::client::FindGroupParams; use xmtp_mls::groups::message_history::MessageHistoryContent; use xmtp_mls::storage::group_message::GroupMessageKind; @@ -208,15 +210,17 @@ async fn main() { // recv(&client).await.unwrap(); let group_list = client - .find_groups(None, None, None, None) + .find_groups(FindGroupParams::default()) .expect("failed to list groups"); for group in group_list.iter() { group.sync(&client).await.expect("error syncing group"); } + let serializable_group_list = group_list .iter() - .map(Into::into) - .collect::>(); + .map(|g| SerializableGroup::from(g, &client)) + .collect::>(); + let serializable_group_list = join_all(serializable_group_list).await; info!( "group members", @@ -337,7 +341,7 @@ async fn main() { .group(hex::decode(group_id).expect("bad group id")) .expect("group not found"); group.sync(&client).await.unwrap(); - let serializable: SerializableGroup = group.into(); + let serializable = SerializableGroup::from(group, &client).await; info!("Group {}", group_id, { command_output: true, group_id: group_id, group_info: make_value(&serializable) }) } Commands::RequestHistorySync {} => { @@ -457,14 +461,17 @@ async fn register(cli: &Cli, maybe_seed_phrase: Option) -> Result<(), Cl ) .await?; let mut signature_request = client.identity().signature_request().unwrap(); - let signature = RecoverableEcdsaSignature::new( - signature_request.signature_text(), - w.sign(signature_request.signature_text().as_str()) - .unwrap() - .into(), - ); + let sig_bytes: Vec = w + .sign(signature_request.signature_text().as_str()) + .unwrap() + .into(); + let signature = + UnverifiedSignature::RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature::new(sig_bytes)); signature_request - .add_signature(Box::new(signature)) + .add_signature( + signature, + client.smart_contract_signature_verifier().as_ref(), + ) .await .unwrap(); @@ -509,7 +516,7 @@ fn format_messages( if text.is_none() { continue; } - // TODO:nm use inbox ID + let sender = if msg.sender_inbox_id == my_account_address { "Me".to_string() } else { diff --git a/examples/cli/serializable.rs b/examples/cli/serializable.rs index 34f4d11c8..9153e0345 100644 --- a/examples/cli/serializable.rs +++ b/examples/cli/serializable.rs @@ -4,6 +4,7 @@ use xmtp_mls::{ codecs::{text::TextCodec, ContentCodec}, groups::MlsGroup, storage::group_message::StoredGroupMessage, + XmtpApi, }; use xmtp_proto::xmtp::mls::message_contents::EncodedContent; @@ -20,11 +21,15 @@ pub struct SerializableGroup { pub metadata: SerializableGroupMetadata, } -impl<'a> From<&'a MlsGroup> for SerializableGroup { - fn from(group: &'a MlsGroup) -> Self { +impl SerializableGroup { + pub async fn from( + group: &MlsGroup, + client: &xmtp_mls::Client, + ) -> Self { let group_id = hex::encode(group.group_id.clone()); let members = group - .members() + .members(client) + .await .expect("could not load members") .into_iter() .map(|m| m.inbox_id) diff --git a/mls_validation_service/Cargo.toml b/mls_validation_service/Cargo.toml index 6da9cbdb5..92c33927c 100644 --- a/mls_validation_service/Cargo.toml +++ b/mls_validation_service/Cargo.toml @@ -10,10 +10,9 @@ path = "src/main.rs" [dependencies] clap = { version = "4.4.6", features = ["derive"] } ed25519-dalek = { workspace = true, features = ["digest"] } -env_logger = "0.11" +ethers = { workspace = true } futures = { workspace = true } hex = { workspace = true } -log = { workspace = true } openmls = { workspace = true } openmls_rust_crypto = { workspace = true } openmls_traits = { workspace = true } @@ -22,13 +21,13 @@ serde = { workspace = true } thiserror.workspace = true tokio = { workspace = true, features = ["full"] } tonic = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +tracing.workspace = true warp = "0.3.6" +xmtp_cryptography = { path = "../xmtp_cryptography" } xmtp_id.workspace = true xmtp_mls.workspace = true -xmtp_proto = { path = "../xmtp_proto", features = [ - "proto_full", - "convert", -] } +xmtp_proto = { path = "../xmtp_proto", features = ["proto_full", "convert"] } [dev-dependencies] anyhow.workspace = true diff --git a/mls_validation_service/src/handlers.rs b/mls_validation_service/src/handlers.rs index f32579016..4f2cc350a 100644 --- a/mls_validation_service/src/handlers.rs +++ b/mls_validation_service/src/handlers.rs @@ -1,31 +1,42 @@ -use futures::future::join_all; -use openmls::{ - credentials::BasicCredential, - prelude::{tls_codec::Deserialize, MlsMessageIn, ProtocolMessage}, -}; +use ethers::types::{BlockNumber, U64}; +use futures::future::{join_all, try_join_all}; +use openmls::prelude::{tls_codec::Deserialize, MlsMessageIn, ProtocolMessage}; use openmls_rust_crypto::RustCrypto; use tonic::{Request, Response, Status}; -use xmtp_id::associations::{ - self, try_map_vec, AssociationError, DeserializationError, MemberIdentifier, +use xmtp_id::{ + associations::{ + self, try_map_vec, unverified::UnverifiedIdentityUpdate, AssociationError, + DeserializationError, SignatureError, + }, + scw_verifier::SmartContractSignatureVerifier, }; use xmtp_mls::{ utils::id::serialize_group_id, - verified_key_package::VerifiedKeyPackage, verified_key_package_v2::{KeyPackageVerificationError, VerifiedKeyPackageV2}, }; use xmtp_proto::xmtp::{ - identity::associations::IdentityUpdate as IdentityUpdateProto, + identity::{ + api::v1::{ + verify_smart_contract_wallet_signatures_response::ValidationResponse as VerifySmartContractWalletSignaturesResponseValidationResponse, + UnverifiedSmartContractWalletSignature, VerifySmartContractWalletSignaturesRequest, + VerifySmartContractWalletSignaturesResponse, + }, + associations::IdentityUpdate as IdentityUpdateProto, + }, mls_validation::v1::{ validate_group_messages_response::ValidationResponse as ValidateGroupMessageValidationResponse, validate_inbox_id_key_packages_response::Response as ValidateInboxIdKeyPackageResponse, - validate_inbox_ids_request::ValidationRequest as InboxIdValidationRequest, - validate_inbox_ids_response::ValidationResponse as InboxIdValidationResponse, - validate_key_packages_response::ValidationResponse as ValidateKeyPackageValidationResponse, - validation_api_server::ValidationApi, GetAssociationStateRequest, - GetAssociationStateResponse, ValidateGroupMessagesRequest, ValidateGroupMessagesResponse, - ValidateInboxIdKeyPackagesResponse, ValidateInboxIdsRequest, ValidateInboxIdsResponse, - ValidateKeyPackagesRequest, ValidateKeyPackagesResponse, + validation_api_server::ValidationApi, + GetAssociationStateRequest, + GetAssociationStateResponse, + ValidateGroupMessagesRequest, + ValidateGroupMessagesResponse, + ValidateInboxIdKeyPackagesResponse, + ValidateInboxIdsRequest, + ValidateInboxIdsResponse, + ValidateKeyPackagesRequest, + ValidateKeyPackagesResponse, // VerifySmartContractWalletSignaturesRequest, VerifySmartContractWalletSignaturesResponse, }, }; @@ -35,6 +46,8 @@ pub enum GrpcServerError { Deserialization(#[from] DeserializationError), #[error(transparent)] Association(#[from] AssociationError), + #[error(transparent)] + Signature(#[from] SignatureError), } impl From for Status { @@ -43,44 +56,34 @@ impl From for Status { } } -#[derive(Debug, Default)] -pub struct ValidationService {} +pub struct ValidationService { + pub(crate) scw_verifier: Box, +} + +impl ValidationService { + pub fn new(scw_verifier: impl SmartContractSignatureVerifier) -> Self { + Self { + scw_verifier: Box::new(scw_verifier), + } + } +} #[tonic::async_trait] impl ValidationApi for ValidationService { - async fn validate_key_packages( + async fn validate_inbox_ids( &self, - request: Request, - ) -> Result, Status> { - let out: Vec = request - .into_inner() - .key_packages - .into_iter() - .map( - |kp| match validate_key_package(kp.key_package_bytes_tls_serialized) { - Ok(res) => ValidateKeyPackageValidationResponse { - is_ok: true, - error_message: "".to_string(), - installation_id: res.installation_id, - account_address: res.account_address, - credential_identity_bytes: res.credential_identity_bytes, - expiration: res.expiration, - }, - Err(e) => ValidateKeyPackageValidationResponse { - is_ok: false, - error_message: e, - installation_id: vec![], - account_address: "".to_string(), - credential_identity_bytes: vec![], - expiration: 0, - }, - }, - ) - .collect(); + _request: tonic::Request, + ) -> Result, tonic::Status> { + // Stubbed for v2 nodes + unimplemented!() + } - Ok(Response::new(ValidateKeyPackagesResponse { - responses: out, - })) + async fn validate_key_packages( + &self, + _request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + // Stubbed out for v2 nodes + unimplemented!() } async fn validate_group_messages( @@ -121,12 +124,21 @@ impl ValidationApi for ValidationService { new_updates, } = request.into_inner(); - get_association_state(old_updates, new_updates) + get_association_state(old_updates, new_updates, self.scw_verifier.as_ref()) .await .map(Response::new) .map_err(Into::into) } + async fn verify_smart_contract_wallet_signatures( + &self, + request: Request, + ) -> Result, Status> { + let VerifySmartContractWalletSignaturesRequest { signatures } = request.into_inner(); + + verify_smart_contract_wallet_signatures(signatures, self.scw_verifier.as_ref()).await + } + async fn validate_inbox_id_key_packages( &self, request: Request, @@ -139,7 +151,7 @@ impl ValidationApi for ValidationService { .map(validate_inbox_id_key_package) .collect(); - let responses: Vec = join_all(responses) + let responses: Vec<_> = join_all(responses) .await .into_iter() .map(|res| res.map_err(ValidateInboxIdKeyPackageResponse::from)) @@ -150,23 +162,6 @@ impl ValidationApi for ValidationService { responses, })) } - - async fn validate_inbox_ids( - &self, - request: Request, - ) -> Result, Status> { - let ValidateInboxIdsRequest { requests } = request.into_inner(); - let responses: Vec<_> = requests.into_iter().map(validate_inbox_id).collect(); - - let responses: Vec = join_all(responses) - .await - .into_iter() - .map(|res| res.map_err(InboxIdValidationResponse::from)) - .map(|r| r.unwrap_or_else(|e| e)) - .collect(); - - Ok(Response::new(ValidateInboxIdsResponse { responses })) - } } #[derive(thiserror::Error, Debug)] @@ -203,132 +198,91 @@ async fn validate_inbox_id_key_package( }) } -/// Error type for inbox ID validation -/// Each variant requires carrying the ID that failed to validate -/// The error variant itself becomes the failed version of `InboxIdValidationResponse` but allows -/// us to write normal rust in `validate_inbox_id` -#[derive(thiserror::Error, Debug)] -enum InboxIdValidationError { - #[error("Inbox ID {id} failed to validate")] - Deserialization { - id: String, - source: DeserializationError, - }, - #[error("Valid association state could not be found for inbox {id}, {source}")] - Association { - id: String, - source: AssociationError, - }, - #[error("Missing Credential")] - MissingCredential, - #[error("Inbox {id} is not associated with member {member}")] - MemberNotAssociated { - id: String, - member: MemberIdentifier, - }, - #[error( - "Given Inbox Id, {credential_inbox_id} does not match resulting inbox id, {state_inbox_id}" - )] - InboxIdDoesNotMatch { - credential_inbox_id: String, - state_inbox_id: String, - }, -} - -impl InboxIdValidationError { - pub fn inbox_id(&self) -> String { - match self { - InboxIdValidationError::Deserialization { id, .. } => id.clone(), - InboxIdValidationError::MissingCredential => "null".to_string(), - InboxIdValidationError::Association { id, .. } => id.clone(), - InboxIdValidationError::MemberNotAssociated { id, .. } => id.clone(), - InboxIdValidationError::InboxIdDoesNotMatch { - credential_inbox_id, - .. - } => credential_inbox_id.clone(), - } - } -} - -impl From for InboxIdValidationResponse { - fn from(err: InboxIdValidationError) -> Self { - InboxIdValidationResponse { - is_ok: false, - error_message: err.to_string(), - inbox_id: err.inbox_id(), - } - } -} +async fn verify_smart_contract_wallet_signatures( + signatures: Vec, + scw_verifier: &dyn SmartContractSignatureVerifier, +) -> Result, Status> { + let mut responses = vec![]; + for request in signatures { + let handle = async move { + let Some(signature) = request.scw_signature else { + return Ok::(false); + }; + + let account_id = signature.account_id.try_into().map_err(|_e| { + GrpcServerError::Deserialization(DeserializationError::InvalidAccountId) + })?; + + let valid = scw_verifier + .is_valid_signature( + account_id, + request.hash.try_into().map_err(|_| { + GrpcServerError::Deserialization(DeserializationError::InvalidHash) + })?, + signature.signature.into(), + Some(BlockNumber::Number(U64::from(signature.block_number))), + ) + .await + .map_err(|e| GrpcServerError::Signature(SignatureError::VerifierError(e)))?; + + Ok(valid) + }; -async fn validate_inbox_id( - request: InboxIdValidationRequest, -) -> Result { - let InboxIdValidationRequest { - credential, - installation_public_key, - identity_updates, - } = request; - - if credential.is_none() { - return Err(InboxIdValidationError::MissingCredential); + responses.push(handle); } - let inbox_id = credential.expect("checked for empty credential").inbox_id; - - let state = associations::get_state(try_map_vec(identity_updates).map_err(|e| { - InboxIdValidationError::Deserialization { - source: e, - id: inbox_id.clone(), - } - })?) - .await - .map_err(|e| InboxIdValidationError::Association { - source: e, - id: inbox_id.clone(), - })?; - - // this is defensive and should not happen. - // The only way an inbox id is different is if xmtp-node-go hands over identity updates with a different inbox id. - // which is a bug. - if state.inbox_id().as_ref() != *inbox_id { - return Err(InboxIdValidationError::InboxIdDoesNotMatch { - credential_inbox_id: inbox_id.clone(), - state_inbox_id: state.inbox_id().clone(), - }); - } + let responses: Vec<_> = join_all(responses) + .await + .into_iter() + .map(|result| match result { + Err(err) => VerifySmartContractWalletSignaturesResponseValidationResponse { + is_valid: false, + error: Some(format!("{err:?}")), + }, + Ok(is_valid) => VerifySmartContractWalletSignaturesResponseValidationResponse { + is_valid, + error: None, + }, + }) + .collect(); - let member = MemberIdentifier::Installation(installation_public_key); - if state.get(&member).is_none() { - return Err(InboxIdValidationError::MemberNotAssociated { - id: inbox_id, - member, - }); - } - Ok(InboxIdValidationResponse { - is_ok: true, - error_message: "".to_string(), - inbox_id, - }) + Ok(Response::new(VerifySmartContractWalletSignaturesResponse { + responses, + })) } async fn get_association_state( old_updates: Vec, new_updates: Vec, + scw_verifier: &dyn SmartContractSignatureVerifier, ) -> Result { - let (old_updates, new_updates) = (try_map_vec(old_updates)?, try_map_vec(new_updates)?); - + let old_unverified_updates: Vec = try_map_vec(old_updates)?; + let new_unverified_updates: Vec = try_map_vec(new_updates)?; + + let old_updates = try_join_all( + old_unverified_updates + .iter() + .map(|u| u.to_verified(scw_verifier)), + ) + .await?; + let new_updates = try_join_all( + new_unverified_updates + .iter() + .map(|u| u.to_verified(scw_verifier)), + ) + .await?; if old_updates.is_empty() { - let new_state = associations::get_state(&new_updates).await?; + let new_state = associations::get_state(&new_updates)?; return Ok(GetAssociationStateResponse { association_state: Some(new_state.clone().into()), state_diff: Some(new_state.as_diff().into()), }); } - let old_state = associations::get_state(&old_updates).await?; + let old_state = associations::get_state(&old_updates)?; let mut new_state = old_state.clone(); for update in new_updates { - new_state = associations::apply_update(new_state, update).await?; + new_state = associations::apply_update(new_state, update)?; } let state_diff = old_state.diff(&new_state); @@ -356,92 +310,40 @@ fn validate_group_message(message: Vec) -> Result, - account_address: String, - credential_identity_bytes: Vec, - expiration: u64, -} - -fn validate_key_package(key_package_bytes: Vec) -> Result { - let rust_crypto = RustCrypto::default(); - let verified_key_package = - VerifiedKeyPackage::from_bytes(&rust_crypto, key_package_bytes.as_slice()) - .map_err(|e| e.to_string())?; - - let credential = verified_key_package.inner.leaf_node().credential(); - - let basic_credential = - BasicCredential::try_from(credential.clone()).map_err(|e| e.to_string())?; - - Ok(ValidateKeyPackageResult { - installation_id: verified_key_package.installation_id(), - account_address: verified_key_package.account_address, - credential_identity_bytes: basic_credential.identity().to_vec(), - expiration: 0, - }) -} - #[cfg(test)] mod tests { use ed25519_dalek::SigningKey; use ethers::signers::{LocalWallet, Signer as _}; use openmls::{ extensions::{ApplicationIdExtension, Extension, Extensions}, - prelude::{ - tls_codec::Serialize, Ciphersuite, Credential as OpenMlsCredential, CredentialWithKey, - }, + prelude::{tls_codec::Serialize, Credential as OpenMlsCredential, CredentialWithKey}, prelude_test::KeyPackage, }; use openmls_basic_credential::SignatureKeyPair; use openmls_rust_crypto::OpenMlsRustCrypto; - use prost::Message; - use sha2::{Digest, Sha512}; - use xmtp_id::{ - associations::{ - generate_inbox_id, - unsigned_actions::{ - SignatureTextCreator as _, UnsignedAction, UnsignedAddAssociation, - UnsignedCreateInbox, UnsignedIdentityUpdate, - }, - Action, AddAssociation, CreateInbox, IdentityUpdate, InstallationKeySignature, - RecoverableEcdsaSignature, - }, - constants::INSTALLATION_KEY_SIGNATURE_CONTEXT, + use xmtp_id::associations::{ + generate_inbox_id, + test_utils::{rand_string, rand_u64, MockSmartContractSignatureVerifier}, + unverified::{UnverifiedAction, UnverifiedIdentityUpdate}, }; - use xmtp_mls::{credential::Credential, InboxOwner}; + use xmtp_mls::configuration::CIPHERSUITE; use xmtp_proto::xmtp::{ - identity::associations::IdentityUpdate as IdentityUpdateProto, - identity::MlsCredential as InboxIdMlsCredential, - mls::message_contents::MlsCredential as CredentialProto, + identity::{ + associations::IdentityUpdate as IdentityUpdateProto, + MlsCredential as InboxIdMlsCredential, + }, mls_validation::v1::validate_key_packages_request::KeyPackage as KeyPackageProtoWrapper, }; use super::*; - const CIPHERSUITE: Ciphersuite = - Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519; - - fn generate_identity() -> (Vec, SignatureKeyPair, String) { - let rng = &mut rand::thread_rng(); - let wallet = LocalWallet::new(rng); - let signature_key_pair = SignatureKeyPair::new(CIPHERSUITE.signature_algorithm()).unwrap(); - - let _pub_key = signature_key_pair.public(); - let account_address = wallet.get_address(); - - let credential = - Credential::create(&signature_key_pair, &wallet).expect("failed to create credential"); - let credential_proto: CredentialProto = credential.into(); - - ( - credential_proto.encode_to_vec(), - signature_key_pair, - account_address, - ) + impl Default for ValidationService { + fn default() -> Self { + Self::new(MockSmartContractSignatureVerifier::new(true)) + } } - async fn generate_inbox_id_credential() -> (String, LocalWallet, SigningKey, CreateInbox) { + fn generate_inbox_id_credential() -> (String, SigningKey) { let signing_key = SigningKey::generate(&mut rand::thread_rng()); let wallet = LocalWallet::new(&mut rand::thread_rng()); @@ -449,80 +351,7 @@ mod tests { let inbox_id = generate_inbox_id(&address, &0); - let unsigned_action = UnsignedAction::CreateInbox(UnsignedCreateInbox { - nonce: 0, - account_address: address.clone(), - }); - - let update = UnsignedIdentityUpdate { - client_timestamp_ns: 1_000_000u64, - inbox_id: inbox_id.clone(), - actions: vec![unsigned_action], - }; - - let signature = wallet - .sign_message(update.signature_text()) - .await - .unwrap() - .to_vec(); - - let ecdsa_signature = - RecoverableEcdsaSignature::new(update.signature_text(), signature.clone()); - let create = CreateInbox { - nonce: 0, - account_address: address, - initial_address_signature: Box::new(ecdsa_signature), - }; - - (inbox_id, wallet, signing_key, create) - } - - async fn generate_installation_association( - signing_key: &SigningKey, - wallet: LocalWallet, - inbox_id: &str, - ) -> AddAssociation { - let keypair = SignatureKeyPair::from_raw( - CIPHERSUITE.signature_algorithm(), - signing_key.to_bytes().into(), - signing_key.verifying_key().to_bytes().into(), - ); - - let action = UnsignedAction::AddAssociation(UnsignedAddAssociation { - new_member_identifier: MemberIdentifier::Installation(keypair.public().to_vec()), - }); - - let update = UnsignedIdentityUpdate { - client_timestamp_ns: 2_000_000u64, - inbox_id: inbox_id.to_owned(), - actions: vec![action], - }; - - let mut prehashed = Sha512::new(); - prehashed.update(update.signature_text()); - let signature = signing_key - .sign_prehashed(prehashed.clone(), Some(INSTALLATION_KEY_SIGNATURE_CONTEXT)) - .unwrap(); - let existing_member = wallet - .sign_message(update.signature_text()) - .await - .unwrap() - .to_vec(); - - let existing_member = - RecoverableEcdsaSignature::new(update.signature_text(), existing_member); - - let signature = InstallationKeySignature::new( - update.signature_text(), - signature.to_vec(), - signing_key.verifying_key().as_bytes().to_vec(), - ); - - AddAssociation { - new_member_signature: Box::new(signature), - new_member_identifier: MemberIdentifier::Installation(keypair.public().to_vec()), - existing_member_signature: Box::new(existing_member), - } + (inbox_id, signing_key) } fn build_key_package_bytes( @@ -564,84 +393,23 @@ mod tests { ) } - #[tokio::test] - async fn test_validate_key_packages_happy_path() { - let (identity, keypair, account_address) = generate_identity(); - - let credential: OpenMlsCredential = BasicCredential::new(identity).into(); - let credential_with_key = CredentialWithKey { - credential, - signature_key: keypair.to_public_vec().into(), - }; - - let key_package_bytes = build_key_package_bytes( - &keypair, - &credential_with_key, - Some(account_address.clone()), - ); - let request = ValidateKeyPackagesRequest { - key_packages: vec![KeyPackageProtoWrapper { - key_package_bytes_tls_serialized: key_package_bytes, - is_inbox_id_credential: false, - }], - }; - - let res = ValidationService::default() - .validate_key_packages(Request::new(request)) - .await - .unwrap(); - - let first_response = &res.into_inner().responses[0]; - assert_eq!(first_response.installation_id, keypair.public()); - assert_eq!(first_response.account_address, account_address); - assert!(!first_response.credential_identity_bytes.is_empty()); - } - - #[tokio::test] - async fn test_validate_key_packages_fail() { - let (identity, keypair, account_address) = generate_identity(); - let (_, other_keypair, _) = generate_identity(); - - let credential: OpenMlsCredential = BasicCredential::new(identity).into(); - let credential_with_key = CredentialWithKey { - credential, - // Use the wrong signature key to make the validation fail - signature_key: other_keypair.to_public_vec().into(), - }; - - let key_package_bytes = - build_key_package_bytes(&keypair, &credential_with_key, Some(account_address)); - - let request = ValidateKeyPackagesRequest { - key_packages: vec![KeyPackageProtoWrapper { - key_package_bytes_tls_serialized: key_package_bytes, - is_inbox_id_credential: false, - }], - }; - - let res = ValidationService::default() - .validate_key_packages(Request::new(request)) - .await - .unwrap(); - - let first_response = &res.into_inner().responses[0]; - - assert!(!first_response.is_ok); - assert_eq!(first_response.account_address, "".to_string()); - } - // this test will panic until signature recovery is added // and `MockSignature` is updated with signatures that can be recovered #[tokio::test] #[should_panic] async fn test_get_association_state() { - let create_request = CreateInbox::default(); - let inbox_id = generate_inbox_id(&create_request.account_address, &create_request.nonce); - - let updates = vec![IdentityUpdate::new_test( - vec![Action::CreateInbox(create_request)], + let account_address = rand_string(); + let nonce = rand_u64(); + let inbox_id = generate_inbox_id(&account_address, &nonce); + let update = UnverifiedIdentityUpdate::new_test( + vec![UnverifiedAction::new_test_create_inbox( + &account_address, + &nonce, + )], inbox_id.clone(), - )]; + ); + + let updates = vec![update]; ValidationService::default() .get_association_state(Request::new(GetAssociationStateRequest { @@ -657,7 +425,7 @@ mod tests { #[tokio::test] async fn test_validate_inbox_id_key_package_happy_path() { - let (inbox_id, _, keypair, _) = generate_inbox_id_credential().await; + let (inbox_id, keypair) = generate_inbox_id_credential(); let keypair = to_signature_keypair(keypair); let credential: OpenMlsCredential = InboxIdMlsCredential { @@ -695,8 +463,8 @@ mod tests { #[tokio::test] async fn test_validate_inbox_id_key_package_failure() { - let (inbox_id, _, keypair, _) = generate_inbox_id_credential().await; - let (_, _, other_keypair, _) = generate_inbox_id_credential().await; + let (inbox_id, keypair) = generate_inbox_id_credential(); + let (_, other_keypair) = generate_inbox_id_credential(); let keypair = to_signature_keypair(keypair); let other_keypair = to_signature_keypair(other_keypair); @@ -734,48 +502,4 @@ mod tests { assert_eq!(first_response.credential, None); assert_eq!(first_response.installation_public_key, Vec::::new()); } - - #[tokio::test] - async fn test_validate_inbox_ids_happy_path() { - let (inbox_id, wallet, keypair, create) = generate_inbox_id_credential().await; - let add_association = generate_installation_association(&keypair, wallet, &inbox_id).await; - let keypair = to_signature_keypair(keypair); - - let updates = vec![ - IdentityUpdate::new( - vec![Action::CreateInbox(create)], - inbox_id.clone(), - 1_000_000u64, - ) - .to_proto(), - IdentityUpdate::new( - vec![Action::AddAssociation(add_association)], - inbox_id.clone(), - 2_000_000u64, - ) - .to_proto(), - ]; - - let credential = Some(InboxIdMlsCredential { - inbox_id: inbox_id.clone(), - }); - let request = ValidateInboxIdsRequest { - requests: vec![InboxIdValidationRequest { - credential: credential.clone(), - installation_public_key: keypair.public().to_vec(), - identity_updates: updates.clone(), - }], - }; - - let res = ValidationService::default() - .validate_inbox_ids(Request::new(request)) - .await - .unwrap(); - - let res = &res.into_inner().responses[0]; - - assert!(res.is_ok); - assert_eq!(res.error_message, "".to_string()); - assert_eq!(res.inbox_id, inbox_id); - } } diff --git a/mls_validation_service/src/main.rs b/mls_validation_service/src/main.rs index 0209667e3..db10c2f3a 100644 --- a/mls_validation_service/src/main.rs +++ b/mls_validation_service/src/main.rs @@ -4,21 +4,24 @@ mod health_check; use clap::Parser; use config::Args; -use env_logger::Env; use handlers::ValidationService; use health_check::health_check_server; use tokio::signal::unix::{signal, SignalKind}; use tonic::transport::Server; +use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt as _, EnvFilter}; +use xmtp_id::scw_verifier::RpcSmartContractWalletVerifier; use xmtp_proto::xmtp::mls_validation::v1::validation_api_server::ValidationApiServer; #[macro_use] -extern crate log; +extern crate tracing; #[tokio::main] async fn main() -> Result<(), Box> { - let env = Env::default(); - env_logger::init_from_env(env); + tracing_subscriber::registry() + .with(fmt::layer()) + .with(EnvFilter::from_default_env()) + .init(); let args = Args::parse(); let addr = format!("0.0.0.0:{}", args.port).parse()?; @@ -27,8 +30,13 @@ async fn main() -> Result<(), Box> { let health_server = health_check_server(args.health_check_port as u16); + // TODO:nm replace with real verifier + let scw_verifier = RpcSmartContractWalletVerifier::new("http://fixme.com".to_string()); + let grpc_server = Server::builder() - .add_service(ValidationApiServer::new(ValidationService::default())) + .add_service(ValidationApiServer::new(ValidationService::new( + scw_verifier, + ))) .serve_with_shutdown(addr, async { wait_for_quit().await; info!("Shutdown signal received"); diff --git a/xmtp_api_grpc/Cargo.toml b/xmtp_api_grpc/Cargo.toml index d96a19b1d..f0d6b8bac 100644 --- a/xmtp_api_grpc/Cargo.toml +++ b/xmtp_api_grpc/Cargo.toml @@ -8,9 +8,6 @@ async-stream.workspace = true base64 = "0.22" futures.workspace = true hex.workspace = true -log = { workspace = true, features = ["std"] } -pbjson-types.workspace = true -pbjson.workspace = true prost = { workspace = true, features = ["prost-derive"] } serde = { workspace = true, features = ["derive"] } tokio = { workspace = true, features = ["macros", "rt-multi-thread", "time"] } diff --git a/xmtp_api_grpc/src/grpc_api_helper.rs b/xmtp_api_grpc/src/grpc_api_helper.rs index 7f9235405..6e61a81ac 100644 --- a/xmtp_api_grpc/src/grpc_api_helper.rs +++ b/xmtp_api_grpc/src/grpc_api_helper.rs @@ -7,13 +7,13 @@ use futures::stream::{AbortHandle, Abortable}; use futures::{SinkExt, Stream, StreamExt, TryStreamExt}; use tokio::sync::oneshot; use tonic::transport::ClientTlsConfig; -use tonic::{async_trait, metadata::MetadataValue, transport::Channel, Request, Streaming}; +use tonic::{metadata::MetadataValue, transport::Channel, Request, Streaming}; -use xmtp_proto::api_client::ClientWithMetadata; +use xmtp_proto::api_client::{ClientWithMetadata, XmtpMlsStreams}; +use xmtp_proto::xmtp::mls::api::v1::{GroupMessage, WelcomeMessage}; use xmtp_proto::{ api_client::{ - Error, ErrorKind, GroupMessageStream, MutableApiSubscription, WelcomeMessageStream, - XmtpApiClient, XmtpApiSubscription, XmtpMlsClient, + Error, ErrorKind, MutableApiSubscription, XmtpApiClient, XmtpApiSubscription, XmtpMlsClient, }, xmtp::identity::api::v1::identity_api_client::IdentityApiClient as ProtoIdentityApiClient, xmtp::message_api::v1::{ @@ -131,7 +131,6 @@ impl ClientWithMetadata for Client { } } -#[async_trait] impl XmtpApiClient for Client { type Subscription = Subscription; type MutableSubscription = GrpcMutableSubscription; @@ -318,7 +317,6 @@ impl Stream for GrpcMutableSubscription { } } -#[async_trait] impl MutableApiSubscription for GrpcMutableSubscription { async fn update(&mut self, req: SubscribeRequest) -> Result<(), Error> { self.update_channel @@ -334,8 +332,6 @@ impl MutableApiSubscription for GrpcMutableSubscription { self.update_channel.close_channel(); } } - -#[async_trait] impl XmtpMlsClient for Client { #[tracing::instrument(level = "trace", skip_all)] async fn upload_key_package(&self, req: UploadKeyPackageRequest) -> Result<(), Error> { @@ -405,11 +401,62 @@ impl XmtpMlsClient for Client { res.map(|r| r.into_inner()) .map_err(|e| Error::new(ErrorKind::MlsError).with(e)) } +} + +pub struct GroupMessageStream { + inner: tonic::codec::Streaming, +} + +impl From> for GroupMessageStream { + fn from(inner: tonic::codec::Streaming) -> Self { + GroupMessageStream { inner } + } +} + +impl Stream for GroupMessageStream { + type Item = Result; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.inner + .poll_next_unpin(cx) + .map(|data| data.map(|v| v.map_err(|e| Error::new(ErrorKind::SubscribeError).with(e)))) + } +} + +pub struct WelcomeMessageStream { + inner: tonic::codec::Streaming, +} + +impl From> for WelcomeMessageStream { + fn from(inner: tonic::codec::Streaming) -> Self { + WelcomeMessageStream { inner } + } +} + +impl Stream for WelcomeMessageStream { + type Item = Result; + + fn poll_next( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.inner + .poll_next_unpin(cx) + .map(|data| data.map(|v| v.map_err(|e| Error::new(ErrorKind::SubscribeError).with(e)))) + } +} + +impl XmtpMlsStreams for Client { + type GroupMessageStream<'a> = GroupMessageStream; + type WelcomeMessageStream<'a> = WelcomeMessageStream; async fn subscribe_group_messages( &self, req: SubscribeGroupMessagesRequest, - ) -> Result { + ) -> Result, Error> { let client = &mut self.mls_client.clone(); let res = client .subscribe_group_messages(self.build_request(req)) @@ -417,16 +464,13 @@ impl XmtpMlsClient for Client { .map_err(|e| Error::new(ErrorKind::MlsError).with(e))?; let stream = res.into_inner(); - - let new_stream = stream.map_err(|e| Error::new(ErrorKind::SubscribeError).with(e)); - - Ok(Box::pin(new_stream)) + Ok(stream.into()) } async fn subscribe_welcome_messages( &self, req: SubscribeWelcomeMessagesRequest, - ) -> Result { + ) -> Result, Error> { let client = &mut self.mls_client.clone(); let res = client .subscribe_welcome_messages(self.build_request(req)) @@ -435,8 +479,6 @@ impl XmtpMlsClient for Client { let stream = res.into_inner(); - let new_stream = stream.map_err(|e| Error::new(ErrorKind::SubscribeError).with(e)); - - Ok(Box::pin(new_stream)) + Ok(stream.into()) } } diff --git a/xmtp_api_grpc/src/identity.rs b/xmtp_api_grpc/src/identity.rs index 0fbb27e6d..92531e0a6 100644 --- a/xmtp_api_grpc/src/identity.rs +++ b/xmtp_api_grpc/src/identity.rs @@ -1,4 +1,3 @@ -use tonic::async_trait; use xmtp_proto::{ api_client::{Error, ErrorKind, XmtpIdentityClient}, xmtp::identity::api::v1::{ @@ -10,7 +9,6 @@ use xmtp_proto::{ use crate::Client; -#[async_trait] impl XmtpIdentityClient for Client { #[tracing::instrument(level = "trace", skip_all)] async fn publish_identity_update( diff --git a/xmtp_api_grpc/src/lib.rs b/xmtp_api_grpc/src/lib.rs index 10472c2a8..a774b86bc 100644 --- a/xmtp_api_grpc/src/lib.rs +++ b/xmtp_api_grpc/src/lib.rs @@ -5,7 +5,7 @@ mod identity; pub const LOCALHOST_ADDRESS: &str = "http://localhost:5556"; pub const DEV_ADDRESS: &str = "https://grpc.dev.xmtp.network:443"; -pub use grpc_api_helper::Client; +pub use grpc_api_helper::{Client, GroupMessageStream, WelcomeMessageStream}; #[cfg(test)] mod tests { diff --git a/xmtp_api_http/Cargo.toml b/xmtp_api_http/Cargo.toml index 13852a3dc..58bd4ab5e 100644 --- a/xmtp_api_http/Cargo.toml +++ b/xmtp_api_http/Cargo.toml @@ -8,17 +8,13 @@ crate-type = ["cdylib", "rlib"] [dependencies] async-stream.workspace = true -async-trait = { workspace = true } -bytes = "1.7" futures = { workspace = true } -log.workspace = true +tracing.workspace = true reqwest = { version = "0.12.5", features = ["json", "stream"] } serde = { workspace = true } serde_json = { workspace = true } thiserror = "1.0" tokio = { workspace = true, features = ["sync", "rt", "macros"] } -tokio-stream = { version = "0.1", default-features = false } -tracing.workspace = true xmtp_proto = { path = "../xmtp_proto", features = ["proto_full"] } [dev-dependencies] diff --git a/xmtp_api_http/src/lib.rs b/xmtp_api_http/src/lib.rs index aa6fca4b4..9ba77042f 100755 --- a/xmtp_api_http/src/lib.rs +++ b/xmtp_api_http/src/lib.rs @@ -3,7 +3,7 @@ pub mod constants; mod util; -use async_trait::async_trait; +use futures::stream; use reqwest::header; use util::{create_grpc_stream, handle_error}; use xmtp_proto::api_client::{ClientWithMetadata, Error, ErrorKind, XmtpIdentityClient}; @@ -14,7 +14,7 @@ use xmtp_proto::xmtp::identity::api::v1::{ }; use xmtp_proto::xmtp::mls::api::v1::{GroupMessage, WelcomeMessage}; use xmtp_proto::{ - api_client::{GroupMessageStream, WelcomeMessageStream, XmtpMlsClient}, + api_client::{XmtpMlsClient, XmtpMlsStreams}, xmtp::mls::api::v1::{ FetchKeyPackagesRequest, FetchKeyPackagesResponse, QueryGroupMessagesRequest, QueryGroupMessagesResponse, QueryWelcomeMessagesRequest, QueryWelcomeMessagesResponse, @@ -120,8 +120,6 @@ impl ClientWithMetadata for XmtpHttpApiClient { } } -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] impl XmtpMlsClient for XmtpHttpApiClient { async fn upload_key_package(&self, request: UploadKeyPackageRequest) -> Result<(), Error> { let res = self @@ -135,7 +133,7 @@ impl XmtpMlsClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::MlsError).with(e))?; - log::debug!("upload_key_package"); + tracing::debug!("upload_key_package"); handle_error(&*res) } @@ -154,7 +152,7 @@ impl XmtpMlsClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::MlsError).with(e))?; - log::debug!("fetch_key_packages"); + tracing::debug!("fetch_key_packages"); handle_error(&*res) } @@ -170,7 +168,7 @@ impl XmtpMlsClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::MlsError).with(e))?; - log::debug!("send_group_messages"); + tracing::debug!("send_group_messages"); handle_error(&*res) } @@ -189,7 +187,7 @@ impl XmtpMlsClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::MlsError).with(e))?; - log::debug!("send_welcome_messages"); + tracing::debug!("send_welcome_messages"); handle_error(&*res) } @@ -208,7 +206,7 @@ impl XmtpMlsClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::MlsError).with(e))?; - log::debug!("query_group_messages"); + tracing::debug!("query_group_messages"); handle_error(&*res) } @@ -227,15 +225,33 @@ impl XmtpMlsClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::MlsError).with(e))?; - log::debug!("query_welcome_messages"); + tracing::debug!("query_welcome_messages"); handle_error(&*res) } +} + +impl XmtpMlsStreams for XmtpHttpApiClient { + // hard to avoid boxing here: + // 1.) use `hyper` instead of `reqwest` and create our own `Stream` type + // 2.) ise `impl Stream` in return of `XmtpMlsStreams` but that + // breaks the `mockall::` functionality, since `mockall` does not support `impl Trait` in + // `Trait` yet. + + #[cfg(not(target_arch = "wasm32"))] + type GroupMessageStream<'a> = stream::BoxStream<'a, Result>; + #[cfg(not(target_arch = "wasm32"))] + type WelcomeMessageStream<'a> = stream::BoxStream<'a, Result>; + + #[cfg(target_arch = "wasm32")] + type GroupMessageStream<'a> = stream::LocalBoxStream<'a, Result>; + #[cfg(target_arch = "wasm32")] + type WelcomeMessageStream<'a> = stream::LocalBoxStream<'a, Result>; async fn subscribe_group_messages( &self, request: SubscribeGroupMessagesRequest, - ) -> Result { - log::debug!("subscribe_group_messages"); + ) -> Result, Error> { + tracing::debug!("subscribe_group_messages"); Ok(create_grpc_stream::<_, GroupMessage>( request, self.endpoint(ApiEndpoints::SUBSCRIBE_GROUP_MESSAGES), @@ -246,8 +262,8 @@ impl XmtpMlsClient for XmtpHttpApiClient { async fn subscribe_welcome_messages( &self, request: SubscribeWelcomeMessagesRequest, - ) -> Result { - log::debug!("subscribe_welcome_messages"); + ) -> Result, Error> { + tracing::debug!("subscribe_welcome_messages"); Ok(create_grpc_stream::<_, WelcomeMessage>( request, self.endpoint(ApiEndpoints::SUBSCRIBE_WELCOME_MESSAGES), @@ -256,8 +272,6 @@ impl XmtpMlsClient for XmtpHttpApiClient { } } -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] impl XmtpIdentityClient for XmtpHttpApiClient { async fn publish_identity_update( &self, @@ -274,7 +288,7 @@ impl XmtpIdentityClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::IdentityError).with(e))?; - log::debug!("publish_identity_update"); + tracing::debug!("publish_identity_update"); handle_error(&*res) } @@ -293,7 +307,7 @@ impl XmtpIdentityClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::IdentityError).with(e))?; - log::debug!("get_identity_updates_v2"); + tracing::debug!("get_identity_updates_v2"); handle_error(&*res) } @@ -312,7 +326,7 @@ impl XmtpIdentityClient for XmtpHttpApiClient { .await .map_err(|e| Error::new(ErrorKind::IdentityError).with(e))?; - log::debug!("get_inbox_ids"); + tracing::debug!("get_inbox_ids"); handle_error(&*res) } } diff --git a/xmtp_api_http/src/util.rs b/xmtp_api_http/src/util.rs index 056471eef..80e86f5da 100644 --- a/xmtp_api_http/src/util.rs +++ b/xmtp_api_http/src/util.rs @@ -1,4 +1,7 @@ -use futures::{stream, Stream, StreamExt}; +use futures::{ + stream::{self, StreamExt}, + Stream, +}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::Deserializer; use std::io::Read; @@ -49,9 +52,7 @@ pub fn create_grpc_stream< endpoint: String, http_client: reqwest::Client, ) -> stream::LocalBoxStream<'static, Result> { - log::info!("About to spawn stream"); - let stream = create_grpc_stream_inner(request, endpoint, http_client); - stream.boxed_local() + create_grpc_stream_inner(request, endpoint, http_client).boxed_local() } #[cfg(not(target_arch = "wasm32"))] @@ -63,12 +64,10 @@ pub fn create_grpc_stream< endpoint: String, http_client: reqwest::Client, ) -> stream::BoxStream<'static, Result> { - log::info!("About to spawn stream"); - let stream = create_grpc_stream_inner(request, endpoint, http_client); - stream.boxed() + create_grpc_stream_inner(request, endpoint, http_client).boxed() } -fn create_grpc_stream_inner< +pub fn create_grpc_stream_inner< T: Serialize + Send + 'static, R: DeserializeOwned + Send + std::fmt::Debug + 'static, >( @@ -77,7 +76,7 @@ fn create_grpc_stream_inner< http_client: reqwest::Client, ) -> impl Stream> { async_stream::stream! { - log::info!("Spawning grpc http stream"); + tracing::info!("Spawning grpc http stream"); let request = http_client .post(endpoint) .json(&request) diff --git a/xmtp_cryptography/Cargo.toml b/xmtp_cryptography/Cargo.toml index 7e06749f0..14c5e3a02 100644 --- a/xmtp_cryptography/Cargo.toml +++ b/xmtp_cryptography/Cargo.toml @@ -5,13 +5,12 @@ rust-version = "1.70" version.workspace = true [dependencies] +tracing.workspace = true curve25519-dalek = "4" ecdsa = "0.16.9" ethers = { workspace = true } -ethers-core = { workspace = true } hex = { workspace = true } k256 = { version = "0.13.3", features = ["ecdh"] } -log = { workspace = true } rand = { workspace = true } rand_chacha = "0.3.1" rustc-hex.workspace = true diff --git a/xmtp_cryptography/src/signature.rs b/xmtp_cryptography/src/signature.rs index 4f25414fe..b33377831 100644 --- a/xmtp_cryptography/src/signature.rs +++ b/xmtp_cryptography/src/signature.rs @@ -1,6 +1,6 @@ use curve25519_dalek::{edwards::CompressedEdwardsY, traits::IsIdentity}; +use ethers::core::types::{self as ethers_types, H160}; use ethers::types::Address; -use ethers_core::types::{self as ethers_types, H160}; pub use k256::ecdsa::{RecoveryId, SigningKey, VerifyingKey}; use k256::Secp256k1; use serde::{Deserialize, Serialize}; @@ -98,8 +98,8 @@ impl From<(ecdsa::Signature, RecoveryId)> for RecoverableSignature { } } -impl From for RecoverableSignature { - fn from(value: ethers_core::types::Signature) -> Self { +impl From for RecoverableSignature { + fn from(value: ethers::core::types::Signature) -> Self { RecoverableSignature::Eip191Signature(value.to_vec()) } } @@ -168,7 +168,7 @@ pub fn is_valid_ed25519_public_key>(public_key: Bytes) -> boo let compressed = match CompressedEdwardsY::from_slice(public_key) { Ok(v) => v, Err(_) => { - log::debug!("Invalid ed22519 public key. Does not have length of 32"); + tracing::debug!("Invalid ed22519 public key. Does not have length of 32"); return false; } }; @@ -176,14 +176,14 @@ pub fn is_valid_ed25519_public_key>(public_key: Bytes) -> boo match compressed.decompress() { Some(point) => { if point.is_small_order() || point.is_identity() { - log::debug!( + tracing::debug!( "Invalid public key, not a point on the curve or is the identity element." ); return false; } } None => { - log::debug!("Not a valid ed25519 public key: Decompression failure"); + tracing::debug!("Not a valid ed25519 public key: Decompression failure"); return false; } } diff --git a/xmtp_cryptography/src/utils.rs b/xmtp_cryptography/src/utils.rs index efbc1c502..35e13d4ba 100644 --- a/xmtp_cryptography/src/utils.rs +++ b/xmtp_cryptography/src/utils.rs @@ -1,5 +1,5 @@ +use ethers::core::utils::keccak256; pub use ethers::prelude::LocalWallet; -use ethers_core::utils::keccak256; use k256::ecdsa::VerifyingKey; use rand::{CryptoRng, RngCore, SeedableRng}; use rand_chacha::ChaCha20Rng; diff --git a/xmtp_id/Cargo.toml b/xmtp_id/Cargo.toml index 449c5f5fa..fce31a2d9 100644 --- a/xmtp_id/Cargo.toml +++ b/xmtp_id/Cargo.toml @@ -7,28 +7,24 @@ version.workspace = true async-trait.workspace = true chrono.workspace = true ed25519-dalek = { workspace = true, features = ["digest"] } -ed25519.workspace = true -ethers-core.workspace = true ethers.workspace = true futures.workspace = true hex.workspace = true -log.workspace = true -openmls.workspace = true -openmls_basic_credential.workspace = true -openmls_rust_crypto.workspace = true +tracing.workspace = true openmls_traits.workspace = true prost.workspace = true rand.workspace = true regex.workspace = true rustc-hex.workspace = true serde.workspace = true +serde_json.workspace = true sha2.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["macros"] } -tracing.workspace = true -url.workspace = true +url = { workspace = true, features = ["serde"] } xmtp_cryptography.workspace = true xmtp_proto = { workspace = true, features = ["proto_full"] } +dyn-clone = "1" [dev-dependencies] ctor = "0.2.5" diff --git a/xmtp_id/src/associations/association_log.rs b/xmtp_id/src/associations/association_log.rs index 2bccf68d0..cc821d762 100644 --- a/xmtp_id/src/associations/association_log.rs +++ b/xmtp_id/src/associations/association_log.rs @@ -1,12 +1,10 @@ use super::hashes::generate_inbox_id; use super::member::{Member, MemberIdentifier, MemberKind}; -use super::serialization::{from_identity_update_proto, DeserializationError}; -use super::signature::{Signature, SignatureError, SignatureKind}; +use super::serialization::DeserializationError; +use super::signature::{SignatureError, SignatureKind}; use super::state::AssociationState; -use async_trait::async_trait; -use prost::Message; +use super::verified_signature::VerifiedSignature; use thiserror::Error; -use xmtp_proto::xmtp::identity::associations::IdentityUpdate as IdentityUpdateProto; #[derive(Debug, Error)] pub enum AssociationError { @@ -38,11 +36,11 @@ pub enum AssociationError { MissingIdentityUpdate, } -#[async_trait] pub trait IdentityAction: Send + 'static { - async fn update_state( + fn update_state( &self, existing_state: Option, + client_timestamp_ns: u64, ) -> Result; fn signatures(&self) -> Vec>; fn replay_check(&self, state: &AssociationState) -> Result<(), AssociationError> { @@ -62,34 +60,30 @@ pub trait IdentityAction: Send + 'static { pub struct CreateInbox { pub nonce: u64, pub account_address: String, - pub initial_address_signature: Box, + pub initial_address_signature: VerifiedSignature, } -#[async_trait] impl IdentityAction for CreateInbox { - async fn update_state( + fn update_state( &self, existing_state: Option, + _client_timestamp_ns: u64, ) -> Result { if existing_state.is_some() { return Err(AssociationError::MultipleCreate); } let account_address = self.account_address.clone(); - let recovered_signer = self.initial_address_signature.recover_signer().await?; + let recovered_signer = self.initial_address_signature.signer.clone(); if recovered_signer.ne(&MemberIdentifier::Address( account_address.clone().to_lowercase(), )) { return Err(AssociationError::MissingExistingMember); } - allowed_signature_for_kind( - &MemberKind::Address, - &self.initial_address_signature.signature_kind(), - )?; + allowed_signature_for_kind(&MemberKind::Address, &self.initial_address_signature.kind)?; - if self.initial_address_signature.signature_kind() == SignatureKind::LegacyDelegated - && self.nonce != 0 + if self.initial_address_signature.kind == SignatureKind::LegacyDelegated && self.nonce != 0 { return Err(AssociationError::LegacySignatureReuse); } @@ -98,31 +92,31 @@ impl IdentityAction for CreateInbox { } fn signatures(&self) -> Vec> { - vec![self.initial_address_signature.bytes()] + vec![self.initial_address_signature.raw_bytes.clone()] } } /// AddAssociation Action #[derive(Debug, Clone)] pub struct AddAssociation { - pub new_member_signature: Box, + pub new_member_signature: VerifiedSignature, pub new_member_identifier: MemberIdentifier, - pub existing_member_signature: Box, + pub existing_member_signature: VerifiedSignature, } -#[async_trait::async_trait] impl IdentityAction for AddAssociation { - async fn update_state( + fn update_state( &self, maybe_existing_state: Option, + client_timestamp_ns: u64, ) -> Result { let existing_state = maybe_existing_state.ok_or(AssociationError::NotCreated)?; self.replay_check(&existing_state)?; // Validate the new member signature and get the recovered signer - let new_member_address = self.new_member_signature.recover_signer().await?; + let new_member_address = &self.new_member_signature.signer; // Validate the existing member signature and get the recovedred signer - let existing_member_identifier = self.existing_member_signature.recover_signer().await?; + let existing_member_identifier = &self.existing_member_signature.signer; if new_member_address.ne(&self.new_member_identifier) { return Err(AssociationError::NewMemberIdSignatureMismatch); @@ -138,7 +132,7 @@ impl IdentityAction for AddAssociation { if (is_legacy_signature(&self.new_member_signature) || is_legacy_signature(&self.existing_member_signature)) && existing_state.inbox_id().ne(&generate_inbox_id( - &existing_member_identifier.to_string(), + existing_member_identifier.to_string().as_str(), &0, )) { @@ -147,10 +141,10 @@ impl IdentityAction for AddAssociation { allowed_signature_for_kind( &self.new_member_identifier.kind(), - &self.new_member_signature.signature_kind(), + &self.new_member_signature.kind, )?; - let existing_member = existing_state.get(&existing_member_identifier); + let existing_member = existing_state.get(existing_member_identifier); let existing_entity_id = match existing_member { // If there is an existing member of the XID, use that member's ID @@ -176,7 +170,7 @@ impl IdentityAction for AddAssociation { // Ensure that the existing member signature is correct for the existing member type allowed_signature_for_kind( &existing_entity_id.kind(), - &self.existing_member_signature.signature_kind(), + &self.existing_member_signature.kind, )?; // Ensure that the new member signature is correct for the new member type @@ -185,15 +179,19 @@ impl IdentityAction for AddAssociation { self.new_member_identifier.kind(), )?; - let new_member = Member::new(new_member_address, Some(existing_entity_id)); + let new_member = Member::new( + new_member_address.clone(), + Some(existing_entity_id), + Some(client_timestamp_ns), + ); Ok(existing_state.add(new_member)) } fn signatures(&self) -> Vec> { vec![ - self.existing_member_signature.bytes(), - self.new_member_signature.bytes(), + self.existing_member_signature.raw_bytes.clone(), + self.new_member_signature.raw_bytes.clone(), ] } } @@ -201,15 +199,15 @@ impl IdentityAction for AddAssociation { /// RevokeAssociation Action #[derive(Debug, Clone)] pub struct RevokeAssociation { - pub recovery_address_signature: Box, + pub recovery_address_signature: VerifiedSignature, pub revoked_member: MemberIdentifier, } -#[async_trait] impl IdentityAction for RevokeAssociation { - async fn update_state( + fn update_state( &self, maybe_existing_state: Option, + _client_timestamp_ns: u64, ) -> Result { let existing_state = maybe_existing_state.ok_or(AssociationError::NotCreated)?; self.replay_check(&existing_state)?; @@ -221,7 +219,7 @@ impl IdentityAction for RevokeAssociation { )); } // Don't need to check for replay here since revocation is idempotent - let recovery_signer = self.recovery_address_signature.recover_signer().await?; + let recovery_signer = &self.recovery_address_signature.signer; // Make sure there is a recovery address set on the state let state_recovery_address = existing_state.recovery_address(); @@ -250,22 +248,22 @@ impl IdentityAction for RevokeAssociation { } fn signatures(&self) -> Vec> { - vec![self.recovery_address_signature.bytes()] + vec![self.recovery_address_signature.raw_bytes.clone()] } } /// ChangeRecoveryAddress Action #[derive(Debug, Clone)] pub struct ChangeRecoveryAddress { - pub recovery_address_signature: Box, + pub recovery_address_signature: VerifiedSignature, pub new_recovery_address: String, } -#[async_trait] impl IdentityAction for ChangeRecoveryAddress { - async fn update_state( + fn update_state( &self, existing_state: Option, + _client_timestamp_ns: u64, ) -> Result { let existing_state = existing_state.ok_or(AssociationError::NotCreated)?; self.replay_check(&existing_state)?; @@ -277,7 +275,7 @@ impl IdentityAction for ChangeRecoveryAddress { )); } - let recovery_signer = self.recovery_address_signature.recover_signer().await?; + let recovery_signer = &self.recovery_address_signature.signer; if recovery_signer.ne(&existing_state.recovery_address().clone().into()) { return Err(AssociationError::MissingExistingMember); } @@ -286,7 +284,7 @@ impl IdentityAction for ChangeRecoveryAddress { } fn signatures(&self) -> Vec> { - vec![self.recovery_address_signature.bytes()] + vec![self.recovery_address_signature.raw_bytes.clone()] } } @@ -299,17 +297,23 @@ pub enum Action { ChangeRecoveryAddress(ChangeRecoveryAddress), } -#[async_trait] impl IdentityAction for Action { - async fn update_state( + fn update_state( &self, existing_state: Option, + client_timestamp_ns: u64, ) -> Result { match self { - Action::CreateInbox(event) => event.update_state(existing_state).await, - Action::AddAssociation(event) => event.update_state(existing_state).await, - Action::RevokeAssociation(event) => event.update_state(existing_state).await, - Action::ChangeRecoveryAddress(event) => event.update_state(existing_state).await, + Action::CreateInbox(event) => event.update_state(existing_state, client_timestamp_ns), + Action::AddAssociation(event) => { + event.update_state(existing_state, client_timestamp_ns) + } + Action::RevokeAssociation(event) => { + event.update_state(existing_state, client_timestamp_ns) + } + Action::ChangeRecoveryAddress(event) => { + event.update_state(existing_state, client_timestamp_ns) + } } } @@ -339,47 +343,22 @@ impl IdentityUpdate { client_timestamp_ns, } } - - pub fn to_proto(self) -> IdentityUpdateProto { - IdentityUpdateProto::from(self) - } - - pub fn from_proto(proto: IdentityUpdateProto) -> Result { - from_identity_update_proto(proto) - } -} - -impl TryFrom for IdentityUpdate { - type Error = DeserializationError; - - fn try_from(proto: IdentityUpdateProto) -> Result { - IdentityUpdate::from_proto(proto) - } -} - -impl TryFrom> for IdentityUpdate { - type Error = DeserializationError; - - fn try_from(bytes: Vec) -> Result { - let proto = IdentityUpdateProto::decode(bytes.as_slice())?; - IdentityUpdate::from_proto(proto) - } } -#[async_trait] impl IdentityAction for IdentityUpdate { - async fn update_state( + fn update_state( &self, existing_state: Option, + _client_timestamp_ns: u64, ) -> Result { let mut state = existing_state.clone(); for action in &self.actions { - state = Some(action.update_state(state).await?); + state = Some(action.update_state(state, self.client_timestamp_ns)?); } let new_state = state.ok_or(AssociationError::NotCreated)?; if new_state.inbox_id().ne(&self.inbox_id) { - log::error!( + tracing::error!( "state inbox id mismatch, old: {}, new: {}", self.inbox_id, new_state.inbox_id() @@ -401,8 +380,8 @@ impl IdentityAction for IdentityUpdate { } #[allow(clippy::borrowed_box)] -fn is_legacy_signature(signature: &Box) -> bool { - signature.signature_kind() == SignatureKind::LegacyDelegated +fn is_legacy_signature(signature: &VerifiedSignature) -> bool { + signature.kind == SignatureKind::LegacyDelegated } fn allowed_association( diff --git a/xmtp_id/src/associations/builder.rs b/xmtp_id/src/associations/builder.rs index 041b4aef4..553eb421e 100644 --- a/xmtp_id/src/associations/builder.rs +++ b/xmtp_id/src/associations/builder.rs @@ -4,17 +4,21 @@ use std::collections::{HashMap, HashSet}; -use crate::utils::now_ns; +use crate::{scw_verifier::SmartContractSignatureVerifier, utils::now_ns}; use thiserror::Error; use super::{ - association_log::{AddAssociation, ChangeRecoveryAddress, CreateInbox, RevokeAssociation}, unsigned_actions::{ SignatureTextCreator, UnsignedAction, UnsignedAddAssociation, UnsignedChangeRecoveryAddress, UnsignedCreateInbox, UnsignedIdentityUpdate, UnsignedRevokeAssociation, }, - Action, IdentityUpdate, MemberIdentifier, MemberKind, Signature, SignatureError, + unverified::{ + UnverifiedAction, UnverifiedAddAssociation, UnverifiedChangeRecoveryAddress, + UnverifiedCreateInbox, UnverifiedIdentityUpdate, UnverifiedRevokeAssociation, + UnverifiedSignature, + }, + MemberIdentifier, MemberKind, SignatureError, }; /// The SignatureField is used to map the signatures from a [SignatureRequest] back to the correct @@ -169,7 +173,7 @@ pub enum SignatureRequestError { pub struct SignatureRequest { pending_actions: Vec, signature_text: String, - signatures: HashMap>, + signatures: HashMap, client_timestamp_ns: u64, inbox_id: String, } @@ -218,19 +222,24 @@ impl SignatureRequest { pub async fn add_signature( &mut self, - signature: Box, + signature: UnverifiedSignature, + scw_verifier: &dyn SmartContractSignatureVerifier, ) -> Result<(), SignatureRequestError> { - let signer_identity = signature.recover_signer().await?; + let verified_sig = signature + .to_verified(self.signature_text.clone(), scw_verifier) + .await?; + let signer_identity = &verified_sig.signer; + let missing_signatures = self.missing_signatures(); - log::info!("Provided Signer: {}", signer_identity); - log::info!("Missing Signatures: {:?}", missing_signatures); + tracing::info!("Provided Signer: {}", signer_identity); + tracing::info!("Missing Signatures: {:?}", missing_signatures); // Make sure the signer is someone actually in the request - if !missing_signatures.contains(&signer_identity) { + if !missing_signatures.contains(signer_identity) { return Err(SignatureRequestError::UnknownSigner); } - self.signatures.insert(signer_identity, signature); + self.signatures.insert(verified_sig.signer, signature); Ok(()) } @@ -243,7 +252,7 @@ impl SignatureRequest { self.signature_text.clone() } - pub fn build_identity_update(self) -> Result { + pub fn build_identity_update(self) -> Result { if !self.is_ready() { return Err(SignatureRequestError::MissingSigner); } @@ -253,12 +262,12 @@ impl SignatureRequest { .clone() .into_iter() .map(|pending_action| build_action(pending_action, &self.signatures)) - .collect::, SignatureRequestError>>()?; + .collect::, SignatureRequestError>>()?; - Ok(IdentityUpdate::new( - actions, + Ok(UnverifiedIdentityUpdate::new( self.inbox_id, self.client_timestamp_ns, + actions, )) } @@ -269,8 +278,8 @@ impl SignatureRequest { fn build_action( pending_action: PendingIdentityAction, - signatures: &HashMap>, -) -> Result { + signatures: &HashMap, +) -> Result { match pending_action.unsigned_action { UnsignedAction::CreateInbox(unsigned_action) => { let signer_identity = pending_action @@ -282,9 +291,8 @@ fn build_action( .cloned() .ok_or(SignatureRequestError::MissingSigner)?; - Ok(Action::CreateInbox(CreateInbox { - nonce: unsigned_action.nonce, - account_address: unsigned_action.account_address, + Ok(UnverifiedAction::CreateInbox(UnverifiedCreateInbox { + unsigned_action, initial_address_signature, })) } @@ -308,8 +316,8 @@ fn build_action( .cloned() .ok_or(SignatureRequestError::MissingSigner)?; - Ok(Action::AddAssociation(AddAssociation { - new_member_identifier: unsigned_action.new_member_identifier, + Ok(UnverifiedAction::AddAssociation(UnverifiedAddAssociation { + unsigned_action, existing_member_signature, new_member_signature, })) @@ -324,10 +332,12 @@ fn build_action( .cloned() .ok_or(SignatureRequestError::MissingSigner)?; - Ok(Action::RevokeAssociation(RevokeAssociation { - recovery_address_signature, - revoked_member: unsigned_action.revoked_member, - })) + Ok(UnverifiedAction::RevokeAssociation( + UnverifiedRevokeAssociation { + recovery_address_signature, + unsigned_action, + }, + )) } UnsignedAction::ChangeRecoveryAddress(unsigned_action) => { let signer_identity = pending_action @@ -340,10 +350,12 @@ fn build_action( .cloned() .ok_or(SignatureRequestError::MissingSigner)?; - Ok(Action::ChangeRecoveryAddress(ChangeRecoveryAddress { - recovery_address_signature, - new_recovery_address: unsigned_action.new_recovery_address, - })) + Ok(UnverifiedAction::ChangeRecoveryAddress( + UnverifiedChangeRecoveryAddress { + recovery_address_signature, + unsigned_action, + }, + )) } } } @@ -364,84 +376,85 @@ fn get_signature_text( #[cfg(test)] mod tests { - use crate::associations::{ - get_state, - hashes::generate_inbox_id, - test_utils::{rand_string, rand_vec, MockSignature}, - MemberKind, SignatureKind, + use ethers::signers::{LocalWallet, Signer}; + + use crate::{ + associations::{ + get_state, + hashes::generate_inbox_id, + test_utils::{ + add_installation_key_signature, add_wallet_signature, + MockSmartContractSignatureVerifier, + }, + unverified::UnverifiedRecoverableEcdsaSignature, + IdentityUpdate, + }, + InboxOwner, }; + use ed25519_dalek::SigningKey as Ed25519SigningKey; use super::*; - // Helper function to add all the missing signatures, since we don't have real signers available - async fn add_missing_signatures_to_request(signature_request: &mut SignatureRequest) { - let missing_signatures = signature_request.missing_signatures(); - for member_identifier in missing_signatures { - let signature_kind = match member_identifier.kind() { - MemberKind::Address => SignatureKind::Erc191, - MemberKind::Installation => SignatureKind::InstallationKey, - }; - - signature_request - .add_signature(MockSignature::new_boxed( - true, - member_identifier.clone(), - signature_kind, - Some(signature_request.signature_text()), - )) - .await - .expect("should succeed"); - } + async fn convert_to_verified(identity_update: &UnverifiedIdentityUpdate) -> IdentityUpdate { + let scw_verifier = MockSmartContractSignatureVerifier::new(false); + identity_update + .to_verified(&scw_verifier) + .await + .expect("should be valid") } #[tokio::test] async fn create_inbox() { - let account_address = "account_address".to_string(); + let wallet = LocalWallet::new(&mut rand::thread_rng()); + let account_address = wallet.get_address(); let nonce = 0; let inbox_id = generate_inbox_id(&account_address, &nonce); + let mut signature_request = SignatureRequestBuilder::new(inbox_id) .create_inbox(account_address.into(), nonce) .build(); - add_missing_signatures_to_request(&mut signature_request).await; + add_wallet_signature(&mut signature_request, &wallet).await; let identity_update = signature_request .build_identity_update() .expect("should be valid"); - get_state(vec![identity_update]) - .await - .expect("should be valid"); + get_state(vec![convert_to_verified(&identity_update).await]).expect("should be valid"); } #[tokio::test] async fn create_and_add_identity() { - let account_address = "account_address".to_string(); + let wallet = LocalWallet::new(&mut rand::thread_rng()); + let installation_key = Ed25519SigningKey::generate(&mut rand::thread_rng()); + let account_address = wallet.get_address(); + let installation_key_id = installation_key.verifying_key().as_bytes().to_vec(); let nonce = 0; let inbox_id = generate_inbox_id(&account_address, &nonce); let existing_member_identifier: MemberIdentifier = account_address.into(); - let new_member_identifier: MemberIdentifier = rand_vec().into(); + let new_member_identifier: MemberIdentifier = installation_key_id.into(); let mut signature_request = SignatureRequestBuilder::new(inbox_id) .create_inbox(existing_member_identifier.clone(), nonce) .add_association(new_member_identifier, existing_member_identifier) .build(); - add_missing_signatures_to_request(&mut signature_request).await; + add_wallet_signature(&mut signature_request, &wallet).await; + add_installation_key_signature(&mut signature_request, &installation_key).await; let identity_update = signature_request .build_identity_update() .expect("should be valid"); - let state = get_state(vec![identity_update]) - .await - .expect("should be valid"); + let state = + get_state(vec![convert_to_verified(&identity_update).await]).expect("should be valid"); assert_eq!(state.members().len(), 2); } #[tokio::test] async fn create_and_revoke() { - let account_address = "account_address".to_string(); + let wallet = LocalWallet::new(&mut rand::thread_rng()); + let account_address = wallet.get_address(); let nonce = 0; let inbox_id = generate_inbox_id(&account_address, &nonce); let existing_member_identifier: MemberIdentifier = account_address.clone().into(); @@ -451,15 +464,14 @@ mod tests { .revoke_association(existing_member_identifier.clone(), account_address.into()) .build(); - add_missing_signatures_to_request(&mut signature_request).await; + add_wallet_signature(&mut signature_request, &wallet).await; let identity_update = signature_request .build_identity_update() .expect("should be valid"); - let state = get_state(vec![identity_update]) - .await - .expect("should be valid"); + let state = + get_state(vec![convert_to_verified(&identity_update).await]).expect("should be valid"); assert_eq!(state.members().len(), 0); } @@ -473,13 +485,20 @@ mod tests { .create_inbox(account_address.into(), nonce) .build(); + let rand_wallet = LocalWallet::new(&mut rand::thread_rng()); + + let signature_text = signature_request.signature_text(); + let sig = rand_wallet + .sign_message(signature_text) + .await + .unwrap() + .to_vec(); + let unverified_sig = + UnverifiedSignature::RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature::new(sig)); + let scw_verifier = MockSmartContractSignatureVerifier::new(false); + let attempt_to_add_random_member = signature_request - .add_signature(MockSignature::new_boxed( - true, - rand_string().into(), - SignatureKind::Erc191, - None, - )) + .add_signature(unverified_sig, &scw_verifier) .await; assert!(matches!( diff --git a/xmtp_id/src/associations/member.rs b/xmtp_id/src/associations/member.rs index 44a31cde9..3159a6110 100644 --- a/xmtp_id/src/associations/member.rs +++ b/xmtp_id/src/associations/member.rs @@ -77,13 +77,19 @@ impl From> for MemberIdentifier { pub struct Member { pub identifier: MemberIdentifier, pub added_by_entity: Option, + pub client_timestamp_ns: Option, } impl Member { - pub fn new(identifier: MemberIdentifier, added_by_entity: Option) -> Self { + pub fn new( + identifier: MemberIdentifier, + added_by_entity: Option, + client_timestamp_ns: Option, + ) -> Self { Self { identifier, added_by_entity, + client_timestamp_ns, } } @@ -118,6 +124,7 @@ mod tests { Self { identifier: MemberIdentifier::default(), added_by_entity: None, + client_timestamp_ns: None, } } } diff --git a/xmtp_id/src/associations/mod.rs b/xmtp_id/src/associations/mod.rs index 198a84a26..022a948bf 100644 --- a/xmtp_id/src/associations/mod.rs +++ b/xmtp_id/src/associations/mod.rs @@ -8,6 +8,8 @@ mod state; #[cfg(any(test, feature = "test-utils"))] pub mod test_utils; pub mod unsigned_actions; +pub mod unverified; +pub mod verified_signature; pub use self::association_log::*; pub use self::hashes::generate_inbox_id; @@ -17,20 +19,20 @@ pub use self::signature::*; pub use self::state::{AssociationState, AssociationStateDiff}; // Apply a single IdentityUpdate to an existing AssociationState -pub async fn apply_update( +pub fn apply_update( initial_state: AssociationState, update: IdentityUpdate, ) -> Result { - update.update_state(Some(initial_state)).await + update.update_state(Some(initial_state), update.client_timestamp_ns) } // Get the current state from an array of `IdentityUpdate`s. Entire operation fails if any operation fails -pub async fn get_state>( +pub fn get_state>( updates: Updates, ) -> Result { let mut state = None; for update in updates.as_ref().iter() { - let res = update.update_state(state).await; + let res = update.update_state(state, update.client_timestamp_ns); state = Some(res?); } @@ -39,7 +41,11 @@ pub async fn get_state>( #[cfg(any(test, feature = "test-utils"))] pub mod test_defaults { - use self::test_utils::{rand_string, rand_u64, rand_vec, MockSignature}; + use self::{ + test_utils::{rand_string, rand_u64, rand_vec}, + unverified::{UnverifiedAction, UnverifiedIdentityUpdate}, + verified_signature::VerifiedSignature, + }; use super::*; impl IdentityUpdate { @@ -48,22 +54,26 @@ pub mod test_defaults { } } + impl UnverifiedIdentityUpdate { + pub fn new_test(actions: Vec, inbox_id: String) -> Self { + Self::new(inbox_id, rand_u64(), actions) + } + } + impl Default for AddAssociation { fn default() -> Self { let existing_member = rand_string(); let new_member = rand_vec(); Self { - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( existing_member.into(), SignatureKind::Erc191, - None, + rand_vec(), ), - new_member_signature: MockSignature::new_boxed( - true, + new_member_signature: VerifiedSignature::new( new_member.clone().into(), SignatureKind::InstallationKey, - None, + rand_vec(), ), new_member_identifier: new_member.into(), } @@ -77,11 +87,10 @@ pub mod test_defaults { Self { nonce: rand_u64(), account_address: signer.clone(), - initial_address_signature: MockSignature::new_boxed( - true, + initial_address_signature: VerifiedSignature::new( signer.into(), SignatureKind::Erc191, - None, + rand_vec(), ), } } @@ -91,11 +100,10 @@ pub mod test_defaults { fn default() -> Self { let signer = rand_string(); Self { - recovery_address_signature: MockSignature::new_boxed( - true, + recovery_address_signature: VerifiedSignature::new( signer.into(), SignatureKind::Erc191, - None, + rand_vec(), ), revoked_member: rand_string().into(), } @@ -105,7 +113,10 @@ pub mod test_defaults { #[cfg(test)] mod tests { - use self::test_utils::{rand_string, rand_vec, MockSignature}; + use self::{ + test_utils::{rand_string, rand_vec}, + verified_signature::VerifiedSignature, + }; use super::*; pub async fn new_test_inbox() -> AssociationState { @@ -114,7 +125,7 @@ mod tests { let identity_update = IdentityUpdate::new_test(vec![Action::CreateInbox(create_request)], inbox_id); - get_state(vec![identity_update]).await.unwrap() + get_state(vec![identity_update]).unwrap() } pub async fn new_test_inbox_with_installation() -> AssociationState { @@ -124,11 +135,10 @@ mod tests { initial_state.recovery_address().clone().into(); let update = Action::AddAssociation(AddAssociation { - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( initial_wallet_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), ..Default::default() }); @@ -137,7 +147,6 @@ mod tests { initial_state, IdentityUpdate::new_test(vec![update], inbox_id.clone()), ) - .await .unwrap() } @@ -148,7 +157,7 @@ mod tests { let account_address = create_request.account_address.clone(); let identity_update = IdentityUpdate::new_test(vec![Action::CreateInbox(create_request)], inbox_id.clone()); - let state = get_state(vec![identity_update]).await.unwrap(); + let state = get_state(vec![identity_update]).unwrap(); assert_eq!(state.members().len(), 1); let existing_entity = state.get(&account_address.clone().into()).unwrap(); @@ -164,17 +173,15 @@ mod tests { let update = Action::AddAssociation(AddAssociation { new_member_identifier: new_installation_identifier.clone(), - new_member_signature: MockSignature::new_boxed( - true, + new_member_signature: VerifiedSignature::new( new_installation_identifier.clone(), SignatureKind::InstallationKey, - None, + rand_vec(), ), - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( first_member.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), }); @@ -182,7 +189,6 @@ mod tests { initial_state, IdentityUpdate::new_test(vec![update], inbox_id.clone()), ) - .await .unwrap(); assert_eq!(new_state.members().len(), 2); @@ -197,18 +203,16 @@ mod tests { let inbox_id = generate_inbox_id(&account_address, &create_action.nonce); let new_member_identifier: MemberIdentifier = rand_vec().into(); let add_action = AddAssociation { - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( account_address.clone().into(), SignatureKind::Erc191, - None, + rand_vec(), ), // Add an installation ID - new_member_signature: MockSignature::new_boxed( - true, + new_member_signature: VerifiedSignature::new( new_member_identifier.clone(), SignatureKind::InstallationKey, - None, + rand_vec(), ), new_member_identifier: new_member_identifier.clone(), }; @@ -219,7 +223,7 @@ mod tests { ], inbox_id.clone(), ); - let state = get_state(vec![identity_update]).await.unwrap(); + let state = get_state(vec![identity_update]).unwrap(); assert_eq!(state.members().len(), 2); assert_eq!( state.get(&new_member_identifier).unwrap().added_by_entity, @@ -233,11 +237,10 @@ mod tests { let create_action = CreateInbox { nonce: 0, account_address: member_identifier.to_string(), - initial_address_signature: MockSignature::new_boxed( - true, + initial_address_signature: VerifiedSignature::new( member_identifier.clone(), SignatureKind::LegacyDelegated, - Some("0".to_string()), + "0".as_bytes().to_vec(), ), }; let inbox_id = generate_inbox_id(&member_identifier.to_string(), &0); @@ -245,26 +248,23 @@ mod tests { vec![Action::CreateInbox(create_action)], inbox_id.clone(), )]) - .await .unwrap(); assert_eq!(state.members().len(), 1); // The legacy key can only be used once. After this, subsequent updates should fail let update = Action::AddAssociation(AddAssociation { - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( member_identifier, SignatureKind::LegacyDelegated, // All requests from the same legacy key will have the same signature nonce - Some("0".to_string()), + "0".as_bytes().to_vec(), ), ..Default::default() }); let update_result = apply_update( state, IdentityUpdate::new_test(vec![update], inbox_id.clone()), - ) - .await; + ); assert!(matches!(update_result, Err(AssociationError::Replay))); } @@ -282,17 +282,15 @@ mod tests { let new_wallet_address: MemberIdentifier = rand_string().into(); let add_association = Action::AddAssociation(AddAssociation { new_member_identifier: new_wallet_address.clone(), - new_member_signature: MockSignature::new_boxed( - true, + new_member_signature: VerifiedSignature::new( new_wallet_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( installation_id.clone(), SignatureKind::InstallationKey, - None, + rand_vec(), ), }); @@ -300,29 +298,29 @@ mod tests { initial_state, IdentityUpdate::new_test(vec![add_association], inbox_id.clone()), ) - .await .expect("expected update to succeed"); assert_eq!(new_state.members().len(), 3); } #[tokio::test] async fn reject_invalid_signature_on_create() { + // Creates a signature with the wrong signer let bad_signature = - MockSignature::new_boxed(false, rand_string().into(), SignatureKind::Erc191, None); + VerifiedSignature::new(rand_string().into(), SignatureKind::Erc191, rand_vec()); let action = CreateInbox { - initial_address_signature: bad_signature.clone(), + initial_address_signature: bad_signature, ..Default::default() }; let state_result = get_state(vec![IdentityUpdate::new_test( vec![Action::CreateInbox(action)], rand_string(), - )]) - .await; + )]); + assert!(state_result.is_err()); assert!(matches!( state_result, - Err(AssociationError::Signature(SignatureError::Invalid)) + Err(AssociationError::MissingExistingMember) )); } @@ -330,8 +328,9 @@ mod tests { async fn reject_invalid_signature_on_update() { let initial_state = new_test_inbox().await; let inbox_id = initial_state.inbox_id().clone(); + // Signature is from a random address let bad_signature = - MockSignature::new_boxed(false, rand_string().into(), SignatureKind::Erc191, None); + VerifiedSignature::new(rand_string().into(), SignatureKind::Erc191, rand_vec()); let update_with_bad_existing_member = Action::AddAssociation(AddAssociation { existing_member_signature: bad_signature.clone(), @@ -341,20 +340,19 @@ mod tests { let update_result = apply_update( initial_state.clone(), IdentityUpdate::new_test(vec![update_with_bad_existing_member], inbox_id.clone()), - ) - .await; + ); + assert!(matches!( update_result, - Err(AssociationError::Signature(SignatureError::Invalid)) + Err(AssociationError::MissingExistingMember) )); let update_with_bad_new_member = Action::AddAssociation(AddAssociation { new_member_signature: bad_signature.clone(), - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( initial_state.recovery_address().clone().into(), SignatureKind::Erc191, - None, + rand_vec(), ), ..Default::default() }); @@ -362,11 +360,10 @@ mod tests { let update_result_2 = apply_update( initial_state, IdentityUpdate::new_test(vec![update_with_bad_new_member], inbox_id.clone()), - ) - .await; + ); assert!(matches!( update_result_2, - Err(AssociationError::Signature(SignatureError::Invalid)) + Err(AssociationError::NewMemberIdSignatureMismatch) )); } @@ -378,11 +375,10 @@ mod tests { // The default here will create an AddAssociation from a random wallet let update = Action::AddAssociation(AddAssociation { // Existing member signature is coming from a random wallet - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( rand_string().into(), SignatureKind::Erc191, - None, + rand_vec(), ), ..Default::default() }); @@ -390,8 +386,7 @@ mod tests { let state_result = get_state(vec![IdentityUpdate::new_test( vec![create_request, update], inbox_id.clone(), - )]) - .await; + )]); assert!(matches!( state_result, Err(AssociationError::MissingExistingMember) @@ -407,26 +402,23 @@ mod tests { let new_installation_id: MemberIdentifier = rand_vec().into(); let update = Action::AddAssociation(AddAssociation { - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( existing_installation.identifier.clone(), SignatureKind::InstallationKey, - None, + rand_vec(), ), new_member_identifier: new_installation_id.clone(), - new_member_signature: MockSignature::new_boxed( - true, + new_member_signature: VerifiedSignature::new( new_installation_id.clone(), SignatureKind::InstallationKey, - None, + rand_vec(), ), }); let update_result = apply_update( existing_state, IdentityUpdate::new_test(vec![update], inbox_id.clone()), - ) - .await; + ); assert!(matches!( update_result, Err(AssociationError::MemberNotAllowed( @@ -447,11 +439,10 @@ mod tests { .unwrap() .identifier; let update = Action::RevokeAssociation(RevokeAssociation { - recovery_address_signature: MockSignature::new_boxed( - true, + recovery_address_signature: VerifiedSignature::new( initial_state.recovery_address().clone().into(), SignatureKind::Erc191, - None, + rand_vec(), ), revoked_member: installation_id.clone(), }); @@ -460,7 +451,6 @@ mod tests { initial_state, IdentityUpdate::new_test(vec![update], inbox_id.clone()), ) - .await .expect("expected update to succeed"); assert!(new_state.get(&installation_id).is_none()); } @@ -477,11 +467,10 @@ mod tests { .identifier; let add_second_installation = Action::AddAssociation(AddAssociation { - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( wallet_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), ..Default::default() }); @@ -490,16 +479,14 @@ mod tests { initial_state, IdentityUpdate::new_test(vec![add_second_installation], inbox_id.clone()), ) - .await .expect("expected update to succeed"); assert_eq!(new_state.members().len(), 3); let revocation = Action::RevokeAssociation(RevokeAssociation { - recovery_address_signature: MockSignature::new_boxed( - true, + recovery_address_signature: VerifiedSignature::new( wallet_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), revoked_member: wallet_address.clone(), }); @@ -509,7 +496,6 @@ mod tests { new_state, IdentityUpdate::new_test(vec![revocation], inbox_id.clone()), ) - .await .expect("expected update to succeed"); assert_eq!(new_state.members().len(), 0); } @@ -529,26 +515,23 @@ mod tests { let second_wallet_address: MemberIdentifier = rand_string().into(); let add_second_wallet = Action::AddAssociation(AddAssociation { new_member_identifier: second_wallet_address.clone(), - new_member_signature: MockSignature::new_boxed( - true, + new_member_signature: VerifiedSignature::new( second_wallet_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( wallet_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), }); let revoke_second_wallet = Action::RevokeAssociation(RevokeAssociation { - recovery_address_signature: MockSignature::new_boxed( - true, + recovery_address_signature: VerifiedSignature::new( wallet_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), revoked_member: second_wallet_address.clone(), }); @@ -560,23 +543,20 @@ mod tests { inbox_id.clone(), ), ) - .await .expect("expected update to succeed"); assert_eq!(state_after_remove.members().len(), 1); let add_second_wallet_again = Action::AddAssociation(AddAssociation { new_member_identifier: second_wallet_address.clone(), - new_member_signature: MockSignature::new_boxed( - true, + new_member_signature: VerifiedSignature::new( second_wallet_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), - existing_member_signature: MockSignature::new_boxed( - true, + existing_member_signature: VerifiedSignature::new( wallet_address, SignatureKind::Erc191, - None, + rand_vec(), ), }); @@ -584,7 +564,6 @@ mod tests { state_after_remove, IdentityUpdate::new_test(vec![add_second_wallet_again], inbox_id.clone()), ) - .await .expect("expected update to succeed"); assert_eq!(state_after_re_add.members().len(), 2); } @@ -598,11 +577,10 @@ mod tests { let new_recovery_address = rand_string(); let update_recovery = Action::ChangeRecoveryAddress(ChangeRecoveryAddress { new_recovery_address: new_recovery_address.clone(), - recovery_address_signature: MockSignature::new_boxed( - true, + recovery_address_signature: VerifiedSignature::new( initial_state.recovery_address().clone().into(), SignatureKind::Erc191, - None, + rand_vec(), ), }); @@ -610,16 +588,14 @@ mod tests { initial_state, IdentityUpdate::new_test(vec![update_recovery], inbox_id.clone()), ) - .await .expect("expected update to succeed"); assert_eq!(new_state.recovery_address(), &new_recovery_address); let attempted_revoke = Action::RevokeAssociation(RevokeAssociation { - recovery_address_signature: MockSignature::new_boxed( - true, + recovery_address_signature: VerifiedSignature::new( initial_recovery_address.clone(), SignatureKind::Erc191, - None, + rand_vec(), ), revoked_member: initial_recovery_address.clone(), }); @@ -627,8 +603,7 @@ mod tests { let revoke_result = apply_update( new_state, IdentityUpdate::new_test(vec![attempted_revoke], inbox_id.clone()), - ) - .await; + ); assert!(revoke_result.is_err()); assert!(matches!( revoke_result, diff --git a/xmtp_id/src/associations/serialization.rs b/xmtp_id/src/associations/serialization.rs index 10de98549..f0cb837d2 100644 --- a/xmtp_id/src/associations/serialization.rs +++ b/xmtp_id/src/associations/serialization.rs @@ -1,26 +1,26 @@ use std::collections::{HashMap, HashSet}; use super::{ - association_log::{ - Action, AddAssociation, ChangeRecoveryAddress, CreateInbox, RevokeAssociation, - }, member::Member, - signature::{ - AccountId, InstallationKeySignature, LegacyDelegatedSignature, RecoverableEcdsaSignature, - SmartContractWalletSignature, ValidatedLegacySignedPublicKey, - }, + signature::{AccountId, ValidatedLegacySignedPublicKey}, state::{AssociationState, AssociationStateDiff}, unsigned_actions::{ - SignatureTextCreator, UnsignedAction, UnsignedAddAssociation, - UnsignedChangeRecoveryAddress, UnsignedCreateInbox, UnsignedIdentityUpdate, + UnsignedAddAssociation, UnsignedChangeRecoveryAddress, UnsignedCreateInbox, UnsignedRevokeAssociation, }, - IdentityUpdate, MemberIdentifier, Signature, SignatureError, + unverified::{ + UnverifiedAction, UnverifiedAddAssociation, UnverifiedChangeRecoveryAddress, + UnverifiedCreateInbox, UnverifiedIdentityUpdate, UnverifiedInstallationKeySignature, + UnverifiedLegacyDelegatedSignature, UnverifiedRecoverableEcdsaSignature, + UnverifiedRevokeAssociation, UnverifiedSignature, UnverifiedSmartContractWalletSignature, + }, + verified_signature::VerifiedSignature, + MemberIdentifier, SignatureError, }; use prost::{DecodeError, Message}; use regex::Regex; use thiserror::Error; -use xmtp_cryptography::signature::{sanitize_evm_addresses, RecoverableSignature}; +use xmtp_cryptography::signature::sanitize_evm_addresses; use xmtp_proto::xmtp::{ identity::associations::{ identity_action::Kind as IdentityActionKindProto, @@ -30,9 +30,12 @@ use xmtp_proto::xmtp::{ AssociationStateDiff as AssociationStateDiffProto, ChangeRecoveryAddress as ChangeRecoveryAddressProto, CreateInbox as CreateInboxProto, IdentityAction as IdentityActionProto, IdentityUpdate as IdentityUpdateProto, - Member as MemberProto, MemberIdentifier as MemberIdentifierProto, - MemberMap as MemberMapProto, RevokeAssociation as RevokeAssociationProto, - Signature as SignatureWrapperProto, + LegacyDelegatedSignature as LegacyDelegatedSignatureProto, Member as MemberProto, + MemberIdentifier as MemberIdentifierProto, MemberMap as MemberMapProto, + RecoverableEcdsaSignature as RecoverableEcdsaSignatureProto, + RecoverableEd25519Signature as RecoverableEd25519SignatureProto, + RevokeAssociation as RevokeAssociationProto, Signature as SignatureWrapperProto, + SmartContractWalletSignature as SmartContractWalletSignatureProto, }, message_contents::{ signature::{Union, WalletEcdsaCompact}, @@ -60,254 +63,252 @@ pub enum DeserializationError { Decode(#[from] DecodeError), #[error("Invalid account id")] InvalidAccountId, + #[error("Invalid hash (needs to be 32 bytes)")] + InvalidHash, } -pub fn from_identity_update_proto( - proto: IdentityUpdateProto, -) -> Result { - let client_timestamp_ns = proto.client_timestamp_ns; - let inbox_id = proto.inbox_id; - let all_actions = proto - .actions - .into_iter() - .map(|action| match action.kind { - Some(action) => Ok(action), - None => Err(DeserializationError::MissingAction), - }) - .collect::, DeserializationError>>()?; +impl TryFrom for UnverifiedIdentityUpdate { + type Error = DeserializationError; + + fn try_from(proto: IdentityUpdateProto) -> Result { + let IdentityUpdateProto { + client_timestamp_ns, + inbox_id, + actions, + } = proto; + let all_actions = actions + .into_iter() + .map(|action| match action.kind { + Some(action) => Ok(action), + None => Err(DeserializationError::MissingAction), + }) + .collect::, DeserializationError>>()?; + + let processed_actions: Vec = all_actions + .into_iter() + .map(UnverifiedAction::try_from) + .collect::, DeserializationError>>()?; + + Ok(UnverifiedIdentityUpdate::new( + inbox_id, + client_timestamp_ns, + processed_actions, + )) + } +} - let signature_text = get_signature_text(&all_actions, inbox_id.clone(), client_timestamp_ns)?; +impl TryFrom for UnverifiedAction { + type Error = DeserializationError; - let processed_actions: Vec = all_actions - .into_iter() - .map(|action| match action { + fn try_from(action: IdentityActionKindProto) -> Result { + Ok(match action { IdentityActionKindProto::Add(add_action) => { - Ok(Action::AddAssociation(AddAssociation { - new_member_signature: from_signature_proto_option( - add_action.new_member_signature, - signature_text.clone(), - )?, - existing_member_signature: from_signature_proto_option( - add_action.existing_member_signature, - signature_text.clone(), - )?, - new_member_identifier: from_member_identifier_proto_option( - add_action.new_member_identifier, - )?, - })) + UnverifiedAction::AddAssociation(UnverifiedAddAssociation { + new_member_signature: add_action.new_member_signature.try_into()?, + existing_member_signature: add_action.existing_member_signature.try_into()?, + unsigned_action: UnsignedAddAssociation { + new_member_identifier: add_action + .new_member_identifier + .ok_or(DeserializationError::MissingMemberIdentifier)? + .try_into()?, + }, + }) } - IdentityActionKindProto::CreateInbox(create_inbox_action) => { - Ok(Action::CreateInbox(CreateInbox { - nonce: create_inbox_action.nonce, - account_address: create_inbox_action.initial_address, - initial_address_signature: from_signature_proto_option( - create_inbox_action.initial_address_signature, - signature_text.clone(), - )?, - })) + IdentityActionKindProto::CreateInbox(action_proto) => { + UnverifiedAction::CreateInbox(UnverifiedCreateInbox { + initial_address_signature: action_proto.initial_address_signature.try_into()?, + unsigned_action: UnsignedCreateInbox { + nonce: action_proto.nonce, + account_address: action_proto.initial_address, + }, + }) } - IdentityActionKindProto::ChangeRecoveryAddress(change_recovery_address_action) => { - Ok(Action::ChangeRecoveryAddress(ChangeRecoveryAddress { - new_recovery_address: change_recovery_address_action.new_recovery_address, - recovery_address_signature: from_signature_proto_option( - change_recovery_address_action.existing_recovery_address_signature, - signature_text.clone(), - )?, - })) + IdentityActionKindProto::ChangeRecoveryAddress(action_proto) => { + UnverifiedAction::ChangeRecoveryAddress(UnverifiedChangeRecoveryAddress { + recovery_address_signature: action_proto + .existing_recovery_address_signature + .try_into()?, + unsigned_action: UnsignedChangeRecoveryAddress { + new_recovery_address: action_proto.new_recovery_address, + }, + }) } - IdentityActionKindProto::Revoke(revoke_action) => { - Ok(Action::RevokeAssociation(RevokeAssociation { - revoked_member: from_member_identifier_proto_option( - revoke_action.member_to_revoke, - )?, - recovery_address_signature: from_signature_proto_option( - revoke_action.recovery_address_signature, - signature_text.clone(), - )?, - })) + IdentityActionKindProto::Revoke(action_proto) => { + UnverifiedAction::RevokeAssociation(UnverifiedRevokeAssociation { + recovery_address_signature: action_proto + .recovery_address_signature + .try_into()?, + unsigned_action: UnsignedRevokeAssociation { + revoked_member: action_proto + .member_to_revoke + .ok_or(DeserializationError::MissingMember)? + .try_into()?, + }, + }) } }) - .collect::, DeserializationError>>()?; - - Ok(IdentityUpdate::new( - processed_actions, - inbox_id, - client_timestamp_ns, - )) + } } -fn get_signature_text( - actions: &[IdentityActionKindProto], - inbox_id: String, - client_timestamp_ns: u64, -) -> Result { - let unsigned_actions: Vec = actions - .iter() - .map(|action| match action { - IdentityActionKindProto::Add(add_action) => { - Ok(UnsignedAction::AddAssociation(UnsignedAddAssociation { - new_member_identifier: from_member_identifier_proto_option( - add_action.new_member_identifier.clone(), - )?, - })) - } - IdentityActionKindProto::CreateInbox(create_inbox_action) => { - Ok(UnsignedAction::CreateInbox(UnsignedCreateInbox { - nonce: create_inbox_action.nonce, - account_address: create_inbox_action.initial_address.clone(), - })) +impl TryFrom for UnverifiedSignature { + type Error = DeserializationError; + + fn try_from(proto: SignatureWrapperProto) -> Result { + let signature = unwrap_proto_signature(proto)?; + let unverified_sig = match signature { + SignatureKindProto::Erc191(sig) => UnverifiedSignature::RecoverableEcdsa( + UnverifiedRecoverableEcdsaSignature::new(sig.bytes), + ), + SignatureKindProto::DelegatedErc191(sig) => { + UnverifiedSignature::LegacyDelegated(UnverifiedLegacyDelegatedSignature::new( + UnverifiedRecoverableEcdsaSignature::new( + sig.signature.ok_or(DeserializationError::Signature)?.bytes, + ), + sig.delegated_key.ok_or(DeserializationError::Signature)?, + )) } - IdentityActionKindProto::ChangeRecoveryAddress(change_recovery_address_action) => Ok( - UnsignedAction::ChangeRecoveryAddress(UnsignedChangeRecoveryAddress { - new_recovery_address: change_recovery_address_action - .new_recovery_address - .clone(), - }), + SignatureKindProto::InstallationKey(sig) => UnverifiedSignature::InstallationKey( + UnverifiedInstallationKeySignature::new(sig.bytes, sig.public_key), ), - IdentityActionKindProto::Revoke(revoke_action) => Ok( - UnsignedAction::RevokeAssociation(UnsignedRevokeAssociation { - revoked_member: from_member_identifier_proto_option( - revoke_action.member_to_revoke.clone(), - )?, - }), + SignatureKindProto::Erc6492(sig) => UnverifiedSignature::SmartContractWallet( + UnverifiedSmartContractWalletSignature::new( + sig.signature, + sig.account_id.try_into()?, + sig.block_number, + ), ), - }) - .collect::, DeserializationError>>()?; + }; - let unsigned_update = - UnsignedIdentityUpdate::new(unsigned_actions, inbox_id, client_timestamp_ns); + Ok(unverified_sig) + } +} + +impl TryFrom> for UnverifiedSignature { + type Error = DeserializationError; - Ok(unsigned_update.signature_text()) + fn try_from(value: Option) -> Result { + value + .ok_or_else(|| DeserializationError::Signature)? + .try_into() + } } -fn from_member_identifier_proto_option( - proto: Option, -) -> Result { - match proto { - None => Err(DeserializationError::MissingMemberIdentifier), - Some(identifier_proto) => match identifier_proto.kind { - Some(identifier) => Ok(identifier.into()), - None => Err(DeserializationError::MissingMemberIdentifier), - }, +fn unwrap_proto_signature( + value: SignatureWrapperProto, +) -> Result { + match value.signature { + Some(inner) => Ok(inner), + None => Err(DeserializationError::Signature), } } -impl From for MemberIdentifier { - fn from(proto: MemberIdentifierKindProto) -> Self { - match proto { - MemberIdentifierKindProto::Address(address) => address.into(), - MemberIdentifierKindProto::InstallationPublicKey(public_key) => public_key.into(), +impl From for IdentityUpdateProto { + fn from(value: UnverifiedIdentityUpdate) -> Self { + Self { + inbox_id: value.inbox_id, + client_timestamp_ns: value.client_timestamp_ns, + actions: map_vec(value.actions), } } } -fn from_signature_proto_option( - proto: Option, - signature_text: String, -) -> Result, DeserializationError> { - match proto { - None => Err(DeserializationError::Signature), - Some(signature_proto) => match signature_proto.signature { - Some(signature) => Ok(from_signature_kind_proto(signature, signature_text)?), - None => Err(DeserializationError::Signature), - }, +impl From for IdentityActionProto { + fn from(value: UnverifiedAction) -> Self { + let kind: IdentityActionKindProto = match value { + UnverifiedAction::CreateInbox(action) => { + IdentityActionKindProto::CreateInbox(CreateInboxProto { + nonce: action.unsigned_action.nonce, + initial_address: action.unsigned_action.account_address, + initial_address_signature: Some(action.initial_address_signature.into()), + }) + } + UnverifiedAction::AddAssociation(action) => { + IdentityActionKindProto::Add(AddAssociationProto { + new_member_identifier: Some( + action.unsigned_action.new_member_identifier.into(), + ), + existing_member_signature: Some(action.existing_member_signature.into()), + new_member_signature: Some(action.new_member_signature.into()), + }) + } + UnverifiedAction::ChangeRecoveryAddress(action) => { + IdentityActionKindProto::ChangeRecoveryAddress(ChangeRecoveryAddressProto { + new_recovery_address: action.unsigned_action.new_recovery_address, + existing_recovery_address_signature: Some( + action.recovery_address_signature.into(), + ), + }) + } + UnverifiedAction::RevokeAssociation(action) => { + IdentityActionKindProto::Revoke(RevokeAssociationProto { + recovery_address_signature: Some(action.recovery_address_signature.into()), + member_to_revoke: Some(action.unsigned_action.revoked_member.into()), + }) + } + }; + + IdentityActionProto { kind: Some(kind) } } } -fn from_signature_kind_proto( - proto: SignatureKindProto, - signature_text: String, -) -> Result, DeserializationError> { - Ok(match proto { - SignatureKindProto::InstallationKey(installation_key_signature) => { - Box::new(InstallationKeySignature::new( - signature_text, - installation_key_signature.bytes, - installation_key_signature.public_key, - )) - } - SignatureKindProto::Erc191(erc191_signature) => Box::new(RecoverableEcdsaSignature::new( - signature_text, - erc191_signature.bytes, - )), - SignatureKindProto::Erc6492(signature) => Box::new(SmartContractWalletSignature::new( - signature_text, - signature.signature, - signature.account_id.try_into()?, - signature.chain_rpc_url, - signature.block_number, - )), - SignatureKindProto::DelegatedErc191(delegated_erc191_signature) => { - let signature_value = delegated_erc191_signature - .signature - .ok_or(DeserializationError::Signature)?; - let recoverable_ecdsa_signature = - RecoverableEcdsaSignature::new(signature_text, signature_value.bytes); - - Box::new(LegacyDelegatedSignature::new( - recoverable_ecdsa_signature, - delegated_erc191_signature - .delegated_key - .ok_or(DeserializationError::Signature)?, - )) +impl From for SignatureWrapperProto { + fn from(value: UnverifiedSignature) -> Self { + let signature = match value { + UnverifiedSignature::SmartContractWallet(sig) => { + SignatureKindProto::Erc6492(SmartContractWalletSignatureProto { + account_id: sig.account_id.into(), + block_number: sig.block_number, + signature: sig.signature_bytes, + }) + } + UnverifiedSignature::InstallationKey(sig) => { + SignatureKindProto::InstallationKey(RecoverableEd25519SignatureProto { + bytes: sig.signature_bytes, + public_key: sig.verifying_key, + }) + } + UnverifiedSignature::LegacyDelegated(sig) => { + SignatureKindProto::DelegatedErc191(LegacyDelegatedSignatureProto { + delegated_key: Some(sig.signed_public_key_proto), + signature: Some(RecoverableEcdsaSignatureProto { + bytes: sig.legacy_key_signature.signature_bytes, + }), + }) + } + UnverifiedSignature::RecoverableEcdsa(sig) => { + SignatureKindProto::Erc191(RecoverableEcdsaSignatureProto { + bytes: sig.signature_bytes, + }) + } + }; + + Self { + signature: Some(signature), } - }) + } } -impl From for IdentityUpdateProto { - fn from(update: IdentityUpdate) -> IdentityUpdateProto { - let actions: Vec = - update.actions.into_iter().map(Into::into).collect(); +impl TryFrom> for UnverifiedIdentityUpdate { + type Error = DeserializationError; - IdentityUpdateProto { - client_timestamp_ns: update.client_timestamp_ns, - inbox_id: update.inbox_id, - actions, - } + fn try_from(value: Vec) -> Result { + let update_proto: IdentityUpdateProto = IdentityUpdateProto::decode(value.as_slice())?; + UnverifiedIdentityUpdate::try_from(update_proto) } } -impl From for IdentityActionProto { - fn from(action: Action) -> IdentityActionProto { - match action { - Action::AddAssociation(add_association) => IdentityActionProto { - kind: Some(IdentityActionKindProto::Add(AddAssociationProto { - new_member_identifier: Some(add_association.new_member_identifier.into()), - new_member_signature: Some(add_association.new_member_signature.to_proto()), - existing_member_signature: Some( - add_association.existing_member_signature.to_proto(), - ), - })), - }, - Action::CreateInbox(create_inbox) => IdentityActionProto { - kind: Some(IdentityActionKindProto::CreateInbox(CreateInboxProto { - nonce: create_inbox.nonce, - initial_address: create_inbox.account_address, - initial_address_signature: Some( - create_inbox.initial_address_signature.to_proto(), - ), - })), - }, - Action::RevokeAssociation(revoke_association) => IdentityActionProto { - kind: Some(IdentityActionKindProto::Revoke(RevokeAssociationProto { - member_to_revoke: Some(revoke_association.revoked_member.into()), - recovery_address_signature: Some( - revoke_association.recovery_address_signature.to_proto(), - ), - })), - }, - Action::ChangeRecoveryAddress(change_recovery_address) => IdentityActionProto { - kind: Some(IdentityActionKindProto::ChangeRecoveryAddress( - ChangeRecoveryAddressProto { - new_recovery_address: change_recovery_address.new_recovery_address, - existing_recovery_address_signature: Some( - change_recovery_address - .recovery_address_signature - .to_proto(), - ), - }, - )), - }, +impl From for Vec { + fn from(value: UnverifiedIdentityUpdate) -> Self { + let proto: IdentityUpdateProto = value.into(); + proto.encode_to_vec() + } +} + +impl From for MemberIdentifier { + fn from(proto: MemberIdentifierKindProto) -> Self { + match proto { + MemberIdentifierKindProto::Address(address) => address.into(), + MemberIdentifierKindProto::InstallationPublicKey(public_key) => public_key.into(), } } } @@ -317,6 +318,7 @@ impl From for MemberProto { MemberProto { identifier: Some(member.identifier.into()), added_by_entity: member.added_by_entity.map(Into::into), + client_timestamp_ns: member.client_timestamp_ns, } } } @@ -331,6 +333,7 @@ impl TryFrom for Member { .ok_or(DeserializationError::MissingMemberIdentifier)? .try_into()?, added_by_entity: proto.added_by_entity.map(TryInto::try_into).transpose()?, + client_timestamp_ns: proto.client_timestamp_ns, }) } } @@ -432,6 +435,7 @@ pub fn try_map_vec>(other: Vec) -> Result, for ValidatedLegacySignedPublicKey { type Error = SignatureError; @@ -460,9 +464,12 @@ impl TryFrom for ValidatedLegacySignedPublicKey { signature } }; - let wallet_signature = RecoverableSignature::Eip191Signature(wallet_signature); - let account_address = - wallet_signature.recover_address(&Self::text(&serialized_key_data))?; + let verified_wallet_signature = VerifiedSignature::from_recoverable_ecdsa( + Self::text(&serialized_key_data), + &wallet_signature, + )?; + + let account_address = verified_wallet_signature.signer.to_string(); let account_address = sanitize_evm_addresses(vec![account_address])?[0].clone(); let legacy_unsigned_public_key_proto = @@ -480,7 +487,7 @@ impl TryFrom for ValidatedLegacySignedPublicKey { Ok(Self { account_address, - wallet_signature, + wallet_signature: verified_wallet_signature, serialized_key_data, public_key_bytes, created_ns, @@ -490,7 +497,7 @@ impl TryFrom for ValidatedLegacySignedPublicKey { impl From for LegacySignedPublicKeyProto { fn from(validated: ValidatedLegacySignedPublicKey) -> Self { - let RecoverableSignature::Eip191Signature(signature) = validated.wallet_signature; + let signature = validated.wallet_signature.raw_bytes; Self { key_bytes: validated.serialized_key_data, signature: Some(SignedPublicKeySignatureProto { @@ -512,12 +519,15 @@ impl TryFrom for AccountId { return Err(DeserializationError::InvalidAccountId); } let chain_id = format!("{}:{}", parts[0], parts[1]); - let chain_id_regex = Regex::new(r"^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$").unwrap(); + let chain_id_regex = Regex::new(r"^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$") + .expect("Static regex should always compile"); let account_address = parts[2]; - let account_address_regex = Regex::new(r"^[-.%a-zA-Z0-9]{1,128}$").unwrap(); + let account_address_regex = + Regex::new(r"^[-.%a-zA-Z0-9]{1,128}$").expect("static regex should always compile"); if !chain_id_regex.is_match(&chain_id) || !account_address_regex.is_match(account_address) { return Err(DeserializationError::InvalidAccountId); } + Ok(AccountId { chain_id: chain_id.to_string(), account_address: account_address.to_string(), @@ -543,28 +553,58 @@ impl From for String { mod tests { use crate::associations::{ hashes::generate_inbox_id, - test_utils::{rand_string, rand_u64}, + test_utils::{rand_string, rand_u64, rand_vec}, }; use super::*; #[test] - fn test_round_trip() { + fn test_round_trip_unverified() { let account_address = rand_string(); let nonce = rand_u64(); let inbox_id = generate_inbox_id(&account_address, &nonce); + let client_timestamp_ns = rand_u64(); + let signature_bytes = rand_vec(); - let identity_update = IdentityUpdate::new( - vec![Action::CreateInbox(CreateInbox { - nonce, - account_address, - initial_address_signature: Box::new(RecoverableEcdsaSignature::new( - "foo".to_string(), - vec![1, 2, 3], - )), - })], + let identity_update = UnverifiedIdentityUpdate::new( inbox_id, - rand_u64(), + client_timestamp_ns, + vec![ + UnverifiedAction::CreateInbox(UnverifiedCreateInbox { + initial_address_signature: UnverifiedSignature::RecoverableEcdsa( + UnverifiedRecoverableEcdsaSignature::new(signature_bytes), + ), + unsigned_action: UnsignedCreateInbox { + nonce, + account_address, + }, + }), + UnverifiedAction::AddAssociation(UnverifiedAddAssociation { + new_member_signature: UnverifiedSignature::new_recoverable_ecdsa(vec![1, 2, 3]), + existing_member_signature: UnverifiedSignature::new_recoverable_ecdsa(vec![ + 4, 5, 6, + ]), + unsigned_action: UnsignedAddAssociation { + new_member_identifier: rand_string().into(), + }, + }), + UnverifiedAction::ChangeRecoveryAddress(UnverifiedChangeRecoveryAddress { + recovery_address_signature: UnverifiedSignature::new_recoverable_ecdsa(vec![ + 7, 8, 9, + ]), + unsigned_action: UnsignedChangeRecoveryAddress { + new_recovery_address: rand_string(), + }, + }), + UnverifiedAction::RevokeAssociation(UnverifiedRevokeAssociation { + recovery_address_signature: UnverifiedSignature::new_recoverable_ecdsa(vec![ + 10, 11, 12, + ]), + unsigned_action: UnsignedRevokeAssociation { + revoked_member: rand_string().into(), + }, + }), + ], ); let serialized_update = IdentityUpdateProto::from(identity_update.clone()); @@ -573,10 +613,14 @@ mod tests { serialized_update.client_timestamp_ns, identity_update.client_timestamp_ns ); - assert_eq!(serialized_update.actions.len(), 1); + assert_eq!(serialized_update.actions.len(), 4); + + let deserialized_update: UnverifiedIdentityUpdate = serialized_update + .clone() + .try_into() + .expect("deserialization error"); - let deserialized_update = from_identity_update_proto(serialized_update.clone()) - .expect("deserialization should succeed"); + assert_eq!(deserialized_update, identity_update); let reserialized = IdentityUpdateProto::from(deserialized_update); @@ -684,4 +728,13 @@ mod tests { Err(DeserializationError::InvalidAccountId) )); } + + #[test] + fn test_account_id_create() { + let address = "0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb".to_string(); + let chain_id = 12; + let account_id = AccountId::new_evm(chain_id, address.clone()); + assert_eq!(account_id.account_address, address); + assert_eq!(account_id.chain_id, "eip155:12"); + } } diff --git a/xmtp_id/src/associations/signature.rs b/xmtp_id/src/associations/signature.rs index 7a4190d51..ef49e9ef7 100644 --- a/xmtp_id/src/associations/signature.rs +++ b/xmtp_id/src/associations/signature.rs @@ -1,32 +1,14 @@ -use super::MemberIdentifier; -use crate::constants::INSTALLATION_KEY_SIGNATURE_CONTEXT; -use async_trait::async_trait; -use ed25519_dalek::{Signature as Ed25519Signature, VerifyingKey}; -use ethers::{ - core::k256, - providers::{Http, Middleware, Provider}, - signers::{LocalWallet, Signer}, - types::{BlockNumber, U64}, - utils::{hash_message, public_key_to_address}, -}; +use ethers::signers::{LocalWallet, Signer}; use prost::Message; -use sha2::{Digest, Sha512}; use std::array::TryFromSliceError; use thiserror::Error; -use xmtp_cryptography::signature::{h160addr_to_string, RecoverableSignature}; -use xmtp_proto::xmtp::{ - identity::associations::{ - signature::Signature as SignatureKindProto, - LegacyDelegatedSignature as LegacyDelegatedSignatureProto, - RecoverableEcdsaSignature as RecoverableEcdsaSignatureProto, - RecoverableEd25519Signature as RecoverableEd25519SignatureProto, - Signature as SignatureProto, - SmartContractWalletSignature as SmartContractWalletSignatureProto, - }, - message_contents::{ - signed_private_key, SignedPrivateKey as LegacySignedPrivateKeyProto, - SignedPublicKey as LegacySignedPublicKeyProto, - }, +use xmtp_proto::xmtp::message_contents::{ + signed_private_key, SignedPrivateKey as LegacySignedPrivateKeyProto, +}; + +use super::{ + unverified::{UnverifiedLegacyDelegatedSignature, UnverifiedRecoverableEcdsaSignature}, + verified_signature::VerifiedSignature, }; #[derive(Debug, Error)] @@ -38,7 +20,6 @@ pub enum SignatureError { WalletError(#[from] ethers::signers::WalletError), #[error(transparent)] ECDSAError(#[from] ethers::types::SignatureError), - #[error("Malformed legacy key: {0}")] MalformedLegacyKey(String), #[error(transparent)] @@ -80,78 +61,8 @@ impl std::fmt::Display for SignatureKind { } } } - -#[async_trait] -pub trait Signature: SignatureClone + std::fmt::Debug + Send + Sync + 'static { - async fn recover_signer(&self) -> Result; - fn signature_kind(&self) -> SignatureKind; - fn bytes(&self) -> Vec; - fn to_proto(&self) -> SignatureProto; -} - -pub trait SignatureClone { - fn clone_box(&self) -> Box; -} - -impl SignatureClone for T -where - T: 'static + Signature + Clone, -{ - fn clone_box(&self) -> Box { - Box::new(self.clone()) - } -} - -impl Clone for Box { - fn clone(&self) -> Box { - self.clone_box() - } -} - -#[allow(dead_code)] -#[derive(Debug, Clone)] -pub struct RecoverableEcdsaSignature { - signature_text: String, - signature_bytes: Vec, -} - -impl RecoverableEcdsaSignature { - pub fn new(signature_text: String, signature_bytes: Vec) -> Self { - RecoverableEcdsaSignature { - signature_text, - signature_bytes, - } - } -} - -#[async_trait] -impl Signature for RecoverableEcdsaSignature { - async fn recover_signer(&self) -> Result { - let signature = ethers::types::Signature::try_from(self.bytes().as_slice())?; - Ok(MemberIdentifier::Address(h160addr_to_string( - signature.recover(self.signature_text.clone())?, - ))) - } - - fn signature_kind(&self) -> SignatureKind { - SignatureKind::Erc191 - } - - fn bytes(&self) -> Vec { - self.signature_bytes.clone() - } - - fn to_proto(&self) -> SignatureProto { - SignatureProto { - signature: Some(SignatureKindProto::Erc191(RecoverableEcdsaSignatureProto { - bytes: self.bytes(), - })), - } - } -} - // CAIP-10[https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct AccountId { pub(crate) chain_id: String, pub(crate) account_address: String, @@ -164,224 +75,17 @@ impl AccountId { account_address, } } - pub fn is_evm_chain(&self) -> bool { - self.chain_id.starts_with("eip155") - } - pub fn get_account_address(&self) -> &str { - &self.account_address - } -} - -/// A ERC-6492 signature. -#[derive(Debug, Clone)] -pub struct SmartContractWalletSignature { - signature_text: String, - signature_bytes: Vec, - account_id: AccountId, - block_number: u64, - chain_rpc_url: String, -} - -unsafe impl Send for SmartContractWalletSignature {} - -impl SmartContractWalletSignature { - pub fn new( - signature_text: String, - signature_bytes: Vec, - account_id: AccountId, - chain_rpc_url: String, - block_number: u64, - ) -> Self { - SmartContractWalletSignature { - signature_text, - signature_bytes, - account_id, - chain_rpc_url, - block_number, - } - } - - /// Fetch Chain ID & block number from the RPC URL and create the new ERC1271 Signature - /// This could be used by platform SDK who only needs to provide the RPC URL and account address. - pub async fn new_with_rpc( - signature_text: String, - signature_bytes: Vec, - account_address: String, - chain_rpc_url: String, - ) -> Result { - let provider = Provider::::try_from(&chain_rpc_url)?; - let block_number = provider.get_block_number().await?; - let chain_id = provider.get_chainid().await?; - let account_id = AccountId::new(chain_id.to_string(), account_address); - Ok(SmartContractWalletSignature::new( - signature_text, - signature_bytes, - account_id, - chain_rpc_url, - block_number.as_u64(), - )) - } -} - -#[async_trait] -impl Signature for SmartContractWalletSignature { - async fn recover_signer(&self) -> Result { - let verifier = - crate::scw_verifier::SmartContractWalletVerifier::new(self.chain_rpc_url.clone()); - let is_valid = verifier - .is_valid_signature( - self.account_id.get_account_address().parse()?, - hash_message(self.signature_text.clone()).into(), // the hash function should match the one used by the user wallet - &self.bytes().into(), - Some(BlockNumber::Number(U64::from(self.block_number))), - ) - .await?; - if is_valid { - Ok(MemberIdentifier::Address( - self.account_id - .get_account_address() - .to_string() - .to_lowercase(), - )) - } else { - Err(SignatureError::Invalid) - } - } - - fn signature_kind(&self) -> SignatureKind { - SignatureKind::Erc1271 - } - - fn bytes(&self) -> Vec { - self.signature_bytes.clone() - } - - fn to_proto(&self) -> SignatureProto { - SignatureProto { - signature: Some(SignatureKindProto::Erc6492( - SmartContractWalletSignatureProto { - account_id: self.account_id.clone().into(), - block_number: self.block_number, - signature: self.bytes(), - chain_rpc_url: self.chain_rpc_url.clone(), - }, - )), - } - } -} - -#[derive(Clone, Debug)] -pub struct InstallationKeySignature { - signature_text: String, - signature_bytes: Vec, - verifying_key: Vec, -} - -impl InstallationKeySignature { - pub fn new(signature_text: String, signature_bytes: Vec, verifying_key: Vec) -> Self { - InstallationKeySignature { - signature_text, - signature_bytes, - verifying_key, - } - } -} - -#[async_trait] -impl Signature for InstallationKeySignature { - async fn recover_signer(&self) -> Result { - let signature: Ed25519Signature = - Ed25519Signature::from_bytes(self.bytes().as_slice().try_into()?); - let verifying_key: VerifyingKey = - VerifyingKey::from_bytes(&self.verifying_key.as_slice().try_into()?)?; - let mut prehashed: Sha512 = Sha512::new(); - prehashed.update(self.signature_text.clone()); - verifying_key.verify_prehashed( - prehashed, - Some(INSTALLATION_KEY_SIGNATURE_CONTEXT), - &signature, - )?; - Ok(MemberIdentifier::Installation(self.verifying_key.clone())) - } - - fn signature_kind(&self) -> SignatureKind { - SignatureKind::InstallationKey - } - - fn bytes(&self) -> Vec { - self.signature_bytes.clone() - } - fn to_proto(&self) -> SignatureProto { - SignatureProto { - signature: Some(SignatureKindProto::InstallationKey( - RecoverableEd25519SignatureProto { - bytes: self.bytes(), - public_key: self.verifying_key.clone(), - }, - )), - } - } -} - -#[derive(Debug, Clone)] -pub struct LegacyDelegatedSignature { - legacy_key_signature: RecoverableEcdsaSignature, // signature from the legacy key(delegatee) - signed_public_key_proto: LegacySignedPublicKeyProto, // signature from the wallet(delegator) -} - -impl LegacyDelegatedSignature { - pub fn new( - legacy_key_signature: RecoverableEcdsaSignature, - signed_public_key_proto: LegacySignedPublicKeyProto, - ) -> Self { - LegacyDelegatedSignature { - legacy_key_signature, - signed_public_key_proto, - } + pub fn new_evm(chain_id: u64, account_address: String) -> Self { + Self::new(format!("eip155:{}", chain_id), account_address) } -} -#[async_trait] -impl Signature for LegacyDelegatedSignature { - async fn recover_signer(&self) -> Result { - // Recover the RecoverableEcdsaSignature of the legacy signer(address of the legacy key) - let legacy_signer = self.legacy_key_signature.recover_signer().await?; - // Derive the address from legacy public key and compare it with legacy_signer. - // Note that it's not recovering the address from the __signed__ public key. - let signed_public_key: ValidatedLegacySignedPublicKey = - self.signed_public_key_proto.clone().try_into()?; - let public_key: k256::ecdsa::VerifyingKey = - k256::ecdsa::VerifyingKey::from_sec1_bytes(&signed_public_key.public_key_bytes)?; - let address = h160addr_to_string(public_key_to_address(&public_key)); - if MemberIdentifier::Address(address) != legacy_signer { - return Err(SignatureError::Invalid); - } - - Ok(MemberIdentifier::Address( - signed_public_key.account_address().to_lowercase(), - )) - } - - fn signature_kind(&self) -> SignatureKind { - SignatureKind::LegacyDelegated - } - - fn bytes(&self) -> Vec { - self.legacy_key_signature.bytes() + pub fn is_evm_chain(&self) -> bool { + self.chain_id.starts_with("eip155") } - fn to_proto(&self) -> SignatureProto { - SignatureProto { - signature: Some(SignatureKindProto::DelegatedErc191( - LegacyDelegatedSignatureProto { - delegated_key: Some(self.signed_public_key_proto.clone()), - signature: Some(RecoverableEcdsaSignatureProto { - bytes: self.bytes(), - }), - }, - )), - } + pub fn get_account_address(&self) -> &str { + &self.account_address } } @@ -389,7 +93,7 @@ impl Signature for LegacyDelegatedSignature { pub async fn sign_with_legacy_key( signature_text: String, legacy_signed_private_key: Vec, -) -> Result { +) -> Result { let legacy_signed_private_key_proto = LegacySignedPrivateKeyProto::decode(legacy_signed_private_key.as_slice())?; let signed_private_key::Union::Secp256k1(secp256k1) = legacy_signed_private_key_proto @@ -408,10 +112,8 @@ pub async fn sign_with_legacy_key( "Missing public_key field".to_string(), ))?; - let recoverable_sig = RecoverableEcdsaSignature::new(signature_text, signature.to_vec()); - - Ok(LegacyDelegatedSignature::new( - recoverable_sig, + Ok(UnverifiedLegacyDelegatedSignature::new( + UnverifiedRecoverableEcdsaSignature::new(signature.to_vec()), legacy_signed_public_key_proto, )) } @@ -420,7 +122,7 @@ pub async fn sign_with_legacy_key( pub struct ValidatedLegacySignedPublicKey { pub(crate) account_address: String, pub(crate) serialized_key_data: Vec, - pub(crate) wallet_signature: RecoverableSignature, + pub(crate) wallet_signature: VerifiedSignature, pub(crate) public_key_bytes: Vec, pub(crate) created_ns: u64, } @@ -461,165 +163,3 @@ impl ValidatedLegacySignedPublicKey { self.created_ns } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - associations::{ - signature::Signature, - test_utils::{rand_u64, MockSignature}, - unsigned_actions::{SignatureTextCreator, UnsignedAddAssociation, UnsignedCreateInbox}, - }, - InboxOwner, - }; - use ed25519_dalek::SigningKey; - use ethers::prelude::*; - - use prost::Message; - use sha2::{Digest, Sha512}; - use xmtp_proto::xmtp::message_contents::SignedPublicKey as LegacySignedPublicKeyProto; - use xmtp_v2::k256_helper::sign_sha256; - - #[test] - fn validate_good_key_round_trip() { - let proto_bytes = vec![ - 10, 79, 8, 192, 195, 165, 174, 203, 153, 231, 213, 23, 26, 67, 10, 65, 4, 216, 84, 174, - 252, 198, 225, 219, 168, 239, 166, 62, 233, 206, 108, 53, 155, 87, 132, 8, 43, 91, 36, - 91, 81, 93, 213, 67, 241, 69, 5, 31, 249, 186, 129, 119, 144, 4, 44, 54, 76, 185, 95, - 61, 23, 231, 72, 7, 169, 18, 70, 113, 79, 173, 82, 13, 37, 146, 201, 43, 174, 180, 33, - 125, 43, 18, 70, 18, 68, 10, 64, 7, 136, 100, 172, 155, 247, 230, 255, 253, 247, 78, - 50, 212, 226, 41, 78, 239, 183, 136, 247, 122, 88, 155, 245, 219, 183, 215, 202, 42, - 89, 162, 128, 96, 96, 120, 131, 17, 70, 38, 231, 2, 27, 91, 29, 66, 110, 128, 140, 1, - 42, 217, 185, 2, 181, 208, 100, 143, 143, 219, 159, 174, 1, 233, 191, 16, 1, - ]; - let account_address = "0x220ca99fb7fafa18cb623d924794dde47b4bc2e9"; - - let proto = LegacySignedPublicKeyProto::decode(proto_bytes.as_slice()).unwrap(); - let validated_key = ValidatedLegacySignedPublicKey::try_from(proto) - .expect("Key should validate successfully"); - let proto: LegacySignedPublicKeyProto = validated_key.into(); - let validated_key = ValidatedLegacySignedPublicKey::try_from(proto) - .expect("Key should still validate successfully"); - assert_eq!(validated_key.account_address(), account_address); - } - - #[test] - fn validate_malformed_key() { - let proto_bytes = vec![ - 10, 79, 8, 192, 195, 165, 174, 203, 153, 231, 213, 23, 26, 67, 10, 65, 4, 216, 84, 174, - 252, 198, 225, 219, 168, 239, 166, 62, 233, 206, 108, 53, 155, 87, 132, 8, 43, 91, 36, - 91, 81, 93, 213, 67, 241, 69, 5, 31, 249, 186, 129, 119, 144, 4, 44, 54, 76, 185, 95, - 61, 23, 231, 72, 7, 169, 18, 70, 113, 79, 173, 82, 13, 37, 146, 201, 43, 174, 180, 33, - 125, 43, 18, 70, 18, 68, 10, 64, 7, 136, 100, 172, 155, 247, 230, 255, 253, 247, 78, - 50, 212, 226, 41, 78, 239, 183, 136, 247, 122, 88, 155, 245, 219, 183, 215, 202, 42, - 89, 162, 128, 96, 96, 120, 131, 17, 70, 38, 231, 2, 27, 91, 29, 66, 110, 128, 140, 1, - 42, 217, 185, 2, 181, 208, 100, 143, 143, 219, 159, 174, 1, 233, 191, 16, 1, - ]; - let mut proto = LegacySignedPublicKeyProto::decode(proto_bytes.as_slice()).unwrap(); - proto.key_bytes[0] += 1; // Corrupt the serialized key data - assert!(matches!( - ValidatedLegacySignedPublicKey::try_from(proto), - Err(super::SignatureError::Invalid) - )); - } - - #[tokio::test] - async fn recover_signer_ecdsa() { - let wallet: LocalWallet = LocalWallet::new(&mut rand::thread_rng()); - let unsigned_action = UnsignedCreateInbox { - nonce: rand_u64(), - account_address: wallet.get_address(), - }; - let signature_text = unsigned_action.signature_text(); - let signature_bytes: Vec = wallet - .sign_message(signature_text.clone()) - .await - .unwrap() - .to_vec(); - let signature = RecoverableEcdsaSignature::new(signature_text.clone(), signature_bytes); - let expected = MemberIdentifier::Address(wallet.get_address()); - let actual = signature.recover_signer().await.unwrap(); - - assert_eq!(expected, actual); - } - - #[tokio::test] - async fn recover_signer_erc1271() { - let wallet: LocalWallet = LocalWallet::new(&mut rand::thread_rng()); - - let mock_erc1271 = MockSignature::new_boxed( - true, - MemberIdentifier::Address(wallet.get_address()), - SignatureKind::Erc1271, - None, - ); - - let expected = MemberIdentifier::Address(wallet.get_address()); - let actual = mock_erc1271.recover_signer().await.unwrap(); - assert_eq!(expected, actual); - } - - #[tokio::test] - async fn recover_signer_installation() { - let signing_key: SigningKey = SigningKey::generate(&mut rand::thread_rng()); - let verifying_key = signing_key.verifying_key(); - - let unsigned_action = UnsignedAddAssociation { - new_member_identifier: MemberIdentifier::Address("0x123456789abcdef".to_string()), - }; - let signature_text = unsigned_action.signature_text(); - let mut prehashed: Sha512 = Sha512::new(); - prehashed.update(signature_text.clone()); - let sig = signing_key - .sign_prehashed(prehashed, Some(INSTALLATION_KEY_SIGNATURE_CONTEXT)) - .unwrap(); - let installation_key_sig = InstallationKeySignature::new( - signature_text.clone(), - sig.to_vec(), - verifying_key.as_bytes().to_vec(), - ); - let expected = MemberIdentifier::Installation(verifying_key.as_bytes().to_vec()); - let actual = installation_key_sig.recover_signer().await.unwrap(); - assert_eq!(expected, actual); - } - - // Test the happy path with LocalWallet & fail path with a secp256k1 signer. - #[tokio::test] - async fn recover_signer_legacy() { - let signature_text = "test_legacy_signature".to_string(); - let account_address = "0x0bd00b21af9a2d538103c3aaf95cb507f8af1b28".to_string(); - let legacy_signed_private_key = hex::decode("0880bdb7a8b3f6ede81712220a20ad528ea38ce005268c4fb13832cfed13c2b2219a378e9099e48a38a30d66ef991a96010a4c08aaa8e6f5f9311a430a41047fd90688ca39237c2899281cdf2756f9648f93767f91c0e0f74aed7e3d3a8425e9eaa9fa161341c64aa1c782d004ff37ffedc887549ead4a40f18d1179df9dff124612440a403c2cb2338fb98bfe5f6850af11f6a7e97a04350fc9d37877060f8d18e8f66de31c77b3504c93cf6a47017ea700a48625c4159e3f7e75b52ff4ea23bc13db77371001").unwrap(); - - // happy path - let legacy_signature = - sign_with_legacy_key(signature_text.clone(), legacy_signed_private_key.clone()) - .await - .unwrap(); - let expected = MemberIdentifier::Address(account_address.clone()); - let actual = legacy_signature.recover_signer().await.unwrap(); - assert_eq!(expected, actual); - - // fail path - let legacy_signed_private_key_proto = - LegacySignedPrivateKeyProto::decode(legacy_signed_private_key.as_slice()).unwrap(); - let signed_private_key::Union::Secp256k1(secp256k1) = - legacy_signed_private_key_proto.union.unwrap(); - let legacy_private_key = secp256k1.bytes; - let (mut legacy_signature, recovery_id) = sign_sha256( - &legacy_private_key, // secret_key - signature_text.as_bytes(), // message - ) - .unwrap(); - legacy_signature.push(recovery_id); - let legacy_signature = RecoverableEcdsaSignature::new(signature_text, legacy_signature); - let legacy_signed_public_key_proto = legacy_signed_private_key_proto.public_key.unwrap(); - let legacy_signature: LegacyDelegatedSignature = - LegacyDelegatedSignature::new(legacy_signature, legacy_signed_public_key_proto); - - assert!(matches!( - legacy_signature.recover_signer().await, - Err(super::SignatureError::Invalid) - )); - } -} diff --git a/xmtp_id/src/associations/state.rs b/xmtp_id/src/associations/state.rs index 83cc8752e..a22e4b659 100644 --- a/xmtp_id/src/associations/state.rs +++ b/xmtp_id/src/associations/state.rs @@ -13,6 +13,12 @@ pub struct AssociationStateDiff { pub removed_members: Vec, } +#[derive(Debug)] +pub struct Installation { + pub id: Vec, + pub client_timestamp_ns: Option, +} + impl AssociationStateDiff { pub fn new_installations(&self) -> Vec> { self.new_members @@ -128,6 +134,19 @@ impl AssociationState { .collect() } + pub fn installations(&self) -> Vec { + self.members() + .into_iter() + .filter_map(|member| match member.identifier { + MemberIdentifier::Address(_) => None, + MemberIdentifier::Installation(id) => Some(Installation { + id, + client_timestamp_ns: member.client_timestamp_ns, + }), + }) + .collect() + } + pub fn diff(&self, new_state: &Self) -> AssociationStateDiff { let new_members: Vec = new_state .members @@ -163,13 +182,9 @@ impl AssociationState { pub fn new(account_address: String, nonce: u64) -> Self { let inbox_id = generate_inbox_id(&account_address, &nonce); let identifier = MemberIdentifier::Address(account_address.clone()); - let new_member = Member::new(identifier.clone(), None); + let new_member = Member::new(identifier.clone(), None, None); Self { - members: { - let mut members = HashMap::new(); - members.insert(identifier, new_member); - members - }, + members: HashMap::from_iter([(identifier, new_member)]), seen_signatures: HashSet::new(), recovery_address: account_address.to_lowercase(), inbox_id, diff --git a/xmtp_id/src/associations/test_utils.rs b/xmtp_id/src/associations/test_utils.rs index f3cd5f2b7..9a64aa68b 100644 --- a/xmtp_id/src/associations/test_utils.rs +++ b/xmtp_id/src/associations/test_utils.rs @@ -1,19 +1,21 @@ -use rand::{distributions::Alphanumeric, Rng}; -use xmtp_proto::xmtp::{ - identity::associations::{ - signature::Signature as SignatureKindProto, - LegacyDelegatedSignature as LegacyDelegatedSignatureProto, - RecoverableEcdsaSignature as RecoverableEcdsaSignatureProto, - RecoverableEd25519Signature as RecoverableEd25519SignatureProto, - Signature as SignatureProto, - SmartContractWalletSignature as SmartContractWalletSignatureProto, - }, - message_contents::{ - Signature as LegacySignatureProto, SignedPublicKey as LegacySignedPublicKeyProto, - }, +use super::{ + builder::SignatureRequest, + unsigned_actions::UnsignedCreateInbox, + unverified::{UnverifiedAction, UnverifiedCreateInbox, UnverifiedSignature}, + AccountId, }; - -use super::{MemberIdentifier, Signature, SignatureError, SignatureKind}; +use crate::{ + constants::INSTALLATION_KEY_SIGNATURE_CONTEXT, + scw_verifier::{SmartContractSignatureVerifier, VerifierError}, +}; +use ed25519_dalek::SigningKey as Ed25519SigningKey; +use ethers::{ + core::types::BlockNumber, + signers::{LocalWallet, Signer}, + types::{Bytes, U64}, +}; +use rand::{distributions::Alphanumeric, Rng}; +use sha2::{Digest, Sha512}; pub fn rand_string() -> String { let v: String = rand::thread_rng() @@ -36,86 +38,79 @@ pub fn rand_vec() -> Vec { } #[derive(Debug, Clone)] -pub struct MockSignature { - is_valid: bool, - signer_identity: MemberIdentifier, - signature_kind: SignatureKind, - signature_nonce: String, +pub struct MockSmartContractSignatureVerifier { + is_valid_signature: bool, } -impl MockSignature { - pub fn new_boxed( - is_valid: bool, - signer_identity: MemberIdentifier, - signature_kind: SignatureKind, - // Signature nonce is used to control what the signature bytes are - // Defaults to random - signature_nonce: Option, - ) -> Box { - let nonce = signature_nonce.unwrap_or(rand_string()); - Box::new(Self { - is_valid, - signer_identity, - signature_kind, - signature_nonce: nonce, - }) +impl MockSmartContractSignatureVerifier { + pub fn new(is_valid_signature: bool) -> Self { + Self { is_valid_signature } } } #[async_trait::async_trait] -impl Signature for MockSignature { - fn signature_kind(&self) -> SignatureKind { - self.signature_kind.clone() +impl SmartContractSignatureVerifier for MockSmartContractSignatureVerifier { + async fn is_valid_signature( + &self, + _account_id: AccountId, + _hash: [u8; 32], + _signature: Bytes, + _block_number: Option, + ) -> Result { + Ok(self.is_valid_signature) } - async fn recover_signer(&self) -> Result { - match self.is_valid { - true => Ok(self.signer_identity.clone()), - false => Err(SignatureError::Invalid), - } + async fn current_block_number(&self, _chain_id: &str) -> Result { + Ok(1.into()) } +} - fn bytes(&self) -> Vec { - let sig = format!("{}{}", self.signer_identity, self.signature_nonce); - sig.as_bytes().to_vec() - } +pub async fn add_wallet_signature(signature_request: &mut SignatureRequest, wallet: &LocalWallet) { + let signature_text = signature_request.signature_text(); + let sig = wallet.sign_message(signature_text).await.unwrap().to_vec(); + let unverified_sig = UnverifiedSignature::new_recoverable_ecdsa(sig); + let scw_verifier = MockSmartContractSignatureVerifier::new(false); - fn to_proto(&self) -> SignatureProto { - match self.signature_kind { - SignatureKind::Erc191 => SignatureProto { - signature: Some(SignatureKindProto::Erc191(RecoverableEcdsaSignatureProto { - bytes: vec![0], - })), - }, - SignatureKind::Erc1271 => SignatureProto { - signature: Some(SignatureKindProto::Erc6492( - SmartContractWalletSignatureProto { - account_id: "eip155:1:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb".into(), - block_number: 0, - signature: vec![0], - chain_rpc_url: "https://example.com".to_string(), - }, - )), - }, - SignatureKind::InstallationKey => SignatureProto { - signature: Some(SignatureKindProto::InstallationKey( - RecoverableEd25519SignatureProto { - bytes: vec![0], - public_key: vec![0], - }, - )), - }, - SignatureKind::LegacyDelegated => SignatureProto { - signature: Some(SignatureKindProto::DelegatedErc191( - LegacyDelegatedSignatureProto { - delegated_key: Some(LegacySignedPublicKeyProto { - key_bytes: vec![0], - signature: Some(LegacySignatureProto { union: None }), - }), - signature: Some(RecoverableEcdsaSignatureProto { bytes: vec![0] }), - }, - )), + signature_request + .add_signature(unverified_sig, &scw_verifier) + .await + .expect("should succeed"); +} + +pub async fn add_installation_key_signature( + signature_request: &mut SignatureRequest, + installation_key: &Ed25519SigningKey, +) { + let signature_text = signature_request.signature_text(); + let verifying_key = installation_key.verifying_key(); + let mut prehashed: Sha512 = Sha512::new(); + prehashed.update(signature_text); + + let sig = installation_key + .sign_prehashed(prehashed, Some(INSTALLATION_KEY_SIGNATURE_CONTEXT)) + .unwrap(); + let unverified_sig = UnverifiedSignature::new_installation_key( + sig.to_bytes().to_vec(), + verifying_key.as_bytes().to_vec(), + ); + + signature_request + .add_signature( + unverified_sig, + &MockSmartContractSignatureVerifier::new(false), + ) + .await + .expect("should succeed"); +} + +impl UnverifiedAction { + pub fn new_test_create_inbox(account_address: &str, nonce: &u64) -> Self { + Self::CreateInbox(UnverifiedCreateInbox::new( + UnsignedCreateInbox { + account_address: account_address.to_owned(), + nonce: *nonce, }, - } + UnverifiedSignature::new_recoverable_ecdsa(vec![1, 2, 3]), + )) } } diff --git a/xmtp_id/src/associations/unsigned_actions.rs b/xmtp_id/src/associations/unsigned_actions.rs index 4c89e2d31..b0c21f9bf 100644 --- a/xmtp_id/src/associations/unsigned_actions.rs +++ b/xmtp_id/src/associations/unsigned_actions.rs @@ -11,7 +11,7 @@ pub trait SignatureTextCreator { fn signature_text(&self) -> String; } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedCreateInbox { pub nonce: u64, pub account_address: String, @@ -23,7 +23,7 @@ impl SignatureTextCreator for UnsignedCreateInbox { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedAddAssociation { pub new_member_identifier: MemberIdentifier, } @@ -40,7 +40,7 @@ impl SignatureTextCreator for UnsignedAddAssociation { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedRevokeAssociation { pub revoked_member: MemberIdentifier, } @@ -57,7 +57,7 @@ impl SignatureTextCreator for UnsignedRevokeAssociation { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedChangeRecoveryAddress { pub new_recovery_address: String, } @@ -73,7 +73,7 @@ impl SignatureTextCreator for UnsignedChangeRecoveryAddress { } #[allow(dead_code)] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum UnsignedAction { CreateInbox(UnsignedCreateInbox), AddAssociation(UnsignedAddAssociation), @@ -92,7 +92,7 @@ impl SignatureTextCreator for UnsignedAction { } } -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedIdentityUpdate { pub inbox_id: String, pub client_timestamp_ns: u64, diff --git a/xmtp_id/src/associations/unverified.rs b/xmtp_id/src/associations/unverified.rs new file mode 100644 index 000000000..9ce787fb0 --- /dev/null +++ b/xmtp_id/src/associations/unverified.rs @@ -0,0 +1,415 @@ +#![allow(dead_code)] +use crate::scw_verifier::SmartContractSignatureVerifier; + +use super::{ + unsigned_actions::{ + SignatureTextCreator, UnsignedAction, UnsignedAddAssociation, + UnsignedChangeRecoveryAddress, UnsignedCreateInbox, UnsignedIdentityUpdate, + UnsignedRevokeAssociation, + }, + verified_signature::VerifiedSignature, + AccountId, Action, AddAssociation, CreateInbox, IdentityUpdate, RevokeAssociation, + SignatureError, +}; +use futures::future::try_join_all; +use xmtp_proto::xmtp::message_contents::SignedPublicKey as LegacySignedPublicKeyProto; + +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedIdentityUpdate { + pub inbox_id: String, + pub client_timestamp_ns: u64, + pub actions: Vec, +} + +impl UnverifiedIdentityUpdate { + pub fn new(inbox_id: String, client_timestamp_ns: u64, actions: Vec) -> Self { + Self { + inbox_id, + client_timestamp_ns, + actions, + } + } + + fn signature_text(&self) -> String { + let unsigned_actions = self + .actions + .iter() + .map(|action| action.unsigned_action()) + .collect(); + let unsigned_identity_update = UnsignedIdentityUpdate::new( + unsigned_actions, + self.inbox_id.clone(), + self.client_timestamp_ns, + ); + + unsigned_identity_update.signature_text() + } + + fn signatures(&self) -> Vec { + self.actions + .iter() + .flat_map(|action| action.signatures()) + .collect() + } + + pub async fn to_verified( + &self, + scw_verifier: &dyn SmartContractSignatureVerifier, + ) -> Result { + let signature_text = self.signature_text(); + + let actions: Vec = try_join_all( + self.actions + .iter() + .map(|action| async { action.to_verified(&signature_text, scw_verifier).await }), + ) + .await?; + + Ok(IdentityUpdate::new( + actions, + self.inbox_id.clone(), + self.client_timestamp_ns, + )) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum UnverifiedAction { + CreateInbox(UnverifiedCreateInbox), + AddAssociation(UnverifiedAddAssociation), + RevokeAssociation(UnverifiedRevokeAssociation), + ChangeRecoveryAddress(UnverifiedChangeRecoveryAddress), +} + +impl UnverifiedAction { + fn unsigned_action(&self) -> UnsignedAction { + match self { + UnverifiedAction::CreateInbox(action) => { + UnsignedAction::CreateInbox(action.unsigned_action.clone()) + } + UnverifiedAction::AddAssociation(action) => { + UnsignedAction::AddAssociation(action.unsigned_action.clone()) + } + UnverifiedAction::RevokeAssociation(action) => { + UnsignedAction::RevokeAssociation(action.unsigned_action.clone()) + } + UnverifiedAction::ChangeRecoveryAddress(action) => { + UnsignedAction::ChangeRecoveryAddress(action.unsigned_action.clone()) + } + } + } + + fn signatures(&self) -> Vec { + match self { + UnverifiedAction::CreateInbox(action) => vec![action.initial_address_signature.clone()], + UnverifiedAction::AddAssociation(action) => vec![ + action.existing_member_signature.clone(), + action.new_member_signature.clone(), + ], + UnverifiedAction::RevokeAssociation(action) => { + vec![action.recovery_address_signature.clone()] + } + UnverifiedAction::ChangeRecoveryAddress(action) => { + vec![action.recovery_address_signature.clone()] + } + } + } + + pub async fn to_verified>( + &self, + signature_text: Text, + scw_verifier: &dyn SmartContractSignatureVerifier, + ) -> Result { + let action = match self { + UnverifiedAction::CreateInbox(action) => Action::CreateInbox(CreateInbox { + nonce: action.unsigned_action.nonce, + account_address: action.unsigned_action.account_address.clone(), + initial_address_signature: action + .initial_address_signature + .to_verified(signature_text.as_ref(), scw_verifier) + .await?, + }), + UnverifiedAction::AddAssociation(action) => Action::AddAssociation(AddAssociation { + new_member_signature: action + .new_member_signature + .to_verified(signature_text.as_ref(), scw_verifier) + .await?, + new_member_identifier: action.unsigned_action.new_member_identifier.clone(), + existing_member_signature: action + .existing_member_signature + .to_verified(signature_text.as_ref(), scw_verifier) + .await?, + }), + UnverifiedAction::RevokeAssociation(action) => { + Action::RevokeAssociation(RevokeAssociation { + recovery_address_signature: action + .recovery_address_signature + .to_verified(signature_text.as_ref(), scw_verifier) + .await?, + revoked_member: action.unsigned_action.revoked_member.clone(), + }) + } + UnverifiedAction::ChangeRecoveryAddress(action) => { + Action::ChangeRecoveryAddress(super::ChangeRecoveryAddress { + recovery_address_signature: action + .recovery_address_signature + .to_verified(signature_text.as_ref(), scw_verifier) + .await?, + new_recovery_address: action.unsigned_action.new_recovery_address.clone(), + }) + } + }; + + Ok(action) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedCreateInbox { + pub(crate) unsigned_action: UnsignedCreateInbox, + pub(crate) initial_address_signature: UnverifiedSignature, +} + +impl UnverifiedCreateInbox { + pub fn new( + unsigned_action: UnsignedCreateInbox, + initial_address_signature: UnverifiedSignature, + ) -> Self { + Self { + unsigned_action, + initial_address_signature, + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedAddAssociation { + pub(crate) unsigned_action: UnsignedAddAssociation, + pub(crate) new_member_signature: UnverifiedSignature, + pub(crate) existing_member_signature: UnverifiedSignature, +} + +impl UnverifiedAddAssociation { + pub fn new( + unsigned_action: UnsignedAddAssociation, + new_member_signature: UnverifiedSignature, + existing_member_signature: UnverifiedSignature, + ) -> Self { + Self { + unsigned_action, + new_member_signature, + existing_member_signature, + } + } +} +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedRevokeAssociation { + pub(crate) recovery_address_signature: UnverifiedSignature, + pub(crate) unsigned_action: UnsignedRevokeAssociation, +} + +impl UnverifiedRevokeAssociation { + pub fn new( + unsigned_action: UnsignedRevokeAssociation, + recovery_address_signature: UnverifiedSignature, + ) -> Self { + Self { + unsigned_action, + recovery_address_signature, + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedChangeRecoveryAddress { + pub(crate) recovery_address_signature: UnverifiedSignature, + pub(crate) unsigned_action: UnsignedChangeRecoveryAddress, +} + +impl UnverifiedChangeRecoveryAddress { + pub fn new( + unsigned_action: UnsignedChangeRecoveryAddress, + recovery_address_signature: UnverifiedSignature, + ) -> Self { + Self { + unsigned_action, + recovery_address_signature, + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub enum UnverifiedSignature { + InstallationKey(UnverifiedInstallationKeySignature), + RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature), + SmartContractWallet(UnverifiedSmartContractWalletSignature), + LegacyDelegated(UnverifiedLegacyDelegatedSignature), +} + +impl UnverifiedSignature { + pub async fn to_verified>( + &self, + signature_text: Text, + scw_verifier: &dyn SmartContractSignatureVerifier, + ) -> Result { + match self { + UnverifiedSignature::InstallationKey(sig) => VerifiedSignature::from_installation_key( + signature_text, + &sig.signature_bytes, + &sig.verifying_key, + ), + UnverifiedSignature::RecoverableEcdsa(sig) => { + VerifiedSignature::from_recoverable_ecdsa(signature_text, &sig.signature_bytes) + } + UnverifiedSignature::SmartContractWallet(sig) => { + VerifiedSignature::from_smart_contract_wallet( + signature_text, + scw_verifier, + &sig.signature_bytes, + sig.account_id.clone(), + Some(sig.block_number), + ) + .await + } + UnverifiedSignature::LegacyDelegated(sig) => VerifiedSignature::from_legacy_delegated( + signature_text, + &sig.legacy_key_signature.signature_bytes, + sig.signed_public_key_proto.clone(), + ), + } + } + + pub fn new_recoverable_ecdsa(signature: Vec) -> Self { + Self::RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature::new(signature)) + } + + pub fn new_installation_key(signature: Vec, verifying_key: Vec) -> Self { + Self::InstallationKey(UnverifiedInstallationKeySignature::new( + signature, + verifying_key, + )) + } + + pub fn new_smart_contract_wallet( + signature: Vec, + account_id: AccountId, + block_number: u64, + ) -> Self { + Self::SmartContractWallet(UnverifiedSmartContractWalletSignature::new( + signature, + account_id, + block_number, + )) + } + + pub fn new_legacy_delegated( + signature: Vec, + signed_public_key_proto: LegacySignedPublicKeyProto, + ) -> Self { + Self::LegacyDelegated(UnverifiedLegacyDelegatedSignature::new( + UnverifiedRecoverableEcdsaSignature::new(signature), + signed_public_key_proto, + )) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedInstallationKeySignature { + pub(crate) signature_bytes: Vec, + pub(crate) verifying_key: Vec, +} + +impl UnverifiedInstallationKeySignature { + pub fn new(signature_bytes: Vec, verifying_key: Vec) -> Self { + Self { + signature_bytes, + verifying_key, + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedRecoverableEcdsaSignature { + pub(crate) signature_bytes: Vec, +} + +impl UnverifiedRecoverableEcdsaSignature { + pub fn new(signature_bytes: Vec) -> Self { + Self { signature_bytes } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedSmartContractWalletSignature { + pub(crate) signature_bytes: Vec, + pub(crate) account_id: AccountId, + pub(crate) block_number: u64, +} + +impl UnverifiedSmartContractWalletSignature { + pub fn new(signature_bytes: Vec, account_id: AccountId, block_number: u64) -> Self { + Self { + signature_bytes, + account_id, + block_number, + } + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct UnverifiedLegacyDelegatedSignature { + pub(crate) legacy_key_signature: UnverifiedRecoverableEcdsaSignature, + pub(crate) signed_public_key_proto: LegacySignedPublicKeyProto, +} + +impl UnverifiedLegacyDelegatedSignature { + pub fn new( + legacy_key_signature: UnverifiedRecoverableEcdsaSignature, + signed_public_key_proto: LegacySignedPublicKeyProto, + ) -> Self { + Self { + legacy_key_signature, + signed_public_key_proto, + } + } +} + +#[cfg(test)] +mod tests { + use crate::associations::{ + generate_inbox_id, test_utils::rand_string, unsigned_actions::UnsignedCreateInbox, + }; + + use super::{ + UnverifiedAction, UnverifiedCreateInbox, UnverifiedIdentityUpdate, + UnverifiedRecoverableEcdsaSignature, UnverifiedSignature, + }; + + #[test] + fn create_identity_update() { + let account_address = rand_string(); + let nonce = 1; + let update = UnverifiedIdentityUpdate { + inbox_id: generate_inbox_id(account_address.as_str(), &nonce), + client_timestamp_ns: 10, + actions: vec![UnverifiedAction::CreateInbox(UnverifiedCreateInbox { + unsigned_action: UnsignedCreateInbox { + account_address: account_address.to_string(), + nonce, + }, + initial_address_signature: UnverifiedSignature::RecoverableEcdsa( + UnverifiedRecoverableEcdsaSignature { + signature_bytes: vec![1, 2, 3], + }, + ), + })], + }; + assert!( + update + .signature_text() + .contains(format!("(Owner: {})", account_address).as_str()), + "could not find account address in signature text: {}", + update.signature_text() + ); + } +} diff --git a/xmtp_id/src/associations/verified_signature.rs b/xmtp_id/src/associations/verified_signature.rs new file mode 100644 index 000000000..d33f034af --- /dev/null +++ b/xmtp_id/src/associations/verified_signature.rs @@ -0,0 +1,342 @@ +#![allow(dead_code)] + +use ed25519_dalek::{Signature as Ed25519Signature, VerifyingKey as Ed25519VerifyingKey}; +use ethers::types::Signature as EthersSignature; +use ethers::utils::hash_message; +use ethers::{core::k256::ecdsa::VerifyingKey as EcdsaVerifyingKey, utils::public_key_to_address}; +use sha2::{Digest, Sha512}; +use xmtp_cryptography::signature::h160addr_to_string; +use xmtp_proto::xmtp::message_contents::SignedPublicKey as LegacySignedPublicKeyProto; + +use crate::constants::INSTALLATION_KEY_SIGNATURE_CONTEXT; +use crate::scw_verifier::SmartContractSignatureVerifier; + +use super::{ + AccountId, MemberIdentifier, SignatureError, SignatureKind, ValidatedLegacySignedPublicKey, +}; + +#[derive(Debug, Clone)] +pub struct VerifiedSignature { + pub signer: MemberIdentifier, + pub kind: SignatureKind, + pub raw_bytes: Vec, +} + +impl VerifiedSignature { + pub fn new(signer: MemberIdentifier, kind: SignatureKind, raw_bytes: Vec) -> Self { + Self { + signer, + kind, + raw_bytes, + } + } + + /** + * Verifies an ECDSA signature against the provided signature text. + * Returns a VerifiedSignature if the signature is valid, otherwise returns an error. + */ + pub fn from_recoverable_ecdsa>( + signature_text: Text, + signature_bytes: &[u8], + ) -> Result { + let signature = EthersSignature::try_from(signature_bytes)?; + let address = h160addr_to_string(signature.recover(signature_text.as_ref())?); + + Ok(Self::new( + MemberIdentifier::Address(address), + SignatureKind::Erc191, + signature_bytes.to_vec(), + )) + } + + pub fn from_recoverable_ecdsa_with_expected_address>( + signature_text: Text, + signature_bytes: &[u8], + expected_address: Text, + ) -> Result { + let partially_verified = Self::from_recoverable_ecdsa(signature_text, signature_bytes)?; + if partially_verified + .signer + .address() + .ok_or(SignatureError::Invalid)? + .to_lowercase() + != expected_address.as_ref().to_lowercase() + { + return Err(SignatureError::Invalid); + } + + Ok(partially_verified) + } + + /** + * Verifies an installation key signature against the provided signature text and verifying key bytes. + * Returns a VerifiedSignature if the signature is valid, otherwise returns an error. + */ + pub fn from_installation_key>( + signature_text: Text, + signature_bytes: &[u8], + verifying_key_bytes: &[u8], + ) -> Result { + let signature = Ed25519Signature::from_bytes(signature_bytes.try_into()?); + let verifying_key = Ed25519VerifyingKey::from_bytes(verifying_key_bytes.try_into()?)?; + let mut prehashed = Sha512::new(); + prehashed.update(signature_text.as_ref()); + + verifying_key.verify_prehashed( + prehashed, + Some(INSTALLATION_KEY_SIGNATURE_CONTEXT), + &signature, + )?; + + Ok(Self::new( + MemberIdentifier::Installation(verifying_key_bytes.to_vec()), + SignatureKind::InstallationKey, + signature_bytes.to_vec(), + )) + } + + pub fn from_legacy_delegated>( + signature_text: Text, + signature_bytes: &[u8], + signed_public_key_proto: LegacySignedPublicKeyProto, + ) -> Result { + let verified_legacy_signature = + Self::from_recoverable_ecdsa(signature_text, signature_bytes)?; + let signed_public_key: ValidatedLegacySignedPublicKey = + signed_public_key_proto.try_into()?; + let public_key = EcdsaVerifyingKey::from_sec1_bytes(&signed_public_key.public_key_bytes)?; + let address = h160addr_to_string(public_key_to_address(&public_key)); + + if MemberIdentifier::Address(address) != verified_legacy_signature.signer { + return Err(SignatureError::Invalid); + } + + Ok(Self::new( + MemberIdentifier::Address(signed_public_key.account_address.to_lowercase()), + SignatureKind::LegacyDelegated, + // Must use the wallet signature bytes, since those are the ones we care about making unique. + // This protects against using the legacy key more than once in the Identity Update Log + signed_public_key.wallet_signature.raw_bytes, + )) + } + + pub async fn from_smart_contract_wallet>( + signature_text: Text, + signature_verifier: &dyn SmartContractSignatureVerifier, + signature_bytes: &[u8], + account_id: AccountId, + block_number: Option, + ) -> Result { + let is_valid = signature_verifier + .is_valid_signature( + account_id.clone(), + hash_message(signature_text.as_ref()).into(), + signature_bytes.to_vec().into(), + block_number.map(|n| n.into()), + ) + .await?; + + if is_valid { + Ok(Self::new( + MemberIdentifier::Address(account_id.into()), + SignatureKind::Erc1271, + signature_bytes.to_vec(), + )) + } else { + Err(SignatureError::Invalid) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + associations::{ + sign_with_legacy_key, verified_signature::VerifiedSignature, MemberIdentifier, + SignatureKind, + }, + constants::INSTALLATION_KEY_SIGNATURE_CONTEXT, + InboxOwner, + }; + use ed25519_dalek::SigningKey as Ed25519SigningKey; + use ethers::signers::{LocalWallet, Signer}; + use prost::Message; + use xmtp_proto::xmtp::message_contents::{ + signature::Union as SignatureUnion, signed_private_key, + SignedPrivateKey as LegacySignedPrivateKeyProto, + }; + use xmtp_v2::k256_helper::sign_sha256; + + #[tokio::test] + async fn test_recoverable_ecdsa() { + let wallet: LocalWallet = LocalWallet::new(&mut rand::thread_rng()); + let signature_text = "test signature body"; + + let sig_bytes: Vec = wallet.sign_message(signature_text).await.unwrap().to_vec(); + let verified_sig = VerifiedSignature::from_recoverable_ecdsa(signature_text, &sig_bytes) + .expect("should succeed"); + + assert_eq!(verified_sig.signer.address().unwrap(), wallet.get_address()); + assert_eq!(verified_sig.kind, SignatureKind::Erc191); + assert_eq!(verified_sig.raw_bytes, sig_bytes); + } + + #[tokio::test] + async fn test_recoverable_ecdsa_incorrect() { + let wallet: LocalWallet = LocalWallet::new(&mut rand::thread_rng()); + let signature_text = "test signature body"; + + let sig_bytes: Vec = wallet.sign_message(signature_text).await.unwrap().to_vec(); + + let verified_sig = + VerifiedSignature::from_recoverable_ecdsa("wrong text again", &sig_bytes).unwrap(); + assert_ne!(verified_sig.signer, wallet.get_address().into()); + } + + #[tokio::test] + async fn test_installation_key() { + let signing_key = Ed25519SigningKey::generate(&mut rand::thread_rng()); + let verifying_key = signing_key.verifying_key(); + + let signature_text = "test signature text"; + let mut prehashed: Sha512 = Sha512::new(); + prehashed.update(signature_text); + + let sig = signing_key + .sign_prehashed(prehashed, Some(INSTALLATION_KEY_SIGNATURE_CONTEXT)) + .unwrap(); + + let verified_sig = VerifiedSignature::from_installation_key( + signature_text, + sig.to_bytes().as_slice(), + verifying_key.as_bytes(), + ) + .expect("should succeed"); + let expected = MemberIdentifier::Installation(verifying_key.as_bytes().to_vec()); + assert_eq!(expected, verified_sig.signer); + assert_eq!(SignatureKind::InstallationKey, verified_sig.kind); + assert_eq!(verified_sig.raw_bytes, sig.to_bytes().as_slice()); + + // Make sure it fails with the wrong signature text + VerifiedSignature::from_installation_key( + "wrong signature text", + sig.to_bytes().as_slice(), + verifying_key.as_bytes(), + ) + .expect_err("should fail with incorrect signature text"); + + // Make sure it fails with the wrong verifying key + VerifiedSignature::from_installation_key( + signature_text, + sig.to_bytes().as_slice(), + &[verifying_key.as_bytes().as_slice(), vec![2, 3].as_slice()].concat(), + ) + .expect_err("should fail with incorrect verifying key"); + } + + #[test] + fn validate_good_key_round_trip() { + let proto_bytes = vec![ + 10, 79, 8, 192, 195, 165, 174, 203, 153, 231, 213, 23, 26, 67, 10, 65, 4, 216, 84, 174, + 252, 198, 225, 219, 168, 239, 166, 62, 233, 206, 108, 53, 155, 87, 132, 8, 43, 91, 36, + 91, 81, 93, 213, 67, 241, 69, 5, 31, 249, 186, 129, 119, 144, 4, 44, 54, 76, 185, 95, + 61, 23, 231, 72, 7, 169, 18, 70, 113, 79, 173, 82, 13, 37, 146, 201, 43, 174, 180, 33, + 125, 43, 18, 70, 18, 68, 10, 64, 7, 136, 100, 172, 155, 247, 230, 255, 253, 247, 78, + 50, 212, 226, 41, 78, 239, 183, 136, 247, 122, 88, 155, 245, 219, 183, 215, 202, 42, + 89, 162, 128, 96, 96, 120, 131, 17, 70, 38, 231, 2, 27, 91, 29, 66, 110, 128, 140, 1, + 42, 217, 185, 2, 181, 208, 100, 143, 143, 219, 159, 174, 1, 233, 191, 16, 1, + ]; + let account_address = "0x220ca99fb7fafa18cb623d924794dde47b4bc2e9"; + + let proto = LegacySignedPublicKeyProto::decode(proto_bytes.as_slice()).unwrap(); + let validated_key = ValidatedLegacySignedPublicKey::try_from(proto) + .expect("Key should validate successfully"); + let proto: LegacySignedPublicKeyProto = validated_key.into(); + let validated_key = ValidatedLegacySignedPublicKey::try_from(proto) + .expect("Key should still validate successfully"); + assert_eq!(validated_key.account_address(), account_address); + } + + #[test] + fn validate_malformed_key() { + let proto_bytes = vec![ + 10, 79, 8, 192, 195, 165, 174, 203, 153, 231, 213, 23, 26, 67, 10, 65, 4, 216, 84, 174, + 252, 198, 225, 219, 168, 239, 166, 62, 233, 206, 108, 53, 155, 87, 132, 8, 43, 91, 36, + 91, 81, 93, 213, 67, 241, 69, 5, 31, 249, 186, 129, 119, 144, 4, 44, 54, 76, 185, 95, + 61, 23, 231, 72, 7, 169, 18, 70, 113, 79, 173, 82, 13, 37, 146, 201, 43, 174, 180, 33, + 125, 43, 18, 70, 18, 68, 10, 64, 7, 136, 100, 172, 155, 247, 230, 255, 253, 247, 78, + 50, 212, 226, 41, 78, 239, 183, 136, 247, 122, 88, 155, 245, 219, 183, 215, 202, 42, + 89, 162, 128, 96, 96, 120, 131, 17, 70, 38, 231, 2, 27, 91, 29, 66, 110, 128, 140, 1, + 42, 217, 185, 2, 181, 208, 100, 143, 143, 219, 159, 174, 1, 233, 191, 16, 1, + ]; + let mut proto = LegacySignedPublicKeyProto::decode(proto_bytes.as_slice()).unwrap(); + proto.key_bytes[0] += 1; // Corrupt the serialized key data + assert!(matches!( + ValidatedLegacySignedPublicKey::try_from(proto), + Err(super::SignatureError::Invalid) + )); + } + + #[tokio::test] + async fn test_legacy_delegated() { + let signature_text = "test_legacy_signature"; + let account_address = "0x0bd00b21af9a2d538103c3aaf95cb507f8af1b28".to_string(); + let legacy_signed_private_key = hex::decode("0880bdb7a8b3f6ede81712220a20ad528ea38ce005268c4fb13832cfed13c2b2219a378e9099e48a38a30d66ef991a96010a4c08aaa8e6f5f9311a430a41047fd90688ca39237c2899281cdf2756f9648f93767f91c0e0f74aed7e3d3a8425e9eaa9fa161341c64aa1c782d004ff37ffedc887549ead4a40f18d1179df9dff124612440a403c2cb2338fb98bfe5f6850af11f6a7e97a04350fc9d37877060f8d18e8f66de31c77b3504c93cf6a47017ea700a48625c4159e3f7e75b52ff4ea23bc13db77371001").unwrap(); + + // happy path + let legacy_signature = sign_with_legacy_key( + signature_text.to_string(), + legacy_signed_private_key.clone(), + ) + .await + .unwrap(); + let expected = MemberIdentifier::Address(account_address.clone()); + let verified_sig = VerifiedSignature::from_legacy_delegated( + signature_text, + &legacy_signature.legacy_key_signature.signature_bytes, + legacy_signature.signed_public_key_proto.clone(), + ) + .expect("should succeed"); + + let legacy_signature_bytes = match legacy_signature + .signed_public_key_proto + .signature + .unwrap() + .union + .unwrap() + { + SignatureUnion::WalletEcdsaCompact(legacy_wallet_ecdsa) => [ + legacy_wallet_ecdsa.bytes, + vec![legacy_wallet_ecdsa.recovery as u8], + ] + .concat(), + _ => panic!("Invalid signature type"), + }; + + assert_eq!(verified_sig.signer, expected); + assert_eq!(verified_sig.kind, SignatureKind::LegacyDelegated); + assert_eq!(verified_sig.raw_bytes, legacy_signature_bytes,); + + // fail path + let legacy_signed_private_key_proto = + LegacySignedPrivateKeyProto::decode(legacy_signed_private_key.as_slice()).unwrap(); + let signed_private_key::Union::Secp256k1(secp256k1) = + legacy_signed_private_key_proto.union.unwrap(); + let legacy_private_key = secp256k1.bytes; + let (mut legacy_signature, recovery_id) = sign_sha256( + &legacy_private_key, // secret_key + signature_text.as_bytes(), // message + ) + .unwrap(); + legacy_signature.push(recovery_id); + let legacy_signed_public_key_proto = legacy_signed_private_key_proto.public_key.unwrap(); + + let res = VerifiedSignature::from_legacy_delegated( + signature_text, + &legacy_signature, + legacy_signed_public_key_proto, + ); + assert!(matches!(res, Err(super::SignatureError::Invalid))); + } +} diff --git a/xmtp_id/src/lib.rs b/xmtp_id/src/lib.rs index 9a446127b..f6fa1ad29 100644 --- a/xmtp_id/src/lib.rs +++ b/xmtp_id/src/lib.rs @@ -53,7 +53,7 @@ impl InboxOwner for LocalWallet { } fn sign(&self, text: &str) -> Result { - let message_hash = ethers_core::utils::hash_message(text); + let message_hash = ethers::core::utils::hash_message(text); Ok(self.sign_hash(message_hash)?.to_vec().into()) } } diff --git a/xmtp_id/src/scw_verifier.rs b/xmtp_id/src/scw_verifier/chain_rpc_verifier.rs similarity index 86% rename from xmtp_id/src/scw_verifier.rs rename to xmtp_id/src/scw_verifier/chain_rpc_verifier.rs index bde5ce5ea..440692d2d 100644 --- a/xmtp_id/src/scw_verifier.rs +++ b/xmtp_id/src/scw_verifier/chain_rpc_verifier.rs @@ -1,26 +1,17 @@ //! Interaction with [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) smart contracts. +use crate::scw_verifier::SmartContractSignatureVerifier; +use async_trait::async_trait; use ethers::abi::{Constructor, Param, ParamType, Token}; use ethers::contract::abigen; use ethers::providers::{Http, Middleware, Provider}; use ethers::types::transaction::eip2718::TypedTransaction; -use ethers::types::{Address, BlockId, BlockNumber, Bytes, TransactionRequest}; -use hex::FromHex; +use ethers::types::{Address, BlockNumber, Bytes, TransactionRequest, U64}; +use hex::{FromHex, FromHexError}; use std::sync::Arc; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum VerifierError { - #[error("calling smart contract {0}")] - Contract(#[from] ethers::contract::ContractError>), - #[error("unexpected result from ERC-6492 {0}")] - UnexpectedERC6492Result(String), - #[error(transparent)] - FromHex(#[from] hex::FromHexError), - #[error(transparent)] - Abi(#[from] ethers::abi::Error), - #[error(transparent)] - Provider(#[from] ethers::providers::ProviderError), -} + +use crate::associations::AccountId; + +use super::VerifierError; // https://github.com/AmbireTech/signature-validator/blob/7706bda/index.ts#L13 // Contract from AmbireTech that is also used by Viem. @@ -36,33 +27,39 @@ abigen!( derives(serde::Serialize, serde::Deserialize) ); -#[derive(Debug)] -pub struct SmartContractWalletVerifier { +#[derive(Debug, Clone)] +pub struct RpcSmartContractWalletVerifier { pub provider: Arc>, } -impl SmartContractWalletVerifier { +impl RpcSmartContractWalletVerifier { pub fn new(url: String) -> Self { let provider = Arc::new(Provider::::try_from(url).unwrap()); Self { provider } } +} +#[async_trait] +impl SmartContractSignatureVerifier for RpcSmartContractWalletVerifier { /// Verifies an ERC-6492 signature. /// /// # Arguments /// - /// * `block_number` - Block number to verify the signature at. /// * `signer` - can be the smart wallet address or EOA address. /// * `hash` - Message digest for the signature. /// * `signature` - Could be encoded smart wallet signature or raw ECDSA signature. - pub async fn is_valid_signature( + async fn is_valid_signature( &self, - signer: Address, + signer: AccountId, hash: [u8; 32], - signature: &Bytes, + signature: Bytes, block_number: Option, ) -> Result { let code = hex::decode(VALIDATE_SIG_OFFCHAIN_BYTECODE).unwrap(); + let account_address: Address = signer + .account_address + .parse() + .map_err(|_| FromHexError::InvalidStringLength)?; // ABI of the ValidateSigOffchain constructor // constructor (address _signer, bytes32 _hash, bytes memory _signature) let inputs: Vec = vec![ @@ -84,17 +81,25 @@ impl SmartContractWalletVerifier { ]; let constructor = Constructor { inputs }; let tokens = &[ - Token::Address(signer), + Token::Address(account_address), Token::FixedBytes(hash.to_vec()), Token::Bytes(signature.to_vec()), ]; let data = constructor.encode_input(code, tokens)?; let tx: TypedTransaction = TransactionRequest::new().data(data).into(); - let res = self - .provider - .call(&tx, block_number.map(BlockId::Number)) - .await?; - Ok(res == Bytes::from_hex("0x01").unwrap()) + let block_number = match block_number { + Some(bn) => bn, + None => BlockNumber::Number(self.current_block_number(&signer.chain_id).await?), + }; + let res = self.provider.call(&tx, Some(block_number.into())).await?; + Ok(res == Bytes::from_hex("0x01").expect("Hardcoded hex will not fail.")) + } + + async fn current_block_number(&self, _chain_id: &str) -> Result { + self.provider + .get_block_number() + .await + .map_err(VerifierError::Provider) } } @@ -107,7 +112,6 @@ pub mod tests { abi::{self, Token}, core::utils::Anvil, middleware::{MiddlewareBuilder, SignerMiddleware}, - providers::Middleware, signers::{LocalWallet, Signer as _}, types::{H256, U256}, utils::{hash_message, AnvilInstance}, @@ -203,6 +207,7 @@ pub mod tests { .get_address(owners_addresses.clone(), nonce) .await .unwrap(); + let contract_call = factory.create_account(owners_addresses.clone(), nonce); let pending_tx = contract_call.send().await.unwrap(); pending_tx.await.unwrap(); @@ -214,15 +219,17 @@ pub mod tests { ); let hash: [u8; 32] = H256::random().into(); let replay_safe_hash = smart_wallet.replay_safe_hash(hash).call().await.unwrap(); - let verifier = SmartContractWalletVerifier::new(anvil.endpoint()); + let verifier = RpcSmartContractWalletVerifier::new(anvil.endpoint()); // verify owner0 is a valid owner let sig0 = owner0.sign_hash(replay_safe_hash.into()).unwrap(); + let account_id = + AccountId::new_evm(anvil.chain_id(), format!("{:?}", smart_wallet_address)); let res = verifier .is_valid_signature( - smart_wallet_address, + account_id.clone(), hash, - &abi::encode(&[Token::Tuple(vec![ + abi::encode(&[Token::Tuple(vec![ Token::Uint(U256::from(0)), Token::Bytes(sig0.to_vec()), ])]) @@ -236,9 +243,9 @@ pub mod tests { let sig1 = owner1.sign_hash(replay_safe_hash.into()).unwrap(); let res = verifier .is_valid_signature( - smart_wallet_address, + account_id.clone(), hash, - &abi::encode(&[Token::Tuple(vec![ + abi::encode(&[Token::Tuple(vec![ Token::Uint(U256::from(1)), Token::Bytes(sig1.to_vec()), ])]) @@ -251,9 +258,9 @@ pub mod tests { // owner0 siganture must not be used to verify owner1 let res = verifier .is_valid_signature( - smart_wallet_address, + account_id.clone(), hash, - &abi::encode(&[Token::Tuple(vec![ + abi::encode(&[Token::Tuple(vec![ Token::Uint(U256::from(1)), Token::Bytes(sig0.to_vec()), ])]) @@ -275,9 +282,9 @@ pub mod tests { let res = verifier .is_valid_signature( - smart_wallet_address, + account_id.clone(), hash, - &abi::encode(&[Token::Tuple(vec![ + abi::encode(&[Token::Tuple(vec![ Token::Uint(U256::from(1)), Token::Bytes(sig1.to_vec()), ])]) @@ -290,9 +297,9 @@ pub mod tests { // time travel to the pre-removel block number and verify owner1 WAS a valid owner let res = verifier .is_valid_signature( - smart_wallet_address, + account_id.clone(), hash, - &abi::encode(&[Token::Tuple(vec![ + abi::encode(&[Token::Tuple(vec![ Token::Uint(U256::from(1)), Token::Bytes(sig1.to_vec()), ])]) @@ -344,37 +351,42 @@ pub mod tests { ])]) .into(); - let verifier = SmartContractWalletVerifier::new(anvil.endpoint()); + let verifier = RpcSmartContractWalletVerifier::new(anvil.endpoint()); + + let account_id = + AccountId::new_evm(anvil.chain_id(), format!("{:?}", smart_wallet_address)); // Testing ERC-6492 signatures with deployed ERC-1271. assert!(verifier - .is_valid_signature(smart_wallet_address, hash, &signature, None,) + .is_valid_signature(account_id.clone(), hash, signature.clone(), None) .await .unwrap()); assert!(!verifier - .is_valid_signature( - smart_wallet_address, - H256::random().into(), - &signature, - None, - ) + .is_valid_signature(account_id.clone(), H256::random().into(), signature, None) .await .unwrap()); // Testing if EOA wallet signature is valid on ERC-6492 let signature = owner.sign_hash(hash.into()).unwrap(); + let owner_account_id = + AccountId::new_evm(anvil.chain_id(), format!("{:?}", owner.address())); assert!(verifier - .is_valid_signature(owner.address(), hash, &signature.to_vec().into(), None,) + .is_valid_signature( + owner_account_id.clone(), + hash, + signature.to_vec().into(), + None + ) .await .unwrap()); assert!(!verifier .is_valid_signature( - owner.address(), + owner_account_id, H256::random().into(), - &signature.to_vec().into(), - None, + signature.to_vec().into(), + None ) .await .unwrap()); @@ -387,16 +399,15 @@ pub mod tests { #[ignore] // This test is temporarily being ignored as it relies on an external service #[tokio::test] async fn test_erc6492_ambire_wallet() { - let signer: Address = "0x4836a472ab1dd406ecb8d0f933a985541ee3921f" - .parse() - .unwrap(); + let signer = "0x4836a472ab1dd406ecb8d0f933a985541ee3921f".to_string(); + let hash = hex::decode("787177").unwrap(); let hash = hash_message(hash); let signature = Bytes::from_hex("0x000000000000000000000000bf07a0df119ca234634588fbdb5625594e2a5bca00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000038449c81579000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000004836a472ab1dd406ecb8d0f933a985541ee3921f0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000007a7f00000000000000000000000000000000000000000000000000000000000000017f7f0f292b79d9ce101861526459da50f62368077ae24affe97b792bf4bdd2e171553d602d80604d3d3981f3363d3d373d3d3d363d732a2b85eb1054d6f0c6c2e37da05ed3e5fea684ef5af43d82803e903d91602b57fd5bf300000000000000000000000000000000000000000000000000000000000000000000000002246171d1c9000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000004836a472ab1dd406ecb8d0f933a985541ee3921f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000942f9ce5d9a33a82f88d233aeb3292e6802303480000000000000000000000000000000000000000000000000014c3c6ef1cdc01000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042f2eaaebf45fc0340eb55f11c52a30e2ca7f48539d0a1f1cdc240482210326494545def903e8ed4441bd5438109abe950f1f79baf032f184728ba2d4161dea32e1b0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042c0f8db6019888d87a0afc1299e81ef45d3abce64f63072c8d7a6ef00f5f82c1522958ff110afa98b8c0d23b558376db1d2fbab4944e708f8bf6dc7b977ee07201b000000000000000000000000000000000000000000000000000000000000006492649264926492649264926492649264926492649264926492649264926492").unwrap(); - let verifier = SmartContractWalletVerifier::new("https://polygon-rpc.com".to_string()); + let verifier = RpcSmartContractWalletVerifier::new("https://polygon-rpc.com".to_string()); assert!(verifier - .is_valid_signature(signer, hash.into(), &signature, None) + .is_valid_signature(AccountId::new_evm(1, signer), hash.into(), signature, None) .await .unwrap()); } diff --git a/xmtp_id/src/scw_verifier/chain_urls_default.json b/xmtp_id/src/scw_verifier/chain_urls_default.json new file mode 100644 index 000000000..a079c84b5 --- /dev/null +++ b/xmtp_id/src/scw_verifier/chain_urls_default.json @@ -0,0 +1,5 @@ +{ + "1": "https://eth.llamarpc.com", + "8453": "https://base.llamarpc.com", + "42161": "https://arbitrum.llamarpc.com" +} diff --git a/xmtp_id/src/scw_verifier/mod.rs b/xmtp_id/src/scw_verifier/mod.rs new file mode 100644 index 000000000..7d479f16b --- /dev/null +++ b/xmtp_id/src/scw_verifier/mod.rs @@ -0,0 +1,157 @@ +mod chain_rpc_verifier; + +use std::{collections::HashMap, fs, path::Path, str::FromStr}; + +use async_trait::async_trait; +use dyn_clone::DynClone; +use ethers::{ + contract::ContractError, + providers::{Http, Provider, ProviderError}, + types::{BlockNumber, Bytes, U64}, +}; +use thiserror::Error; +use url::Url; + +use crate::associations::AccountId; + +pub use self::chain_rpc_verifier::*; + +static DEFAULT_CHAIN_URLS: &str = include_str!("chain_urls_default.json"); + +#[derive(Debug, Error)] +pub enum VerifierError { + #[error("calling smart contract {0}")] + Contract(#[from] ethers::contract::ContractError>), + #[error("unexpected result from ERC-6492 {0}")] + UnexpectedERC6492Result(String), + #[error(transparent)] + FromHex(#[from] hex::FromHexError), + #[error(transparent)] + Abi(#[from] ethers::abi::Error), + #[error(transparent)] + Provider(#[from] ethers::providers::ProviderError), +} + +#[async_trait] +pub trait SmartContractSignatureVerifier: Send + Sync + DynClone + 'static { + async fn current_block_number(&self, chain_id: &str) -> Result; + async fn is_valid_signature( + &self, + account_id: AccountId, + hash: [u8; 32], + signature: Bytes, + block_number: Option, + ) -> Result; +} + +dyn_clone::clone_trait_object!(SmartContractSignatureVerifier); + +#[async_trait] +impl SmartContractSignatureVerifier for Box { + async fn is_valid_signature( + &self, + account_id: AccountId, + hash: [u8; 32], + signature: Bytes, + block_number: Option, + ) -> Result { + (**self) + .is_valid_signature(account_id, hash, signature, block_number) + .await + } + + async fn current_block_number(&self, chain_id: &str) -> Result { + (**self).current_block_number(chain_id).await + } +} + +#[derive(Clone)] +pub struct MultiSmartContractSignatureVerifier { + verifiers: HashMap>, +} + +impl MultiSmartContractSignatureVerifier { + pub fn new(urls: HashMap) -> Self { + let verifiers: HashMap> = urls + .into_iter() + .map(|(chain_id, url)| { + ( + chain_id, + Box::new(RpcSmartContractWalletVerifier::new(url.to_string())) + as Box, + ) + }) + .collect(); + + Self { verifiers } + } + + pub fn new_from_file(path: impl AsRef) -> Self { + let path = path.as_ref(); + + let file_str; + let json = if path.exists() { + file_str = fs::read_to_string(path).unwrap_or_else(|_| panic!("{path:?} is missing")); + &file_str + } else { + DEFAULT_CHAIN_URLS + }; + + let json: HashMap = + serde_json::from_str(json).unwrap_or_else(|_| panic!("{path:?} is malformatted")); + + let urls = json + .into_iter() + .map(|(id, url)| { + ( + id, + Url::from_str(&url) + .unwrap_or_else(|_| panic!("unable to parse url in {path:?} ({url})")), + ) + }) + .collect(); + + Self::new(urls) + } +} + +#[async_trait] +impl SmartContractSignatureVerifier for MultiSmartContractSignatureVerifier { + async fn is_valid_signature( + &self, + account_id: AccountId, + hash: [u8; 32], + signature: Bytes, + block_number: Option, + ) -> Result { + let id: u64 = account_id.chain_id.parse().map_err(|e| { + VerifierError::Contract(ContractError::DecodingError( + ethers::core::abi::Error::ParseInt(e), + )) + })?; + if let Some(verifier) = self.verifiers.get(&id) { + return verifier + .is_valid_signature(account_id, hash, signature, block_number) + .await; + } + + Err(VerifierError::Provider(ProviderError::CustomError( + "Verifier not present".to_string(), + ))) + } + + async fn current_block_number(&self, chain_id: &str) -> Result { + let id: u64 = chain_id.parse().map_err(|e| { + VerifierError::Contract(ContractError::DecodingError( + ethers::core::abi::Error::ParseInt(e), + )) + })?; + if let Some(verifier) = self.verifiers.get(&id) { + return verifier.current_block_number(chain_id).await; + } + + Err(VerifierError::Provider(ProviderError::CustomError( + "Verifier not present".to_string(), + ))) + } +} diff --git a/xmtp_mls/Cargo.toml b/xmtp_mls/Cargo.toml index c992137ba..dff1d5bd5 100644 --- a/xmtp_mls/Cargo.toml +++ b/xmtp_mls/Cargo.toml @@ -20,15 +20,14 @@ bench = [ ] default = ["native"] http-api = ["xmtp_api_http"] -native = ["libsqlite3-sys/bundled-sqlcipher-vendored-openssl"] -test-utils = [] +message-history = [] +native = ["libsqlite3-sys/bundled-sqlcipher-vendored-openssl", "xmtp_api_grpc"] +test-utils = ["xmtp_id/test-utils"] [dependencies] aes-gcm = { version = "0.10.3", features = ["std"] } async-stream.workspace = true -async-trait.workspace = true bincode = "1.3.3" -chrono = { workspace = true } diesel = { version = "2.2.2", features = [ "sqlite", "r2d2", @@ -36,12 +35,9 @@ diesel = { version = "2.2.2", features = [ ] } diesel_migrations = { version = "2.2.0", features = ["sqlite"] } ed25519-dalek = "2.1.1" -ethers-core.workspace = true -ethers.workspace = true futures.workspace = true hex.workspace = true libsqlite3-sys = { version = "0.29.0", optional = true } -log.workspace = true openmls = { workspace = true, features = ["test-utils"] } openmls_basic_credential = { workspace = true } openmls_rust_crypto = { workspace = true } @@ -53,7 +49,6 @@ reqwest = { version = "0.12.4", features = ["stream"] } serde = { workspace = true } serde_json.workspace = true sha2.workspace = true -smart-default = "0.7.1" thiserror = { workspace = true } tls_codec = { workspace = true } tokio = { workspace = true, features = [ @@ -63,11 +58,11 @@ tokio = { workspace = true, features = [ ] } tokio-stream = { version = "0.1", features = ["sync"] } toml = "0.8.4" -tracing.workspace = true +tracing = { workspace = true, features = ["release_max_level_debug"] } +trait-variant.workspace = true xmtp_cryptography = { workspace = true } xmtp_id = { path = "../xmtp_id" } xmtp_proto = { workspace = true, features = ["proto_full", "convert"] } -xmtp_v2 = { path = "../xmtp_v2" } # Test/Bench Utils anyhow = { workspace = true, optional = true } @@ -83,13 +78,11 @@ anyhow.workspace = true async-barrier = "1.1" criterion = { version = "0.5", features = ["html_reports", "async_tokio"] } ctor.workspace = true -flume = "0.11" +ethers.workspace = true mockall = "0.13.0" mockito = "1.4.0" tempfile = "3.5.0" -tracing-log = "0.2.0" -tracing-subscriber.workspace = true -tracing-test = "0.2.4" +tracing-subscriber = { workspace = true, features = ["env-filter"] } tracing.workspace = true xmtp_api_grpc = { path = "../xmtp_api_grpc" } xmtp_id = { path = "../xmtp_id", features = ["test-utils"] } diff --git a/xmtp_mls/benches/group_limit.rs b/xmtp_mls/benches/group_limit.rs index 8408bd305..7319f5364 100755 --- a/xmtp_mls/benches/group_limit.rs +++ b/xmtp_mls/benches/group_limit.rs @@ -3,11 +3,9 @@ //! using `RUST_LOG=trace` will additionally output a `tracing.folded` file, which //! may be used to generate a flamegraph of execution from tracing logs. use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; -use ethers::signers::LocalWallet; use std::{collections::HashMap, sync::Arc}; use tokio::runtime::{Builder, Handle, Runtime}; use tracing::{trace_span, Instrument}; -use xmtp_cryptography::utils::rng; use xmtp_mls::{ builder::ClientBuilder, groups::GroupMetadataOptions, @@ -33,13 +31,13 @@ fn setup() -> (Arc, Vec, Runtime) { .unwrap(); let (client, identities) = runtime.block_on(async { - let wallet = LocalWallet::new(&mut rng()); + let wallet = xmtp_cryptography::utils::generate_local_wallet(); // use dev network if `DEV_GRPC` is set let dev = std::env::var("DEV_GRPC"); let is_dev_network = matches!(dev, Ok(d) if d == "true" || d == "1"); let client = if is_dev_network { - log::info!("Using Dev GRPC"); + tracing::info!("Using Dev GRPC"); Arc::new(ClientBuilder::new_dev_client(&wallet).await) } else { Arc::new(ClientBuilder::new_test_client(&wallet).await) diff --git a/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/down.sql b/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/down.sql new file mode 100644 index 000000000..dd3043403 --- /dev/null +++ b/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE IF EXISTS "consent_records"; diff --git a/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/up.sql b/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/up.sql new file mode 100644 index 000000000..76e7f7f27 --- /dev/null +++ b/xmtp_mls/migrations/2024-08-07-213816_create-private-preference-store/up.sql @@ -0,0 +1,9 @@ +CREATE TABLE "consent_records"( + -- Enum of the CONSENT_TYPE (GROUP_ID, INBOX_ID, etc..) + "entity_type" int NOT NULL, + -- Enum of CONSENT_STATE (ALLOWED, DENIED, etc..) + "state" int NOT NULL, + -- The entity of what has consent (0x00 etc..) + "entity" text NOT NULL, + PRIMARY KEY (entity_type, entity) +); \ No newline at end of file diff --git a/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/down.sql b/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/down.sql new file mode 100644 index 000000000..2dbbf5787 --- /dev/null +++ b/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE groups DROP COLUMN dm_inbox_id; +DROP INDEX idx_dm_target; diff --git a/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/up.sql b/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/up.sql new file mode 100644 index 000000000..6614f371a --- /dev/null +++ b/xmtp_mls/migrations/2024-09-09-231735_create_dm_inbox_id/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE groups ADD COLUMN dm_inbox_id text; +CREATE INDEX idx_dm_target ON groups(dm_inbox_id); diff --git a/xmtp_mls/migrations/2024-09-16-221459_key_package_history/down.sql b/xmtp_mls/migrations/2024-09-16-221459_key_package_history/down.sql new file mode 100644 index 000000000..2f4a654c3 --- /dev/null +++ b/xmtp_mls/migrations/2024-09-16-221459_key_package_history/down.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS key_package_history; + diff --git a/xmtp_mls/migrations/2024-09-16-221459_key_package_history/up.sql b/xmtp_mls/migrations/2024-09-16-221459_key_package_history/up.sql new file mode 100644 index 000000000..f5a0a78a1 --- /dev/null +++ b/xmtp_mls/migrations/2024-09-16-221459_key_package_history/up.sql @@ -0,0 +1,6 @@ +CREATE TABLE key_package_history( + "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, + "key_package_hash_ref" BLOB UNIQUE NOT NULL, + "created_at_ns" bigint NOT NULL +); + diff --git a/xmtp_mls/migrations/2024-09-18-185314_clear_association_states_cache/down.sql b/xmtp_mls/migrations/2024-09-18-185314_clear_association_states_cache/down.sql new file mode 100644 index 000000000..e69de29bb diff --git a/xmtp_mls/migrations/2024-09-18-185314_clear_association_states_cache/up.sql b/xmtp_mls/migrations/2024-09-18-185314_clear_association_states_cache/up.sql new file mode 100644 index 000000000..7a6ba7017 --- /dev/null +++ b/xmtp_mls/migrations/2024-09-18-185314_clear_association_states_cache/up.sql @@ -0,0 +1 @@ +DELETE FROM association_state; diff --git a/xmtp_mls/src/api/identity.rs b/xmtp_mls/src/api/identity.rs index 5a7a5a245..5a7081ce3 100644 --- a/xmtp_mls/src/api/identity.rs +++ b/xmtp_mls/src/api/identity.rs @@ -4,7 +4,7 @@ use super::{ApiClientWrapper, WrappedApiError}; use crate::XmtpApi; use futures::future::try_join_all; use xmtp_id::{ - associations::{DeserializationError, IdentityUpdate}, + associations::{unverified::UnverifiedIdentityUpdate, DeserializationError}, InboxId, }; use xmtp_proto::xmtp::identity::api::v1::{ @@ -37,7 +37,7 @@ impl From<&GetIdentityUpdatesV2Filter> for GetIdentityUpdatesV2RequestProto { pub struct InboxUpdate { pub sequence_id: u64, pub server_timestamp_ns: u64, - pub update: IdentityUpdate, + pub update: UnverifiedIdentityUpdate, } impl TryFrom for InboxUpdate { @@ -68,7 +68,7 @@ where { pub async fn publish_identity_update( &self, - update: IdentityUpdate, + update: UnverifiedIdentityUpdate, ) -> Result<(), WrappedApiError> { self.api_client .publish_identity_update(PublishIdentityUpdateRequest { @@ -122,7 +122,7 @@ where &self, account_addresses: Vec, ) -> Result { - log::info!( + tracing::info!( "Getting inbox_ids for account addresses: {:?}", &account_addresses ); @@ -155,7 +155,7 @@ mod tests { use super::super::test_utils::*; use super::GetIdentityUpdatesV2Filter; use crate::{api::ApiClientWrapper, retry::Retry}; - use xmtp_id::associations::{test_utils::rand_string, Action, CreateInbox, IdentityUpdate}; + use xmtp_id::associations::{test_utils::rand_string, unverified::UnverifiedIdentityUpdate}; use xmtp_proto::xmtp::identity::api::v1::{ get_identity_updates_response::{ IdentityUpdateLog, Response as GetIdentityUpdatesResponseItem, @@ -164,8 +164,12 @@ mod tests { GetIdentityUpdatesResponse, GetInboxIdsResponse, PublishIdentityUpdateResponse, }; - fn create_identity_update(inbox_id: String) -> IdentityUpdate { - IdentityUpdate::new_test(vec![Action::CreateInbox(CreateInbox::default())], inbox_id) + fn create_identity_update(inbox_id: String) -> UnverifiedIdentityUpdate { + UnverifiedIdentityUpdate::new_test( + // TODO:nm Add default actions + vec![], + inbox_id, + ) } #[tokio::test] @@ -202,7 +206,7 @@ mod tests { updates: vec![IdentityUpdateLog { sequence_id: 1, server_timestamp_ns: 1, - update: Some(identity_update.to_proto()), + update: Some(identity_update.into()), }], }], }) diff --git a/xmtp_mls/src/api/mls.rs b/xmtp_mls/src/api/mls.rs index 7ac073f26..dd79a1a76 100644 --- a/xmtp_mls/src/api/mls.rs +++ b/xmtp_mls/src/api/mls.rs @@ -2,9 +2,7 @@ use std::collections::HashMap; use super::ApiClientWrapper; use crate::{retry_async, XmtpApi}; -use xmtp_proto::api_client::{ - Error as ApiError, ErrorKind, GroupMessageStream, WelcomeMessageStream, -}; +use xmtp_proto::api_client::{Error as ApiError, ErrorKind}; use xmtp_proto::xmtp::mls::api::v1::{ group_message_input::{Version as GroupMessageInputVersion, V1 as GroupMessageInputV1}, subscribe_group_messages_request::Filter as GroupFilterProto, @@ -264,7 +262,7 @@ where pub async fn subscribe_group_messages( &self, filters: Vec, - ) -> Result { + ) -> Result> + '_, ApiError> { self.api_client .subscribe_group_messages(SubscribeGroupMessagesRequest { filters: filters.into_iter().map(|f| f.into()).collect(), @@ -276,7 +274,7 @@ where &self, installation_key: Vec, id_cursor: Option, - ) -> Result { + ) -> Result> + '_, ApiError> { self.api_client .subscribe_welcome_messages(SubscribeWelcomeMessagesRequest { filters: vec![WelcomeFilterProto { diff --git a/xmtp_mls/src/api/test_utils.rs b/xmtp_mls/src/api/test_utils.rs index 973ab17b4..604804aa5 100644 --- a/xmtp_mls/src/api/test_utils.rs +++ b/xmtp_mls/src/api/test_utils.rs @@ -1,24 +1,26 @@ -use async_trait::async_trait; use mockall::mock; use xmtp_proto::{ - api_client::{ - ClientWithMetadata, Error, GroupMessageStream, WelcomeMessageStream, XmtpIdentityClient, - XmtpMlsClient, - }, - xmtp::identity::api::v1::{ - GetIdentityUpdatesRequest as GetIdentityUpdatesV2Request, - GetIdentityUpdatesResponse as GetIdentityUpdatesV2Response, GetInboxIdsRequest, - GetInboxIdsResponse, PublishIdentityUpdateRequest, PublishIdentityUpdateResponse, - }, - xmtp::mls::api::v1::{ - group_message::{Version as GroupMessageVersion, V1 as GroupMessageV1}, - FetchKeyPackagesRequest, FetchKeyPackagesResponse, GroupMessage, QueryGroupMessagesRequest, - QueryGroupMessagesResponse, QueryWelcomeMessagesRequest, QueryWelcomeMessagesResponse, - SendGroupMessagesRequest, SendWelcomeMessagesRequest, SubscribeGroupMessagesRequest, - SubscribeWelcomeMessagesRequest, UploadKeyPackageRequest, + api_client::{ClientWithMetadata, Error, XmtpIdentityClient, XmtpMlsClient, XmtpMlsStreams}, + xmtp::{ + identity::api::v1::{ + GetIdentityUpdatesRequest as GetIdentityUpdatesV2Request, + GetIdentityUpdatesResponse as GetIdentityUpdatesV2Response, GetInboxIdsRequest, + GetInboxIdsResponse, PublishIdentityUpdateRequest, PublishIdentityUpdateResponse, + }, + mls::api::v1::{ + group_message::{Version as GroupMessageVersion, V1 as GroupMessageV1}, + FetchKeyPackagesRequest, FetchKeyPackagesResponse, GroupMessage, + QueryGroupMessagesRequest, QueryGroupMessagesResponse, QueryWelcomeMessagesRequest, + QueryWelcomeMessagesResponse, SendGroupMessagesRequest, SendWelcomeMessagesRequest, + SubscribeGroupMessagesRequest, SubscribeWelcomeMessagesRequest, + UploadKeyPackageRequest, + }, }, }; +#[cfg(feature = "http-api")] +use xmtp_proto::xmtp::mls::api::v1::WelcomeMessage; + use crate::XmtpTestClient; pub fn build_group_messages(num_messages: usize, group_id: Vec) -> Vec { @@ -46,7 +48,6 @@ mock! { fn set_app_version(&mut self, version: String) -> Result<(), Error>; } - #[async_trait] impl XmtpMlsClient for ApiClient { async fn upload_key_package(&self, request: UploadKeyPackageRequest) -> Result<(), Error>; async fn fetch_key_packages( @@ -57,18 +58,30 @@ mock! { async fn send_welcome_messages(&self, request: SendWelcomeMessagesRequest) -> Result<(), Error>; async fn query_group_messages(&self, request: QueryGroupMessagesRequest) -> Result; async fn query_welcome_messages(&self, request: QueryWelcomeMessagesRequest) -> Result; - async fn subscribe_group_messages(&self, request: SubscribeGroupMessagesRequest) -> Result; - async fn subscribe_welcome_messages(&self, request: SubscribeWelcomeMessagesRequest) -> Result; } - #[async_trait] + impl XmtpMlsStreams for ApiClient { + #[cfg(not(feature = "http-api"))] + type GroupMessageStream<'a> = xmtp_api_grpc::GroupMessageStream; + #[cfg(not(feature = "http-api"))] + type WelcomeMessageStream<'a> = xmtp_api_grpc::WelcomeMessageStream; + + #[cfg(feature = "http-api")] + type GroupMessageStream<'a> = futures::stream::BoxStream<'static, Result>; + #[cfg(feature = "http-api")] + type WelcomeMessageStream<'a> = futures::stream::BoxStream<'static, Result>; + + + async fn subscribe_group_messages(&self, request: SubscribeGroupMessagesRequest) -> Result<::GroupMessageStream<'static>, Error>; + async fn subscribe_welcome_messages(&self, request: SubscribeWelcomeMessagesRequest) -> Result<::WelcomeMessageStream<'static>, Error>; + } + impl XmtpIdentityClient for ApiClient { async fn publish_identity_update(&self, request: PublishIdentityUpdateRequest) -> Result; async fn get_identity_updates_v2(&self, request: GetIdentityUpdatesV2Request) -> Result; async fn get_inbox_ids(&self, request: GetInboxIdsRequest) -> Result; } - #[async_trait] impl XmtpTestClient for ApiClient { async fn create_local() -> Self { ApiClient } async fn create_dev() -> Self { ApiClient } diff --git a/xmtp_mls/src/builder.rs b/xmtp_mls/src/builder.rs index dce196d84..a77cb316d 100644 --- a/xmtp_mls/src/builder.rs +++ b/xmtp_mls/src/builder.rs @@ -1,7 +1,8 @@ -use log::debug; use thiserror::Error; +use tracing::debug; use xmtp_cryptography::signature::AddressValidationError; +use xmtp_id::scw_verifier::{MultiSmartContractSignatureVerifier, SmartContractSignatureVerifier}; use crate::{ api::ApiClientWrapper, @@ -51,6 +52,7 @@ pub struct ClientBuilder { identity_strategy: IdentityStrategy, history_sync_url: Option, app_version: Option, + scw_verifier: Option>, } impl ClientBuilder @@ -65,6 +67,7 @@ where identity_strategy: strategy, history_sync_url: None, app_version: None, + scw_verifier: None, } } @@ -93,6 +96,11 @@ where self } + pub fn scw_signature_verifier(mut self, verifier: impl SmartContractSignatureVerifier) -> Self { + self.scw_verifier = Some(Box::new(verifier)); + self + } + pub async fn build(mut self) -> Result, ClientBuilderError> { debug!("Building client"); let mut api_client = @@ -106,6 +114,12 @@ where api_client.set_app_version(app_version)?; } + let scw_verifier = self.scw_verifier.take().unwrap_or_else(|| { + Box::new(MultiSmartContractSignatureVerifier::new_from_file( + "chain_urls.json", + )) + }); + let api_client_wrapper = ApiClientWrapper::new(api_client, Retry::default()); let store = self .store @@ -114,7 +128,7 @@ where debug!("Initializing identity"); let identity = self .identity_strategy - .initialize_identity(&api_client_wrapper, &store) + .initialize_identity(&api_client_wrapper, &store, scw_verifier.as_ref()) .await?; // get sequence_id from identity updates and loaded into the DB @@ -125,7 +139,17 @@ where ) .await?; - let client = Client::new(api_client_wrapper, identity, store, self.history_sync_url); + #[cfg(feature = "message-history")] + let client = Client::new( + api_client_wrapper, + identity, + store, + scw_verifier, + self.history_sync_url, + ); + + #[cfg(not(feature = "message-history"))] + let client = Client::new(api_client_wrapper, identity, store, scw_verifier); Ok(client) } @@ -133,6 +157,8 @@ where #[cfg(test)] mod tests { + use std::sync::atomic::AtomicBool; + use crate::api::ApiClientWrapper; use crate::builder::ClientBuilderError; use crate::identity::IdentityError; @@ -142,18 +168,17 @@ mod tests { api::test_utils::*, identity::Identity, storage::identity::StoredIdentity, utils::test::rand_vec, Store, }; - use ethers::signers::Signer; - use ethers_core::k256; use openmls::credentials::{Credential, CredentialType}; use openmls_basic_credential::SignatureKeyPair; use openmls_traits::types::SignatureScheme; use prost::Message; - use xmtp_cryptography::signature::h160addr_to_string; use xmtp_cryptography::utils::{generate_local_wallet, rng}; - use xmtp_id::associations::ValidatedLegacySignedPublicKey; - use xmtp_id::associations::{ - generate_inbox_id, test_utils::rand_u64, RecoverableEcdsaSignature, + use xmtp_id::associations::test_utils::MockSmartContractSignatureVerifier; + use xmtp_id::associations::unverified::{ + UnverifiedRecoverableEcdsaSignature, UnverifiedSignature, }; + use xmtp_id::associations::ValidatedLegacySignedPublicKey; + use xmtp_id::associations::{generate_inbox_id, test_utils::rand_u64}; use xmtp_proto::xmtp::identity::api::v1::{ get_inbox_ids_response::Response as GetInboxIdsResponseItem, GetInboxIdsResponse, }; @@ -174,11 +199,14 @@ mod tests { async fn register_client(client: &Client, owner: &impl InboxOwner) { let mut signature_request = client.context.signature_request().unwrap(); let signature_text = signature_request.signature_text(); + let scw_verifier = MockSmartContractSignatureVerifier::new(true); signature_request - .add_signature(Box::new(RecoverableEcdsaSignature::new( - signature_text.clone(), - owner.sign(&signature_text).unwrap().into(), - ))) + .add_signature( + UnverifiedSignature::RecoverableEcdsa(UnverifiedRecoverableEcdsaSignature::new( + owner.sign(&signature_text).unwrap().into(), + )), + &scw_verifier, + ) .await .unwrap(); @@ -188,10 +216,10 @@ mod tests { /// Generate a random legacy key proto bytes and corresponding account address. async fn generate_random_legacy_key() -> (Vec, String) { let wallet = generate_local_wallet(); - let address = h160addr_to_string(wallet.address()); + let address = wallet.get_address(); let created_ns = rand_u64(); - let secret_key = k256::ecdsa::SigningKey::random(&mut rng()); - let public_key = k256::ecdsa::VerifyingKey::from(&secret_key); + let secret_key = ethers::core::k256::ecdsa::SigningKey::random(&mut rng()); + let public_key = ethers::core::k256::ecdsa::VerifyingKey::from(&secret_key); let public_key_bytes = public_key.to_sec1_bytes().to_vec(); let mut public_key_buf = vec![]; UnsignedPublicKey { @@ -205,7 +233,7 @@ mod tests { .encode(&mut public_key_buf) .unwrap(); let message = ValidatedLegacySignedPublicKey::text(&public_key_buf); - let signed_public_key = wallet.sign_message(message).await.unwrap().to_vec(); + let signed_public_key: Vec = wallet.sign(&message).unwrap().into(); let (bytes, recovery_id) = signed_public_key.as_slice().split_at(64); let recovery_id = recovery_id[0]; let signed_private_key: SignedPrivateKey = SignedPrivateKey { @@ -355,8 +383,11 @@ mod tests { 0, Some(legacy_key.clone()), ); - let store = - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmp_path())).unwrap(); + let store = EncryptedMessageStore::new( + StorageOption::Persistent(tmp_path()), + EncryptedMessageStore::generate_enc_key(), + ) + .unwrap(); let client1 = ClientBuilder::new(identity_strategy.clone()) .store(store.clone()) @@ -416,9 +447,13 @@ mod tests { async fn api_identity_mismatch() { let mut mock_api = MockApiClient::new(); let tmpdb = tmp_path(); + let scw_verifier = MockSmartContractSignatureVerifier::new(true); - let store = - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmpdb)).unwrap(); + let store = EncryptedMessageStore::new( + StorageOption::Persistent(tmpdb), + EncryptedMessageStore::generate_enc_key(), + ) + .unwrap(); let nonce = 0; let address = generate_local_wallet().get_address(); let inbox_id = generate_inbox_id(&address, &nonce); @@ -440,7 +475,7 @@ mod tests { IdentityStrategy::CreateIfNotFound("other_inbox_id".to_string(), address, nonce, None); assert!(matches!( identity - .initialize_identity(&wrapper, &store) + .initialize_identity(&wrapper, &store, &scw_verifier) .await .unwrap_err(), IdentityError::NewIdentity(msg) if msg == "Inbox ID mismatch" @@ -452,9 +487,13 @@ mod tests { async fn api_identity_happy_path() { let mut mock_api = MockApiClient::new(); let tmpdb = tmp_path(); + let scw_verifier = MockSmartContractSignatureVerifier::new(true); - let store = - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmpdb)).unwrap(); + let store = EncryptedMessageStore::new( + StorageOption::Persistent(tmpdb), + EncryptedMessageStore::generate_enc_key(), + ) + .unwrap(); let nonce = 0; let address = generate_local_wallet().get_address(); let inbox_id = generate_inbox_id(&address, &nonce); @@ -473,7 +512,12 @@ mod tests { let wrapper = ApiClientWrapper::new(mock_api, Retry::default()); let identity = IdentityStrategy::CreateIfNotFound(inbox_id.clone(), address, nonce, None); - assert!(dbg!(identity.initialize_identity(&wrapper, &store).await).is_ok()); + assert!(dbg!( + identity + .initialize_identity(&wrapper, &store, &scw_verifier) + .await + ) + .is_ok()); } // Use a stored identity as long as the inbox_id matches the one provided. @@ -481,9 +525,13 @@ mod tests { async fn stored_identity_happy_path() { let mock_api = MockApiClient::new(); let tmpdb = tmp_path(); + let scw_verifier = MockSmartContractSignatureVerifier::new(true); - let store = - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmpdb)).unwrap(); + let store = EncryptedMessageStore::new( + StorageOption::Persistent(tmpdb), + EncryptedMessageStore::generate_enc_key(), + ) + .unwrap(); let nonce = 0; let address = generate_local_wallet().get_address(); let inbox_id = generate_inbox_id(&address, &nonce); @@ -493,6 +541,7 @@ mod tests { installation_keys: SignatureKeyPair::new(SignatureScheme::ED25519).unwrap(), credential: Credential::new(CredentialType::Basic, rand_vec()), signature_request: None, + is_ready: AtomicBool::new(true), }) .try_into() .unwrap(); @@ -500,26 +549,34 @@ mod tests { stored.store(&store.conn().unwrap()).unwrap(); let wrapper = ApiClientWrapper::new(mock_api, Retry::default()); let identity = IdentityStrategy::CreateIfNotFound(inbox_id.clone(), address, nonce, None); - assert!(identity.initialize_identity(&wrapper, &store).await.is_ok()); + assert!(identity + .initialize_identity(&wrapper, &store, &scw_verifier) + .await + .is_ok()); } #[tokio::test] async fn stored_identity_mismatch() { let mock_api = MockApiClient::new(); + let scw_verifier = MockSmartContractSignatureVerifier::new(true); let nonce = 0; let address = generate_local_wallet().get_address(); let stored_inbox_id = generate_inbox_id(&address, &nonce); let tmpdb = tmp_path(); - let store = - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmpdb)).unwrap(); + let store = EncryptedMessageStore::new( + StorageOption::Persistent(tmpdb), + EncryptedMessageStore::generate_enc_key(), + ) + .unwrap(); let stored: StoredIdentity = (&Identity { inbox_id: stored_inbox_id.clone(), installation_keys: SignatureKeyPair::new(SignatureScheme::ED25519).unwrap(), credential: Credential::new(CredentialType::Basic, rand_vec()), signature_request: None, + is_ready: AtomicBool::new(true), }) .try_into() .unwrap(); @@ -532,7 +589,7 @@ mod tests { let identity = IdentityStrategy::CreateIfNotFound(inbox_id.clone(), address.clone(), nonce, None); let err = identity - .initialize_identity(&wrapper, &store) + .initialize_identity(&wrapper, &store, &scw_verifier) .await .unwrap_err(); @@ -545,11 +602,11 @@ mod tests { async fn identity_persistence_test() { let tmpdb = tmp_path(); let wallet = &generate_local_wallet(); + let db_key = EncryptedMessageStore::generate_enc_key(); // Generate a new Wallet + Store let store_a = - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmpdb.clone())) - .unwrap(); + EncryptedMessageStore::new(StorageOption::Persistent(tmpdb.clone()), db_key).unwrap(); let nonce = 1; let inbox_id = generate_inbox_id(&wallet.get_address(), &nonce); @@ -567,14 +624,14 @@ mod tests { .unwrap(); register_client(&client_a, wallet).await; + assert!(client_a.identity().is_ready()); let keybytes_a = client_a.installation_public_key(); drop(client_a); // Reload the existing store and wallet let store_b = - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmpdb.clone())) - .unwrap(); + EncryptedMessageStore::new(StorageOption::Persistent(tmpdb.clone()), db_key).unwrap(); let client_b = ClientBuilder::new(IdentityStrategy::CreateIfNotFound( inbox_id, @@ -613,8 +670,7 @@ mod tests { // Use cached only strategy let store_d = - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmpdb.clone())) - .unwrap(); + EncryptedMessageStore::new(StorageOption::Persistent(tmpdb.clone()), db_key).unwrap(); let client_d = ClientBuilder::new(IdentityStrategy::CachedOnly) .local_client() .await diff --git a/xmtp_mls/src/client.rs b/xmtp_mls/src/client.rs index 84e64d1a5..8a6687247 100644 --- a/xmtp_mls/src/client.rs +++ b/xmtp_mls/src/client.rs @@ -16,7 +16,7 @@ use openmls::{ framing::{MlsMessageBodyIn, MlsMessageIn}, group::GroupEpoch, messages::Welcome, - prelude::tls_codec::{Deserialize, Error as TlsCodecError, Serialize}, + prelude::tls_codec::{Deserialize, Error as TlsCodecError}, }; use openmls_traits::OpenMlsProvider; use prost::EncodeError; @@ -27,8 +27,9 @@ use xmtp_cryptography::signature::{sanitize_evm_addresses, AddressValidationErro use xmtp_id::{ associations::{ builder::{SignatureRequest, SignatureRequestError}, - AssociationError, AssociationState, + AssociationError, AssociationState, SignatureError, }, + scw_verifier::SmartContractSignatureVerifier, InboxId, }; @@ -49,6 +50,7 @@ use crate::{ retry::Retry, retry_async, retryable, storage::{ + consent_record::{ConsentState, ConsentType, StoredConsentRecord}, db_connection::DbConnection, group::{GroupMembershipState, StoredGroup}, group_message::StoredGroupMessage, @@ -96,6 +98,8 @@ pub enum ClientError { StreamInconsistency(String), #[error("Association error: {0}")] Association(#[from] AssociationError), + #[error("signature validation error: {0}")] + SignatureValidation(#[from] SignatureError), #[error(transparent)] IdentityUpdate(#[from] IdentityUpdateError), #[error(transparent)] @@ -214,11 +218,20 @@ impl From<&str> for ClientError { } } +#[derive(Debug, Default)] +pub struct FindGroupParams { + pub allowed_states: Option>, + pub created_after_ns: Option, + pub created_before_ns: Option, + pub limit: Option, + pub include_dm_groups: bool, +} + /// Clients manage access to the network, identity, and data store -#[derive(Debug)] pub struct Client { pub(crate) api_client: ApiClientWrapper, pub(crate) context: Arc, + #[cfg(feature = "message-history")] pub(crate) history_sync_url: Option, pub(crate) local_events: broadcast::Sender, } @@ -226,13 +239,13 @@ pub struct Client { /// The local context a XMTP MLS needs to function: /// - Sqlite Database /// - Identity for the User -#[derive(Debug)] pub struct XmtpMlsLocalContext { /// XMTP Identity pub(crate) identity: Identity, /// XMTP Local Storage pub(crate) store: EncryptedMessageStore, pub(crate) mutexes: MutexRegistry, + pub scw_verifier: Box, } impl XmtpMlsLocalContext { @@ -274,17 +287,20 @@ where api_client: ApiClientWrapper, identity: Identity, store: EncryptedMessageStore, - history_sync_url: Option, + scw_verifier: Box, + #[cfg(feature = "message-history")] history_sync_url: Option, ) -> Self { let context = XmtpMlsLocalContext { identity, store, mutexes: MutexRegistry::new(), + scw_verifier, }; let (tx, _) = broadcast::channel(10); Self { api_client, context: Arc::new(context), + #[cfg(feature = "message-history")] history_sync_url, local_events: tx, } @@ -307,17 +323,33 @@ where &self, address: String, ) -> Result, ClientError> { - if let Some(sanitized_address) = sanitize_evm_addresses(vec![address])?.pop() { - let mut results = self - .api_client - .get_inbox_ids(vec![sanitized_address.clone()]) - .await?; - Ok(results.remove(&sanitized_address)) + let results = self + .find_inbox_ids_from_addresses(vec![address.clone()]) + .await?; + if let Some(first_result) = results.into_iter().next() { + Ok(first_result) } else { Ok(None) } } + pub async fn find_inbox_ids_from_addresses( + &self, + addresses: Vec, + ) -> Result>, ClientError> { + let sanitized_addresses = sanitize_evm_addresses(addresses.clone())?; + let mut results = self + .api_client + .get_inbox_ids(sanitized_addresses.clone()) + .await?; + let inbox_ids: Vec> = sanitized_addresses + .into_iter() + .map(|address| results.remove(&address)) + .collect(); + + Ok(inbox_ids) + } + /// Get sequence id, may not be consistent with the backend pub fn inbox_sequence_id(&self, conn: &DbConnection) -> Result { self.context.inbox_sequence_id(conn) @@ -336,6 +368,70 @@ where Ok(state) } + // set the consent record in the database + // if the consent record is an address also set the inboxId + pub async fn set_consent_states( + &self, + mut records: Vec, + ) -> Result<(), ClientError> { + let conn = self.store().conn()?; + + let mut new_records = Vec::new(); + let mut addresses_to_lookup = Vec::new(); + let mut record_indices = Vec::new(); + + for (index, record) in records.iter().enumerate() { + if record.entity_type == ConsentType::Address { + addresses_to_lookup.push(record.entity.clone()); + record_indices.push(index); + } + } + + let inbox_ids = self + .find_inbox_ids_from_addresses(addresses_to_lookup) + .await?; + + for (i, inbox_id_opt) in inbox_ids.into_iter().enumerate() { + if let Some(inbox_id) = inbox_id_opt { + let record = &records[record_indices[i]]; + new_records.push(StoredConsentRecord::new( + ConsentType::InboxId, + record.state, + inbox_id, + )); + } + } + + records.extend(new_records); + conn.insert_or_replace_consent_records(records)?; + + Ok(()) + } + + // get the consent record from the database + // if the consent record is an address also get the inboxId instead + pub async fn get_consent_state( + &self, + entity_type: ConsentType, + entity: String, + ) -> Result { + let conn = self.store().conn()?; + let record = if entity_type == ConsentType::Address { + if let Some(inbox_id) = self.find_inbox_id_from_address(entity.clone()).await? { + conn.get_consent_record(inbox_id, ConsentType::InboxId)? + } else { + conn.get_consent_record(entity, entity_type)? + } + } else { + conn.get_consent_record(entity, entity_type)? + }; + + match record { + Some(rec) => Ok(rec.state), + None => Ok(ConsentState::Unknown), + } + } + pub fn store(&self) -> &EncryptedMessageStore { &self.context.store } @@ -359,13 +455,17 @@ where &self.context } + pub fn smart_contract_signature_verifier(&self) -> Box { + self.context.scw_verifier.clone() + } + /// Create a new group with the default settings pub fn create_group( &self, permissions_policy_set: Option, opts: GroupMetadataOptions, ) -> Result { - log::info!("creating group"); + tracing::info!("creating group"); let group = MlsGroup::create_and_insert( self.context.clone(), @@ -386,7 +486,7 @@ where permissions_policy_set: Option, opts: GroupMetadataOptions, ) -> Result { - log::info!("creating group"); + tracing::info!("creating group"); let group = MlsGroup::create_and_insert( self.context.clone(), @@ -403,8 +503,52 @@ where Ok(group) } + /// Create a new Direct Message with the default settings + pub async fn create_dm(&self, account_address: String) -> Result { + tracing::info!("creating dm with address: {}", account_address); + + let inbox_id = match self + .find_inbox_id_from_address(account_address.clone()) + .await? + { + Some(id) => id, + None => { + return Err(ClientError::Storage(StorageError::NotFound(format!( + "inbox id for address {} not found", + account_address + )))) + } + }; + + self.create_dm_by_inbox_id(inbox_id).await + } + + /// Create a new Direct Message with the default settings + pub async fn create_dm_by_inbox_id( + &self, + dm_target_inbox_id: InboxId, + ) -> Result { + tracing::info!("creating dm with {}", dm_target_inbox_id); + + let group = MlsGroup::create_dm_and_insert( + self.context.clone(), + GroupMembershipState::Allowed, + dm_target_inbox_id.clone(), + )?; + + group + .add_members_by_inbox_id(self, vec![dm_target_inbox_id]) + .await?; + + // notify any streams of the new group + let _ = self.local_events.send(LocalEvents::NewGroup(group.clone())); + + Ok(group) + } + + #[cfg(feature = "message-history")] pub(crate) fn create_sync_group(&self) -> Result { - log::info!("creating sync group"); + tracing::info!("creating sync group"); let sync_group = MlsGroup::create_and_insert_sync_group(self.context.clone())?; Ok(sync_group) @@ -449,17 +593,17 @@ where /// - created_after_ns: only return groups created after the given timestamp (in nanoseconds) /// - created_before_ns: only return groups created before the given timestamp (in nanoseconds) /// - limit: only return the first `limit` groups - pub fn find_groups( - &self, - allowed_states: Option>, - created_after_ns: Option, - created_before_ns: Option, - limit: Option, - ) -> Result, ClientError> { + pub fn find_groups(&self, params: FindGroupParams) -> Result, ClientError> { Ok(self .store() .conn()? - .find_groups(allowed_states, created_after_ns, created_before_ns, limit)? + .find_groups( + params.allowed_states, + params.created_after_ns, + params.created_before_ns, + params.limit, + params.include_dm_groups, + )? .into_iter() .map(|stored_group| { MlsGroup::new( @@ -477,7 +621,7 @@ where &self, signature_request: SignatureRequest, ) -> Result<(), ClientError> { - log::info!("registering identity"); + tracing::info!("registering identity"); // Register the identity before applying the signature request let provider: XmtpOpenMlsProvider = self.store().conn()?.into(); @@ -493,11 +637,13 @@ where /// Upload a new key package to the network replacing an existing key package /// This is expected to be run any time the client receives new Welcome messages pub async fn rotate_key_package(&self) -> Result<(), ClientError> { - let provider: XmtpOpenMlsProvider = self.store().conn()?.into(); - - let kp = self.identity().new_key_package(&provider)?; - let kp_bytes = kp.tls_serialize_detached()?; - self.api_client.upload_key_package(kp_bytes, true).await?; + self.store() + .transaction_async(|provider| async move { + self.identity() + .rotate_key_package(&provider, &self.api_client) + .await + }) + .await?; Ok(()) } @@ -575,6 +721,7 @@ where /// Returns any new groups created in the operation pub async fn sync_welcomes(&self) -> Result, ClientError> { let envelopes = self.query_welcome_messages(&self.store().conn()?).await?; + let num_envelopes = envelopes.len(); let id = self.installation_public_key(); let groups: Vec = stream::iter(envelopes.into_iter()) @@ -582,7 +729,7 @@ where let welcome_v1 = match extract_welcome_message(envelope) { Ok(inner) => inner, Err(err) => { - log::error!("failed to extract welcome message: {}", err); + tracing::error!("failed to extract welcome message: {}", err); return None; } }; @@ -611,9 +758,9 @@ where use crate::DuplicateItem::*; if matches!(err, GroupError::Storage(Duplicate(WelcomeId(_)))) { - log::warn!("failed to create group from welcome due to duplicate welcome ID: {}", err); + tracing::warn!("failed to create group from welcome due to duplicate welcome ID: {}", err); } else { - log::error!("failed to create group from welcome: {}", err); + tracing::error!("failed to create group from welcome: {}", err); } Err(MessageProcessingError::WelcomeProcessing( @@ -632,6 +779,11 @@ where .collect() .await; + // If any welcomes were found, rotate your key package + if num_envelopes > 0 { + self.rotate_key_package().await?; + } + Ok(groups) } @@ -652,8 +804,8 @@ where let active_group_count = Arc::clone(&active_group_count); async move { let mls_group = group.load_mls_group(provider_ref)?; - log::info!("[{}] syncing group", self.inbox_id()); - log::info!( + tracing::info!("[{}] syncing group", self.inbox_id()); + tracing::info!( "current epoch for [{}] in sync_all_groups() is Epoch: [{}]", self.inbox_id(), mls_group.epoch() @@ -755,15 +907,51 @@ pub fn deserialize_welcome(welcome_bytes: &Vec) -> Result( + client: &Client, + installation_id: &[u8], + ) -> Vec { + let kps = client + .get_key_packages_for_installation_ids(vec![installation_id.to_vec()]) + .await + .unwrap(); + let kp = kps.first().unwrap(); + + serialize_key_package_hash_ref(&kp.inner, &client.mls_provider().unwrap()).unwrap() + } + + #[tokio::test] + async fn test_key_package_rotation() { + let alix_wallet = generate_local_wallet(); + let bo_wallet = generate_local_wallet(); + let alix = ClientBuilder::new_test_client(&alix_wallet).await; + let bo = ClientBuilder::new_test_client(&bo_wallet).await; + let bo_store = bo.store(); + + let alix_original_init_key = + get_key_package_init_key(&alix, &alix.installation_public_key()).await; + let bo_original_init_key = + get_key_package_init_key(&bo, &bo.installation_public_key()).await; + + // Bo's original key should be deleted + let bo_original_from_db = bo_store + .conn() + .unwrap() + .find_key_package_history_entry_by_hash_ref(bo_original_init_key.clone()); + assert!(bo_original_from_db.is_ok()); + + alix.create_group_with_members( + vec![bo_wallet.get_address()], + None, + GroupMetadataOptions::default(), + ) + .await + .unwrap(); + + bo.sync_welcomes().await.unwrap(); + + let bo_new_key = get_key_package_init_key(&bo, &bo.installation_public_key()).await; + // Bo's key should have changed + assert_ne!(bo_original_init_key, bo_new_key); + + bo.sync_welcomes().await.unwrap(); + let bo_new_key_2 = get_key_package_init_key(&bo, &bo.installation_public_key()).await; + // Bo's key should not have changed syncing the second time. + assert_eq!(bo_new_key, bo_new_key_2); + + alix.sync_welcomes().await.unwrap(); + let alix_key_2 = get_key_package_init_key(&alix, &alix.installation_public_key()).await; + // Alix's key should not have changed at all + assert_eq!(alix_original_init_key, alix_key_2); + + alix.create_group_with_members( + vec![bo_wallet.get_address()], + None, + GroupMetadataOptions::default(), + ) + .await + .unwrap(); + bo.sync_welcomes().await.unwrap(); + + // Bo should have two groups now + let bo_groups = bo.find_groups(FindGroupParams::default()).unwrap(); + assert_eq!(bo_groups.len(), 2); + + // Bo's original key should be deleted + let bo_original_after_delete = bo_store + .conn() + .unwrap() + .find_key_package_history_entry_by_hash_ref(bo_original_init_key); + assert!(bo_original_after_delete.is_err()); + } } diff --git a/xmtp_mls/src/credential/grant_messaging_access_association.rs b/xmtp_mls/src/credential/grant_messaging_access_association.rs deleted file mode 100644 index 86a6cce00..000000000 --- a/xmtp_mls/src/credential/grant_messaging_access_association.rs +++ /dev/null @@ -1,290 +0,0 @@ -use chrono::DateTime; -use serde::{Deserialize, Serialize}; - -use xmtp_cryptography::signature::{ - ed25519_public_key_to_address, sanitize_evm_addresses, RecoverableSignature, -}; -use xmtp_proto::xmtp::mls::message_contents::{ - GrantMessagingAccessAssociation as GrantMessagingAccessAssociationProto, - RecoverableEcdsaSignature as RecoverableEcdsaSignatureProto, -}; - -use crate::{types::Address, utils::time::NS_IN_SEC, InboxOwner}; - -use super::AssociationError; - -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -pub struct UnsignedGrantMessagingAccessData { - pub(crate) account_address: Address, - pub(crate) installation_public_key: Vec, - pub(crate) created_ns: u64, - iso8601_time: String, -} - -impl UnsignedGrantMessagingAccessData { - pub fn new( - account_address: Address, - installation_public_key: Vec, - created_ns: u64, - ) -> Result { - let account_address = sanitize_evm_addresses(vec![account_address])?[0].clone(); - let created_time = DateTime::from_timestamp( - created_ns as i64 / NS_IN_SEC, - (created_ns as i64 % NS_IN_SEC) as u32, - ) - .ok_or(AssociationError::MalformedAssociation)?; - let iso8601_time = format!("{}", created_time.format("%+")); - - Ok(Self { - account_address, - installation_public_key, - created_ns, - iso8601_time, - }) - } - - pub fn account_address(&self) -> Address { - self.account_address.clone() - } - - pub fn installation_public_key(&self) -> Vec { - self.installation_public_key.clone() - } - - pub fn created_ns(&self) -> u64 { - self.created_ns - } - - fn header_text() -> String { - let label = "Grant Messaging Access".to_string(); - format!("XMTP : {}", label) - } - - fn body_text( - account_address: &Address, - installation_public_key: &[u8], - iso8601_time: &str, - ) -> String { - format!( - "\nCurrent Time: {}\nAccount Address: {}\nInstallation ID: {}", - iso8601_time, - account_address, - ed25519_public_key_to_address(installation_public_key) - ) - } - - fn footer_text() -> String { - "For more info: https://xmtp.org/signatures/".to_string() - } - - pub fn text(&self) -> String { - format!( - "{}\n{}\n\n{}", - Self::header_text(), - Self::body_text( - &self.account_address, - &self.installation_public_key, - &self.iso8601_time - ), - Self::footer_text() - ) - .to_string() - } -} - -/// An Association is link between a blockchain account and an xmtp installation for the purposes of -/// authentication. -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] -pub struct GrantMessagingAccessAssociation { - association_data: UnsignedGrantMessagingAccessData, - signature: RecoverableSignature, -} - -impl GrantMessagingAccessAssociation { - pub(crate) fn new_validated( - association_data: UnsignedGrantMessagingAccessData, - signature: RecoverableSignature, - ) -> Result { - let this = Self { - association_data, - signature, - }; - this.is_valid()?; - Ok(this) - } - - pub(crate) fn create( - owner: &impl InboxOwner, - installation_public_key: Vec, - created_ns: u64, - ) -> Result { - let unsigned_data = UnsignedGrantMessagingAccessData::new( - owner.get_address(), - installation_public_key, - created_ns, - )?; - let text = unsigned_data.text(); - let signature = owner.sign(&text)?; - Self::new_validated(unsigned_data, signature) - } - - pub fn from_proto_validated( - proto: GrantMessagingAccessAssociationProto, - expected_installation_public_key: &[u8], - ) -> Result { - let signature = RecoverableSignature::Eip191Signature( - proto - .signature - .ok_or(AssociationError::MalformedAssociation)? - .bytes, - ); - Self::new_validated( - UnsignedGrantMessagingAccessData::new( - proto.account_address, - expected_installation_public_key.to_vec(), - proto.created_ns, - )?, - signature, - ) - } - - fn is_valid(&self) -> Result<(), AssociationError> { - let assumed_addr = self.association_data.account_address(); - - let addr = self - .signature - .recover_address(&self.association_data.text())?; - - let sanitized_addresses = sanitize_evm_addresses(vec![assumed_addr, addr])?; - if sanitized_addresses[0] != sanitized_addresses[1] { - Err(AssociationError::AddressMismatch { - provided_addr: sanitized_addresses[0].clone(), - signing_addr: sanitized_addresses[1].clone(), - }) - } else { - Ok(()) - } - } - - pub fn account_address(&self) -> String { - self.association_data.account_address() - } - - pub fn installation_public_key(&self) -> Vec { - self.association_data.installation_public_key() - } - - pub fn created_ns(&self) -> u64 { - self.association_data.created_ns() - } -} - -impl From for GrantMessagingAccessAssociationProto { - fn from(assoc: GrantMessagingAccessAssociation) -> Self { - let account_address = assoc.account_address(); - let created_ns = assoc.created_ns(); - Self { - account_address, - // Hardcoded version for now - association_text_version: 1, - signature: Some(RecoverableEcdsaSignatureProto { - bytes: assoc.signature.into(), - }), - created_ns, - } - } -} - -#[cfg(test)] -pub mod tests { - use ethers::signers::{LocalWallet, Signer}; - - use xmtp_cryptography::{signature::h160addr_to_string, utils::rng}; - use xmtp_proto::xmtp::mls::message_contents::GrantMessagingAccessAssociation as GrantMessagingAccessAssociationProto; - - use crate::credential::{ - grant_messaging_access_association::GrantMessagingAccessAssociation, - UnsignedGrantMessagingAccessData, - }; - - #[tokio::test] - async fn assoc_gen() { - let key_bytes = vec![22, 33, 44, 55]; - - let wallet = LocalWallet::new(&mut rng()); - let other_wallet = LocalWallet::new(&mut rng()); - let addr = h160addr_to_string(wallet.address()); - let other_addr = h160addr_to_string(other_wallet.address()); - let grant_time = 1609459200000000; - let bad_grant_time = 1609459200000001; - - let data = - UnsignedGrantMessagingAccessData::new(addr.clone(), key_bytes.clone(), grant_time) - .unwrap(); - let sig = wallet.sign_message(data.text()).await.expect("BadSign"); - - let other_data = UnsignedGrantMessagingAccessData::new( - other_addr.clone(), - key_bytes.clone(), - grant_time, - ) - .unwrap(); - let other_sig = wallet - .sign_message(other_data.text()) - .await - .expect("BadSign"); - - let bad_key_bytes = vec![11, 22, 33]; - - assert!(GrantMessagingAccessAssociation::new_validated( - UnsignedGrantMessagingAccessData::new(addr.clone(), key_bytes.clone(), grant_time) - .unwrap(), - sig.into() - ) - .is_ok()); - assert!(GrantMessagingAccessAssociation::new_validated( - UnsignedGrantMessagingAccessData::new(addr.clone(), bad_key_bytes.clone(), grant_time) - .unwrap(), - sig.into() - ) - .is_err()); - assert!(GrantMessagingAccessAssociation::new_validated( - UnsignedGrantMessagingAccessData::new( - other_addr.clone(), - key_bytes.clone(), - grant_time, - ) - .unwrap(), - sig.into() - ) - .is_err()); - assert!(GrantMessagingAccessAssociation::new_validated( - UnsignedGrantMessagingAccessData::new(addr.clone(), key_bytes.clone(), bad_grant_time) - .unwrap(), - sig.into() - ) - .is_err()); - assert!(GrantMessagingAccessAssociation::new_validated( - UnsignedGrantMessagingAccessData::new(addr.clone(), key_bytes.clone(), grant_time) - .unwrap(), - other_sig.into() - ) - .is_err()); - } - - #[tokio::test] - async fn to_proto() { - let key_bytes = vec![22, 33, 44, 55]; - let wallet = LocalWallet::new(&mut rng()); - let addr = h160addr_to_string(wallet.address()); - let created_ns = 1609459200000000; - let data = UnsignedGrantMessagingAccessData::new(addr, key_bytes, created_ns).unwrap(); - let sig = wallet.sign_message(data.text()).await.expect("BadSign"); - - let assoc = GrantMessagingAccessAssociation::new_validated(data, sig.into()).unwrap(); - let proto_signature: GrantMessagingAccessAssociationProto = assoc.into(); - - assert_eq!(proto_signature.association_text_version, 1); - assert_eq!(proto_signature.signature.unwrap().bytes, sig.to_vec()); - } -} diff --git a/xmtp_mls/src/credential/legacy_create_identity_association.rs b/xmtp_mls/src/credential/legacy_create_identity_association.rs deleted file mode 100644 index c974064e0..000000000 --- a/xmtp_mls/src/credential/legacy_create_identity_association.rs +++ /dev/null @@ -1,211 +0,0 @@ -use prost::Message; - -use xmtp_id::associations::signature::ValidatedLegacySignedPublicKey; -use xmtp_proto::xmtp::{ - message_contents::{signed_private_key, SignedPrivateKey as LegacySignedPrivateKeyProto}, - mls::message_contents::{ - LegacyCreateIdentityAssociation as LegacyCreateIdentityAssociationProto, - RecoverableEcdsaSignature as RecoverableEcdsaSignatureProto, - }, -}; -use xmtp_v2::k256_helper; - -use super::AssociationError; - -/// An Association is link between a blockchain account and an xmtp installation for the purposes of -/// authentication. -pub struct LegacyCreateIdentityAssociation { - installation_public_key: Vec, - delegating_signature: Vec, - legacy_signed_public_key: ValidatedLegacySignedPublicKey, -} - -impl LegacyCreateIdentityAssociation { - fn new_validated( - installation_public_key: Vec, - delegating_signature: Vec, - legacy_signed_public_key: ValidatedLegacySignedPublicKey, - ) -> Result { - let this = Self { - installation_public_key, - delegating_signature, - legacy_signed_public_key, - }; - this.is_valid()?; - Ok(this) - } - - pub(crate) fn create( - legacy_signed_private_key: Vec, - installation_public_key: Vec, - ) -> Result { - let legacy_signed_private_key_proto = - LegacySignedPrivateKeyProto::decode(legacy_signed_private_key.as_slice())?; - let signed_private_key::Union::Secp256k1(secp256k1) = legacy_signed_private_key_proto - .union - .ok_or(AssociationError::MalformedLegacyKey( - "Missing secp256k1.union field".to_string(), - ))?; - let legacy_private_key = secp256k1.bytes; - let (mut delegating_signature, recovery_id) = k256_helper::sign_sha256( - &legacy_private_key, // secret_key - &installation_public_key, // message - ) - .map_err(AssociationError::LegacySignature)?; - delegating_signature.push(recovery_id); // TODO: normalize recovery ID if necessary - - let legacy_signed_public_key_proto = legacy_signed_private_key_proto.public_key.ok_or( - AssociationError::MalformedLegacyKey("Missing public_key field".to_string()), - )?; - Self::new_validated( - installation_public_key, - delegating_signature, - legacy_signed_public_key_proto.try_into()?, // ValidatedLegacySignedPublicKey - ) - } - - pub fn from_proto_validated( - proto: LegacyCreateIdentityAssociationProto, - expected_installation_public_key: &[u8], - ) -> Result { - let delegating_signature = proto - .signature - .ok_or(AssociationError::MalformedAssociation)? - .bytes; - let legacy_signed_public_key_proto = proto - .signed_legacy_create_identity_key - .ok_or(AssociationError::MalformedAssociation)?; - - Self::new_validated( - expected_installation_public_key.to_vec(), - delegating_signature, - legacy_signed_public_key_proto.try_into()?, // ValidatedLegacySignedPublicKey - ) - } - - fn is_valid(&self) -> Result<(), AssociationError> { - // Validate legacy key signs installation key - if self.delegating_signature.len() != 65 { - return Err(AssociationError::MalformedAssociation); - } - assert!(k256_helper::verify_sha256( - &self.legacy_signed_public_key.key_bytes(), // signed_by - &self.installation_public_key, // message - &self.delegating_signature[0..64], // signature - self.delegating_signature[64], // recovery_id - ) - .map_err(AssociationError::LegacySignature)?); // always returns true if no error - - // Wallet signature of legacy key is internally validated by ValidatedLegacySignedPublicKey on creation - Ok(()) - } - - pub fn account_address(&self) -> String { - self.legacy_signed_public_key.account_address() - } - - pub fn installation_public_key(&self) -> Vec { - self.installation_public_key.clone() - } - - pub fn created_ns(&self) -> u64 { - self.legacy_signed_public_key.created_ns() - } -} - -impl From for LegacyCreateIdentityAssociationProto { - fn from(assoc: LegacyCreateIdentityAssociation) -> Self { - Self { - signature: Some(RecoverableEcdsaSignatureProto { - bytes: assoc.delegating_signature.clone(), - }), - signed_legacy_create_identity_key: Some(assoc.legacy_signed_public_key.into()), - } - } -} - -#[cfg(test)] -pub mod tests { - use openmls_basic_credential::SignatureKeyPair; - use xmtp_proto::xmtp::mls::message_contents::LegacyCreateIdentityAssociation as LegacyCreateIdentityAssociationProto; - - use crate::{ - assert_err, - configuration::CIPHERSUITE, - credential::{ - legacy_create_identity_association::LegacyCreateIdentityAssociation, AssociationError, - }, - }; - - #[tokio::test] - async fn validate_serialization_round_trip() { - let legacy_address = "0x419cb1fa5635b0c6df47c9dc5765c8f1f4dff78e"; - let legacy_signed_private_key_proto = vec![ - 8, 128, 154, 196, 133, 220, 244, 197, 216, 23, 18, 34, 10, 32, 214, 70, 104, 202, 68, - 204, 25, 202, 197, 141, 239, 159, 145, 249, 55, 242, 147, 126, 3, 124, 159, 207, 96, - 135, 134, 122, 60, 90, 82, 171, 131, 162, 26, 153, 1, 10, 79, 8, 128, 154, 196, 133, - 220, 244, 197, 216, 23, 26, 67, 10, 65, 4, 232, 32, 50, 73, 113, 99, 115, 168, 104, - 229, 206, 24, 217, 132, 223, 217, 91, 63, 137, 136, 50, 89, 82, 186, 179, 150, 7, 127, - 140, 10, 165, 117, 233, 117, 196, 134, 227, 143, 125, 210, 187, 77, 195, 169, 162, 116, - 34, 20, 196, 145, 40, 164, 246, 139, 197, 154, 233, 190, 148, 35, 131, 240, 106, 103, - 18, 70, 18, 68, 10, 64, 90, 24, 36, 99, 130, 246, 134, 57, 60, 34, 142, 165, 221, 123, - 63, 27, 138, 242, 195, 175, 212, 146, 181, 152, 89, 48, 8, 70, 104, 94, 163, 0, 25, - 196, 228, 190, 49, 108, 141, 60, 174, 150, 177, 115, 229, 138, 92, 105, 170, 226, 204, - 249, 206, 12, 37, 145, 3, 35, 226, 15, 49, 20, 102, 60, 16, 1, - ]; - let installation_keys = SignatureKeyPair::new(CIPHERSUITE.signature_algorithm()).unwrap(); - - let assoc = LegacyCreateIdentityAssociation::create( - legacy_signed_private_key_proto, - installation_keys.to_public_vec(), - ) - .unwrap(); - - let proto: LegacyCreateIdentityAssociationProto = assoc.into(); - let assoc = LegacyCreateIdentityAssociation::from_proto_validated( - proto, - &installation_keys.to_public_vec(), - ) - .unwrap(); - assert_eq!(assoc.account_address(), legacy_address); - assert_eq!( - assoc.installation_public_key(), - installation_keys.to_public_vec() - ); - } - - #[tokio::test] - async fn validate_bad_signature() { - // let legacy_address = "0x419Cb1fA5635b0c6Df47c9DC5765c8f1f4DfF78e"; - let legacy_signed_private_key_proto = vec![ - 8, 128, 154, 196, 133, 220, 244, 197, 216, 23, 18, 34, 10, 32, 214, 70, 104, 202, 68, - 204, 25, 202, 197, 141, 239, 159, 145, 249, 55, 242, 147, 126, 3, 124, 159, 207, 96, - 135, 134, 122, 60, 90, 82, 171, 131, 162, 26, 153, 1, 10, 79, 8, 128, 154, 196, 133, - 220, 244, 197, 216, 23, 26, 67, 10, 65, 4, 232, 32, 50, 73, 113, 99, 115, 168, 104, - 229, 206, 24, 217, 132, 223, 217, 91, 63, 137, 136, 50, 89, 82, 186, 179, 150, 7, 127, - 140, 10, 165, 117, 233, 117, 196, 134, 227, 143, 125, 210, 187, 77, 195, 169, 162, 116, - 34, 20, 196, 145, 40, 164, 246, 139, 197, 154, 233, 190, 148, 35, 131, 240, 106, 103, - 18, 70, 18, 68, 10, 64, 90, 24, 36, 99, 130, 246, 134, 57, 60, 34, 142, 165, 221, 123, - 63, 27, 138, 242, 195, 175, 212, 146, 181, 152, 89, 48, 8, 70, 104, 94, 163, 0, 25, - 196, 228, 190, 49, 108, 141, 60, 174, 150, 177, 115, 229, 138, 92, 105, 170, 226, 204, - 249, 206, 12, 37, 145, 3, 35, 226, 15, 49, 20, 102, 60, 16, 1, - ]; - let installation_keys = SignatureKeyPair::new(CIPHERSUITE.signature_algorithm()).unwrap(); - - let mut assoc = LegacyCreateIdentityAssociation::create( - legacy_signed_private_key_proto, - installation_keys.to_public_vec(), - ) - .unwrap(); - assoc.delegating_signature[0] ^= 1; - - let proto: LegacyCreateIdentityAssociationProto = assoc.into(); - assert_err!( - LegacyCreateIdentityAssociation::from_proto_validated( - proto, - &installation_keys.to_public_vec(), - ), - AssociationError::LegacySignature(_) - ); - } -} diff --git a/xmtp_mls/src/credential/mod.rs b/xmtp_mls/src/credential/mod.rs deleted file mode 100644 index 44e137ae3..000000000 --- a/xmtp_mls/src/credential/mod.rs +++ /dev/null @@ -1,185 +0,0 @@ -mod grant_messaging_access_association; -mod legacy_create_identity_association; - -use openmls_basic_credential::SignatureKeyPair; -use prost::{DecodeError, Message}; -use thiserror::Error; - -use xmtp_cryptography::signature::AddressValidationError; -use xmtp_cryptography::signature::{RecoverableSignature, SignatureError}; -use xmtp_proto::xmtp::mls::message_contents::{ - mls_credential::Association as AssociationProto, MlsCredential as MlsCredentialProto, -}; - -use crate::{types::Address, utils::time::now_ns, InboxOwner}; - -pub use self::grant_messaging_access_association::GrantMessagingAccessAssociation; -pub use self::grant_messaging_access_association::UnsignedGrantMessagingAccessData; -pub use self::legacy_create_identity_association::LegacyCreateIdentityAssociation; - -#[derive(Debug, Error)] -pub enum AssociationError { - #[error("bad signature")] - BadSignature(#[from] SignatureError), - #[error("decode error: {0}")] - DecodeError(#[from] DecodeError), - #[error("legacy key: {0}")] - MalformedLegacyKey(String), - #[error("legacy signature: {0}")] - LegacySignature(String), - #[error("Association text mismatch")] - TextMismatch, - #[error("Installation public key mismatch")] - InstallationPublicKeyMismatch, - #[error( - "Address mismatch in Association: Provided:{provided_addr:?} != signed:{signing_addr:?}" - )] - AddressMismatch { - provided_addr: Address, - signing_addr: Address, - }, - #[error(transparent)] - AddressValidationError(#[from] AddressValidationError), - #[error("Malformed association")] - MalformedAssociation, - - #[error(transparent)] - // TODO: remove this AssociationError and use [xmtp_id::associations::AssociationError] - IDAssociationError(#[from] xmtp_id::associations::AssociationError), - #[error(transparent)] - SignatureError(#[from] xmtp_id::associations::SignatureError), -} - -pub enum Credential { - GrantMessagingAccess(GrantMessagingAccessAssociation), - LegacyCreateIdentity(LegacyCreateIdentityAssociation), -} - -impl Credential { - pub fn create( - installation_keys: &SignatureKeyPair, - owner: &impl InboxOwner, - ) -> Result { - let created_ns = now_ns() as u64; - let association = GrantMessagingAccessAssociation::create( - owner, - installation_keys.to_public_vec(), - created_ns, - )?; - Ok(Self::GrantMessagingAccess(association)) - } - - pub fn create_from_external_signer( - association_data: UnsignedGrantMessagingAccessData, - signature: Vec, - ) -> Result { - let association = GrantMessagingAccessAssociation::new_validated( - association_data, - RecoverableSignature::Eip191Signature(signature), - )?; - Ok(Self::GrantMessagingAccess(association)) - } - - pub fn create_from_legacy( - installation_keys: &SignatureKeyPair, - legacy_signed_private_key: Vec, - ) -> Result { - let association = LegacyCreateIdentityAssociation::create( - legacy_signed_private_key, - installation_keys.to_public_vec(), - )?; - Ok(Self::LegacyCreateIdentity(association)) - } - - pub fn from_proto_validated( - proto: MlsCredentialProto, - expected_account_address: Option<&str>, // Must validate when fetching identity updates - expected_installation_public_key: Option<&[u8]>, // Must cross-reference against leaf node when relevant - ) -> Result { - let credential = match proto - .association - .ok_or(AssociationError::MalformedAssociation)? - { - AssociationProto::MessagingAccess(assoc) => { - GrantMessagingAccessAssociation::from_proto_validated( - assoc, - &proto.installation_public_key, - ) - .map(Credential::GrantMessagingAccess) - } - AssociationProto::LegacyCreateIdentity(assoc) => { - LegacyCreateIdentityAssociation::from_proto_validated( - assoc, - &proto.installation_public_key, - ) - .map(Credential::LegacyCreateIdentity) - } - }?; - - if let Some(address) = expected_account_address { - if credential.address() != address { - return Err(AssociationError::AddressMismatch { - provided_addr: address.to_string(), - signing_addr: credential.address(), - }); - } - } - if let Some(public_key) = expected_installation_public_key { - if credential.installation_public_key() != public_key { - return Err(AssociationError::InstallationPublicKeyMismatch); - } - } - Ok(credential) - } - - pub fn address(&self) -> String { - match &self { - Credential::GrantMessagingAccess(assoc) => assoc.account_address(), - Credential::LegacyCreateIdentity(assoc) => assoc.account_address(), - } - } - - pub fn installation_public_key(&self) -> Vec { - match &self { - Credential::GrantMessagingAccess(assoc) => assoc.installation_public_key(), - Credential::LegacyCreateIdentity(assoc) => assoc.installation_public_key(), - } - } - - pub fn created_ns(&self) -> u64 { - match &self { - Credential::GrantMessagingAccess(assoc) => assoc.created_ns(), - Credential::LegacyCreateIdentity(assoc) => assoc.created_ns(), - } - } -} - -impl From for MlsCredentialProto { - fn from(credential: Credential) -> Self { - Self { - installation_public_key: credential.installation_public_key(), - association: match credential { - Credential::GrantMessagingAccess(assoc) => { - Some(AssociationProto::MessagingAccess(assoc.into())) - } - Credential::LegacyCreateIdentity(assoc) => { - Some(AssociationProto::LegacyCreateIdentity(assoc.into())) - } - }, - } - } -} - -pub fn get_validated_account_address( - credential: &[u8], - installation_public_key: &[u8], -) -> Result { - let proto = MlsCredentialProto::decode(credential)?; - let credential = Credential::from_proto_validated( - proto, - None, // expected_account_address - Some(installation_public_key), - )?; - - Ok(credential.address()) -} diff --git a/xmtp_mls/src/groups/group_metadata.rs b/xmtp_mls/src/groups/group_metadata.rs index 608294e14..d80ea93ec 100644 --- a/xmtp_mls/src/groups/group_metadata.rs +++ b/xmtp_mls/src/groups/group_metadata.rs @@ -3,7 +3,8 @@ use prost::Message; use thiserror::Error; use xmtp_proto::xmtp::mls::message_contents::{ - ConversationType as ConversationTypeProto, GroupMetadataV1 as GroupMetadataProto, + ConversationType as ConversationTypeProto, DmMembers as DmMembersProto, + GroupMetadataV1 as GroupMetadataProto, Inbox as InboxProto, }; #[derive(Debug, Error)] @@ -16,6 +17,10 @@ pub enum GroupMetadataError { InvalidConversationType, #[error("missing extension")] MissingExtension, + #[error("invalid dm members")] + InvalidDmMembers, + #[error("missing a dm member")] + MissingDmMember, } #[derive(Debug, Clone, PartialEq)] @@ -23,40 +28,35 @@ pub struct GroupMetadata { pub conversation_type: ConversationType, // TODO: Remove this once transition is completed pub creator_inbox_id: String, + pub dm_members: Option, } impl GroupMetadata { - pub fn new(conversation_type: ConversationType, creator_inbox_id: String) -> Self { + pub fn new( + conversation_type: ConversationType, + creator_inbox_id: String, + dm_members: Option, + ) -> Self { Self { conversation_type, creator_inbox_id, + dm_members, } } - - pub(crate) fn from_proto(proto: GroupMetadataProto) -> Result { - Ok(Self::new( - proto.conversation_type.try_into()?, - proto.creator_inbox_id.clone(), - )) - } - - pub(crate) fn to_proto(&self) -> Result { - let conversation_type: ConversationTypeProto = self.conversation_type.clone().into(); - Ok(GroupMetadataProto { - conversation_type: conversation_type as i32, - creator_inbox_id: self.creator_inbox_id.clone(), - creator_account_address: "".to_string(), // TODO: remove from proto - dm_members: None, - }) - } } impl TryFrom for Vec { type Error = GroupMetadataError; fn try_from(value: GroupMetadata) -> Result { - let mut buf = Vec::new(); - let proto_val = value.to_proto()?; + let conversation_type: ConversationTypeProto = value.conversation_type.clone().into(); + let proto_val = GroupMetadataProto { + conversation_type: conversation_type as i32, + creator_inbox_id: value.creator_inbox_id.clone(), + creator_account_address: "".to_string(), // TODO: remove from proto + dm_members: value.dm_members.clone().map(|dm| dm.into()), + }; + let mut buf: Vec = Vec::new(); proto_val.encode(&mut buf)?; Ok(buf) @@ -68,7 +68,7 @@ impl TryFrom<&Vec> for GroupMetadata { fn try_from(value: &Vec) -> Result { let proto_val = GroupMetadataProto::decode(value.as_slice())?; - Self::from_proto(proto_val) + proto_val.try_into() } } @@ -76,7 +76,12 @@ impl TryFrom for GroupMetadata { type Error = GroupMetadataError; fn try_from(value: GroupMetadataProto) -> Result { - Self::from_proto(value) + let dm_members = value.dm_members.map(DmMembers::try_from).transpose()?; + Ok(Self::new( + value.conversation_type.try_into()?, + value.creator_inbox_id, + dm_members, + )) } } @@ -121,6 +126,42 @@ impl TryFrom for ConversationType { } } +#[derive(Debug, Clone, PartialEq)] +pub struct DmMembers { + pub member_one_inbox_id: String, + pub member_two_inbox_id: String, +} + +impl From for DmMembersProto { + fn from(value: DmMembers) -> Self { + DmMembersProto { + dm_member_one: Some(InboxProto { + inbox_id: value.member_one_inbox_id.clone(), + }), + dm_member_two: Some(InboxProto { + inbox_id: value.member_two_inbox_id.clone(), + }), + } + } +} + +impl TryFrom for DmMembers { + type Error = GroupMetadataError; + + fn try_from(value: DmMembersProto) -> Result { + Ok(Self { + member_one_inbox_id: value + .dm_member_one + .ok_or(GroupMetadataError::MissingDmMember)? + .inbox_id, + member_two_inbox_id: value + .dm_member_two + .ok_or(GroupMetadataError::MissingDmMember)? + .inbox_id, + }) + } +} + pub fn extract_group_metadata(group: &OpenMlsGroup) -> Result { let extension = group .export_group_context() diff --git a/xmtp_mls/src/groups/group_mutable_metadata.rs b/xmtp_mls/src/groups/group_mutable_metadata.rs index 6b1eaf2fe..c693782e5 100644 --- a/xmtp_mls/src/groups/group_mutable_metadata.rs +++ b/xmtp_mls/src/groups/group_mutable_metadata.rs @@ -18,6 +18,7 @@ use crate::configuration::{ use super::GroupMetadataOptions; +/// Errors that can occur when working with GroupMutableMetadata. #[derive(Debug, Error)] pub enum GroupMutableMetadataError { #[error("serialization: {0}")] @@ -36,7 +37,10 @@ pub enum GroupMutableMetadataError { MissingMetadataField, } -// Fields should be added to supported_fields fn for Metadata Update Support +/// Represents the "updateable" metadata fields for a group. +/// Members ability to update metadata is gated by the group permissions. +/// +/// New fields should be added to the `supported_fields` function for Metadata Update Support. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum MetadataField { GroupName, @@ -46,6 +50,7 @@ pub enum MetadataField { } impl MetadataField { + /// String representations used as keys in the GroupMutableMetadata attributes map. pub const fn as_str(&self) -> &'static str { match self { MetadataField::GroupName => "group_name", @@ -62,15 +67,24 @@ impl fmt::Display for MetadataField { } } +/// Represents the mutable metadata for a group. +/// +/// This struct is stored as an MLS Unknown Group Context Extension. #[derive(Debug, Clone, PartialEq)] pub struct GroupMutableMetadata { - // Allow libxmtp to receive attributes from updated versions not yet captured in MetadataField + /// Map to store various metadata attributes (e.g., group name, description). + /// Allows libxmtp to receive attributes from updated versions not yet captured in MetadataField. pub attributes: HashMap, + /// List of admin inbox IDs for this group. + /// See [GroupMutablePermissions](crate::groups::GroupMutablePermissions) for more details on admin permissions. pub admin_list: Vec, + /// List of super admin inbox IDs for this group. + /// See [GroupMutablePermissions](crate::groups::GroupMutablePermissions) for more details on super admin permissions. pub super_admin_list: Vec, } impl GroupMutableMetadata { + /// Creates a new GroupMutableMetadata instance. pub fn new( attributes: HashMap, admin_list: Vec, @@ -83,6 +97,9 @@ impl GroupMutableMetadata { } } + /// Creates a new GroupMutableMetadata instance with default values. + /// The creator is automatically added as a super admin. + /// See [GroupMutablePermissions](crate::groups::GroupMutablePermissions) for more details on super admin permissions. pub fn new_default(creator_inbox_id: String, opts: GroupMetadataOptions) -> Self { let mut attributes = HashMap::new(); attributes.insert( @@ -113,7 +130,38 @@ impl GroupMutableMetadata { } } - // These fields will receive default permission policies for new groups + // Admin / super admin is not needed for a DM + pub fn new_dm_default(_creator_inbox_id: String, _dm_target_inbox_id: &str) -> Self { + let mut attributes = HashMap::new(); + // TODO: would it be helpful to incorporate the dm inbox ids in the name or description? + attributes.insert( + MetadataField::GroupName.to_string(), + DEFAULT_GROUP_NAME.to_string(), + ); + attributes.insert( + MetadataField::Description.to_string(), + DEFAULT_GROUP_DESCRIPTION.to_string(), + ); + attributes.insert( + MetadataField::GroupImageUrlSquare.to_string(), + DEFAULT_GROUP_IMAGE_URL_SQUARE.to_string(), + ); + attributes.insert( + MetadataField::GroupPinnedFrameUrl.to_string(), + DEFAULT_GROUP_PINNED_FRAME_URL.to_string(), + ); + let admin_list = vec![]; + let super_admin_list = vec![]; + Self { + attributes, + admin_list, + super_admin_list, + } + } + + /// Returns a vector of supported metadata fields. + /// + /// These fields will receive default permission policies for new groups. pub fn supported_fields() -> Vec { vec![ MetadataField::GroupName, @@ -123,10 +171,12 @@ impl GroupMutableMetadata { ] } + /// Checks if the given inbox ID is an admin. pub fn is_admin(&self, inbox_id: &String) -> bool { self.admin_list.contains(inbox_id) } + /// Checks if the given inbox ID is a super admin. pub fn is_super_admin(&self, inbox_id: &String) -> bool { self.super_admin_list.contains(inbox_id) } @@ -135,6 +185,7 @@ impl GroupMutableMetadata { impl TryFrom for Vec { type Error = GroupMutableMetadataError; + /// Converts GroupMutableMetadata to a byte vector for storage as an MLS Unknown Group Context Extension. fn try_from(value: GroupMutableMetadata) -> Result { let mut buf = Vec::new(); let proto_val = GroupMutableMetadataProto { @@ -155,6 +206,7 @@ impl TryFrom for Vec { impl TryFrom<&Vec> for GroupMutableMetadata { type Error = GroupMutableMetadataError; + /// Converts a byte vector to GroupMutableMetadata. fn try_from(value: &Vec) -> Result { let proto_val = GroupMutableMetadataProto::decode(value.as_slice())?; Self::try_from(proto_val) @@ -164,6 +216,7 @@ impl TryFrom<&Vec> for GroupMutableMetadata { impl TryFrom for GroupMutableMetadata { type Error = GroupMutableMetadataError; + /// Converts a GroupMutableMetadataProto to GroupMutableMetadata. fn try_from(value: GroupMutableMetadataProto) -> Result { let admin_list = value .admin_list @@ -186,6 +239,7 @@ impl TryFrom for GroupMutableMetadata { impl TryFrom<&Extensions> for GroupMutableMetadata { type Error = GroupMutableMetadataError; + /// Attempts to extract GroupMutableMetadata from MLS Extensions. fn try_from(value: &Extensions) -> Result { match find_mutable_metadata_extension(value) { Some(metadata) => GroupMutableMetadata::try_from(metadata), @@ -197,12 +251,17 @@ impl TryFrom<&Extensions> for GroupMutableMetadata { impl TryFrom<&OpenMlsGroup> for GroupMutableMetadata { type Error = GroupMutableMetadataError; + /// Attempts to extract GroupMutableMetadata from an OpenMlsGroup. fn try_from(value: &OpenMlsGroup) -> Result { let extensions = value.export_group_context().extensions(); extensions.try_into() } } +/// Finds the mutable metadata extension in the given MLS Extensions. +/// +/// This function searches for an Unknown Extension with the +/// [MUTABLE_METADATA_EXTENSION_ID](crate::configuration::MUTABLE_METADATA_EXTENSION_ID). pub fn find_mutable_metadata_extension(extensions: &Extensions) -> Option<&Vec> { extensions.iter().find_map(|extension| { if let Extension::Unknown(MUTABLE_METADATA_EXTENSION_ID, UnknownExtension(metadata)) = diff --git a/xmtp_mls/src/groups/group_permissions.rs b/xmtp_mls/src/groups/group_permissions.rs index 05d6f691c..cff50081d 100644 --- a/xmtp_mls/src/groups/group_permissions.rs +++ b/xmtp_mls/src/groups/group_permissions.rs @@ -32,6 +32,7 @@ use super::{ validated_commit::{CommitParticipant, Inbox, MetadataFieldChange, ValidatedCommit}, }; +/// Errors that can occur when working with GroupMutablePermissions. #[derive(Debug, Error)] pub enum GroupMutablePermissionsError { #[error("serialization: {0}")] @@ -50,22 +51,29 @@ pub enum GroupMutablePermissionsError { InvalidPermissionPolicyOption, } +/// Represents the mutable permissions for a group. +/// +/// This struct is stored as an MLS Unknown Group Context Extension. #[derive(Debug, Clone, PartialEq)] pub struct GroupMutablePermissions { + /// The set of policies that define the permissions for the group. pub policies: PolicySet, } impl GroupMutablePermissions { + /// Creates a new GroupMutablePermissions instance. pub fn new(policies: PolicySet) -> Self { Self { policies } } + /// Returns the preconfigured policy for the group permissions. pub fn preconfigured_policy( &self, ) -> Result { Ok(PreconfiguredPolicies::from_policy_set(&self.policies)?) } + /// Creates a GroupMutablePermissions instance from a proto representation. pub(crate) fn from_proto( proto: GroupMutablePermissionsProto, ) -> Result { @@ -77,6 +85,7 @@ impl GroupMutablePermissions { Ok(Self::new(PolicySet::from_proto(policies)?)) } + /// Converts the GroupMutablePermissions to its proto representation. pub(crate) fn to_proto( &self, ) -> Result { @@ -86,6 +95,7 @@ impl GroupMutablePermissions { } } +/// Implements conversion from GroupMutablePermissions to Vec. impl TryFrom for Vec { type Error = GroupMutablePermissionsError; @@ -98,6 +108,7 @@ impl TryFrom for Vec { } } +/// Implements conversion from &Vec to GroupMutablePermissions. impl TryFrom<&Vec> for GroupMutablePermissions { type Error = GroupMutablePermissionsError; @@ -107,6 +118,7 @@ impl TryFrom<&Vec> for GroupMutablePermissions { } } +/// Implements conversion from GroupMutablePermissionsProto to GroupMutablePermissions. impl TryFrom for GroupMutablePermissions { type Error = GroupMutablePermissionsError; @@ -115,6 +127,7 @@ impl TryFrom for GroupMutablePermissions { } } +/// Implements conversion from &Extensions to GroupMutablePermissions. impl TryFrom<&Extensions> for GroupMutablePermissions { type Error = GroupMutablePermissionsError; @@ -130,6 +143,7 @@ impl TryFrom<&Extensions> for GroupMutablePermissions { } } +/// Implements conversion from &OpenMlsGroup to GroupMutablePermissions. impl TryFrom<&OpenMlsGroup> for GroupMutablePermissions { type Error = GroupMutablePermissionsError; @@ -139,6 +153,7 @@ impl TryFrom<&OpenMlsGroup> for GroupMutablePermissions { } } +/// Extracts group permissions from an OpenMlsGroup. pub fn extract_group_permissions( group: &OpenMlsGroup, ) -> Result { @@ -146,14 +161,19 @@ pub fn extract_group_permissions( extensions.try_into() } -// A trait for policies that can update Metadata for the group +/// A trait for policies that can update Metadata for the group. pub trait MetadataPolicy: std::fmt::Debug { - // Verify relevant metadata is actually changed before evaluating against the MetadataPolicy - // See evaluate_metadata_policy + /// Evaluates the policy for a given actor and metadata change. + /// + /// Verify relevant metadata is actually changed before evaluating against the MetadataPolicy. + /// See evaluate_metadata_policy. fn evaluate(&self, actor: &CommitParticipant, change: &MetadataFieldChange) -> bool; + + /// Converts the policy to its proto representation. fn to_proto(&self) -> Result; } +/// Represents the base policies for metadata updates. #[derive(Clone, Copy, Debug, PartialEq)] pub enum MetadataBasePolicies { Allow, @@ -162,6 +182,7 @@ pub enum MetadataBasePolicies { AllowIfActorSuperAdmin, } +/// Implements the MetadataPolicy trait for MetadataBasePolicies. impl MetadataPolicy for &MetadataBasePolicies { fn evaluate(&self, actor: &CommitParticipant, _change: &MetadataFieldChange) -> bool { match self { @@ -192,6 +213,7 @@ impl MetadataPolicy for &MetadataBasePolicies { } } +/// Represents the different types of metadata policies. #[derive(Debug, Clone, PartialEq)] #[allow(dead_code)] pub enum MetadataPolicies { @@ -201,6 +223,7 @@ pub enum MetadataPolicies { } impl MetadataPolicies { + /// Creates a default map of metadata policies. pub fn default_map(policies: MetadataPolicies) -> HashMap { let mut map: HashMap = HashMap::new(); for field in GroupMutableMetadata::supported_fields() { @@ -209,31 +232,47 @@ impl MetadataPolicies { map } + // by default members of DM groups can update all metadata + pub fn dm_map() -> HashMap { + let mut map: HashMap = HashMap::new(); + for field in GroupMutableMetadata::supported_fields() { + map.insert(field.to_string(), MetadataPolicies::allow()); + } + map + } + + /// Creates an "Allow" metadata policy. pub fn allow() -> Self { MetadataPolicies::Standard(MetadataBasePolicies::Allow) } + /// Creates a "Deny" metadata policy. pub fn deny() -> Self { MetadataPolicies::Standard(MetadataBasePolicies::Deny) } + /// Creates an "Allow if actor is admin" metadata policy. pub fn allow_if_actor_admin() -> Self { MetadataPolicies::Standard(MetadataBasePolicies::AllowIfActorAdminOrSuperAdmin) } + /// Creates an "Allow if actor is super admin" metadata policy. pub fn allow_if_actor_super_admin() -> Self { MetadataPolicies::Standard(MetadataBasePolicies::AllowIfActorSuperAdmin) } + /// Creates an "And" condition metadata policy. pub fn and(policies: Vec) -> Self { MetadataPolicies::AndCondition(MetadataAndCondition::new(policies)) } + /// Creates an "Any" condition metadata policy. pub fn any(policies: Vec) -> Self { MetadataPolicies::AnyCondition(MetadataAnyCondition::new(policies)) } } +/// Implements conversion from MetadataPolicyProto to MetadataPolicies. impl TryFrom for MetadataPolicies { type Error = PolicyError; @@ -276,6 +315,7 @@ impl TryFrom for MetadataPolicies { } } +/// Implements the MetadataPolicy trait for MetadataPolicies. impl MetadataPolicy for MetadataPolicies { fn evaluate(&self, actor: &CommitParticipant, change: &MetadataFieldChange) -> bool { match self { @@ -294,7 +334,7 @@ impl MetadataPolicy for MetadataPolicies { } } -// An AndCondition evaluates to true if all the policies it contains evaluate to true +/// An AndCondition evaluates to true if all the policies it contains evaluate to true. #[derive(Clone, Debug, PartialEq)] pub struct MetadataAndCondition { policies: Vec, @@ -306,6 +346,7 @@ impl MetadataAndCondition { } } +/// Implements the MetadataPolicy trait for MetadataAndCondition. impl MetadataPolicy for MetadataAndCondition { fn evaluate(&self, actor: &CommitParticipant, change: &MetadataFieldChange) -> bool { self.policies @@ -328,7 +369,7 @@ impl MetadataPolicy for MetadataAndCondition { } } -// An AnyCondition evaluates to true if any of the contained policies evaluate to true +/// An AnyCondition evaluates to true if any of the contained policies evaluate to true. #[derive(Clone, Debug, PartialEq)] pub struct MetadataAnyCondition { policies: Vec, @@ -341,6 +382,7 @@ impl MetadataAnyCondition { } } +/// Implements the MetadataPolicy trait for MetadataAnyCondition. impl MetadataPolicy for MetadataAnyCondition { fn evaluate(&self, actor: &CommitParticipant, change: &MetadataFieldChange) -> bool { self.policies @@ -363,14 +405,16 @@ impl MetadataPolicy for MetadataAnyCondition { } } -// A trait for policies that can update Permissions for the group +/// A trait for policies that can update Permissions for the group. pub trait PermissionsPolicy: std::fmt::Debug { - // Verify relevant metadata is actually changed before evaluating against the MetadataPolicy - // See evaluate_metadata_policy + /// Evaluates the policy for a given actor. fn evaluate(&self, actor: &CommitParticipant) -> bool; + + /// Converts the policy to its proto representation. fn to_proto(&self) -> Result; } +/// Represents the base policies for permissions updates. #[derive(Clone, Copy, Debug, PartialEq)] pub enum PermissionsBasePolicies { Deny, @@ -378,6 +422,7 @@ pub enum PermissionsBasePolicies { AllowIfActorSuperAdmin, } +/// Implements the PermissionsPolicy trait for PermissionsBasePolicies. impl PermissionsPolicy for &PermissionsBasePolicies { fn evaluate(&self, actor: &CommitParticipant) -> bool { match self { @@ -406,6 +451,7 @@ impl PermissionsPolicy for &PermissionsBasePolicies { } } +/// Represents the different types of permissions policies. #[derive(Debug, Clone, PartialEq)] #[allow(dead_code)] pub enum PermissionsPolicies { @@ -415,29 +461,33 @@ pub enum PermissionsPolicies { } impl PermissionsPolicies { + /// Creates a "Deny" permissions policy. pub fn deny() -> Self { PermissionsPolicies::Standard(PermissionsBasePolicies::Deny) } - #[allow(dead_code)] + /// Creates an "Allow if actor is admin" permissions policy. pub fn allow_if_actor_admin() -> Self { PermissionsPolicies::Standard(PermissionsBasePolicies::AllowIfActorAdminOrSuperAdmin) } - #[allow(dead_code)] + /// Creates an "Allow if actor is super admin" permissions policy. pub fn allow_if_actor_super_admin() -> Self { PermissionsPolicies::Standard(PermissionsBasePolicies::AllowIfActorSuperAdmin) } + /// Creates an "And" condition permissions policy. pub fn and(policies: Vec) -> Self { PermissionsPolicies::AndCondition(PermissionsAndCondition::new(policies)) } + /// Creates an "Any" condition permissions policy. pub fn any(policies: Vec) -> Self { PermissionsPolicies::AnyCondition(PermissionsAnyCondition::new(policies)) } } +/// Implements conversion from PermissionsPolicyProto to PermissionsPolicies. impl TryFrom for PermissionsPolicies { type Error = PolicyError; @@ -479,6 +529,7 @@ impl TryFrom for PermissionsPolicies { } } +/// Implements the PermissionsPolicy trait for PermissionsPolicies. impl PermissionsPolicy for PermissionsPolicies { fn evaluate(&self, actor: &CommitParticipant) -> bool { match self { @@ -497,7 +548,7 @@ impl PermissionsPolicy for PermissionsPolicies { } } -// An AndCondition evaluates to true if all the policies it contains evaluate to true +/// An AndCondition evaluates to true if all the policies it contains evaluate to true. #[derive(Clone, Debug, PartialEq)] pub struct PermissionsAndCondition { policies: Vec, @@ -509,6 +560,7 @@ impl PermissionsAndCondition { } } +/// Implements the PermissionsPolicy trait for PermissionsAndCondition. impl PermissionsPolicy for PermissionsAndCondition { fn evaluate(&self, actor: &CommitParticipant) -> bool { self.policies.iter().all(|policy| policy.evaluate(actor)) @@ -529,7 +581,7 @@ impl PermissionsPolicy for PermissionsAndCondition { } } -// An AnyCondition evaluates to true if any of the contained policies evaluate to true +/// An AnyCondition evaluates to true if any of the contained policies evaluate to true. #[derive(Clone, Debug, PartialEq)] pub struct PermissionsAnyCondition { policies: Vec, @@ -542,6 +594,7 @@ impl PermissionsAnyCondition { } } +/// Implements the PermissionsPolicy trait for PermissionsAnyCondition. impl PermissionsPolicy for PermissionsAnyCondition { fn evaluate(&self, actor: &CommitParticipant) -> bool { self.policies.iter().any(|policy| policy.evaluate(actor)) @@ -562,12 +615,16 @@ impl PermissionsPolicy for PermissionsAnyCondition { } } -// A trait for policies that can add/remove members and installations for the group +/// A trait for policies that can add/remove members and installations for the group. pub trait MembershipPolicy: std::fmt::Debug { + /// Evaluates the policy for a given actor and inbox change. fn evaluate(&self, actor: &CommitParticipant, change: &Inbox) -> bool; + + /// Converts the policy to its proto representation. fn to_proto(&self) -> Result; } +/// Errors that can occur when working with policies. #[derive(Debug, Error)] pub enum PolicyError { #[error("serialization {0}")] @@ -598,7 +655,8 @@ pub enum PolicyError { FromProtoUpdatePermissionsInvalidPolicy, } -#[derive(Clone, Copy, Debug, PartialEq)] +/// Represents the base policies for membership updates. +#[derive(Debug, Clone, Copy, PartialEq)] #[allow(dead_code)] #[repr(u8)] pub enum BasePolicies { @@ -610,6 +668,7 @@ pub enum BasePolicies { AllowIfSuperAdmin, } +/// Implements the MembershipPolicy trait for BasePolicies. impl MembershipPolicy for BasePolicies { fn evaluate(&self, actor: &CommitParticipant, inbox: &Inbox) -> bool { match self { @@ -638,6 +697,7 @@ impl MembershipPolicy for BasePolicies { } } +/// Represents the different types of membership policies. #[derive(Debug, Clone, PartialEq)] #[allow(dead_code)] pub enum MembershipPolicies { @@ -647,38 +707,40 @@ pub enum MembershipPolicies { } impl MembershipPolicies { + /// Creates an "Allow" membership policy. pub fn allow() -> Self { MembershipPolicies::Standard(BasePolicies::Allow) } + /// Creates a "Deny" membership policy. pub fn deny() -> Self { MembershipPolicies::Standard(BasePolicies::Deny) } - #[allow(dead_code)] - pub fn allow_same_member() -> Self { - MembershipPolicies::Standard(BasePolicies::AllowSameMember) - } - + /// Creates an "Allow if actor is admin" membership policy. #[allow(dead_code)] pub fn allow_if_actor_admin() -> Self { MembershipPolicies::Standard(BasePolicies::AllowIfAdminOrSuperAdmin) } + /// Creates an "Allow if actor is super admin" membership policy. #[allow(dead_code)] pub fn allow_if_actor_super_admin() -> Self { MembershipPolicies::Standard(BasePolicies::AllowIfSuperAdmin) } + /// Creates an "And" condition membership policy. pub fn and(policies: Vec) -> Self { MembershipPolicies::AndCondition(AndCondition::new(policies)) } + /// Creates an "Any" condition membership policy. pub fn any(policies: Vec) -> Self { MembershipPolicies::AnyCondition(AnyCondition::new(policies)) } } +/// Implements conversion from MembershipPolicyProto to MembershipPolicies. impl TryFrom for MembershipPolicies { type Error = PolicyError; @@ -721,6 +783,7 @@ impl TryFrom for MembershipPolicies { } } +/// Implements the MembershipPolicy trait for MembershipPolicies. impl MembershipPolicy for MembershipPolicies { fn evaluate(&self, actor: &CommitParticipant, inbox: &Inbox) -> bool { match self { @@ -739,7 +802,7 @@ impl MembershipPolicy for MembershipPolicies { } } -// An AndCondition evaluates to true if all the policies it contains evaluate to true +/// An AndCondition evaluates to true if all the policies it contains evaluate to true. #[derive(Clone, Debug, PartialEq)] pub struct AndCondition { policies: Vec, @@ -751,6 +814,7 @@ impl AndCondition { } } +/// Implements the MembershipPolicy trait for AndCondition. impl MembershipPolicy for AndCondition { fn evaluate(&self, actor: &CommitParticipant, inbox: &Inbox) -> bool { self.policies @@ -771,7 +835,7 @@ impl MembershipPolicy for AndCondition { } } -// An AnyCondition evaluates to true if any of the contained policies evaluate to true +/// An AnyCondition evaluates to true if any of the contained policies evaluate to true. #[derive(Clone, Debug, PartialEq)] pub struct AnyCondition { policies: Vec, @@ -784,6 +848,7 @@ impl AnyCondition { } } +/// Implements the MembershipPolicy trait for AnyCondition. impl MembershipPolicy for AnyCondition { fn evaluate(&self, actor: &CommitParticipant, inbox: &Inbox) -> bool { self.policies @@ -804,18 +869,26 @@ impl MembershipPolicy for AnyCondition { } } +/// Represents a set of policies for a group. #[derive(Debug, Clone, PartialEq)] #[allow(dead_code)] pub struct PolicySet { + /// The policy for adding members to the group. pub add_member_policy: MembershipPolicies, + /// The policy for removing members from the group. pub remove_member_policy: MembershipPolicies, + /// The policies for updating metadata fields. pub update_metadata_policy: HashMap, + /// The policy for adding admins to the group. pub add_admin_policy: PermissionsPolicies, + /// The policy for removing admins from the group. pub remove_admin_policy: PermissionsPolicies, + /// The policy for updating permissions. pub update_permissions_policy: PermissionsPolicies, } impl PolicySet { + /// Creates a new PolicySet instance. pub fn new( add_member_policy: MembershipPolicies, remove_member_policy: MembershipPolicies, @@ -834,14 +907,41 @@ impl PolicySet { } } + pub fn new_dm() -> Self { + Self { + add_member_policy: MembershipPolicies::deny(), + remove_member_policy: MembershipPolicies::deny(), + update_metadata_policy: MetadataPolicies::dm_map(), + add_admin_policy: PermissionsPolicies::deny(), + remove_admin_policy: PermissionsPolicies::deny(), + update_permissions_policy: PermissionsPolicies::deny(), + } + } + + /// The [evaluate_commit] function is the core function for client side verification + /// that [ValidatedCommit](crate::groups::validated_commit::ValidatedCommit) + /// adheres to the XMTP permission policies set in the PolicySet. pub fn evaluate_commit(&self, commit: &ValidatedCommit) -> bool { // Verify add member policy was not violated - let added_inboxes_valid = self.evaluate_policy( + let mut added_inboxes_valid = self.evaluate_policy( commit.added_inboxes.iter(), &self.add_member_policy, &commit.actor, ); + // We can always add DM member's inboxId to a DM + if let Some(dm_members) = &commit.dm_members { + if commit.added_inboxes.len() == 1 { + let added_inbox_id = &commit.added_inboxes[0].inbox_id; + if (added_inbox_id == &dm_members.member_one_inbox_id + || added_inbox_id == &dm_members.member_two_inbox_id) + && added_inbox_id != &commit.actor_inbox_id() + { + added_inboxes_valid = true; + } + } + } + // Verify remove member policy was not violated // Super admin can not be removed from a group let removed_inboxes_valid = self.evaluate_policy( @@ -890,6 +990,7 @@ impl PolicySet { && permissions_changes_valid } + /// Evaluates a policy for a given set of changes. fn evaluate_policy<'a, I, P>( &self, mut changes: I, @@ -903,7 +1004,7 @@ impl PolicySet { changes.all(|change| { let is_ok = policy.evaluate(actor, change); if !is_ok { - log::info!( + tracing::info!( "Policy {:?} failed for actor {:?} and change {:?}", policy, actor, @@ -914,6 +1015,7 @@ impl PolicySet { }) } + /// Evaluates metadata policies for a given set of changes. fn evaluate_metadata_policy<'a, I>( &self, mut changes: I, @@ -926,7 +1028,7 @@ impl PolicySet { changes.all(|change| { if let Some(policy) = policies.get(&change.field_name) { if !policy.evaluate(actor, change) { - log::info!( + tracing::info!( "Policy for field {} failed for actor {:?} and change {:?}", change.field_name, actor, @@ -946,7 +1048,7 @@ impl PolicySet { MetadataPolicies::allow_if_actor_admin() }; if !policy_for_unrecognized_field.evaluate(actor, change) { - log::info!( + tracing::info!( "Metadata field update with unknown policy was denied: {}", change.field_name ); @@ -956,6 +1058,7 @@ impl PolicySet { }) } + /// Converts the PolicySet to its proto representation. pub(crate) fn to_proto(&self) -> Result { let add_member_policy = Some(self.add_member_policy.to_proto()?); let remove_member_policy = Some(self.remove_member_policy.to_proto()?); @@ -978,6 +1081,7 @@ impl PolicySet { }) } + /// Creates a PolicySet from its proto representation. pub(crate) fn from_proto(proto: PolicySetProto) -> Result { let add_member_policy = MembershipPolicies::try_from( proto @@ -1020,6 +1124,7 @@ impl PolicySet { )) } + /// Converts the PolicySet to a Vec. pub fn to_bytes(&self) -> Result, PolicyError> { let proto = self.to_proto()?; let mut buf = Vec::new(); @@ -1027,16 +1132,19 @@ impl PolicySet { Ok(buf) } + /// Creates a PolicySet from a Vec. pub fn from_bytes(bytes: &[u8]) -> Result { let proto = PolicySetProto::decode(bytes)?; Self::from_proto(proto) } } -// Depending on if the client is on a newer or older version of libxmtp -// since the group was created, the number of metadata policies might not match -// the default All Members Policy Set. As long as all metadata policies are allow, we will -// match against All Members Preconfigured Policy +/// Checks if a PolicySet is equivalent to the "All Members" preconfigured policy. +/// +/// Depending on if the client is on a newer or older version of libxmtp +/// since the group was created, the number of metadata policies might not match +/// the default All Members Policy Set. As long as all metadata policies are allow, we will +/// match against All Members Preconfigured Policy pub fn is_policy_all_members(policy: &PolicySet) -> Result { let mut metadata_policies_equal = true; for field_name in policy.update_metadata_policy.keys() { @@ -1056,10 +1164,12 @@ pub fn is_policy_all_members(policy: &PolicySet) -> Result { && policy.update_permissions_policy == PermissionsPolicies::allow_if_actor_super_admin()) } -// Depending on if the client is on a newer or older version of libxmtp -// since the group was created, the number of metadata policies might not match -// the default Admin Only Policy Set. As long as all metadata policies are admin only, we will -// match against Admin Only Preconfigured Policy +/// Checks if a PolicySet is equivalent to the "Admin Only" preconfigured policy. +/// +/// Depending on if the client is on a newer or older version of libxmtp +/// since the group was created, the number of metadata policies might not match +/// the default Admin Only Policy Set. As long as all metadata policies are admin only, we will +/// match against Admin Only Preconfigured Policy pub fn is_policy_admin_only(policy: &PolicySet) -> Result { let mut metadata_policies_equal = true; for field_name in policy.update_metadata_policy.keys() { @@ -1079,6 +1189,8 @@ pub fn is_policy_admin_only(policy: &PolicySet) -> Result { && policy.update_permissions_policy == PermissionsPolicies::allow_if_actor_super_admin()) } +/// Returns the "All Members" preconfigured policy. +/// /// A policy where any member can add or remove any other member pub(crate) fn policy_all_members() -> PolicySet { let mut metadata_policies_map: HashMap = HashMap::new(); @@ -1095,6 +1207,8 @@ pub(crate) fn policy_all_members() -> PolicySet { ) } +/// Returns the "Admin Only" preconfigured policy. +/// /// A policy where only the admins can add or remove members pub(crate) fn policy_admin_only() -> PolicySet { let mut metadata_policies_map: HashMap = HashMap::new(); @@ -1110,20 +1224,26 @@ pub(crate) fn policy_admin_only() -> PolicySet { PermissionsPolicies::allow_if_actor_super_admin(), ) } + +/// Implements the Default trait for PolicySet. impl Default for PolicySet { fn default() -> Self { PreconfiguredPolicies::default().to_policy_set() } } +/// Represents preconfigured policies for a group. #[derive(Debug, Clone, PartialEq, Default)] pub enum PreconfiguredPolicies { + /// The "All Members" preconfigured policy. #[default] AllMembers, + /// The "Admin Only" preconfigured policy. AdminsOnly, } impl PreconfiguredPolicies { + /// Converts the PreconfiguredPolicies to a PolicySet. pub fn to_policy_set(&self) -> PolicySet { match self { PreconfiguredPolicies::AllMembers => policy_all_members(), @@ -1131,6 +1251,7 @@ impl PreconfiguredPolicies { } } + /// Creates a PreconfiguredPolicies from a PolicySet. pub fn from_policy_set(policy_set: &PolicySet) -> Result { if is_policy_all_members(policy_set)? { Ok(PreconfiguredPolicies::AllMembers) @@ -1142,6 +1263,7 @@ impl PreconfiguredPolicies { } } +/// Implements the Display trait for PreconfiguredPolicies. impl std::fmt::Display for PreconfiguredPolicies { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{:?}", self) @@ -1151,7 +1273,10 @@ impl std::fmt::Display for PreconfiguredPolicies { #[cfg(test)] mod tests { use crate::{ - groups::{group_mutable_metadata::MetadataField, validated_commit::MutableMetadataChanges}, + groups::{ + group_metadata::DmMembers, group_mutable_metadata::MetadataField, + validated_commit::MutableMetadataChanges, + }, utils::test::{rand_string, rand_vec}, }; @@ -1166,6 +1291,7 @@ mod tests { } } + /// Test helper function for building a CommitParticipant. fn build_actor( inbox_id: Option, installation_id: Option>, @@ -1181,26 +1307,35 @@ mod tests { } } + enum MemberType { + SameAsActor, + DmTarget, + Random, + } + + /// Test helper function for building a ValidatedCommit. fn build_validated_commit( // Add a member with the same account address as the actor if true, random account address if false - member_added: Option, - member_removed: Option, + member_added: Option, + member_removed: Option, metadata_fields_changed: Option>, permissions_changed: bool, actor_is_admin: bool, actor_is_super_admin: bool, + dm_target_inbox_id: Option, ) -> ValidatedCommit { let actor = build_actor(None, None, actor_is_admin, actor_is_super_admin); - let build_membership_change = |same_address_as_actor| { - if same_address_as_actor { - vec![build_change( - Some(actor.inbox_id.clone()), - actor_is_admin, - actor_is_super_admin, - )] - } else { - vec![build_change(None, false, false)] + let dm_target_inbox_id_clone = dm_target_inbox_id.clone(); + let build_membership_change = |member_type: MemberType| match member_type { + MemberType::SameAsActor => vec![build_change( + Some(actor.inbox_id.clone()), + actor_is_admin, + actor_is_super_admin, + )], + MemberType::DmTarget => { + vec![build_change(dm_target_inbox_id_clone.clone(), false, false)] } + MemberType::Random => vec![build_change(None, false, false)], }; let field_changes = metadata_fields_changed @@ -1209,6 +1344,15 @@ mod tests { .map(|field| MetadataFieldChange::new(field, Some(rand_string()), Some(rand_string()))) .collect(); + let dm_members = if let Some(dm_target_inbox_id) = dm_target_inbox_id { + Some(DmMembers { + member_one_inbox_id: actor.inbox_id.clone(), + member_two_inbox_id: dm_target_inbox_id, + }) + } else { + None + }; + ValidatedCommit { actor: actor.clone(), added_inboxes: member_added @@ -1222,9 +1366,12 @@ mod tests { ..Default::default() }, permissions_changed, + dm_members, } } + /// Tests that a commit by a non admin/super admin can add and remove members + /// with allow policies. #[test] fn test_allow_all() { let permissions = PolicySet::new( @@ -1236,10 +1383,19 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let commit = build_validated_commit(Some(true), Some(true), None, false, false, false); + let commit = build_validated_commit( + Some(MemberType::SameAsActor), + Some(MemberType::SameAsActor), + None, + false, + false, + false, + None, + ); assert!(permissions.evaluate_commit(&commit)); } + /// Tests that a commit by a non admin/super admin is denied for add and remove member policies. #[test] fn test_deny() { let permissions = PolicySet::new( @@ -1251,15 +1407,30 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let member_added_commit = - build_validated_commit(Some(false), None, None, false, false, false); + let member_added_commit = build_validated_commit( + Some(MemberType::Random), + None, + None, + false, + false, + false, + None, + ); assert!(!permissions.evaluate_commit(&member_added_commit)); - let member_removed_commit = - build_validated_commit(None, Some(false), None, false, false, false); + let member_removed_commit = build_validated_commit( + None, + Some(MemberType::Random), + None, + false, + false, + false, + None, + ); assert!(!permissions.evaluate_commit(&member_removed_commit)); } + /// Tests that a group creator can perform super admin actions. #[test] fn test_actor_is_creator() { let permissions = PolicySet::new( @@ -1272,39 +1443,41 @@ mod tests { ); // Can not remove the creator if they are the only super admin - let commit_with_creator = - build_validated_commit(Some(true), Some(true), None, false, false, true); + let commit_with_creator = build_validated_commit( + Some(MemberType::SameAsActor), + Some(MemberType::SameAsActor), + None, + false, + false, + true, + None, + ); assert!(!permissions.evaluate_commit(&commit_with_creator)); - let commit_with_creator = - build_validated_commit(Some(true), Some(false), None, false, false, true); + let commit_with_creator = build_validated_commit( + Some(MemberType::SameAsActor), + Some(MemberType::Random), + None, + false, + false, + true, + None, + ); assert!(permissions.evaluate_commit(&commit_with_creator)); - let commit_without_creator = - build_validated_commit(Some(true), Some(true), None, false, false, false); - assert!(!permissions.evaluate_commit(&commit_without_creator)); - } - - #[test] - fn test_allow_same_member() { - let permissions = PolicySet::new( - MembershipPolicies::allow_same_member(), - MembershipPolicies::deny(), - MetadataPolicies::default_map(MetadataPolicies::deny()), - PermissionsPolicies::allow_if_actor_super_admin(), - PermissionsPolicies::allow_if_actor_super_admin(), - PermissionsPolicies::allow_if_actor_super_admin(), + let commit_without_creator = build_validated_commit( + Some(MemberType::SameAsActor), + Some(MemberType::SameAsActor), + None, + false, + false, + false, + None, ); - - let commit_with_same_member = - build_validated_commit(Some(true), None, None, false, false, false); - assert!(permissions.evaluate_commit(&commit_with_same_member)); - - let commit_with_different_member = - build_validated_commit(Some(false), None, None, false, false, false); - assert!(!permissions.evaluate_commit(&commit_with_different_member)); + assert!(!permissions.evaluate_commit(&commit_without_creator)); } + /// Tests that and conditions are enforced as expected. #[test] fn test_and_condition() { let permissions = PolicySet::new( @@ -1319,11 +1492,19 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let member_added_commit = - build_validated_commit(Some(true), None, None, false, false, false); + let member_added_commit = build_validated_commit( + Some(MemberType::SameAsActor), + None, + None, + false, + false, + false, + None, + ); assert!(!permissions.evaluate_commit(&member_added_commit)); } + /// Tests that any conditions are enforced as expected. #[test] fn test_any_condition() { let permissions = PolicySet::new( @@ -1338,11 +1519,19 @@ mod tests { PermissionsPolicies::allow_if_actor_super_admin(), ); - let member_added_commit = - build_validated_commit(Some(true), None, None, false, false, false); + let member_added_commit = build_validated_commit( + Some(MemberType::SameAsActor), + None, + None, + false, + false, + false, + None, + ); assert!(permissions.evaluate_commit(&member_added_commit)); } + /// Tests that the PolicySet can be serialized and deserialized. #[test] fn test_serialize() { let permissions = PolicySet::new( @@ -1370,6 +1559,7 @@ mod tests { assert!(permissions.eq(&restored)) } + /// Tests that the PolicySet can enforce update group name policy. #[test] fn test_update_group_name() { let allow_permissions = PolicySet::new( @@ -1382,12 +1572,13 @@ mod tests { ); let member_added_commit = build_validated_commit( - Some(true), + Some(MemberType::SameAsActor), None, Some(vec![MetadataField::GroupName.to_string()]), false, false, false, + None, ); assert!(allow_permissions.evaluate_commit(&member_added_commit)); @@ -1404,21 +1595,7 @@ mod tests { assert!(!deny_permissions.evaluate_commit(&member_added_commit)); } - #[test] - fn test_disallow_serialize_allow_same_member() { - let permissions = PolicySet::new( - MembershipPolicies::allow_same_member(), - MembershipPolicies::deny(), - MetadataPolicies::default_map(MetadataPolicies::deny()), - PermissionsPolicies::allow_if_actor_super_admin(), - PermissionsPolicies::allow_if_actor_super_admin(), - PermissionsPolicies::allow_if_actor_super_admin(), - ); - - let proto_result = permissions.to_proto(); - assert!(proto_result.is_err()); - } - + /// Tests that the preconfigured policy functions work as expected #[test] fn test_preconfigured_policy() { let group_permissions = GroupMutablePermissions::new(policy_all_members()); @@ -1439,6 +1616,7 @@ mod tests { ); } + /// Tests that the preconfigured policy functions work as expected with new metadata fields. #[test] fn test_preconfigured_policy_equality_new_metadata() { let mut metadata_policies_map = MetadataPolicies::default_map(MetadataPolicies::allow()); @@ -1472,6 +1650,7 @@ mod tests { assert!(is_policy_admin_only(&policy_set_new_metadata_permission).unwrap()); } + /// Tests that the permission update policy is enforced as expected. #[test] fn test_permission_update() { let permissions = PolicySet::new( @@ -1484,14 +1663,15 @@ mod tests { ); // Commit should fail because actor is not superadmin - let commit = build_validated_commit(None, None, None, true, false, false); + let commit = build_validated_commit(None, None, None, true, false, false, None); assert!(!permissions.evaluate_commit(&commit)); // Commit should pass because actor is superadmin - let commit = build_validated_commit(None, None, None, true, false, true); + let commit = build_validated_commit(None, None, None, true, false, true, None); assert!(permissions.evaluate_commit(&commit)); } + /// Tests that the PolicySet can evaluate field updates with unknown policies. #[test] fn test_evaluate_field_with_unknown_policy() { // Create a group whose default metadata can be updated by any member @@ -1512,6 +1692,7 @@ mod tests { false, false, false, + None, ); assert!(permissions.evaluate_commit(&name_updated_commit)); @@ -1523,6 +1704,7 @@ mod tests { false, false, false, + None, ); assert!(!permissions.evaluate_commit(&non_existing_field_updated_commit)); @@ -1534,6 +1716,7 @@ mod tests { false, true, false, + None, ); assert!(permissions.evaluate_commit(&non_existing_field_updated_commit)); @@ -1547,6 +1730,7 @@ mod tests { false, true, false, + None, ); assert!(!permissions.evaluate_commit(&non_existing_field_updated_commit)); @@ -1560,7 +1744,97 @@ mod tests { false, false, true, + None, ); assert!(permissions.evaluate_commit(&non_existing_field_updated_commit)); } + + #[test] + fn test_dm_group_permissions() { + // Simulate a group with DM Permissions + let permissions = PolicySet::new_dm(); + + // String below represents the inbox id of the DM target + const TARGET_INBOX_ID: &str = "example_target_dm_id"; + + // DM group can not add a random inbox + let commit = build_validated_commit( + Some(MemberType::Random), + None, + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + + // DM group can not add themselves + let commit = build_validated_commit( + Some(MemberType::SameAsActor), + None, + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + + // DM group can add the target inbox + let commit = build_validated_commit( + Some(MemberType::DmTarget), + None, + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(permissions.evaluate_commit(&commit)); + + // DM group can not remove + let commit = build_validated_commit( + None, + Some(MemberType::Random), + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + let commit = build_validated_commit( + None, + Some(MemberType::DmTarget), + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + let commit = build_validated_commit( + None, + Some(MemberType::SameAsActor), + None, + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(!permissions.evaluate_commit(&commit)); + + // DM group can update metadata + let commit = build_validated_commit( + None, + None, + Some(vec![MetadataField::GroupName.to_string()]), + false, + false, + false, + Some(TARGET_INBOX_ID.to_string()), + ); + assert!(permissions.evaluate_commit(&commit)); + } } diff --git a/xmtp_mls/src/groups/intents.rs b/xmtp_mls/src/groups/intents.rs index 588c832d9..f5394fa74 100644 --- a/xmtp_mls/src/groups/intents.rs +++ b/xmtp_mls/src/groups/intents.rs @@ -241,7 +241,7 @@ impl UpdateGroupMembershipIntentData { } pub fn apply_to_group_membership(&self, group_membership: &GroupMembership) -> GroupMembership { - log::info!("old group membership: {:?}", group_membership.members); + tracing::info!("old group membership: {:?}", group_membership.members); let mut new_membership = group_membership.clone(); for (inbox_id, sequence_id) in self.membership_updates.iter() { new_membership.add(inbox_id.clone(), *sequence_id); @@ -250,7 +250,7 @@ impl UpdateGroupMembershipIntentData { for inbox_id in self.removed_members.iter() { new_membership.remove(inbox_id) } - log::info!("updated group membership: {:?}", new_membership.members); + tracing::info!("updated group membership: {:?}", new_membership.members); new_membership } } @@ -466,7 +466,7 @@ impl From for PermissionsPolicies { fn from(value: PermissionPolicyOption) -> Self { match value { PermissionPolicyOption::Allow => { - log::error!("PermissionPolicyOption::Allow is not allowed for PermissionsPolicies, set to super_admin only instead"); + tracing::error!("PermissionPolicyOption::Allow is not allowed for PermissionsPolicies, set to super_admin only instead"); PermissionsPolicies::allow_if_actor_super_admin() } PermissionPolicyOption::Deny => PermissionsPolicies::deny(), diff --git a/xmtp_mls/src/groups/members.rs b/xmtp_mls/src/groups/members.rs index 0cdedf843..91ee8d90d 100644 --- a/xmtp_mls/src/groups/members.rs +++ b/xmtp_mls/src/groups/members.rs @@ -3,7 +3,12 @@ use xmtp_id::InboxId; use super::{validated_commit::extract_group_membership, GroupError, MlsGroup}; use crate::{ - storage::association_state::StoredAssociationState, xmtp_openmls_provider::XmtpOpenMlsProvider, + storage::{ + association_state::StoredAssociationState, + consent_record::{ConsentState, ConsentType}, + }, + xmtp_openmls_provider::XmtpOpenMlsProvider, + Client, XmtpApi, }; #[derive(Debug, Clone)] @@ -12,6 +17,7 @@ pub struct GroupMember { pub account_addresses: Vec, pub installation_ids: Vec>, pub permission_level: PermissionLevel, + pub consent_state: ConsentState, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -23,13 +29,17 @@ pub enum PermissionLevel { impl MlsGroup { // Load the member list for the group from the DB, merging together multiple installations into a single entry - pub fn members(&self) -> Result, GroupError> { + pub async fn members( + &self, + client: &Client, + ) -> Result, GroupError> { let provider = self.mls_provider()?; - self.members_with_provider(&provider) + self.members_with_provider(client, &provider).await } - pub fn members_with_provider( + pub async fn members_with_provider( &self, + client: &Client, provider: &XmtpOpenMlsProvider, ) -> Result, GroupError> { let openmls_group = self.load_mls_group(provider)?; @@ -43,19 +53,41 @@ impl MlsGroup { .collect::>(); let conn = provider.conn_ref(); - let association_states = + let mut association_states = StoredAssociationState::batch_read_from_cache(conn, requests.clone())?; let mutable_metadata = self.mutable_metadata(provider)?; if association_states.len() != requests.len() { - // Cache miss - not expected to happen because: - // 1. We don't allow updates to the group metadata unless we have already validated the association state - // 2. When validating the association state, we must have written it to the cache - log::error!( - "Failed to load all members for group - metadata: {:?}, computed members: {:?}", - requests, - association_states - ); - return Err(GroupError::InvalidGroupMembership); + // Attempt to rebuild the cache. + let missing_requests: Vec<_> = requests + .iter() + .filter_map(|(id, sequence)| { + // Filter out association states we already have to avoid unnecessary requests. + if association_states + .iter() + .any(|state| state.inbox_id() == id) + { + return None; + } + Some((id.clone(), Some(*sequence))) + }) + .collect(); + + let mut new_states = client + .batch_get_association_state(conn, &missing_requests) + .await?; + association_states.append(&mut new_states); + + if association_states.len() != requests.len() { + // Cache miss - not expected to happen because: + // 1. We don't allow updates to the group metadata unless we have already validated the association state + // 2. When validating the association state, we must have written it to the cache + tracing::error!( + "Failed to load all members for group - metadata: {:?}, computed members: {:?}", + requests, + association_states + ); + return Err(GroupError::InvalidGroupMembership); + } } let members = association_states .into_iter() @@ -71,11 +103,15 @@ impl MlsGroup { PermissionLevel::Member }; + let consent = + conn.get_consent_record(inbox_id_str.clone(), ConsentType::InboxId)?; + Ok(GroupMember { - inbox_id: inbox_id_str, + inbox_id: inbox_id_str.clone(), account_addresses: association_state.account_addresses(), installation_ids: association_state.installation_ids(), permission_level, + consent_state: consent.map_or(ConsentState::Unknown, |c| c.state), }) }) .collect::, GroupError>>()?; diff --git a/xmtp_mls/src/groups/message_history.rs b/xmtp_mls/src/groups/message_history.rs index 0f0768397..ed9896c10 100644 --- a/xmtp_mls/src/groups/message_history.rs +++ b/xmtp_mls/src/groups/message_history.rs @@ -135,7 +135,7 @@ where pub async fn ensure_member_of_all_groups(&self, inbox_id: String) -> Result<(), GroupError> { let conn = self.store().conn()?; - let groups = conn.find_groups(None, None, None, None)?; + let groups = conn.find_groups(None, None, None, None, false)?; for group in groups { let group = self.group(group.id)?; Box::pin(group.add_members_by_inbox_id(self, vec![inbox_id.clone()])).await?; @@ -194,7 +194,7 @@ where // publish the intent if let Err(err) = sync_group.publish_intents(&conn.into(), self).await { - log::error!("error publishing sync group intents: {:?}", err); + tracing::error!("error publishing sync group intents: {:?}", err); } Ok((request_id, pin_code)) @@ -242,7 +242,7 @@ where } }; - log::info!("{:?}", last_message); + tracing::info!("{:?}", last_message); if let Some(msg) = last_message { // ensure the requester is a member of all the groups @@ -266,7 +266,7 @@ where // publish the intent if let Err(err) = sync_group.publish_intents(&conn.into(), self).await { - log::error!("error publishing sync group intents: {:?}", err); + tracing::error!("error publishing sync group intents: {:?}", err); } Ok(()) } @@ -384,7 +384,7 @@ where self.sync_welcomes().await?; let conn = self.store().conn()?; - let groups = conn.find_groups(None, None, None, None)?; + let groups = conn.find_groups(None, None, None, None, false)?; for crate::storage::group::StoredGroup { id, .. } in groups.into_iter() { let group = self.group(id)?; Box::pin(group.sync(self)).await?; @@ -418,7 +418,7 @@ where request.request_id.eq(request_id) && request.pin_code.eq(pin_code) } Err(e) => { - log::debug!("serde_json error: {:?}", e); + tracing::debug!("serde_json error: {:?}", e); false } _ => false, @@ -469,12 +469,12 @@ where None => return Err(MessageHistoryError::MissingHistorySyncUrl), }; let upload_url = format!("{}{}", url, "upload"); - log::info!("using upload url {:?}", upload_url); + tracing::info!("using upload url {:?}", upload_url); let bundle_file = upload_history_bundle(&upload_url, history_file.clone()).await?; let bundle_url = format!("{}files/{}", url, bundle_file); - log::info!("history bundle uploaded to {:?}", bundle_url); + tracing::info!("history bundle uploaded to {:?}", bundle_url); Ok(HistoryReply::new(request_id, &bundle_url, enc_key)) } @@ -502,14 +502,14 @@ where async fn prepare_groups_to_sync(&self) -> Result, MessageHistoryError> { let conn = self.store().conn()?; - Ok(conn.find_groups(None, None, None, None)?) + Ok(conn.find_groups(None, None, None, None, false)?) } async fn prepare_messages_to_sync( &self, ) -> Result, MessageHistoryError> { let conn = self.store().conn()?; - let groups = conn.find_groups(None, None, None, None)?; + let groups = conn.find_groups(None, None, None, None, false)?; let mut all_messages: Vec = vec![]; for StoredGroup { id, .. } in groups.into_iter() { @@ -608,7 +608,7 @@ async fn upload_history_bundle( if response.status().is_success() { Ok(response.text().await?) } else { - log::error!( + tracing::error!( "Failed to upload file. Status code: {} Response: {:?}", response.status(), response @@ -624,7 +624,7 @@ async fn upload_history_bundle( pub(crate) async fn download_history_bundle(url: &str) -> Result { let client = reqwest::Client::new(); - log::info!("downloading history bundle from {:?}", url); + tracing::info!("downloading history bundle from {:?}", url); let bundle_name = url .split('/') @@ -639,10 +639,10 @@ pub(crate) async fn download_history_bundle(url: &str) -> Result), #[error("Installation diff error: {0}")] @@ -180,6 +184,8 @@ pub enum GroupError { PublishCancelled, #[error("the publish failed to complete due to panic")] PublishPanicked, + #[error("dm requires target inbox_id")] + InvalidDmMissingInboxId, #[error("Missing metadata field {name}")] MissingMetadataField { name: String }, #[error("Message was processed but is missing")] @@ -213,7 +219,6 @@ impl RetryableError for GroupError { } } -#[derive(Debug)] pub struct MlsGroup { pub group_id: Vec, pub created_at_ns: i64, @@ -289,9 +294,10 @@ impl MlsGroup { ) -> Result { let conn = context.store.conn()?; let provider = XmtpOpenMlsProvider::new(conn); + let creator_inbox_id = context.inbox_id(); let protected_metadata = - build_protected_metadata_extension(&context.identity, Purpose::Conversation)?; - let mutable_metadata = build_mutable_metadata_extension_default(&context.identity, opts)?; + build_protected_metadata_extension(creator_inbox_id.clone(), Purpose::Conversation)?; + let mutable_metadata = build_mutable_metadata_extension_default(creator_inbox_id, opts)?; let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); let mutable_permissions = build_mutable_permissions_extension(permissions_policy_set)?; let group_config = build_group_config( @@ -317,6 +323,57 @@ impl MlsGroup { now_ns(), membership_state, context.inbox_id(), + None, + ); + + stored_group.store(provider.conn_ref())?; + let new_group = Self::new(context.clone(), group_id, stored_group.created_at_ns); + + // Consent state defaults to allowed when the user creates the group + new_group.update_consent_state(ConsentState::Allowed)?; + Ok(new_group) + } + + // Create a new DM and save it to the DB + pub fn create_dm_and_insert( + context: Arc, + membership_state: GroupMembershipState, + dm_target_inbox_id: InboxId, + ) -> Result { + let conn = context.store.conn()?; + let provider = XmtpOpenMlsProvider::new(conn); + let protected_metadata = + build_dm_protected_metadata_extension(context.inbox_id(), dm_target_inbox_id.clone())?; + let mutable_metadata = + build_dm_mutable_metadata_extension_default(context.inbox_id(), &dm_target_inbox_id)?; + let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); + let mutable_permissions = PolicySet::new_dm(); + let mutable_permission_extension = + build_mutable_permissions_extension(mutable_permissions)?; + let group_config = build_group_config( + protected_metadata, + mutable_metadata, + group_membership, + mutable_permission_extension, + )?; + + let mls_group = OpenMlsGroup::new( + &provider, + &context.identity.installation_keys, + &group_config, + CredentialWithKey { + credential: context.identity.credential(), + signature_key: context.identity.installation_keys.to_public_vec().into(), + }, + )?; + + let group_id = mls_group.group_id().to_vec(); + let stored_group = StoredGroup::new( + group_id.clone(), + now_ns(), + membership_state, + context.inbox_id(), + Some(dm_target_inbox_id), ); stored_group.store(provider.conn_ref())?; @@ -336,23 +393,47 @@ impl MlsGroup { added_by_inbox: String, welcome_id: i64, ) -> Result { + tracing::info!("Creating from welcome"); let mls_welcome = StagedWelcome::new_from_welcome(provider, &build_group_join_config(), welcome, None)?; let mls_group = mls_welcome.into_group(provider)?; let group_id = mls_group.group_id().to_vec(); let metadata = extract_group_metadata(&mls_group)?; + let dm_members = metadata.dm_members; + let dm_inbox_id = if let Some(dm_members) = &dm_members { + if dm_members.member_one_inbox_id == client.inbox_id() { + Some(dm_members.member_two_inbox_id.clone()) + } else { + Some(dm_members.member_one_inbox_id.clone()) + } + } else { + None + }; let group_type = metadata.conversation_type; let to_store = match group_type { - ConversationType::Group | ConversationType::Dm => StoredGroup::new_from_welcome( + ConversationType::Group => StoredGroup::new_from_welcome( group_id.clone(), now_ns(), GroupMembershipState::Pending, added_by_inbox, welcome_id, Purpose::Conversation, + dm_inbox_id, ), + ConversationType::Dm => { + validate_dm_group(client, &mls_group, &added_by_inbox)?; + StoredGroup::new_from_welcome( + group_id.clone(), + now_ns(), + GroupMembershipState::Pending, + added_by_inbox, + welcome_id, + Purpose::Conversation, + dm_inbox_id, + ) + } ConversationType::Sync => StoredGroup::new_from_welcome( group_id.clone(), now_ns(), @@ -360,6 +441,7 @@ impl MlsGroup { added_by_inbox, welcome_id, Purpose::Sync, + dm_inbox_id, ), }; @@ -382,6 +464,7 @@ impl MlsGroup { encrypted_welcome_bytes: Vec, welcome_id: i64, ) -> Result { + tracing::info!("Trying to decrypt welcome"); let welcome_bytes = decrypt_welcome(provider, hpke_public_key, &encrypted_welcome_bytes)?; let welcome = deserialize_welcome(&welcome_bytes)?; @@ -392,6 +475,7 @@ impl MlsGroup { ProcessedWelcome::new_from_welcome(provider, &join_config, welcome.clone())?; let psks = processed_welcome.psks(); if !psks.is_empty() { + tracing::error!("No PSK support for welcome"); return Err(GroupError::NoPSKSupport); } let staged_welcome = processed_welcome.into_staged_welcome(provider, None)?; @@ -404,16 +488,18 @@ impl MlsGroup { Self::create_from_welcome(client, provider, welcome, inbox_id, welcome_id).await } + #[cfg(feature = "message-history")] pub(crate) fn create_and_insert_sync_group( context: Arc, ) -> Result { let conn = context.store.conn()?; // let my_sequence_id = context.inbox_sequence_id(&conn)?; + let creator_inbox_id = context.inbox_id().to_string(); let provider = XmtpOpenMlsProvider::new(conn); let protected_metadata = - build_protected_metadata_extension(&context.identity, Purpose::Sync)?; + build_protected_metadata_extension(creator_inbox_id.clone(), Purpose::Sync)?; let mutable_metadata = build_mutable_metadata_extension_default( - &context.identity, + creator_inbox_id, GroupMetadataOptions::default(), )?; let group_membership = build_starting_group_membership_extension(context.inbox_id(), 0); @@ -470,6 +556,9 @@ impl MlsGroup { self.sync_until_last_intent_resolved(&provider, client) .await?; + // implicitly set group consent state to allowed + self.update_consent_state(ConsentState::Allowed)?; + message_id } @@ -488,6 +577,10 @@ impl MlsGroup { .await?; self.sync_until_last_intent_resolved(&provider, client) .await?; + + // implicitly set group consent state to allowed + self.update_consent_state(ConsentState::Allowed)?; + Ok(()) } @@ -612,7 +705,7 @@ impl MlsGroup { .get_inbox_ids(account_addresses.clone()) .await?; // get current number of users in group - let member_count = self.members()?.len(); + let member_count = self.members(client).await?.len(); if member_count + inbox_id_map.len() > MAX_GROUP_SIZE as usize { return Err(GroupError::UserLimitExceeded); } @@ -645,7 +738,7 @@ impl MlsGroup { // If some existing group member has an update, this will return an intent with changes // when we really should return an error if intent_data.is_empty() { - log::warn!("Member already added"); + tracing::warn!("Member already added"); return Ok(()); } @@ -942,6 +1035,29 @@ impl MlsGroup { }) } + /// Find the `consent_state` of the group + pub fn consent_state(&self) -> Result { + let conn = self.context.store.conn()?; + let record = + conn.get_consent_record(hex::encode(self.group_id.clone()), ConsentType::GroupId)?; + + match record { + Some(rec) => Ok(rec.state), + None => Ok(ConsentState::Unknown), + } + } + + pub fn update_consent_state(&self, state: ConsentState) -> Result<(), GroupError> { + let conn = self.context.store.conn()?; + conn.insert_or_replace_consent_records(vec![StoredConsentRecord::new( + ConsentType::GroupId, + state, + hex::encode(self.group_id.clone()), + )])?; + + Ok(()) + } + // Update this installation's leaf key in the group by creating a key update commit pub async fn key_update(&self, client: &Client) -> Result<(), GroupError> where @@ -984,6 +1100,68 @@ impl MlsGroup { Ok(extract_group_permissions(&mls_group)?) } + /// Used for testing that dm group validation works as expected. + /// + /// See the `test_validate_dm_group` test function for more details. + #[cfg(test)] + pub fn create_test_dm_group( + context: Arc, + dm_target_inbox_id: InboxId, + custom_protected_metadata: Option, + custom_mutable_metadata: Option, + custom_group_membership: Option, + custom_mutable_permissions: Option, + ) -> Result { + let conn = context.store.conn()?; + let provider = XmtpOpenMlsProvider::new(conn); + + let protected_metadata = custom_protected_metadata.unwrap_or_else(|| { + build_dm_protected_metadata_extension(context.inbox_id(), dm_target_inbox_id.clone()) + .unwrap() + }); + let mutable_metadata = custom_mutable_metadata.unwrap_or_else(|| { + build_dm_mutable_metadata_extension_default(context.inbox_id(), &dm_target_inbox_id) + .unwrap() + }); + let group_membership = custom_group_membership + .unwrap_or_else(|| build_starting_group_membership_extension(context.inbox_id(), 0)); + let mutable_permissions = custom_mutable_permissions.unwrap_or_else(PolicySet::new_dm); + let mutable_permission_extension = + build_mutable_permissions_extension(mutable_permissions)?; + + let group_config = build_group_config( + protected_metadata, + mutable_metadata, + group_membership, + mutable_permission_extension, + )?; + + let mls_group = OpenMlsGroup::new( + &provider, + &context.identity.installation_keys, + &group_config, + CredentialWithKey { + credential: context.identity.credential(), + signature_key: context.identity.installation_keys.to_public_vec().into(), + }, + )?; + + let group_id = mls_group.group_id().to_vec(); + let stored_group = StoredGroup::new( + group_id.clone(), + now_ns(), + GroupMembershipState::Allowed, // Use Allowed as default for tests + context.inbox_id(), + Some(dm_target_inbox_id), + ); + + stored_group.store(provider.conn_ref())?; + Ok(Self::new( + context.clone(), + group_id, + stored_group.created_at_ns, + )) + } } fn extract_message_v1(message: GroupMessage) -> Result { @@ -1001,14 +1179,30 @@ pub fn extract_group_id(message: &GroupMessage) -> Result, MessageProces } fn build_protected_metadata_extension( - identity: &Identity, + creator_inbox_id: String, group_purpose: Purpose, ) -> Result { let group_type = match group_purpose { Purpose::Conversation => ConversationType::Group, Purpose::Sync => ConversationType::Sync, }; - let metadata = GroupMetadata::new(group_type, identity.inbox_id().clone()); + + let metadata = GroupMetadata::new(group_type, creator_inbox_id, None); + let protected_metadata = Metadata::new(metadata.try_into()?); + + Ok(Extension::ImmutableMetadata(protected_metadata)) +} + +fn build_dm_protected_metadata_extension( + creator_inbox_id: String, + dm_inbox_id: InboxId, +) -> Result { + let dm_members = Some(DmMembers { + member_one_inbox_id: creator_inbox_id.clone(), + member_two_inbox_id: dm_inbox_id, + }); + + let metadata = GroupMetadata::new(ConversationType::Dm, creator_inbox_id, dm_members); let protected_metadata = Metadata::new(metadata.try_into()?); Ok(Extension::ImmutableMetadata(protected_metadata)) @@ -1025,11 +1219,25 @@ fn build_mutable_permissions_extension(policies: PolicySet) -> Result Result { let mutable_metadata: Vec = - GroupMutableMetadata::new_default(identity.inbox_id.clone(), opts).try_into()?; + GroupMutableMetadata::new_default(creator_inbox_id, opts).try_into()?; + let unknown_gc_extension = UnknownExtension(mutable_metadata); + + Ok(Extension::Unknown( + MUTABLE_METADATA_EXTENSION_ID, + unknown_gc_extension, + )) +} + +pub fn build_dm_mutable_metadata_extension_default( + creator_inbox_id: String, + dm_target_inbox_id: &str, +) -> Result { + let mutable_metadata: Vec = + GroupMutableMetadata::new_dm_default(creator_inbox_id, dm_target_inbox_id).try_into()?; let unknown_gc_extension = UnknownExtension(mutable_metadata); Ok(Extension::Unknown( @@ -1230,6 +1438,7 @@ async fn validate_initial_group_membership( conn: &DbConnection, mls_group: &OpenMlsGroup, ) -> Result<(), GroupError> { + tracing::info!("Validating initial group membership"); let membership = extract_group_membership(mls_group.extensions())?; let needs_update = client.filter_inbox_ids_needing_updates(conn, membership.to_filters())?; if !needs_update.is_empty() { @@ -1261,6 +1470,60 @@ async fn validate_initial_group_membership( return Err(GroupError::InvalidGroupMembership); } + tracing::info!("Group membership validated"); + Ok(()) +} + +fn validate_dm_group( + client: &Client, + mls_group: &OpenMlsGroup, + added_by_inbox: &str, +) -> Result<(), GroupError> { + let metadata = extract_group_metadata(mls_group)?; + + // Check if the conversation type is DM + if metadata.conversation_type != ConversationType::Dm { + return Err(GroupError::Generic( + "Invalid conversation type for DM group".to_string(), + )); + } + + // Check if DmMembers are set and validate their contents + if let Some(dm_members) = metadata.dm_members { + let our_inbox_id = client.context.identity.inbox_id().clone(); + if !((dm_members.member_one_inbox_id == added_by_inbox + && dm_members.member_two_inbox_id == our_inbox_id) + || (dm_members.member_one_inbox_id == our_inbox_id + && dm_members.member_two_inbox_id == added_by_inbox)) + { + return Err(GroupError::Generic( + "DM members do not match expected inboxes".to_string(), + )); + } + } else { + return Err(GroupError::Generic( + "DM group must have DmMembers set".to_string(), + )); + } + + // Validate mutable metadata + let mutable_metadata: GroupMutableMetadata = mls_group.try_into()?; + + // Check if the admin list and super admin list are empty + if !mutable_metadata.admin_list.is_empty() || !mutable_metadata.super_admin_list.is_empty() { + return Err(GroupError::Generic( + "DM group must have empty admin and super admin lists".to_string(), + )); + } + + // Validate permissions + let permissions = extract_group_permissions(mls_group)?; + if permissions != GroupMutablePermissions::new(PolicySet::new_dm()) { + return Err(GroupError::Generic( + "Invalid permissions for DM group".to_string(), + )); + } + Ok(()) } @@ -1279,25 +1542,28 @@ mod tests { use openmls::prelude::{tls_codec::Serialize, Member, MlsGroup as OpenMlsGroup}; use prost::Message; use std::sync::Arc; - use tracing_test::traced_test; use xmtp_cryptography::utils::generate_local_wallet; use xmtp_proto::xmtp::mls::message_contents::EncodedContent; use crate::{ assert_err, assert_logged, builder::ClientBuilder, - client::MessageProcessingError, + client::{FindGroupParams, MessageProcessingError}, codecs::{group_updated::GroupUpdatedCodec, ContentCodec}, groups::{ - build_group_membership_extension, + build_dm_protected_metadata_extension, build_group_membership_extension, + build_mutable_metadata_extension_default, build_protected_metadata_extension, group_membership::GroupMembership, group_metadata::{ConversationType, GroupMetadata}, group_mutable_metadata::MetadataField, intents::{PermissionPolicyOption, PermissionUpdateType}, members::{GroupMember, PermissionLevel}, - DeliveryStatus, GroupMetadataOptions, PreconfiguredPolicies, UpdateAdminListType, + validate_dm_group, DeliveryStatus, GroupMetadataOptions, PreconfiguredPolicies, + UpdateAdminListType, }, storage::{ + consent_record::ConsentState, + group::Purpose, group_intent::{IntentKind, IntentState, NewGroupIntent}, group_message::{GroupMessageKind, StoredGroupMessage}, }, @@ -1306,6 +1572,7 @@ mod tests { }; use super::{ + group_permissions::PolicySet, intents::{Installation, SendWelcomesAction}, GroupError, MlsGroup, }; @@ -1315,7 +1582,7 @@ mod tests { ApiClient: XmtpApi, { client.sync_welcomes().await.unwrap(); - let mut groups = client.find_groups(None, None, None, None).unwrap(); + let mut groups = client.find_groups(FindGroupParams::default()).unwrap(); groups.remove(0) } @@ -1478,8 +1745,8 @@ mod tests { assert_eq!(bola_group_name, ""); // Check if both clients can see the members correctly - let amal_members: Vec = amal_group.members().unwrap(); - let bola_members: Vec = bola_group.members().unwrap(); + let amal_members: Vec = amal_group.members(&amal).await.unwrap(); + let bola_members: Vec = bola_group.members(&bola).await.unwrap(); assert_eq!(amal_members.len(), 2); assert_eq!(bola_members.len(), 2); @@ -1523,13 +1790,13 @@ mod tests { let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); - log::info!("Adding charlie from amal"); + tracing::info!("Adding charlie from amal"); // Have amal and bola both invite charlie. amal_group .add_members_by_inbox_id(&amal, vec![charlie.inbox_id()]) .await .expect("failed to add charlie"); - log::info!("Adding charlie from bola"); + tracing::info!("Adding charlie from bola"); bola_group .add_members_by_inbox_id(&bola, vec![charlie.inbox_id()]) .await @@ -1593,43 +1860,44 @@ mod tests { let matching_message = bola_messages .iter() .find(|m| m.decrypted_message_bytes == "hello from amal".as_bytes()); - log::info!("found message: {:?}", bola_messages); + tracing::info!("found message: {:?}", bola_messages); assert!(matching_message.is_some()); } - #[tokio::test(flavor = "multi_thread", worker_threads = 1)] - #[traced_test] - async fn test_create_from_welcome_validation() { - let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; - let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; - - let alix_group: MlsGroup = alix - .create_group(None, GroupMetadataOptions::default()) - .unwrap(); - let provider = alix.mls_provider().unwrap(); - // Doctor the group membership - let mut mls_group = alix_group.load_mls_group(&provider).unwrap(); - let mut existing_extensions = mls_group.extensions().clone(); - let mut group_membership = GroupMembership::new(); - group_membership.add("foo".to_string(), 1); - existing_extensions.add_or_replace(build_group_membership_extension(&group_membership)); - mls_group - .update_group_context_extensions( - &provider, - existing_extensions.clone(), - &alix.identity().installation_keys, - ) - .unwrap(); - mls_group.merge_pending_commit(&provider).unwrap(); - - // Now add bo to the group - force_add_member(&alix, &bo, &alix_group, &mut mls_group, &provider).await; - - // Bo should not be able to actually read this group - bo.sync_welcomes().await.unwrap(); - let groups = bo.find_groups(None, None, None, None).unwrap(); - assert_eq!(groups.len(), 0); - assert_logged!("failed to create group from welcome", 1); + #[test] + fn test_create_from_welcome_validation() { + crate::traced_test(|| async { + let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let bo = ClientBuilder::new_test_client(&generate_local_wallet()).await; + + let alix_group: MlsGroup = alix + .create_group(None, GroupMetadataOptions::default()) + .unwrap(); + let provider = alix.mls_provider().unwrap(); + // Doctor the group membership + let mut mls_group = alix_group.load_mls_group(&provider).unwrap(); + let mut existing_extensions = mls_group.extensions().clone(); + let mut group_membership = GroupMembership::new(); + group_membership.add("foo".to_string(), 1); + existing_extensions.add_or_replace(build_group_membership_extension(&group_membership)); + mls_group + .update_group_context_extensions( + &provider, + existing_extensions.clone(), + &alix.identity().installation_keys, + ) + .unwrap(); + mls_group.merge_pending_commit(&provider).unwrap(); + + // Now add bo to the group + force_add_member(&alix, &bo, &alix_group, &mut mls_group, &provider).await; + + // Bo should not be able to actually read this group + bo.sync_welcomes().await.unwrap(); + let groups = bo.find_groups(FindGroupParams::default()).unwrap(); + assert_eq!(groups.len(), 0); + assert_logged!("failed to create group from welcome", 1); + }); } #[tokio::test(flavor = "multi_thread", worker_threads = 1)] @@ -1755,7 +2023,7 @@ mod tests { .expect("send message"); bola_client.sync_welcomes().await.unwrap(); - let bola_groups = bola_client.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola_client.find_groups(FindGroupParams::default()).unwrap(); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola_client).await.unwrap(); let bola_messages = bola_group @@ -1805,8 +2073,8 @@ mod tests { ) .await .unwrap(); - log::info!("created the group with 2 additional members"); - assert_eq!(group.members().unwrap().len(), 3); + tracing::info!("created the group with 2 additional members"); + assert_eq!(group.members(&bola).await.unwrap().len(), 3); let messages = group.find_messages(None, None, None, None, None).unwrap(); assert_eq!(messages.len(), 1); assert_eq!(messages[0].kind, GroupMessageKind::MembershipChange); @@ -1820,8 +2088,8 @@ mod tests { .remove_members(&amal, vec![bola_wallet.get_address()]) .await .unwrap(); - assert_eq!(group.members().unwrap().len(), 2); - log::info!("removed bola"); + assert_eq!(group.members(&bola).await.unwrap().len(), 2); + tracing::info!("removed bola"); let messages = group.find_messages(None, None, None, None, None).unwrap(); assert_eq!(messages.len(), 2); assert_eq!(messages[1].kind, GroupMessageKind::MembershipChange); @@ -1856,20 +2124,22 @@ mod tests { ) .await .unwrap(); - assert_eq!(group.members().unwrap().len(), 3); + assert_eq!(group.members(&bola).await.unwrap().len(), 3); group .remove_members(&amal, vec![bola_wallet.get_address()]) .await .unwrap(); - assert_eq!(group.members().unwrap().len(), 2); + assert_eq!(group.members(&bola).await.unwrap().len(), 2); assert!(group - .members() + .members(&bola) + .await .unwrap() .iter() .all(|m| m.inbox_id != bola.inbox_id())); assert!(group - .members() + .members(&bola) + .await .unwrap() .iter() .any(|m| m.inbox_id == charlie.inbox_id())); @@ -1915,7 +2185,7 @@ mod tests { .await .unwrap(); - assert_eq!(group.members().unwrap().len(), 2); + assert_eq!(group.members(&amal).await.unwrap().len(), 2); let provider: XmtpOpenMlsProvider = amal.context.store.conn().unwrap().into(); // Finished with setup @@ -2106,7 +2376,7 @@ mod tests { .await .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2274,7 +2544,7 @@ mod tests { .await .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2353,7 +2623,7 @@ mod tests { .await .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2369,7 +2639,7 @@ mod tests { // Verify that bola can not add caro because they are not an admin bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2433,7 +2703,7 @@ mod tests { // Verify that bola can not add charlie because they are not an admin bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2461,7 +2731,7 @@ mod tests { .await .unwrap(); bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2477,7 +2747,7 @@ mod tests { // Verify that bola can not add caro as an admin because they are not a super admin bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); assert_eq!(bola_groups.len(), 1); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); @@ -2562,7 +2832,7 @@ mod tests { amal_group.sync(&amal).await.unwrap(); // Initial checks for group members - let initial_members = amal_group.members().unwrap(); + let initial_members = amal_group.members(&amal).await.unwrap(); let mut count_member = 0; let mut count_admin = 0; let mut count_super_admin = 0; @@ -2590,7 +2860,7 @@ mod tests { amal_group.sync(&amal).await.unwrap(); // Check after adding Bola as an admin - let members = amal_group.members().unwrap(); + let members = amal_group.members(&amal).await.unwrap(); let mut count_member = 0; let mut count_admin = 0; let mut count_super_admin = 0; @@ -2618,7 +2888,7 @@ mod tests { amal_group.sync(&amal).await.unwrap(); // Check after adding Caro as a super admin - let members = amal_group.members().unwrap(); + let members = amal_group.members(&amal).await.unwrap(); let mut count_member = 0; let mut count_admin = 0; let mut count_super_admin = 0; @@ -2724,7 +2994,7 @@ mod tests { // Step 3: Verify that Bola can update the group name, and amal sees the update bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); bola_group @@ -2789,7 +3059,7 @@ mod tests { // Step 3: Bola attemps to add Caro, but fails because group is admin only let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; bola.sync_welcomes().await.unwrap(); - let bola_groups = bola.find_groups(None, None, None, None).unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); let bola_group: &MlsGroup = bola_groups.first().unwrap(); bola_group.sync(&bola).await.unwrap(); let result = bola_group @@ -2833,7 +3103,7 @@ mod tests { .await .unwrap(); bola_group.sync(&bola).await.unwrap(); - let members = bola_group.members().unwrap(); + let members = bola_group.members(&bola).await.unwrap(); assert_eq!(members.len(), 3); } @@ -2926,6 +3196,78 @@ mod tests { ); } + #[tokio::test(flavor = "multi_thread")] + async fn test_dm_creation() { + let amal = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let bola = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; + + // Amal creates a dm group targetting bola + let amal_dm: MlsGroup = amal.create_dm_by_inbox_id(bola.inbox_id()).await.unwrap(); + + // Amal can not add caro to the dm group + let result = amal_dm + .add_members_by_inbox_id(&amal, vec![caro.inbox_id()]) + .await; + assert!(result.is_err()); + + // Bola is already a member + let result = amal_dm + .add_members_by_inbox_id(&amal, vec![bola.inbox_id(), caro.inbox_id()]) + .await; + assert!(result.is_err()); + amal_dm.sync(&amal).await.unwrap(); + let members = amal_dm.members(&amal).await.unwrap(); + assert_eq!(members.len(), 2); + + // Bola can message amal + let _ = bola.sync_welcomes().await; + let bola_groups = bola + .find_groups(FindGroupParams { + include_dm_groups: true, + ..FindGroupParams::default() + }) + .unwrap(); + let bola_dm: &MlsGroup = bola_groups.first().unwrap(); + bola_dm.send_message(b"test one", &bola).await.unwrap(); + + // Amal sync and reads message + amal_dm.sync(&amal).await.unwrap(); + let messages = amal_dm.find_messages(None, None, None, None, None).unwrap(); + assert_eq!(messages.len(), 2); + let message = messages.last().unwrap(); + assert_eq!(message.decrypted_message_bytes, b"test one"); + + // Amal can not remove bola + let result = amal_dm + .remove_members_by_inbox_id(&amal, vec![bola.inbox_id()]) + .await; + assert!(result.is_err()); + amal_dm.sync(&amal).await.unwrap(); + let members = amal_dm.members(&amal).await.unwrap(); + assert_eq!(members.len(), 2); + + // Neither Amal nor Bola is an admin or super admin + amal_dm.sync(&amal).await.unwrap(); + bola_dm.sync(&bola).await.unwrap(); + let is_amal_admin = amal_dm + .is_admin(amal.inbox_id(), amal.mls_provider().unwrap()) + .unwrap(); + let is_bola_admin = amal_dm + .is_admin(bola.inbox_id(), bola.mls_provider().unwrap()) + .unwrap(); + let is_amal_super_admin = amal_dm + .is_super_admin(amal.inbox_id(), amal.mls_provider().unwrap()) + .unwrap(); + let is_bola_super_admin = amal_dm + .is_super_admin(bola.inbox_id(), bola.mls_provider().unwrap()) + .unwrap(); + assert!(!is_amal_admin); + assert!(!is_bola_admin); + assert!(!is_amal_super_admin); + assert!(!is_bola_super_admin); + } + #[tokio::test(flavor = "multi_thread")] async fn process_messages_abort_on_retryable_error() { let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; @@ -3218,4 +3560,170 @@ mod tests { MessageProcessingError::EpochIncrementNotAllowed ); } + + #[tokio::test] + async fn test_get_and_set_consent() { + let alix = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let bola = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let caro = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let alix_group = alix + .create_group(None, GroupMetadataOptions::default()) + .unwrap(); + + // group consent state should be allowed if user created it + assert_eq!(alix_group.consent_state().unwrap(), ConsentState::Allowed); + + alix_group + .update_consent_state(ConsentState::Denied) + .unwrap(); + assert_eq!(alix_group.consent_state().unwrap(), ConsentState::Denied); + + alix_group + .add_members_by_inbox_id(&alix, vec![bola.inbox_id()]) + .await + .unwrap(); + + bola.sync_welcomes().await.unwrap(); + let bola_groups = bola.find_groups(FindGroupParams::default()).unwrap(); + let bola_group = bola_groups.first().unwrap(); + // group consent state should default to unknown for users who did not create the group + assert_eq!(bola_group.consent_state().unwrap(), ConsentState::Unknown); + + bola_group + .send_message("hi from bola".as_bytes(), &bola) + .await + .unwrap(); + + // group consent state should be allowed if user sends a message to the group + assert_eq!(bola_group.consent_state().unwrap(), ConsentState::Allowed); + + alix_group + .add_members_by_inbox_id(&alix, vec![caro.inbox_id()]) + .await + .unwrap(); + + caro.sync_welcomes().await.unwrap(); + let caro_groups = caro.find_groups(FindGroupParams::default()).unwrap(); + let caro_group = caro_groups.first().unwrap(); + + caro_group + .send_message_optimistic("hi from caro".as_bytes()) + .unwrap(); + + caro_group.publish_messages(&caro).await.unwrap(); + + // group consent state should be allowed if user publishes a message to the group + assert_eq!(caro_group.consent_state().unwrap(), ConsentState::Allowed); + } + + #[tokio::test] + async fn test_validate_dm_group() { + let client = ClientBuilder::new_test_client(&generate_local_wallet()).await; + let added_by_inbox = "added_by_inbox_id"; + let creator_inbox_id = client.context.identity.inbox_id().clone(); + let dm_target_inbox_id = added_by_inbox.to_string(); + + // Test case 1: Valid DM group + let valid_dm_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + None, + None, + None, + None, + ) + .unwrap(); + assert!(validate_dm_group( + &client, + &valid_dm_group + .load_mls_group(client.mls_provider().unwrap()) + .unwrap(), + added_by_inbox + ) + .is_ok()); + + // Test case 2: Invalid conversation type + let invalid_protected_metadata = + build_protected_metadata_extension(creator_inbox_id.clone(), Purpose::Conversation) + .unwrap(); + let invalid_type_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + Some(invalid_protected_metadata), + None, + None, + None, + ) + .unwrap(); + assert!(matches!( + validate_dm_group(&client, &invalid_type_group.load_mls_group(client.mls_provider().unwrap()).unwrap(), added_by_inbox), + Err(GroupError::Generic(msg)) if msg.contains("Invalid conversation type") + )); + + // Test case 3: Missing DmMembers + // This case is not easily testable with the current structure, as DmMembers are set in the protected metadata + + // Test case 4: Mismatched DM members + let mismatched_dm_members = build_dm_protected_metadata_extension( + creator_inbox_id.clone(), + "wrong_inbox_id".to_string(), + ) + .unwrap(); + let mismatched_dm_members_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + Some(mismatched_dm_members), + None, + None, + None, + ) + .unwrap(); + assert!(matches!( + validate_dm_group(&client, &mismatched_dm_members_group.load_mls_group(client.mls_provider().unwrap()).unwrap(), added_by_inbox), + Err(GroupError::Generic(msg)) if msg.contains("DM members do not match expected inboxes") + )); + + // Test case 5: Non-empty admin list + let non_empty_admin_list = build_mutable_metadata_extension_default( + creator_inbox_id.clone(), + GroupMetadataOptions::default(), + ) + .unwrap(); + let non_empty_admin_list_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + None, + Some(non_empty_admin_list), + None, + None, + ) + .unwrap(); + assert!(matches!( + validate_dm_group(&client, &non_empty_admin_list_group.load_mls_group(client.mls_provider().unwrap()).unwrap(), added_by_inbox), + Err(GroupError::Generic(msg)) if msg.contains("DM group must have empty admin and super admin lists") + )); + + // Test case 6: Non-empty super admin list + // Similar to test case 5, but with super_admin_list + + // Test case 7: Invalid permissions + let invalid_permissions = PolicySet::default(); + let invalid_permissions_group = MlsGroup::create_test_dm_group( + client.context.clone(), + dm_target_inbox_id.clone(), + None, + None, + None, + Some(invalid_permissions), + ) + .unwrap(); + assert!(matches!( + validate_dm_group( + &client, + &invalid_permissions_group.load_mls_group(client.mls_provider().unwrap()).unwrap(), + added_by_inbox + ), + Err(GroupError::Generic(msg)) if msg.contains("Invalid permissions for DM group") + )); + } } diff --git a/xmtp_mls/src/groups/subscriptions.rs b/xmtp_mls/src/groups/subscriptions.rs index 88cf2faa6..30f814d41 100644 --- a/xmtp_mls/src/groups/subscriptions.rs +++ b/xmtp_mls/src/groups/subscriptions.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::pin::Pin; use std::sync::Arc; use futures::Stream; @@ -9,8 +8,8 @@ use crate::storage::group_message::StoredGroupMessage; use crate::storage::refresh_state::EntityKind; use crate::storage::StorageError; use crate::subscriptions::{MessagesStreamInfo, StreamHandle}; +use crate::XmtpApi; use crate::{retry::Retry, retry_async, Client}; -use crate::{retry_sync, XmtpApi}; use prost::Message; use xmtp_proto::xmtp::mls::api::v1::GroupMessage; @@ -18,7 +17,7 @@ impl MlsGroup { pub(crate) async fn process_stream_entry( &self, envelope: GroupMessage, - client: Arc>, + client: &Client, ) -> Result, GroupError> where ApiClient: XmtpApi, @@ -26,19 +25,17 @@ impl MlsGroup { let msgv1 = extract_message_v1(envelope)?; let msg_id = msgv1.id; let client_id = client.inbox_id(); - log::info!( + tracing::info!( "client [{}] is about to process streamed envelope: [{}]", &client_id.clone(), &msg_id ); let created_ns = msgv1.created_ns; - if !self.has_already_synced(msg_id)? { - let client_pointer = client.clone(); + if !self.has_already_synced(msg_id).await? { let process_result = retry_async!( Retry::default(), (async { - let client_pointer = client_pointer.clone(); let client_id = client_id.clone(); let msgv1 = msgv1.clone(); self.context @@ -48,14 +45,14 @@ impl MlsGroup { // Attempt processing immediately, but fail if the message is not an Application Message // Returning an error should roll back the DB tx - log::info!( + tracing::info!( "current epoch for [{}] in process_stream_entry() is Epoch: [{}]", client_id, openmls_group.epoch() ); self.process_message( - client_pointer.as_ref(), + client, &mut openmls_group, &provider, &msgv1, @@ -71,16 +68,16 @@ impl MlsGroup { if let Some(GroupError::ReceiveError(_)) = process_result.as_ref().err() { // Swallow errors here, since another process may have successfully saved the message // to the DB - match self.sync_with_conn(&client.mls_provider()?, &client).await { + match self.sync_with_conn(&client.mls_provider()?, client).await { Ok(_) => { - log::debug!("Sync triggered by streamed message successful") + tracing::debug!("Sync triggered by streamed message successful") } Err(err) => { - log::warn!("Sync triggered by streamed message failed: {}", err); + tracing::warn!("Sync triggered by streamed message failed: {}", err); } }; } else if process_result.is_err() { - log::error!("Process stream entry {:?}", process_result.err()); + tracing::error!("Process stream entry {:?}", process_result.err()); } } @@ -96,21 +93,20 @@ impl MlsGroup { } // Checks if a message has already been processed through a sync - fn has_already_synced(&self, id: u64) -> Result { + async fn has_already_synced(&self, id: u64) -> Result { let check_for_last_cursor = || -> Result { let conn = self.context.store.conn()?; conn.get_last_cursor_for_id(&self.group_id, EntityKind::Group) }; - let last_id = retry_sync!(Retry::default(), check_for_last_cursor)?; - + let last_id = retry_async!(Retry::default(), (async { check_for_last_cursor() }))?; Ok(last_id >= id as i64) } pub async fn process_streamed_group_message( &self, envelope_bytes: Vec, - client: Arc>, + client: &Client, ) -> Result where ApiClient: XmtpApi, @@ -122,21 +118,21 @@ impl MlsGroup { message.ok_or(GroupError::MissingMessage) } - pub async fn stream( - &self, - client: Arc>, - ) -> Result + Send + '_>>, GroupError> + pub async fn stream<'a, ApiClient>( + &'a self, + client: &'a Client, + ) -> Result + '_, GroupError> where - ApiClient: crate::XmtpApi, + ApiClient: crate::XmtpApi + 'static, { Ok(client - .stream_messages(HashMap::from([( + .stream_messages(Arc::new(HashMap::from([( self.group_id.clone(), MessagesStreamInfo { convo_created_at_ns: self.created_at_ns, cursor: 0, }, - )])) + )]))) .await?) } @@ -147,7 +143,7 @@ impl MlsGroup { callback: impl FnMut(StoredGroupMessage) + Send + 'static, ) -> StreamHandle> where - ApiClient: crate::XmtpApi, + ApiClient: crate::XmtpApi + 'static, { Client::::stream_messages_with_callback( client, @@ -203,7 +199,7 @@ mod tests { let mut message_bytes: Vec = Vec::new(); message.encode(&mut message_bytes).unwrap(); let message_again = amal_group - .process_streamed_group_message(message_bytes, Arc::new(amal)) + .process_streamed_group_message(message_bytes, &amal) .await; if let Ok(message) = message_again { @@ -238,7 +234,8 @@ mod tests { let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); let mut stream = UnboundedReceiverStream::new(rx); tokio::spawn(async move { - let mut stream = bola_group_ptr.stream(bola_ptr).await.unwrap(); + let stream = bola_group_ptr.stream(&bola_ptr).await.unwrap(); + futures::pin_mut!(stream); while let Some(item) = stream.next().await { let _ = tx.send(item); notify_ptr.notify_one(); @@ -282,7 +279,8 @@ mod tests { let amal_ptr = amal.clone(); let group_ptr = group.clone(); tokio::spawn(async move { - let mut stream = group_ptr.stream(amal_ptr).await.unwrap(); + let stream = group_ptr.stream(&amal_ptr).await.unwrap(); + futures::pin_mut!(stream); while let Some(item) = stream.next().await { let _ = tx.send(item); } @@ -324,7 +322,8 @@ mod tests { let (start_tx, start_rx) = tokio::sync::oneshot::channel(); let mut stream = UnboundedReceiverStream::new(rx); tokio::spawn(async move { - let mut stream = amal_group_ptr.stream(amal_ptr).await.unwrap(); + let stream = amal_group_ptr.stream(&amal_ptr).await.unwrap(); + futures::pin_mut!(stream); let _ = start_tx.send(()); while let Some(item) = stream.next().await { let _ = tx.send(item); diff --git a/xmtp_mls/src/groups/sync.rs b/xmtp_mls/src/groups/sync.rs index bbcfbc41d..c5c10f824 100644 --- a/xmtp_mls/src/groups/sync.rs +++ b/xmtp_mls/src/groups/sync.rs @@ -13,6 +13,8 @@ use super::{ validated_commit::extract_group_membership, GroupError, MlsGroup, }; +#[cfg(feature = "message-history")] +use crate::groups::message_history::MessageHistoryContent; use crate::{ client::MessageProcessingError, codecs::{group_updated::GroupUpdatedCodec, ContentCodec}, @@ -20,10 +22,7 @@ use crate::{ GRPC_DATA_LIMIT, MAX_GROUP_SIZE, MAX_INTENT_PUBLISH_ATTEMPTS, MAX_PAST_EPOCHS, SYNC_UPDATE_INSTALLATIONS_INTERVAL_NS, }, - groups::{ - intents::UpdateMetadataIntentData, message_history::MessageHistoryContent, - validated_commit::ValidatedCommit, - }, + groups::{intents::UpdateMetadataIntentData, validated_commit::ValidatedCommit}, hpke::{encrypt_welcome, HpkeError}, identity::parse_credential, identity_updates::load_identity_updates, @@ -41,7 +40,6 @@ use crate::{ Client, Delete, Fetch, StoreOrIgnore, XmtpApi, }; use futures::future::try_join_all; -use log::debug; use openmls::{ credentials::BasicCredential, extensions::Extensions, @@ -59,6 +57,7 @@ use openmls_basic_credential::SignatureKeyPair; use openmls_traits::OpenMlsProvider; use prost::bytes::Bytes; use prost::Message; +use tracing::debug; use xmtp_id::InboxId; use xmtp_proto::xmtp::mls::{ api::v1::{ @@ -69,14 +68,16 @@ use xmtp_proto::xmtp::mls::{ GroupMessage, WelcomeMessageInput, }, message_contents::{ - plaintext_envelope::{ - v2::MessageType::{Reply, Request}, - Content, V1, V2, - }, + plaintext_envelope::{Content, V1, V2}, GroupUpdated, PlaintextEnvelope, }, }; +#[cfg(feature = "message-history")] +use xmtp_proto::xmtp::mls::message_contents::plaintext_envelope::v2::MessageType::{ + Reply, Request, +}; + #[derive(Debug)] struct PublishIntentData { staged_commit: Option>, @@ -92,8 +93,8 @@ impl MlsGroup { let conn = self.context.store.conn()?; let mls_provider = XmtpOpenMlsProvider::from(conn); - log::info!("[{}] syncing group", client.inbox_id()); - log::info!( + tracing::info!("[{}] syncing group", client.inbox_id()); + tracing::info!( "current epoch for [{}] in sync() is Epoch: [{}]", client.inbox_id(), self.load_mls_group(&mls_provider)?.epoch() @@ -120,20 +121,20 @@ impl MlsGroup { // Even if publish fails, continue to receiving if let Err(publish_error) = self.publish_intents(provider, client).await { - log::error!("Sync: error publishing intents {:?}", publish_error); + tracing::error!("Sync: error publishing intents {:?}", publish_error); errors.push(publish_error); } // Even if receiving fails, continue to post_commit if let Err(receive_error) = self.receive(provider, client).await { - log::error!("receive error {:?}", receive_error); + tracing::error!("receive error {:?}", receive_error); // We don't return an error if receive fails, because it's possible this is caused // by malicious data sent over the network, or messages from before the user was // added to the group } if let Err(post_commit_err) = self.post_commit(conn, client).await { - log::error!("post commit error {:?}", post_commit_err); + tracing::error!("post commit error {:?}", post_commit_err); errors.push(post_commit_err); } @@ -188,7 +189,7 @@ impl MlsGroup { let mut last_err: Option = None; while num_attempts < crate::configuration::MAX_GROUP_SYNC_RETRIES { if let Err(err) = self.sync_with_conn(provider, client).await { - log::error!("error syncing group {:?}", err); + tracing::error!("error syncing group {:?}", err); last_err = Some(err); } @@ -202,7 +203,7 @@ impl MlsGroup { state: IntentState::Error, .. })) => { - log::warn!( + tracing::warn!( "not retrying intent ID {id}. since it is in state Error. {:?}", last_err ); @@ -211,10 +212,10 @@ impl MlsGroup { ))); } Ok(Some(StoredGroupIntent { id, state, .. })) => { - log::warn!("retrying intent ID {id}. intent currently in state {state:?}"); + tracing::warn!("retrying intent ID {id}. intent currently in state {state:?}"); } Err(err) => { - log::error!("database error fetching intent {:?}", err); + tracing::error!("database error fetching intent {:?}", err); last_err = Some(GroupError::Storage(err)); } }; @@ -232,7 +233,7 @@ impl MlsGroup { max_past_epochs: usize, ) -> bool { if message_epoch.as_u64() + max_past_epochs as u64 <= group_epoch.as_u64() { - log::warn!( + tracing::warn!( "[{}] own message epoch {} is {} or more less than group epoch {} for intent {}. Retrying message", inbox_id, message_epoch, @@ -243,7 +244,7 @@ impl MlsGroup { return false; } else if message_epoch.as_u64() > group_epoch.as_u64() { // Should not happen, logging proactively - log::error!( + tracing::error!( "[{}] own message epoch {} is greater than group epoch {} for intent {}. Retrying message", inbox_id, message_epoch, @@ -293,7 +294,7 @@ impl MlsGroup { let group_epoch_u64 = group_epoch.as_u64(); if published_in_epoch_u64 != group_epoch_u64 { - log::warn!( + tracing::warn!( "Intent was published in epoch {} but group is currently in epoch {}", published_in_epoch_u64, group_epoch_u64 @@ -308,7 +309,7 @@ impl MlsGroup { return Err(MessageProcessingError::IntentMissingStagedCommit); }; - log::info!( + tracing::info!( "[{}] Validating commit for intent {}. Message timestamp: {}", self.context.inbox_id(), intent.id, @@ -324,7 +325,7 @@ impl MlsGroup { .await; if let Err(err) = maybe_validated_commit { - log::error!( + tracing::error!( "Error validating commit for own message. Intent ID [{}]: {:?}", intent.id, err @@ -336,13 +337,13 @@ impl MlsGroup { let validated_commit = maybe_validated_commit.expect("Checked for error"); - log::info!( + tracing::info!( "[{}] merging pending commit for intent {}", self.context.inbox_id(), intent.id ); if let Err(err) = openmls_group.merge_staged_commit(&provider, pending_commit) { - log::error!("error merging commit: {}", err); + tracing::error!("error merging commit: {}", err); return Ok(IntentState::ToPublish); } else { // If no error committing the change, write a transcript message @@ -380,14 +381,14 @@ impl MlsGroup { let decrypted_message = openmls_group.process_message(provider, message)?; let (sender_inbox_id, sender_installation_id) = extract_message_sender(openmls_group, &decrypted_message, envelope_timestamp_ns)?; - log::info!( + tracing::info!( "[{}] extracted sender inbox id: {}", self.context.inbox_id(), sender_inbox_id ); match decrypted_message.into_content() { ProcessedMessageContent::ApplicationMessage(application_message) => { - log::info!("[{}] decoding application message", self.context.inbox_id()); + tracing::info!("[{}] decoding application message", self.context.inbox_id()); let message_bytes = application_message.into_bytes(); let mut bytes = Bytes::from(message_bytes.clone()); @@ -413,10 +414,12 @@ impl MlsGroup { } .store_or_ignore(provider.conn_ref())? } + #[cfg_attr(not(feature = "message-history"), allow(unused_variables))] Some(Content::V2(V2 { idempotency_key, message_type, })) => match message_type { + #[cfg(feature = "message-history")] Some(Request(history_request)) => { let content: MessageHistoryContent = MessageHistoryContent::Request(history_request); @@ -440,6 +443,7 @@ impl MlsGroup { } .store_or_ignore(provider.conn_ref())?; } + #[cfg(feature = "message-history")] Some(Reply(history_reply)) => { let content: MessageHistoryContent = MessageHistoryContent::Reply(history_reply); @@ -477,7 +481,7 @@ impl MlsGroup { // intentionally left blank. } ProcessedMessageContent::StagedCommitMessage(staged_commit) => { - log::info!( + tracing::info!( "[{}] received staged commit. Merging and clearing any pending commits", self.context.inbox_id() ); @@ -492,7 +496,7 @@ impl MlsGroup { openmls_group, ) .await?; - log::info!( + tracing::info!( "[{}] staged commit is valid, will attempt to merge", self.context.inbox_id() ); @@ -538,7 +542,7 @@ impl MlsGroup { // Intent with the payload hash matches Ok(Some(intent)) => { let intent_id = intent.id; - log::info!( + tracing::info!( "client [{}] is about to process own envelope [{}] for intent [{}]", client.inbox_id(), envelope.id, @@ -562,18 +566,18 @@ impl MlsGroup { Ok(provider.conn_ref().set_group_intent_committed(intent_id)?) } IntentState::Published => { - log::error!("Unexpected behaviour: returned intent state published from process_own_message"); + tracing::error!("Unexpected behaviour: returned intent state published from process_own_message"); Ok(()) } IntentState::Error => { - log::warn!("Intent [{}] moved to error status", intent_id); + tracing::warn!("Intent [{}] moved to error status", intent_id); Ok(provider.conn_ref().set_group_intent_error(intent_id)?) } } } // No matching intent found Ok(None) => { - log::info!( + tracing::info!( "client [{}] is about to process external envelope [{}]", client.inbox_id(), envelope.id @@ -649,7 +653,7 @@ impl MlsGroup { // If the error is retryable we cannot move on to the next message // otherwise you can get into a forked group state. if is_retryable { - log::error!( + tracing::error!( "Aborting message processing for retryable error: {}", error_message ); @@ -661,7 +665,7 @@ impl MlsGroup { if receive_errors.is_empty() { Ok(()) } else { - log::error!("Message processing errors: {:?}", receive_errors); + tracing::error!("Message processing errors: {:?}", receive_errors); Err(GroupError::ReceiveErrors(receive_errors)) } } @@ -692,7 +696,7 @@ impl MlsGroup { return Ok(None); } - log::info!( + tracing::info!( "{}: Storing a transcript message with {} members added and {} members removed and {} metadata changes", self.context.inbox_id(), validated_commit.added_inboxes.len(), @@ -701,7 +705,7 @@ impl MlsGroup { ); let sender_installation_id = validated_commit.actor_installation_id(); let sender_inbox_id = validated_commit.actor_inbox_id(); - // TODO:nm replace with new membership change codec + let payload: GroupUpdated = validated_commit.into(); let encoded_payload = GroupUpdatedCodec::encode(payload)?; let mut encoded_payload_bytes = Vec::new(); @@ -757,9 +761,9 @@ impl MlsGroup { match result { Err(err) => { - log::error!("error getting publish intent data {:?}", err); + tracing::error!("error getting publish intent data {:?}", err); if (intent.publish_attempts + 1) as usize >= MAX_INTENT_PUBLISH_ATTEMPTS { - log::error!("intent {} has reached max publish attempts", intent.id); + tracing::error!("intent {} has reached max publish attempts", intent.id); // TODO: Eventually clean up errored attempts provider .conn_ref() @@ -786,7 +790,7 @@ impl MlsGroup { staged_commit, openmls_group.epoch().as_u64() as i64, )?; - log::debug!( + tracing::debug!( "client [{}] set stored intent [{}] to state `published`", client.inbox_id(), intent.id @@ -797,19 +801,19 @@ impl MlsGroup { .send_group_messages(vec![payload_slice]) .await?; - log::info!( + tracing::info!( "[{}] published intent [{}] of type [{}]", client.inbox_id(), intent.id, intent.kind ); if has_staged_commit { - log::info!("Commit sent. Stopping further publishes for this round"); + tracing::info!("Commit sent. Stopping further publishes for this round"); return Ok(()); } } Ok(None) => { - log::info!("Skipping intent because no publish data returned"); + tracing::info!("Skipping intent because no publish data returned"); let deleter: &dyn Delete = provider.conn_ref(); deleter.delete(intent.id)?; } @@ -1087,7 +1091,7 @@ impl MlsGroup { updates.insert(inbox_id.to_string(), *latest_sequence_id as u64); } (_, _) => { - log::warn!( + tracing::warn!( "Could not find existing sequence ID for inbox {}", inbox_id ); @@ -1143,13 +1147,13 @@ impl MlsGroup { .map(|w| match w { WelcomeMessageInputVersion::V1(w) => { let w = w.installation_key.len() + w.data.len() + w.hpke_public_key.len(); - log::debug!("total welcome message proto bytes={w}"); + tracing::debug!("total welcome message proto bytes={w}"); w } }) .unwrap_or(GRPC_DATA_LIMIT / usize::from(MAX_GROUP_SIZE)); - log::debug!("welcome chunk_size={chunk_size}"); + tracing::debug!("welcome chunk_size={chunk_size}"); let mut futures = vec![]; for welcomes in welcomes.chunks(chunk_size) { futures.push(client.api_client.send_welcome_messages(welcomes)); diff --git a/xmtp_mls/src/groups/validated_commit.rs b/xmtp_mls/src/groups/validated_commit.rs index 03f0b3b98..ead219534 100644 --- a/xmtp_mls/src/groups/validated_commit.rs +++ b/xmtp_mls/src/groups/validated_commit.rs @@ -32,7 +32,7 @@ use crate::{ use super::{ group_membership::{GroupMembership, MembershipDiff}, - group_metadata::{GroupMetadata, GroupMetadataError}, + group_metadata::{DmMembers, GroupMetadata, GroupMetadataError}, group_mutable_metadata::{ find_mutable_metadata_extension, GroupMutableMetadata, GroupMutableMetadataError, }, @@ -210,6 +210,7 @@ pub struct ValidatedCommit { pub removed_inboxes: Vec, pub metadata_changes: MutableMetadataChanges, pub permissions_changed: bool, + pub dm_members: Option, } impl ValidatedCommit { @@ -326,6 +327,7 @@ impl ValidatedCommit { removed_inboxes, metadata_changes, permissions_changed, + dm_members: immutable_metadata.dm_members, }; let policy_set = extract_group_permissions(openmls_group)?; @@ -426,7 +428,7 @@ fn get_latest_group_membership( Proposal::GroupContextExtensions(group_context_extensions) => { let new_group_membership: GroupMembership = extract_group_membership(group_context_extensions.extensions())?; - log::info!( + tracing::info!( "Group context extensions proposal found: {:?}", new_group_membership ); diff --git a/xmtp_mls/src/identity.rs b/xmtp_mls/src/identity.rs index 27eadbfd2..acb481ff0 100644 --- a/xmtp_mls/src/identity.rs +++ b/xmtp_mls/src/identity.rs @@ -1,4 +1,5 @@ use std::array::TryFromSliceError; +use std::sync::atomic::{AtomicBool, Ordering}; use crate::configuration::GROUP_PERMISSIONS_EXTENSION_ID; use crate::retry::RetryableError; @@ -15,9 +16,7 @@ use crate::{ }; use crate::{retryable, Fetch, Store}; use ed25519_dalek::SigningKey; -use ethers::signers::WalletError; -use log::debug; -use log::info; +use openmls::prelude::hash_ref::HashReference; use openmls::prelude::tls_codec::Serialize; use openmls::{ credentials::{errors::BasicCredentialError, BasicCredential, CredentialWithKey}, @@ -29,15 +28,20 @@ use openmls::{ prelude_test::KeyPackage, }; use openmls_basic_credential::SignatureKeyPair; +use openmls_traits::storage::StorageProvider; use openmls_traits::types::CryptoError; use openmls_traits::OpenMlsProvider; use prost::Message; use sha2::{Digest, Sha512}; use thiserror::Error; +use tracing::debug; +use tracing::info; +use xmtp_id::associations::unverified::{UnverifiedInstallationKeySignature, UnverifiedSignature}; +use xmtp_id::scw_verifier::SmartContractSignatureVerifier; use xmtp_id::{ associations::{ builder::{SignatureRequest, SignatureRequestBuilder, SignatureRequestError}, - generate_inbox_id, sign_with_legacy_key, InstallationKeySignature, MemberIdentifier, + generate_inbox_id, sign_with_legacy_key, MemberIdentifier, }, constants::INSTALLATION_KEY_SIGNATURE_CONTEXT, InboxId, @@ -60,6 +64,7 @@ impl IdentityStrategy { self, api_client: &ApiClientWrapper, store: &EncryptedMessageStore, + scw_signature_verifier: &dyn SmartContractSignatureVerifier, ) -> Result { info!("Initializing identity"); let conn = store.conn()?; @@ -98,6 +103,7 @@ impl IdentityStrategy { legacy_signed_private_key, api_client, &provider, + scw_signature_verifier, ) .await } @@ -141,8 +147,6 @@ pub enum IdentityError { #[error("legacy key does not match address")] LegacyKeyMismatch, #[error(transparent)] - WalletError(#[from] WalletError), - #[error(transparent)] OpenMls(#[from] openmls::prelude::Error), #[error(transparent)] StorageError(#[from] crate::storage::StorageError), @@ -160,6 +164,8 @@ pub enum IdentityError { RequiredIdentityNotFound, #[error("error creating new identity: {0}")] NewIdentity(String), + #[error(transparent)] + DieselResult(#[from] diesel::result::Error), } impl RetryableError for IdentityError { @@ -169,17 +175,31 @@ impl RetryableError for IdentityError { Self::WrappedApi(err) => retryable!(err), Self::StorageError(err) => retryable!(err), Self::OpenMlsStorageError(err) => retryable!(err), + Self::DieselResult(err) => retryable!(err), _ => false, } } } -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Identity { pub(crate) inbox_id: InboxId, pub(crate) installation_keys: SignatureKeyPair, pub(crate) credential: OpenMlsCredential, pub(crate) signature_request: Option, + pub(crate) is_ready: AtomicBool, +} + +impl Clone for Identity { + fn clone(&self) -> Self { + Self { + inbox_id: self.inbox_id.clone(), + installation_keys: self.installation_keys.clone(), + credential: self.credential.clone(), + signature_request: self.signature_request(), + is_ready: AtomicBool::new(self.is_ready.load(Ordering::SeqCst)), + } + } } impl Identity { @@ -197,6 +217,7 @@ impl Identity { legacy_signed_private_key: Option>, api_client: &ApiClientWrapper, provider: &XmtpOpenMlsProvider, + scw_signature_verifier: &dyn SmartContractSignatureVerifier, ) -> Result { // check if address is already associated with an inbox_id let address = address.to_lowercase(); @@ -209,7 +230,7 @@ impl Identity { if let Some(associated_inbox_id) = associated_inbox_id { // If an inbox is associated with address, we'd use it to create Identity and ignore the nonce. // We would need a signature from user's wallet. - if associated_inbox_id != &inbox_id { + if *associated_inbox_id != inbox_id { return Err(IdentityError::NewIdentity("Inbox ID mismatch".to_string())); } let builder = SignatureRequestBuilder::new(associated_inbox_id.clone()); @@ -218,13 +239,16 @@ impl Identity { .build(); signature_request - .add_signature(Box::new( - sign_with_installation_key( - signature_request.signature_text(), - sized_installation_key(signature_keys.private())?, - ) - .await?, - )) + .add_signature( + UnverifiedSignature::InstallationKey( + sign_with_installation_key( + signature_request.signature_text(), + sized_installation_key(signature_keys.private())?, + ) + .await?, + ), + scw_signature_verifier, + ) .await?; let identity = Self { @@ -232,6 +256,7 @@ impl Identity { installation_keys: signature_keys, credential: create_credential(associated_inbox_id.clone())?, signature_request: Some(signature_request), + is_ready: AtomicBool::new(false), }; Ok(identity) @@ -253,22 +278,28 @@ impl Identity { .build(); signature_request - .add_signature(Box::new( - sign_with_installation_key( - signature_request.signature_text(), - sized_installation_key(signature_keys.private())?, - ) - .await?, - )) + .add_signature( + UnverifiedSignature::InstallationKey( + sign_with_installation_key( + signature_request.signature_text(), + sized_installation_key(signature_keys.private())?, + ) + .await?, + ), + scw_signature_verifier, + ) .await?; signature_request - .add_signature(Box::new( - sign_with_legacy_key( - signature_request.signature_text(), - legacy_signed_private_key, - ) - .await?, - )) + .add_signature( + UnverifiedSignature::LegacyDelegated( + sign_with_legacy_key( + signature_request.signature_text(), + legacy_signed_private_key, + ) + .await?, + ), + scw_signature_verifier, + ) .await?; // Make sure to register the identity before applying the signature request @@ -277,6 +308,7 @@ impl Identity { installation_keys: signature_keys, credential: create_credential(inbox_id)?, signature_request: None, + is_ready: AtomicBool::new(true), }; identity.register(provider, api_client).await?; @@ -301,13 +333,16 @@ impl Identity { // We can pre-sign the request with an installation key signature, since we have access to the key signature_request - .add_signature(Box::new( - sign_with_installation_key( - signature_request.signature_text(), - sized_installation_key(signature_keys.private())?, - ) - .await?, - )) + .add_signature( + UnverifiedSignature::InstallationKey( + sign_with_installation_key( + signature_request.signature_text(), + sized_installation_key(signature_keys.private())?, + ) + .await?, + ), + scw_signature_verifier, + ) .await?; let identity = Self { @@ -315,6 +350,7 @@ impl Identity { installation_keys: signature_keys, credential: create_credential(inbox_id.clone())?, signature_request: Some(signature_request), + is_ready: AtomicBool::new(false), }; Ok(identity) @@ -330,8 +366,8 @@ impl Identity { } #[allow(dead_code)] - fn is_ready(&self) -> bool { - self.signature_request.is_none() + pub fn is_ready(&self) -> bool { + self.is_ready.load(Ordering::SeqCst) } pub fn signature_request(&self) -> Option { @@ -393,16 +429,7 @@ impl Identity { // This is needed to get to the private key when decrypting welcome messages. let public_init_key = kp.key_package().hpke_init_key().tls_serialize_detached()?; - let key_package_hash_ref = match kp.key_package().hash_ref(provider.crypto()) { - Ok(key_package_hash_ref) => key_package_hash_ref, - Err(_) => return Err(IdentityError::UninitializedIdentity), - }; - - // Serialize the hash reference (with bincode) - let hash_ref = match bincode::serialize(&key_package_hash_ref) { - Ok(hash_ref) => hash_ref, - Err(_) => return Err(IdentityError::UninitializedIdentity), - }; + let hash_ref = serialize_key_package_hash_ref(kp.key_package(), &provider)?; // Store the hash reference, keyed with the public init key provider .storage() @@ -424,31 +451,83 @@ impl Identity { info!("Identity already registered. skipping key package publishing"); return Ok(()); } + + self.rotate_key_package(provider, api_client).await?; + self.is_ready.store(true, Ordering::SeqCst); + + Ok(StoredIdentity::try_from(self)?.store(provider.conn_ref())?) + } + + pub(crate) async fn rotate_key_package( + &self, + provider: &XmtpOpenMlsProvider, + api_client: &ApiClientWrapper, + ) -> Result<(), IdentityError> { let kp = self.new_key_package(provider)?; let kp_bytes = kp.tls_serialize_detached()?; + let conn = provider.conn_ref(); + let hash_ref = serialize_key_package_hash_ref(&kp, provider)?; + let history_id = conn.store_key_package_history_entry(hash_ref)?.id; + let old_id = history_id - 1; + + // Find all key packages that are not the current or previous KPs + // We can delete before uploading because this is either run inside a transaction or is being applied to a brand + // new identity + let old_key_packages = conn.find_key_package_history_entries_before_id(old_id)?; + for kp in old_key_packages { + self.delete_key_package(provider, kp.key_package_hash_ref)?; + } + conn.delete_key_package_history_entries_before_id(old_id)?; + api_client.upload_key_package(kp_bytes, true).await?; + Ok(()) + } - Ok(StoredIdentity::try_from(self)?.store(provider.conn_ref())?) + pub(crate) fn delete_key_package( + &self, + provider: &XmtpOpenMlsProvider, + hash_ref: Vec, + ) -> Result<(), IdentityError> { + let openmls_hash_ref = deserialize_key_package_hash_ref(&hash_ref)?; + provider.storage().delete_key_package(&openmls_hash_ref)?; + + Ok(()) } } +pub(crate) fn serialize_key_package_hash_ref( + kp: &KeyPackage, + provider: &impl OpenMlsProvider, +) -> Result, IdentityError> { + let key_package_hash_ref = kp + .hash_ref(provider.crypto()) + .map_err(|_| IdentityError::UninitializedIdentity)?; + let serialized = bincode::serialize(&key_package_hash_ref) + .map_err(|_| IdentityError::UninitializedIdentity)?; + + Ok(serialized) +} + +fn deserialize_key_package_hash_ref(hash_ref: &[u8]) -> Result { + let key_package_hash_ref: HashReference = + bincode::deserialize(hash_ref).map_err(|_| IdentityError::UninitializedIdentity)?; + + Ok(key_package_hash_ref) +} + async fn sign_with_installation_key( signature_text: String, installation_private_key: &[u8; 32], -) -> Result { +) -> Result { let signing_key: SigningKey = SigningKey::from_bytes(installation_private_key); let verifying_key = signing_key.verifying_key(); let mut prehashed: Sha512 = Sha512::new(); prehashed.update(signature_text.clone()); let sig = signing_key.sign_prehashed(prehashed, Some(INSTALLATION_KEY_SIGNATURE_CONTEXT))?; + let unverified_sig = + UnverifiedInstallationKeySignature::new(sig.to_vec(), verifying_key.as_bytes().to_vec()); - let installation_key_sig = InstallationKeySignature::new( - signature_text.clone(), - sig.to_vec(), - verifying_key.as_bytes().to_vec(), - ); - - Ok(installation_key_sig) + Ok(unverified_sig) } fn sized_installation_key(installation_key: &[u8]) -> Result<&[u8; 32], IdentityError> { diff --git a/xmtp_mls/src/identity_updates.rs b/xmtp_mls/src/identity_updates.rs index b4350eb53..40fe9f5dc 100644 --- a/xmtp_mls/src/identity_updates.rs +++ b/xmtp_mls/src/identity_updates.rs @@ -5,13 +5,20 @@ use crate::{ retry_async, retryable, storage::association_state::StoredAssociationState, }; -use prost::Message; +use futures::future::try_join_all; use thiserror::Error; -use xmtp_id::associations::{ - apply_update, - builder::{SignatureRequest, SignatureRequestBuilder, SignatureRequestError}, - generate_inbox_id, get_state, AssociationError, AssociationState, AssociationStateDiff, - IdentityUpdate, InstallationKeySignature, MemberIdentifier, +use xmtp_id::{ + associations::{ + apply_update, + builder::{SignatureRequest, SignatureRequestBuilder, SignatureRequestError}, + generate_inbox_id, get_state, + unverified::{ + UnverifiedIdentityUpdate, UnverifiedInstallationKeySignature, UnverifiedSignature, + }, + AssociationError, AssociationState, AssociationStateDiff, IdentityUpdate, MemberIdentifier, + SignatureError, + }, + scw_verifier::SmartContractSignatureVerifier, }; use crate::{ @@ -83,6 +90,24 @@ where Ok(needs_update) } + pub async fn batch_get_association_state>( + &self, + conn: &DbConnection, + identifiers: &[(InboxId, Option)], + ) -> Result, ClientError> { + let association_states = try_join_all( + identifiers + .iter() + .map(|(inbox_id, to_sequence_id)| { + self.get_association_state(conn, inbox_id, *to_sequence_id) + }) + .collect::>(), + ) + .await?; + + Ok(association_states) + } + pub async fn get_latest_association_state>( &self, conn: &DbConnection, @@ -106,8 +131,10 @@ where .last() .ok_or::(AssociationError::MissingIdentityUpdate.into())? .sequence_id; - if to_sequence_id.is_some() && to_sequence_id != Some(last_sequence_id) { - return Err(AssociationError::MissingIdentityUpdate.into()); + if let Some(to_sequence_id) = to_sequence_id { + if to_sequence_id != last_sequence_id { + return Err(AssociationError::MissingIdentityUpdate.into()); + } } if let Some(association_state) = @@ -116,11 +143,17 @@ where return Ok(association_state); } - let updates = updates + let unverified_updates = updates .into_iter() - .map(IdentityUpdate::try_from) - .collect::, AssociationError>>()?; - let association_state = get_state(updates).await?; + .map(UnverifiedIdentityUpdate::try_from) + .collect::, AssociationError>>()?; + let updates = verify_updates( + unverified_updates, + self.smart_contract_signature_verifier().as_ref(), + ) + .await?; + + let association_state = get_state(updates)?; StoredAssociationState::write_to_cache( conn, @@ -139,7 +172,7 @@ where starting_sequence_id: Option, ending_sequence_id: Option, ) -> Result { - log::debug!( + tracing::debug!( "Computing diff for {:?} from {:?} to {:?}", inbox_id.as_ref(), starting_sequence_id, @@ -164,7 +197,7 @@ where && last_sequence_id.is_some() && last_sequence_id != ending_sequence_id { - log::error!( + tracing::error!( "Did not find the expected last sequence id. Expected: {:?}, Found: {:?}", ending_sequence_id, last_sequence_id @@ -172,17 +205,22 @@ where return Err(AssociationError::MissingIdentityUpdate.into()); } - let incremental_updates = incremental_updates + let unverified_incremental_updates: Vec = incremental_updates .into_iter() .map(|update| update.try_into()) - .collect::, AssociationError>>()?; + .collect::, AssociationError>>()?; + let incremental_updates = verify_updates( + unverified_incremental_updates, + self.smart_contract_signature_verifier().as_ref(), + ) + .await?; let mut final_state = initial_state.clone(); for update in incremental_updates { - final_state = apply_update(final_state, update).await?; + final_state = apply_update(final_state, update)?; } - log::debug!("Final state at {:?}: {:?}", last_sequence_id, final_state); + tracing::debug!("Final state at {:?}: {:?}", last_sequence_id, final_state); if let Some(last_sequence_id) = last_sequence_id { StoredAssociationState::write_to_cache( conn, @@ -211,14 +249,19 @@ where .add_association(installation_public_key.to_vec().into(), member_identifier) .build(); + let sig_bytes = self + .identity() + .sign(signature_request.signature_text())? + .to_vec(); // We can pre-sign the request with an installation key signature, since we have access to the key signature_request - .add_signature(Box::new(InstallationKeySignature::new( - signature_request.signature_text(), - // TODO: Move this to a method on the new identity - self.identity().sign(signature_request.signature_text())?, - self.installation_public_key(), - ))) + .add_signature( + UnverifiedSignature::InstallationKey(UnverifiedInstallationKeySignature::new( + sig_bytes, + installation_public_key.to_vec(), + )), + self.smart_contract_signature_verifier().as_ref(), + ) .await?; Ok(signature_request) @@ -229,7 +272,7 @@ where existing_wallet_address: String, new_wallet_address: String, ) -> Result { - log::info!("Associating new wallet with inbox_id {}", self.inbox_id()); + tracing::info!("Associating new wallet with inbox_id {}", self.inbox_id()); let inbox_id = self.inbox_id(); let builder = SignatureRequestBuilder::new(inbox_id); @@ -328,7 +371,7 @@ where new_group_membership: &GroupMembership, membership_diff: &MembershipDiff<'_>, ) -> Result { - log::info!( + tracing::info!( "Getting installation diff. Old: {:?}. New {:?}", old_group_membership, new_group_membership @@ -410,7 +453,7 @@ pub async fn load_identity_updates( if inbox_ids.is_empty() { return Ok(HashMap::new()); } - log::debug!("Fetching identity updates for: {:?}", inbox_ids); + tracing::debug!("Fetching identity updates for: {:?}", inbox_ids); let existing_sequence_ids = conn.get_latest_sequence_id(&inbox_ids)?; let filters: Vec = inbox_ids @@ -434,7 +477,7 @@ pub async fn load_identity_updates( inbox_id: inbox_id.clone(), sequence_id: update.sequence_id as i64, server_timestamp_ns: update.server_timestamp_ns as i64, - payload: update.update.to_proto().encode_to_vec(), + payload: update.update.into(), }) }) .collect::>(); @@ -443,13 +486,26 @@ pub async fn load_identity_updates( Ok(updates) } +async fn verify_updates( + updates: Vec, + scw_verifier: &dyn SmartContractSignatureVerifier, +) -> Result, SignatureError> { + try_join_all( + updates + .iter() + .map(|update| update.to_verified(scw_verifier)), + ) + .await +} + #[cfg(test)] pub(crate) mod tests { - use ethers::signers::LocalWallet; - use tracing_test::traced_test; use xmtp_cryptography::utils::generate_local_wallet; use xmtp_id::{ - associations::{builder::SignatureRequest, AssociationState, RecoverableEcdsaSignature}, + associations::{ + builder::SignatureRequest, test_utils::add_wallet_signature, AssociationState, + MemberIdentifier, + }, InboxOwner, }; @@ -464,24 +520,6 @@ pub(crate) mod tests { use super::load_identity_updates; - pub(crate) async fn sign_with_wallet( - wallet: &LocalWallet, - signature_request: &mut SignatureRequest, - ) { - let wallet_signature: Vec = wallet - .sign(signature_request.signature_text().as_str()) - .unwrap() - .into(); - - signature_request - .add_signature(Box::new(RecoverableEcdsaSignature::new( - signature_request.signature_text(), - wallet_signature, - ))) - .await - .unwrap(); - } - async fn get_association_state( client: &Client, inbox_id: String, @@ -520,7 +558,7 @@ pub(crate) mod tests { .unwrap(); let inbox_id = signature_request.inbox_id(); - sign_with_wallet(&wallet, &mut signature_request).await; + add_wallet_signature(&mut signature_request, &wallet).await; client .apply_signature_request(signature_request) @@ -546,8 +584,8 @@ pub(crate) mod tests { .associate_wallet(wallet_address.clone(), wallet_2_address.clone()) .unwrap(); - sign_with_wallet(&wallet, &mut add_association_request).await; - sign_with_wallet(&wallet_2, &mut add_association_request).await; + add_wallet_signature(&mut add_association_request, &wallet).await; + add_wallet_signature(&mut add_association_request, &wallet_2).await; client .apply_signature_request(add_association_request) @@ -556,62 +594,70 @@ pub(crate) mod tests { let association_state = get_association_state(&client, client.inbox_id()).await; + let members = + association_state.members_by_parent(&MemberIdentifier::Address(wallet_address.clone())); + // Those members should have timestamps + for member in members { + assert!(member.client_timestamp_ns.is_some()); + } + assert_eq!(association_state.members().len(), 3); assert_eq!(association_state.recovery_address(), &wallet_address); assert!(association_state.get(&wallet_2_address.into()).is_some()); } - #[tokio::test] - #[traced_test] - async fn cache_association_state() { - let wallet = generate_local_wallet(); - let wallet_2 = generate_local_wallet(); - let wallet_address = wallet.get_address(); - let wallet_2_address = wallet_2.get_address(); - let client = ClientBuilder::new_test_client(&wallet).await; - let inbox_id = client.inbox_id(); + #[test] + fn cache_association_state() { + crate::traced_test(|| async { + let wallet = generate_local_wallet(); + let wallet_2 = generate_local_wallet(); + let wallet_address = wallet.get_address(); + let wallet_2_address = wallet_2.get_address(); + let client = ClientBuilder::new_test_client(&wallet).await; + let inbox_id = client.inbox_id(); - get_association_state(&client, inbox_id.clone()).await; + get_association_state(&client, inbox_id.clone()).await; - assert_logged!("Loaded association", 0); - assert_logged!("Wrote association", 1); + assert_logged!("Loaded association", 0); + assert_logged!("Wrote association", 1); - let association_state = get_association_state(&client, inbox_id.clone()).await; + let association_state = get_association_state(&client, inbox_id.clone()).await; - assert_eq!(association_state.members().len(), 2); - assert_eq!(association_state.recovery_address(), &wallet_address); - assert!(association_state - .get(&wallet_address.clone().into()) - .is_some()); + assert_eq!(association_state.members().len(), 2); + assert_eq!(association_state.recovery_address(), &wallet_address); + assert!(association_state + .get(&wallet_address.clone().into()) + .is_some()); - assert_logged!("Loaded association", 1); - assert_logged!("Wrote association", 1); + assert_logged!("Loaded association", 1); + assert_logged!("Wrote association", 1); - let mut add_association_request = client - .associate_wallet(wallet_address.clone(), wallet_2_address.clone()) - .unwrap(); + let mut add_association_request = client + .associate_wallet(wallet_address.clone(), wallet_2_address.clone()) + .unwrap(); - sign_with_wallet(&wallet, &mut add_association_request).await; - sign_with_wallet(&wallet_2, &mut add_association_request).await; + add_wallet_signature(&mut add_association_request, &wallet).await; + add_wallet_signature(&mut add_association_request, &wallet_2).await; - client - .apply_signature_request(add_association_request) - .await - .unwrap(); + client + .apply_signature_request(add_association_request) + .await + .unwrap(); - get_association_state(&client, inbox_id.clone()).await; + get_association_state(&client, inbox_id.clone()).await; - assert_logged!("Loaded association", 1); - assert_logged!("Wrote association", 2); + assert_logged!("Loaded association", 1); + assert_logged!("Wrote association", 2); - let association_state = get_association_state(&client, inbox_id.clone()).await; + let association_state = get_association_state(&client, inbox_id.clone()).await; - assert_logged!("Loaded association", 2); - assert_logged!("Wrote association", 2); + assert_logged!("Loaded association", 2); + assert_logged!("Wrote association", 2); - assert_eq!(association_state.members().len(), 3); - assert_eq!(association_state.recovery_address(), &wallet_address); - assert!(association_state.get(&wallet_2_address.into()).is_some()); + assert_eq!(association_state.members().len(), 3); + assert_eq!(association_state.recovery_address(), &wallet_address); + assert!(association_state.get(&wallet_2_address.into()).is_some()); + }); } #[tokio::test] @@ -659,7 +705,7 @@ pub(crate) mod tests { let inbox_id = signature_request.inbox_id(); inbox_ids.push(inbox_id.clone()); - sign_with_wallet(&wallet, &mut signature_request).await; + add_wallet_signature(&mut signature_request, &wallet).await; client .apply_signature_request(signature_request) .await @@ -669,8 +715,8 @@ pub(crate) mod tests { .associate_wallet(wallet.get_address(), new_wallet.get_address()) .unwrap(); - sign_with_wallet(&wallet, &mut add_association_request).await; - sign_with_wallet(&new_wallet, &mut add_association_request).await; + add_wallet_signature(&mut add_association_request, &wallet).await; + add_wallet_signature(&mut add_association_request, &new_wallet).await; client .apply_signature_request(add_association_request) @@ -749,8 +795,8 @@ pub(crate) mod tests { .associate_wallet(recovery_wallet.get_address(), second_wallet.get_address()) .unwrap(); - sign_with_wallet(&recovery_wallet, &mut add_wallet_signature_request).await; - sign_with_wallet(&second_wallet, &mut add_wallet_signature_request).await; + add_wallet_signature(&mut add_wallet_signature_request, &recovery_wallet).await; + add_wallet_signature(&mut add_wallet_signature_request, &second_wallet).await; client .apply_signature_request(add_wallet_signature_request) @@ -774,7 +820,8 @@ pub(crate) mod tests { .revoke_wallets(vec![second_wallet.get_address()]) .await .unwrap(); - sign_with_wallet(&recovery_wallet, &mut revoke_signature_request).await; + add_wallet_signature(&mut revoke_signature_request, &recovery_wallet).await; + client .apply_signature_request(revoke_signature_request) .await @@ -809,7 +856,7 @@ pub(crate) mod tests { .revoke_installations(vec![client2.installation_public_key()]) .await .unwrap(); - sign_with_wallet(&wallet, &mut revoke_installation_request).await; + add_wallet_signature(&mut revoke_installation_request, &wallet).await; client1 .apply_signature_request(revoke_installation_request) .await diff --git a/xmtp_mls/src/lib.rs b/xmtp_mls/src/lib.rs index eedf39233..3ee3bf278 100644 --- a/xmtp_mls/src/lib.rs +++ b/xmtp_mls/src/lib.rs @@ -6,64 +6,99 @@ pub mod builder; pub mod client; pub mod codecs; pub mod configuration; -pub mod credential; pub mod groups; mod hpke; pub mod identity; mod identity_updates; mod mutex_registry; -pub mod owner; pub mod retry; pub mod storage; pub mod subscriptions; pub mod types; pub mod utils; -pub mod verified_key_package; pub mod verified_key_package_v2; mod xmtp_openmls_provider; pub use client::{Client, Network}; use storage::{DuplicateItem, StorageError}; -use xmtp_cryptography::signature::{RecoverableSignature, SignatureError}; use xmtp_proto::api_client::{ClientWithMetadata, XmtpIdentityClient, XmtpMlsClient}; +pub use trait_impls::*; + /// XMTP Api Super Trait /// Implements all Trait Network APIs for convenience. -#[cfg(not(test))] -pub trait XmtpApi -where - Self: XmtpMlsClient + XmtpIdentityClient + ClientWithMetadata, -{ -} -#[cfg(not(test))] -impl XmtpApi for T where T: XmtpMlsClient + XmtpIdentityClient + ClientWithMetadata + ?Sized {} +mod trait_impls { + pub use inner::*; -#[cfg(test)] -pub trait XmtpApi -where - Self: XmtpMlsClient + XmtpIdentityClient + XmtpTestClient + ClientWithMetadata, -{ -} + // native, release + #[cfg(not(test))] + mod inner { + use xmtp_proto::api_client::{ + ClientWithMetadata, XmtpIdentityClient, XmtpMlsClient, XmtpMlsStreams, + }; -#[cfg(test)] -impl XmtpApi for T where - T: XmtpMlsClient + XmtpIdentityClient + XmtpTestClient + ClientWithMetadata + ?Sized -{ + pub trait XmtpApi + where + Self: XmtpMlsClient + + XmtpMlsStreams + + XmtpIdentityClient + + ClientWithMetadata + + Send + + Sync, + { + } + impl XmtpApi for T where + T: XmtpMlsClient + + XmtpMlsStreams + + XmtpIdentityClient + + ClientWithMetadata + + Send + + Sync + + ?Sized + { + } + } + + // test, native + #[cfg(test)] + mod inner { + use xmtp_proto::api_client::{ + ClientWithMetadata, XmtpIdentityClient, XmtpMlsClient, XmtpMlsStreams, + }; + + pub trait XmtpApi + where + Self: XmtpMlsClient + + XmtpMlsStreams + + XmtpIdentityClient + + crate::XmtpTestClient + + ClientWithMetadata + + Send + + Sync, + { + } + impl XmtpApi for T where + T: XmtpMlsClient + + XmtpMlsStreams + + XmtpIdentityClient + + crate::XmtpTestClient + + ClientWithMetadata + + Send + + Sync + + ?Sized + { + } + } } #[cfg(any(test, feature = "test-utils", feature = "bench"))] -#[async_trait::async_trait] -pub trait XmtpTestClient { +#[trait_variant::make(XmtpTestClient: Send)] +pub trait LocalXmtpTestClient { async fn create_local() -> Self; async fn create_dev() -> Self; } -pub trait InboxOwner { - /// Get address of the wallet. - fn get_address(&self) -> String; - /// Sign text with the wallet. - fn sign(&self, text: &str) -> Result; -} +pub use xmtp_id::InboxOwner; /// Inserts a model to the underlying data store, erroring if it already exists pub trait Store { @@ -87,34 +122,136 @@ pub trait Delete { fn delete(&self, key: Self::Key) -> Result; } +#[cfg(test)] +pub use self::tests::traced_test; + #[cfg(test)] mod tests { - use log::LevelFilter; - use tracing_test::traced_test; + use parking_lot::Mutex; + use std::{io, sync::Arc}; + use tracing_subscriber::{ + filter::EnvFilter, + fmt::{self, MakeWriter}, + prelude::*, + }; // Execute once before any tests are run #[ctor::ctor] - // Capture traces in a variable that can be checked in tests, as well as outputting them to stdout on test failure - #[traced_test] fn setup() { - // Capture logs (e.g. log::info!()) as traces too - let _ = tracing_log::LogTracer::init_with_filter(LevelFilter::Debug); + let filter = EnvFilter::builder() + .with_default_directive(tracing::metadata::LevelFilter::INFO.into()) + .from_env_lossy(); + + tracing_subscriber::registry() + .with(fmt::layer()) + .with(filter) + .init(); + } + + thread_local! { + pub static LOG_BUFFER: TestWriter = TestWriter::new(); + } + + /// Thread local writer which stores logs in memory + pub struct TestWriter(Arc>>); + impl TestWriter { + pub fn new() -> Self { + Self(Arc::new(Mutex::new(vec![]))) + } + + pub fn as_string(&self) -> String { + let buf = self.0.lock(); + String::from_utf8(buf.clone()).expect("Not valid UTF-8") + } + + pub fn clear(&self) { + let mut buf = self.0.lock(); + buf.clear(); + } + pub fn flush(&self) { + let mut buf = self.0.lock(); + std::io::Write::flush(&mut *buf).unwrap(); + } + } + + impl io::Write for TestWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + let mut this = self.0.lock(); + // still print logs for tests + print!("{}", String::from_utf8_lossy(buf)); + Vec::::write(&mut this, buf) + } + + fn flush(&mut self) -> io::Result<()> { + let mut this = self.0.lock(); + Vec::::flush(&mut this) + } + } + + impl Clone for TestWriter { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + + impl MakeWriter<'_> for TestWriter { + type Writer = TestWriter; + + fn make_writer(&self) -> Self::Writer { + self.clone() + } } - /// Note: tests that use this must have the #[traced_test] attribute + /// Only works with current-thread + pub fn traced_test(f: impl Fn() -> Fut) + where + Fut: futures::Future, + { + LOG_BUFFER.with(|buf| { + let rt = tokio::runtime::Builder::new_current_thread() + .thread_name("tracing-test") + .enable_time() + .enable_io() + .build() + .unwrap(); + buf.clear(); + + let subscriber = fmt::Subscriber::builder() + .with_env_filter(format!("{}=debug", env!("CARGO_PKG_NAME"))) + .with_writer(buf.clone()) + .with_level(true) + .with_ansi(false) + .finish(); + + let dispatch = tracing::Dispatch::new(subscriber); + tracing::dispatcher::with_default(&dispatch, || { + rt.block_on(f()); + }); + + buf.clear(); + }); + } + + /// macro that can assert logs in tests. + /// Note: tests that use this must be used in `traced_test` function + /// and only with tokio's `current` runtime. #[macro_export] macro_rules! assert_logged { ( $search:expr , $occurrences:expr ) => { - logs_assert(|lines: &[&str]| { - let actual = lines.iter().filter(|line| line.contains($search)).count(); + $crate::tests::LOG_BUFFER.with(|buf| { + let lines = { + buf.flush(); + buf.as_string() + }; + let lines = lines.lines(); + let actual = lines.filter(|line| line.contains($search)).count(); if actual != $occurrences { - return Err(format!( + panic!( "Expected '{}' to be logged {} times, but was logged {} times instead", $search, $occurrences, actual - )); + ); } - Ok(()) - }); + }) }; } diff --git a/xmtp_mls/src/owner/evm_owner.rs b/xmtp_mls/src/owner/evm_owner.rs deleted file mode 100644 index bbf4fbf19..000000000 --- a/xmtp_mls/src/owner/evm_owner.rs +++ /dev/null @@ -1,16 +0,0 @@ -pub use ethers::signers::{LocalWallet, Signer}; - -use xmtp_cryptography::signature::{h160addr_to_string, RecoverableSignature, SignatureError}; - -use crate::InboxOwner; - -impl InboxOwner for LocalWallet { - fn get_address(&self) -> String { - h160addr_to_string(self.address()) - } - - fn sign(&self, text: &str) -> Result { - let message_hash = ethers_core::utils::hash_message(text); - Ok(self.sign_hash(message_hash)?.to_vec().into()) - } -} diff --git a/xmtp_mls/src/owner/mod.rs b/xmtp_mls/src/owner/mod.rs deleted file mode 100644 index 1b15ea292..000000000 --- a/xmtp_mls/src/owner/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod evm_owner; diff --git a/xmtp_mls/src/retry.rs b/xmtp_mls/src/retry.rs index fed9020a1..6b3140e5e 100644 --- a/xmtp_mls/src/retry.rs +++ b/xmtp_mls/src/retry.rs @@ -19,7 +19,6 @@ use std::time::Duration; use rand::Rng; -use smart_default::SmartDefault; /// Specifies which errors are retryable. /// All Errors are not retryable by-default. @@ -28,19 +27,26 @@ pub trait RetryableError: std::error::Error { } /// Options to specify how to retry a function -#[derive(SmartDefault, Debug, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct Retry { - #[default = 5] retries: usize, - #[default(_code = "std::time::Duration::from_millis(50)")] duration: std::time::Duration, - #[default = 3] // The amount to multiply the duration on each subsequent attempt multiplier: u32, - #[default = 25] max_jitter_ms: usize, } +impl Default for Retry { + fn default() -> Self { + Self { + retries: 5, + duration: std::time::Duration::from_millis(50), + multiplier: 3, + max_jitter_ms: 25, + } + } +} + impl Retry { /// Get the number of retries this is configured with. pub fn retries(&self) -> usize { @@ -115,80 +121,11 @@ impl Retry { } } -/// Retry a function, specifying the strategy with $retry. -/// -/// # Example -/// ``` -/// use thiserror::Error; -/// use xmtp_mls::{retry_sync, retry::{RetryableError, Retry}}; -/// -/// #[derive(Debug, Error)] -/// enum MyError { -/// #[error("A retryable error")] -/// Retryable, -/// #[error("An error we don't want to retry")] -/// NotRetryable -/// } -/// -/// impl RetryableError for MyError { -/// fn is_retryable(&self) -> bool { -/// match self { -/// Self::Retryable => true, -/// _=> false, -/// } -/// } -/// } -/// -/// fn fallable_fn(i: usize) -> Result<(), MyError> { -/// if i == 2 { -/// return Ok(()); -/// } -/// -/// Err(MyError::Retryable) -/// } -/// -/// fn main() { -/// let mut i = 0; -/// retry_sync!(Retry::default(), (|| -> Result<(), MyError> { -/// let res = fallable_fn(i); -/// i += 1; -/// res -/// })).unwrap(); -/// -/// } -/// ``` -#[macro_export] -macro_rules! retry_sync { - ($retry: expr, $code: tt) => {{ - #[allow(unused)] - use $crate::retry::RetryableError; - let mut attempts = 0; - tracing::trace_span!("retry").in_scope(|| loop { - #[allow(clippy::redundant_closure_call)] - match $code() { - Ok(v) => break Ok(v), - Err(e) => { - if (&e).is_retryable() && attempts < $retry.retries() { - log::info!( - "retrying function that failed with error=`{}`", - e.to_string() - ); - attempts += 1; - std::thread::sleep($retry.duration(attempts)); - } else { - break Err(e); - } - } - } - }) - }}; -} - /// Retry but for an async context /// ``` /// use xmtp_mls::{retry_async, retry::{RetryableError, Retry}}; /// use thiserror::Error; -/// use flume::bounded; +/// use tokio::sync::mpsc; /// /// #[derive(Debug, Error)] /// enum MyError { @@ -207,8 +144,8 @@ macro_rules! retry_sync { /// } /// } /// -/// async fn fallable_fn(rx: &flume::Receiver) -> Result<(), MyError> { -/// if rx.recv_async().await.unwrap() == 2 { +/// async fn fallable_fn(rx: &mut mpsc::Receiver) -> Result<(), MyError> { +/// if rx.recv().await.unwrap() == 2 { /// return Ok(()); /// } /// Err(MyError::Retryable) @@ -216,14 +153,14 @@ macro_rules! retry_sync { /// /// #[tokio::main] /// async fn main() -> Result<(), MyError> { -/// -/// let (tx, rx) = flume::bounded(3); +/// +/// let (tx, mut rx) = mpsc::channel(3); /// /// for i in 0..3 { -/// tx.send(i).unwrap(); +/// tx.send(i).await.unwrap(); /// } /// retry_async!(Retry::default(), (async { -/// fallable_fn(&rx.clone()).await +/// fallable_fn(&mut rx).await /// })) /// } /// ``` @@ -243,11 +180,14 @@ macro_rules! retry_async { Ok(v) => break Ok(v), Err(e) => { if (&e).is_retryable() && attempts < $retry.retries() { - log::warn!("retrying function that failed with error={}", e.to_string()); + tracing::warn!( + "retrying function that failed with error={}", + e.to_string() + ); attempts += 1; tokio::time::sleep($retry.duration(attempts)).await; } else { - log::info!("error is not retryable. {:?}", e); + tracing::info!("error is not retryable. {:?}", e); break Err(e); } } @@ -280,6 +220,7 @@ impl RetryableError for xmtp_proto::api_client::Error { mod tests { use super::*; use thiserror::Error; + use tokio::sync::mpsc; #[derive(Debug, Error)] enum SomeError { @@ -304,8 +245,8 @@ mod tests { Err(SomeError::ARetryableError) } - #[test] - fn it_retries_twice_and_succeeds() { + #[tokio::test] + async fn it_retries_twice_and_succeeds() { let mut i = 0; let mut test_fn = || -> Result<(), SomeError> { if i == 2 { @@ -316,11 +257,11 @@ mod tests { Ok(()) }; - retry_sync!(Retry::default(), test_fn).unwrap(); + retry_async!(Retry::default(), (async { test_fn() })).unwrap(); } - #[test] - fn it_works_with_random_args() { + #[tokio::test] + async fn it_works_with_random_args() { let mut i = 0; let list = vec!["String".into(), "Foo".into()]; let mut test_fn = || -> Result<(), SomeError> { @@ -331,37 +272,37 @@ mod tests { retryable_with_args(i, "Hello".to_string(), &list) }; - retry_sync!(Retry::default(), test_fn).unwrap(); + retry_async!(Retry::default(), (async { test_fn() })).unwrap(); } - #[test] - fn it_fails_on_three_retries() { + #[tokio::test] + async fn it_fails_on_three_retries() { let closure = || -> Result<(), SomeError> { retry_error_fn()?; Ok(()) }; - let result: Result<(), SomeError> = retry_sync!(Retry::default(), (closure)); + let result: Result<(), SomeError> = retry_async!(Retry::default(), (async { closure() })); assert!(result.is_err()) } - #[test] - fn it_only_runs_non_retryable_once() { + #[tokio::test] + async fn it_only_runs_non_retryable_once() { let mut attempts = 0; let mut test_fn = || -> Result<(), SomeError> { attempts += 1; Err(SomeError::DontRetryThis) }; - let _r = retry_sync!(Retry::default(), test_fn); + let _r = retry_async!(Retry::default(), (async { test_fn() })); assert_eq!(attempts, 1); } #[tokio::test] async fn it_works_async() { - async fn retryable_async_fn(rx: &flume::Receiver) -> Result<(), SomeError> { - let val = rx.recv_async().await.unwrap(); + async fn retryable_async_fn(rx: &mut mpsc::Receiver) -> Result<(), SomeError> { + let val = rx.recv().await.unwrap(); if val == 2 { return Ok(()); } @@ -370,14 +311,14 @@ mod tests { Err(SomeError::ARetryableError) } - let (tx, rx) = flume::bounded(3); + let (tx, mut rx) = mpsc::channel(3); for i in 0..3 { - tx.send(i).unwrap(); + tx.send(i).await.unwrap(); } retry_async!( Retry::default(), - (async { retryable_async_fn(&rx.clone()).await }) + (async { retryable_async_fn(&mut rx).await }) ) .unwrap(); assert!(rx.is_empty()); diff --git a/xmtp_mls/src/storage/encrypted_store/association_state.rs b/xmtp_mls/src/storage/encrypted_store/association_state.rs index 079c6ec47..a13398dba 100644 --- a/xmtp_mls/src/storage/encrypted_store/association_state.rs +++ b/xmtp_mls/src/storage/encrypted_store/association_state.rs @@ -48,7 +48,7 @@ impl StoredAssociationState { .store_or_ignore(conn); if result.is_ok() { - log::debug!( + tracing::debug!( "Wrote association state to cache: {} {}", inbox_id, sequence_id @@ -79,7 +79,7 @@ impl StoredAssociationState { .transpose(); if let Ok(Some(_)) = result { - log::debug!( + tracing::debug!( "Loaded association state from cache: {} {}", inbox_id, sequence_id diff --git a/xmtp_mls/src/storage/encrypted_store/consent_record.rs b/xmtp_mls/src/storage/encrypted_store/consent_record.rs new file mode 100644 index 000000000..1a6cd5ef4 --- /dev/null +++ b/xmtp_mls/src/storage/encrypted_store/consent_record.rs @@ -0,0 +1,196 @@ +use crate::{impl_store, storage::StorageError}; + +use super::{ + db_connection::DbConnection, + schema::consent_records::{self, dsl}, +}; +use diesel::{ + backend::Backend, + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + prelude::*, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Integer, + sqlite::Sqlite, + upsert::excluded, +}; +use serde::{Deserialize, Serialize}; + +/// StoredConsentRecord holds a serialized ConsentRecord +#[derive(Insertable, Queryable, Debug, Clone, PartialEq, Eq)] +#[diesel(table_name = consent_records)] +#[diesel(primary_key(entity_type, entity))] +pub struct StoredConsentRecord { + /// Enum, [`ConsentType`] representing the type of consent (group_id inbox_id, etc..) + pub entity_type: ConsentType, + /// Enum, [`ConsentState`] representing the state of consent (allowed, denied, etc..) + pub state: ConsentState, + /// The entity of what was consented (0x00 etc..) + pub entity: String, +} + +impl StoredConsentRecord { + pub fn new(entity_type: ConsentType, state: ConsentState, entity: String) -> Self { + Self { + entity_type, + state, + entity, + } + } +} + +impl_store!(StoredConsentRecord, consent_records); + +impl DbConnection { + /// Returns the consent_records for the given entity up + pub fn get_consent_record( + &self, + entity: String, + entity_type: ConsentType, + ) -> Result, StorageError> { + Ok(self.raw_query(|conn| { + dsl::consent_records + .filter(dsl::entity.eq(entity)) + .filter(dsl::entity_type.eq(entity_type)) + .first(conn) + .optional() + })?) + } + + /// Insert consent_records, and replace existing entries + pub fn insert_or_replace_consent_records( + &self, + records: Vec, + ) -> Result<(), StorageError> { + self.raw_query(|conn| { + conn.transaction::<_, diesel::result::Error, _>(|conn| { + for record in records.iter() { + diesel::insert_into(dsl::consent_records) + .values(record) + .on_conflict((dsl::entity_type, dsl::entity)) + .do_update() + .set(dsl::state.eq(excluded(dsl::state))) + .execute(conn)?; + } + Ok(()) + }) + })?; + + Ok(()) + } +} + +#[repr(i32)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq, AsExpression, FromSqlRow)] +#[diesel(sql_type = Integer)] +/// Type of consent record stored +pub enum ConsentType { + /// Consent is for a group + GroupId = 1, + /// Consent is for an inbox + InboxId = 2, + /// Consent is for an address + Address = 3, +} + +impl ToSql for ConsentType +where + i32: ToSql, +{ + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result { + out.set_value(*self as i32); + Ok(IsNull::No) + } +} + +impl FromSql for ConsentType +where + i32: FromSql, +{ + fn from_sql(bytes: ::RawValue<'_>) -> deserialize::Result { + match i32::from_sql(bytes)? { + 1 => Ok(ConsentType::GroupId), + 2 => Ok(ConsentType::InboxId), + 3 => Ok(ConsentType::Address), + x => Err(format!("Unrecognized variant {}", x).into()), + } + } +} + +#[repr(i32)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, Eq, PartialEq, AsExpression, FromSqlRow)] +#[diesel(sql_type = Integer)] +/// The state of the consent +pub enum ConsentState { + /// Consent is unknown + Unknown = 0, + /// Consent is allowed + Allowed = 1, + /// Consent is denied + Denied = 2, +} + +impl ToSql for ConsentState +where + i32: ToSql, +{ + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result { + out.set_value(*self as i32); + Ok(IsNull::No) + } +} + +impl FromSql for ConsentState +where + i32: FromSql, +{ + fn from_sql(bytes: ::RawValue<'_>) -> deserialize::Result { + match i32::from_sql(bytes)? { + 0 => Ok(ConsentState::Unknown), + 1 => Ok(ConsentState::Allowed), + 2 => Ok(ConsentState::Denied), + x => Err(format!("Unrecognized variant {}", x).into()), + } + } +} + +#[cfg(test)] +mod tests { + use crate::storage::encrypted_store::tests::with_connection; + + use super::*; + + fn generate_consent_record( + entity_type: ConsentType, + state: ConsentState, + entity: String, + ) -> StoredConsentRecord { + StoredConsentRecord { + entity_type, + state, + entity, + } + } + + #[test] + fn insert_and_read() { + with_connection(|conn| { + let inbox_id = "inbox_1"; + let consent_record = generate_consent_record( + ConsentType::InboxId, + ConsentState::Denied, + inbox_id.to_string(), + ); + let consent_record_entity = consent_record.entity.clone(); + + conn.insert_or_replace_consent_records(vec![consent_record]) + .expect("should store without error"); + + let consent_record = conn + .get_consent_record(inbox_id.to_owned(), ConsentType::InboxId) + .expect("query should work"); + + assert_eq!(consent_record.unwrap().entity, consent_record_entity); + }); + } +} diff --git a/xmtp_mls/src/storage/encrypted_store/group.rs b/xmtp_mls/src/storage/encrypted_store/group.rs index e9aff785c..f790f81b7 100644 --- a/xmtp_mls/src/storage/encrypted_store/group.rs +++ b/xmtp_mls/src/storage/encrypted_store/group.rs @@ -39,6 +39,8 @@ pub struct StoredGroup { pub added_by_inbox_id: String, /// The sequence id of the welcome message pub welcome_id: Option, + /// The inbox_id of the DM target + pub dm_inbox_id: Option, } impl_fetch!(StoredGroup, groups, Vec); @@ -53,6 +55,7 @@ impl StoredGroup { added_by_inbox_id: String, welcome_id: i64, purpose: Purpose, + dm_inbox_id: Option, ) -> Self { Self { id, @@ -62,6 +65,7 @@ impl StoredGroup { purpose, added_by_inbox_id, welcome_id: Some(welcome_id), + dm_inbox_id, } } @@ -71,6 +75,7 @@ impl StoredGroup { created_at_ns: i64, membership_state: GroupMembershipState, added_by_inbox_id: String, + dm_inbox_id: Option, ) -> Self { Self { id, @@ -80,6 +85,7 @@ impl StoredGroup { purpose: Purpose::Conversation, added_by_inbox_id, welcome_id: None, + dm_inbox_id, } } @@ -98,6 +104,7 @@ impl StoredGroup { purpose: Purpose::Sync, added_by_inbox_id: "".into(), welcome_id: None, + dm_inbox_id: None, } } } @@ -110,6 +117,7 @@ impl DbConnection { created_after_ns: Option, created_before_ns: Option, limit: Option, + include_dm_groups: bool, ) -> Result, StorageError> { let mut query = dsl::groups.order(dsl::created_at_ns.asc()).into_boxed(); @@ -129,6 +137,10 @@ impl DbConnection { query = query.limit(limit); } + if !include_dm_groups { + query = query.filter(dsl::dm_inbox_id.is_null()); + } + query = query.filter(dsl::purpose.eq(Purpose::Conversation)); Ok(self.raw_query(|conn| query.load(conn))?) @@ -162,7 +174,7 @@ impl DbConnection { query = query.filter(dsl::welcome_id.eq(welcome_id)); let groups: Vec = self.raw_query(|conn| query.load(conn))?; if groups.len() > 1 { - log::error!("More than one group found for welcome_id {}", welcome_id); + tracing::error!("More than one group found for welcome_id {}", welcome_id); } // Manually extract the first element Ok(groups.into_iter().next()) @@ -212,6 +224,7 @@ impl DbConnection { } pub fn insert_or_replace_group(&self, group: StoredGroup) -> Result { + tracing::info!("Trying to insert group"); let stored_group = self.raw_query(|conn| { let maybe_inserted_group: Option = diesel::insert_into(dsl::groups) .values(&group) @@ -222,13 +235,17 @@ impl DbConnection { if maybe_inserted_group.is_none() { let existing_group: StoredGroup = dsl::groups.find(group.id).first(conn)?; if existing_group.welcome_id == group.welcome_id { + tracing::info!("Group welcome id already exists"); // Error so OpenMLS db transaction are rolled back on duplicate welcomes return Err(StorageError::Duplicate(DuplicateItem::WelcomeId( existing_group.welcome_id, ))); } else { + tracing::info!("Group already exists"); return Ok(existing_group); } + } else { + tracing::info!("Group is inserted"); } match maybe_inserted_group { @@ -330,6 +347,22 @@ pub(crate) mod tests { created_at_ns, membership_state, "placeholder_address".to_string(), + None, + ) + } + + /// Generate a test dm group + pub fn generate_dm(state: Option) -> StoredGroup { + let id = rand_vec(); + let created_at_ns = now_ns(); + let membership_state = state.unwrap_or(GroupMembershipState::Allowed); + let dm_inbox_id = Some("placeholder_inbox_id".to_string()); + StoredGroup::new( + id, + created_at_ns, + membership_state, + "placeholder_address".to_string(), + dm_inbox_id, ) } @@ -391,23 +424,31 @@ pub(crate) mod tests { test_group_1.store(conn).unwrap(); let test_group_2 = generate_group(Some(GroupMembershipState::Allowed)); test_group_2.store(conn).unwrap(); + let test_group_3 = generate_dm(Some(GroupMembershipState::Allowed)); + test_group_3.store(conn).unwrap(); - let all_results = conn.find_groups(None, None, None, None).unwrap(); + let all_results = conn.find_groups(None, None, None, None, false).unwrap(); assert_eq!(all_results.len(), 2); let pending_results = conn - .find_groups(Some(vec![GroupMembershipState::Pending]), None, None, None) + .find_groups( + Some(vec![GroupMembershipState::Pending]), + None, + None, + None, + false, + ) .unwrap(); assert_eq!(pending_results[0].id, test_group_1.id); assert_eq!(pending_results.len(), 1); // Offset and limit - let results_with_limit = conn.find_groups(None, None, None, Some(1)).unwrap(); + let results_with_limit = conn.find_groups(None, None, None, Some(1), false).unwrap(); assert_eq!(results_with_limit.len(), 1); assert_eq!(results_with_limit[0].id, test_group_1.id); let results_with_created_at_ns_after = conn - .find_groups(None, Some(test_group_1.created_at_ns), None, Some(1)) + .find_groups(None, Some(test_group_1.created_at_ns), None, Some(1), false) .unwrap(); assert_eq!(results_with_created_at_ns_after.len(), 1); assert_eq!(results_with_created_at_ns_after[0].id, test_group_2.id); @@ -416,7 +457,10 @@ pub(crate) mod tests { let synced_groups = conn.find_sync_groups().unwrap(); assert_eq!(synced_groups.len(), 0); - // test that ONLY normal groups show up. + // test that dm groups are included + let dm_results = conn.find_groups(None, None, None, None, true).unwrap(); + assert_eq!(dm_results.len(), 3); + assert_eq!(dm_results[2].id, test_group_3.id); }) } diff --git a/xmtp_mls/src/storage/encrypted_store/group_intent.rs b/xmtp_mls/src/storage/encrypted_store/group_intent.rs index 4ff7615e7..b5104f9ac 100644 --- a/xmtp_mls/src/storage/encrypted_store/group_intent.rs +++ b/xmtp_mls/src/storage/encrypted_store/group_intent.rs @@ -404,6 +404,7 @@ mod tests { 100, GroupMembershipState::Allowed, "placeholder_address".to_string(), + None, ); group.store(conn).unwrap(); } diff --git a/xmtp_mls/src/storage/encrypted_store/identity.rs b/xmtp_mls/src/storage/encrypted_store/identity.rs index ad54cdd65..88b23c638 100644 --- a/xmtp_mls/src/storage/encrypted_store/identity.rs +++ b/xmtp_mls/src/storage/encrypted_store/identity.rs @@ -1,3 +1,5 @@ +use std::sync::atomic::AtomicBool; + use crate::storage::{encrypted_store::schema::identity, StorageError}; use diesel::prelude::*; use xmtp_id::InboxId; @@ -55,6 +57,7 @@ impl TryFrom for Identity { installation_keys: db_deserialize(&identity.installation_keys)?, credential: db_deserialize(&identity.credential_bytes)?, signature_request: None, + is_ready: AtomicBool::new(true), }) } } diff --git a/xmtp_mls/src/storage/encrypted_store/identity_update.rs b/xmtp_mls/src/storage/encrypted_store/identity_update.rs index ca33c6df9..d8515c488 100644 --- a/xmtp_mls/src/storage/encrypted_store/identity_update.rs +++ b/xmtp_mls/src/storage/encrypted_store/identity_update.rs @@ -7,7 +7,7 @@ use super::{ schema::identity_updates::{self, dsl}, }; use diesel::{dsl::max, prelude::*}; -use xmtp_id::associations::{AssociationError, IdentityUpdate}; +use xmtp_id::associations::{unverified::UnverifiedIdentityUpdate, AssociationError}; /// StoredIdentityUpdate holds a serialized IdentityUpdate record #[derive(Insertable, Identifiable, Queryable, Debug, Clone, PartialEq, Eq)] @@ -36,11 +36,11 @@ impl StoredIdentityUpdate { } } -impl TryFrom for IdentityUpdate { +impl TryFrom for UnverifiedIdentityUpdate { type Error = AssociationError; fn try_from(update: StoredIdentityUpdate) -> Result { - Ok(IdentityUpdate::try_from(update.payload)?) + Ok(UnverifiedIdentityUpdate::try_from(update.payload)?) } } diff --git a/xmtp_mls/src/storage/encrypted_store/key_package_history.rs b/xmtp_mls/src/storage/encrypted_store/key_package_history.rs new file mode 100644 index 000000000..1f759a8bc --- /dev/null +++ b/xmtp_mls/src/storage/encrypted_store/key_package_history.rs @@ -0,0 +1,122 @@ +use diesel::prelude::*; + +use super::{db_connection::DbConnection, schema::key_package_history, StorageError}; +use crate::{impl_store_or_ignore, utils::time::now_ns, StoreOrIgnore}; + +#[derive(Insertable, Debug, Clone)] +#[diesel(table_name = key_package_history)] +pub struct NewKeyPackageHistoryEntry { + pub key_package_hash_ref: Vec, + pub created_at_ns: i64, +} + +#[derive(Queryable, Selectable, Debug, Clone)] +#[diesel(table_name = key_package_history)] +pub struct StoredKeyPackageHistoryEntry { + pub id: i32, + pub key_package_hash_ref: Vec, + pub created_at_ns: i64, +} + +impl_store_or_ignore!(NewKeyPackageHistoryEntry, key_package_history); + +impl DbConnection { + pub fn store_key_package_history_entry( + &self, + key_package_hash_ref: Vec, + ) -> Result { + let entry = NewKeyPackageHistoryEntry { + key_package_hash_ref: key_package_hash_ref.clone(), + created_at_ns: now_ns(), + }; + entry.store_or_ignore(self)?; + + self.find_key_package_history_entry_by_hash_ref(key_package_hash_ref) + } + + pub fn find_key_package_history_entry_by_hash_ref( + &self, + hash_ref: Vec, + ) -> Result { + let result = self.raw_query(|conn| { + key_package_history::dsl::key_package_history + .filter(key_package_history::dsl::key_package_hash_ref.eq(hash_ref)) + .first::(conn) + })?; + + Ok(result) + } + + pub fn find_key_package_history_entries_before_id( + &self, + id: i32, + ) -> Result, StorageError> { + let result = self.raw_query(|conn| { + key_package_history::dsl::key_package_history + .filter(key_package_history::dsl::id.lt(id)) + .load::(conn) + })?; + + Ok(result) + } + + pub fn delete_key_package_history_entries_before_id( + &self, + id: i32, + ) -> Result<(), StorageError> { + self.raw_query(|conn| { + diesel::delete( + key_package_history::dsl::key_package_history + .filter(key_package_history::dsl::id.lt(id)), + ) + .execute(conn) + })?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::{storage::encrypted_store::tests::with_connection, utils::test::rand_vec}; + + #[test] + fn test_store_key_package_history_entry() { + with_connection(|conn| { + let hash_ref = rand_vec(); + let new_entry = conn + .store_key_package_history_entry(hash_ref.clone()) + .unwrap(); + assert_eq!(new_entry.key_package_hash_ref, hash_ref); + assert_eq!(new_entry.id, 1); + }) + } + + #[test] + fn test_store_multiple() { + with_connection(|conn| { + let hash_ref1 = rand_vec(); + let hash_ref2 = rand_vec(); + let hash_ref3 = rand_vec(); + + conn.store_key_package_history_entry(hash_ref1.clone()) + .unwrap(); + conn.store_key_package_history_entry(hash_ref2.clone()) + .unwrap(); + let entry_3 = conn + .store_key_package_history_entry(hash_ref3.clone()) + .unwrap(); + + let all_entries = conn + .find_key_package_history_entries_before_id(100) + .unwrap(); + + assert_eq!(all_entries.len(), 3); + + let earlier_entries = conn + .find_key_package_history_entries_before_id(entry_3.id) + .unwrap(); + assert_eq!(earlier_entries.len(), 2); + }) + } +} diff --git a/xmtp_mls/src/storage/encrypted_store/mod.rs b/xmtp_mls/src/storage/encrypted_store/mod.rs index f5d2f843d..244a0b170 100644 --- a/xmtp_mls/src/storage/encrypted_store/mod.rs +++ b/xmtp_mls/src/storage/encrypted_store/mod.rs @@ -11,56 +11,41 @@ //! `diesel print-schema` or use `cargo run update-schema` which will update the files for you. pub mod association_state; +pub mod consent_record; pub mod db_connection; pub mod group; pub mod group_intent; pub mod group_message; pub mod identity; pub mod identity_update; +pub mod key_package_history; pub mod key_store_entry; pub mod refresh_state; pub mod schema; +mod sqlcipher_connection; -use std::{borrow::Cow, sync::Arc}; +use std::sync::Arc; use diesel::{ connection::{AnsiTransactionManager, SimpleConnection, TransactionManager}, prelude::*, r2d2::{ConnectionManager, Pool, PoolTransactionManager, PooledConnection}, - result::{DatabaseErrorKind, Error}, + result::Error, sql_query, }; use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; -use log::{log_enabled, warn}; use parking_lot::RwLock; -use rand::RngCore; -use xmtp_cryptography::utils as crypto_utils; use self::db_connection::DbConnection; +pub use self::sqlcipher_connection::{EncryptedConnection, EncryptionKey}; + use super::StorageError; use crate::{xmtp_openmls_provider::XmtpOpenMlsProvider, Store}; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations/"); - pub type RawDbConnection = PooledConnection>; -pub type EncryptionKey = [u8; 32]; - -// For PRAGMA query log statements -#[derive(QueryableByName, Debug)] -struct CipherVersion { - #[diesel(sql_type = diesel::sql_types::Text)] - cipher_version: String, -} - -// For PRAGMA query log statements -#[derive(QueryableByName, Debug)] -struct CipherProviderVersion { - #[diesel(sql_type = diesel::sql_types::Text)] - cipher_provider_version: String, -} - // For PRAGMA query log statements #[derive(QueryableByName, Debug)] struct SqliteVersion { @@ -75,13 +60,32 @@ pub enum StorageOption { Persistent(String), } -pub fn ignore_unique_violation( - result: Result, -) -> Result<(), StorageError> { - match result { - Ok(_) => Ok(()), - Err(Error::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) => Ok(()), - Err(error) => Err(StorageError::from(error)), +impl StorageOption { + // create a completely new standalone connection + fn conn(&self) -> Result { + use StorageOption::*; + match self { + Persistent(path) => SqliteConnection::establish(path), + Ephemeral => SqliteConnection::establish(":memory:"), + } + } +} + +/// An Unencrypted Connection +/// Creates a Sqlite3 Database/Connection in WAL mode. +/// Sets `busy_timeout` on each connection. +/// _*NOTE:*_Unencrypted Connections are not validated and mostly meant for testing. +/// It is not recommended to use an unencrypted connection in production. +#[derive(Clone, Debug)] +pub struct UnencryptedConnection; + +impl diesel::r2d2::CustomizeConnection + for UnencryptedConnection +{ + fn on_acquire(&self, conn: &mut SqliteConnection) -> Result<(), diesel::r2d2::Error> { + conn.batch_execute("PRAGMA busy_timeout = 5000;") + .map_err(diesel::r2d2::Error::QueryError)?; + Ok(()) } } @@ -91,13 +95,7 @@ pub fn ignore_unique_violation( pub struct EncryptedMessageStore { connect_opt: StorageOption, pool: Arc>>>>, - enc_key: Option, -} - -impl<'a> From<&'a EncryptedMessageStore> for Cow<'a, EncryptedMessageStore> { - fn from(store: &'a EncryptedMessageStore) -> Cow<'a, EncryptedMessageStore> { - Cow::Borrowed(store) - } + enc_opts: Option, } impl EncryptedMessageStore { @@ -114,64 +112,55 @@ impl EncryptedMessageStore { opts: StorageOption, enc_key: Option, ) -> Result { - log::info!("Setting up DB connection pool"); - let pool = - match opts { - StorageOption::Ephemeral => Pool::builder() - .max_size(1) - .build(ConnectionManager::::new(":memory:"))?, - StorageOption::Persistent(ref path) => Pool::builder() - .max_size(25) - .build(ConnectionManager::::new(path))?, - }; - - // TODO: Validate that sqlite is correctly configured. Bad EncKey is not detected until the - // migrations run which returns an unhelpful error. - let mut obj = Self { + tracing::info!("Setting up DB connection pool"); + let mut builder = Pool::builder(); + + let enc_opts = if let Some(key) = enc_key { + let enc_opts = EncryptedConnection::new(key, &opts)?; + builder = builder.connection_customizer(Box::new(enc_opts.clone())); + Some(enc_opts) + } else if matches!(opts, StorageOption::Persistent(_)) { + builder = builder.connection_customizer(Box::new(UnencryptedConnection)); + None + } else { + None + }; + + let pool = match opts { + StorageOption::Ephemeral => builder + .max_size(1) + .build(ConnectionManager::::new(":memory:"))?, + StorageOption::Persistent(ref path) => builder + .max_size(25) + .build(ConnectionManager::::new(path))?, + }; + + let mut this = Self { connect_opt: opts, pool: Arc::new(Some(pool).into()), - enc_key, + enc_opts, }; - obj.init_db()?; - Ok(obj) + this.init_db()?; + Ok(this) } fn init_db(&mut self) -> Result<(), StorageError> { - let conn = &mut self.raw_conn()?; - conn.batch_execute("PRAGMA journal_mode = WAL;") - .map_err(|e| StorageError::DbInit(e.to_string()))?; + if let Some(ref encrypted_conn) = self.enc_opts { + encrypted_conn.validate(&self.connect_opt)?; + } - log::info!("Running DB migrations"); + let conn = &mut self.raw_conn()?; + conn.batch_execute("PRAGMA journal_mode = WAL;")?; + tracing::info!("Running DB migrations"); conn.run_pending_migrations(MIGRATIONS) - .map_err(|e| StorageError::DbInit(e.to_string()))?; + .map_err(|e| StorageError::DbInit(format!("Failed to run migrations: {}", e)))?; let sqlite_version = sql_query("SELECT sqlite_version() AS version").load::(conn)?; - log::info!("sqlite_version={}", sqlite_version[0].version); - - if self.enc_key.is_some() { - let cipher_version = sql_query("PRAGMA cipher_version").load::(conn)?; - if cipher_version.is_empty() { - return Err(StorageError::SqlCipherNotLoaded); - } - let cipher_provider_version = - sql_query("PRAGMA cipher_provider_version").load::(conn)?; - log::info!( - "Sqlite cipher_version={:?}, cipher_provider_version={:?}", - cipher_version.first().as_ref().map(|v| &v.cipher_version), - cipher_provider_version - .first() - .as_ref() - .map(|v| &v.cipher_provider_version) - ); - if log_enabled!(log::Level::Info) { - conn.batch_execute("PRAGMA cipher_log = stderr; PRAGMA cipher_log_level = INFO;") - .ok(); - } - } + tracing::info!("sqlite_version={}", sqlite_version[0].version); - log::info!("Migrations successful"); + tracing::info!("Migrations successful"); Ok(()) } @@ -184,20 +173,13 @@ impl EncryptedMessageStore { .as_ref() .ok_or(StorageError::PoolNeedsConnection)?; - log::debug!( + tracing::debug!( "Pulling connection from pool, idle_connections={}, total_connections={}", pool.state().idle_connections, pool.state().connections ); - let mut conn = pool.get()?; - if let Some(ref key) = self.enc_key { - conn.batch_execute(&format!("PRAGMA key = \"x'{}'\";", hex::encode(key)))?; - } - - conn.batch_execute("PRAGMA busy_timeout = 5000;")?; - - Ok(conn) + Ok(pool.get()?) } pub fn conn(&self) -> Result { @@ -223,7 +205,7 @@ impl EncryptedMessageStore { F: FnOnce(&XmtpOpenMlsProvider) -> Result, E: From + From, { - log::debug!("Transaction beginning"); + tracing::debug!("Transaction beginning"); let mut connection = self.raw_conn()?; AnsiTransactionManager::begin_transaction(&mut *connection)?; @@ -236,11 +218,11 @@ impl EncryptedMessageStore { conn.raw_query(|conn| { PoolTransactionManager::::commit_transaction(&mut *conn) })?; - log::debug!("Transaction being committed"); + tracing::debug!("Transaction being committed"); Ok(value) } Err(err) => { - log::debug!("Transaction being rolled back"); + tracing::debug!("Transaction being rolled back"); match conn.raw_query(|conn| { PoolTransactionManager::::rollback_transaction( &mut *conn, @@ -274,7 +256,7 @@ impl EncryptedMessageStore { Fut: futures::Future>, E: From + From, { - log::debug!("Transaction async beginning"); + tracing::debug!("Transaction async beginning"); let mut connection = self.raw_conn()?; AnsiTransactionManager::begin_transaction(&mut *connection)?; let connection = Arc::new(parking_lot::Mutex::new(connection)); @@ -286,11 +268,13 @@ impl EncryptedMessageStore { // ensuring we have only one strong reference let result = fun(provider).await; if Arc::strong_count(&local_connection) > 1 { - log::warn!("More than 1 strong connection references still exist during transaction"); + tracing::warn!( + "More than 1 strong connection references still exist during transaction" + ); } if Arc::weak_count(&local_connection) > 1 { - log::warn!("More than 1 weak connection references still exist during transaction"); + tracing::warn!("More than 1 weak connection references still exist during transaction"); } // after the closure finishes, `local_provider` should have the only reference ('strong') @@ -301,11 +285,11 @@ impl EncryptedMessageStore { local_connection.raw_query(|conn| { PoolTransactionManager::::commit_transaction(&mut *conn) })?; - log::debug!("Transaction async being committed"); + tracing::debug!("Transaction async being committed"); Ok(value) } Err(err) => { - log::debug!("Transaction async being rolled back"); + tracing::debug!("Transaction async being rolled back"); match local_connection.raw_query(|conn| { PoolTransactionManager::::rollback_transaction( &mut *conn, @@ -319,13 +303,6 @@ impl EncryptedMessageStore { } } - pub fn generate_enc_key() -> EncryptionKey { - // TODO: Handle Key Better/ Zeroize - let mut key = [0u8; 32]; - crypto_utils::rng().fill_bytes(&mut key[..]); - key - } - pub fn release_connection(&self) -> Result<(), StorageError> { let mut pool_guard = self.pool.write(); pool_guard.take(); @@ -333,15 +310,20 @@ impl EncryptedMessageStore { } pub fn reconnect(&self) -> Result<(), StorageError> { - let pool = - match self.connect_opt { - StorageOption::Ephemeral => Pool::builder() - .max_size(1) - .build(ConnectionManager::::new(":memory:"))?, - StorageOption::Persistent(ref path) => Pool::builder() - .max_size(25) - .build(ConnectionManager::::new(path))?, - }; + let mut builder = Pool::builder(); + + if let Some(ref opts) = self.enc_opts { + builder = builder.connection_customizer(Box::new(opts.clone())); + } + + let pool = match self.connect_opt { + StorageOption::Ephemeral => builder + .max_size(1) + .build(ConnectionManager::::new(":memory:"))?, + StorageOption::Persistent(ref path) => builder + .max_size(25) + .build(ConnectionManager::::new(path))?, + }; let mut pool_write = self.pool.write(); *pool_write = Some(pool); @@ -353,7 +335,7 @@ impl EncryptedMessageStore { #[allow(dead_code)] fn warn_length(list: &[T], str_id: &str, max_length: usize) { if list.len() > max_length { - warn!( + tracing::warn!( "EncryptedStore expected at most {} {} however found {}. Using the Oldest.", max_length, str_id, @@ -422,12 +404,13 @@ macro_rules! impl_store_or_ignore { &self, into: &$crate::storage::encrypted_store::db_connection::DbConnection, ) -> Result<(), $crate::StorageError> { - let result = into.raw_query(|conn| { - diesel::insert_into($table::table) + into.raw_query(|conn| { + diesel::insert_or_ignore_into($table::table) .values(self) .execute(conn) - }); - $crate::storage::ignore_unique_violation(result) + .map(|_| ()) + }) + .map_err($crate::StorageError::from) } } }; @@ -447,18 +430,16 @@ where #[cfg(test)] mod tests { - use super::{ - db_connection::DbConnection, identity::StoredIdentity, EncryptedMessageStore, StorageError, - StorageOption, - }; + use super::*; use std::sync::Barrier; use crate::{ storage::group::{GroupMembershipState, StoredGroup}, + storage::identity::StoredIdentity, utils::test::{rand_vec, tmp_path}, Fetch, Store, }; - use std::{fs, sync::Arc}; + use std::sync::Arc; /// Test harness that loads an Ephemeral store. pub fn with_connection(fun: F) -> R @@ -522,8 +503,7 @@ mod tests { let fetched_identity: StoredIdentity = conn.fetch(&()).unwrap().unwrap(); assert_eq!(fetched_identity.inbox_id, inbox_id); } - - fs::remove_file(db_path).unwrap(); + EncryptedMessageStore::remove_db_files(db_path) } #[test] @@ -554,7 +534,7 @@ mod tests { assert_eq!(fetched_identity2.inbox_id, inbox_id); } - fs::remove_file(db_path).unwrap(); + EncryptedMessageStore::remove_db_files(db_path) } #[test] @@ -578,72 +558,34 @@ mod tests { // Ensure it fails assert!( - matches!(res.err(), Some(StorageError::DbInit(_))), - "Expected DbInitError" + matches!(res.err(), Some(StorageError::SqlCipherKeyIncorrect)), + "Expected SqlCipherKeyIncorrect error" ); - fs::remove_file(db_path).unwrap(); + EncryptedMessageStore::remove_db_files(db_path) } #[tokio::test] async fn encrypted_db_with_multiple_connections() { let db_path = tmp_path(); - let store = EncryptedMessageStore::new( - StorageOption::Persistent(db_path.clone()), - EncryptedMessageStore::generate_enc_key(), - ) - .unwrap(); - - let conn1 = &store.conn().unwrap(); - let inbox_id = "inbox_id"; - StoredIdentity::new(inbox_id.to_string(), rand_vec(), rand_vec()) - .store(conn1) + { + let store = EncryptedMessageStore::new( + StorageOption::Persistent(db_path.clone()), + EncryptedMessageStore::generate_enc_key(), + ) .unwrap(); - let conn2 = &store.conn().unwrap(); - let fetched_identity: StoredIdentity = conn2.fetch(&()).unwrap().unwrap(); - assert_eq!(fetched_identity.inbox_id, inbox_id); - } - - #[test] - fn it_returns_ok_when_given_ok_result() { - let result: Result<(), diesel::result::Error> = Ok(()); - assert!( - super::ignore_unique_violation(result).is_ok(), - "Expected Ok(()) when given Ok result" - ); - } - - #[test] - fn it_returns_ok_on_unique_violation_error() { - let result: Result<(), diesel::result::Error> = Err(diesel::result::Error::DatabaseError( - diesel::result::DatabaseErrorKind::UniqueViolation, - Box::new("violation".to_string()), - )); - assert!( - super::ignore_unique_violation(result).is_ok(), - "Expected Ok(()) when given UniqueViolation error" - ); - } - - #[test] - fn it_returns_err_on_non_unique_violation_database_errors() { - let result: Result<(), diesel::result::Error> = Err(diesel::result::Error::DatabaseError( - diesel::result::DatabaseErrorKind::NotNullViolation, - Box::new("other kind".to_string()), - )); - assert!( - super::ignore_unique_violation(result).is_err(), - "Expected Err when given non-UniqueViolation database error" - ); - } + let conn1 = &store.conn().unwrap(); + let inbox_id = "inbox_id"; + StoredIdentity::new(inbox_id.to_string(), rand_vec(), rand_vec()) + .store(conn1) + .unwrap(); - #[test] - fn it_returns_err_on_non_database_errors() { - let result: Result<(), diesel::result::Error> = Err(diesel::result::Error::NotFound); - assert!( - super::ignore_unique_violation(result).is_err(), - "Expected Err when given a non-database error" - ); + let conn2 = &store.conn().unwrap(); + tracing::info!("Getting conn 2"); + let fetched_identity: StoredIdentity = conn2.fetch(&()).unwrap().unwrap(); + assert_eq!(fetched_identity.inbox_id, inbox_id); + } + EncryptedMessageStore::remove_db_files(db_path) } // get two connections @@ -688,6 +630,7 @@ mod tests { 0, GroupMembershipState::Allowed, "goodbye".to_string(), + None, ); group.store(connection)?; Ok(()) @@ -739,6 +682,7 @@ mod tests { 0, GroupMembershipState::Allowed, "goodbye".to_string(), + None, ); group.store(conn1).unwrap(); diff --git a/xmtp_mls/src/storage/encrypted_store/schema.rs b/xmtp_mls/src/storage/encrypted_store/schema.rs index 84d3c69ec..7266406cd 100644 --- a/xmtp_mls/src/storage/encrypted_store/schema.rs +++ b/xmtp_mls/src/storage/encrypted_store/schema.rs @@ -8,6 +8,14 @@ diesel::table! { } } +diesel::table! { + consent_records (entity_type, entity) { + entity_type -> Integer, + state -> Integer, + entity -> Text, + } +} + diesel::table! { group_intents (id) { id -> Integer, @@ -45,6 +53,7 @@ diesel::table! { purpose -> Integer, added_by_inbox_id -> Text, welcome_id -> Nullable, + dm_inbox_id -> Nullable, } } @@ -66,6 +75,14 @@ diesel::table! { } } +diesel::table! { + key_package_history (id) { + id -> Integer, + key_package_hash_ref -> Binary, + created_at_ns -> BigInt, + } +} + diesel::table! { openmls_key_store (key_bytes) { key_bytes -> Binary, @@ -94,11 +111,13 @@ diesel::joinable!(group_messages -> groups (group_id)); diesel::allow_tables_to_appear_in_same_query!( association_state, + consent_records, group_intents, group_messages, groups, identity, identity_updates, + key_package_history, openmls_key_store, openmls_key_value, refresh_state, diff --git a/xmtp_mls/src/storage/encrypted_store/sqlcipher_connection.rs b/xmtp_mls/src/storage/encrypted_store/sqlcipher_connection.rs new file mode 100644 index 000000000..4fa0e3f50 --- /dev/null +++ b/xmtp_mls/src/storage/encrypted_store/sqlcipher_connection.rs @@ -0,0 +1,351 @@ +//! SQLCipher-specific Connection +use diesel::{ + connection::{LoadConnection, SimpleConnection}, + deserialize::FromSqlRow, + prelude::*, + sql_query, +}; +use std::{ + fmt::Display, + fs::File, + io::{Read, Write}, + path::{Path, PathBuf}, +}; + +use crate::storage::StorageError; + +use super::StorageOption; + +pub type EncryptionKey = [u8; 32]; +pub type Salt = [u8; 16]; +const PLAINTEXT_HEADER_SIZE: usize = 32; +const SALT_FILE_NAME: &str = "sqlcipher_salt"; + +// For PRAGMA query log statements +#[derive(QueryableByName, Debug)] +struct CipherVersion { + #[diesel(sql_type = diesel::sql_types::Text)] + cipher_version: String, +} + +// For PRAGMA query log statements +#[derive(QueryableByName, Debug)] +struct CipherProviderVersion { + #[diesel(sql_type = diesel::sql_types::Text)] + cipher_provider_version: String, +} + +/// Specialized Connection for r2d2 connection pool. +#[derive(Clone, Debug)] +pub struct EncryptedConnection { + key: EncryptionKey, + /// We don't store the salt for Ephemeral Dbs + salt: Option, +} + +impl EncryptedConnection { + /// Creates a file for the salt and stores it + pub fn new(key: EncryptionKey, opts: &StorageOption) -> Result { + use super::StorageOption::*; + let salt = match opts { + Ephemeral => None, + Persistent(ref db_path) => { + let mut salt = [0u8; 16]; + let db_pathbuf = PathBuf::from(db_path); + let salt_path = Self::salt_file(db_path)?; + + match (salt_path.try_exists()?, db_pathbuf.try_exists()?) { + // db and salt exist + (true, true) => { + let file = File::open(salt_path)?; + salt = ::from_hex( + file.bytes().take(32).collect::, _>>()?, + )?; + } + // the db exists and needs to be migrated + (false, true) => { + tracing::debug!("migrating sqlcipher db to plaintext header."); + Self::migrate(db_path, key, &mut salt)?; + } + // the db doesn't exist yet and needs to be created + (false, false) => { + tracing::debug!("creating new sqlcipher db"); + Self::create(db_path, key, &mut salt)?; + } + // the db doesn't exist but the salt does + // This generally doesn't make sense & shouldn't happen. + // Create a new database and delete the salt file. + (true, false) => { + std::fs::remove_file(salt_path)?; + Self::create(db_path, key, &mut salt)?; + } + } + Some(salt) + } + }; + + Ok(Self { key, salt }) + } + + /// create a new database + salt file. + /// writes the 16-bytes hex-encoded salt to `salt` + fn create(path: &String, key: EncryptionKey, salt: &mut [u8]) -> Result<(), StorageError> { + let conn = &mut SqliteConnection::establish(path)?; + conn.batch_execute(&format!( + r#" + {} + {} + PRAGMA journal_mode = WAL; + "#, + pragma_key(hex::encode(key)), + pragma_plaintext_header() + ))?; + + Self::write_salt(path, conn, salt)?; + Ok(()) + } + + /// Executes the steps outlined in the [SQLCipher Docs](https://www.zetetic.net/sqlcipher/sqlcipher-api/#cipher_plaintext_header_size) + /// Migrates the database to `cipher_plaintext_header_size` and returns the salt after + /// persisting it to SALT_FILE_NAME. + /// + /// if the salt file already exists, deletes it. + fn migrate(path: &String, key: EncryptionKey, salt: &mut [u8]) -> Result<(), StorageError> { + let conn = &mut SqliteConnection::establish(path)?; + + conn.batch_execute(&format!( + r#" + {} + select count(*) from sqlite_master; -- trigger header read, currently it is encrypted + "#, + pragma_key(hex::encode(key)) + ))?; + + // get the salt and save it for later use + Self::write_salt(path, conn, salt)?; + + conn.batch_execute(&format!( + r#" + {} + PRAGMA user_version = 1; -- force header write + "#, + pragma_plaintext_header() + ))?; + + Ok(()) + } + + /// Get the salt from the opened database, write it to `Self::salt_file(db_path)` as hex-encoded + /// bytes, and then copy it to `buf` after decoding hex bytes. + fn write_salt( + path: &String, + conn: &mut SqliteConnection, + buf: &mut [u8], + ) -> Result<(), StorageError> { + let mut row_iter = conn.load(sql_query("PRAGMA cipher_salt"))?; + // cipher salt should always exist. if it doesn't SQLCipher is misconfigured. + let row = row_iter.next().ok_or(StorageError::NotFound( + "Cipher salt doesn't exist in database".into(), + ))??; + let salt = >::build_from_row(&row)?; + tracing::debug!( + "writing salt={} to file {:?}", + salt, + Self::salt_file(PathBuf::from(path))?, + ); + let mut f = File::create(Self::salt_file(PathBuf::from(path))?)?; + + f.write_all(salt.as_bytes())?; + let mut perms = f.metadata()?.permissions(); + perms.set_readonly(true); + f.set_permissions(perms)?; + + let salt = hex::decode(salt)?; + buf.copy_from_slice(&salt); + Ok(()) + } + + /// Salt file is stored next to the sqlite3 db3 file as `{db_file_name}.SALT_FILE_NAME`. + /// If the db file is named `sqlite3_xmtp_db.db3`, the salt file would + /// be stored next to this file as `sqlite3_xmtp_db.db3.sqlcipher_salt` + pub(crate) fn salt_file>(db_path: P) -> std::io::Result { + let db_path: &Path = db_path.as_ref(); + let name = db_path.file_name().ok_or(std::io::Error::new( + std::io::ErrorKind::NotFound, + "database file has no name", + ))?; + let db_path = db_path.parent().ok_or(std::io::Error::new( + std::io::ErrorKind::NotFound, + "Parent directory could not be found", + ))?; + Ok(db_path.join(format!("{}.{}", name.to_string_lossy(), SALT_FILE_NAME))) + } + + pub(super) fn validate(&self, opts: &StorageOption) -> Result<(), StorageError> { + let conn = &mut opts.conn()?; + + let cipher_version = sql_query("PRAGMA cipher_version").load::(conn)?; + if cipher_version.is_empty() { + return Err(StorageError::SqlCipherNotLoaded); + } + + // test the key according to + // https://www.zetetic.net/sqlcipher/sqlcipher-api/#testing-the-key + conn.batch_execute(&format!( + "{} + SELECT count(*) FROM sqlite_master;", + self.pragmas() + )) + .map_err(|_| StorageError::SqlCipherKeyIncorrect)?; + + let CipherProviderVersion { + cipher_provider_version, + } = sql_query("PRAGMA cipher_provider_version") + .get_result::(conn)?; + tracing::info!( + "Sqlite cipher_version={:?}, cipher_provider_version={:?}", + cipher_version.first().as_ref().map(|v| &v.cipher_version), + cipher_provider_version + ); + + if tracing::enabled!(tracing::Level::INFO) { + conn.batch_execute("PRAGMA cipher_log = stderr; PRAGMA cipher_log_level = INFO;") + .ok(); + } else { + conn.batch_execute("PRAGMA cipher_log = stderr; PRAGMA cipher_log_level = WARN;") + .ok(); + } + tracing::debug!("SQLCipher Database validated."); + Ok(()) + } + + /// Output the corect order of PRAGMAS to instantiate a connection + fn pragmas(&self) -> impl Display { + let Self { ref key, ref salt } = self; + + if let Some(s) = salt { + format!( + "{}\n{}\n{}", + pragma_key(hex::encode(key)), + pragma_plaintext_header(), + pragma_salt(hex::encode(s)) + ) + } else { + format!( + "{}\n{}", + pragma_key(hex::encode(key)), + pragma_plaintext_header() + ) + } + } +} + +impl diesel::r2d2::CustomizeConnection + for EncryptedConnection +{ + fn on_acquire(&self, conn: &mut SqliteConnection) -> Result<(), diesel::r2d2::Error> { + conn.batch_execute(&format!( + "{} + PRAGMA busy_timeout = 5000;", + self.pragmas() + )) + .map_err(diesel::r2d2::Error::QueryError)?; + + Ok(()) + } +} + +fn pragma_key(key: impl Display) -> impl Display { + format!(r#"PRAGMA key = "x'{key}'";"#) +} + +fn pragma_salt(salt: impl Display) -> impl Display { + format!(r#"PRAGMA cipher_salt="x'{salt}'";"#) +} + +fn pragma_plaintext_header() -> impl Display { + format!(r#"PRAGMA cipher_plaintext_header_size={PLAINTEXT_HEADER_SIZE};"#) +} + +#[cfg(test)] +mod tests { + use crate::{storage::EncryptedMessageStore, utils::test::tmp_path}; + use diesel_migrations::MigrationHarness; + use std::fs::File; + + use super::*; + const SQLITE3_PLAINTEXT_HEADER: &str = "SQLite format 3\0"; + use StorageOption::*; + + #[test] + fn test_db_creates_with_plaintext_header() { + let db_path = tmp_path(); + { + let _ = EncryptedMessageStore::new( + Persistent(db_path.clone()), + EncryptedMessageStore::generate_enc_key(), + ) + .unwrap(); + + assert!(EncryptedConnection::salt_file(&db_path).unwrap().exists()); + let bytes = std::fs::read(EncryptedConnection::salt_file(&db_path).unwrap()).unwrap(); + let salt = hex::decode(bytes).unwrap(); + assert_eq!(salt.len(), 16); + + let mut plaintext_header = [0; 16]; + let mut file = File::open(&db_path).unwrap(); + file.read_exact(&mut plaintext_header).unwrap(); + + assert_eq!( + SQLITE3_PLAINTEXT_HEADER, + String::from_utf8(plaintext_header.into()).unwrap() + ); + } + EncryptedMessageStore::remove_db_files(db_path) + } + + #[test] + fn test_db_migrates() { + let db_path = tmp_path(); + { + let key = EncryptedMessageStore::generate_enc_key(); + { + let conn = &mut SqliteConnection::establish(&db_path).unwrap(); + conn.batch_execute(&format!( + r#" + {} + PRAGMA busy_timeout = 5000; + PRAGMA journal_mode = WAL; + "#, + pragma_key(hex::encode(key)) + )) + .unwrap(); + conn.run_pending_migrations(crate::storage::MIGRATIONS) + .unwrap(); + } + + // no plaintext header before migration + let mut plaintext_header = [0; 16]; + let mut file = File::open(&db_path).unwrap(); + file.read_exact(&mut plaintext_header).unwrap(); + assert!(String::from_utf8_lossy(&plaintext_header) != SQLITE3_PLAINTEXT_HEADER); + + let _ = EncryptedMessageStore::new(Persistent(db_path.clone()), key).unwrap(); + + assert!(EncryptedConnection::salt_file(&db_path).unwrap().exists()); + let bytes = std::fs::read(EncryptedConnection::salt_file(&db_path).unwrap()).unwrap(); + let salt = hex::decode(bytes).unwrap(); + assert_eq!(salt.len(), 16); + + let mut plaintext_header = [0; 16]; + let mut file = File::open(&db_path).unwrap(); + file.read_exact(&mut plaintext_header).unwrap(); + + assert_eq!( + SQLITE3_PLAINTEXT_HEADER, + String::from_utf8(plaintext_header.into()).unwrap() + ); + } + EncryptedMessageStore::remove_db_files(db_path) + } +} diff --git a/xmtp_mls/src/storage/errors.rs b/xmtp_mls/src/storage/errors.rs index d29bc2b12..f109b0248 100644 --- a/xmtp_mls/src/storage/errors.rs +++ b/xmtp_mls/src/storage/errors.rs @@ -35,6 +35,12 @@ pub enum StorageError { Intent(#[from] IntentError), #[error("The SQLCipher Sqlite extension is not present, but an encryption key is given")] SqlCipherNotLoaded, + #[error("PRAGMA key or salt has incorrect value")] + SqlCipherKeyIncorrect, + #[error(transparent)] + Io(#[from] std::io::Error), + #[error(transparent)] + FromHex(#[from] hex::FromHexError), #[error(transparent)] Duplicate(DuplicateItem), } @@ -87,6 +93,7 @@ impl RetryableError for StorageError { Self::Lock(_) => true, Self::SqlCipherNotLoaded => true, Self::PoolNeedsConnection => true, + Self::SqlCipherKeyIncorrect => false, Self::Duplicate(d) => retryable!(d), _ => false, } diff --git a/xmtp_mls/src/storage/sql_key_store.rs b/xmtp_mls/src/storage/sql_key_store.rs index 12f795115..c37296bc1 100644 --- a/xmtp_mls/src/storage/sql_key_store.rs +++ b/xmtp_mls/src/storage/sql_key_store.rs @@ -86,7 +86,7 @@ impl SqlKeyStore { key: &[u8], value: &[u8], ) -> Result<(), >::Error> { - log::debug!("write {}", String::from_utf8_lossy(label)); + tracing::debug!("write {}", String::from_utf8_lossy(label)); let storage_key = build_key_from_vec::(label, key.to_vec()); @@ -101,7 +101,7 @@ impl SqlKeyStore { key: &[u8], value: &[u8], ) -> Result<(), >::Error> { - log::debug!("append {}", String::from_utf8_lossy(label)); + tracing::debug!("append {}", String::from_utf8_lossy(label)); let storage_key = build_key_from_vec::(label, key.to_vec()); let data = self.select_query::(&storage_key)?; @@ -133,7 +133,7 @@ impl SqlKeyStore { key: &[u8], value: &[u8], ) -> Result<(), >::Error> { - log::debug!("remove_item {}", String::from_utf8_lossy(label)); + tracing::debug!("remove_item {}", String::from_utf8_lossy(label)); let storage_key = build_key_from_vec::(label, key.to_vec()); let data: Vec = self.select_query::(&storage_key)?; @@ -166,7 +166,7 @@ impl SqlKeyStore { label: &[u8], key: &[u8], ) -> Result, >::Error> { - log::debug!("read {}", String::from_utf8_lossy(label)); + tracing::debug!("read {}", String::from_utf8_lossy(label)); let storage_key = build_key_from_vec::(label, key.to_vec()); @@ -187,7 +187,7 @@ impl SqlKeyStore { label: &[u8], key: &[u8], ) -> Result, >::Error> { - log::debug!("read_list {}", String::from_utf8_lossy(label)); + tracing::debug!("read_list {}", String::from_utf8_lossy(label)); let storage_key = build_key_from_vec::(label, key.to_vec()); let results = self.select_query::(&storage_key)?; @@ -201,7 +201,7 @@ impl SqlKeyStore { match bincode::deserialize::(&v) { Ok(deserialized_value) => deserialized_list.push(deserialized_value), Err(e) => { - log::error!("Error occurred: {}", e); + tracing::error!("Error occurred: {}", e); return Err(SqlKeyStoreError::SerializationError); } } @@ -775,9 +775,9 @@ impl StorageProvider for SqlKeyStore { ) -> Result<(), Self::Error> { let key = epoch_key_pairs_id(group_id, epoch, leaf_index)?; let value = bincode::serialize(key_pairs)?; - log::debug!("Writing encryption epoch key pairs"); - log::debug!(" key: {}", hex::encode(&key)); - log::debug!(" value: {}", hex::encode(&value)); + tracing::debug!("Writing encryption epoch key pairs"); + tracing::debug!(" key: {}", hex::encode(&key)); + tracing::debug!(" value: {}", hex::encode(&value)); self.write::(EPOCH_KEY_PAIRS_LABEL, &key, &value) } @@ -792,11 +792,11 @@ impl StorageProvider for SqlKeyStore { epoch: &EpochKey, leaf_index: u32, ) -> Result, Self::Error> { - log::debug!("Reading encryption epoch key pairs"); + tracing::debug!("Reading encryption epoch key pairs"); let key = epoch_key_pairs_id(group_id, epoch, leaf_index)?; let storage_key = build_key_from_vec::(EPOCH_KEY_PAIRS_LABEL, key); - log::debug!(" key: {}", hex::encode(&storage_key)); + tracing::debug!(" key: {}", hex::encode(&storage_key)); let query = "SELECT value_bytes FROM openmls_key_value WHERE key_bytes = ? AND version = ?"; @@ -887,7 +887,7 @@ impl StorageProvider for SqlKeyStore { &self, group_id: &GroupId, ) -> Result, Self::Error> { - log::debug!("own_leaf_nodes"); + tracing::debug!("own_leaf_nodes"); let key = build_key::(OWN_LEAF_NODES_LABEL, group_id)?; self.read_list(OWN_LEAF_NODES_LABEL, &key) @@ -1109,7 +1109,7 @@ mod tests { .expect("Failed to queue proposal"); } - log::debug!("Finished with queued proposals"); + tracing::debug!("Finished with queued proposals"); // Read proposal refs let proposal_refs_read: Vec = provider .storage() diff --git a/xmtp_mls/src/subscriptions.rs b/xmtp_mls/src/subscriptions.rs index f44315a17..10282ecd9 100644 --- a/xmtp_mls/src/subscriptions.rs +++ b/xmtp_mls/src/subscriptions.rs @@ -1,5 +1,6 @@ -use std::{collections::HashMap, pin::Pin, sync::Arc}; +use std::{collections::HashMap, sync::Arc}; +use crate::xmtp_openmls_provider::XmtpOpenMlsProvider; use futures::{FutureExt, Stream, StreamExt}; use prost::Message; use tokio::{sync::oneshot, task::JoinHandle}; @@ -9,7 +10,7 @@ use xmtp_proto::xmtp::mls::api::v1::WelcomeMessage; use crate::{ api::GroupFilter, client::{extract_welcome_message, ClientError}, - groups::{extract_group_id, GroupError, MlsGroup}, + groups::{extract_group_id, group_metadata::ConversationType, GroupError, MlsGroup}, retry::Retry, retry_async, storage::{group::StoredGroup, group_message::StoredGroupMessage}, @@ -26,7 +27,7 @@ pub struct StreamHandle { /// Events local to this client /// are broadcast across all senders/receivers of streams -#[derive(Clone, Debug)] +#[derive(Clone)] pub(crate) enum LocalEvents { // a new group was created NewGroup(MlsGroup), @@ -67,7 +68,7 @@ impl From for (Vec, MessagesStreamInfo) { impl Client where - ApiClient: XmtpApi, + ApiClient: XmtpApi + 'static, { async fn process_streamed_welcome( &self, @@ -77,6 +78,7 @@ where let creation_result = retry_async!( Retry::default(), (async { + tracing::info!("Trying to process streamed welcome"); let welcome_v1 = welcome_v1.clone(); self.context .store @@ -99,7 +101,7 @@ where let result = conn.find_group_by_welcome_id(welcome_v1.id as i64); match result { Ok(Some(group)) => { - log::info!( + tracing::info!( "Loading existing group for welcome_id: {:?}", group.welcome_id ); @@ -130,118 +132,155 @@ where pub async fn stream_conversations( &self, - ) -> Result + Send + '_>>, ClientError> { + include_dm: bool, + ) -> Result + '_, ClientError> { + let provider = Arc::new(self.context.mls_provider()?); + let event_queue = tokio_stream::wrappers::BroadcastStream::new(self.local_events.subscribe()); - let event_queue = event_queue.filter_map(|event| async move { - match event { - Ok(LocalEvents::NewGroup(g)) => Some(g), - Err(BroadcastStreamRecvError::Lagged(missed)) => { - log::warn!("Missed {missed} messages due to local event queue lagging"); + // Helper function for filtering Dm groups + let filter_group = move |group: MlsGroup, provider: Arc| async move { + match group.metadata(provider.as_ref()) { + Ok(metadata) => { + if include_dm || metadata.conversation_type != ConversationType::Dm { + Some(group) + } else { + None + } + } + Err(err) => { + tracing::error!("Error processing group metadata: {:?}", err); None } } + }; + + let event_provider = Arc::clone(&provider); + let event_queue = event_queue.filter_map(move |event| { + let provider = Arc::clone(&event_provider); + async move { + match event { + Ok(LocalEvents::NewGroup(group)) => filter_group(group, provider).await, + Err(BroadcastStreamRecvError::Lagged(missed)) => { + tracing::warn!("Missed {missed} messages due to local event queue lagging"); + None + } + } + } }); let installation_key = self.installation_public_key(); let id_cursor = 0; + tracing::info!("Setting up conversation stream"); let subscription = self .api_client .subscribe_welcome_messages(installation_key, Some(id_cursor)) .await?; + let stream_provider = Arc::clone(&provider); let stream = subscription .map(|welcome| async { - log::info!("Received conversation streaming payload"); + tracing::info!("Received conversation streaming payload"); self.process_streamed_welcome(welcome?).await }) - .filter_map(|res| async { - match res.await { - Ok(group) => Some(group), - Err(err) => { - log::error!("Error processing stream entry for conversation: {:?}", err); - None + .filter_map(move |res| { + let provider = Arc::clone(&stream_provider); + async move { + match res.await { + Ok(group) => filter_group(group, provider).await, + Err(err) => { + tracing::error!( + "Error processing stream entry for conversation: {:?}", + err + ); + None + } } } }); - Ok(Box::pin(futures::stream::select(stream, event_queue))) + Ok(futures::stream::select(stream, event_queue)) } #[tracing::instrument(skip(self, group_id_to_info))] pub(crate) async fn stream_messages( - self: Arc, - group_id_to_info: HashMap, MessagesStreamInfo>, - ) -> Result + Send>>, ClientError> { + &self, + group_id_to_info: Arc, MessagesStreamInfo>>, + ) -> Result + '_, ClientError> + where + ApiClient: 'static, + { let filters: Vec = group_id_to_info .iter() .map(|(group_id, info)| GroupFilter::new(group_id.clone(), Some(info.cursor))) .collect(); + let messages_subscription = self.api_client.subscribe_group_messages(filters).await?; let stream = messages_subscription .map(move |res| { - let context = self.context.clone(); - let client = self.clone(); - - let group_id_to_info = group_id_to_info.clone(); + let group_info = group_id_to_info.clone(); async move { match res { Ok(envelope) => { - log::info!("Received message streaming payload"); + tracing::info!("Received message streaming payload"); let group_id = extract_group_id(&envelope)?; - log::info!("Extracted group id {}", hex::encode(&group_id)); - let stream_info = group_id_to_info.get(&group_id).ok_or( + tracing::info!("Extracted group id {}", hex::encode(&group_id)); + let stream_info = group_info.get(&group_id).ok_or( ClientError::StreamInconsistency( "Received message for a non-subscribed group".to_string(), ), )?; - let mls_group = - MlsGroup::new(context, group_id, stream_info.convo_created_at_ns); - mls_group - .process_stream_entry(envelope.clone(), client.clone()) - .await + let mls_group = MlsGroup::new( + self.context.clone(), + group_id, + stream_info.convo_created_at_ns, + ); + mls_group.process_stream_entry(envelope, self).await } Err(err) => Err(GroupError::Api(err)), } } }) - .filter_map(move |res| async { + .filter_map(|res| async { match res.await { Ok(Some(message)) => Some(message), Ok(None) => { - log::info!("Skipped message streaming payload"); + tracing::info!("Skipped message streaming payload"); None } Err(err) => { - log::error!("Error processing stream entry: {:?}", err); + tracing::error!("Error processing stream entry: {:?}", err); None } } }); - - Ok(Box::pin(stream)) + Ok(stream) } } impl Client where - ApiClient: XmtpApi, + ApiClient: XmtpApi + 'static, { pub fn stream_conversations_with_callback( client: Arc>, mut convo_callback: impl FnMut(MlsGroup) + Send + 'static, + include_dm: bool, ) -> StreamHandle> { let (tx, rx) = oneshot::channel(); let handle = tokio::spawn(async move { - let mut stream = client.stream_conversations().await?; + let stream = client.stream_conversations(include_dm).await?; + futures::pin_mut!(stream); let _ = tx.send(()); while let Some(convo) = stream.next().await { + tracing::info!("Trigger conversation callback"); convo_callback(convo) } + tracing::debug!("`stream_conversations` stream ended, dropping stream"); Ok(()) }); @@ -258,12 +297,15 @@ where ) -> StreamHandle> { let (tx, rx) = oneshot::channel(); + let client = client.clone(); let handle = tokio::spawn(async move { - let mut stream = Self::stream_messages(client, group_id_to_info).await?; + let stream = Self::stream_messages(&client, group_id_to_info.into()).await?; let _ = tx.send(()); + futures::pin_mut!(stream); while let Some(message) = stream.next().await { callback(message) } + tracing::debug!("`stream_messages` stream ended, dropping stream"); Ok(()) }); @@ -274,25 +316,29 @@ where } pub async fn stream_all_messages( - client: Arc>, - ) -> Result>, ClientError> { - client.sync_welcomes().await?; + &self, + ) -> Result> + '_, ClientError> { + self.sync_welcomes().await?; - let mut group_id_to_info = client + let mut group_id_to_info = self .store() .conn()? - .find_groups(None, None, None, None)? + .find_groups(None, None, None, None, false)? .into_iter() .map(Into::into) .collect::, MessagesStreamInfo>>(); let stream = async_stream::stream! { - let client = client.clone(); - let mut messages_stream = client - .clone() - .stream_messages(group_id_to_info.clone()) + let messages_stream = self + .stream_messages(Arc::new(group_id_to_info.clone())) .await?; - let mut convo_stream = Self::stream_conversations(&client).await?; + futures::pin_mut!(messages_stream); + + tracing::info!("Setting up conversation stream in stream_all_messages"); + let convo_stream = self.stream_conversations(true).await?; + + futures::pin_mut!(convo_stream); + let mut extra_messages = Vec::new(); loop { @@ -313,10 +359,10 @@ where yield Ok(message); } Some(new_group) = convo_stream.next() => { + tracing::info!("Received new conversation inside streamAllMessages"); if group_id_to_info.contains_key(&new_group.group_id) { continue; } - for info in group_id_to_info.values_mut() { info.cursor = 0; } @@ -327,27 +373,26 @@ where cursor: 1, // For the new group, stream all messages since the group was created }, ); - - let new_messages_stream = match client.clone().stream_messages(group_id_to_info.clone()).await { + let new_messages_stream = match self.stream_messages(Arc::new(group_id_to_info.clone())).await { Ok(stream) => stream, Err(e) => { - log::error!("{}", e); + tracing::error!("{}", e); break; } }; - log::debug!("switching streams"); + tracing::debug!("switching streams"); // attempt to drain all ready messages from existing stream while let Some(Some(message)) = messages_stream.next().now_or_never() { extra_messages.push(message); } - let _ = std::mem::replace(&mut messages_stream, new_messages_stream); + messages_stream.set(new_messages_stream); }, } } }; - Ok(Box::pin(stream)) + Ok(stream) } pub fn stream_all_messages_with_callback( @@ -357,14 +402,16 @@ where let (tx, rx) = oneshot::channel(); let handle = tokio::spawn(async move { - let mut stream = Self::stream_all_messages(client).await?; + let stream = Self::stream_all_messages(&client).await?; let _ = tx.send(()); + futures::pin_mut!(stream); while let Some(message) = stream.next().await { match message { Ok(m) => callback(m), - Err(m) => log::error!("error during stream all messages {}", m), + Err(m) => tracing::error!("error during stream all messages {}", m), } } + tracing::debug!("`stream_all_messages` stream ended, dropping stream"); Ok(()) }); @@ -408,7 +455,8 @@ mod tests { let mut stream = tokio_stream::wrappers::UnboundedReceiverStream::new(rx); let bob_ptr = bob.clone(); tokio::spawn(async move { - let mut bob_stream = bob_ptr.stream_conversations().await.unwrap(); + let bob_stream = bob_ptr.stream_conversations(true).await.unwrap(); + futures::pin_mut!(bob_stream); while let Some(item) = bob_stream.next().await { let _ = tx.send(item); } @@ -445,7 +493,8 @@ mod tests { let notify_ptr = notify.clone(); let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); tokio::spawn(async move { - let mut stream = alice_group.stream(alice).await.unwrap(); + let stream = alice_group.stream(&alice).await.unwrap(); + futures::pin_mut!(stream); while let Some(item) = stream.next().await { let _ = tx.send(item); notify_ptr.notify_one(); @@ -693,7 +742,7 @@ mod tests { .unwrap(); } - let _ = tokio::time::timeout(std::time::Duration::from_secs(120), async { + let _ = tokio::time::timeout(std::time::Duration::from_secs(60), async { while blocked.load(Ordering::SeqCst) > 0 { tokio::task::yield_now().await; } @@ -716,12 +765,15 @@ mod tests { let notify = Delivery::new(None); let (notify_pointer, groups_pointer) = (notify.clone(), groups.clone()); - let closer = - Client::::stream_conversations_with_callback(alix.clone(), move |g| { + let closer = Client::::stream_conversations_with_callback( + alix.clone(), + move |g| { let mut groups = groups_pointer.lock(); groups.push(g); notify_pointer.notify_one(); - }); + }, + false, + ); alix.create_group(None, GroupMetadataOptions::default()) .unwrap(); @@ -762,4 +814,67 @@ mod tests { closer.handle.abort(); } + + #[tokio::test(flavor = "multi_thread")] + async fn test_dm_streaming() { + let alix = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); + let bo = Arc::new(ClientBuilder::new_test_client(&generate_local_wallet()).await); + + let groups = Arc::new(Mutex::new(Vec::new())); + // Wait for 2 seconds for the group creation to be streamed + let notify = Delivery::new(Some(std::time::Duration::from_secs(1))); + let (notify_pointer, groups_pointer) = (notify.clone(), groups.clone()); + + // Start a stream with enableDm set to false + let closer = Client::::stream_conversations_with_callback( + alix.clone(), + move |g| { + let mut groups = groups_pointer.lock(); + groups.push(g); + notify_pointer.notify_one(); + }, + false, + ); + + alix.create_dm_by_inbox_id(bo.inbox_id()).await.unwrap(); + + let result = notify.wait_for_delivery().await; + assert!(result.is_err(), "Stream unexpectedly received a DM group"); + + closer.handle.abort(); + + // Start a stream with enableDm set to true + let groups = Arc::new(Mutex::new(Vec::new())); + // Wait for 2 seconds for the group creation to be streamed + let notify = Delivery::new(Some(std::time::Duration::from_secs(60))); + let (notify_pointer, groups_pointer) = (notify.clone(), groups.clone()); + let closer = Client::::stream_conversations_with_callback( + alix.clone(), + move |g| { + let mut groups = groups_pointer.lock(); + groups.push(g); + notify_pointer.notify_one(); + }, + true, + ); + + alix.create_dm_by_inbox_id(bo.inbox_id()).await.unwrap(); + notify.wait_for_delivery().await.unwrap(); + { + let grps = groups.lock(); + assert_eq!(grps.len(), 1); + } + + let dm = bo.create_dm_by_inbox_id(alix.inbox_id()).await.unwrap(); + dm.add_members_by_inbox_id(&bo, vec![alix.inbox_id()]) + .await + .unwrap(); + notify.wait_for_delivery().await.unwrap(); + { + let grps = groups.lock(); + assert_eq!(grps.len(), 2); + } + + closer.handle.abort(); + } } diff --git a/xmtp_mls/src/utils/bench.rs b/xmtp_mls/src/utils/bench.rs index 61ac2d590..99f833cae 100644 --- a/xmtp_mls/src/utils/bench.rs +++ b/xmtp_mls/src/utils/bench.rs @@ -4,7 +4,6 @@ #![allow(clippy::unwrap_used)] use crate::{builder::ClientBuilder, Client}; -use ethers::signers::{LocalWallet, Signer}; use indicatif::{ProgressBar, ProgressStyle}; use once_cell::sync::OnceCell; use serde::{Deserialize, Serialize}; @@ -18,7 +17,8 @@ use tracing_subscriber::{ util::SubscriberInitExt, EnvFilter, }; -use xmtp_cryptography::utils::rng; +use xmtp_cryptography::utils::generate_local_wallet; +use xmtp_id::InboxOwner; use super::test::TestClient; @@ -126,13 +126,13 @@ impl Identity { } async fn create_identity(is_dev_network: bool) -> Identity { - let wallet = LocalWallet::new(&mut rng()); + let wallet = generate_local_wallet(); let client = if is_dev_network { ClientBuilder::new_dev_client(&wallet).await } else { ClientBuilder::new_test_client(&wallet).await }; - Identity::new(client.inbox_id(), format!("0x{:x}", wallet.address())) + Identity::new(client.inbox_id(), wallet.get_address()) } async fn create_identities(n: usize, is_dev_network: bool) -> Vec { @@ -181,7 +181,7 @@ pub async fn create_identities_if_dont_exist( ) -> Vec { match load_identities(is_dev_network) { Ok(identities) => { - log::info!( + tracing::info!( "Found generated identities at {}, checking for existence on backend...", file_path(is_dev_network) ); @@ -195,7 +195,7 @@ pub async fn create_identities_if_dont_exist( _ => (), } - log::info!( + tracing::info!( "Could not find any identitites to load, creating new identitites \n Beware, this fills $TMPDIR with ~10GBs of identities" ); diff --git a/xmtp_mls/src/utils/test.rs b/xmtp_mls/src/utils/test.rs index 5fc724d5e..ce5cbf7a8 100755 --- a/xmtp_mls/src/utils/test.rs +++ b/xmtp_mls/src/utils/test.rs @@ -3,17 +3,21 @@ use std::env; use rand::{ distributions::{Alphanumeric, DistString}, - Rng, + Rng, RngCore, }; use std::sync::Arc; use tokio::{sync::Notify, time::error::Elapsed}; use xmtp_api_grpc::grpc_api_helper::Client as GrpcClient; -use xmtp_id::associations::{generate_inbox_id, RecoverableEcdsaSignature}; +use xmtp_id::associations::{ + generate_inbox_id, + test_utils::MockSmartContractSignatureVerifier, + unverified::{UnverifiedRecoverableEcdsaSignature, UnverifiedSignature}, +}; use crate::{ builder::ClientBuilder, identity::IdentityStrategy, - storage::{EncryptedMessageStore, StorageOption}, + storage::{EncryptedConnection, EncryptedMessageStore, EncryptionKey, StorageOption}, types::Address, Client, InboxOwner, XmtpApi, XmtpTestClient, }; @@ -49,7 +53,6 @@ pub fn rand_time() -> i64 { rng.gen_range(0..1_000_000_000) } -#[async_trait::async_trait] #[cfg(feature = "http-api")] impl XmtpTestClient for XmtpHttpApiClient { async fn create_local() -> Self { @@ -61,7 +64,6 @@ impl XmtpTestClient for XmtpHttpApiClient { } } -#[async_trait::async_trait] impl XmtpTestClient for GrpcClient { async fn create_local() -> Self { GrpcClient::create("http://localhost:5556".into(), false) @@ -76,11 +78,29 @@ impl XmtpTestClient for GrpcClient { } } +impl EncryptedMessageStore { + pub fn generate_enc_key() -> EncryptionKey { + let mut key = [0u8; 32]; + xmtp_cryptography::utils::rng().fill_bytes(&mut key[..]); + key + } + + pub fn remove_db_files>(path: P) { + let path = path.as_ref(); + std::fs::remove_file(path).unwrap(); + std::fs::remove_file(EncryptedConnection::salt_file(path).unwrap()).unwrap(); + } +} + impl ClientBuilder { pub fn temp_store(self) -> Self { let tmpdb = tmp_path(); self.store( - EncryptedMessageStore::new_unencrypted(StorageOption::Persistent(tmpdb)).unwrap(), + EncryptedMessageStore::new( + StorageOption::Persistent(tmpdb), + EncryptedMessageStore::generate_enc_key(), + ) + .unwrap(), ) } @@ -100,6 +120,7 @@ impl ClientBuilder { nonce, None, )) + .scw_signature_verifier(MockSmartContractSignatureVerifier::new(true)) .temp_store() .local_client() .await @@ -174,11 +195,14 @@ impl Client { pub async fn register_client(client: &Client, owner: &impl InboxOwner) { let mut signature_request = client.context.signature_request().unwrap(); let signature_text = signature_request.signature_text(); + let unverified_signature = UnverifiedSignature::RecoverableEcdsa( + UnverifiedRecoverableEcdsaSignature::new(owner.sign(&signature_text).unwrap().into()), + ); signature_request - .add_signature(Box::new(RecoverableEcdsaSignature::new( - signature_text.clone(), - owner.sign(&signature_text).unwrap().into(), - ))) + .add_signature( + unverified_signature, + client.smart_contract_signature_verifier().as_ref(), + ) .await .unwrap(); diff --git a/xmtp_mls/src/verified_key_package.rs b/xmtp_mls/src/verified_key_package.rs deleted file mode 100644 index 0621d1355..000000000 --- a/xmtp_mls/src/verified_key_package.rs +++ /dev/null @@ -1,116 +0,0 @@ -use openmls::{ - credentials::{errors::BasicCredentialError, BasicCredential}, - prelude::{ - tls_codec::{Deserialize, Error as TlsCodecError}, - KeyPackage, KeyPackageIn, KeyPackageVerifyError, - }, -}; - -use openmls_rust_crypto::RustCrypto; -use thiserror::Error; - -use crate::{ - configuration::MLS_PROTOCOL_VERSION, - credential::{get_validated_account_address, AssociationError}, - identity::IdentityError, - types::Address, -}; - -#[derive(Debug, Error)] -pub enum KeyPackageVerificationError { - #[error("TLS Codec error: {0}")] - TlsError(#[from] TlsCodecError), - #[error("mls validation: {0}")] - MlsValidation(#[from] KeyPackageVerifyError), - #[error("identity: {0}")] - Identity(#[from] IdentityError), - #[error("invalid application id")] - InvalidApplicationId, - #[error("application id ({0}) does not match the credential address ({1}).")] - ApplicationIdCredentialMismatch(String, String), - #[error("invalid credential")] - InvalidCredential, - #[error(transparent)] - Association(#[from] AssociationError), - #[error("generic: {0}")] - Generic(String), - #[error("wrong credential type")] - WrongCredentialType(#[from] BasicCredentialError), -} - -#[derive(Debug, Clone, PartialEq)] -pub struct VerifiedKeyPackage { - pub inner: KeyPackage, - pub account_address: String, -} - -impl VerifiedKeyPackage { - pub fn new(inner: KeyPackage, account_address: String) -> Self { - Self { - inner, - account_address, - } - } - - /// Validates starting with a KeyPackage (which is already validated by OpenMLS) - pub fn from_key_package(kp: KeyPackage) -> Result { - let leaf_node = kp.leaf_node(); - let basic_credential = BasicCredential::try_from(leaf_node.credential().clone())?; - let pub_key_bytes = leaf_node.signature_key().as_slice(); - let account_address = - identity_to_account_address(basic_credential.identity(), pub_key_bytes)?; - let application_id = extract_application_id(&kp)?; - if !account_address.eq(&application_id) { - return Err( - KeyPackageVerificationError::ApplicationIdCredentialMismatch( - application_id, - account_address, - ), - ); - } - - Ok(Self::new(kp, account_address)) - } - - // Validates starting with a KeyPackageIn as bytes (which is not validated by OpenMLS) - pub fn from_bytes( - crypto_provider: &RustCrypto, - data: &[u8], - ) -> Result { - let kp_in: KeyPackageIn = KeyPackageIn::tls_deserialize_exact(data)?; - let kp = kp_in.validate(crypto_provider, MLS_PROTOCOL_VERSION)?; - - Self::from_key_package(kp) - } - - pub fn installation_id(&self) -> Vec { - self.inner.leaf_node().signature_key().as_slice().to_vec() - } - - pub fn hpke_init_key(&self) -> Vec { - self.inner.hpke_init_key().as_slice().to_vec() - } -} - -fn identity_to_account_address( - credential_bytes: &[u8], - installation_key_bytes: &[u8], -) -> Result { - Ok(get_validated_account_address( - credential_bytes, - installation_key_bytes, - )?) -} - -fn extract_application_id(kp: &KeyPackage) -> Result { - let application_id_bytes = kp - .leaf_node() - .extensions() - .application_id() - .ok_or_else(|| KeyPackageVerificationError::InvalidApplicationId)? - .as_slice() - .to_vec(); - - String::from_utf8(application_id_bytes) - .map_err(|_| KeyPackageVerificationError::InvalidApplicationId) -} diff --git a/xmtp_proto/Cargo.toml b/xmtp_proto/Cargo.toml index b231be0f7..f81cc9b15 100644 --- a/xmtp_proto/Cargo.toml +++ b/xmtp_proto/Cargo.toml @@ -4,51 +4,37 @@ name = "xmtp_proto" version.workspace = true [dependencies] -async-trait = { workspace = true } futures = { workspace = true } -futures-core = { workspace = true } pbjson-types.workspace = true pbjson.workspace = true prost = { workspace = true, features = ["prost-derive"] } # Only necessary if using Protobuf well-known types: prost-types = { workspace = true } serde = { workspace = true } -openmls_basic_credential = { workspace = true, optional = true } openmls = { workspace = true, optional = true } +trait-variant = "0.1.2" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tonic = { workspace = true } [features] -convert = ["openmls_basic_credential", "openmls", "proto_full"] +convert = ["openmls", "proto_full"] default = [] # @@protoc_deletion_point(features) # This section is automatically generated by protoc-gen-prost-crate. # Changes in this area may be lost on regeneration. -proto_full = [ - "xmtp-identity", - "xmtp-identity-api-v1", - "xmtp-identity-associations", - "xmtp-keystore_api-v1", - "xmtp-message_api-v1", - "xmtp-message_contents", - "xmtp-mls-api-v1", - "xmtp-mls-database", - "xmtp-mls-message_contents", - "xmtp-mls_validation-v1", - "xmtp-xmtpv4", -] +proto_full = ["xmtp-identity","xmtp-identity-api-v1","xmtp-identity-associations","xmtp-keystore_api-v1","xmtp-message_api-v1","xmtp-message_contents","xmtp-mls-api-v1","xmtp-mls-database","xmtp-mls-message_contents","xmtp-mls_validation-v1","xmtp-xmtpv4"] "xmtp-identity" = [] -"xmtp-identity-api-v1" = ["xmtp-identity", "xmtp-identity-associations"] -"xmtp-identity-associations" = ["xmtp-identity", "xmtp-message_contents"] +"xmtp-identity-api-v1" = ["xmtp-identity","xmtp-identity-associations"] +"xmtp-identity-associations" = ["xmtp-identity","xmtp-message_contents"] "xmtp-keystore_api-v1" = ["xmtp-message_contents"] "xmtp-message_api-v1" = ["xmtp-message_contents"] "xmtp-message_contents" = [] "xmtp-mls-api-v1" = ["xmtp-message_contents"] "xmtp-mls-database" = [] -"xmtp-mls-message_contents" = ["xmtp-message_contents"] -"xmtp-mls_validation-v1" = ["xmtp-identity-associations"] -"xmtp-xmtpv4" = ["xmtp-identity-associations", "xmtp-mls-api-v1"] -## @@protoc_insertion_point(features) +"xmtp-mls-message_contents" = [] +"xmtp-mls_validation-v1" = ["xmtp-identity-api-v1","xmtp-identity-associations"] +"xmtp-xmtpv4" = ["xmtp-identity-associations","xmtp-mls-api-v1"] +## @@protoc_insertion_point(features) \ No newline at end of file diff --git a/xmtp_proto/src/api_client.rs b/xmtp_proto/src/api_client.rs index cd0dd6160..60db8e4e9 100644 --- a/xmtp_proto/src/api_client.rs +++ b/xmtp_proto/src/api_client.rs @@ -1,7 +1,6 @@ use std::{error::Error as StdError, fmt}; -use async_trait::async_trait; -use futures::{stream, Stream}; +use futures::Stream; pub use super::xmtp::message_api::v1::{ BatchQueryRequest, BatchQueryResponse, Envelope, PagingInfo, PublishRequest, PublishResponse, @@ -103,22 +102,28 @@ pub trait XmtpApiSubscription { fn close_stream(&mut self); } -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[allow(async_fn_in_trait)] pub trait MutableApiSubscription: Stream> + Send { async fn update(&mut self, req: SubscribeRequest) -> Result<(), Error>; fn close(&self); } -pub trait ClientWithMetadata: Send + Sync { +pub trait ClientWithMetadata { fn set_libxmtp_version(&mut self, version: String) -> Result<(), Error>; fn set_app_version(&mut self, version: String) -> Result<(), Error>; } +/// Global Marker trait for WebAssembly +#[cfg(target_arch = "wasm32")] +pub trait Wasm {} +#[cfg(target_arch = "wasm32")] +impl Wasm for T {} + // Wasm futures don't have `Send` or `Sync` bounds. -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -pub trait XmtpApiClient: Send + Sync { +#[allow(async_fn_in_trait)] +#[cfg_attr(not(target_arch = "wasm32"), trait_variant::make(XmtpApiClient: Send))] +#[cfg_attr(target_arch = "wasm32", trait_variant::make(XmtpApiClient: Wasm))] +pub trait LocalXmtpApiClient { type Subscription: XmtpApiSubscription; type MutableSubscription: MutableApiSubscription; @@ -140,20 +145,11 @@ pub trait XmtpApiClient: Send + Sync { async fn batch_query(&self, request: BatchQueryRequest) -> Result; } -#[cfg(not(target_arch = "wasm32"))] -pub type GroupMessageStream = stream::BoxStream<'static, Result>; -#[cfg(target_arch = "wasm32")] -pub type GroupMessageStream = stream::LocalBoxStream<'static, Result>; - -#[cfg(not(target_arch = "wasm32"))] -pub type WelcomeMessageStream = stream::BoxStream<'static, Result>; -#[cfg(target_arch = "wasm32")] -pub type WelcomeMessageStream = stream::LocalBoxStream<'static, Result>; - // Wasm futures don't have `Send` or `Sync` bounds. -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -pub trait XmtpMlsClient: Send + Sync + 'static { +#[allow(async_fn_in_trait)] +#[cfg_attr(not(target_arch = "wasm32"), trait_variant::make(XmtpMlsClient: Send))] +#[cfg_attr(target_arch = "wasm32", trait_variant::make(XmtpMlsClient: Wasm))] +pub trait LocalXmtpMlsClient { async fn upload_key_package(&self, request: UploadKeyPackageRequest) -> Result<(), Error>; async fn fetch_key_packages( &self, @@ -170,20 +166,57 @@ pub trait XmtpMlsClient: Send + Sync + 'static { &self, request: QueryWelcomeMessagesRequest, ) -> Result; +} + +#[allow(async_fn_in_trait)] +#[cfg_attr(target_arch = "wasm32", trait_variant::make(XmtpMlsStreams: Wasm))] +pub trait LocalXmtpMlsStreams { + type GroupMessageStream<'a>: Stream> + 'a + where + Self: 'a; + + type WelcomeMessageStream<'a>: Stream> + 'a + where + Self: 'a; + async fn subscribe_group_messages( &self, request: SubscribeGroupMessagesRequest, - ) -> Result; + ) -> Result, Error>; async fn subscribe_welcome_messages( &self, request: SubscribeWelcomeMessagesRequest, - ) -> Result; + ) -> Result, Error>; } -// Wasm futures don't have `Send` or `Sync` bounds. -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -pub trait XmtpIdentityClient: Send + Sync + 'static { +// we manually make a Local+Non-Local trait variant here b/c the +// macro breaks with GATs +#[allow(async_fn_in_trait)] +#[cfg(not(target_arch = "wasm32"))] +pub trait XmtpMlsStreams: Send { + type GroupMessageStream<'a>: Stream> + Send + 'a + where + Self: 'a; + + type WelcomeMessageStream<'a>: Stream> + Send + 'a + where + Self: 'a; + + fn subscribe_group_messages( + &self, + request: SubscribeGroupMessagesRequest, + ) -> impl futures::Future, Error>> + Send; + + fn subscribe_welcome_messages( + &self, + request: SubscribeWelcomeMessagesRequest, + ) -> impl futures::Future, Error>> + Send; +} + +#[allow(async_fn_in_trait)] +#[cfg_attr(not(target_arch = "wasm32"), trait_variant::make(XmtpIdentityClient: Send))] +#[cfg_attr(target_arch = "wasm32", trait_variant::make(XmtpIdentityClient: Wasm))] +pub trait LocalXmtpIdentityClient { async fn publish_identity_update( &self, request: PublishIdentityUpdateRequest, diff --git a/xmtp_proto/src/gen/xmtp.identity.api.v1.rs b/xmtp_proto/src/gen/xmtp.identity.api.v1.rs index 0b77836b7..0def39e97 100644 --- a/xmtp_proto/src/gen/xmtp.identity.api.v1.rs +++ b/xmtp_proto/src/gen/xmtp.identity.api.v1.rs @@ -1,5 +1,37 @@ // @generated // This file is @generated by prost-build. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VerifySmartContractWalletSignaturesRequest { + #[prost(message, repeated, tag="1")] + pub signatures: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UnverifiedSmartContractWalletSignature { + #[prost(message, optional, tag="1")] + pub scw_signature: ::core::option::Option, + /// SHA256 hash of the signature payload + #[prost(bytes="vec", tag="5")] + pub hash: ::prost::alloc::vec::Vec, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VerifySmartContractWalletSignaturesResponse { + #[prost(message, repeated, tag="1")] + pub responses: ::prost::alloc::vec::Vec, +} +/// Nested message and enum types in `VerifySmartContractWalletSignaturesResponse`. +pub mod verify_smart_contract_wallet_signatures_response { + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct ValidationResponse { + #[prost(bool, tag="1")] + pub is_valid: bool, + #[prost(string, optional, tag="2")] + pub error: ::core::option::Option<::prost::alloc::string::String>, + } +} /// Publishes an identity update to the network #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -100,7 +132,7 @@ pub mod get_inbox_ids_response { } /// Encoded file descriptor set for the `xmtp.identity.api.v1` package pub const FILE_DESCRIPTOR_SET: &[u8] = &[ - 0x0a, 0xae, 0x26, 0x0a, 0x1e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x70, + 0x0a, 0xcb, 0x32, 0x0a, 0x1e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, @@ -108,306 +140,403 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, - 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, - 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x73, 0x0a, 0x1c, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x53, 0x0a, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x1f, 0x0a, 0x1d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x53, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, - 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x45, 0x0a, 0x07, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, - 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, - 0x22, 0xa6, 0x03, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x57, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x1a, 0x25, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, + 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, + 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8a, 0x01, 0x0a, 0x2a, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5c, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x53, 0x6d, 0x61, 0x72, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x26, 0x55, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x69, 0x65, 0x64, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, + 0x5d, 0x0a, 0x0d, 0x73, 0x63, 0x77, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x0c, 0x73, 0x63, 0x77, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, + 0x73, 0x68, 0x22, 0xf7, 0x01, 0x0a, 0x2b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x6d, 0x61, + 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x72, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x54, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x12, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x69, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x88, + 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x73, 0x0a, 0x1c, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x53, 0x0a, 0x0f, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x22, 0x1f, 0x0a, 0x1d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x49, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0xb7, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x53, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0xa8, 0x01, 0x0a, 0x11, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x12, 0x1f, - 0x0a, 0x0b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x0a, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, - 0x2e, 0x0a, 0x13, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, - 0x42, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, - 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x06, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x1a, 0x83, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x45, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x5c, 0x0a, 0x07, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, - 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x4c, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, - 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x23, - 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x22, 0xba, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, - 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x09, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, + 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, + 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0a, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x22, 0xa6, 0x03, 0x0a, + 0x1a, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x09, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x1a, 0xa8, 0x01, 0x0a, 0x11, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0a, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, + 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, + 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x1a, + 0x83, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x5c, 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x52, 0x07, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, + 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x08, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x51, 0x0a, - 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, - 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, - 0x32, 0xf5, 0x03, 0x0a, 0x0b, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x70, 0x69, - 0x12, 0xb1, 0x01, 0x0a, 0x15, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x78, 0x6d, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x23, 0x0a, 0x07, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, + 0xba, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x51, 0x0a, 0x08, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x1e, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, + 0x0b, 0x0a, 0x09, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x32, 0xe3, 0x05, 0x0a, + 0x0b, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x70, 0x69, 0x12, 0xb1, 0x01, 0x0a, + 0x15, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x73, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, - 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x73, 0x68, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2d, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x12, 0xa5, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x2d, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x89, 0x01, 0x0a, - 0x0b, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x12, 0x28, 0x2e, 0x78, + 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x3a, 0x01, 0x2a, 0x22, 0x24, 0x2f, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, + 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x12, 0xa5, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x26, 0x3a, 0x01, 0x2a, 0x22, 0x21, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x2d, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x89, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x12, 0x28, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, + 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x2d, 0x69, 0x6e, 0x62, 0x6f, 0x78, + 0x2d, 0x69, 0x64, 0x73, 0x12, 0xeb, 0x01, 0x0a, 0x23, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, + 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x40, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x2d, 0x69, - 0x6e, 0x62, 0x6f, 0x78, 0x2d, 0x69, 0x64, 0x73, 0x42, 0xdb, 0x01, 0x92, 0x41, 0x14, 0x12, 0x12, - 0x0a, 0x0b, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x70, 0x69, 0x32, 0x03, 0x31, - 0x2e, 0x30, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x26, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x58, 0x49, 0x41, 0xaa, 0x02, 0x14, 0x58, 0x6d, - 0x74, 0x70, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x41, 0x70, 0x69, 0x2e, - 0x56, 0x31, 0xca, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, - 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x17, 0x58, - 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x41, - 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x4a, 0xe0, 0x16, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x68, - 0x01, 0x0a, 0x17, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x0d, 0x20, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, - 0x03, 0x02, 0x00, 0x1d, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x04, 0x00, 0x26, 0x0a, - 0x09, 0x0a, 0x02, 0x03, 0x01, 0x12, 0x03, 0x05, 0x00, 0x31, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, - 0x12, 0x03, 0x06, 0x00, 0x38, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x08, 0x00, 0x3d, 0x0a, - 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x08, 0x00, 0x3d, 0x0a, 0x09, 0x0a, 0x01, 0x08, 0x12, - 0x04, 0x0a, 0x00, 0x0f, 0x02, 0x0a, 0x0b, 0x0a, 0x03, 0x08, 0x92, 0x08, 0x12, 0x04, 0x0a, 0x00, - 0x0f, 0x02, 0x0a, 0x0c, 0x0a, 0x04, 0x08, 0x92, 0x08, 0x02, 0x12, 0x04, 0x0b, 0x02, 0x0e, 0x03, - 0x0a, 0x0c, 0x0a, 0x05, 0x08, 0x92, 0x08, 0x02, 0x01, 0x12, 0x03, 0x0c, 0x04, 0x18, 0x0a, 0x0c, - 0x0a, 0x05, 0x08, 0x92, 0x08, 0x02, 0x06, 0x12, 0x03, 0x0d, 0x04, 0x12, 0x0a, 0x26, 0x0a, 0x02, - 0x06, 0x00, 0x12, 0x04, 0x12, 0x00, 0x2d, 0x01, 0x1a, 0x1a, 0x20, 0x52, 0x50, 0x43, 0x73, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x4d, 0x4c, 0x53, 0x20, - 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x06, 0x00, 0x01, 0x12, 0x03, 0x12, 0x08, 0x13, - 0x0a, 0x9d, 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x00, 0x12, 0x04, 0x15, 0x02, 0x1a, 0x03, 0x1a, - 0x8e, 0x01, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x58, 0x49, 0x44, 0x20, 0x6f, 0x72, 0x20, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x0a, 0x20, 0x63, 0x6f, - 0x6e, 0x73, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, - 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, - 0x6e, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x15, 0x06, 0x1b, 0x0a, 0x0c, - 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x15, 0x1c, 0x38, 0x0a, 0x0c, 0x0a, 0x05, - 0x06, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x15, 0x43, 0x60, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, - 0x02, 0x00, 0x04, 0x12, 0x04, 0x16, 0x04, 0x19, 0x06, 0x0a, 0x11, 0x0a, 0x09, 0x06, 0x00, 0x02, - 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x04, 0x16, 0x04, 0x19, 0x06, 0x0a, 0x11, 0x0a, 0x0a, - 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x03, 0x17, 0x06, 0x32, 0x0a, - 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x03, 0x18, - 0x06, 0x0f, 0x0a, 0xc6, 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x01, 0x12, 0x04, 0x1f, 0x02, 0x24, - 0x03, 0x1a, 0xb7, 0x01, 0x20, 0x55, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x65, - 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x0a, 0x20, 0x57, - 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x61, - 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6e, 0x65, 0x77, 0x20, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x0a, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x72, 0x65, 0x76, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, - 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, - 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x1f, 0x06, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, - 0x01, 0x02, 0x12, 0x03, 0x1f, 0x19, 0x32, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x03, - 0x12, 0x03, 0x1f, 0x3d, 0x57, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x04, 0x12, 0x04, - 0x20, 0x04, 0x23, 0x06, 0x0a, 0x11, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, - 0x22, 0x12, 0x04, 0x20, 0x04, 0x23, 0x06, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x01, 0x04, - 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x03, 0x21, 0x06, 0x2f, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, - 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x03, 0x22, 0x06, 0x0f, 0x0a, 0x39, 0x0a, - 0x04, 0x06, 0x00, 0x02, 0x02, 0x12, 0x04, 0x27, 0x02, 0x2c, 0x03, 0x1a, 0x2b, 0x20, 0x52, 0x65, - 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x58, 0x49, 0x44, 0x73, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, - 0x01, 0x12, 0x03, 0x27, 0x06, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x02, 0x12, - 0x03, 0x27, 0x12, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x27, - 0x2f, 0x42, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x04, 0x12, 0x04, 0x28, 0x04, 0x2b, - 0x06, 0x0a, 0x11, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x04, - 0x28, 0x04, 0x2b, 0x06, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, - 0x22, 0x04, 0x12, 0x03, 0x29, 0x06, 0x28, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x02, 0x04, - 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x03, 0x2a, 0x06, 0x0f, 0x0a, 0x39, 0x0a, 0x02, 0x04, 0x00, - 0x12, 0x04, 0x30, 0x00, 0x32, 0x01, 0x1a, 0x2d, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, + 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x6d, 0x61, 0x72, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x3f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x39, 0x3a, 0x01, 0x2a, 0x22, 0x34, 0x2f, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x2d, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x2d, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2d, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x42, 0xdb, 0x01, 0x92, 0x41, 0x14, 0x12, 0x12, 0x0a, 0x0b, 0x49, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x41, 0x70, 0x69, 0x32, 0x03, 0x31, 0x2e, 0x30, 0x0a, 0x18, 0x63, 0x6f, + 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, + 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0xa2, + 0x02, 0x03, 0x58, 0x49, 0x41, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x14, 0x58, + 0x6d, 0x74, 0x70, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, 0x70, 0x69, + 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x17, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, + 0x4a, 0xc3, 0x1c, 0x0a, 0x07, 0x12, 0x05, 0x01, 0x00, 0x84, 0x01, 0x01, 0x0a, 0x17, 0x0a, 0x01, + 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x0d, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x02, 0x00, 0x1d, 0x0a, + 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x04, 0x00, 0x26, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x01, + 0x12, 0x03, 0x05, 0x00, 0x31, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, 0x12, 0x03, 0x06, 0x00, 0x2f, + 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x03, 0x12, 0x03, 0x07, 0x00, 0x38, 0x0a, 0x08, 0x0a, 0x01, 0x08, + 0x12, 0x03, 0x09, 0x00, 0x3d, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x09, 0x00, 0x3d, + 0x0a, 0x09, 0x0a, 0x01, 0x08, 0x12, 0x04, 0x0b, 0x00, 0x10, 0x02, 0x0a, 0x0b, 0x0a, 0x03, 0x08, + 0x92, 0x08, 0x12, 0x04, 0x0b, 0x00, 0x10, 0x02, 0x0a, 0x0c, 0x0a, 0x04, 0x08, 0x92, 0x08, 0x02, + 0x12, 0x04, 0x0c, 0x02, 0x0f, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x08, 0x92, 0x08, 0x02, 0x01, 0x12, + 0x03, 0x0d, 0x04, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x08, 0x92, 0x08, 0x02, 0x06, 0x12, 0x03, 0x0e, + 0x04, 0x12, 0x0a, 0x26, 0x0a, 0x02, 0x06, 0x00, 0x12, 0x04, 0x13, 0x00, 0x36, 0x01, 0x1a, 0x1a, + 0x20, 0x52, 0x50, 0x43, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, + 0x77, 0x20, 0x4d, 0x4c, 0x53, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x06, 0x00, + 0x01, 0x12, 0x03, 0x13, 0x08, 0x13, 0x0a, 0x9d, 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x00, 0x12, + 0x04, 0x16, 0x02, 0x1b, 0x03, 0x1a, 0x8e, 0x01, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x30, 0x08, - 0x24, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x31, 0x02, 0x40, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x31, 0x02, 0x2b, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x31, 0x2c, 0x3b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x31, 0x3e, 0x3f, 0x0a, 0x3e, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x03, - 0x35, 0x00, 0x28, 0x1a, 0x33, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, - 0x03, 0x35, 0x08, 0x25, 0x0a, 0x46, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x38, 0x00, 0x41, 0x01, - 0x1a, 0x3a, 0x20, 0x47, 0x65, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x20, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, - 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, - 0x04, 0x02, 0x01, 0x12, 0x03, 0x38, 0x08, 0x21, 0x0a, 0x8f, 0x01, 0x0a, 0x04, 0x04, 0x02, 0x03, - 0x00, 0x12, 0x04, 0x3b, 0x02, 0x3e, 0x03, 0x1a, 0x80, 0x01, 0x20, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x68, - 0x61, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2e, 0x20, 0x54, 0x68, 0x65, - 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x20, 0x73, 0x68, 0x6f, - 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x0a, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x30, - 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x68, - 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, - 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, - 0x03, 0x00, 0x01, 0x12, 0x03, 0x3b, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, - 0x02, 0x00, 0x12, 0x03, 0x3c, 0x04, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, - 0x00, 0x05, 0x12, 0x03, 0x3c, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, - 0x00, 0x01, 0x12, 0x03, 0x3c, 0x0b, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, - 0x00, 0x03, 0x12, 0x03, 0x3c, 0x16, 0x17, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, - 0x01, 0x12, 0x03, 0x3d, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, - 0x05, 0x12, 0x03, 0x3d, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, - 0x01, 0x12, 0x03, 0x3d, 0x0b, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, - 0x03, 0x12, 0x03, 0x3d, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, - 0x40, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x04, 0x12, 0x03, 0x40, 0x02, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x40, 0x0b, 0x12, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x40, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x40, 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, 0x04, - 0x03, 0x12, 0x04, 0x44, 0x00, 0x53, 0x01, 0x1a, 0x36, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, - 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, - 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x65, 0x64, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x0a, 0x0a, - 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x44, 0x08, 0x22, 0x0a, 0x3c, 0x0a, 0x04, 0x04, - 0x03, 0x03, 0x00, 0x12, 0x04, 0x46, 0x02, 0x4a, 0x03, 0x1a, 0x2e, 0x20, 0x41, 0x20, 0x73, 0x69, - 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x58, 0x49, 0x44, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x03, - 0x00, 0x01, 0x12, 0x03, 0x46, 0x0a, 0x1b, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, - 0x00, 0x12, 0x03, 0x47, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, - 0x05, 0x12, 0x03, 0x47, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x47, 0x0b, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, - 0x03, 0x12, 0x03, 0x47, 0x19, 0x1a, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, - 0x12, 0x03, 0x48, 0x04, 0x23, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x05, - 0x12, 0x03, 0x48, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, - 0x12, 0x03, 0x48, 0x0b, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x03, - 0x12, 0x03, 0x48, 0x21, 0x22, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x12, - 0x03, 0x49, 0x04, 0x39, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x06, 0x12, - 0x03, 0x49, 0x04, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x49, 0x2e, 0x34, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, - 0x03, 0x49, 0x37, 0x38, 0x0a, 0x54, 0x0a, 0x04, 0x04, 0x03, 0x03, 0x01, 0x12, 0x04, 0x4d, 0x02, - 0x50, 0x03, 0x1a, 0x46, 0x20, 0x54, 0x68, 0x65, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, - 0x6c, 0x6f, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, - 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x69, 0x6e, 0x67, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, - 0x73, 0x74, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, - 0x03, 0x01, 0x01, 0x12, 0x03, 0x4d, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x01, - 0x02, 0x00, 0x12, 0x03, 0x4e, 0x04, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, 0x02, - 0x00, 0x05, 0x12, 0x03, 0x4e, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, 0x02, - 0x00, 0x01, 0x12, 0x03, 0x4e, 0x0b, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, 0x02, - 0x00, 0x03, 0x12, 0x03, 0x4e, 0x16, 0x17, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x01, 0x02, - 0x01, 0x12, 0x03, 0x4f, 0x04, 0x2b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, 0x02, 0x01, - 0x04, 0x12, 0x03, 0x4f, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, 0x02, 0x01, - 0x06, 0x12, 0x03, 0x4f, 0x0d, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, 0x02, 0x01, - 0x01, 0x12, 0x03, 0x4f, 0x1f, 0x26, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x01, 0x02, 0x01, - 0x03, 0x12, 0x03, 0x4f, 0x29, 0x2a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, - 0x52, 0x02, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x04, 0x12, 0x03, 0x52, 0x02, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, 0x12, 0x03, 0x52, 0x0b, 0x13, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x52, 0x14, 0x1d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x52, 0x20, 0x21, 0x0a, 0x42, 0x0a, 0x02, 0x04, - 0x04, 0x12, 0x04, 0x56, 0x00, 0x5d, 0x01, 0x1a, 0x36, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x58, 0x49, 0x44, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, - 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, 0x0a, - 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x56, 0x08, 0x1a, 0x0a, 0x34, 0x0a, 0x04, 0x04, - 0x04, 0x03, 0x00, 0x12, 0x04, 0x58, 0x02, 0x5a, 0x03, 0x1a, 0x26, 0x20, 0x41, 0x20, 0x73, 0x69, - 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x03, 0x00, 0x01, 0x12, 0x03, 0x58, 0x0a, 0x11, 0x0a, - 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x59, 0x04, 0x17, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x59, 0x04, 0x0a, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x59, 0x0b, 0x12, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x59, 0x15, 0x16, 0x0a, 0x0b, - 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x5c, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x04, 0x02, 0x00, 0x04, 0x12, 0x03, 0x5c, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, - 0x00, 0x06, 0x12, 0x03, 0x5c, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x5c, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x5c, 0x1e, 0x1f, 0x0a, 0x40, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x60, 0x00, 0x68, 0x01, 0x1a, - 0x34, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x58, 0x49, 0x44, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, 0x60, 0x08, - 0x1b, 0x0a, 0x35, 0x0a, 0x04, 0x04, 0x05, 0x03, 0x00, 0x12, 0x04, 0x62, 0x02, 0x65, 0x03, 0x1a, - 0x27, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x03, 0x00, - 0x01, 0x12, 0x03, 0x62, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, - 0x12, 0x03, 0x63, 0x04, 0x17, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x05, - 0x12, 0x03, 0x63, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x63, 0x0b, 0x12, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x63, 0x15, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x12, - 0x03, 0x64, 0x04, 0x21, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x04, 0x12, - 0x03, 0x64, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, - 0x03, 0x64, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, - 0x03, 0x64, 0x14, 0x1c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, - 0x03, 0x64, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x67, 0x02, - 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x04, 0x12, 0x03, 0x67, 0x02, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x06, 0x12, 0x03, 0x67, 0x0b, 0x13, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x67, 0x14, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x67, 0x20, 0x21, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x58, 0x49, 0x44, + 0x20, 0x6f, 0x72, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x20, 0x41, 0x6e, 0x20, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x6d, + 0x61, 0x79, 0x0a, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6d, + 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x20, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, + 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x69, + 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x16, 0x06, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x16, + 0x1c, 0x38, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x16, 0x43, 0x60, + 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x04, 0x12, 0x04, 0x17, 0x04, 0x1a, 0x06, 0x0a, + 0x11, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x04, 0x17, 0x04, + 0x1a, 0x06, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, + 0x12, 0x03, 0x18, 0x06, 0x32, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, + 0xbc, 0x22, 0x07, 0x12, 0x03, 0x19, 0x06, 0x0f, 0x0a, 0xc6, 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, + 0x01, 0x12, 0x04, 0x20, 0x02, 0x25, 0x03, 0x1a, 0xb7, 0x01, 0x20, 0x55, 0x73, 0x65, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x2e, 0x0a, 0x20, 0x57, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x0a, 0x20, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, + 0x20, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x2e, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x20, 0x06, 0x18, 0x0a, + 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x20, 0x19, 0x32, 0x0a, 0x0c, 0x0a, + 0x05, 0x06, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x20, 0x3d, 0x57, 0x0a, 0x0d, 0x0a, 0x05, 0x06, + 0x00, 0x02, 0x01, 0x04, 0x12, 0x04, 0x21, 0x04, 0x24, 0x06, 0x0a, 0x11, 0x0a, 0x09, 0x06, 0x00, + 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x04, 0x21, 0x04, 0x24, 0x06, 0x0a, 0x11, 0x0a, + 0x0a, 0x06, 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x03, 0x22, 0x06, 0x2f, + 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x03, + 0x23, 0x06, 0x0f, 0x0a, 0x39, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x02, 0x12, 0x04, 0x28, 0x02, 0x2d, + 0x03, 0x1a, 0x2b, 0x20, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x58, 0x49, 0x44, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, + 0x76, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x28, 0x06, 0x11, 0x0a, 0x0c, 0x0a, 0x05, + 0x06, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x28, 0x12, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, + 0x02, 0x02, 0x03, 0x12, 0x03, 0x28, 0x2f, 0x42, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, + 0x04, 0x12, 0x04, 0x29, 0x04, 0x2c, 0x06, 0x0a, 0x11, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x02, 0x04, + 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x04, 0x29, 0x04, 0x2c, 0x06, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, + 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x03, 0x2a, 0x06, 0x28, 0x0a, 0x11, 0x0a, + 0x0a, 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x03, 0x2b, 0x06, 0x0f, + 0x0a, 0x44, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x03, 0x12, 0x04, 0x30, 0x02, 0x35, 0x03, 0x1a, 0x36, + 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x20, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x01, 0x12, + 0x03, 0x30, 0x06, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, 0x30, + 0x2a, 0x54, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x03, 0x12, 0x04, 0x30, 0x5f, 0x8a, + 0x01, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x04, 0x12, 0x04, 0x31, 0x04, 0x34, 0x06, + 0x0a, 0x11, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x03, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x04, 0x31, + 0x04, 0x34, 0x06, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x03, 0x04, 0xb0, 0xca, 0xbc, 0x22, + 0x04, 0x12, 0x03, 0x32, 0x06, 0x42, 0x0a, 0x11, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x03, 0x04, 0xb0, + 0xca, 0xbc, 0x22, 0x07, 0x12, 0x03, 0x33, 0x06, 0x0f, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x00, 0x12, + 0x04, 0x38, 0x00, 0x3a, 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x38, 0x08, + 0x32, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x39, 0x02, 0x41, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, 0x39, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x39, 0x0b, 0x31, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x39, 0x32, 0x3c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x39, 0x3f, 0x40, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x3c, 0x00, + 0x40, 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x3c, 0x08, 0x2e, 0x0a, 0x0b, + 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x3d, 0x02, 0x4c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x3d, 0x02, 0x39, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x3d, 0x3a, 0x47, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, + 0x12, 0x03, 0x3d, 0x4a, 0x4b, 0x0a, 0x33, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x3f, + 0x02, 0x11, 0x1a, 0x26, 0x20, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x20, 0x68, 0x61, 0x73, 0x68, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, + 0x02, 0x01, 0x05, 0x12, 0x03, 0x3f, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, + 0x01, 0x12, 0x03, 0x3f, 0x08, 0x0c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, + 0x03, 0x3f, 0x0f, 0x10, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x42, 0x00, 0x49, 0x01, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x42, 0x08, 0x33, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x43, 0x02, 0x46, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x03, 0x00, 0x01, 0x12, 0x03, 0x43, 0x0a, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, + 0x02, 0x00, 0x12, 0x03, 0x44, 0x04, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, + 0x00, 0x05, 0x12, 0x03, 0x44, 0x04, 0x08, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x44, 0x09, 0x11, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, + 0x00, 0x03, 0x12, 0x03, 0x44, 0x14, 0x15, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, + 0x01, 0x12, 0x03, 0x45, 0x04, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, + 0x04, 0x12, 0x03, 0x45, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, + 0x05, 0x12, 0x03, 0x45, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, + 0x01, 0x12, 0x03, 0x45, 0x14, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x45, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, + 0x48, 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x04, 0x12, 0x03, 0x48, 0x02, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x48, 0x0b, 0x1d, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x48, 0x1e, 0x27, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x48, 0x2a, 0x2b, 0x0a, 0x39, 0x0a, 0x02, 0x04, + 0x03, 0x12, 0x04, 0x4c, 0x00, 0x4e, 0x01, 0x1a, 0x2d, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x4c, + 0x08, 0x24, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x4d, 0x02, 0x40, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, 0x12, 0x03, 0x4d, 0x02, 0x2b, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x4d, 0x2c, 0x3b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x4d, 0x3e, 0x3f, 0x0a, 0x3e, 0x0a, 0x02, 0x04, 0x04, 0x12, + 0x03, 0x51, 0x00, 0x28, 0x1a, 0x33, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, + 0x12, 0x03, 0x51, 0x08, 0x25, 0x0a, 0x46, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x54, 0x00, 0x5d, + 0x01, 0x1a, 0x3a, 0x20, 0x47, 0x65, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x20, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, + 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, 0x54, 0x08, 0x21, 0x0a, 0x8f, 0x01, 0x0a, 0x04, 0x04, 0x05, + 0x03, 0x00, 0x12, 0x04, 0x57, 0x02, 0x5a, 0x03, 0x1a, 0x80, 0x01, 0x20, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, + 0x68, 0x61, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2e, 0x20, 0x54, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x20, 0x73, 0x68, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x0a, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, + 0x30, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, + 0x68, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, + 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x05, 0x03, 0x00, 0x01, 0x12, 0x03, 0x57, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, + 0x00, 0x02, 0x00, 0x12, 0x03, 0x58, 0x04, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, + 0x02, 0x00, 0x05, 0x12, 0x03, 0x58, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x58, 0x0b, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x58, 0x16, 0x17, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, + 0x02, 0x01, 0x12, 0x03, 0x59, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, + 0x01, 0x05, 0x12, 0x03, 0x59, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, + 0x01, 0x01, 0x12, 0x03, 0x59, 0x0b, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, + 0x01, 0x03, 0x12, 0x03, 0x59, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, + 0x03, 0x5c, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x04, 0x12, 0x03, 0x5c, + 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x06, 0x12, 0x03, 0x5c, 0x0b, 0x12, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x5c, 0x13, 0x1b, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x5c, 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, + 0x04, 0x06, 0x12, 0x04, 0x60, 0x00, 0x6f, 0x01, 0x1a, 0x36, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, + 0x6e, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x65, 0x64, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x60, 0x08, 0x22, 0x0a, 0x3c, 0x0a, 0x04, + 0x04, 0x06, 0x03, 0x00, 0x12, 0x04, 0x62, 0x02, 0x66, 0x03, 0x1a, 0x2e, 0x20, 0x41, 0x20, 0x73, + 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x58, 0x49, 0x44, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, + 0x03, 0x00, 0x01, 0x12, 0x03, 0x62, 0x0a, 0x1b, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, 0x00, + 0x02, 0x00, 0x12, 0x03, 0x63, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, + 0x00, 0x05, 0x12, 0x03, 0x63, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x63, 0x0b, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, + 0x00, 0x03, 0x12, 0x03, 0x63, 0x19, 0x1a, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, 0x00, 0x02, + 0x01, 0x12, 0x03, 0x64, 0x04, 0x23, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x01, + 0x05, 0x12, 0x03, 0x64, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x01, + 0x01, 0x12, 0x03, 0x64, 0x0b, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x64, 0x21, 0x22, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, 0x00, 0x02, 0x02, + 0x12, 0x03, 0x65, 0x04, 0x39, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x02, 0x06, + 0x12, 0x03, 0x65, 0x04, 0x2d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x02, 0x01, + 0x12, 0x03, 0x65, 0x2e, 0x34, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x02, 0x03, + 0x12, 0x03, 0x65, 0x37, 0x38, 0x0a, 0x54, 0x0a, 0x04, 0x04, 0x06, 0x03, 0x01, 0x12, 0x04, 0x69, + 0x02, 0x6c, 0x03, 0x1a, 0x46, 0x20, 0x54, 0x68, 0x65, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, + 0x61, 0x73, 0x74, 0x20, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x06, 0x03, 0x01, 0x01, 0x12, 0x03, 0x69, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, + 0x01, 0x02, 0x00, 0x12, 0x03, 0x6a, 0x04, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x01, + 0x02, 0x00, 0x05, 0x12, 0x03, 0x6a, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x01, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x6a, 0x0b, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x01, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x6a, 0x16, 0x17, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, 0x01, + 0x02, 0x01, 0x12, 0x03, 0x6b, 0x04, 0x2b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x01, 0x02, + 0x01, 0x04, 0x12, 0x03, 0x6b, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x01, 0x02, + 0x01, 0x06, 0x12, 0x03, 0x6b, 0x0d, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x01, 0x02, + 0x01, 0x01, 0x12, 0x03, 0x6b, 0x1f, 0x26, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x01, 0x02, + 0x01, 0x03, 0x12, 0x03, 0x6b, 0x29, 0x2a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x00, 0x12, + 0x03, 0x6e, 0x02, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x04, 0x12, 0x03, 0x6e, + 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x06, 0x12, 0x03, 0x6e, 0x0b, 0x13, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, 0x03, 0x6e, 0x14, 0x1d, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x6e, 0x20, 0x21, 0x0a, 0x42, 0x0a, 0x02, + 0x04, 0x07, 0x12, 0x04, 0x72, 0x00, 0x79, 0x01, 0x1a, 0x36, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x58, 0x49, 0x44, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x07, 0x01, 0x12, 0x03, 0x72, 0x08, 0x1a, 0x0a, 0x34, 0x0a, 0x04, + 0x04, 0x07, 0x03, 0x00, 0x12, 0x04, 0x74, 0x02, 0x76, 0x03, 0x1a, 0x26, 0x20, 0x41, 0x20, 0x73, + 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x03, 0x00, 0x01, 0x12, 0x03, 0x74, 0x0a, 0x11, + 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x75, 0x04, 0x17, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x75, 0x04, 0x0a, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x75, 0x0b, 0x12, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x75, 0x15, 0x16, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x00, 0x12, 0x03, 0x78, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x07, 0x02, 0x00, 0x04, 0x12, 0x03, 0x78, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, + 0x02, 0x00, 0x06, 0x12, 0x03, 0x78, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, + 0x01, 0x12, 0x03, 0x78, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x03, 0x12, + 0x03, 0x78, 0x1e, 0x1f, 0x0a, 0x41, 0x0a, 0x02, 0x04, 0x08, 0x12, 0x05, 0x7c, 0x00, 0x84, 0x01, + 0x01, 0x1a, 0x34, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x58, 0x49, 0x44, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x08, 0x01, 0x12, 0x03, + 0x7c, 0x08, 0x1b, 0x0a, 0x36, 0x0a, 0x04, 0x04, 0x08, 0x03, 0x00, 0x12, 0x05, 0x7e, 0x02, 0x81, + 0x01, 0x03, 0x1a, 0x27, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, + 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x08, 0x03, 0x00, 0x01, 0x12, 0x03, 0x7e, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x08, 0x03, + 0x00, 0x02, 0x00, 0x12, 0x03, 0x7f, 0x04, 0x17, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, + 0x02, 0x00, 0x05, 0x12, 0x03, 0x7f, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x7f, 0x0b, 0x12, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x7f, 0x15, 0x16, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, + 0x02, 0x01, 0x12, 0x04, 0x80, 0x01, 0x04, 0x21, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, + 0x02, 0x01, 0x04, 0x12, 0x04, 0x80, 0x01, 0x04, 0x0c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, + 0x00, 0x02, 0x01, 0x05, 0x12, 0x04, 0x80, 0x01, 0x0d, 0x13, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, + 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x80, 0x01, 0x14, 0x1c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, + 0x08, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0x80, 0x01, 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x08, 0x02, 0x00, 0x12, 0x04, 0x83, 0x01, 0x02, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, + 0x02, 0x00, 0x04, 0x12, 0x04, 0x83, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, + 0x00, 0x06, 0x12, 0x04, 0x83, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, + 0x01, 0x12, 0x04, 0x83, 0x01, 0x14, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x03, + 0x12, 0x04, 0x83, 0x01, 0x20, 0x21, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ]; include!("xmtp.identity.api.v1.serde.rs"); include!("xmtp.identity.api.v1.tonic.rs"); diff --git a/xmtp_proto/src/gen/xmtp.identity.api.v1.serde.rs b/xmtp_proto/src/gen/xmtp.identity.api.v1.serde.rs index ed2e88547..8aeb2eb61 100644 --- a/xmtp_proto/src/gen/xmtp.identity.api.v1.serde.rs +++ b/xmtp_proto/src/gen/xmtp.identity.api.v1.serde.rs @@ -1084,3 +1084,407 @@ impl<'de> serde::Deserialize<'de> for PublishIdentityUpdateResponse { deserializer.deserialize_struct("xmtp.identity.api.v1.PublishIdentityUpdateResponse", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for UnverifiedSmartContractWalletSignature { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.scw_signature.is_some() { + len += 1; + } + if !self.hash.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.identity.api.v1.UnverifiedSmartContractWalletSignature", len)?; + if let Some(v) = self.scw_signature.as_ref() { + struct_ser.serialize_field("scwSignature", v)?; + } + if !self.hash.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("hash", pbjson::private::base64::encode(&self.hash).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for UnverifiedSmartContractWalletSignature { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "scw_signature", + "scwSignature", + "hash", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + ScwSignature, + Hash, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "scwSignature" | "scw_signature" => Ok(GeneratedField::ScwSignature), + "hash" => Ok(GeneratedField::Hash), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = UnverifiedSmartContractWalletSignature; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.identity.api.v1.UnverifiedSmartContractWalletSignature") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut scw_signature__ = None; + let mut hash__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::ScwSignature => { + if scw_signature__.is_some() { + return Err(serde::de::Error::duplicate_field("scwSignature")); + } + scw_signature__ = map_.next_value()?; + } + GeneratedField::Hash => { + if hash__.is_some() { + return Err(serde::de::Error::duplicate_field("hash")); + } + hash__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + } + } + Ok(UnverifiedSmartContractWalletSignature { + scw_signature: scw_signature__, + hash: hash__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.identity.api.v1.UnverifiedSmartContractWalletSignature", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for VerifySmartContractWalletSignaturesRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.signatures.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.identity.api.v1.VerifySmartContractWalletSignaturesRequest", len)?; + if !self.signatures.is_empty() { + struct_ser.serialize_field("signatures", &self.signatures)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for VerifySmartContractWalletSignaturesRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "signatures", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Signatures, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "signatures" => Ok(GeneratedField::Signatures), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = VerifySmartContractWalletSignaturesRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.identity.api.v1.VerifySmartContractWalletSignaturesRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut signatures__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Signatures => { + if signatures__.is_some() { + return Err(serde::de::Error::duplicate_field("signatures")); + } + signatures__ = Some(map_.next_value()?); + } + } + } + Ok(VerifySmartContractWalletSignaturesRequest { + signatures: signatures__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.identity.api.v1.VerifySmartContractWalletSignaturesRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for VerifySmartContractWalletSignaturesResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.responses.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.identity.api.v1.VerifySmartContractWalletSignaturesResponse", len)?; + if !self.responses.is_empty() { + struct_ser.serialize_field("responses", &self.responses)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for VerifySmartContractWalletSignaturesResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "responses", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Responses, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "responses" => Ok(GeneratedField::Responses), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = VerifySmartContractWalletSignaturesResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.identity.api.v1.VerifySmartContractWalletSignaturesResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut responses__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Responses => { + if responses__.is_some() { + return Err(serde::de::Error::duplicate_field("responses")); + } + responses__ = Some(map_.next_value()?); + } + } + } + Ok(VerifySmartContractWalletSignaturesResponse { + responses: responses__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.identity.api.v1.VerifySmartContractWalletSignaturesResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for verify_smart_contract_wallet_signatures_response::ValidationResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.is_valid { + len += 1; + } + if self.error.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.identity.api.v1.VerifySmartContractWalletSignaturesResponse.ValidationResponse", len)?; + if self.is_valid { + struct_ser.serialize_field("isValid", &self.is_valid)?; + } + if let Some(v) = self.error.as_ref() { + struct_ser.serialize_field("error", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for verify_smart_contract_wallet_signatures_response::ValidationResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "is_valid", + "isValid", + "error", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + IsValid, + Error, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "isValid" | "is_valid" => Ok(GeneratedField::IsValid), + "error" => Ok(GeneratedField::Error), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = verify_smart_contract_wallet_signatures_response::ValidationResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.identity.api.v1.VerifySmartContractWalletSignaturesResponse.ValidationResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut is_valid__ = None; + let mut error__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::IsValid => { + if is_valid__.is_some() { + return Err(serde::de::Error::duplicate_field("isValid")); + } + is_valid__ = Some(map_.next_value()?); + } + GeneratedField::Error => { + if error__.is_some() { + return Err(serde::de::Error::duplicate_field("error")); + } + error__ = map_.next_value()?; + } + } + } + Ok(verify_smart_contract_wallet_signatures_response::ValidationResponse { + is_valid: is_valid__.unwrap_or_default(), + error: error__, + }) + } + } + deserializer.deserialize_struct("xmtp.identity.api.v1.VerifySmartContractWalletSignaturesResponse.ValidationResponse", FIELDS, GeneratedVisitor) + } +} diff --git a/xmtp_proto/src/gen/xmtp.identity.api.v1.tonic.rs b/xmtp_proto/src/gen/xmtp.identity.api.v1.tonic.rs index 52a54f8e5..7f3924903 100644 --- a/xmtp_proto/src/gen/xmtp.identity.api.v1.tonic.rs +++ b/xmtp_proto/src/gen/xmtp.identity.api.v1.tonic.rs @@ -172,6 +172,38 @@ pub mod identity_api_client { ); self.inner.unary(req, path, codec).await } + pub async fn verify_smart_contract_wallet_signatures( + &mut self, + request: impl tonic::IntoRequest< + super::VerifySmartContractWalletSignaturesRequest, + >, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/xmtp.identity.api.v1.IdentityApi/VerifySmartContractWalletSignatures", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "xmtp.identity.api.v1.IdentityApi", + "VerifySmartContractWalletSignatures", + ), + ); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -203,6 +235,13 @@ pub mod identity_api_server { tonic::Response, tonic::Status, >; + async fn verify_smart_contract_wallet_signatures( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; } #[derive(Debug)] pub struct IdentityApiServer { @@ -417,6 +456,60 @@ pub mod identity_api_server { }; Box::pin(fut) } + "/xmtp.identity.api.v1.IdentityApi/VerifySmartContractWalletSignatures" => { + #[allow(non_camel_case_types)] + struct VerifySmartContractWalletSignaturesSvc( + pub Arc, + ); + impl< + T: IdentityApi, + > tonic::server::UnaryService< + super::VerifySmartContractWalletSignaturesRequest, + > for VerifySmartContractWalletSignaturesSvc { + type Response = super::VerifySmartContractWalletSignaturesResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::VerifySmartContractWalletSignaturesRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::verify_smart_contract_wallet_signatures( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = VerifySmartContractWalletSignaturesSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { Ok( diff --git a/xmtp_proto/src/gen/xmtp.identity.associations.rs b/xmtp_proto/src/gen/xmtp.identity.associations.rs index 8ec6b99a5..bdba74505 100644 --- a/xmtp_proto/src/gen/xmtp.identity.associations.rs +++ b/xmtp_proto/src/gen/xmtp.identity.associations.rs @@ -33,9 +33,6 @@ pub struct SmartContractWalletSignature { /// The actual signature bytes #[prost(bytes="vec", tag="3")] pub signature: ::prost::alloc::vec::Vec, - /// The RPC URL specifies a chain to verify the signature against - #[prost(string, tag="4")] - pub chain_rpc_url: ::prost::alloc::string::String, } /// An existing address on xmtpv2 may have already signed a legacy identity key /// of type SignedPublicKey via the 'Create Identity' signature. @@ -109,6 +106,8 @@ pub struct Member { pub identifier: ::core::option::Option, #[prost(message, optional, tag="2")] pub added_by_entity: ::core::option::Option, + #[prost(uint64, optional, tag="3")] + pub client_timestamp_ns: ::core::option::Option, } /// The first entry of any XID log. The XID must be deterministically derivable /// from the address and nonce. @@ -231,7 +230,7 @@ pub struct AssociationStateDiff { } /// Encoded file descriptor set for the `xmtp.identity.associations` package pub const FILE_DESCRIPTOR_SET: &[u8] = &[ - 0x0a, 0xe0, 0x1a, 0x0a, 0x25, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, + 0x0a, 0xc3, 0x19, 0x0a, 0x25, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, @@ -246,232 +245,227 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x22, 0xa2, 0x01, 0x0a, 0x1c, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, - 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x70, 0x63, 0x5f, 0x75, - 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x52, - 0x70, 0x63, 0x55, 0x72, 0x6c, 0x22, 0xbc, 0x01, 0x0a, 0x18, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x52, 0x0c, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, - 0x53, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x22, 0x8b, 0x03, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x12, 0x50, 0x0a, 0x07, 0x65, 0x72, 0x63, 0x5f, 0x31, 0x39, 0x31, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, - 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, 0x06, 0x65, 0x72, - 0x63, 0x31, 0x39, 0x31, 0x12, 0x55, 0x0a, 0x08, 0x65, 0x72, 0x63, 0x5f, 0x36, 0x34, 0x39, 0x32, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x22, 0x7e, 0x0a, 0x1c, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x48, 0x00, 0x52, 0x07, 0x65, 0x72, 0x63, 0x36, 0x34, 0x39, 0x32, 0x12, 0x64, 0x0a, 0x10, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x64, - 0x32, 0x35, 0x35, 0x31, 0x39, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, - 0x52, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, - 0x79, 0x12, 0x62, 0x0a, 0x11, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x65, - 0x72, 0x63, 0x5f, 0x31, 0x39, 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x44, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x48, 0x00, 0x52, 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x45, - 0x72, 0x63, 0x31, 0x39, 0x31, 0x42, 0x0b, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x42, 0xed, 0x01, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, - 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x49, 0x41, - 0xaa, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x2e, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xca, 0x02, 0x1a, - 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xe2, 0x02, 0x26, 0x58, 0x6d, 0x74, - 0x70, 0x5c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, 0x73, 0x73, 0x6f, 0x63, - 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x4a, 0x86, 0x11, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x3d, 0x01, 0x0a, 0x35, 0x0a, - 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x2b, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, - 0x67, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x23, 0x0a, 0x09, - 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, 0x00, 0x2b, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, - 0x07, 0x00, 0x48, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x07, 0x00, 0x48, 0x0a, 0x45, - 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0b, 0x00, 0x0e, 0x01, 0x1a, 0x39, 0x20, 0x52, 0x65, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x45, 0x49, 0x50, 0x2d, 0x31, - 0x39, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x56, 0x32, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0b, 0x08, - 0x21, 0x0a, 0x4a, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0d, 0x02, 0x12, 0x1a, 0x3d, - 0x20, 0x36, 0x35, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x5b, 0x20, 0x52, 0x20, 0x7c, 0x7c, - 0x20, 0x53, 0x20, 0x7c, 0x7c, 0x20, 0x56, 0x20, 0x5d, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, - 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x64, 0x20, 0x61, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0d, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0d, 0x08, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x00, 0x03, 0x12, 0x03, 0x0d, 0x10, 0x11, 0x0a, 0x27, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x11, - 0x00, 0x16, 0x01, 0x1a, 0x1b, 0x20, 0x45, 0x64, 0x44, 0x53, 0x41, 0x20, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x32, 0x35, 0x35, 0x31, 0x39, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x11, 0x08, 0x23, 0x0a, 0x34, 0x0a, 0x04, - 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x13, 0x02, 0x12, 0x1a, 0x27, 0x20, 0x36, 0x34, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x20, 0x5b, 0x52, 0x28, 0x33, 0x32, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x53, 0x28, 0x33, 0x32, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x29, - 0x5d, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x13, 0x02, 0x07, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x13, 0x08, 0x0d, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x13, 0x10, 0x11, 0x0a, 0x17, 0x0a, 0x04, - 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x15, 0x02, 0x17, 0x1a, 0x0a, 0x20, 0x33, 0x32, 0x20, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x05, 0x12, 0x03, - 0x15, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x15, 0x08, - 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x15, 0x15, 0x16, 0x0a, - 0x2d, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x19, 0x00, 0x23, 0x01, 0x1a, 0x21, 0x20, 0x53, 0x6d, - 0x61, 0x72, 0x74, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x20, 0x57, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x19, 0x08, 0x24, 0x0a, 0x60, 0x0a, 0x04, 0x04, 0x02, - 0x02, 0x00, 0x12, 0x03, 0x1c, 0x02, 0x18, 0x1a, 0x53, 0x20, 0x43, 0x41, 0x49, 0x50, 0x2d, 0x31, - 0x30, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, - 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x41, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x41, 0x49, 0x50, 0x73, - 0x2f, 0x62, 0x6c, 0x6f, 0x62, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x43, 0x41, 0x49, 0x50, 0x73, - 0x2f, 0x63, 0x61, 0x69, 0x70, 0x2d, 0x31, 0x30, 0x2e, 0x6d, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, 0x1c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, - 0x02, 0x00, 0x01, 0x12, 0x03, 0x1c, 0x09, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, - 0x03, 0x12, 0x03, 0x1c, 0x16, 0x17, 0x0a, 0x47, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, - 0x1e, 0x02, 0x1a, 0x1a, 0x3a, 0x20, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, - 0x6f, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x05, 0x12, 0x03, 0x1e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x1e, 0x09, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x1e, 0x18, 0x19, 0x0a, 0x29, 0x0a, 0x04, 0x04, 0x02, 0x02, - 0x02, 0x12, 0x03, 0x20, 0x02, 0x16, 0x1a, 0x1c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x63, 0x74, - 0x75, 0x61, 0x6c, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x05, 0x12, 0x03, 0x20, - 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x20, 0x08, 0x11, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x20, 0x14, 0x15, 0x0a, 0x4c, - 0x0a, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, 0x03, 0x22, 0x02, 0x1b, 0x1a, 0x3f, 0x20, 0x54, 0x68, - 0x65, 0x20, 0x52, 0x50, 0x43, 0x20, 0x55, 0x52, 0x4c, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, - 0x69, 0x65, 0x73, 0x20, 0x61, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x76, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x02, 0x02, 0x03, 0x05, 0x12, 0x03, 0x22, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, - 0x02, 0x03, 0x01, 0x12, 0x03, 0x22, 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, - 0x03, 0x12, 0x03, 0x22, 0x19, 0x1a, 0x0a, 0x95, 0x03, 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x2b, - 0x00, 0x2e, 0x01, 0x1a, 0x88, 0x03, 0x20, 0x41, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, - 0x6e, 0x67, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x78, 0x6d, - 0x74, 0x70, 0x76, 0x32, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x6c, - 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x20, 0x6c, - 0x65, 0x67, 0x61, 0x63, 0x79, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x6b, - 0x65, 0x79, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x20, 0x76, 0x69, 0x61, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x27, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x27, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, - 0x0a, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x74, 0x6f, 0x20, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x33, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, - 0x65, 0x67, 0x61, 0x63, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x6f, - 0x6e, 0x20, 0x62, 0x65, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x0a, - 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x78, 0x6d, - 0x74, 0x70, 0x76, 0x33, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x2e, 0x0a, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, - 0x4f, 0x4e, 0x4c, 0x59, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x58, 0x69, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, - 0x64, 0x64, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6e, - 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, - 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x33, 0x2e, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x2b, 0x08, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, - 0x02, 0x00, 0x12, 0x03, 0x2c, 0x02, 0x3a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, - 0x12, 0x03, 0x2c, 0x02, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, - 0x2c, 0x28, 0x35, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2c, 0x38, - 0x39, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, 0x2d, 0x02, 0x2a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x06, 0x12, 0x03, 0x2d, 0x02, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, 0x03, 0x2d, 0x1c, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, - 0x02, 0x01, 0x03, 0x12, 0x03, 0x2d, 0x28, 0x29, 0x0a, 0x38, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, - 0x31, 0x00, 0x3d, 0x01, 0x1a, 0x2c, 0x20, 0x41, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, - 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x31, 0x08, 0x11, 0x0a, 0xb0, - 0x02, 0x0a, 0x04, 0x04, 0x04, 0x08, 0x00, 0x12, 0x04, 0x37, 0x02, 0x3c, 0x03, 0x1a, 0xa1, 0x02, - 0x20, 0x4d, 0x75, 0x73, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x70, - 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x3a, 0x0a, 0x20, 0x31, 0x2e, 0x20, 0x41, - 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x28, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, - 0x6b, 0x65, 0x79, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, - 0x62, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, - 0x6c, 0x65, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, - 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x0a, 0x20, 0x32, 0x2e, - 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x63, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x69, - 0x73, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, - 0x62, 0x65, 0x20, 0x69, 0x6e, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x69, 0x6e, 0x20, - 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x2e, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x08, 0x00, 0x01, 0x12, 0x03, 0x37, 0x08, 0x11, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x38, 0x04, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x04, 0x02, 0x00, 0x06, 0x12, 0x03, 0x38, 0x04, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, - 0x02, 0x00, 0x01, 0x12, 0x03, 0x38, 0x1e, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, - 0x03, 0x12, 0x03, 0x38, 0x28, 0x29, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, 0x03, - 0x39, 0x04, 0x2e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x06, 0x12, 0x03, 0x39, 0x04, - 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x39, 0x21, 0x29, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x39, 0x2c, 0x2d, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x04, 0x02, 0x02, 0x12, 0x03, 0x3a, 0x04, 0x35, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, - 0x02, 0x02, 0x06, 0x12, 0x03, 0x3a, 0x04, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, - 0x01, 0x12, 0x03, 0x3a, 0x20, 0x30, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, - 0x03, 0x3a, 0x33, 0x34, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x03, 0x12, 0x03, 0x3b, 0x04, - 0x33, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x03, 0x06, 0x12, 0x03, 0x3b, 0x04, 0x1c, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x03, 0x01, 0x12, 0x03, 0x3b, 0x1d, 0x2e, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x04, 0x02, 0x03, 0x03, 0x12, 0x03, 0x3b, 0x31, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, 0x0a, 0x88, 0x31, 0x0a, 0x27, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x1a, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, - 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x25, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x70, 0x0a, 0x10, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x06, 0x0a, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x22, 0xc5, 0x01, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, - 0x4c, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, + 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x22, 0xbc, 0x01, 0x0a, 0x18, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x4b, 0x0a, + 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, 0x0c, 0x64, 0x65, + 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x53, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, + 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, + 0x8b, 0x03, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x50, 0x0a, + 0x07, 0x65, 0x72, 0x63, 0x5f, 0x31, 0x39, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, + 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, 0x06, 0x65, 0x72, 0x63, 0x31, 0x39, 0x31, 0x12, + 0x55, 0x0a, 0x08, 0x65, 0x72, 0x63, 0x5f, 0x36, 0x34, 0x39, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x38, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, + 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, 0x07, 0x65, + 0x72, 0x63, 0x36, 0x34, 0x39, 0x32, 0x12, 0x64, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x37, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, 0x0f, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x62, 0x0a, 0x11, + 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x72, 0x63, 0x5f, 0x31, 0x39, + 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x44, 0x65, 0x6c, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, + 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x45, 0x72, 0x63, 0x31, 0x39, 0x31, + 0x42, 0x0b, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0xed, 0x01, + 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x59, 0x0a, - 0x0f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, + 0x42, 0x0e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, + 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x49, 0x41, 0xaa, 0x02, 0x1a, 0x58, 0x6d, + 0x74, 0x70, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x41, 0x73, 0x73, 0x6f, + 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xca, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x5c, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xe2, 0x02, 0x26, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5c, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x1c, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, + 0x3a, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4a, 0x8e, 0x10, + 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x3b, 0x01, 0x0a, 0x35, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, + 0x00, 0x12, 0x1a, 0x2b, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, + 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x23, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, + 0x03, 0x05, 0x00, 0x2b, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x07, 0x00, 0x48, 0x0a, 0x09, + 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x07, 0x00, 0x48, 0x0a, 0x45, 0x0a, 0x02, 0x04, 0x00, 0x12, + 0x04, 0x0b, 0x00, 0x0e, 0x01, 0x1a, 0x39, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, + 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x45, 0x49, 0x50, 0x2d, 0x31, 0x39, 0x31, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x56, 0x32, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0b, 0x08, 0x21, 0x0a, 0x4a, 0x0a, 0x04, + 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0d, 0x02, 0x12, 0x1a, 0x3d, 0x20, 0x36, 0x35, 0x2d, 0x62, + 0x79, 0x74, 0x65, 0x73, 0x20, 0x5b, 0x20, 0x52, 0x20, 0x7c, 0x7c, 0x20, 0x53, 0x20, 0x7c, 0x7c, + 0x20, 0x56, 0x20, 0x5d, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x20, 0x69, 0x64, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, + 0x73, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, + 0x05, 0x12, 0x03, 0x0d, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x0d, 0x08, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0d, + 0x10, 0x11, 0x0a, 0x27, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x11, 0x00, 0x16, 0x01, 0x1a, 0x1b, + 0x20, 0x45, 0x64, 0x44, 0x53, 0x41, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x32, 0x35, 0x35, 0x31, 0x39, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, + 0x01, 0x01, 0x12, 0x03, 0x11, 0x08, 0x23, 0x0a, 0x34, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, + 0x03, 0x13, 0x02, 0x12, 0x1a, 0x27, 0x20, 0x36, 0x34, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, + 0x5b, 0x52, 0x28, 0x33, 0x32, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x29, 0x20, 0x7c, 0x7c, 0x20, + 0x53, 0x28, 0x33, 0x32, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x29, 0x5d, 0x0a, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x13, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x13, 0x08, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x00, 0x03, 0x12, 0x03, 0x13, 0x10, 0x11, 0x0a, 0x17, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, + 0x03, 0x15, 0x02, 0x17, 0x1a, 0x0a, 0x20, 0x33, 0x32, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x05, 0x12, 0x03, 0x15, 0x02, 0x07, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x15, 0x08, 0x12, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x15, 0x15, 0x16, 0x0a, 0x2d, 0x0a, 0x02, 0x04, 0x02, + 0x12, 0x04, 0x19, 0x00, 0x21, 0x01, 0x1a, 0x21, 0x20, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x20, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x20, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, + 0x12, 0x03, 0x19, 0x08, 0x24, 0x0a, 0x60, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x1c, + 0x02, 0x18, 0x1a, 0x53, 0x20, 0x43, 0x41, 0x49, 0x50, 0x2d, 0x31, 0x30, 0x20, 0x73, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x41, 0x67, 0x6e, + 0x6f, 0x73, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x41, 0x49, 0x50, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x62, + 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x43, 0x41, 0x49, 0x50, 0x73, 0x2f, 0x63, 0x61, 0x69, 0x70, + 0x2d, 0x31, 0x30, 0x2e, 0x6d, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x05, + 0x12, 0x03, 0x1c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x1c, 0x09, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x1c, 0x16, + 0x17, 0x0a, 0x47, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x1e, 0x02, 0x1a, 0x1a, 0x3a, + 0x20, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x01, 0x05, 0x12, 0x03, 0x1e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, + 0x01, 0x12, 0x03, 0x1e, 0x09, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, + 0x03, 0x1e, 0x18, 0x19, 0x0a, 0x29, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, 0x20, 0x02, + 0x16, 0x1a, 0x1c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x05, 0x12, 0x03, 0x20, 0x02, 0x07, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x20, 0x08, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x20, 0x14, 0x15, 0x0a, 0x95, 0x03, 0x0a, 0x02, 0x04, 0x03, + 0x12, 0x04, 0x29, 0x00, 0x2c, 0x01, 0x1a, 0x88, 0x03, 0x20, 0x41, 0x6e, 0x20, 0x65, 0x78, 0x69, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x6e, + 0x20, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x32, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, + 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, + 0x61, 0x20, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x20, 0x6b, 0x65, 0x79, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x53, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x20, 0x76, + 0x69, 0x61, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x27, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x2e, 0x0a, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x6d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x33, 0x2c, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, + 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x65, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x0a, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, + 0x20, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x33, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x2e, 0x0a, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, + 0x61, 0x6e, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x58, 0x69, 0x64, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x41, 0x64, 0x64, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x0a, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x63, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, + 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x33, 0x2e, + 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x29, 0x08, 0x20, 0x0a, 0x0b, 0x0a, + 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x2a, 0x02, 0x3a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, + 0x02, 0x00, 0x06, 0x12, 0x03, 0x2a, 0x02, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, + 0x01, 0x12, 0x03, 0x2a, 0x28, 0x35, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, + 0x03, 0x2a, 0x38, 0x39, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, 0x2b, 0x02, + 0x2a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x06, 0x12, 0x03, 0x2b, 0x02, 0x1b, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, 0x03, 0x2b, 0x1c, 0x25, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x03, 0x12, 0x03, 0x2b, 0x28, 0x29, 0x0a, 0x38, 0x0a, 0x02, 0x04, + 0x04, 0x12, 0x04, 0x2f, 0x00, 0x3b, 0x01, 0x1a, 0x2c, 0x20, 0x41, 0x20, 0x77, 0x72, 0x61, 0x70, + 0x70, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x70, 0x6f, 0x73, 0x73, + 0x69, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x2f, 0x08, + 0x11, 0x0a, 0xb0, 0x02, 0x0a, 0x04, 0x04, 0x04, 0x08, 0x00, 0x12, 0x04, 0x35, 0x02, 0x3a, 0x03, + 0x1a, 0xa1, 0x02, 0x20, 0x4d, 0x75, 0x73, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x77, + 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x3a, 0x0a, 0x20, 0x31, + 0x2e, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, + 0x28, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x65, 0x69, 0x74, 0x68, + 0x65, 0x72, 0x20, 0x62, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, + 0x69, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2e, 0x0a, + 0x20, 0x32, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x2e, 0x20, 0x54, 0x68, + 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x75, + 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x20, 0x66, + 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, + 0x69, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x08, 0x00, 0x01, 0x12, 0x03, 0x35, + 0x08, 0x11, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x36, 0x04, 0x2a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x06, 0x12, 0x03, 0x36, 0x04, 0x1d, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x36, 0x1e, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x36, 0x28, 0x29, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, + 0x01, 0x12, 0x03, 0x37, 0x04, 0x2e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x06, 0x12, + 0x03, 0x37, 0x04, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x37, + 0x21, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x37, 0x2c, 0x2d, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x02, 0x12, 0x03, 0x38, 0x04, 0x35, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x04, 0x02, 0x02, 0x06, 0x12, 0x03, 0x38, 0x04, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x38, 0x20, 0x30, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, + 0x02, 0x03, 0x12, 0x03, 0x38, 0x33, 0x34, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x03, 0x12, + 0x03, 0x39, 0x04, 0x33, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x03, 0x06, 0x12, 0x03, 0x39, + 0x04, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x03, 0x01, 0x12, 0x03, 0x39, 0x1d, 0x2e, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x03, 0x03, 0x12, 0x03, 0x39, 0x31, 0x32, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0x9a, 0x32, 0x0a, 0x27, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x1a, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x25, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x70, 0x0a, 0x10, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, + 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x92, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x64, 0x64, 0x65, 0x64, 0x42, 0x79, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x61, 0x64, 0x64, - 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0xaf, 0x01, 0x0a, + 0x66, 0x69, 0x65, 0x72, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, + 0x12, 0x59, 0x0a, 0x0f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x64, 0x64, 0x65, 0x64, + 0x42, 0x79, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x88, 0x01, 0x01, 0x12, 0x33, 0x0a, 0x13, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, + 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x11, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x88, 0x01, 0x01, + 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x22, 0xaf, 0x01, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x41, 0x64, @@ -607,7 +601,7 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x3a, 0x3a, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4a, 0xde, 0x1c, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x63, 0x01, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4a, 0xa3, 0x1d, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x64, 0x01, 0x0a, 0x3b, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x31, 0x20, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, @@ -627,7 +621,7 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x00, 0x02, 0x01, 0x12, 0x03, 0x0e, 0x04, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x0e, 0x04, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0e, 0x0a, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0e, - 0x24, 0x25, 0x0a, 0x50, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x13, 0x00, 0x16, 0x01, 0x1a, 0x44, + 0x24, 0x25, 0x0a, 0x50, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x13, 0x00, 0x17, 0x01, 0x1a, 0x44, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6d, @@ -640,204 +634,209 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x03, 0x15, 0x02, 0x30, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x04, 0x12, 0x03, 0x15, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x15, 0x0b, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x15, 0x1c, 0x2b, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x15, 0x2e, 0x2f, 0x0a, 0xf8, 0x01, 0x0a, - 0x02, 0x04, 0x02, 0x12, 0x04, 0x1c, 0x00, 0x20, 0x01, 0x1a, 0xeb, 0x01, 0x20, 0x54, 0x68, 0x65, - 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, - 0x61, 0x6e, 0x79, 0x20, 0x58, 0x49, 0x44, 0x20, 0x6c, 0x6f, 0x67, 0x2e, 0x20, 0x54, 0x68, 0x65, - 0x20, 0x58, 0x49, 0x44, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x64, - 0x65, 0x72, 0x69, 0x76, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, - 0x6f, 0x6e, 0x63, 0x65, 0x2e, 0x0a, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x74, - 0x69, 0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x75, 0x6e, 0x6c, 0x65, 0x73, 0x73, 0x0a, 0x20, 0x74, - 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73, 0x75, 0x62, 0x73, 0x65, 0x71, - 0x75, 0x65, 0x6e, 0x74, 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6c, 0x6f, 0x67, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, - 0x1c, 0x08, 0x13, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x1d, 0x02, 0x1d, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, 0x1d, 0x02, 0x08, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x1d, 0x09, 0x18, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x1d, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, - 0x02, 0x01, 0x12, 0x03, 0x1e, 0x02, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x05, - 0x12, 0x03, 0x1e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, - 0x1e, 0x09, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x1e, 0x11, - 0x12, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, 0x1f, 0x02, 0x2a, 0x22, 0x1f, - 0x20, 0x4d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x06, 0x12, 0x03, 0x1f, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x1f, 0x0c, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x1f, 0x28, 0x29, 0x0a, 0x82, 0x02, 0x0a, 0x02, 0x04, 0x03, - 0x12, 0x04, 0x26, 0x00, 0x2a, 0x01, 0x1a, 0xf5, 0x01, 0x20, 0x41, 0x64, 0x64, 0x73, 0x20, 0x61, - 0x20, 0x6e, 0x65, 0x77, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x61, 0x6e, 0x20, 0x58, 0x49, 0x44, 0x20, 0x2d, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, - 0x61, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x61, 0x0a, - 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x63, 0x74, 0x69, - 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x65, 0x68, 0x61, 0x6c, 0x66, 0x20, 0x6f, 0x66, 0x20, - 0x61, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x0a, 0x20, 0x41, 0x20, 0x6b, - 0x65, 0x79, 0x2d, 0x70, 0x61, 0x69, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x73, - 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x20, 0x4d, - 0x55, 0x53, 0x54, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, - 0x74, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x0a, 0x20, 0x61, 0x73, 0x73, 0x6f, - 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x64, 0x69, - 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x72, 0x6f, 0x6c, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x26, 0x08, 0x16, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, - 0x02, 0x00, 0x12, 0x03, 0x27, 0x02, 0x2d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, - 0x12, 0x03, 0x27, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, - 0x27, 0x13, 0x28, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x27, 0x2b, - 0x2c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, 0x28, 0x02, 0x2a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x06, 0x12, 0x03, 0x28, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, 0x03, 0x28, 0x0c, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, - 0x02, 0x01, 0x03, 0x12, 0x03, 0x28, 0x28, 0x29, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x02, - 0x12, 0x03, 0x29, 0x02, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x06, 0x12, 0x03, - 0x29, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x01, 0x12, 0x03, 0x29, 0x0c, - 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x12, 0x03, 0x29, 0x23, 0x24, 0x0a, - 0x5a, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x2d, 0x00, 0x30, 0x01, 0x1a, 0x4e, 0x20, 0x52, 0x65, - 0x76, 0x6f, 0x6b, 0x65, 0x73, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x66, - 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x20, 0x58, 0x49, 0x44, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, + 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x15, 0x2e, 0x2f, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x16, 0x02, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x02, 0x04, 0x12, 0x03, 0x16, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x05, + 0x12, 0x03, 0x16, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, + 0x16, 0x12, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x16, 0x28, + 0x29, 0x0a, 0xf8, 0x01, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x1d, 0x00, 0x21, 0x01, 0x1a, 0xeb, + 0x01, 0x20, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x58, 0x49, 0x44, 0x20, 0x6c, 0x6f, 0x67, + 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x58, 0x49, 0x44, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, + 0x65, 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x69, 0x63, 0x61, + 0x6c, 0x6c, 0x79, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x20, 0x66, + 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x2e, 0x0a, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, - 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, - 0x04, 0x01, 0x12, 0x03, 0x2d, 0x08, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, - 0x03, 0x2e, 0x02, 0x28, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x06, 0x12, 0x03, 0x2e, - 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2e, 0x13, 0x23, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2e, 0x26, 0x27, 0x0a, 0x0b, - 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, 0x03, 0x2f, 0x02, 0x2b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x04, 0x02, 0x01, 0x06, 0x12, 0x03, 0x2f, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, - 0x01, 0x01, 0x12, 0x03, 0x2f, 0x0c, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, - 0x12, 0x03, 0x2f, 0x29, 0x2a, 0x0a, 0xd1, 0x01, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x35, 0x00, - 0x38, 0x01, 0x1a, 0xc4, 0x01, 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x58, 0x49, 0x44, 0x2e, 0x20, 0x54, - 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x64, 0x0a, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x58, 0x49, 0x44, 0x2e, 0x20, - 0x49, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62, - 0x65, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x64, - 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x72, - 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, - 0x63, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x20, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, - 0x12, 0x03, 0x35, 0x08, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x36, - 0x02, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x05, 0x12, 0x03, 0x36, 0x02, 0x08, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x36, 0x09, 0x1d, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x36, 0x20, 0x21, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x05, 0x02, 0x01, 0x12, 0x03, 0x37, 0x02, 0x34, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, - 0x01, 0x06, 0x12, 0x03, 0x37, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x01, - 0x12, 0x03, 0x37, 0x0c, 0x2f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x03, 0x12, 0x03, - 0x37, 0x32, 0x33, 0x0a, 0x29, 0x0a, 0x02, 0x04, 0x06, 0x12, 0x04, 0x3b, 0x00, 0x42, 0x01, 0x1a, - 0x1d, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x3b, 0x08, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x06, - 0x08, 0x00, 0x12, 0x04, 0x3c, 0x02, 0x41, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x08, 0x00, - 0x01, 0x12, 0x03, 0x3c, 0x08, 0x0c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x00, 0x12, 0x03, - 0x3d, 0x04, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x06, 0x12, 0x03, 0x3d, 0x04, - 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, 0x03, 0x3d, 0x10, 0x1c, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3d, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x06, 0x02, 0x01, 0x12, 0x03, 0x3e, 0x04, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, - 0x02, 0x01, 0x06, 0x12, 0x03, 0x3e, 0x04, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, - 0x01, 0x12, 0x03, 0x3e, 0x13, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x03, 0x12, - 0x03, 0x3e, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x02, 0x12, 0x03, 0x3f, 0x04, - 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x02, 0x06, 0x12, 0x03, 0x3f, 0x04, 0x15, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x02, 0x01, 0x12, 0x03, 0x3f, 0x16, 0x1c, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x06, 0x02, 0x02, 0x03, 0x12, 0x03, 0x3f, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x06, 0x02, 0x03, 0x12, 0x03, 0x40, 0x04, 0x36, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x03, - 0x06, 0x12, 0x03, 0x40, 0x04, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x03, 0x01, 0x12, - 0x03, 0x40, 0x1a, 0x31, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x03, 0x03, 0x12, 0x03, 0x40, - 0x34, 0x35, 0x0a, 0xd5, 0x03, 0x0a, 0x02, 0x04, 0x07, 0x12, 0x04, 0x4b, 0x00, 0x4f, 0x01, 0x1a, - 0xc8, 0x03, 0x20, 0x4f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, - 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x0a, 0x20, 0x45, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x3a, 0x20, 0x5b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x58, 0x69, 0x64, 0x2c, - 0x20, 0x41, 0x64, 0x64, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, - 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5d, 0x0a, 0x20, 0x31, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, - 0x62, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x6e, 0x61, 0x74, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, - 0x68, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, - 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x73, 0x65, - 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x27, 0x5c, 0x6e, 0x5c, 0x6e, 0x5c, 0x6e, - 0x27, 0x2e, 0x0a, 0x20, 0x32, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, - 0x73, 0x69, 0x67, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x61, - 0x74, 0x65, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x0a, - 0x20, 0x33, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, - 0x67, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, - 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x61, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x20, 0x77, - 0x68, 0x65, 0x72, 0x65, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x2e, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x61, - 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x07, - 0x01, 0x12, 0x03, 0x4b, 0x08, 0x16, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x00, 0x12, 0x03, - 0x4c, 0x02, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x04, 0x12, 0x03, 0x4c, 0x02, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x06, 0x12, 0x03, 0x4c, 0x0b, 0x19, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x01, 0x12, 0x03, 0x4c, 0x1a, 0x21, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x07, 0x02, 0x00, 0x03, 0x12, 0x03, 0x4c, 0x24, 0x25, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x07, 0x02, 0x01, 0x12, 0x03, 0x4d, 0x02, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, - 0x05, 0x12, 0x03, 0x4d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x01, 0x12, - 0x03, 0x4d, 0x09, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x03, 0x12, 0x03, 0x4d, - 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x02, 0x12, 0x03, 0x4e, 0x02, 0x16, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x02, 0x05, 0x12, 0x03, 0x4e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x07, 0x02, 0x02, 0x01, 0x12, 0x03, 0x4e, 0x09, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x07, 0x02, 0x02, 0x03, 0x12, 0x03, 0x4e, 0x14, 0x15, 0x0a, 0x35, 0x0a, 0x02, 0x04, 0x08, 0x12, - 0x04, 0x52, 0x00, 0x55, 0x01, 0x1a, 0x29, 0x20, 0x4d, 0x61, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x6e, 0x67, - 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x08, 0x01, 0x12, 0x03, 0x52, 0x08, 0x11, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x08, 0x02, 0x00, 0x12, 0x03, 0x53, 0x02, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, - 0x00, 0x06, 0x12, 0x03, 0x53, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x53, 0x13, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x53, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x01, 0x12, 0x03, 0x54, 0x02, 0x13, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x06, 0x12, 0x03, 0x54, 0x02, 0x08, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x01, 0x12, 0x03, 0x54, 0x09, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x08, 0x02, 0x01, 0x03, 0x12, 0x03, 0x54, 0x11, 0x12, 0x0a, 0x51, 0x0a, 0x02, 0x04, 0x09, - 0x12, 0x04, 0x58, 0x00, 0x5d, 0x01, 0x1a, 0x45, 0x20, 0x41, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, - 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x6f, - 0x6d, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x60, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x60, 0x0a, 0x0a, 0x0a, 0x0a, - 0x03, 0x04, 0x09, 0x01, 0x12, 0x03, 0x58, 0x08, 0x18, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x09, 0x02, - 0x00, 0x12, 0x03, 0x59, 0x02, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x05, 0x12, - 0x03, 0x59, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x01, 0x12, 0x03, 0x59, - 0x09, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x03, 0x12, 0x03, 0x59, 0x14, 0x15, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x09, 0x02, 0x01, 0x12, 0x03, 0x5a, 0x02, 0x21, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x09, 0x02, 0x01, 0x04, 0x12, 0x03, 0x5a, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x09, 0x02, 0x01, 0x06, 0x12, 0x03, 0x5a, 0x0b, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, - 0x01, 0x01, 0x12, 0x03, 0x5a, 0x15, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x01, 0x03, - 0x12, 0x03, 0x5a, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x09, 0x02, 0x02, 0x12, 0x03, 0x5b, - 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x02, 0x05, 0x12, 0x03, 0x5b, 0x02, 0x08, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x02, 0x01, 0x12, 0x03, 0x5b, 0x09, 0x19, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x09, 0x02, 0x02, 0x03, 0x12, 0x03, 0x5b, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x09, 0x02, 0x03, 0x12, 0x03, 0x5c, 0x02, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, - 0x03, 0x04, 0x12, 0x03, 0x5c, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x03, 0x05, - 0x12, 0x03, 0x5c, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x03, 0x01, 0x12, 0x03, - 0x5c, 0x11, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x03, 0x03, 0x12, 0x03, 0x5c, 0x23, - 0x24, 0x0a, 0x3d, 0x0a, 0x02, 0x04, 0x0a, 0x12, 0x04, 0x60, 0x00, 0x63, 0x01, 0x1a, 0x31, 0x2f, - 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, 0x20, 0x62, 0x65, 0x74, 0x77, - 0x65, 0x65, 0x6e, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x41, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x0a, 0x01, 0x12, 0x03, 0x60, 0x08, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x0a, 0x02, 0x00, 0x12, 0x03, 0x61, 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, - 0x00, 0x04, 0x12, 0x03, 0x61, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x06, - 0x12, 0x03, 0x61, 0x0b, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x01, 0x12, 0x03, - 0x61, 0x1c, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x03, 0x12, 0x03, 0x61, 0x2a, - 0x2b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0a, 0x02, 0x01, 0x12, 0x03, 0x62, 0x02, 0x30, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x01, 0x04, 0x12, 0x03, 0x62, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x0a, 0x02, 0x01, 0x06, 0x12, 0x03, 0x62, 0x0b, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, - 0x02, 0x01, 0x01, 0x12, 0x03, 0x62, 0x1c, 0x2b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x01, - 0x03, 0x12, 0x03, 0x62, 0x2e, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x75, 0x6e, 0x6c, 0x65, + 0x73, 0x73, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73, + 0x75, 0x62, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x67, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, + 0x04, 0x02, 0x01, 0x12, 0x03, 0x1d, 0x08, 0x13, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, + 0x12, 0x03, 0x1e, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, + 0x1e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x1e, 0x09, + 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x1e, 0x1b, 0x1c, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x1f, 0x02, 0x13, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x02, 0x02, 0x01, 0x05, 0x12, 0x03, 0x1f, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x1f, 0x09, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x1f, 0x11, 0x12, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, + 0x20, 0x02, 0x2a, 0x22, 0x1f, 0x20, 0x4d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, + 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x06, 0x12, 0x03, 0x20, + 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x20, 0x0c, 0x25, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x20, 0x28, 0x29, 0x0a, 0x82, + 0x02, 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x27, 0x00, 0x2b, 0x01, 0x1a, 0xf5, 0x01, 0x20, 0x41, + 0x64, 0x64, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x58, 0x49, 0x44, 0x20, 0x2d, 0x20, 0x65, 0x69, + 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, + 0x61, 0x73, 0x20, 0x61, 0x0a, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2c, 0x20, 0x6f, 0x72, + 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x61, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x65, 0x68, 0x61, 0x6c, + 0x66, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, + 0x0a, 0x20, 0x41, 0x20, 0x6b, 0x65, 0x79, 0x2d, 0x70, 0x61, 0x69, 0x72, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, + 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x72, + 0x6f, 0x6c, 0x65, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x0a, + 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x61, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x72, 0x6f, 0x6c, + 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x27, 0x08, 0x16, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x28, 0x02, 0x2d, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x03, 0x02, 0x00, 0x06, 0x12, 0x03, 0x28, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x28, 0x13, 0x28, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x28, 0x2b, 0x2c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, + 0x29, 0x02, 0x2a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x06, 0x12, 0x03, 0x29, 0x02, + 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, 0x03, 0x29, 0x0c, 0x25, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x03, 0x12, 0x03, 0x29, 0x28, 0x29, 0x0a, 0x0b, 0x0a, + 0x04, 0x04, 0x03, 0x02, 0x02, 0x12, 0x03, 0x2a, 0x02, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, + 0x02, 0x02, 0x06, 0x12, 0x03, 0x2a, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, + 0x01, 0x12, 0x03, 0x2a, 0x0c, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x12, + 0x03, 0x2a, 0x23, 0x24, 0x0a, 0x5a, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x2e, 0x00, 0x31, 0x01, + 0x1a, 0x4e, 0x20, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x73, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x20, 0x58, 0x49, 0x44, 0x2e, + 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x2e, 0x08, 0x19, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x2f, 0x02, 0x28, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, + 0x00, 0x06, 0x12, 0x03, 0x2f, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, + 0x12, 0x03, 0x2f, 0x13, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x2f, 0x26, 0x27, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, 0x03, 0x30, 0x02, 0x2b, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x06, 0x12, 0x03, 0x30, 0x02, 0x0b, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x30, 0x0c, 0x26, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x30, 0x29, 0x2a, 0x0a, 0xd1, 0x01, 0x0a, 0x02, 0x04, + 0x05, 0x12, 0x04, 0x36, 0x00, 0x39, 0x01, 0x1a, 0xc4, 0x01, 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x20, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x58, + 0x49, 0x44, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, + 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, + 0x61, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x58, 0x49, 0x44, 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, + 0x6f, 0x20, 0x61, 0x64, 0x64, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x74, + 0x68, 0x65, 0x0a, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x72, 0x65, + 0x76, 0x6f, 0x6b, 0x65, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x0a, 0x0a, + 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, 0x36, 0x08, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, + 0x02, 0x00, 0x12, 0x03, 0x37, 0x02, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x05, + 0x12, 0x03, 0x37, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x37, 0x09, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x37, 0x20, + 0x21, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x01, 0x12, 0x03, 0x38, 0x02, 0x34, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x06, 0x12, 0x03, 0x38, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x05, 0x02, 0x01, 0x01, 0x12, 0x03, 0x38, 0x0c, 0x2f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, + 0x02, 0x01, 0x03, 0x12, 0x03, 0x38, 0x32, 0x33, 0x0a, 0x29, 0x0a, 0x02, 0x04, 0x06, 0x12, 0x04, + 0x3c, 0x00, 0x43, 0x01, 0x1a, 0x1d, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x3c, 0x08, 0x16, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x06, 0x08, 0x00, 0x12, 0x04, 0x3d, 0x02, 0x42, 0x03, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x06, 0x08, 0x00, 0x01, 0x12, 0x03, 0x3d, 0x08, 0x0c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x06, 0x02, 0x00, 0x12, 0x03, 0x3e, 0x04, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, + 0x06, 0x12, 0x03, 0x3e, 0x04, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x3e, 0x10, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3e, + 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x01, 0x12, 0x03, 0x3f, 0x04, 0x1b, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x06, 0x12, 0x03, 0x3f, 0x04, 0x12, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x06, 0x02, 0x01, 0x01, 0x12, 0x03, 0x3f, 0x13, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x06, 0x02, 0x01, 0x03, 0x12, 0x03, 0x3f, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, + 0x02, 0x12, 0x03, 0x40, 0x04, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x02, 0x06, 0x12, + 0x03, 0x40, 0x04, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x02, 0x01, 0x12, 0x03, 0x40, + 0x16, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x02, 0x03, 0x12, 0x03, 0x40, 0x1f, 0x20, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x03, 0x12, 0x03, 0x41, 0x04, 0x36, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x06, 0x02, 0x03, 0x06, 0x12, 0x03, 0x41, 0x04, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x06, 0x02, 0x03, 0x01, 0x12, 0x03, 0x41, 0x1a, 0x31, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, + 0x03, 0x03, 0x12, 0x03, 0x41, 0x34, 0x35, 0x0a, 0xd5, 0x03, 0x0a, 0x02, 0x04, 0x07, 0x12, 0x04, + 0x4c, 0x00, 0x50, 0x01, 0x1a, 0xc8, 0x03, 0x20, 0x4f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6d, + 0x6f, 0x72, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x0a, + 0x20, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x20, 0x5b, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x58, 0x69, 0x64, 0x2c, 0x20, 0x41, 0x64, 0x64, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5d, 0x0a, 0x20, 0x31, 0x2e, + 0x20, 0x54, 0x68, 0x65, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, + 0x65, 0x6e, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x65, 0x78, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, + 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x61, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2c, 0x20, 0x27, 0x5c, + 0x6e, 0x5c, 0x6e, 0x5c, 0x6e, 0x27, 0x2e, 0x0a, 0x20, 0x32, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, + 0x75, 0x73, 0x65, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x20, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x2e, 0x0a, 0x20, 0x33, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x20, 0x69, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x63, + 0x68, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, + 0x6e, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, + 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, + 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x70, 0x6c, 0x65, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x0a, + 0x0a, 0x0a, 0x03, 0x04, 0x07, 0x01, 0x12, 0x03, 0x4c, 0x08, 0x16, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x07, 0x02, 0x00, 0x12, 0x03, 0x4d, 0x02, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, + 0x04, 0x12, 0x03, 0x4d, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x06, 0x12, + 0x03, 0x4d, 0x0b, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x01, 0x12, 0x03, 0x4d, + 0x1a, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x03, 0x12, 0x03, 0x4d, 0x24, 0x25, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x01, 0x12, 0x03, 0x4e, 0x02, 0x21, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x07, 0x02, 0x01, 0x05, 0x12, 0x03, 0x4e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x07, 0x02, 0x01, 0x01, 0x12, 0x03, 0x4e, 0x09, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, + 0x01, 0x03, 0x12, 0x03, 0x4e, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x02, 0x12, + 0x03, 0x4f, 0x02, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x02, 0x05, 0x12, 0x03, 0x4f, + 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x02, 0x01, 0x12, 0x03, 0x4f, 0x09, 0x11, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x02, 0x03, 0x12, 0x03, 0x4f, 0x14, 0x15, 0x0a, 0x35, + 0x0a, 0x02, 0x04, 0x08, 0x12, 0x04, 0x53, 0x00, 0x56, 0x01, 0x1a, 0x29, 0x20, 0x4d, 0x61, 0x70, + 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x6f, + 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x62, 0x6f, + 0x78, 0x5f, 0x69, 0x64, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x08, 0x01, 0x12, 0x03, 0x53, 0x08, + 0x11, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x00, 0x12, 0x03, 0x54, 0x02, 0x1b, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x06, 0x12, 0x03, 0x54, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x08, 0x02, 0x00, 0x01, 0x12, 0x03, 0x54, 0x13, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x54, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x01, + 0x12, 0x03, 0x55, 0x02, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x06, 0x12, 0x03, + 0x55, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x01, 0x12, 0x03, 0x55, 0x09, + 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x03, 0x12, 0x03, 0x55, 0x11, 0x12, 0x0a, + 0x51, 0x0a, 0x02, 0x04, 0x09, 0x12, 0x04, 0x59, 0x00, 0x5e, 0x01, 0x1a, 0x45, 0x20, 0x41, 0x20, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, + 0x67, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, + 0x60, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, + 0x60, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x09, 0x01, 0x12, 0x03, 0x59, 0x08, 0x18, 0x0a, 0x0b, + 0x0a, 0x04, 0x04, 0x09, 0x02, 0x00, 0x12, 0x03, 0x5a, 0x02, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x09, 0x02, 0x00, 0x05, 0x12, 0x03, 0x5a, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x5a, 0x09, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x03, + 0x12, 0x03, 0x5a, 0x14, 0x15, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x09, 0x02, 0x01, 0x12, 0x03, 0x5b, + 0x02, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x01, 0x04, 0x12, 0x03, 0x5b, 0x02, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x01, 0x06, 0x12, 0x03, 0x5b, 0x0b, 0x14, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x09, 0x02, 0x01, 0x01, 0x12, 0x03, 0x5b, 0x15, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x09, 0x02, 0x01, 0x03, 0x12, 0x03, 0x5b, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x09, + 0x02, 0x02, 0x12, 0x03, 0x5c, 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x02, 0x05, + 0x12, 0x03, 0x5c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x02, 0x01, 0x12, 0x03, + 0x5c, 0x09, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x02, 0x03, 0x12, 0x03, 0x5c, 0x1c, + 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x09, 0x02, 0x03, 0x12, 0x03, 0x5d, 0x02, 0x25, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x09, 0x02, 0x03, 0x04, 0x12, 0x03, 0x5d, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x09, 0x02, 0x03, 0x05, 0x12, 0x03, 0x5d, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, + 0x02, 0x03, 0x01, 0x12, 0x03, 0x5d, 0x11, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x03, + 0x03, 0x12, 0x03, 0x5d, 0x23, 0x24, 0x0a, 0x3d, 0x0a, 0x02, 0x04, 0x0a, 0x12, 0x04, 0x61, 0x00, + 0x64, 0x01, 0x1a, 0x31, 0x2f, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, + 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x66, 0x69, 0x6e, + 0x61, 0x6c, 0x20, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x0a, 0x01, 0x12, 0x03, 0x61, 0x08, + 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0a, 0x02, 0x00, 0x12, 0x03, 0x62, 0x02, 0x2c, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x04, 0x12, 0x03, 0x62, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x0a, 0x02, 0x00, 0x06, 0x12, 0x03, 0x62, 0x0b, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x62, 0x1c, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x62, 0x2a, 0x2b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0a, 0x02, 0x01, 0x12, 0x03, + 0x63, 0x02, 0x30, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x01, 0x04, 0x12, 0x03, 0x63, 0x02, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x01, 0x06, 0x12, 0x03, 0x63, 0x0b, 0x1b, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x01, 0x01, 0x12, 0x03, 0x63, 0x1c, 0x2b, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x0a, 0x02, 0x01, 0x03, 0x12, 0x03, 0x63, 0x2e, 0x2f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, ]; include!("xmtp.identity.associations.serde.rs"); // @@protoc_insertion_point(module) \ No newline at end of file diff --git a/xmtp_proto/src/gen/xmtp.identity.associations.serde.rs b/xmtp_proto/src/gen/xmtp.identity.associations.serde.rs index 89ceafd87..78668b72f 100644 --- a/xmtp_proto/src/gen/xmtp.identity.associations.serde.rs +++ b/xmtp_proto/src/gen/xmtp.identity.associations.serde.rs @@ -1017,6 +1017,9 @@ impl serde::Serialize for Member { if self.added_by_entity.is_some() { len += 1; } + if self.client_timestamp_ns.is_some() { + len += 1; + } let mut struct_ser = serializer.serialize_struct("xmtp.identity.associations.Member", len)?; if let Some(v) = self.identifier.as_ref() { struct_ser.serialize_field("identifier", v)?; @@ -1024,6 +1027,11 @@ impl serde::Serialize for Member { if let Some(v) = self.added_by_entity.as_ref() { struct_ser.serialize_field("addedByEntity", v)?; } + if let Some(v) = self.client_timestamp_ns.as_ref() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("clientTimestampNs", ToString::to_string(&v).as_str())?; + } struct_ser.end() } } @@ -1037,12 +1045,15 @@ impl<'de> serde::Deserialize<'de> for Member { "identifier", "added_by_entity", "addedByEntity", + "client_timestamp_ns", + "clientTimestampNs", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { Identifier, AddedByEntity, + ClientTimestampNs, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1066,6 +1077,7 @@ impl<'de> serde::Deserialize<'de> for Member { match value { "identifier" => Ok(GeneratedField::Identifier), "addedByEntity" | "added_by_entity" => Ok(GeneratedField::AddedByEntity), + "clientTimestampNs" | "client_timestamp_ns" => Ok(GeneratedField::ClientTimestampNs), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1087,6 +1099,7 @@ impl<'de> serde::Deserialize<'de> for Member { { let mut identifier__ = None; let mut added_by_entity__ = None; + let mut client_timestamp_ns__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::Identifier => { @@ -1101,11 +1114,20 @@ impl<'de> serde::Deserialize<'de> for Member { } added_by_entity__ = map_.next_value()?; } + GeneratedField::ClientTimestampNs => { + if client_timestamp_ns__.is_some() { + return Err(serde::de::Error::duplicate_field("clientTimestampNs")); + } + client_timestamp_ns__ = + map_.next_value::<::std::option::Option<::pbjson::private::NumberDeserialize<_>>>()?.map(|x| x.0) + ; + } } } Ok(Member { identifier: identifier__, added_by_entity: added_by_entity__, + client_timestamp_ns: client_timestamp_ns__, }) } } @@ -1808,9 +1830,6 @@ impl serde::Serialize for SmartContractWalletSignature { if !self.signature.is_empty() { len += 1; } - if !self.chain_rpc_url.is_empty() { - len += 1; - } let mut struct_ser = serializer.serialize_struct("xmtp.identity.associations.SmartContractWalletSignature", len)?; if !self.account_id.is_empty() { struct_ser.serialize_field("accountId", &self.account_id)?; @@ -1825,9 +1844,6 @@ impl serde::Serialize for SmartContractWalletSignature { #[allow(clippy::needless_borrows_for_generic_args)] struct_ser.serialize_field("signature", pbjson::private::base64::encode(&self.signature).as_str())?; } - if !self.chain_rpc_url.is_empty() { - struct_ser.serialize_field("chainRpcUrl", &self.chain_rpc_url)?; - } struct_ser.end() } } @@ -1843,8 +1859,6 @@ impl<'de> serde::Deserialize<'de> for SmartContractWalletSignature { "block_number", "blockNumber", "signature", - "chain_rpc_url", - "chainRpcUrl", ]; #[allow(clippy::enum_variant_names)] @@ -1852,7 +1866,6 @@ impl<'de> serde::Deserialize<'de> for SmartContractWalletSignature { AccountId, BlockNumber, Signature, - ChainRpcUrl, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -1877,7 +1890,6 @@ impl<'de> serde::Deserialize<'de> for SmartContractWalletSignature { "accountId" | "account_id" => Ok(GeneratedField::AccountId), "blockNumber" | "block_number" => Ok(GeneratedField::BlockNumber), "signature" => Ok(GeneratedField::Signature), - "chainRpcUrl" | "chain_rpc_url" => Ok(GeneratedField::ChainRpcUrl), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -1900,7 +1912,6 @@ impl<'de> serde::Deserialize<'de> for SmartContractWalletSignature { let mut account_id__ = None; let mut block_number__ = None; let mut signature__ = None; - let mut chain_rpc_url__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::AccountId => { @@ -1925,19 +1936,12 @@ impl<'de> serde::Deserialize<'de> for SmartContractWalletSignature { Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) ; } - GeneratedField::ChainRpcUrl => { - if chain_rpc_url__.is_some() { - return Err(serde::de::Error::duplicate_field("chainRpcUrl")); - } - chain_rpc_url__ = Some(map_.next_value()?); - } } } Ok(SmartContractWalletSignature { account_id: account_id__.unwrap_or_default(), block_number: block_number__.unwrap_or_default(), signature: signature__.unwrap_or_default(), - chain_rpc_url: chain_rpc_url__.unwrap_or_default(), }) } } diff --git a/xmtp_proto/src/gen/xmtp.keystore_api.v1.rs b/xmtp_proto/src/gen/xmtp.keystore_api.v1.rs index 65ac75867..83faab516 100644 --- a/xmtp_proto/src/gen/xmtp.keystore_api.v1.rs +++ b/xmtp_proto/src/gen/xmtp.keystore_api.v1.rs @@ -523,6 +523,13 @@ pub mod get_conversation_hmac_keys_response { pub values: ::prost::alloc::vec::Vec, } } +/// A mapping of message hashes to their private preferences action +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PrivatePreferencesActionMap { + #[prost(map="string, message", tag="1")] + pub actions: ::std::collections::HashMap<::prost::alloc::string::String, super::super::message_contents::PrivatePreferencesAction>, +} /// Application-specific error codes for the Keystore API. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] @@ -588,7 +595,7 @@ impl JobType { } /// Encoded file descriptor set for the `xmtp.keystore_api.v1` package pub const FILE_DESCRIPTOR_SET: &[u8] = &[ - 0x0a, 0xba, 0x7c, 0x0a, 0x1e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, + 0x0a, 0xf1, 0x7f, 0x0a, 0x1e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, @@ -601,989 +608,1017 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5e, 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x33, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, - 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xac, 0x02, 0x0a, 0x10, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x6f, 0x1a, 0x2a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x72, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x5e, 0x0a, 0x0d, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x33, 0x0a, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, + 0x65, 0x22, 0xac, 0x02, 0x0a, 0x10, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x31, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x1a, 0xcb, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, + 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x74, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x43, 0x0a, 0x09, 0x70, + 0x65, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x73, + 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x22, 0xb0, 0x02, 0x0a, 0x0f, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, + 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x73, 0x1a, 0xce, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x50, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x36, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x27, + 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x64, 0x65, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0xef, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, + 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x73, 0x1a, 0x8e, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x3b, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x21, 0x0a, + 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x70, 0x69, + 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x54, 0x6f, 0x70, 0x69, 0x63, 0x22, 0xed, 0x01, 0x0a, 0x10, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x31, 0x52, 0x65, 0x71, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0xcb, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, - 0x43, 0x0a, 0x09, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x08, 0x70, 0x65, 0x65, 0x72, - 0x4b, 0x65, 0x79, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x73, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x53, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x22, 0xb0, 0x02, 0x0a, 0x0f, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0xce, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x1a, 0x27, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a, - 0x09, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x09, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xef, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x56, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x08, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x32, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x8e, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, - 0x79, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, - 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x22, 0xed, 0x01, 0x0a, 0x10, 0x45, 0x6e, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, - 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, - 0x31, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x8c, 0x01, 0x0a, 0x07, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xf4, 0x02, 0x0a, 0x0f, 0x45, 0x6e, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, - 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x92, 0x02, 0x0a, 0x08, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, - 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x6b, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x6d, - 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, - 0x48, 0x6d, 0x61, 0x63, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x32, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, - 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x73, 0x1a, 0x6b, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x22, 0x87, - 0x01, 0x0a, 0x12, 0x53, 0x65, 0x6c, 0x66, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, - 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x8c, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x44, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x09, 0x72, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xf4, 0x02, 0x0a, 0x0f, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x92, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x1a, 0x6b, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x3f, + 0x0a, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x74, 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x12, + 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x48, 0x6d, 0x61, 0x63, + 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xcb, 0x01, 0x0a, + 0x10, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x56, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x4a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x56, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x6b, 0x0a, + 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x6c, 0x66, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x73, 0x1a, 0x23, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xbc, 0x02, 0x0a, 0x13, 0x53, 0x65, 0x6c, - 0x66, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x50, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, + 0x74, 0x12, 0x4c, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x45, - 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x73, 0x1a, 0xd2, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x54, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, + 0x23, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xbc, 0x02, 0x0a, 0x13, 0x53, 0x65, 0x6c, 0x66, 0x45, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x09, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x1a, 0x27, 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a, - 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x09, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x6c, 0x66, - 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4c, - 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x44, 0x65, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x23, 0x0a, 0x07, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x22, 0x4e, 0x0a, 0x2c, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x49, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, - 0x72, 0x22, 0x98, 0x02, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, 0x07, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x2e, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x12, 0x4a, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x73, 0x12, 0x4f, 0x0a, 0x0d, 0x63, - 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x65, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0c, - 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x82, 0x01, 0x0a, - 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x22, 0xcf, 0x01, 0x0a, 0x12, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x6b, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x70, - 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x22, 0xf0, 0x02, 0x0a, 0x13, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, - 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x09, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x86, 0x02, - 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x78, 0x6d, 0x74, + 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0xd2, + 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x27, + 0x0a, 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x65, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x6c, 0x66, 0x44, 0x65, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x08, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x66, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x23, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x4e, 0x0a, + 0x2c, 0x47, 0x65, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, + 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x98, 0x02, + 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x49, + 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x09, + 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x09, 0x72, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x73, 0x12, 0x4f, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x65, + 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x74, 0x50, 0x72, + 0x6f, 0x6f, 0x66, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x73, + 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x82, 0x01, 0x0a, 0x14, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x50, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, + 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xcf, 0x01, + 0x0a, 0x12, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x4c, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, + 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x61, + 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x73, 0x1a, 0x6b, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, + 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x70, + 0x69, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, + 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, + 0xf0, 0x02, 0x0a, 0x13, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, - 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x12, 0x3b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x5b, 0x0a, - 0x07, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x50, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x63, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x51, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x26, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x22, 0x70, 0x0a, 0x1a, 0x53, 0x61, 0x76, - 0x65, 0x56, 0x31, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x52, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0d, 0x63, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x1d, 0x0a, 0x1b, 0x53, - 0x61, 0x76, 0x65, 0x56, 0x31, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6e, 0x0a, 0x18, 0x47, 0x65, - 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, - 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0d, 0x63, 0x6f, 0x6e, - 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x41, 0x0a, 0x18, 0x47, 0x65, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x86, 0x02, 0x0a, 0x08, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, + 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x61, + 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x3b, 0x0a, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x5b, 0x0a, 0x07, 0x53, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x12, 0x50, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x51, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0c, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, + 0x73, 0x88, 0x01, 0x01, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x22, 0x70, 0x0a, 0x1a, 0x53, 0x61, 0x76, 0x65, 0x56, 0x31, 0x43, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x52, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x1d, 0x0a, 0x1b, 0x53, 0x61, 0x76, 0x65, 0x56, + 0x31, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6e, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x41, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xea, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xea, 0x01, - 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x78, 0x6d, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, + 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, + 0x75, 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x4b, 0x45, 0x59, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x4b, 0x45, 0x59, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x5f, 0x53, + 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, + 0x5a, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x4b, 0x45, 0x59, 0x53, 0x54, 0x4f, 0x52, + 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, + 0x49, 0x5a, 0x45, 0x44, 0x10, 0x02, 0x22, 0x5c, 0x0a, 0x13, 0x49, 0x6e, 0x69, 0x74, 0x4b, 0x65, + 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, + 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, 0x08, 0x0a, 0x06, 0x62, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x51, 0x0a, 0x14, 0x49, 0x6e, 0x69, 0x74, 0x4b, 0x65, 0x79, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4b, 0x65, 0x79, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x75, 0x0a, 0x0e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x4b, 0x45, 0x59, 0x53, 0x54, 0x4f, 0x52, - 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x4b, 0x45, 0x59, 0x53, 0x54, 0x4f, - 0x52, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x49, 0x4e, 0x49, 0x54, - 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x4b, 0x45, 0x59, - 0x53, 0x54, 0x4f, 0x52, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x49, 0x4e, 0x49, - 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x02, 0x22, 0x5c, 0x0a, 0x13, 0x49, 0x6e, - 0x69, 0x74, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x3b, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, 0x08, - 0x0a, 0x06, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x51, 0x0a, 0x14, 0x49, 0x6e, 0x69, 0x74, - 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x39, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7f, 0x0a, 0x11, 0x53, - 0x69, 0x67, 0x6e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0c, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, - 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x23, 0x0a, - 0x0c, 0x70, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x50, 0x0a, 0x14, - 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x08, 0x6a, 0x6f, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, - 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, - 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x6a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x22, 0x37, - 0x0a, 0x15, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x72, 0x75, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6c, 0x61, - 0x73, 0x74, 0x52, 0x75, 0x6e, 0x4e, 0x73, 0x22, 0x6f, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x52, 0x65, - 0x66, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, - 0x0a, 0x08, 0x6a, 0x6f, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x1d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x07, 0x6a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6c, - 0x61, 0x73, 0x74, 0x52, 0x75, 0x6e, 0x4e, 0x73, 0x22, 0x17, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0xc8, 0x02, 0x0a, 0x08, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4d, 0x61, 0x70, 0x12, 0x42, - 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4d, 0x61, 0x70, 0x2e, 0x54, - 0x6f, 0x70, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, - 0x63, 0x73, 0x1a, 0x92, 0x01, 0x0a, 0x09, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, - 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x73, 0x12, - 0x21, 0x0a, 0x0c, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x43, 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x52, 0x0a, 0x69, 0x6e, 0x76, - 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x63, 0x0a, 0x0b, 0x54, 0x6f, 0x70, 0x69, 0x63, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, - 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x6f, 0x70, 0x69, 0x63, 0x4d, 0x61, 0x70, 0x2e, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x44, 0x61, 0x74, - 0x61, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x38, 0x0a, 0x1e, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, - 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, - 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x22, 0xd5, 0x03, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, - 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x09, 0x68, 0x6d, - 0x61, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x08, 0x68, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0x6c, 0x0a, 0x0b, - 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x42, 0x0a, 0x1e, 0x74, - 0x68, 0x69, 0x72, 0x74, 0x79, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, - 0x73, 0x5f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x1a, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x44, 0x61, 0x79, 0x50, 0x65, - 0x72, 0x69, 0x6f, 0x64, 0x73, 0x53, 0x69, 0x6e, 0x63, 0x65, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, - 0x19, 0x0a, 0x08, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x68, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x1a, 0x65, 0x0a, 0x08, 0x48, 0x6d, - 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x59, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, - 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6d, 0x61, - 0x63, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x6d, - 0x61, 0x63, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x73, 0x1a, 0x7b, 0x0a, 0x0d, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x6e, 0x74, + 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x7f, 0x0a, 0x11, 0x53, 0x69, 0x67, 0x6e, 0x44, + 0x69, 0x67, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x64, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0c, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0c, 0x70, 0x72, 0x65, + 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x48, + 0x00, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x08, + 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x22, 0x50, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x38, 0x0a, 0x08, 0x6a, 0x6f, 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x07, 0x6a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x22, 0x37, 0x0a, 0x15, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x75, 0x6e, 0x5f, + 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x75, + 0x6e, 0x4e, 0x73, 0x22, 0x6f, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x65, 0x73, 0x68, + 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x08, 0x6a, 0x6f, + 0x62, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x6a, 0x6f, 0x62, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x75, 0x6e, + 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x52, + 0x75, 0x6e, 0x4e, 0x73, 0x22, 0x17, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, + 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc8, 0x02, + 0x0a, 0x08, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4d, 0x61, 0x70, 0x12, 0x42, 0x0a, 0x06, 0x74, 0x6f, + 0x70, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x4d, 0x61, 0x70, 0x2e, 0x54, 0x6f, 0x70, 0x69, 0x63, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x1a, 0x92, + 0x01, 0x0a, 0x09, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, + 0x65, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x43, + 0x0a, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x76, 0x69, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x52, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x1a, 0x63, 0x0a, 0x0b, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x54, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, - 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x4b, - 0x65, 0x79, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x2a, 0x68, - 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x49, 0x4e, - 0x50, 0x55, 0x54, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, - 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x49, 0x4e, 0x47, 0x5f, - 0x50, 0x52, 0x45, 0x4b, 0x45, 0x59, 0x10, 0x02, 0x2a, 0x70, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, - 0x13, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x46, 0x52, 0x45, 0x53, - 0x48, 0x5f, 0x56, 0x31, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x52, 0x45, 0x46, 0x52, 0x45, 0x53, 0x48, 0x5f, 0x56, 0x32, 0x10, 0x02, 0x12, - 0x19, 0x0a, 0x15, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x46, 0x52, - 0x45, 0x53, 0x48, 0x5f, 0x50, 0x50, 0x50, 0x50, 0x10, 0x03, 0x42, 0xc4, 0x01, 0x0a, 0x18, 0x63, - 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x58, 0x4b, 0x58, 0xaa, 0x02, 0x13, 0x58, 0x6d, - 0x74, 0x70, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x70, 0x69, 0x2e, 0x56, - 0x31, 0xca, 0x02, 0x13, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1f, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4b, - 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, - 0x3a, 0x3a, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, - 0x31, 0x4a, 0x81, 0x4c, 0x0a, 0x07, 0x12, 0x05, 0x01, 0x00, 0xbb, 0x02, 0x01, 0x0a, 0x2f, 0x0a, - 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x25, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, - 0x6e, 0x67, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x0a, 0x0a, 0x08, - 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x1d, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, - 0x05, 0x00, 0x2b, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x01, 0x12, 0x03, 0x06, 0x00, 0x37, 0x0a, 0x09, - 0x0a, 0x02, 0x03, 0x02, 0x12, 0x03, 0x07, 0x00, 0x2b, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x03, 0x12, - 0x03, 0x08, 0x00, 0x2c, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x04, 0x12, 0x03, 0x09, 0x00, 0x2b, 0x0a, - 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x0b, 0x00, 0x42, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, - 0x03, 0x0b, 0x00, 0x42, 0x0a, 0x44, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, 0x0f, 0x00, 0x13, 0x01, - 0x1a, 0x38, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, - 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x63, 0x6f, - 0x64, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x20, 0x41, 0x50, 0x49, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, - 0x01, 0x12, 0x03, 0x0f, 0x05, 0x0e, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, - 0x10, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x10, 0x02, - 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x10, 0x1b, 0x1c, 0x0a, - 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x11, 0x02, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, - 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x11, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, - 0x02, 0x01, 0x02, 0x12, 0x03, 0x11, 0x1d, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x02, - 0x12, 0x03, 0x12, 0x02, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, - 0x12, 0x02, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x12, 0x22, - 0x23, 0x0a, 0x3c, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x16, 0x00, 0x19, 0x01, 0x1a, 0x30, 0x20, - 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, - 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x16, 0x08, 0x15, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x00, 0x02, 0x00, 0x12, 0x03, 0x17, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, - 0x05, 0x12, 0x03, 0x17, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, - 0x03, 0x17, 0x09, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x17, - 0x13, 0x14, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x18, 0x02, 0x15, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x18, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x18, 0x0c, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x18, 0x13, 0x14, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x01, 0x12, - 0x04, 0x1c, 0x00, 0x26, 0x01, 0x1a, 0x36, 0x20, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, - 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x58, 0x33, 0x44, 0x48, 0x20, 0x6b, - 0x65, 0x79, 0x20, 0x61, 0x67, 0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, - 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x1c, 0x08, 0x18, 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x01, 0x03, - 0x00, 0x12, 0x04, 0x1e, 0x02, 0x23, 0x03, 0x1a, 0x1d, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, - 0x6c, 0x65, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x03, 0x00, 0x01, 0x12, - 0x03, 0x1e, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, - 0x1f, 0x04, 0x31, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x1f, 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, - 0x1f, 0x25, 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x1f, 0x2f, 0x30, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x20, - 0x04, 0x38, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x20, - 0x04, 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x20, - 0x2a, 0x33, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x20, - 0x36, 0x37, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x21, 0x04, - 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x21, 0x04, - 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x21, 0x0a, - 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x21, 0x19, - 0x1a, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x12, 0x03, 0x22, 0x04, 0x17, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x22, 0x04, 0x08, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x22, 0x09, 0x12, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x22, 0x15, 0x16, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x25, 0x02, 0x20, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x25, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x25, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, - 0x00, 0x01, 0x12, 0x03, 0x25, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x25, 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x29, 0x00, 0x38, - 0x01, 0x1a, 0x36, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x79, 0x70, - 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x56, 0x31, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x56, 0x32, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, - 0x12, 0x03, 0x29, 0x08, 0x17, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x2b, - 0x02, 0x35, 0x03, 0x1a, 0x1e, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x64, - 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x00, 0x01, 0x12, 0x03, 0x2b, 0x0a, - 0x12, 0x0a, 0x35, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x03, 0x00, 0x12, 0x04, 0x2d, 0x04, 0x2f, - 0x05, 0x1a, 0x25, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, - 0x03, 0x00, 0x01, 0x12, 0x03, 0x2d, 0x0c, 0x13, 0x0a, 0x0f, 0x0a, 0x08, 0x04, 0x02, 0x03, 0x00, - 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x2e, 0x06, 0x1a, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x02, 0x03, - 0x00, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2e, 0x06, 0x0b, 0x0a, 0x10, 0x0a, 0x09, 0x04, - 0x02, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2e, 0x0c, 0x15, 0x0a, 0x10, 0x0a, - 0x09, 0x04, 0x02, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2e, 0x18, 0x19, 0x0a, - 0x0e, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x08, 0x00, 0x12, 0x04, 0x31, 0x04, 0x34, 0x05, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x08, 0x00, 0x01, 0x12, 0x03, 0x31, 0x0a, 0x12, 0x0a, - 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x32, 0x06, 0x19, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x32, 0x06, 0x0d, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x32, 0x0e, 0x14, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x32, 0x17, 0x18, 0x0a, 0x0d, - 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x33, 0x06, 0x1e, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x33, 0x06, 0x13, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x33, 0x14, 0x19, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x33, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x37, 0x02, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, - 0x02, 0x00, 0x04, 0x12, 0x03, 0x37, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, - 0x06, 0x12, 0x03, 0x37, 0x0b, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, - 0x03, 0x37, 0x14, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x37, - 0x20, 0x21, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x3b, 0x00, 0x44, 0x01, 0x1a, 0x3e, - 0x20, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, - 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x70, 0x72, 0x69, 0x61, - 0x74, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x3b, 0x08, 0x18, 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x03, - 0x03, 0x00, 0x12, 0x04, 0x3d, 0x02, 0x41, 0x03, 0x1a, 0x1d, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, - 0x67, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x03, 0x00, 0x01, - 0x12, 0x03, 0x3d, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x12, - 0x03, 0x3e, 0x04, 0x31, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, - 0x03, 0x3e, 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, - 0x03, 0x3e, 0x25, 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, - 0x03, 0x3e, 0x2f, 0x30, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, - 0x3f, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, - 0x3f, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, - 0x3f, 0x0a, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, - 0x3f, 0x19, 0x1a, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x40, - 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x40, - 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x40, - 0x0b, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x40, - 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x43, 0x02, 0x20, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x04, 0x12, 0x03, 0x43, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, 0x12, 0x03, 0x43, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x43, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, - 0x00, 0x03, 0x12, 0x03, 0x43, 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x47, - 0x00, 0x50, 0x01, 0x1a, 0x36, 0x20, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x61, 0x20, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x6f, 0x70, 0x69, 0x63, + 0x4d, 0x61, 0x70, 0x2e, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x38, 0x0a, 0x1e, 0x47, 0x65, 0x74, 0x43, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x4b, + 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6f, + 0x70, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6f, 0x70, 0x69, + 0x63, 0x73, 0x22, 0xd5, 0x03, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x09, 0x68, 0x6d, 0x61, 0x63, 0x5f, 0x6b, + 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, + 0x68, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0x6c, 0x0a, 0x0b, 0x48, 0x6d, 0x61, 0x63, + 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x42, 0x0a, 0x1e, 0x74, 0x68, 0x69, 0x72, 0x74, + 0x79, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x5f, 0x73, 0x69, + 0x6e, 0x63, 0x65, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x1a, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x44, 0x61, 0x79, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, + 0x73, 0x53, 0x69, 0x6e, 0x63, 0x65, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x68, + 0x6d, 0x61, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x68, + 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x1a, 0x65, 0x0a, 0x08, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, + 0x79, 0x73, 0x12, 0x59, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, + 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x7b, 0x0a, + 0x0d, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x54, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x3e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe4, 0x01, 0x0a, 0x1b, 0x50, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x12, 0x58, 0x0a, 0x07, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x70, 0x2e, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6b, 0x0a, 0x0c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x2a, 0x68, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1a, + 0x0a, 0x16, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, + 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x41, 0x54, 0x43, 0x48, 0x49, + 0x4e, 0x47, 0x5f, 0x50, 0x52, 0x45, 0x4b, 0x45, 0x59, 0x10, 0x02, 0x2a, 0x70, 0x0a, 0x07, 0x4a, + 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x17, 0x0a, 0x13, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x46, + 0x52, 0x45, 0x53, 0x48, 0x5f, 0x56, 0x31, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4a, 0x4f, 0x42, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x46, 0x52, 0x45, 0x53, 0x48, 0x5f, 0x56, 0x32, + 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4a, 0x4f, 0x42, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, + 0x45, 0x46, 0x52, 0x45, 0x53, 0x48, 0x5f, 0x50, 0x50, 0x50, 0x50, 0x10, 0x03, 0x42, 0xc4, 0x01, + 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6b, 0x65, 0x79, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0d, 0x4b, 0x65, 0x79, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x58, 0x4b, 0x58, 0xaa, 0x02, + 0x13, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x70, + 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x13, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4b, 0x65, 0x79, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1f, 0x58, 0x6d, 0x74, + 0x70, 0x5c, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, + 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x70, 0x69, + 0x3a, 0x3a, 0x56, 0x31, 0x4a, 0xa5, 0x4d, 0x0a, 0x07, 0x12, 0x05, 0x01, 0x00, 0xc1, 0x02, 0x01, + 0x0a, 0x2f, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x25, 0x20, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x63, + 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, + 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x1d, 0x0a, 0x09, 0x0a, 0x02, 0x03, + 0x00, 0x12, 0x03, 0x05, 0x00, 0x2b, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x01, 0x12, 0x03, 0x06, 0x00, + 0x37, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, 0x12, 0x03, 0x07, 0x00, 0x2b, 0x0a, 0x09, 0x0a, 0x02, + 0x03, 0x03, 0x12, 0x03, 0x08, 0x00, 0x2c, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x04, 0x12, 0x03, 0x09, + 0x00, 0x34, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x05, 0x12, 0x03, 0x0a, 0x00, 0x2b, 0x0a, 0x08, 0x0a, + 0x01, 0x08, 0x12, 0x03, 0x0c, 0x00, 0x42, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x0c, + 0x00, 0x42, 0x0a, 0x44, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, 0x10, 0x00, 0x14, 0x01, 0x1a, 0x38, + 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x73, 0x70, 0x65, + 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x64, 0x65, + 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, + 0x72, 0x65, 0x20, 0x41, 0x50, 0x49, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, 0x01, 0x12, + 0x03, 0x10, 0x05, 0x0e, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, 0x11, 0x02, + 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x11, 0x02, 0x18, 0x0a, + 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x11, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, + 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x12, 0x02, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x12, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, + 0x02, 0x12, 0x03, 0x12, 0x1d, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x02, 0x12, 0x03, + 0x13, 0x02, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x13, 0x02, + 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x13, 0x22, 0x23, 0x0a, + 0x3c, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x17, 0x00, 0x1a, 0x01, 0x1a, 0x30, 0x20, 0x57, 0x72, + 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x17, 0x08, 0x15, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, + 0x00, 0x12, 0x03, 0x18, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, + 0x03, 0x18, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x18, + 0x09, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x18, 0x13, 0x14, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x19, 0x02, 0x15, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x19, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x19, 0x0c, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x01, 0x03, 0x12, 0x03, 0x19, 0x13, 0x14, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x1d, + 0x00, 0x27, 0x01, 0x1a, 0x36, 0x20, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x58, 0x33, 0x44, 0x48, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x61, 0x67, 0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, - 0x04, 0x01, 0x12, 0x03, 0x47, 0x08, 0x18, 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x04, 0x03, 0x00, 0x12, - 0x04, 0x49, 0x02, 0x4d, 0x03, 0x1a, 0x1d, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, - 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x03, 0x00, 0x01, 0x12, 0x03, 0x49, - 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x4a, 0x04, - 0x38, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x4a, 0x04, - 0x29, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x4a, 0x2a, - 0x33, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x4a, 0x36, - 0x37, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x4b, 0x04, 0x16, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x4b, 0x04, 0x09, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x4b, 0x0a, 0x11, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x4b, 0x14, 0x15, - 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x4c, 0x04, 0x1b, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x4c, 0x04, 0x09, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x4c, 0x0a, 0x16, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x4c, 0x19, 0x1a, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x4f, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x04, 0x02, 0x00, 0x04, 0x12, 0x03, 0x4f, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, - 0x02, 0x00, 0x06, 0x12, 0x03, 0x4f, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x4f, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, - 0x03, 0x4f, 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x53, 0x00, 0x63, 0x01, - 0x1a, 0x36, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x56, 0x31, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x56, 0x32, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, - 0x03, 0x53, 0x08, 0x17, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x05, 0x03, 0x00, 0x12, 0x04, 0x55, 0x02, - 0x60, 0x03, 0x1a, 0x1e, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x65, 0x6e, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x03, 0x00, 0x01, 0x12, 0x03, 0x55, 0x0a, 0x12, - 0x0a, 0x35, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x12, 0x04, 0x57, 0x04, 0x5a, 0x05, - 0x1a, 0x25, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x72, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x03, - 0x00, 0x01, 0x12, 0x03, 0x57, 0x0c, 0x13, 0x0a, 0x0f, 0x0a, 0x08, 0x04, 0x05, 0x03, 0x00, 0x03, - 0x00, 0x02, 0x00, 0x12, 0x03, 0x58, 0x06, 0x35, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x05, 0x03, 0x00, - 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x58, 0x06, 0x26, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x05, - 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x58, 0x27, 0x30, 0x0a, 0x10, 0x0a, 0x09, - 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x58, 0x33, 0x34, 0x0a, 0x0f, - 0x0a, 0x08, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x59, 0x06, 0x1c, 0x0a, - 0x10, 0x0a, 0x09, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x59, 0x06, - 0x0b, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, - 0x59, 0x0c, 0x17, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, - 0x12, 0x03, 0x59, 0x1a, 0x1b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x08, 0x00, 0x12, - 0x04, 0x5c, 0x04, 0x5f, 0x05, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x08, 0x00, 0x01, - 0x12, 0x03, 0x5c, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x12, - 0x03, 0x5d, 0x06, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, - 0x03, 0x5d, 0x06, 0x0d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, - 0x03, 0x5d, 0x0e, 0x14, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, - 0x03, 0x5d, 0x17, 0x18, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, - 0x5e, 0x06, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, - 0x5e, 0x06, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, - 0x5e, 0x14, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, - 0x5e, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x62, 0x02, 0x22, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x04, 0x12, 0x03, 0x62, 0x02, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x06, 0x12, 0x03, 0x62, 0x0b, 0x13, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x62, 0x14, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x62, 0x20, 0x21, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x06, 0x12, 0x04, - 0x66, 0x00, 0x6f, 0x01, 0x1a, 0x3e, 0x20, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x61, - 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, - 0x72, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x6b, - 0x65, 0x79, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x66, 0x08, 0x18, - 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x06, 0x03, 0x00, 0x12, 0x04, 0x68, 0x02, 0x6c, 0x03, 0x1a, 0x1d, - 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x06, 0x03, 0x00, 0x01, 0x12, 0x03, 0x68, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, - 0x06, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x69, 0x04, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, - 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x69, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, - 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x69, 0x0a, 0x11, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, - 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x69, 0x14, 0x15, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, - 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x6a, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, - 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x6a, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, - 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x6a, 0x0a, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, - 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x6a, 0x19, 0x1a, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, - 0x00, 0x02, 0x02, 0x12, 0x03, 0x6b, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, - 0x02, 0x02, 0x05, 0x12, 0x03, 0x6b, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, - 0x02, 0x02, 0x01, 0x12, 0x03, 0x6b, 0x0b, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, - 0x02, 0x02, 0x03, 0x12, 0x03, 0x6b, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x00, - 0x12, 0x03, 0x6e, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x04, 0x12, 0x03, - 0x6e, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x06, 0x12, 0x03, 0x6e, 0x0b, - 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, 0x03, 0x6e, 0x13, 0x1b, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x6e, 0x1e, 0x1f, 0x0a, 0x2c, 0x0a, - 0x02, 0x04, 0x07, 0x12, 0x04, 0x72, 0x00, 0x79, 0x01, 0x1a, 0x20, 0x20, 0x45, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x6c, 0x66, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, - 0x07, 0x01, 0x12, 0x03, 0x72, 0x08, 0x1a, 0x0a, 0x1c, 0x0a, 0x04, 0x04, 0x07, 0x03, 0x00, 0x12, - 0x04, 0x74, 0x02, 0x76, 0x03, 0x1a, 0x0e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, - 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x03, 0x00, 0x01, 0x12, 0x03, - 0x74, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x75, - 0x04, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x75, - 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x75, - 0x0a, 0x11, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x75, - 0x14, 0x15, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x00, 0x12, 0x03, 0x78, 0x02, 0x20, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x04, 0x12, 0x03, 0x78, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x07, 0x02, 0x00, 0x06, 0x12, 0x03, 0x78, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x07, 0x02, 0x00, 0x01, 0x12, 0x03, 0x78, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, - 0x00, 0x03, 0x12, 0x03, 0x78, 0x1e, 0x1f, 0x0a, 0x33, 0x0a, 0x02, 0x04, 0x08, 0x12, 0x05, 0x7c, - 0x00, 0x8b, 0x01, 0x01, 0x1a, 0x26, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, - 0x74, 0x79, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x65, 0x6c, 0x66, 0x45, 0x6e, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, - 0x04, 0x08, 0x01, 0x12, 0x03, 0x7c, 0x08, 0x1b, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x08, 0x03, 0x00, - 0x12, 0x05, 0x7e, 0x02, 0x88, 0x01, 0x03, 0x1a, 0x0f, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x03, 0x00, - 0x01, 0x12, 0x03, 0x7e, 0x0a, 0x12, 0x0a, 0x24, 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, - 0x12, 0x06, 0x80, 0x01, 0x04, 0x82, 0x01, 0x05, 0x1a, 0x12, 0x20, 0x53, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x01, 0x12, 0x04, 0x80, 0x01, 0x0c, 0x13, 0x0a, 0x10, 0x0a, - 0x08, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0x81, 0x01, 0x06, 0x1a, 0x0a, - 0x11, 0x0a, 0x09, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0x81, 0x01, - 0x06, 0x0b, 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, - 0x04, 0x81, 0x01, 0x0c, 0x15, 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x02, - 0x00, 0x03, 0x12, 0x04, 0x81, 0x01, 0x18, 0x19, 0x0a, 0x10, 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, - 0x08, 0x00, 0x12, 0x06, 0x84, 0x01, 0x04, 0x87, 0x01, 0x05, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, - 0x03, 0x00, 0x08, 0x00, 0x01, 0x12, 0x04, 0x84, 0x01, 0x0a, 0x12, 0x0a, 0x0e, 0x0a, 0x06, 0x04, - 0x08, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0x85, 0x01, 0x06, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, - 0x08, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x04, 0x85, 0x01, 0x06, 0x0d, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x85, 0x01, 0x0e, 0x14, 0x0a, 0x0f, 0x0a, - 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0x85, 0x01, 0x17, 0x18, 0x0a, 0x0e, - 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0x86, 0x01, 0x06, 0x1e, 0x0a, 0x0f, - 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x04, 0x86, 0x01, 0x06, 0x13, 0x0a, - 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x86, 0x01, 0x14, 0x19, - 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0x86, 0x01, 0x1c, - 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x00, 0x12, 0x04, 0x8a, 0x01, 0x02, 0x22, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x04, 0x12, 0x04, 0x8a, 0x01, 0x02, 0x0a, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x06, 0x12, 0x04, 0x8a, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x08, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8a, 0x01, 0x14, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x08, 0x02, 0x00, 0x03, 0x12, 0x04, 0x8a, 0x01, 0x20, 0x21, 0x0a, 0x22, 0x0a, 0x02, 0x04, - 0x09, 0x12, 0x06, 0x8e, 0x01, 0x00, 0x95, 0x01, 0x01, 0x1a, 0x14, 0x20, 0x53, 0x65, 0x6c, 0x66, - 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, - 0x0b, 0x0a, 0x03, 0x04, 0x09, 0x01, 0x12, 0x04, 0x8e, 0x01, 0x08, 0x1a, 0x0a, 0x1e, 0x0a, 0x04, - 0x04, 0x09, 0x03, 0x00, 0x12, 0x06, 0x90, 0x01, 0x02, 0x92, 0x01, 0x03, 0x1a, 0x0e, 0x20, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x09, 0x03, 0x00, 0x01, 0x12, 0x04, 0x90, 0x01, 0x0a, 0x11, 0x0a, 0x0e, 0x0a, 0x06, 0x04, - 0x09, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0x91, 0x01, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, - 0x09, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0x91, 0x01, 0x04, 0x09, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x91, 0x01, 0x0a, 0x11, 0x0a, 0x0f, 0x0a, - 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0x91, 0x01, 0x14, 0x15, 0x0a, 0x0c, - 0x0a, 0x04, 0x04, 0x09, 0x02, 0x00, 0x12, 0x04, 0x94, 0x01, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x09, 0x02, 0x00, 0x04, 0x12, 0x04, 0x94, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x09, 0x02, 0x00, 0x06, 0x12, 0x04, 0x94, 0x01, 0x0b, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, - 0x02, 0x00, 0x01, 0x12, 0x04, 0x94, 0x01, 0x13, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, - 0x00, 0x03, 0x12, 0x04, 0x94, 0x01, 0x1e, 0x1f, 0x0a, 0x3c, 0x0a, 0x02, 0x04, 0x0a, 0x12, 0x06, - 0x98, 0x01, 0x00, 0x9a, 0x01, 0x01, 0x1a, 0x2e, 0x20, 0x47, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0a, 0x01, 0x12, 0x04, 0x98, - 0x01, 0x08, 0x34, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0a, 0x02, 0x00, 0x12, 0x04, 0x99, 0x01, 0x02, - 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x05, 0x12, 0x04, 0x99, 0x01, 0x02, 0x08, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x01, 0x12, 0x04, 0x99, 0x01, 0x09, 0x13, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x03, 0x12, 0x04, 0x99, 0x01, 0x16, 0x17, 0x0a, 0x5d, - 0x0a, 0x02, 0x04, 0x0b, 0x12, 0x06, 0x9d, 0x01, 0x00, 0xa2, 0x01, 0x01, 0x1a, 0x4f, 0x20, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x69, 0x6e, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x0a, 0x0a, 0x0b, 0x0a, - 0x03, 0x04, 0x0b, 0x01, 0x12, 0x04, 0x9d, 0x01, 0x08, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0b, - 0x02, 0x00, 0x12, 0x04, 0x9e, 0x01, 0x02, 0x39, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, - 0x06, 0x12, 0x04, 0x9e, 0x01, 0x02, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x01, - 0x12, 0x04, 0x9e, 0x01, 0x2d, 0x34, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x03, 0x12, - 0x04, 0x9e, 0x01, 0x37, 0x38, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0b, 0x02, 0x01, 0x12, 0x04, 0x9f, - 0x01, 0x02, 0x3c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x06, 0x12, 0x04, 0x9f, 0x01, - 0x02, 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x01, 0x12, 0x04, 0x9f, 0x01, 0x2e, - 0x37, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x03, 0x12, 0x04, 0x9f, 0x01, 0x3a, 0x3b, - 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0b, 0x02, 0x02, 0x12, 0x04, 0xa0, 0x01, 0x02, 0x18, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x02, 0x05, 0x12, 0x04, 0xa0, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x0b, 0x02, 0x02, 0x01, 0x12, 0x04, 0xa0, 0x01, 0x09, 0x13, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x0b, 0x02, 0x02, 0x03, 0x12, 0x04, 0xa0, 0x01, 0x16, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, - 0x0b, 0x02, 0x03, 0x12, 0x04, 0xa1, 0x01, 0x02, 0x3e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, - 0x03, 0x06, 0x12, 0x04, 0xa1, 0x01, 0x02, 0x2b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x03, - 0x01, 0x12, 0x04, 0xa1, 0x01, 0x2c, 0x39, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x03, 0x03, - 0x12, 0x04, 0xa1, 0x01, 0x3c, 0x3d, 0x0a, 0x31, 0x0a, 0x02, 0x04, 0x0c, 0x12, 0x06, 0xa5, 0x01, - 0x00, 0xa8, 0x01, 0x01, 0x1a, 0x23, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x61, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0c, 0x01, - 0x12, 0x04, 0xa5, 0x01, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0c, 0x02, 0x00, 0x12, 0x04, - 0xa6, 0x01, 0x02, 0x3f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x06, 0x12, 0x04, 0xa6, - 0x01, 0x02, 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x01, 0x12, 0x04, 0xa6, 0x01, - 0x2e, 0x3a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x03, 0x12, 0x04, 0xa6, 0x01, 0x3d, - 0x3e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0c, 0x02, 0x01, 0x12, 0x04, 0xa7, 0x01, 0x02, 0x14, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x01, 0x05, 0x12, 0x04, 0xa7, 0x01, 0x02, 0x07, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x01, 0x01, 0x12, 0x04, 0xa7, 0x01, 0x08, 0x0f, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x0c, 0x02, 0x01, 0x03, 0x12, 0x04, 0xa7, 0x01, 0x12, 0x13, 0x0a, 0x4a, 0x0a, 0x02, - 0x04, 0x0d, 0x12, 0x06, 0xab, 0x01, 0x00, 0xb4, 0x01, 0x01, 0x1a, 0x3c, 0x20, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x62, - 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x20, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, - 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0d, 0x01, 0x12, - 0x04, 0xab, 0x01, 0x08, 0x1a, 0x0a, 0x2e, 0x0a, 0x04, 0x04, 0x0d, 0x03, 0x00, 0x12, 0x06, 0xad, - 0x01, 0x02, 0xb1, 0x01, 0x03, 0x1a, 0x1e, 0x20, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x73, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, 0x03, 0x00, 0x01, 0x12, 0x04, - 0xad, 0x01, 0x0a, 0x11, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, - 0xae, 0x01, 0x04, 0x1d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, - 0x04, 0xae, 0x01, 0x04, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x00, 0x01, - 0x12, 0x04, 0xae, 0x01, 0x0b, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x00, - 0x03, 0x12, 0x04, 0xae, 0x01, 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0d, 0x03, 0x00, 0x02, - 0x01, 0x12, 0x04, 0xaf, 0x01, 0x04, 0x1c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, - 0x01, 0x05, 0x12, 0x04, 0xaf, 0x01, 0x04, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, - 0x02, 0x01, 0x01, 0x12, 0x04, 0xaf, 0x01, 0x0b, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, - 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0xaf, 0x01, 0x1a, 0x1b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0d, - 0x03, 0x00, 0x02, 0x02, 0x12, 0x04, 0xb0, 0x01, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, - 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x04, 0xb0, 0x01, 0x04, 0x09, 0x0a, 0x0f, 0x0a, 0x07, 0x04, - 0x0d, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xb0, 0x01, 0x0a, 0x11, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x0d, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x04, 0xb0, 0x01, 0x14, 0x15, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x0d, 0x02, 0x00, 0x12, 0x04, 0xb3, 0x01, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x0d, 0x02, 0x00, 0x04, 0x12, 0x04, 0xb3, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, - 0x02, 0x00, 0x06, 0x12, 0x04, 0xb3, 0x01, 0x0b, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, 0x02, - 0x00, 0x01, 0x12, 0x04, 0xb3, 0x01, 0x13, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, 0x02, 0x00, - 0x03, 0x12, 0x04, 0xb3, 0x01, 0x1e, 0x1f, 0x0a, 0x30, 0x0a, 0x02, 0x04, 0x0e, 0x12, 0x06, 0xb7, - 0x01, 0x00, 0xc6, 0x01, 0x01, 0x1a, 0x22, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0e, 0x01, - 0x12, 0x04, 0xb7, 0x01, 0x08, 0x1b, 0x0a, 0x23, 0x0a, 0x04, 0x04, 0x0e, 0x03, 0x00, 0x12, 0x06, - 0xb9, 0x01, 0x02, 0xc3, 0x01, 0x03, 0x1a, 0x13, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, - 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x0e, 0x03, 0x00, 0x01, 0x12, 0x04, 0xb9, 0x01, 0x0a, 0x12, 0x0a, 0x37, 0x0a, 0x06, 0x04, 0x0e, - 0x03, 0x00, 0x03, 0x00, 0x12, 0x06, 0xbb, 0x01, 0x04, 0xbd, 0x01, 0x05, 0x1a, 0x25, 0x20, 0x57, - 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x03, 0x00, 0x01, 0x12, 0x04, - 0xbb, 0x01, 0x0c, 0x13, 0x0a, 0x10, 0x0a, 0x08, 0x04, 0x0e, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, - 0x12, 0x04, 0xbc, 0x01, 0x06, 0x43, 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x0e, 0x03, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x06, 0x12, 0x04, 0xbc, 0x01, 0x06, 0x31, 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x0e, 0x03, - 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xbc, 0x01, 0x32, 0x3e, 0x0a, 0x11, 0x0a, 0x09, - 0x04, 0x0e, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0xbc, 0x01, 0x41, 0x42, 0x0a, - 0x10, 0x0a, 0x06, 0x04, 0x0e, 0x03, 0x00, 0x08, 0x00, 0x12, 0x06, 0xbf, 0x01, 0x04, 0xc2, 0x01, - 0x05, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x08, 0x00, 0x01, 0x12, 0x04, 0xbf, 0x01, - 0x0a, 0x12, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0xc0, 0x01, - 0x06, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x04, 0xc0, - 0x01, 0x06, 0x0d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, - 0xc0, 0x01, 0x0e, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, - 0x04, 0xc0, 0x01, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x01, 0x12, - 0x04, 0xc1, 0x01, 0x06, 0x1e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x01, 0x06, - 0x12, 0x04, 0xc1, 0x01, 0x06, 0x13, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x01, - 0x01, 0x12, 0x04, 0xc1, 0x01, 0x14, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, - 0x01, 0x03, 0x12, 0x04, 0xc1, 0x01, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0e, 0x02, 0x00, - 0x12, 0x04, 0xc5, 0x01, 0x02, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x04, 0x12, - 0x04, 0xc5, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x06, 0x12, 0x04, - 0xc5, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x01, 0x12, 0x04, 0xc5, - 0x01, 0x14, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x03, 0x12, 0x04, 0xc5, 0x01, - 0x20, 0x21, 0x0a, 0x57, 0x0a, 0x02, 0x04, 0x0f, 0x12, 0x06, 0xc9, 0x01, 0x00, 0xcb, 0x01, 0x01, - 0x1a, 0x49, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, - 0x75, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x58, 0x4d, 0x54, 0x50, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, - 0x0f, 0x01, 0x12, 0x04, 0xc9, 0x01, 0x08, 0x1e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0f, 0x02, 0x00, - 0x12, 0x04, 0xca, 0x01, 0x02, 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x04, 0x12, - 0x04, 0xca, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x05, 0x12, 0x04, - 0xca, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x01, 0x12, 0x04, 0xca, - 0x01, 0x12, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x03, 0x12, 0x04, 0xca, 0x01, - 0x21, 0x22, 0x0a, 0x70, 0x0a, 0x02, 0x04, 0x10, 0x12, 0x06, 0xcf, 0x01, 0x00, 0xd1, 0x01, 0x01, - 0x1a, 0x62, 0x20, 0x53, 0x61, 0x76, 0x65, 0x56, 0x31, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, - 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, - 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x62, - 0x75, 0x69, 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, - 0x6e, 0x63, 0x65, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x10, 0x01, 0x12, 0x04, 0xcf, 0x01, 0x08, - 0x22, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x10, 0x02, 0x00, 0x12, 0x04, 0xd0, 0x01, 0x02, 0x49, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x10, 0x02, 0x00, 0x04, 0x12, 0x04, 0xd0, 0x01, 0x02, 0x0a, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x10, 0x02, 0x00, 0x06, 0x12, 0x04, 0xd0, 0x01, 0x0b, 0x36, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x10, 0x02, 0x00, 0x01, 0x12, 0x04, 0xd0, 0x01, 0x37, 0x44, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x10, 0x02, 0x00, 0x03, 0x12, 0x04, 0xd0, 0x01, 0x47, 0x48, 0x0a, 0x3f, 0x0a, 0x02, 0x04, - 0x11, 0x12, 0x04, 0xd4, 0x01, 0x00, 0x26, 0x1a, 0x33, 0x20, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, - 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, - 0x79, 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x61, 0x76, 0x65, 0x56, 0x31, 0x43, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, - 0x04, 0x11, 0x01, 0x12, 0x04, 0xd4, 0x01, 0x08, 0x23, 0x0a, 0x2f, 0x0a, 0x02, 0x04, 0x12, 0x12, - 0x06, 0xd7, 0x01, 0x00, 0xd9, 0x01, 0x01, 0x1a, 0x21, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x65, 0x74, 0x56, 0x32, 0x43, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x12, - 0x01, 0x12, 0x04, 0xd7, 0x01, 0x08, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x12, 0x02, 0x00, 0x12, - 0x04, 0xd8, 0x01, 0x02, 0x49, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x12, 0x02, 0x00, 0x04, 0x12, 0x04, - 0xd8, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x12, 0x02, 0x00, 0x06, 0x12, 0x04, 0xd8, - 0x01, 0x0b, 0x36, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x12, 0x02, 0x00, 0x01, 0x12, 0x04, 0xd8, 0x01, - 0x37, 0x44, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x12, 0x02, 0x00, 0x03, 0x12, 0x04, 0xd8, 0x01, 0x47, - 0x48, 0x0a, 0x93, 0x01, 0x0a, 0x02, 0x04, 0x13, 0x12, 0x06, 0xdd, 0x01, 0x00, 0xdf, 0x01, 0x01, - 0x1a, 0x84, 0x01, 0x20, 0x55, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x75, 0x70, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x0a, 0x20, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x4f, 0x6e, - 0x6c, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x4d, 0x4d, 0x20, 0x53, - 0x6e, 0x61, 0x70, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x13, 0x01, 0x12, 0x04, - 0xdd, 0x01, 0x08, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x13, 0x02, 0x00, 0x12, 0x04, 0xde, 0x01, - 0x02, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x13, 0x02, 0x00, 0x05, 0x12, 0x04, 0xde, 0x01, 0x02, - 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x13, 0x02, 0x00, 0x01, 0x12, 0x04, 0xde, 0x01, 0x09, 0x17, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x13, 0x02, 0x00, 0x03, 0x12, 0x04, 0xde, 0x01, 0x1a, 0x1b, 0x0a, - 0x34, 0x0a, 0x02, 0x04, 0x14, 0x12, 0x06, 0xe2, 0x01, 0x00, 0xeb, 0x01, 0x01, 0x1a, 0x26, 0x20, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x47, 0x65, 0x74, 0x4b, - 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x14, 0x01, 0x12, 0x04, 0xe2, 0x01, - 0x08, 0x21, 0x0a, 0x49, 0x0a, 0x04, 0x04, 0x14, 0x04, 0x00, 0x12, 0x06, 0xe4, 0x01, 0x02, 0xe8, - 0x01, 0x03, 0x1a, 0x39, 0x20, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x14, 0x04, 0x00, 0x01, 0x12, 0x04, 0xe4, 0x01, 0x07, 0x15, 0x0a, 0x0e, 0x0a, 0x06, - 0x04, 0x14, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0xe5, 0x01, 0x04, 0x24, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x14, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xe5, 0x01, 0x04, 0x1f, 0x0a, 0x0f, 0x0a, - 0x07, 0x04, 0x14, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0xe5, 0x01, 0x22, 0x23, 0x0a, 0x0e, - 0x0a, 0x06, 0x04, 0x14, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, 0xe6, 0x01, 0x04, 0x26, 0x0a, 0x0f, - 0x0a, 0x07, 0x04, 0x14, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xe6, 0x01, 0x04, 0x21, 0x0a, - 0x0f, 0x0a, 0x07, 0x04, 0x14, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0xe6, 0x01, 0x24, 0x25, - 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x14, 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0xe7, 0x01, 0x04, 0x24, - 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x14, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xe7, 0x01, 0x04, - 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x14, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0xe7, 0x01, - 0x22, 0x23, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x14, 0x02, 0x00, 0x12, 0x04, 0xea, 0x01, 0x02, 0x1c, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x14, 0x02, 0x00, 0x06, 0x12, 0x04, 0xea, 0x01, 0x02, 0x10, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x14, 0x02, 0x00, 0x01, 0x12, 0x04, 0xea, 0x01, 0x11, 0x17, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x14, 0x02, 0x00, 0x03, 0x12, 0x04, 0xea, 0x01, 0x1a, 0x1b, 0x0a, 0x64, 0x0a, - 0x02, 0x04, 0x15, 0x12, 0x06, 0xef, 0x01, 0x00, 0xf3, 0x01, 0x01, 0x1a, 0x56, 0x20, 0x55, 0x73, - 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x20, 0x61, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, - 0x20, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, - 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x15, 0x01, 0x12, 0x04, 0xef, 0x01, 0x08, 0x1b, - 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x15, 0x08, 0x00, 0x12, 0x06, 0xf0, 0x01, 0x02, 0xf2, 0x01, 0x03, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x15, 0x08, 0x00, 0x01, 0x12, 0x04, 0xf0, 0x01, 0x08, 0x0e, 0x0a, - 0x0c, 0x0a, 0x04, 0x04, 0x15, 0x02, 0x00, 0x12, 0x04, 0xf1, 0x01, 0x04, 0x34, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x15, 0x02, 0x00, 0x06, 0x12, 0x04, 0xf1, 0x01, 0x04, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x15, 0x02, 0x00, 0x01, 0x12, 0x04, 0xf1, 0x01, 0x2d, 0x2f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x15, 0x02, 0x00, 0x03, 0x12, 0x04, 0xf1, 0x01, 0x32, 0x33, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x16, - 0x12, 0x06, 0xf6, 0x01, 0x00, 0xf8, 0x01, 0x01, 0x1a, 0x34, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x0a, 0x0a, 0x0b, - 0x0a, 0x03, 0x04, 0x16, 0x01, 0x12, 0x04, 0xf6, 0x01, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, - 0x16, 0x02, 0x00, 0x12, 0x04, 0xf7, 0x01, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x16, 0x02, - 0x00, 0x06, 0x12, 0x04, 0xf7, 0x01, 0x02, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x16, 0x02, 0x00, - 0x01, 0x12, 0x04, 0xf7, 0x01, 0x10, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x16, 0x02, 0x00, 0x03, - 0x12, 0x04, 0xf7, 0x01, 0x18, 0x19, 0x0a, 0x64, 0x0a, 0x02, 0x04, 0x17, 0x12, 0x06, 0xfc, 0x01, - 0x00, 0x82, 0x02, 0x01, 0x1a, 0x56, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x44, 0x69, 0x67, 0x65, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, - 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, - 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x0a, 0x20, - 0x6f, 0x72, 0x20, 0x61, 0x20, 0x70, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, - 0x04, 0x17, 0x01, 0x12, 0x04, 0xfc, 0x01, 0x08, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, - 0x00, 0x12, 0x04, 0xfd, 0x01, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x05, - 0x12, 0x04, 0xfd, 0x01, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x01, 0x12, - 0x04, 0xfd, 0x01, 0x08, 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x03, 0x12, 0x04, - 0xfd, 0x01, 0x11, 0x12, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x17, 0x08, 0x00, 0x12, 0x06, 0xfe, 0x01, - 0x02, 0x81, 0x02, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x08, 0x00, 0x01, 0x12, 0x04, 0xfe, - 0x01, 0x08, 0x0e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x01, 0x12, 0x04, 0xff, 0x01, 0x04, - 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x05, 0x12, 0x04, 0xff, 0x01, 0x04, 0x08, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x01, 0x12, 0x04, 0xff, 0x01, 0x09, 0x15, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x03, 0x12, 0x04, 0xff, 0x01, 0x18, 0x19, 0x0a, 0x0c, - 0x0a, 0x04, 0x04, 0x17, 0x02, 0x02, 0x12, 0x04, 0x80, 0x02, 0x04, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x17, 0x02, 0x02, 0x05, 0x12, 0x04, 0x80, 0x02, 0x04, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x17, 0x02, 0x02, 0x01, 0x12, 0x04, 0x80, 0x02, 0x0b, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, - 0x02, 0x02, 0x03, 0x12, 0x04, 0x80, 0x02, 0x1a, 0x1b, 0x0a, 0x58, 0x0a, 0x02, 0x05, 0x01, 0x12, - 0x06, 0x85, 0x02, 0x00, 0x8a, 0x02, 0x01, 0x1a, 0x4a, 0x20, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, - 0x65, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x65, - 0x63, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, - 0x20, 0x6a, 0x6f, 0x62, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, - 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, - 0x6f, 0x6e, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x05, 0x01, 0x01, 0x12, 0x04, 0x85, 0x02, 0x05, 0x0c, - 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x00, 0x12, 0x04, 0x86, 0x02, 0x02, 0x1b, 0x0a, 0x0d, - 0x0a, 0x05, 0x05, 0x01, 0x02, 0x00, 0x01, 0x12, 0x04, 0x86, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, - 0x05, 0x05, 0x01, 0x02, 0x00, 0x02, 0x12, 0x04, 0x86, 0x02, 0x19, 0x1a, 0x0a, 0x0c, 0x0a, 0x04, - 0x05, 0x01, 0x02, 0x01, 0x12, 0x04, 0x87, 0x02, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, - 0x02, 0x01, 0x01, 0x12, 0x04, 0x87, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, - 0x01, 0x02, 0x12, 0x04, 0x87, 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x02, - 0x12, 0x04, 0x88, 0x02, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x02, 0x01, 0x12, - 0x04, 0x88, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x02, 0x02, 0x12, 0x04, - 0x88, 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x03, 0x12, 0x04, 0x89, 0x02, - 0x02, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x03, 0x01, 0x12, 0x04, 0x89, 0x02, 0x02, - 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x03, 0x02, 0x12, 0x04, 0x89, 0x02, 0x1a, 0x1b, - 0x0a, 0x56, 0x0a, 0x02, 0x04, 0x18, 0x12, 0x06, 0x8d, 0x02, 0x00, 0x8f, 0x02, 0x01, 0x1a, 0x48, - 0x20, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, - 0x20, 0x67, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x72, 0x75, - 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x72, 0x65, 0x66, 0x72, - 0x65, 0x73, 0x68, 0x20, 0x6a, 0x6f, 0x62, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x18, 0x01, 0x12, - 0x04, 0x8d, 0x02, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, 0x00, 0x12, 0x04, 0x8e, - 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x06, 0x12, 0x04, 0x8e, 0x02, - 0x02, 0x09, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8e, 0x02, 0x0a, - 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x03, 0x12, 0x04, 0x8e, 0x02, 0x15, 0x16, - 0x0a, 0x5a, 0x0a, 0x02, 0x04, 0x19, 0x12, 0x06, 0x92, 0x02, 0x00, 0x94, 0x02, 0x01, 0x1a, 0x4c, - 0x20, 0x47, 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, - 0x6f, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, - 0x74, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, - 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x20, 0x6a, 0x6f, 0x62, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, - 0x04, 0x19, 0x01, 0x12, 0x04, 0x92, 0x02, 0x08, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x19, 0x02, - 0x00, 0x12, 0x04, 0x93, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x05, - 0x12, 0x04, 0x93, 0x02, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x01, 0x12, - 0x04, 0x93, 0x02, 0x08, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x03, 0x12, 0x04, - 0x93, 0x02, 0x16, 0x17, 0x0a, 0x56, 0x0a, 0x02, 0x04, 0x1a, 0x12, 0x06, 0x97, 0x02, 0x00, 0x9a, - 0x02, 0x01, 0x1a, 0x48, 0x20, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, - 0x74, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, - 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x20, 0x6a, 0x6f, 0x62, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, - 0x04, 0x1a, 0x01, 0x12, 0x04, 0x97, 0x02, 0x08, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1a, 0x02, - 0x00, 0x12, 0x04, 0x98, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x06, - 0x12, 0x04, 0x98, 0x02, 0x02, 0x09, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x01, 0x12, - 0x04, 0x98, 0x02, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x03, 0x12, 0x04, - 0x98, 0x02, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1a, 0x02, 0x01, 0x12, 0x04, 0x99, 0x02, - 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x05, 0x12, 0x04, 0x99, 0x02, 0x02, - 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x01, 0x12, 0x04, 0x99, 0x02, 0x08, 0x13, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x03, 0x12, 0x04, 0x99, 0x02, 0x16, 0x17, 0x0a, - 0x3d, 0x0a, 0x02, 0x04, 0x1b, 0x12, 0x04, 0x9d, 0x02, 0x00, 0x20, 0x1a, 0x31, 0x20, 0x53, 0x65, - 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0b, - 0x0a, 0x03, 0x04, 0x1b, 0x01, 0x12, 0x04, 0x9d, 0x02, 0x08, 0x1d, 0x0a, 0x42, 0x0a, 0x02, 0x04, - 0x1c, 0x12, 0x06, 0xa0, 0x02, 0x00, 0xa8, 0x02, 0x01, 0x1a, 0x34, 0x20, 0x41, 0x20, 0x6d, 0x61, - 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x65, 0x64, 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, - 0x0b, 0x0a, 0x03, 0x04, 0x1c, 0x01, 0x12, 0x04, 0xa0, 0x02, 0x08, 0x10, 0x0a, 0x51, 0x0a, 0x04, - 0x04, 0x1c, 0x03, 0x00, 0x12, 0x06, 0xa2, 0x02, 0x02, 0xa6, 0x02, 0x03, 0x1a, 0x41, 0x20, 0x54, - 0x6f, 0x70, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x20, 0x77, 0x72, 0x61, 0x70, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, - 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, - 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x0a, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x03, 0x00, 0x01, 0x12, 0x04, 0xa2, 0x02, 0x0a, 0x13, 0x0a, 0x0e, - 0x0a, 0x06, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0xa3, 0x02, 0x04, 0x1a, 0x0a, 0x0f, - 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0xa3, 0x02, 0x04, 0x0a, 0x0a, - 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xa3, 0x02, 0x0b, 0x15, - 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0xa3, 0x02, 0x18, - 0x19, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0xa4, 0x02, 0x04, - 0x1c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x04, 0xa4, 0x02, - 0x04, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xa4, - 0x02, 0x0b, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, - 0xa4, 0x02, 0x1a, 0x1b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x02, 0x12, 0x04, - 0xa5, 0x02, 0x04, 0x36, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x02, 0x06, 0x12, - 0x04, 0xa5, 0x02, 0x04, 0x26, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x02, 0x01, - 0x12, 0x04, 0xa5, 0x02, 0x27, 0x31, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x02, - 0x03, 0x12, 0x04, 0xa5, 0x02, 0x34, 0x35, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1c, 0x02, 0x00, 0x12, - 0x04, 0xa7, 0x02, 0x02, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x06, 0x12, 0x04, - 0xa7, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x01, 0x12, 0x04, 0xa7, - 0x02, 0x19, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x03, 0x12, 0x04, 0xa7, 0x02, - 0x22, 0x23, 0x0a, 0x4f, 0x0a, 0x02, 0x04, 0x1d, 0x12, 0x06, 0xab, 0x02, 0x00, 0xad, 0x02, 0x01, - 0x1a, 0x41, 0x20, 0x55, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x61, - 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x76, - 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6b, 0x65, - 0x79, 0x73, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1d, 0x01, 0x12, 0x04, 0xab, 0x02, 0x08, 0x26, - 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1d, 0x02, 0x00, 0x12, 0x04, 0xac, 0x02, 0x02, 0x1d, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x1d, 0x02, 0x00, 0x04, 0x12, 0x04, 0xac, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x1d, 0x02, 0x00, 0x05, 0x12, 0x04, 0xac, 0x02, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x1d, 0x02, 0x00, 0x01, 0x12, 0x04, 0xac, 0x02, 0x12, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x1d, 0x02, 0x00, 0x03, 0x12, 0x04, 0xac, 0x02, 0x1b, 0x1c, 0x0a, 0x36, 0x0a, 0x02, 0x04, 0x1e, - 0x12, 0x06, 0xb0, 0x02, 0x00, 0xbb, 0x02, 0x01, 0x1a, 0x28, 0x20, 0x41, 0x20, 0x6d, 0x61, 0x70, - 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x20, 0x74, - 0x6f, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6b, 0x65, 0x79, - 0x73, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1e, 0x01, 0x12, 0x04, 0xb0, 0x02, 0x08, 0x27, 0x0a, - 0x5d, 0x0a, 0x04, 0x04, 0x1e, 0x03, 0x00, 0x12, 0x06, 0xb2, 0x02, 0x02, 0xb5, 0x02, 0x03, 0x1a, - 0x4d, 0x20, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x20, 0x77, 0x72, - 0x61, 0x70, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6b, 0x65, 0x79, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, - 0x6f, 0x66, 0x20, 0x33, 0x30, 0x20, 0x64, 0x61, 0x79, 0x20, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, - 0x73, 0x20, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x0a, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x1e, 0x03, 0x00, 0x01, 0x12, 0x04, 0xb2, 0x02, 0x0a, 0x15, 0x0a, 0x0e, 0x0a, - 0x06, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0xb3, 0x02, 0x04, 0x2d, 0x0a, 0x0f, 0x0a, - 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0xb3, 0x02, 0x04, 0x09, 0x0a, 0x0f, - 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xb3, 0x02, 0x0a, 0x28, 0x0a, - 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0xb3, 0x02, 0x2b, 0x2c, - 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0xb4, 0x02, 0x04, 0x17, - 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x04, 0xb4, 0x02, 0x04, - 0x09, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xb4, 0x02, - 0x0a, 0x12, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0xb4, - 0x02, 0x15, 0x16, 0x0a, 0x42, 0x0a, 0x04, 0x04, 0x1e, 0x03, 0x01, 0x12, 0x06, 0xb7, 0x02, 0x02, - 0xb9, 0x02, 0x03, 0x1a, 0x32, 0x20, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x20, 0x72, - 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, - 0x6c, 0x65, 0x20, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x20, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x03, 0x01, 0x01, - 0x12, 0x04, 0xb7, 0x02, 0x0a, 0x12, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1e, 0x03, 0x01, 0x02, 0x00, - 0x12, 0x04, 0xb8, 0x02, 0x04, 0x24, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x01, 0x02, 0x00, - 0x04, 0x12, 0x04, 0xb8, 0x02, 0x04, 0x0c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x01, 0x02, - 0x00, 0x06, 0x12, 0x04, 0xb8, 0x02, 0x0d, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x01, - 0x02, 0x00, 0x01, 0x12, 0x04, 0xb8, 0x02, 0x19, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, - 0x01, 0x02, 0x00, 0x03, 0x12, 0x04, 0xb8, 0x02, 0x22, 0x23, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1e, - 0x02, 0x00, 0x12, 0x04, 0xba, 0x02, 0x02, 0x26, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, - 0x06, 0x12, 0x04, 0xba, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, 0x01, - 0x12, 0x04, 0xba, 0x02, 0x18, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, 0x03, 0x12, - 0x04, 0xba, 0x02, 0x24, 0x25, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x01, 0x01, 0x12, 0x03, 0x1d, 0x08, 0x18, 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x01, 0x03, 0x00, 0x12, + 0x04, 0x1f, 0x02, 0x24, 0x03, 0x1a, 0x1d, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, + 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x03, 0x00, 0x01, 0x12, 0x03, 0x1f, + 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x20, 0x04, + 0x31, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x20, 0x04, + 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x20, 0x25, + 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x20, 0x2f, + 0x30, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x21, 0x04, 0x38, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x21, 0x04, 0x29, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x21, 0x2a, 0x33, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x21, 0x36, 0x37, + 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x22, 0x04, 0x1b, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x22, 0x04, 0x09, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x22, 0x0a, 0x16, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x22, 0x19, 0x1a, 0x0a, + 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x12, 0x03, 0x23, 0x04, 0x17, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x23, 0x04, 0x08, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x23, 0x09, 0x12, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x23, 0x15, 0x16, 0x0a, 0x0b, + 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x26, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x26, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x00, 0x06, 0x12, 0x03, 0x26, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, + 0x12, 0x03, 0x26, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x26, 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x2a, 0x00, 0x39, 0x01, 0x1a, + 0x36, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x56, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x56, 0x32, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, + 0x2a, 0x08, 0x17, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x2c, 0x02, 0x36, + 0x03, 0x1a, 0x1e, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x00, 0x01, 0x12, 0x03, 0x2c, 0x0a, 0x12, 0x0a, + 0x35, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x03, 0x00, 0x12, 0x04, 0x2e, 0x04, 0x30, 0x05, 0x1a, + 0x25, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x03, 0x00, + 0x01, 0x12, 0x03, 0x2e, 0x0c, 0x13, 0x0a, 0x0f, 0x0a, 0x08, 0x04, 0x02, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x12, 0x03, 0x2f, 0x06, 0x1a, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x02, 0x03, 0x00, 0x03, + 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2f, 0x06, 0x0b, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x02, 0x03, + 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2f, 0x0c, 0x15, 0x0a, 0x10, 0x0a, 0x09, 0x04, + 0x02, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2f, 0x18, 0x19, 0x0a, 0x0e, 0x0a, + 0x06, 0x04, 0x02, 0x03, 0x00, 0x08, 0x00, 0x12, 0x04, 0x32, 0x04, 0x35, 0x05, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x02, 0x03, 0x00, 0x08, 0x00, 0x01, 0x12, 0x03, 0x32, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, + 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x33, 0x06, 0x19, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x33, 0x06, 0x0d, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x33, 0x0e, 0x14, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x33, 0x17, 0x18, 0x0a, 0x0d, 0x0a, 0x06, + 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x34, 0x06, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x34, 0x06, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x34, 0x14, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x34, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x02, 0x02, 0x00, 0x12, 0x03, 0x38, 0x02, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, + 0x04, 0x12, 0x03, 0x38, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, + 0x03, 0x38, 0x0b, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x38, + 0x14, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x38, 0x20, 0x21, + 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x3c, 0x00, 0x45, 0x01, 0x1a, 0x3e, 0x20, 0x44, + 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, + 0x66, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x70, 0x72, 0x69, 0x61, 0x74, 0x65, + 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, + 0x04, 0x03, 0x01, 0x12, 0x03, 0x3c, 0x08, 0x18, 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x03, 0x03, 0x00, + 0x12, 0x04, 0x3e, 0x02, 0x42, 0x03, 0x1a, 0x1d, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x03, 0x00, 0x01, 0x12, 0x03, + 0x3e, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x3f, + 0x04, 0x31, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x3f, + 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x3f, + 0x25, 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3f, + 0x2f, 0x30, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x40, 0x04, + 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x40, 0x04, + 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x40, 0x0a, + 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x40, 0x19, + 0x1a, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x41, 0x04, 0x1d, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x41, 0x04, 0x0a, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x41, 0x0b, 0x18, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x41, 0x1b, 0x1c, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x44, 0x02, 0x20, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x03, 0x02, 0x00, 0x04, 0x12, 0x03, 0x44, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x03, 0x02, 0x00, 0x06, 0x12, 0x03, 0x44, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x44, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, + 0x12, 0x03, 0x44, 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x48, 0x00, 0x51, + 0x01, 0x1a, 0x36, 0x20, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x61, 0x20, 0x62, 0x61, + 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, + 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x58, 0x33, 0x44, 0x48, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x61, + 0x67, 0x72, 0x65, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, + 0x12, 0x03, 0x48, 0x08, 0x18, 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x04, 0x03, 0x00, 0x12, 0x04, 0x4a, + 0x02, 0x4e, 0x03, 0x1a, 0x1d, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x65, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x03, 0x00, 0x01, 0x12, 0x03, 0x4a, 0x0a, 0x11, + 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x4b, 0x04, 0x38, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x4b, 0x04, 0x29, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x4b, 0x2a, 0x33, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x4b, 0x36, 0x37, 0x0a, + 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x4c, 0x04, 0x16, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x4c, 0x04, 0x09, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x4c, 0x0a, 0x11, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x4c, 0x14, 0x15, 0x0a, 0x0d, + 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x4d, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x4d, 0x04, 0x09, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x4d, 0x0a, 0x16, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x4d, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, + 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x50, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, + 0x02, 0x00, 0x04, 0x12, 0x03, 0x50, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, + 0x06, 0x12, 0x03, 0x50, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x50, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x50, + 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x54, 0x00, 0x64, 0x01, 0x1a, 0x36, + 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x56, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x56, + 0x32, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, 0x54, + 0x08, 0x17, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x05, 0x03, 0x00, 0x12, 0x04, 0x56, 0x02, 0x61, 0x03, + 0x1a, 0x1e, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x03, 0x00, 0x01, 0x12, 0x03, 0x56, 0x0a, 0x12, 0x0a, 0x35, + 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x12, 0x04, 0x58, 0x04, 0x5b, 0x05, 0x1a, 0x25, + 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x01, + 0x12, 0x03, 0x58, 0x0c, 0x13, 0x0a, 0x0f, 0x0a, 0x08, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, + 0x00, 0x12, 0x03, 0x59, 0x06, 0x35, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x06, 0x12, 0x03, 0x59, 0x06, 0x26, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x05, 0x03, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x59, 0x27, 0x30, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x05, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x59, 0x33, 0x34, 0x0a, 0x0f, 0x0a, 0x08, + 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x5a, 0x06, 0x1c, 0x0a, 0x10, 0x0a, + 0x09, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x5a, 0x06, 0x0b, 0x0a, + 0x10, 0x0a, 0x09, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x5a, 0x0c, + 0x17, 0x0a, 0x10, 0x0a, 0x09, 0x04, 0x05, 0x03, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, + 0x5a, 0x1a, 0x1b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x08, 0x00, 0x12, 0x04, 0x5d, + 0x04, 0x60, 0x05, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x08, 0x00, 0x01, 0x12, 0x03, + 0x5d, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x5e, + 0x06, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x5e, + 0x06, 0x0d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x5e, + 0x0e, 0x14, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x5e, + 0x17, 0x18, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x5f, 0x06, + 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x5f, 0x06, + 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x5f, 0x14, + 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x5f, 0x1c, + 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x63, 0x02, 0x22, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x04, 0x12, 0x03, 0x63, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x05, 0x02, 0x00, 0x06, 0x12, 0x03, 0x63, 0x0b, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x63, 0x14, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x63, 0x20, 0x21, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x06, 0x12, 0x04, 0x67, 0x00, + 0x70, 0x01, 0x1a, 0x3e, 0x20, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x61, 0x20, 0x62, + 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x72, 0x6f, + 0x70, 0x72, 0x69, 0x61, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, + 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x67, 0x08, 0x18, 0x0a, 0x2b, + 0x0a, 0x04, 0x04, 0x06, 0x03, 0x00, 0x12, 0x04, 0x69, 0x02, 0x6d, 0x03, 0x1a, 0x1d, 0x20, 0x41, + 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x06, 0x03, 0x00, 0x01, 0x12, 0x03, 0x69, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, + 0x00, 0x02, 0x00, 0x12, 0x03, 0x6a, 0x04, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, + 0x02, 0x00, 0x05, 0x12, 0x03, 0x6a, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x6a, 0x0a, 0x11, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x6a, 0x14, 0x15, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, 0x00, + 0x02, 0x01, 0x12, 0x03, 0x6b, 0x04, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, + 0x01, 0x05, 0x12, 0x03, 0x6b, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, + 0x01, 0x01, 0x12, 0x03, 0x6b, 0x0a, 0x16, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, + 0x01, 0x03, 0x12, 0x03, 0x6b, 0x19, 0x1a, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x06, 0x03, 0x00, 0x02, + 0x02, 0x12, 0x03, 0x6c, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x02, + 0x05, 0x12, 0x03, 0x6c, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x02, + 0x01, 0x12, 0x03, 0x6c, 0x0b, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x06, 0x03, 0x00, 0x02, 0x02, + 0x03, 0x12, 0x03, 0x6c, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x00, 0x12, 0x03, + 0x6f, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x04, 0x12, 0x03, 0x6f, 0x02, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x06, 0x12, 0x03, 0x6f, 0x0b, 0x12, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, 0x03, 0x6f, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x6f, 0x1e, 0x1f, 0x0a, 0x2c, 0x0a, 0x02, 0x04, + 0x07, 0x12, 0x04, 0x73, 0x00, 0x7a, 0x01, 0x1a, 0x20, 0x20, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x79, 0x6f, 0x75, 0x72, 0x73, 0x65, 0x6c, 0x66, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x07, 0x01, + 0x12, 0x03, 0x73, 0x08, 0x1a, 0x0a, 0x1c, 0x0a, 0x04, 0x04, 0x07, 0x03, 0x00, 0x12, 0x04, 0x75, + 0x02, 0x77, 0x03, 0x1a, 0x0e, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x79, + 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x03, 0x00, 0x01, 0x12, 0x03, 0x75, 0x0a, + 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x76, 0x04, 0x16, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x76, 0x04, 0x09, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x76, 0x0a, 0x11, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x76, 0x14, 0x15, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x00, 0x12, 0x03, 0x79, 0x02, 0x20, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x07, 0x02, 0x00, 0x04, 0x12, 0x03, 0x79, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x07, 0x02, 0x00, 0x06, 0x12, 0x03, 0x79, 0x0b, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x79, 0x13, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x03, + 0x12, 0x03, 0x79, 0x1e, 0x1f, 0x0a, 0x33, 0x0a, 0x02, 0x04, 0x08, 0x12, 0x05, 0x7d, 0x00, 0x8c, + 0x01, 0x01, 0x1a, 0x26, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x65, 0x6c, 0x66, 0x45, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x08, + 0x01, 0x12, 0x03, 0x7d, 0x08, 0x1b, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x08, 0x03, 0x00, 0x12, 0x05, + 0x7f, 0x02, 0x89, 0x01, 0x03, 0x1a, 0x0f, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x03, 0x00, 0x01, 0x12, + 0x03, 0x7f, 0x0a, 0x12, 0x0a, 0x24, 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x12, 0x06, + 0x81, 0x01, 0x04, 0x83, 0x01, 0x05, 0x1a, 0x12, 0x20, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, + 0x03, 0x00, 0x03, 0x00, 0x01, 0x12, 0x04, 0x81, 0x01, 0x0c, 0x13, 0x0a, 0x10, 0x0a, 0x08, 0x04, + 0x08, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0x82, 0x01, 0x06, 0x1a, 0x0a, 0x11, 0x0a, + 0x09, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0x82, 0x01, 0x06, 0x0b, + 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x82, + 0x01, 0x0c, 0x15, 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x08, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, + 0x12, 0x04, 0x82, 0x01, 0x18, 0x19, 0x0a, 0x10, 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, 0x08, 0x00, + 0x12, 0x06, 0x85, 0x01, 0x04, 0x88, 0x01, 0x05, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, + 0x08, 0x00, 0x01, 0x12, 0x04, 0x85, 0x01, 0x0a, 0x12, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x08, 0x03, + 0x00, 0x02, 0x00, 0x12, 0x04, 0x86, 0x01, 0x06, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, + 0x00, 0x02, 0x00, 0x06, 0x12, 0x04, 0x86, 0x01, 0x06, 0x0d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, + 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x86, 0x01, 0x0e, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, + 0x08, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0x86, 0x01, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, + 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0x87, 0x01, 0x06, 0x1e, 0x0a, 0x0f, 0x0a, 0x07, + 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x04, 0x87, 0x01, 0x06, 0x13, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x87, 0x01, 0x14, 0x19, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0x87, 0x01, 0x1c, 0x1d, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x00, 0x12, 0x04, 0x8b, 0x01, 0x02, 0x22, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x08, 0x02, 0x00, 0x04, 0x12, 0x04, 0x8b, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x08, 0x02, 0x00, 0x06, 0x12, 0x04, 0x8b, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x08, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8b, 0x01, 0x14, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, + 0x02, 0x00, 0x03, 0x12, 0x04, 0x8b, 0x01, 0x20, 0x21, 0x0a, 0x22, 0x0a, 0x02, 0x04, 0x09, 0x12, + 0x06, 0x8f, 0x01, 0x00, 0x96, 0x01, 0x01, 0x1a, 0x14, 0x20, 0x53, 0x65, 0x6c, 0x66, 0x44, 0x65, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, + 0x03, 0x04, 0x09, 0x01, 0x12, 0x04, 0x8f, 0x01, 0x08, 0x1a, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x09, + 0x03, 0x00, 0x12, 0x06, 0x91, 0x01, 0x02, 0x93, 0x01, 0x03, 0x1a, 0x0e, 0x20, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, + 0x03, 0x00, 0x01, 0x12, 0x04, 0x91, 0x01, 0x0a, 0x11, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x09, 0x03, + 0x00, 0x02, 0x00, 0x12, 0x04, 0x92, 0x01, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, + 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0x92, 0x01, 0x04, 0x09, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, + 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x92, 0x01, 0x0a, 0x11, 0x0a, 0x0f, 0x0a, 0x07, 0x04, + 0x09, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0x92, 0x01, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x09, 0x02, 0x00, 0x12, 0x04, 0x95, 0x01, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, + 0x02, 0x00, 0x04, 0x12, 0x04, 0x95, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, + 0x00, 0x06, 0x12, 0x04, 0x95, 0x01, 0x0b, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, + 0x01, 0x12, 0x04, 0x95, 0x01, 0x13, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x03, + 0x12, 0x04, 0x95, 0x01, 0x1e, 0x1f, 0x0a, 0x3c, 0x0a, 0x02, 0x04, 0x0a, 0x12, 0x06, 0x99, 0x01, + 0x00, 0x9b, 0x01, 0x01, 0x1a, 0x2e, 0x20, 0x47, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x73, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, + 0x69, 0x65, 0x72, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0a, 0x01, 0x12, 0x04, 0x99, 0x01, 0x08, + 0x34, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0a, 0x02, 0x00, 0x12, 0x04, 0x9a, 0x01, 0x02, 0x18, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x05, 0x12, 0x04, 0x9a, 0x01, 0x02, 0x08, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x01, 0x12, 0x04, 0x9a, 0x01, 0x09, 0x13, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x0a, 0x02, 0x00, 0x03, 0x12, 0x04, 0x9a, 0x01, 0x16, 0x17, 0x0a, 0x5d, 0x0a, 0x02, + 0x04, 0x0b, 0x12, 0x06, 0x9e, 0x01, 0x00, 0xa3, 0x01, 0x01, 0x1a, 0x4f, 0x20, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, + 0x6e, 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, + 0x0b, 0x01, 0x12, 0x04, 0x9e, 0x01, 0x08, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0b, 0x02, 0x00, + 0x12, 0x04, 0x9f, 0x01, 0x02, 0x39, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x06, 0x12, + 0x04, 0x9f, 0x01, 0x02, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x01, 0x12, 0x04, + 0x9f, 0x01, 0x2d, 0x34, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x03, 0x12, 0x04, 0x9f, + 0x01, 0x37, 0x38, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0b, 0x02, 0x01, 0x12, 0x04, 0xa0, 0x01, 0x02, + 0x3c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x06, 0x12, 0x04, 0xa0, 0x01, 0x02, 0x2d, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x01, 0x12, 0x04, 0xa0, 0x01, 0x2e, 0x37, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x03, 0x12, 0x04, 0xa0, 0x01, 0x3a, 0x3b, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x0b, 0x02, 0x02, 0x12, 0x04, 0xa1, 0x01, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x0b, 0x02, 0x02, 0x05, 0x12, 0x04, 0xa1, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x0b, 0x02, 0x02, 0x01, 0x12, 0x04, 0xa1, 0x01, 0x09, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, + 0x02, 0x02, 0x03, 0x12, 0x04, 0xa1, 0x01, 0x16, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0b, 0x02, + 0x03, 0x12, 0x04, 0xa2, 0x01, 0x02, 0x3e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x03, 0x06, + 0x12, 0x04, 0xa2, 0x01, 0x02, 0x2b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x03, 0x01, 0x12, + 0x04, 0xa2, 0x01, 0x2c, 0x39, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x03, 0x03, 0x12, 0x04, + 0xa2, 0x01, 0x3c, 0x3d, 0x0a, 0x31, 0x0a, 0x02, 0x04, 0x0c, 0x12, 0x06, 0xa6, 0x01, 0x00, 0xa9, + 0x01, 0x01, 0x1a, 0x23, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, + 0x20, 0x61, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0c, 0x01, 0x12, 0x04, + 0xa6, 0x01, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0c, 0x02, 0x00, 0x12, 0x04, 0xa7, 0x01, + 0x02, 0x3f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x06, 0x12, 0x04, 0xa7, 0x01, 0x02, + 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x01, 0x12, 0x04, 0xa7, 0x01, 0x2e, 0x3a, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x03, 0x12, 0x04, 0xa7, 0x01, 0x3d, 0x3e, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x0c, 0x02, 0x01, 0x12, 0x04, 0xa8, 0x01, 0x02, 0x14, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x0c, 0x02, 0x01, 0x05, 0x12, 0x04, 0xa8, 0x01, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x0c, 0x02, 0x01, 0x01, 0x12, 0x04, 0xa8, 0x01, 0x08, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x0c, 0x02, 0x01, 0x03, 0x12, 0x04, 0xa8, 0x01, 0x12, 0x13, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x0d, + 0x12, 0x06, 0xac, 0x01, 0x00, 0xb5, 0x01, 0x01, 0x1a, 0x3c, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, + 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x20, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0d, 0x01, 0x12, 0x04, 0xac, + 0x01, 0x08, 0x1a, 0x0a, 0x2e, 0x0a, 0x04, 0x04, 0x0d, 0x03, 0x00, 0x12, 0x06, 0xae, 0x01, 0x02, + 0xb2, 0x01, 0x03, 0x1a, 0x1e, 0x20, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, 0x03, 0x00, 0x01, 0x12, 0x04, 0xae, 0x01, + 0x0a, 0x11, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0xaf, 0x01, + 0x04, 0x1d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0xaf, + 0x01, 0x04, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, + 0xaf, 0x01, 0x0b, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, + 0x04, 0xaf, 0x01, 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x01, 0x12, + 0x04, 0xb0, 0x01, 0x04, 0x1c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x01, 0x05, + 0x12, 0x04, 0xb0, 0x01, 0x04, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, 0x01, + 0x01, 0x12, 0x04, 0xb0, 0x01, 0x0b, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, 0x02, + 0x01, 0x03, 0x12, 0x04, 0xb0, 0x01, 0x1a, 0x1b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0d, 0x03, 0x00, + 0x02, 0x02, 0x12, 0x04, 0xb1, 0x01, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, 0x00, + 0x02, 0x02, 0x05, 0x12, 0x04, 0xb1, 0x01, 0x04, 0x09, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, 0x03, + 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xb1, 0x01, 0x0a, 0x11, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0d, + 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x04, 0xb1, 0x01, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x0d, 0x02, 0x00, 0x12, 0x04, 0xb4, 0x01, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, 0x02, + 0x00, 0x04, 0x12, 0x04, 0xb4, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, 0x02, 0x00, + 0x06, 0x12, 0x04, 0xb4, 0x01, 0x0b, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, 0x02, 0x00, 0x01, + 0x12, 0x04, 0xb4, 0x01, 0x13, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0d, 0x02, 0x00, 0x03, 0x12, + 0x04, 0xb4, 0x01, 0x1e, 0x1f, 0x0a, 0x30, 0x0a, 0x02, 0x04, 0x0e, 0x12, 0x06, 0xb8, 0x01, 0x00, + 0xc7, 0x01, 0x01, 0x1a, 0x22, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, + 0x6f, 0x20, 0x61, 0x20, 0x53, 0x61, 0x76, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0e, 0x01, 0x12, 0x04, + 0xb8, 0x01, 0x08, 0x1b, 0x0a, 0x23, 0x0a, 0x04, 0x04, 0x0e, 0x03, 0x00, 0x12, 0x06, 0xba, 0x01, + 0x02, 0xc4, 0x01, 0x03, 0x1a, 0x13, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x03, + 0x00, 0x01, 0x12, 0x04, 0xba, 0x01, 0x0a, 0x12, 0x0a, 0x37, 0x0a, 0x06, 0x04, 0x0e, 0x03, 0x00, + 0x03, 0x00, 0x12, 0x06, 0xbc, 0x01, 0x04, 0xbe, 0x01, 0x05, 0x1a, 0x25, 0x20, 0x57, 0x72, 0x61, + 0x70, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x03, 0x00, 0x01, 0x12, 0x04, 0xbc, 0x01, + 0x0c, 0x13, 0x0a, 0x10, 0x0a, 0x08, 0x04, 0x0e, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, + 0xbd, 0x01, 0x06, 0x43, 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x0e, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x06, 0x12, 0x04, 0xbd, 0x01, 0x06, 0x31, 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x0e, 0x03, 0x00, 0x03, + 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xbd, 0x01, 0x32, 0x3e, 0x0a, 0x11, 0x0a, 0x09, 0x04, 0x0e, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0xbd, 0x01, 0x41, 0x42, 0x0a, 0x10, 0x0a, + 0x06, 0x04, 0x0e, 0x03, 0x00, 0x08, 0x00, 0x12, 0x06, 0xc0, 0x01, 0x04, 0xc3, 0x01, 0x05, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x08, 0x00, 0x01, 0x12, 0x04, 0xc0, 0x01, 0x0a, 0x12, + 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0xc1, 0x01, 0x06, 0x19, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x04, 0xc1, 0x01, 0x06, + 0x0d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xc1, 0x01, + 0x0e, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0xc1, + 0x01, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0xc2, + 0x01, 0x06, 0x1e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x04, + 0xc2, 0x01, 0x06, 0x13, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, + 0x04, 0xc2, 0x01, 0x14, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0e, 0x03, 0x00, 0x02, 0x01, 0x03, + 0x12, 0x04, 0xc2, 0x01, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0e, 0x02, 0x00, 0x12, 0x04, + 0xc6, 0x01, 0x02, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x04, 0x12, 0x04, 0xc6, + 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x06, 0x12, 0x04, 0xc6, 0x01, + 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x01, 0x12, 0x04, 0xc6, 0x01, 0x14, + 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x03, 0x12, 0x04, 0xc6, 0x01, 0x20, 0x21, + 0x0a, 0x57, 0x0a, 0x02, 0x04, 0x0f, 0x12, 0x06, 0xca, 0x01, 0x00, 0xcc, 0x01, 0x01, 0x1a, 0x49, + 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x75, 0x74, + 0x68, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x58, 0x4d, 0x54, 0x50, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x0f, 0x01, + 0x12, 0x04, 0xca, 0x01, 0x08, 0x1e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0f, 0x02, 0x00, 0x12, 0x04, + 0xcb, 0x01, 0x02, 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x04, 0x12, 0x04, 0xcb, + 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x05, 0x12, 0x04, 0xcb, 0x01, + 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x01, 0x12, 0x04, 0xcb, 0x01, 0x12, + 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x03, 0x12, 0x04, 0xcb, 0x01, 0x21, 0x22, + 0x0a, 0x70, 0x0a, 0x02, 0x04, 0x10, 0x12, 0x06, 0xd0, 0x01, 0x00, 0xd2, 0x01, 0x01, 0x1a, 0x62, + 0x20, 0x53, 0x61, 0x76, 0x65, 0x56, 0x31, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, + 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x62, 0x61, + 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x62, 0x75, 0x69, + 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, + 0x65, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x10, 0x01, 0x12, 0x04, 0xd0, 0x01, 0x08, 0x22, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x10, 0x02, 0x00, 0x12, 0x04, 0xd1, 0x01, 0x02, 0x49, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x10, 0x02, 0x00, 0x04, 0x12, 0x04, 0xd1, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x10, 0x02, 0x00, 0x06, 0x12, 0x04, 0xd1, 0x01, 0x0b, 0x36, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x10, 0x02, 0x00, 0x01, 0x12, 0x04, 0xd1, 0x01, 0x37, 0x44, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x10, + 0x02, 0x00, 0x03, 0x12, 0x04, 0xd1, 0x01, 0x47, 0x48, 0x0a, 0x3f, 0x0a, 0x02, 0x04, 0x11, 0x12, + 0x04, 0xd5, 0x01, 0x00, 0x26, 0x1a, 0x33, 0x20, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, + 0x64, 0x65, 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x61, 0x76, 0x65, 0x56, 0x31, 0x43, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x11, + 0x01, 0x12, 0x04, 0xd5, 0x01, 0x08, 0x23, 0x0a, 0x2f, 0x0a, 0x02, 0x04, 0x12, 0x12, 0x06, 0xd8, + 0x01, 0x00, 0xda, 0x01, 0x01, 0x1a, 0x21, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x65, 0x74, 0x56, 0x32, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x12, 0x01, 0x12, + 0x04, 0xd8, 0x01, 0x08, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x12, 0x02, 0x00, 0x12, 0x04, 0xd9, + 0x01, 0x02, 0x49, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x12, 0x02, 0x00, 0x04, 0x12, 0x04, 0xd9, 0x01, + 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x12, 0x02, 0x00, 0x06, 0x12, 0x04, 0xd9, 0x01, 0x0b, + 0x36, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x12, 0x02, 0x00, 0x01, 0x12, 0x04, 0xd9, 0x01, 0x37, 0x44, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x12, 0x02, 0x00, 0x03, 0x12, 0x04, 0xd9, 0x01, 0x47, 0x48, 0x0a, + 0x93, 0x01, 0x0a, 0x02, 0x04, 0x13, 0x12, 0x06, 0xde, 0x01, 0x00, 0xe0, 0x01, 0x01, 0x1a, 0x84, + 0x01, 0x20, 0x55, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x20, + 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x68, + 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x75, 0x70, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x0a, 0x20, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x4f, 0x6e, 0x6c, 0x79, + 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x4d, 0x4d, 0x20, 0x53, 0x6e, 0x61, + 0x70, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x6c, 0x79, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x13, 0x01, 0x12, 0x04, 0xde, 0x01, + 0x08, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x13, 0x02, 0x00, 0x12, 0x04, 0xdf, 0x01, 0x02, 0x1c, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x13, 0x02, 0x00, 0x05, 0x12, 0x04, 0xdf, 0x01, 0x02, 0x08, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x13, 0x02, 0x00, 0x01, 0x12, 0x04, 0xdf, 0x01, 0x09, 0x17, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x13, 0x02, 0x00, 0x03, 0x12, 0x04, 0xdf, 0x01, 0x1a, 0x1b, 0x0a, 0x34, 0x0a, + 0x02, 0x04, 0x14, 0x12, 0x06, 0xe3, 0x01, 0x00, 0xec, 0x01, 0x01, 0x1a, 0x26, 0x20, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x47, 0x65, 0x74, 0x4b, 0x65, 0x79, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x14, 0x01, 0x12, 0x04, 0xe3, 0x01, 0x08, 0x21, + 0x0a, 0x49, 0x0a, 0x04, 0x04, 0x14, 0x04, 0x00, 0x12, 0x06, 0xe5, 0x01, 0x02, 0xe9, 0x01, 0x03, + 0x1a, 0x39, 0x20, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x14, 0x04, 0x00, 0x01, 0x12, 0x04, 0xe5, 0x01, 0x07, 0x15, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x14, + 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0xe6, 0x01, 0x04, 0x24, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x14, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xe6, 0x01, 0x04, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, + 0x14, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0xe6, 0x01, 0x22, 0x23, 0x0a, 0x0e, 0x0a, 0x06, + 0x04, 0x14, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, 0xe7, 0x01, 0x04, 0x26, 0x0a, 0x0f, 0x0a, 0x07, + 0x04, 0x14, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xe7, 0x01, 0x04, 0x21, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x14, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0xe7, 0x01, 0x24, 0x25, 0x0a, 0x0e, + 0x0a, 0x06, 0x04, 0x14, 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0xe8, 0x01, 0x04, 0x24, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x14, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xe8, 0x01, 0x04, 0x1f, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x14, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0xe8, 0x01, 0x22, 0x23, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x14, 0x02, 0x00, 0x12, 0x04, 0xeb, 0x01, 0x02, 0x1c, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x14, 0x02, 0x00, 0x06, 0x12, 0x04, 0xeb, 0x01, 0x02, 0x10, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x14, 0x02, 0x00, 0x01, 0x12, 0x04, 0xeb, 0x01, 0x11, 0x17, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x14, 0x02, 0x00, 0x03, 0x12, 0x04, 0xeb, 0x01, 0x1a, 0x1b, 0x0a, 0x64, 0x0a, 0x02, 0x04, + 0x15, 0x12, 0x06, 0xf0, 0x01, 0x00, 0xf4, 0x01, 0x01, 0x1a, 0x56, 0x20, 0x55, 0x73, 0x65, 0x64, + 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x61, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x62, + 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x15, 0x01, 0x12, 0x04, 0xf0, 0x01, 0x08, 0x1b, 0x0a, 0x0e, + 0x0a, 0x04, 0x04, 0x15, 0x08, 0x00, 0x12, 0x06, 0xf1, 0x01, 0x02, 0xf3, 0x01, 0x03, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x15, 0x08, 0x00, 0x01, 0x12, 0x04, 0xf1, 0x01, 0x08, 0x0e, 0x0a, 0x0c, 0x0a, + 0x04, 0x04, 0x15, 0x02, 0x00, 0x12, 0x04, 0xf2, 0x01, 0x04, 0x34, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x15, 0x02, 0x00, 0x06, 0x12, 0x04, 0xf2, 0x01, 0x04, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x15, + 0x02, 0x00, 0x01, 0x12, 0x04, 0xf2, 0x01, 0x2d, 0x2f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x15, 0x02, + 0x00, 0x03, 0x12, 0x04, 0xf2, 0x01, 0x32, 0x33, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x16, 0x12, 0x06, + 0xf7, 0x01, 0x00, 0xf9, 0x01, 0x01, 0x1a, 0x34, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, + 0x04, 0x16, 0x01, 0x12, 0x04, 0xf7, 0x01, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x16, 0x02, + 0x00, 0x12, 0x04, 0xf8, 0x01, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x16, 0x02, 0x00, 0x06, + 0x12, 0x04, 0xf8, 0x01, 0x02, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x16, 0x02, 0x00, 0x01, 0x12, + 0x04, 0xf8, 0x01, 0x10, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x16, 0x02, 0x00, 0x03, 0x12, 0x04, + 0xf8, 0x01, 0x18, 0x19, 0x0a, 0x64, 0x0a, 0x02, 0x04, 0x17, 0x12, 0x06, 0xfd, 0x01, 0x00, 0x83, + 0x02, 0x01, 0x1a, 0x56, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x20, + 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x0a, 0x20, 0x6f, 0x72, + 0x20, 0x61, 0x20, 0x70, 0x72, 0x65, 0x6b, 0x65, 0x79, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x17, + 0x01, 0x12, 0x04, 0xfd, 0x01, 0x08, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x00, 0x12, + 0x04, 0xfe, 0x01, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x05, 0x12, 0x04, + 0xfe, 0x01, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x01, 0x12, 0x04, 0xfe, + 0x01, 0x08, 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x03, 0x12, 0x04, 0xfe, 0x01, + 0x11, 0x12, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x17, 0x08, 0x00, 0x12, 0x06, 0xff, 0x01, 0x02, 0x82, + 0x02, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x08, 0x00, 0x01, 0x12, 0x04, 0xff, 0x01, 0x08, + 0x0e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x01, 0x12, 0x04, 0x80, 0x02, 0x04, 0x1a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x05, 0x12, 0x04, 0x80, 0x02, 0x04, 0x08, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x01, 0x12, 0x04, 0x80, 0x02, 0x09, 0x15, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x17, 0x02, 0x01, 0x03, 0x12, 0x04, 0x80, 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x17, 0x02, 0x02, 0x12, 0x04, 0x81, 0x02, 0x04, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, + 0x02, 0x02, 0x05, 0x12, 0x04, 0x81, 0x02, 0x04, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, + 0x02, 0x01, 0x12, 0x04, 0x81, 0x02, 0x0b, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x02, + 0x03, 0x12, 0x04, 0x81, 0x02, 0x1a, 0x1b, 0x0a, 0x58, 0x0a, 0x02, 0x05, 0x01, 0x12, 0x06, 0x86, + 0x02, 0x00, 0x8b, 0x02, 0x01, 0x1a, 0x4a, 0x20, 0x4a, 0x6f, 0x62, 0x54, 0x79, 0x70, 0x65, 0x20, + 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, + 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6a, + 0x6f, 0x62, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6f, 0x6e, + 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x05, 0x01, 0x01, 0x12, 0x04, 0x86, 0x02, 0x05, 0x0c, 0x0a, 0x0c, + 0x0a, 0x04, 0x05, 0x01, 0x02, 0x00, 0x12, 0x04, 0x87, 0x02, 0x02, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, + 0x05, 0x01, 0x02, 0x00, 0x01, 0x12, 0x04, 0x87, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x05, + 0x01, 0x02, 0x00, 0x02, 0x12, 0x04, 0x87, 0x02, 0x19, 0x1a, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, + 0x02, 0x01, 0x12, 0x04, 0x88, 0x02, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x01, + 0x01, 0x12, 0x04, 0x88, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x01, 0x02, + 0x12, 0x04, 0x88, 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x02, 0x12, 0x04, + 0x89, 0x02, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x02, 0x01, 0x12, 0x04, 0x89, + 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x02, 0x02, 0x12, 0x04, 0x89, 0x02, + 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x03, 0x12, 0x04, 0x8a, 0x02, 0x02, 0x1c, + 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x03, 0x01, 0x12, 0x04, 0x8a, 0x02, 0x02, 0x17, 0x0a, + 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x03, 0x02, 0x12, 0x04, 0x8a, 0x02, 0x1a, 0x1b, 0x0a, 0x56, + 0x0a, 0x02, 0x04, 0x18, 0x12, 0x06, 0x8e, 0x02, 0x00, 0x90, 0x02, 0x01, 0x1a, 0x48, 0x20, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x67, + 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x72, 0x75, 0x6e, 0x20, + 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, + 0x68, 0x20, 0x6a, 0x6f, 0x62, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x18, 0x01, 0x12, 0x04, 0x8e, + 0x02, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, 0x00, 0x12, 0x04, 0x8f, 0x02, 0x02, + 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x06, 0x12, 0x04, 0x8f, 0x02, 0x02, 0x09, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8f, 0x02, 0x0a, 0x12, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x03, 0x12, 0x04, 0x8f, 0x02, 0x15, 0x16, 0x0a, 0x5a, + 0x0a, 0x02, 0x04, 0x19, 0x12, 0x06, 0x93, 0x02, 0x00, 0x95, 0x02, 0x01, 0x1a, 0x4c, 0x20, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, + 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x72, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x20, 0x6a, 0x6f, 0x62, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x19, + 0x01, 0x12, 0x04, 0x93, 0x02, 0x08, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x19, 0x02, 0x00, 0x12, + 0x04, 0x94, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x05, 0x12, 0x04, + 0x94, 0x02, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x01, 0x12, 0x04, 0x94, + 0x02, 0x08, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x03, 0x12, 0x04, 0x94, 0x02, + 0x16, 0x17, 0x0a, 0x56, 0x0a, 0x02, 0x04, 0x1a, 0x12, 0x06, 0x98, 0x02, 0x00, 0x9b, 0x02, 0x01, + 0x1a, 0x48, 0x20, 0x53, 0x65, 0x74, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, + 0x72, 0x75, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x72, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x20, 0x6a, 0x6f, 0x62, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1a, + 0x01, 0x12, 0x04, 0x98, 0x02, 0x08, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1a, 0x02, 0x00, 0x12, + 0x04, 0x99, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x06, 0x12, 0x04, + 0x99, 0x02, 0x02, 0x09, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x01, 0x12, 0x04, 0x99, + 0x02, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x03, 0x12, 0x04, 0x99, 0x02, + 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1a, 0x02, 0x01, 0x12, 0x04, 0x9a, 0x02, 0x02, 0x18, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x05, 0x12, 0x04, 0x9a, 0x02, 0x02, 0x07, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x01, 0x12, 0x04, 0x9a, 0x02, 0x08, 0x13, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x03, 0x12, 0x04, 0x9a, 0x02, 0x16, 0x17, 0x0a, 0x3d, 0x0a, + 0x02, 0x04, 0x1b, 0x12, 0x04, 0x9e, 0x02, 0x00, 0x20, 0x1a, 0x31, 0x20, 0x53, 0x65, 0x74, 0x52, + 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, + 0x04, 0x1b, 0x01, 0x12, 0x04, 0x9e, 0x02, 0x08, 0x1d, 0x0a, 0x42, 0x0a, 0x02, 0x04, 0x1c, 0x12, + 0x06, 0xa1, 0x02, 0x00, 0xa9, 0x02, 0x01, 0x1a, 0x34, 0x20, 0x41, 0x20, 0x6d, 0x61, 0x70, 0x70, + 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, + 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x0b, 0x0a, + 0x03, 0x04, 0x1c, 0x01, 0x12, 0x04, 0xa1, 0x02, 0x08, 0x10, 0x0a, 0x51, 0x0a, 0x04, 0x04, 0x1c, + 0x03, 0x00, 0x12, 0x06, 0xa3, 0x02, 0x02, 0xa7, 0x02, 0x03, 0x1a, 0x41, 0x20, 0x54, 0x6f, 0x70, + 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x20, 0x77, 0x72, 0x61, 0x70, 0x73, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x69, 0x74, + 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x0a, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1c, 0x03, 0x00, 0x01, 0x12, 0x04, 0xa3, 0x02, 0x0a, 0x13, 0x0a, 0x0e, 0x0a, 0x06, + 0x04, 0x1c, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0xa4, 0x02, 0x04, 0x1a, 0x0a, 0x0f, 0x0a, 0x07, + 0x04, 0x1c, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0xa4, 0x02, 0x04, 0x0a, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xa4, 0x02, 0x0b, 0x15, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0xa4, 0x02, 0x18, 0x19, 0x0a, + 0x0e, 0x0a, 0x06, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0xa5, 0x02, 0x04, 0x1c, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x04, 0xa5, 0x02, 0x04, 0x0a, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xa5, 0x02, 0x0b, + 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0xa5, 0x02, + 0x1a, 0x1b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x02, 0x12, 0x04, 0xa6, 0x02, + 0x04, 0x36, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x02, 0x06, 0x12, 0x04, 0xa6, + 0x02, 0x04, 0x26, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, + 0xa6, 0x02, 0x27, 0x31, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, + 0x04, 0xa6, 0x02, 0x34, 0x35, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1c, 0x02, 0x00, 0x12, 0x04, 0xa8, + 0x02, 0x02, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x06, 0x12, 0x04, 0xa8, 0x02, + 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x01, 0x12, 0x04, 0xa8, 0x02, 0x19, + 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x03, 0x12, 0x04, 0xa8, 0x02, 0x22, 0x23, + 0x0a, 0x4f, 0x0a, 0x02, 0x04, 0x1d, 0x12, 0x06, 0xac, 0x02, 0x00, 0xae, 0x02, 0x01, 0x1a, 0x41, + 0x20, 0x55, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x61, 0x20, 0x6d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6b, 0x65, 0x79, 0x73, + 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1d, 0x01, 0x12, 0x04, 0xac, 0x02, 0x08, 0x26, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x1d, 0x02, 0x00, 0x12, 0x04, 0xad, 0x02, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x1d, 0x02, 0x00, 0x04, 0x12, 0x04, 0xad, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x1d, 0x02, 0x00, 0x05, 0x12, 0x04, 0xad, 0x02, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, + 0x02, 0x00, 0x01, 0x12, 0x04, 0xad, 0x02, 0x12, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, 0x02, + 0x00, 0x03, 0x12, 0x04, 0xad, 0x02, 0x1b, 0x1c, 0x0a, 0x36, 0x0a, 0x02, 0x04, 0x1e, 0x12, 0x06, + 0xb1, 0x02, 0x00, 0xbc, 0x02, 0x01, 0x1a, 0x28, 0x20, 0x41, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x20, 0x74, 0x6f, 0x20, + 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x0a, + 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1e, 0x01, 0x12, 0x04, 0xb1, 0x02, 0x08, 0x27, 0x0a, 0x5d, 0x0a, + 0x04, 0x04, 0x1e, 0x03, 0x00, 0x12, 0x06, 0xb3, 0x02, 0x02, 0xb6, 0x02, 0x03, 0x1a, 0x4d, 0x20, + 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x20, 0x77, 0x72, 0x61, 0x70, + 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6f, 0x66, + 0x20, 0x33, 0x30, 0x20, 0x64, 0x61, 0x79, 0x20, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x20, + 0x73, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x1e, 0x03, 0x00, 0x01, 0x12, 0x04, 0xb3, 0x02, 0x0a, 0x15, 0x0a, 0x0e, 0x0a, 0x06, 0x04, + 0x1e, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0xb4, 0x02, 0x04, 0x2d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, + 0x1e, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0xb4, 0x02, 0x04, 0x09, 0x0a, 0x0f, 0x0a, 0x07, + 0x04, 0x1e, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xb4, 0x02, 0x0a, 0x28, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0xb4, 0x02, 0x2b, 0x2c, 0x0a, 0x0e, + 0x0a, 0x06, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0xb5, 0x02, 0x04, 0x17, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x04, 0xb5, 0x02, 0x04, 0x09, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xb5, 0x02, 0x0a, 0x12, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0xb5, 0x02, 0x15, + 0x16, 0x0a, 0x42, 0x0a, 0x04, 0x04, 0x1e, 0x03, 0x01, 0x12, 0x06, 0xb8, 0x02, 0x02, 0xba, 0x02, + 0x03, 0x1a, 0x32, 0x20, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x20, 0x72, 0x65, 0x70, + 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, + 0x20, 0x48, 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x44, 0x61, 0x74, 0x61, 0x20, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x03, 0x01, 0x01, 0x12, 0x04, + 0xb8, 0x02, 0x0a, 0x12, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1e, 0x03, 0x01, 0x02, 0x00, 0x12, 0x04, + 0xb9, 0x02, 0x04, 0x24, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x01, 0x02, 0x00, 0x04, 0x12, + 0x04, 0xb9, 0x02, 0x04, 0x0c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x01, 0x02, 0x00, 0x06, + 0x12, 0x04, 0xb9, 0x02, 0x0d, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x01, 0x02, 0x00, + 0x01, 0x12, 0x04, 0xb9, 0x02, 0x19, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1e, 0x03, 0x01, 0x02, + 0x00, 0x03, 0x12, 0x04, 0xb9, 0x02, 0x22, 0x23, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1e, 0x02, 0x00, + 0x12, 0x04, 0xbb, 0x02, 0x02, 0x26, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, 0x06, 0x12, + 0x04, 0xbb, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, 0x01, 0x12, 0x04, + 0xbb, 0x02, 0x18, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, 0x03, 0x12, 0x04, 0xbb, + 0x02, 0x24, 0x25, 0x0a, 0x4f, 0x0a, 0x02, 0x04, 0x1f, 0x12, 0x06, 0xbf, 0x02, 0x00, 0xc1, 0x02, + 0x01, 0x1a, 0x41, 0x20, 0x41, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, + 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x20, + 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1f, 0x01, 0x12, 0x04, 0xbf, 0x02, 0x08, + 0x23, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1f, 0x02, 0x00, 0x12, 0x04, 0xc0, 0x02, 0x02, 0x4a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x00, 0x06, 0x12, 0x04, 0xc0, 0x02, 0x02, 0x3d, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x00, 0x01, 0x12, 0x04, 0xc0, 0x02, 0x3e, 0x45, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1f, 0x02, 0x00, 0x03, 0x12, 0x04, 0xc0, 0x02, 0x48, 0x49, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, ]; include!("xmtp.keystore_api.v1.serde.rs"); // @@protoc_insertion_point(module) \ No newline at end of file diff --git a/xmtp_proto/src/gen/xmtp.keystore_api.v1.serde.rs b/xmtp_proto/src/gen/xmtp.keystore_api.v1.serde.rs index 004d74ecf..1ad7f6d66 100644 --- a/xmtp_proto/src/gen/xmtp.keystore_api.v1.serde.rs +++ b/xmtp_proto/src/gen/xmtp.keystore_api.v1.serde.rs @@ -3347,6 +3347,99 @@ impl<'de> serde::Deserialize<'de> for KeystoreError { deserializer.deserialize_struct("xmtp.keystore_api.v1.KeystoreError", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for PrivatePreferencesActionMap { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.actions.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.keystore_api.v1.PrivatePreferencesActionMap", len)?; + if !self.actions.is_empty() { + struct_ser.serialize_field("actions", &self.actions)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for PrivatePreferencesActionMap { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "actions", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Actions, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "actions" => Ok(GeneratedField::Actions), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = PrivatePreferencesActionMap; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.keystore_api.v1.PrivatePreferencesActionMap") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut actions__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Actions => { + if actions__.is_some() { + return Err(serde::de::Error::duplicate_field("actions")); + } + actions__ = Some( + map_.next_value::>()? + ); + } + } + } + Ok(PrivatePreferencesActionMap { + actions: actions__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.keystore_api.v1.PrivatePreferencesActionMap", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for SaveInvitesRequest { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/xmtp_proto/src/gen/xmtp.message_contents.rs b/xmtp_proto/src/gen/xmtp.message_contents.rs index 823855286..b4ec8ba5f 100644 --- a/xmtp_proto/src/gen/xmtp.message_contents.rs +++ b/xmtp_proto/src/gen/xmtp.message_contents.rs @@ -497,6 +497,97 @@ pub mod encrypted_private_key_bundle { V1(super::EncryptedPrivateKeyBundleV1), } } +/// PrivatePreferencesAction is a message used to update the client's preference +/// store. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PrivatePreferencesAction { + #[prost(oneof="private_preferences_action::MessageType", tags="1, 2, 3, 4, 5, 6")] + pub message_type: ::core::option::Option, +} +/// Nested message and enum types in `PrivatePreferencesAction`. +pub mod private_preferences_action { + /// Allow 1:1 direct message (DM) access + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct AllowAddress { + /// Add the given wallet addresses to the allow list + #[prost(string, repeated, tag="1")] + pub wallet_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + } + /// Deny (block) 1:1 direct message (DM) access + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct DenyAddress { + /// Add the given wallet addresses to the deny list + #[prost(string, repeated, tag="1")] + pub wallet_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + } + /// Allow V3 1:1 direct message (DM) access + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct AllowInboxId { + /// Add the given inbox id to the allow list + #[prost(string, repeated, tag="1")] + pub inbox_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + } + /// Deny (block) V3 1:1 direct message (DM) access + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct DenyInboxId { + /// Add the given inbox id to the deny list + #[prost(string, repeated, tag="1")] + pub inbox_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + } + /// Allow Group access + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct AllowGroup { + /// Add the given group_ids to the allow list + #[prost(string, repeated, tag="1")] + pub group_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + } + /// Deny (deny) Group access + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct DenyGroup { + /// Add the given group_ids to the deny list + #[prost(string, repeated, tag="1")] + pub group_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + } + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum MessageType { + #[prost(message, tag="1")] + AllowAddress(AllowAddress), + #[prost(message, tag="2")] + DenyAddress(DenyAddress), + #[prost(message, tag="3")] + AllowGroup(AllowGroup), + #[prost(message, tag="4")] + DenyGroup(DenyGroup), + #[prost(message, tag="5")] + AllowInboxId(AllowInboxId), + #[prost(message, tag="6")] + DenyInboxId(DenyInboxId), + } +} +/// The payload that goes over the wire +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PrivatePreferencesPayload { + #[prost(oneof="private_preferences_payload::Version", tags="1")] + pub version: ::core::option::Option, +} +/// Nested message and enum types in `PrivatePreferencesPayload`. +pub mod private_preferences_payload { + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Version { + #[prost(message, tag="1")] + V1(super::Ciphertext), + } +} /// ContentTypeId is used to identify the type of content stored in a Message. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -813,97 +904,6 @@ pub struct DecodedMessage { #[prost(bytes="vec", tag="8")] pub content_bytes: ::prost::alloc::vec::Vec, } -/// PrivatePreferencesAction is a message used to update the client's preference -/// store. -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PrivatePreferencesAction { - #[prost(oneof="private_preferences_action::MessageType", tags="1, 2, 3, 4, 5, 6")] - pub message_type: ::core::option::Option, -} -/// Nested message and enum types in `PrivatePreferencesAction`. -pub mod private_preferences_action { - /// Allow 1:1 direct message (DM) access - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] - pub struct AllowAddress { - /// Add the given wallet addresses to the allow list - #[prost(string, repeated, tag="1")] - pub wallet_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - } - /// Deny (block) 1:1 direct message (DM) access - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] - pub struct DenyAddress { - /// Add the given wallet addresses to the deny list - #[prost(string, repeated, tag="1")] - pub wallet_addresses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - } - /// Allow V3 1:1 direct message (DM) access - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] - pub struct AllowInboxId { - /// Add the given inbox id to the allow list - #[prost(string, repeated, tag="1")] - pub inbox_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - } - /// Deny (block) V3 1:1 direct message (DM) access - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] - pub struct DenyInboxId { - /// Add the given inbox id to the deny list - #[prost(string, repeated, tag="1")] - pub inbox_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - } - /// Allow Group access - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] - pub struct AllowGroup { - /// Add the given group_ids to the allow list - #[prost(string, repeated, tag="1")] - pub group_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - } - /// Deny (deny) Group access - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] - pub struct DenyGroup { - /// Add the given group_ids to the deny list - #[prost(string, repeated, tag="1")] - pub group_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - } - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum MessageType { - #[prost(message, tag="1")] - AllowAddress(AllowAddress), - #[prost(message, tag="2")] - DenyAddress(DenyAddress), - #[prost(message, tag="3")] - AllowGroup(AllowGroup), - #[prost(message, tag="4")] - DenyGroup(DenyGroup), - #[prost(message, tag="5")] - AllowInboxId(AllowInboxId), - #[prost(message, tag="6")] - DenyInboxId(DenyInboxId), - } -} -/// The payload that goes over the wire -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct PrivatePreferencesPayload { - #[prost(oneof="private_preferences_payload::Version", tags="1")] - pub version: ::core::option::Option, -} -/// Nested message and enum types in `PrivatePreferencesPayload`. -pub mod private_preferences_payload { - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Version { - #[prost(message, tag="1")] - V1(super::Ciphertext), - } -} /// SignedPayload is a wrapper for a signature and a payload #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -2007,227 +2007,80 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x04, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x06, 0x12, 0x03, 0x5b, 0x04, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, 0x03, 0x5b, 0x20, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x5b, 0x25, 0x26, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xdd, 0x18, 0x0a, 0x1e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x21, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x95, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x79, 0x70, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x79, 0x70, 0x65, 0x49, - 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x6a, - 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x83, 0x03, 0x0a, 0x0e, - 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x49, 0x64, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x55, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, - 0x1f, 0x0a, 0x08, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x08, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x88, 0x01, 0x01, - 0x12, 0x49, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, - 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x0b, 0x63, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, - 0x6b, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x44, 0x0a, - 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x06, 0x73, 0x65, 0x6e, - 0x64, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x2a, 0x3c, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, - 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, - 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x5a, 0x49, 0x50, 0x10, - 0x01, 0x42, 0xc8, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, - 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, - 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, 0x74, - 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xfd, 0x0f, 0x0a, - 0x06, 0x12, 0x04, 0x01, 0x00, 0x36, 0x01, 0x0a, 0x2f, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, - 0x12, 0x1a, 0x25, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x72, - 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, - 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, 0x00, 0x2b, 0x0a, 0x09, 0x0a, - 0x02, 0x03, 0x01, 0x12, 0x03, 0x06, 0x00, 0x2a, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x08, - 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x08, 0x00, 0x43, 0x0a, 0x58, 0x0a, - 0x02, 0x04, 0x00, 0x12, 0x04, 0x0c, 0x00, 0x11, 0x01, 0x1a, 0x4c, 0x20, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, - 0x0c, 0x08, 0x15, 0x0a, 0x34, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0d, 0x02, 0x1a, - 0x22, 0x27, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x67, 0x6f, 0x76, - 0x65, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x00, 0x05, 0x12, 0x03, 0x0d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x0d, 0x09, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x0d, 0x18, 0x19, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0e, 0x02, 0x15, - 0x22, 0x11, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x0e, 0x02, - 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0e, 0x09, 0x10, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0e, 0x13, 0x14, 0x0a, 0x28, 0x0a, - 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0f, 0x02, 0x1b, 0x22, 0x1b, 0x20, 0x6d, 0x61, 0x6a, - 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, - 0x12, 0x03, 0x0f, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, - 0x0f, 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x0f, 0x19, - 0x1a, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x10, 0x02, 0x1b, 0x22, 0x1b, - 0x20, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x10, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x03, 0x01, 0x12, 0x03, 0x10, 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x03, - 0x12, 0x03, 0x10, 0x19, 0x1a, 0x0a, 0x67, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, 0x15, 0x00, 0x18, - 0x01, 0x1a, 0x5b, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x63, - 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, - 0x69, 0x74, 0x68, 0x6d, 0x73, 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6c, 0x69, 0x6e, 0x74, - 0x3a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, - 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x5f, 0x56, - 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x45, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x05, 0x00, 0x01, 0x12, 0x03, 0x15, 0x05, 0x10, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, - 0x02, 0x00, 0x12, 0x03, 0x16, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x16, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, - 0x16, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x17, 0x02, 0x17, - 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x17, 0x02, 0x12, 0x0a, 0x0c, - 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x17, 0x15, 0x16, 0x0a, 0xa3, 0x01, 0x0a, - 0x02, 0x04, 0x01, 0x12, 0x04, 0x1d, 0x00, 0x2b, 0x01, 0x1a, 0x96, 0x01, 0x20, 0x45, 0x6e, 0x63, - 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, - 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x73, 0x20, 0x74, 0x79, - 0x70, 0x65, 0x0a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x1d, 0x08, 0x16, 0x0a, 0x65, - 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x20, 0x02, 0x19, 0x1a, 0x58, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, - 0x77, 0x69, 0x74, 0x68, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, - 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x72, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x20, 0x02, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x20, 0x10, - 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x20, 0x17, 0x18, 0x0a, - 0x54, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x22, 0x02, 0x25, 0x1a, 0x47, 0x20, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, - 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, - 0x79, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, - 0x22, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x22, 0x16, - 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x22, 0x23, 0x24, 0x0a, - 0x84, 0x01, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x25, 0x02, 0x1f, 0x1a, 0x77, 0x20, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, - 0x6b, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x61, - 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, - 0x20, 0x63, 0x61, 0x73, 0x65, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x20, - 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x04, 0x12, - 0x03, 0x25, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x05, 0x12, 0x03, 0x25, - 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x25, 0x12, 0x1a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x25, 0x1d, 0x1e, 0x0a, 0x6e, - 0x0a, 0x04, 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x28, 0x02, 0x27, 0x1a, 0x61, 0x20, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, - 0x6d, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x04, 0x12, 0x03, 0x28, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x03, 0x06, 0x12, 0x03, 0x28, 0x0b, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x03, 0x01, 0x12, 0x03, 0x28, 0x17, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, - 0x03, 0x12, 0x03, 0x28, 0x25, 0x26, 0x0a, 0x25, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x04, 0x12, 0x03, - 0x2a, 0x02, 0x14, 0x1a, 0x18, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x0a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x04, 0x05, 0x12, 0x03, 0x2a, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x01, 0x02, 0x04, 0x01, 0x12, 0x03, 0x2a, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, - 0x04, 0x03, 0x12, 0x03, 0x2a, 0x12, 0x13, 0x0a, 0x43, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x2e, - 0x00, 0x36, 0x01, 0x1a, 0x37, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x45, 0x6e, 0x63, 0x6f, - 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, - 0x04, 0x02, 0x01, 0x12, 0x03, 0x2e, 0x08, 0x15, 0x0a, 0x2a, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, - 0x12, 0x03, 0x30, 0x02, 0x14, 0x1a, 0x1d, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, 0x30, - 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x30, 0x08, 0x0f, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x30, 0x12, 0x13, 0x0a, 0x0b, - 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x31, 0x02, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x31, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, - 0x01, 0x01, 0x12, 0x03, 0x31, 0x18, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, - 0x12, 0x03, 0x31, 0x21, 0x22, 0x0a, 0x8a, 0x01, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, - 0x35, 0x02, 0x1a, 0x1a, 0x7d, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x63, - 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x0a, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2c, - 0x0a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x27, 0x73, 0x20, 0x70, 0x72, 0x65, 0x2d, 0x6b, 0x65, 0x79, - 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x06, 0x12, 0x03, 0x35, 0x02, 0x0b, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, 0x03, 0x35, 0x0c, 0x15, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x35, 0x18, 0x19, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xf3, 0x07, 0x0a, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x1a, 0x1e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0xdb, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x12, 0x3b, - 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2e, - 0x50, 0x61, 0x72, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x1a, 0x90, 0x01, 0x0a, 0x04, - 0x50, 0x61, 0x72, 0x74, 0x12, 0x3b, 0x0a, 0x04, 0x70, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6e, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x72, - 0x74, 0x12, 0x40, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x48, 0x00, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0xca, - 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0e, 0x43, 0x6f, - 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, + 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xf3, 0x19, 0x0a, 0x2a, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x69, 0x70, + 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x07, + 0x0a, 0x18, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x63, 0x0a, 0x0d, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x3c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, + 0x00, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x60, 0x0a, 0x0c, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, + 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6e, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x6e, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x5d, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x12, 0x5a, 0x0a, 0x0a, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6e, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, + 0x00, 0x52, 0x09, 0x64, 0x65, 0x6e, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x64, 0x0a, 0x0e, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x62, 0x6f, 0x78, + 0x49, 0x64, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x62, 0x6f, 0x78, + 0x49, 0x64, 0x12, 0x61, 0x0a, 0x0d, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6e, 0x79, 0x49, + 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x6e, 0x79, 0x49, 0x6e, + 0x62, 0x6f, 0x78, 0x49, 0x64, 0x1a, 0x39, 0x0a, 0x0c, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, + 0x1a, 0x38, 0x0a, 0x0b, 0x44, 0x65, 0x6e, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x29, 0x0a, 0x10, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x2b, 0x0a, 0x0c, 0x41, 0x6c, + 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, + 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, + 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x1a, 0x2a, 0x0a, 0x0b, 0x44, 0x65, 0x6e, 0x79, 0x49, + 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, + 0x49, 0x64, 0x73, 0x1a, 0x29, 0x0a, 0x0a, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x1a, 0x28, + 0x0a, 0x09, 0x44, 0x65, 0x6e, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x5b, 0x0a, 0x19, 0x50, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x50, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, + 0x74, 0x65, 0x78, 0x74, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, 0x09, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0xd3, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x42, 0x17, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, @@ -2237,676 +2090,351 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xe4, 0x03, 0x0a, 0x06, - 0x12, 0x04, 0x01, 0x00, 0x15, 0x01, 0x0a, 0x21, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, - 0x1a, 0x17, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, - 0x03, 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, 0x00, 0x28, 0x0a, 0x08, - 0x0a, 0x01, 0x08, 0x12, 0x03, 0x07, 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, - 0x07, 0x00, 0x43, 0x0a, 0x4c, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0b, 0x00, 0x15, 0x01, 0x1a, - 0x40, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x20, 0x69, 0x73, 0x20, 0x75, - 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x20, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, - 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0b, 0x08, 0x11, 0x0a, 0x42, 0x0a, - 0x04, 0x04, 0x00, 0x03, 0x00, 0x12, 0x04, 0x0d, 0x02, 0x12, 0x03, 0x1a, 0x34, 0x20, 0x50, 0x61, - 0x72, 0x74, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x6e, - 0x65, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x63, - 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x00, 0x01, 0x12, 0x03, 0x0d, 0x0a, 0x0e, 0x0a, - 0x0e, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x12, 0x04, 0x0e, 0x04, 0x11, 0x05, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x12, 0x03, 0x0e, 0x0a, 0x11, 0x0a, - 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0f, 0x06, 0x1e, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x0f, 0x06, 0x14, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0f, 0x15, 0x19, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0f, 0x1c, 0x1d, 0x0a, 0x0d, - 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x10, 0x06, 0x1e, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x10, 0x06, 0x0f, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x10, 0x10, 0x19, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x10, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x14, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x02, 0x00, 0x04, 0x12, 0x03, 0x14, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, - 0x06, 0x12, 0x03, 0x14, 0x0b, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, - 0x03, 0x14, 0x10, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x14, - 0x18, 0x19, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xd2, 0x0b, 0x0a, 0x1e, 0x6d, + 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xb4, 0x0f, 0x0a, 0x06, + 0x12, 0x04, 0x04, 0x00, 0x42, 0x01, 0x0a, 0x99, 0x01, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x04, 0x00, + 0x12, 0x1a, 0x8e, 0x01, 0x20, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x4b, 0x65, 0x79, + 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x20, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2c, 0x20, 0x69, + 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x20, 0x61, 0x0a, 0x20, 0x77, 0x61, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, + 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, + 0x6b, 0x65, 0x79, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x2e, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x06, 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, + 0x03, 0x00, 0x12, 0x03, 0x08, 0x00, 0x2b, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x0a, 0x00, + 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x0a, 0x00, 0x43, 0x0a, 0x62, 0x0a, 0x02, + 0x04, 0x00, 0x12, 0x04, 0x0f, 0x00, 0x3d, 0x01, 0x1a, 0x56, 0x20, 0x50, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x27, 0x73, 0x20, 0x70, 0x72, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0f, 0x08, 0x20, 0x0a, 0x34, 0x0a, 0x04, + 0x04, 0x00, 0x03, 0x00, 0x12, 0x04, 0x11, 0x02, 0x14, 0x03, 0x1a, 0x26, 0x20, 0x41, 0x6c, 0x6c, + 0x6f, 0x77, 0x20, 0x31, 0x3a, 0x31, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x28, 0x44, 0x4d, 0x29, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x00, 0x01, 0x12, 0x03, 0x11, 0x0a, 0x16, + 0x0a, 0x41, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x13, 0x04, 0x29, 0x1a, + 0x32, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, + 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6c, 0x69, + 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, + 0x13, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, + 0x13, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x13, 0x14, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x13, 0x27, 0x28, 0x0a, 0x3b, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x01, 0x12, 0x04, 0x17, 0x02, 0x1a, + 0x03, 0x1a, 0x2d, 0x20, 0x44, 0x65, 0x6e, 0x79, 0x20, 0x28, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x29, + 0x20, 0x31, 0x3a, 0x31, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x20, 0x28, 0x44, 0x4d, 0x29, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x01, 0x01, 0x12, 0x03, 0x17, 0x0a, 0x15, 0x0a, 0x40, + 0x0a, 0x06, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x19, 0x04, 0x29, 0x1a, 0x31, 0x20, + 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, 0x04, 0x12, 0x03, 0x19, 0x04, 0x0c, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x19, 0x0d, 0x13, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x19, 0x14, 0x24, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x19, 0x27, 0x28, + 0x0a, 0x37, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x02, 0x12, 0x04, 0x1d, 0x02, 0x20, 0x03, 0x1a, 0x29, + 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x56, 0x33, 0x20, 0x31, 0x3a, 0x31, 0x20, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x28, 0x44, 0x4d, + 0x29, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, + 0x02, 0x01, 0x12, 0x03, 0x1d, 0x0a, 0x16, 0x0a, 0x39, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x02, 0x02, + 0x00, 0x12, 0x03, 0x1f, 0x04, 0x22, 0x1a, 0x2a, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x20, 0x69, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6c, 0x69, 0x73, + 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x02, 0x02, 0x00, 0x04, 0x12, 0x03, 0x1f, + 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, 0x1f, + 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x1f, + 0x14, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x1f, + 0x20, 0x21, 0x0a, 0x3e, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x03, 0x12, 0x04, 0x23, 0x02, 0x26, 0x03, + 0x1a, 0x30, 0x20, 0x44, 0x65, 0x6e, 0x79, 0x20, 0x28, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x20, + 0x56, 0x33, 0x20, 0x31, 0x3a, 0x31, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x28, 0x44, 0x4d, 0x29, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x03, 0x01, 0x12, 0x03, 0x23, 0x0a, 0x15, + 0x0a, 0x38, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x03, 0x02, 0x00, 0x12, 0x03, 0x25, 0x04, 0x22, 0x1a, + 0x29, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, + 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x20, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x64, 0x65, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, + 0x03, 0x03, 0x02, 0x00, 0x04, 0x12, 0x03, 0x25, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, + 0x03, 0x03, 0x02, 0x00, 0x05, 0x12, 0x03, 0x25, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, + 0x03, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x25, 0x14, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, + 0x03, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x25, 0x20, 0x21, 0x0a, 0x22, 0x0a, 0x04, 0x04, 0x00, + 0x03, 0x04, 0x12, 0x04, 0x2a, 0x02, 0x2d, 0x03, 0x1a, 0x14, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, + 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x03, 0x04, 0x01, 0x12, 0x03, 0x2a, 0x0a, 0x14, 0x0a, 0x3a, 0x0a, 0x06, + 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x12, 0x03, 0x2c, 0x04, 0x22, 0x1a, 0x2b, 0x20, 0x41, 0x64, + 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x5f, 0x69, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, + 0x02, 0x00, 0x04, 0x12, 0x03, 0x2c, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, + 0x02, 0x00, 0x05, 0x12, 0x03, 0x2c, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x2c, 0x14, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x2c, 0x20, 0x21, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x05, + 0x12, 0x04, 0x30, 0x02, 0x33, 0x03, 0x1a, 0x1a, 0x20, 0x44, 0x65, 0x6e, 0x79, 0x20, 0x28, 0x64, + 0x65, 0x6e, 0x79, 0x29, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x05, 0x01, 0x12, 0x03, 0x30, 0x0a, 0x13, + 0x0a, 0x39, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x12, 0x03, 0x32, 0x04, 0x22, 0x1a, + 0x2a, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x64, 0x65, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x00, 0x03, 0x05, 0x02, 0x00, 0x04, 0x12, 0x03, 0x32, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x00, 0x03, 0x05, 0x02, 0x00, 0x05, 0x12, 0x03, 0x32, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x00, 0x03, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x32, 0x14, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x00, 0x03, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x32, 0x20, 0x21, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x00, 0x08, 0x00, 0x12, 0x04, 0x35, 0x02, 0x3c, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x08, + 0x00, 0x01, 0x12, 0x03, 0x35, 0x08, 0x14, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, + 0x03, 0x36, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x36, + 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x36, 0x11, 0x1e, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x36, 0x21, 0x22, 0x0a, 0x0b, + 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x37, 0x04, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x37, 0x04, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x01, 0x01, 0x12, 0x03, 0x37, 0x10, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, + 0x12, 0x03, 0x37, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x38, + 0x04, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x06, 0x12, 0x03, 0x38, 0x04, 0x0e, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x38, 0x0f, 0x1a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x38, 0x1d, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x39, 0x04, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x03, 0x06, 0x12, 0x03, 0x39, 0x04, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x01, + 0x12, 0x03, 0x39, 0x0e, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, + 0x39, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x04, 0x12, 0x03, 0x3a, 0x04, 0x24, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x06, 0x12, 0x03, 0x3a, 0x04, 0x10, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, 0x3a, 0x11, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x04, 0x03, 0x12, 0x03, 0x3a, 0x22, 0x23, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, + 0x02, 0x05, 0x12, 0x03, 0x3b, 0x04, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x06, + 0x12, 0x03, 0x3b, 0x04, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x01, 0x12, 0x03, + 0x3b, 0x10, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x03, 0x12, 0x03, 0x3b, 0x20, + 0x21, 0x0a, 0x31, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x40, 0x00, 0x42, 0x01, 0x1a, 0x25, 0x20, + 0x54, 0x68, 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, + 0x20, 0x67, 0x6f, 0x65, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x69, 0x72, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x40, 0x08, 0x21, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x08, 0x00, 0x12, 0x03, 0x41, 0x02, 0x26, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x08, 0x00, 0x01, 0x12, 0x03, 0x41, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x01, 0x02, 0x00, 0x12, 0x03, 0x41, 0x12, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x12, 0x03, 0x41, 0x12, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x41, 0x1d, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x41, + 0x22, 0x23, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xdd, 0x18, 0x0a, 0x1e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, - 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x58, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x63, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x31, 0x12, 0x45, 0x0a, 0x0a, 0x6b, 0x65, - 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x22, 0x5e, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x56, 0x32, 0x12, 0x4b, 0x0a, 0x0a, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x09, 0x6b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x12, 0x38, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x12, 0x38, 0x0a, - 0x02, 0x76, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, - 0x32, 0x48, 0x00, 0x52, 0x02, 0x76, 0x32, 0x42, 0x09, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x42, 0xc8, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x42, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, - 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, - 0x03, 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, - 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xd7, 0x06, - 0x0a, 0x06, 0x12, 0x04, 0x05, 0x00, 0x1f, 0x01, 0x0a, 0xc9, 0x02, 0x0a, 0x01, 0x0c, 0x12, 0x03, - 0x05, 0x00, 0x12, 0x1a, 0xbe, 0x02, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x20, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, - 0x74, 0x6f, 0x20, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, 0x73, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x72, 0x27, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, - 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, - 0x20, 0x54, 0x68, 0x65, 0x79, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, - 0x6e, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, - 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, - 0x6e, 0x74, 0x73, 0x0a, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, - 0x65, 0x6d, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x69, 0x73, - 0x68, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x0a, - 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x73, - 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, - 0x6e, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, - 0x6f, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x0a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, - 0x6d, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, - 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x07, 0x00, 0x1e, 0x0a, 0x09, - 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x09, 0x00, 0x2b, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, - 0x0b, 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x0b, 0x00, 0x43, 0x0a, 0x5a, - 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x10, 0x00, 0x12, 0x01, 0x1a, 0x4e, 0x20, 0x4c, 0x45, 0x47, - 0x41, 0x43, 0x59, 0x3a, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x62, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x56, 0x31, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x2e, 0x0a, 0x20, 0x54, 0x68, 0x65, 0x20, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x62, - 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, - 0x01, 0x12, 0x03, 0x10, 0x08, 0x17, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, - 0x11, 0x02, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x11, 0x02, - 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x11, 0x12, 0x1c, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x11, 0x1f, 0x20, 0x0a, 0x38, 0x0a, - 0x02, 0x04, 0x01, 0x12, 0x04, 0x15, 0x00, 0x17, 0x01, 0x1a, 0x2c, 0x20, 0x55, 0x73, 0x65, 0x72, - 0x20, 0x6b, 0x65, 0x79, 0x20, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x56, 0x32, 0x20, 0x75, - 0x73, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x4b, 0x65, 0x79, 0x73, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, - 0x15, 0x08, 0x17, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x16, 0x02, 0x27, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x16, 0x02, 0x17, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x16, 0x18, 0x22, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x16, 0x25, 0x26, 0x0a, 0x25, 0x0a, 0x02, 0x04, 0x02, - 0x12, 0x04, 0x1a, 0x00, 0x1f, 0x01, 0x1a, 0x19, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x64, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x1a, 0x08, 0x15, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x02, 0x08, 0x00, 0x12, 0x04, 0x1b, 0x02, 0x1e, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x08, 0x00, 0x01, 0x12, 0x03, 0x1b, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, - 0x00, 0x12, 0x03, 0x1c, 0x04, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, - 0x03, 0x1c, 0x04, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x1c, - 0x14, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x1c, 0x19, 0x1a, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x1d, 0x04, 0x1b, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x1d, 0x04, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x1d, 0x14, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, - 0x01, 0x03, 0x12, 0x03, 0x1d, 0x19, 0x1a, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, - 0xe8, 0x04, 0x0a, 0x1c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x65, 0x63, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2b, 0x0a, 0x0c, 0x45, 0x63, 0x69, 0x65, 0x73, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, 0x09, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x42, 0xc6, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x42, 0x0a, 0x45, 0x63, 0x69, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, - 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, - 0x03, 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, - 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xb2, 0x02, - 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x0e, 0x01, 0x0a, 0x31, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, - 0x00, 0x12, 0x1a, 0x27, 0x20, 0x45, 0x43, 0x49, 0x45, 0x53, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, - 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x45, 0x43, 0x49, 0x45, - 0x53, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, - 0x12, 0x03, 0x03, 0x00, 0x1e, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x05, 0x00, 0x43, 0x0a, - 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, 0x43, 0x0a, 0x44, 0x0a, 0x02, 0x04, 0x00, - 0x12, 0x04, 0x09, 0x00, 0x0e, 0x01, 0x1a, 0x38, 0x20, 0x45, 0x63, 0x69, 0x65, 0x73, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, - 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x45, 0x43, 0x49, 0x45, 0x53, 0x20, 0x65, 0x6e, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x09, 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x00, 0x08, 0x00, 0x12, 0x04, 0x0a, 0x02, 0x0d, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x08, 0x00, 0x01, 0x12, 0x03, 0x0a, 0x08, 0x0f, 0x0a, 0x3e, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, - 0x12, 0x03, 0x0c, 0x04, 0x11, 0x1a, 0x31, 0x20, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x45, 0x43, 0x49, 0x45, 0x53, 0x20, - 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, - 0x05, 0x12, 0x03, 0x0c, 0x04, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, - 0x03, 0x0c, 0x0a, 0x0c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0c, - 0x0f, 0x10, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xd5, 0x15, 0x0a, 0x1d, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, - 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, 0x01, 0x0a, 0x0d, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x17, + 0x0a, 0x07, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x74, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x0d, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x6f, + 0x72, 0x22, 0x83, 0x03, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x55, + 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6e, 0x63, 0x6f, 0x64, + 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x66, 0x61, 0x6c, 0x6c, 0x62, + 0x61, 0x63, 0x6b, 0x88, 0x01, 0x01, 0x12, 0x49, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd6, 0x02, 0x0a, 0x0f, 0x46, 0x72, 0x61, - 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1b, 0x0a, 0x09, - 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x75, 0x74, - 0x74, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0b, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, - 0x02, 0x18, 0x01, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x44, - 0x0a, 0x1e, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1c, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x43, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x75, 0x6e, - 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x69, - 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x65, 0x78, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x22, 0xd5, 0x01, 0x0a, 0x0b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x12, 0x65, 0x0a, 0x18, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, + 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x48, + 0x01, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, + 0x01, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x66, + 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, + 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x12, 0x44, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x52, 0x15, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x64, 0x79, 0x42, 0xc7, 0x01, 0x0a, 0x19, 0x63, 0x6f, - 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0b, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, - 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, - 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, - 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x4a, 0xd4, 0x0e, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x2e, 0x01, 0x0a, 0x47, - 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x3d, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, - 0x63, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, - 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, 0x00, 0x2b, 0x0a, 0x09, 0x0a, 0x02, - 0x03, 0x01, 0x12, 0x03, 0x06, 0x00, 0x2a, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x08, 0x00, - 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x08, 0x00, 0x43, 0x0a, 0x83, 0x01, 0x0a, - 0x02, 0x04, 0x00, 0x12, 0x04, 0x0d, 0x00, 0x22, 0x01, 0x1a, 0x77, 0x20, 0x54, 0x68, 0x65, 0x20, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, - 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, - 0x65, 0x0a, 0x20, 0x60, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x60, - 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, - 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0d, 0x08, 0x17, 0x0a, 0x56, - 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x10, 0x02, 0x17, 0x1a, 0x49, 0x20, 0x54, 0x68, - 0x65, 0x20, 0x55, 0x52, 0x4c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x61, - 0x6d, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6c, 0x69, 0x63, - 0x6b, 0x65, 0x64, 0x0a, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x60, 0x70, 0x6f, 0x73, 0x74, - 0x5f, 0x75, 0x72, 0x6c, 0x60, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, - 0x03, 0x10, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x10, - 0x09, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x10, 0x15, 0x16, - 0x0a, 0x34, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x12, 0x02, 0x19, 0x1a, 0x27, 0x20, - 0x54, 0x68, 0x65, 0x20, 0x31, 0x2d, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x20, 0x62, 0x75, - 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6c, - 0x69, 0x63, 0x6b, 0x65, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, - 0x03, 0x12, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x12, - 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x12, 0x17, 0x18, - 0x0a, 0x45, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x14, 0x02, 0x2b, 0x1a, 0x38, 0x20, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x20, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, - 0x12, 0x03, 0x14, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, - 0x14, 0x09, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x14, 0x15, - 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x08, 0x12, 0x03, 0x14, 0x17, 0x2a, 0x0a, - 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x02, 0x02, 0x08, 0x03, 0x12, 0x03, 0x14, 0x18, 0x29, 0x0a, 0x8a, - 0x01, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x17, 0x02, 0x2c, 0x1a, 0x7d, 0x20, 0x41, - 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x69, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, - 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x20, 0x57, - 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x17, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x03, 0x01, 0x12, 0x03, 0x17, 0x09, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x03, - 0x12, 0x03, 0x17, 0x2a, 0x2b, 0x0a, 0x1d, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x04, 0x12, 0x03, 0x19, - 0x02, 0x1c, 0x1a, 0x10, 0x20, 0x55, 0x6e, 0x69, 0x78, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x05, 0x12, 0x03, 0x19, - 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, 0x19, 0x09, 0x17, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x03, 0x12, 0x03, 0x19, 0x1a, 0x1b, 0x0a, 0x31, - 0x0a, 0x04, 0x04, 0x00, 0x02, 0x05, 0x12, 0x03, 0x1b, 0x02, 0x18, 0x1a, 0x24, 0x20, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, - 0x74, 0x65, 0x78, 0x74, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x05, 0x12, 0x03, 0x1b, 0x02, 0x08, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x01, 0x12, 0x03, 0x1b, 0x09, 0x13, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x05, 0x03, 0x12, 0x03, 0x1b, 0x16, 0x17, 0x0a, 0x65, 0x0a, 0x04, 0x04, - 0x00, 0x02, 0x06, 0x12, 0x03, 0x1d, 0x02, 0x13, 0x1a, 0x58, 0x20, 0x41, 0x20, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, - 0x20, 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x66, 0x6f, 0x72, 0x20, 0x65, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x76, 0x69, 0x61, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, - 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, 0x29, 0x29, 0x2e, 0x20, 0x4d, 0x61, - 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x34, 0x30, 0x39, 0x36, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, - 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x06, 0x05, 0x12, 0x03, 0x1d, 0x02, 0x08, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x06, 0x01, 0x12, 0x03, 0x1d, 0x09, 0x0e, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x00, 0x02, 0x06, 0x03, 0x12, 0x03, 0x1d, 0x11, 0x12, 0x0a, 0x22, 0x0a, 0x04, - 0x04, 0x00, 0x02, 0x07, 0x12, 0x03, 0x1f, 0x02, 0x15, 0x1a, 0x15, 0x20, 0x41, 0x20, 0x30, 0x78, - 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x07, 0x05, 0x12, 0x03, 0x1f, 0x02, 0x08, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x00, 0x02, 0x07, 0x01, 0x12, 0x03, 0x1f, 0x09, 0x10, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x00, 0x02, 0x07, 0x03, 0x12, 0x03, 0x1f, 0x13, 0x14, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, - 0x02, 0x08, 0x12, 0x03, 0x21, 0x02, 0x1c, 0x1a, 0x1b, 0x20, 0x41, 0x20, 0x68, 0x61, 0x73, 0x68, - 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, 0x05, 0x12, 0x03, 0x21, - 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, 0x01, 0x12, 0x03, 0x21, 0x09, 0x17, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, 0x03, 0x12, 0x03, 0x21, 0x1a, 0x1b, 0x0a, 0x79, - 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x26, 0x00, 0x2e, 0x01, 0x1a, 0x6d, 0x20, 0x54, 0x68, 0x65, - 0x20, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74, - 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x60, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x60, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x60, - 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x60, 0x20, 0x70, 0x61, - 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, - 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, - 0x12, 0x03, 0x26, 0x08, 0x13, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x27, - 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x27, 0x02, 0x0b, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x27, 0x0c, 0x15, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x27, 0x18, 0x19, 0x0a, 0x92, 0x01, 0x0a, - 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x2a, 0x02, 0x35, 0x1a, 0x84, 0x01, 0x20, 0x54, 0x68, - 0x65, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x72, 0x2c, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, - 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x58, 0x4d, 0x54, 0x50, 0x20, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x61, 0x20, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x2a, 0x02, 0x17, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x2a, 0x18, 0x30, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x2a, 0x33, 0x34, 0x0a, 0x92, 0x01, 0x0a, 0x04, - 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x2d, 0x02, 0x18, 0x1a, 0x84, 0x01, 0x20, 0x53, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x64, 0x79, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, - 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x0a, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x20, - 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x62, 0x79, 0x74, 0x65, 0x2d, 0x70, 0x65, 0x72, 0x66, 0x65, 0x63, - 0x74, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x05, 0x12, 0x03, 0x2d, 0x02, 0x07, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x2d, 0x08, 0x13, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x2d, 0x16, 0x17, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, 0x0a, 0xb5, 0x20, 0x0a, 0x1e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x21, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, - 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0xb5, 0x01, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x56, 0x31, 0x12, 0x3e, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x06, 0x73, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x71, 0x0a, 0x09, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x56, 0x31, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x63, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x65, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0x3c, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, + 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4f, 0x4d, 0x50, + 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x4c, 0x41, 0x54, 0x45, 0x10, + 0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, + 0x5f, 0x47, 0x5a, 0x49, 0x50, 0x10, 0x01, 0x42, 0xc8, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, - 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x22, 0x46, 0x0a, 0x0f, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x32, 0x12, - 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, - 0x6f, 0x70, 0x69, 0x63, 0x22, 0xdd, 0x01, 0x0a, 0x09, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x56, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0a, 0x63, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x12, 0x24, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, - 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x48, 0x6d, 0x61, 0x63, 0x88, 0x01, 0x01, 0x12, 0x24, - 0x0a, 0x0b, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x0a, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x50, 0x75, 0x73, - 0x68, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, - 0x68, 0x6d, 0x61, 0x63, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, - 0x70, 0x75, 0x73, 0x68, 0x22, 0x7c, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x32, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, - 0x02, 0x76, 0x31, 0x12, 0x32, 0x0a, 0x02, 0x76, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, - 0x32, 0x48, 0x00, 0x52, 0x02, 0x76, 0x32, 0x42, 0x09, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x22, 0xed, 0x02, 0x0a, 0x0e, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, - 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x30, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x10, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x6e, 0x74, 0x5f, - 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x74, 0x4e, 0x73, - 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x70, 0x69, - 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x50, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x14, 0x0a, 0x12, - 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x42, 0x0c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, - 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, - 0x03, 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, - 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xf2, 0x14, - 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x4d, 0x01, 0x0a, 0x4a, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, - 0x00, 0x12, 0x1a, 0x40, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x75, 0x73, - 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, - 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x1e, 0x0a, 0x09, - 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, 0x00, 0x2b, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x01, 0x12, - 0x03, 0x06, 0x00, 0x37, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, 0x12, 0x03, 0x07, 0x00, 0x2b, 0x0a, - 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x09, 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, - 0x03, 0x09, 0x00, 0x43, 0x0a, 0x8c, 0x01, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x10, 0x00, 0x14, - 0x01, 0x1a, 0x72, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x73, 0x65, - 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x75, - 0x73, 0x65, 0x64, 0x0a, 0x20, 0x61, 0x73, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, - 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, - 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x32, 0x0c, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, - 0x56, 0x31, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x10, 0x08, 0x17, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x11, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x11, 0x02, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x02, 0x00, 0x01, 0x12, 0x03, 0x11, 0x12, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, - 0x03, 0x12, 0x03, 0x11, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, - 0x12, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x12, 0x02, - 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x12, 0x12, 0x1b, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x12, 0x1e, 0x1f, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x13, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x02, 0x02, 0x05, 0x12, 0x03, 0x13, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, - 0x01, 0x12, 0x03, 0x13, 0x09, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, - 0x03, 0x13, 0x15, 0x16, 0x0a, 0x37, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x17, 0x00, 0x1c, 0x01, - 0x1a, 0x2b, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, - 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x17, 0x08, 0x11, 0x0a, 0x33, 0x0a, 0x04, 0x04, 0x01, 0x02, - 0x00, 0x12, 0x03, 0x19, 0x02, 0x19, 0x1a, 0x26, 0x20, 0x65, 0x6e, 0x63, 0x61, 0x70, 0x73, 0x75, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x31, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x19, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x19, 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x19, 0x17, 0x18, 0x0a, 0x47, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, - 0x12, 0x03, 0x1b, 0x02, 0x1c, 0x1a, 0x3a, 0x20, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x74, 0x2e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, - 0x64, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x1b, 0x02, 0x0c, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x1b, 0x0d, 0x17, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x1b, 0x1a, 0x1b, 0x0a, 0x88, 0x02, 0x0a, 0x02, - 0x04, 0x02, 0x12, 0x04, 0x24, 0x00, 0x29, 0x01, 0x1a, 0xed, 0x01, 0x20, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x61, 0x72, 0x72, 0x69, - 0x65, 0x73, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, - 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x0a, 0x20, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x62, - 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, - 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, - 0x73, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, - 0x61, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x45, 0x41, 0x44, 0x20, 0x65, - 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, - 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x0a, 0x20, 0x74, 0x68, 0x75, 0x73, 0x20, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x61, 0x6d, 0x70, 0x65, 0x72, 0x20, 0x65, 0x76, - 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x0a, 0x32, 0x0c, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x20, 0x56, 0x32, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x24, - 0x08, 0x17, 0x0a, 0x35, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x26, 0x02, 0x18, 0x1a, - 0x28, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, - 0x00, 0x05, 0x12, 0x03, 0x26, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x26, 0x09, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x26, 0x16, 0x17, 0x0a, 0x2f, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x28, 0x02, 0x13, - 0x1a, 0x22, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x6f, 0x6e, 0x67, 0x73, - 0x20, 0x74, 0x6f, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x05, 0x12, 0x03, 0x28, - 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x28, 0x09, 0x0e, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x28, 0x11, 0x12, 0x0a, 0x4d, - 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x2c, 0x00, 0x37, 0x01, 0x1a, 0x41, 0x20, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x65, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, - 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x2c, 0x08, 0x11, 0x0a, 0x33, 0x0a, 0x04, 0x04, 0x03, 0x02, - 0x00, 0x12, 0x03, 0x2e, 0x02, 0x19, 0x1a, 0x26, 0x20, 0x65, 0x6e, 0x63, 0x61, 0x70, 0x73, 0x75, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x32, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2e, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2e, 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x2e, 0x17, 0x18, 0x0a, 0x46, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, - 0x12, 0x03, 0x30, 0x02, 0x1c, 0x1a, 0x39, 0x20, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x74, 0x2e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, - 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x06, 0x12, 0x03, 0x30, 0x02, 0x0c, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, 0x03, 0x30, 0x0d, 0x17, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x03, 0x02, 0x01, 0x03, 0x12, 0x03, 0x30, 0x1a, 0x1b, 0x0a, 0x5c, 0x0a, 0x04, 0x04, 0x03, - 0x02, 0x02, 0x12, 0x03, 0x33, 0x02, 0x21, 0x1a, 0x4f, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6f, - 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x64, 0x65, 0x72, 0x69, - 0x76, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, - 0x69, 0x63, 0x0a, 0x20, 0x6b, 0x65, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, - 0x04, 0x12, 0x03, 0x33, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x05, 0x12, - 0x03, 0x33, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x01, 0x12, 0x03, 0x33, - 0x11, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x12, 0x03, 0x33, 0x1f, 0x20, - 0x0a, 0x5f, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x03, 0x12, 0x03, 0x36, 0x02, 0x20, 0x1a, 0x52, 0x20, - 0x46, 0x6c, 0x61, 0x67, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, - 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x70, 0x75, - 0x73, 0x68, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x6e, 0x6f, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x03, 0x04, 0x12, 0x03, 0x36, 0x02, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x03, 0x05, 0x12, 0x03, 0x36, 0x0b, 0x0f, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x03, 0x02, 0x03, 0x01, 0x12, 0x03, 0x36, 0x10, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x03, 0x02, 0x03, 0x03, 0x12, 0x03, 0x36, 0x1e, 0x1f, 0x0a, 0x1f, 0x0a, 0x02, 0x04, 0x04, 0x12, - 0x04, 0x3a, 0x00, 0x3f, 0x01, 0x1a, 0x13, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, - 0x64, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, - 0x01, 0x12, 0x03, 0x3a, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x04, 0x08, 0x00, 0x12, 0x04, - 0x3b, 0x02, 0x3e, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x08, 0x00, 0x01, 0x12, 0x03, 0x3b, - 0x08, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x3c, 0x04, 0x15, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x06, 0x12, 0x03, 0x3c, 0x04, 0x0d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x3c, 0x0e, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3c, 0x13, 0x14, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, - 0x01, 0x12, 0x03, 0x3d, 0x04, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x06, 0x12, - 0x03, 0x3d, 0x04, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x3d, - 0x0e, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x3d, 0x13, 0x14, - 0x0a, 0xae, 0x01, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x44, 0x00, 0x4d, 0x01, 0x1a, 0xa1, 0x01, - 0x20, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, - 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, - 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x0a, 0x20, 0x44, 0x65, 0x63, 0x6f, - 0x64, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x0a, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, - 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, - 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, 0x44, 0x08, 0x16, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x45, 0x02, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, - 0x02, 0x00, 0x05, 0x12, 0x03, 0x45, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x45, 0x09, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, - 0x03, 0x45, 0x0e, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x01, 0x12, 0x03, 0x46, 0x02, - 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x05, 0x12, 0x03, 0x46, 0x02, 0x08, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x01, 0x12, 0x03, 0x46, 0x09, 0x18, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x05, 0x02, 0x01, 0x03, 0x12, 0x03, 0x46, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x05, 0x02, 0x02, 0x12, 0x03, 0x47, 0x02, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x02, - 0x05, 0x12, 0x03, 0x47, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x47, 0x09, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x02, 0x03, 0x12, 0x03, 0x47, - 0x1a, 0x1b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x03, 0x12, 0x03, 0x48, 0x02, 0x28, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x03, 0x04, 0x12, 0x03, 0x48, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x05, 0x02, 0x03, 0x05, 0x12, 0x03, 0x48, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x05, 0x02, 0x03, 0x01, 0x12, 0x03, 0x48, 0x12, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, - 0x03, 0x03, 0x12, 0x03, 0x48, 0x26, 0x27, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x04, 0x12, - 0x03, 0x49, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x04, 0x05, 0x12, 0x03, 0x49, - 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x04, 0x01, 0x12, 0x03, 0x49, 0x09, 0x10, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x04, 0x03, 0x12, 0x03, 0x49, 0x13, 0x14, 0x0a, 0x0b, - 0x0a, 0x04, 0x04, 0x05, 0x02, 0x05, 0x12, 0x03, 0x4a, 0x02, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x05, 0x02, 0x05, 0x05, 0x12, 0x03, 0x4a, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, - 0x05, 0x01, 0x12, 0x03, 0x4a, 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x05, 0x03, - 0x12, 0x03, 0x4a, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x06, 0x12, 0x03, 0x4b, - 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x06, 0x06, 0x12, 0x03, 0x4b, 0x02, 0x17, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x06, 0x01, 0x12, 0x03, 0x4b, 0x18, 0x24, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x05, 0x02, 0x06, 0x03, 0x12, 0x03, 0x4b, 0x27, 0x28, 0x0a, 0x2a, 0x0a, 0x04, - 0x04, 0x05, 0x02, 0x07, 0x12, 0x03, 0x4c, 0x02, 0x1a, 0x22, 0x1d, 0x20, 0x65, 0x6e, 0x63, 0x61, - 0x70, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x07, - 0x05, 0x12, 0x03, 0x4c, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x07, 0x01, 0x12, - 0x03, 0x4c, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x07, 0x03, 0x12, 0x03, 0x4c, - 0x18, 0x19, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xf3, 0x19, 0x0a, 0x2a, 0x6d, + 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, + 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, + 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, + 0xca, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, + 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x4a, 0xfd, 0x0f, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x36, 0x01, 0x0a, 0x2f, 0x0a, + 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x25, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, + 0x6e, 0x67, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x0a, 0x0a, 0x08, + 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, + 0x05, 0x00, 0x2b, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x01, 0x12, 0x03, 0x06, 0x00, 0x2a, 0x0a, 0x08, + 0x0a, 0x01, 0x08, 0x12, 0x03, 0x08, 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, + 0x08, 0x00, 0x43, 0x0a, 0x58, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0c, 0x00, 0x11, 0x01, 0x1a, + 0x4c, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x20, + 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x69, + 0x6e, 0x20, 0x61, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0c, 0x08, 0x15, 0x0a, 0x34, 0x0a, 0x04, 0x04, 0x00, 0x02, + 0x00, 0x12, 0x03, 0x0d, 0x02, 0x1a, 0x22, 0x27, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, + 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0d, 0x09, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0d, 0x18, 0x19, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x00, 0x02, + 0x01, 0x12, 0x03, 0x0e, 0x02, 0x15, 0x22, 0x11, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x01, 0x05, 0x12, 0x03, 0x0e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, + 0x12, 0x03, 0x0e, 0x09, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, + 0x0e, 0x13, 0x14, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0f, 0x02, 0x1b, + 0x22, 0x1b, 0x20, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x0f, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x0f, 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x02, 0x03, 0x12, 0x03, 0x0f, 0x19, 0x1a, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, + 0x03, 0x10, 0x02, 0x1b, 0x22, 0x1b, 0x20, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x10, 0x02, 0x08, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x10, 0x09, 0x16, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x10, 0x19, 0x1a, 0x0a, 0x67, 0x0a, 0x02, 0x05, + 0x00, 0x12, 0x04, 0x15, 0x00, 0x18, 0x01, 0x1a, 0x5b, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, + 0x69, 0x7a, 0x65, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x0a, 0x20, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x6c, 0x69, 0x6e, 0x74, 0x3a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x45, + 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x5f, + 0x5a, 0x45, 0x52, 0x4f, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x45, 0x4e, 0x44, 0x5f, 0x57, + 0x49, 0x54, 0x48, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, 0x01, 0x12, 0x03, 0x15, 0x05, 0x10, + 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, 0x16, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, + 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x16, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x05, + 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x16, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, + 0x01, 0x12, 0x03, 0x17, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, + 0x03, 0x17, 0x02, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x17, + 0x15, 0x16, 0x0a, 0xa3, 0x01, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x1d, 0x00, 0x2b, 0x01, 0x1a, + 0x96, 0x01, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x20, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x20, + 0x69, 0x74, 0x73, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x64, 0x65, + 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, + 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, + 0x03, 0x1d, 0x08, 0x16, 0x0a, 0x65, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x20, 0x02, + 0x19, 0x1a, 0x58, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x64, + 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, + 0x20, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x20, 0x02, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x00, 0x01, 0x12, 0x03, 0x20, 0x10, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, + 0x12, 0x03, 0x20, 0x17, 0x18, 0x0a, 0x54, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x22, + 0x02, 0x25, 0x1a, 0x47, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x65, 0x6e, + 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, + 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x22, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x01, 0x01, 0x12, 0x03, 0x22, 0x16, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, + 0x12, 0x03, 0x22, 0x23, 0x24, 0x0a, 0x84, 0x01, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, + 0x25, 0x02, 0x1f, 0x1a, 0x77, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, + 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, + 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x0a, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x64, + 0x65, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x01, 0x02, 0x02, 0x04, 0x12, 0x03, 0x25, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, + 0x02, 0x02, 0x05, 0x12, 0x03, 0x25, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, + 0x01, 0x12, 0x03, 0x25, 0x12, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, + 0x03, 0x25, 0x1d, 0x1e, 0x0a, 0x6e, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x28, 0x02, + 0x27, 0x1a, 0x61, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6d, + 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6c, + 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x0a, + 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, + 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x79, + 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x04, 0x12, 0x03, 0x28, + 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x06, 0x12, 0x03, 0x28, 0x0b, 0x16, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x01, 0x12, 0x03, 0x28, 0x17, 0x22, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x03, 0x12, 0x03, 0x28, 0x25, 0x26, 0x0a, 0x25, 0x0a, 0x04, + 0x04, 0x01, 0x02, 0x04, 0x12, 0x03, 0x2a, 0x02, 0x14, 0x1a, 0x18, 0x20, 0x65, 0x6e, 0x63, 0x6f, + 0x64, 0x65, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x73, 0x65, + 0x6c, 0x66, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x05, 0x12, 0x03, 0x2a, 0x02, + 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x01, 0x12, 0x03, 0x2a, 0x08, 0x0f, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x03, 0x12, 0x03, 0x2a, 0x12, 0x13, 0x0a, 0x43, 0x0a, + 0x02, 0x04, 0x02, 0x12, 0x04, 0x2e, 0x00, 0x36, 0x01, 0x1a, 0x37, 0x20, 0x53, 0x69, 0x67, 0x6e, + 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, + 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, + 0x6f, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x2e, 0x08, 0x15, 0x0a, 0x2a, + 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x30, 0x02, 0x14, 0x1a, 0x1d, 0x20, 0x4d, 0x55, + 0x53, 0x54, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, + 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x00, 0x05, 0x12, 0x03, 0x30, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, + 0x01, 0x12, 0x03, 0x30, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, + 0x03, 0x30, 0x12, 0x13, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x31, 0x02, + 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x31, 0x02, 0x17, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x31, 0x18, 0x1e, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x31, 0x21, 0x22, 0x0a, 0x8a, 0x01, 0x0a, 0x04, + 0x04, 0x02, 0x02, 0x02, 0x12, 0x03, 0x35, 0x02, 0x1a, 0x1a, 0x7d, 0x20, 0x4d, 0x55, 0x53, 0x54, + 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, + 0x6f, 0x66, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x73, 0x2c, 0x0a, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, + 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x27, 0x73, 0x20, 0x70, + 0x72, 0x65, 0x2d, 0x6b, 0x65, 0x79, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, + 0x06, 0x12, 0x03, 0x35, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, + 0x03, 0x35, 0x0c, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x35, + 0x18, 0x19, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xf3, 0x07, 0x0a, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, - 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x1e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdb, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6d, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x52, 0x05, 0x70, 0x61, 0x72, 0x74, + 0x73, 0x1a, 0x90, 0x01, 0x0a, 0x04, 0x50, 0x61, 0x72, 0x74, 0x12, 0x3b, 0x0a, 0x04, 0x70, 0x61, + 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x2f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x07, 0x0a, 0x18, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x63, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x60, 0x0a, 0x0c, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6e, - 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x6e, 0x79, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x5d, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x6c, - 0x6c, 0x6f, 0x77, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x5a, 0x0a, 0x0a, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x78, 0x6d, 0x74, + 0x2e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x04, 0x70, 0x61, 0x72, 0x74, 0x12, 0x40, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x44, 0x65, 0x6e, 0x79, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x48, 0x00, 0x52, 0x09, 0x64, 0x65, 0x6e, 0x79, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x12, 0x64, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x62, 0x6f, - 0x78, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x78, 0x6d, 0x74, + 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x48, 0x00, 0x52, 0x09, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x65, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x42, 0xca, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, - 0x77, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, - 0x77, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x61, 0x0a, 0x0d, 0x64, 0x65, 0x6e, 0x79, - 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x44, 0x65, 0x6e, 0x79, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x48, 0x00, 0x52, 0x0b, - 0x64, 0x65, 0x6e, 0x79, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x1a, 0x39, 0x0a, 0x0c, 0x41, - 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x77, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x38, 0x0a, 0x0b, 0x44, 0x65, 0x6e, 0x79, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, - 0x1a, 0x2b, 0x0a, 0x0c, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x1a, 0x2a, 0x0a, - 0x0b, 0x44, 0x65, 0x6e, 0x79, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, - 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x1a, 0x29, 0x0a, 0x0a, 0x41, 0x6c, 0x6c, - 0x6f, 0x77, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x49, 0x64, 0x73, 0x1a, 0x28, 0x0a, 0x09, 0x44, 0x65, 0x6e, 0x79, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x73, 0x42, 0x0e, - 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x5b, - 0x0a, 0x19, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x73, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x0a, 0x02, 0x76, - 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, - 0x42, 0x09, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0xd3, 0x01, 0x0a, 0x19, - 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x17, 0x50, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x50, 0x72, 0x6f, + 0x74, 0x73, 0x42, 0x0e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, @@ -2917,130 +2445,602 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x4a, 0xb4, 0x0f, 0x0a, 0x06, 0x12, 0x04, 0x04, 0x00, 0x42, 0x01, 0x0a, 0x99, 0x01, 0x0a, - 0x01, 0x0c, 0x12, 0x03, 0x04, 0x00, 0x12, 0x1a, 0x8e, 0x01, 0x20, 0x50, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0a, 0x0a, - 0x20, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, - 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x2c, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, - 0x79, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x61, 0x0a, 0x20, 0x77, 0x61, 0x79, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x72, - 0x69, 0x76, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, - 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x06, - 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x08, 0x00, 0x2b, 0x0a, 0x08, 0x0a, - 0x01, 0x08, 0x12, 0x03, 0x0a, 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x0a, - 0x00, 0x43, 0x0a, 0x62, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0f, 0x00, 0x3d, 0x01, 0x1a, 0x56, - 0x20, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x27, 0x73, 0x20, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x0a, 0x20, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0f, - 0x08, 0x20, 0x0a, 0x34, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x00, 0x12, 0x04, 0x11, 0x02, 0x14, 0x03, - 0x1a, 0x26, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x31, 0x3a, 0x31, 0x20, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x28, 0x44, 0x4d, 0x29, - 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x00, - 0x01, 0x12, 0x03, 0x11, 0x0a, 0x16, 0x0a, 0x41, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, - 0x12, 0x03, 0x13, 0x04, 0x29, 0x1a, 0x32, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, - 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, 0x13, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, - 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x13, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, - 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x13, 0x14, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, - 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x13, 0x27, 0x28, 0x0a, 0x3b, 0x0a, 0x04, 0x04, 0x00, 0x03, - 0x01, 0x12, 0x04, 0x17, 0x02, 0x1a, 0x03, 0x1a, 0x2d, 0x20, 0x44, 0x65, 0x6e, 0x79, 0x20, 0x28, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x20, 0x31, 0x3a, 0x31, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x28, 0x44, 0x4d, 0x29, 0x20, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x01, 0x01, 0x12, - 0x03, 0x17, 0x0a, 0x15, 0x0a, 0x40, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, - 0x19, 0x04, 0x29, 0x1a, 0x31, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, - 0x76, 0x65, 0x6e, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x6e, 0x79, - 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, - 0x04, 0x12, 0x03, 0x19, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, - 0x05, 0x12, 0x03, 0x19, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x19, 0x14, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x01, 0x02, 0x00, - 0x03, 0x12, 0x03, 0x19, 0x27, 0x28, 0x0a, 0x37, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x02, 0x12, 0x04, - 0x1d, 0x02, 0x20, 0x03, 0x1a, 0x29, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x56, 0x33, 0x20, - 0x31, 0x3a, 0x31, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x20, 0x28, 0x44, 0x4d, 0x29, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x02, 0x01, 0x12, 0x03, 0x1d, 0x0a, 0x16, 0x0a, 0x39, 0x0a, - 0x06, 0x04, 0x00, 0x03, 0x02, 0x02, 0x00, 0x12, 0x03, 0x1f, 0x04, 0x22, 0x1a, 0x2a, 0x20, 0x41, - 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x62, - 0x6f, 0x78, 0x20, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x02, - 0x02, 0x00, 0x04, 0x12, 0x03, 0x1f, 0x04, 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x02, - 0x02, 0x00, 0x05, 0x12, 0x03, 0x1f, 0x0d, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x02, - 0x02, 0x00, 0x01, 0x12, 0x03, 0x1f, 0x14, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x02, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x1f, 0x20, 0x21, 0x0a, 0x3e, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x03, - 0x12, 0x04, 0x23, 0x02, 0x26, 0x03, 0x1a, 0x30, 0x20, 0x44, 0x65, 0x6e, 0x79, 0x20, 0x28, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x20, 0x56, 0x33, 0x20, 0x31, 0x3a, 0x31, 0x20, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x28, 0x44, 0x4d, 0x29, - 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x03, - 0x01, 0x12, 0x03, 0x23, 0x0a, 0x15, 0x0a, 0x38, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x03, 0x02, 0x00, - 0x12, 0x03, 0x25, 0x04, 0x22, 0x1a, 0x29, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x20, 0x69, 0x64, 0x20, 0x74, - 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x03, 0x02, 0x00, 0x04, 0x12, 0x03, 0x25, 0x04, 0x0c, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x03, 0x02, 0x00, 0x05, 0x12, 0x03, 0x25, 0x0d, 0x13, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x25, 0x14, 0x1d, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x25, 0x20, 0x21, - 0x0a, 0x22, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x04, 0x12, 0x04, 0x2a, 0x02, 0x2d, 0x03, 0x1a, 0x14, - 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x04, 0x01, 0x12, 0x03, 0x2a, - 0x0a, 0x14, 0x0a, 0x3a, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x12, 0x03, 0x2c, 0x04, - 0x22, 0x1a, 0x2b, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, - 0x6e, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x0a, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x04, 0x12, 0x03, 0x2c, 0x04, 0x0c, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2c, 0x0d, 0x13, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2c, 0x14, 0x1d, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x00, 0x03, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2c, 0x20, 0x21, 0x0a, 0x28, - 0x0a, 0x04, 0x04, 0x00, 0x03, 0x05, 0x12, 0x04, 0x30, 0x02, 0x33, 0x03, 0x1a, 0x1a, 0x20, 0x44, - 0x65, 0x6e, 0x79, 0x20, 0x28, 0x64, 0x65, 0x6e, 0x79, 0x29, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x05, - 0x01, 0x12, 0x03, 0x30, 0x0a, 0x13, 0x0a, 0x39, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, - 0x12, 0x03, 0x32, 0x04, 0x22, 0x1a, 0x2a, 0x20, 0x41, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x20, - 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x73, 0x74, - 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x04, 0x12, 0x03, 0x32, 0x04, - 0x0c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x05, 0x12, 0x03, 0x32, 0x0d, - 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x32, 0x14, - 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x32, 0x20, - 0x21, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x08, 0x00, 0x12, 0x04, 0x35, 0x02, 0x3c, 0x03, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x08, 0x00, 0x01, 0x12, 0x03, 0x35, 0x08, 0x14, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x36, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x02, 0x00, 0x06, 0x12, 0x03, 0x36, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x36, 0x11, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, - 0x03, 0x36, 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x37, 0x04, - 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x37, 0x04, 0x0f, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x37, 0x10, 0x1c, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x37, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x00, 0x02, 0x02, 0x12, 0x03, 0x38, 0x04, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, - 0x06, 0x12, 0x03, 0x38, 0x04, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x38, 0x0f, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x38, - 0x1d, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x39, 0x04, 0x1d, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x06, 0x12, 0x03, 0x39, 0x04, 0x0d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x39, 0x0e, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x39, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, - 0x04, 0x12, 0x03, 0x3a, 0x04, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x06, 0x12, - 0x03, 0x3a, 0x04, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, 0x3a, - 0x11, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x03, 0x12, 0x03, 0x3a, 0x22, 0x23, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x05, 0x12, 0x03, 0x3b, 0x04, 0x22, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x05, 0x06, 0x12, 0x03, 0x3b, 0x04, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x05, 0x01, 0x12, 0x03, 0x3b, 0x10, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x05, 0x03, 0x12, 0x03, 0x3b, 0x20, 0x21, 0x0a, 0x31, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x40, - 0x00, 0x42, 0x01, 0x1a, 0x25, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x65, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x72, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, - 0x01, 0x12, 0x03, 0x40, 0x08, 0x21, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x08, 0x00, 0x12, 0x03, - 0x41, 0x02, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x08, 0x00, 0x01, 0x12, 0x03, 0x41, 0x08, - 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x41, 0x12, 0x24, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x41, 0x12, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x41, 0x1d, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x41, 0x22, 0x23, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x4a, 0xe4, 0x03, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x15, 0x01, 0x0a, 0x21, 0x0a, 0x01, + 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x17, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x0a, 0x0a, + 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, + 0x03, 0x05, 0x00, 0x28, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x07, 0x00, 0x43, 0x0a, 0x09, + 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x07, 0x00, 0x43, 0x0a, 0x4c, 0x0a, 0x02, 0x04, 0x00, 0x12, + 0x04, 0x0b, 0x00, 0x15, 0x01, 0x1a, 0x40, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x65, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6f, 0x72, 0x67, 0x2f, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, + 0x0b, 0x08, 0x11, 0x0a, 0x42, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x00, 0x12, 0x04, 0x0d, 0x02, 0x12, + 0x03, 0x1a, 0x34, 0x20, 0x50, 0x61, 0x72, 0x74, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, + 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x6f, 0x66, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x00, 0x01, + 0x12, 0x03, 0x0d, 0x0a, 0x0e, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x12, + 0x04, 0x0e, 0x04, 0x11, 0x05, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, + 0x12, 0x03, 0x0e, 0x0a, 0x11, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x12, + 0x03, 0x0f, 0x06, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, + 0x03, 0x0f, 0x06, 0x14, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x0f, 0x15, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, + 0x03, 0x0f, 0x1c, 0x1d, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, + 0x10, 0x06, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, + 0x10, 0x06, 0x0f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, + 0x10, 0x10, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, + 0x10, 0x1c, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x14, 0x02, 0x1a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, 0x14, 0x02, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x14, 0x0b, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x14, 0x10, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x14, 0x18, 0x19, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0xd2, 0x0b, 0x0a, 0x1e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x58, 0x0a, + 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x31, + 0x12, 0x45, 0x0a, 0x0a, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x09, 0x6b, 0x65, + 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x5e, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x63, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x32, 0x12, 0x4b, 0x0a, 0x0a, 0x6b, 0x65, + 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x09, 0x6b, 0x65, + 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x63, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x38, 0x0a, 0x02, 0x76, 0x31, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x63, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, + 0x02, 0x76, 0x31, 0x12, 0x38, 0x0a, 0x02, 0x76, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x42, + 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, 0x02, 0x76, 0x32, 0x42, 0x09, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0xc8, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, + 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, + 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, + 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x4a, 0xd7, 0x06, 0x0a, 0x06, 0x12, 0x04, 0x05, 0x00, 0x1f, 0x01, 0x0a, 0xc9, + 0x02, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x05, 0x00, 0x12, 0x1a, 0xbe, 0x02, 0x20, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x63, 0x74, 0x20, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, + 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x76, 0x65, 0x72, 0x74, 0x69, + 0x73, 0x65, 0x20, 0x75, 0x73, 0x65, 0x72, 0x27, 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x0a, 0x20, 0x54, 0x68, 0x65, 0x79, 0x20, 0x61, 0x72, 0x65, 0x20, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x65, 0x6c, + 0x6c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x73, 0x20, 0x73, + 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x70, 0x61, 0x72, + 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x0a, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x66, + 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, + 0x65, 0x79, 0x20, 0x77, 0x69, 0x73, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, + 0x6e, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x0a, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, + 0x74, 0x6f, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x20, 0x65, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x0a, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x2d, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2c, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x69, 0x6e, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, + 0x03, 0x07, 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x09, 0x00, 0x2b, 0x0a, + 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x0b, 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, + 0x03, 0x0b, 0x00, 0x43, 0x0a, 0x5a, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x10, 0x00, 0x12, 0x01, + 0x1a, 0x4e, 0x20, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x3a, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, + 0x6b, 0x65, 0x79, 0x20, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x56, 0x31, 0x20, 0x75, 0x73, + 0x69, 0x6e, 0x67, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x2e, 0x0a, + 0x20, 0x54, 0x68, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x20, + 0x4d, 0x55, 0x53, 0x54, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x10, 0x08, 0x17, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x11, 0x02, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x00, 0x06, 0x12, 0x03, 0x11, 0x02, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, + 0x12, 0x03, 0x11, 0x12, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x11, 0x1f, 0x20, 0x0a, 0x38, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x15, 0x00, 0x17, 0x01, 0x1a, + 0x2c, 0x20, 0x55, 0x73, 0x65, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x62, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x20, 0x56, 0x32, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x73, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x15, 0x08, 0x17, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, + 0x00, 0x12, 0x03, 0x16, 0x02, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, + 0x03, 0x16, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x16, + 0x18, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x16, 0x25, 0x26, + 0x0a, 0x25, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x1a, 0x00, 0x1f, 0x01, 0x1a, 0x19, 0x20, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, + 0x1a, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x02, 0x08, 0x00, 0x12, 0x04, 0x1b, 0x02, 0x1e, + 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x08, 0x00, 0x01, 0x12, 0x03, 0x1b, 0x08, 0x0f, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x1c, 0x04, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x1c, 0x04, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x1c, 0x14, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x1c, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, + 0x1d, 0x04, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x1d, 0x04, + 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x1d, 0x14, 0x16, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x1d, 0x19, 0x1a, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xe8, 0x04, 0x0a, 0x1c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x65, 0x63, 0x69, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2b, 0x0a, + 0x0c, 0x45, 0x63, 0x69, 0x65, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, + 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x42, + 0x09, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0xc6, 0x01, 0x0a, 0x19, 0x63, + 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0a, 0x45, 0x63, 0x69, 0x65, 0x73, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, + 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, + 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, + 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x4a, 0xb2, 0x02, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x0e, 0x01, 0x0a, 0x31, + 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x27, 0x20, 0x45, 0x43, 0x49, 0x45, 0x53, + 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x45, 0x43, 0x49, 0x45, 0x53, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, + 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x1e, 0x0a, 0x08, 0x0a, 0x01, 0x08, + 0x12, 0x03, 0x05, 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x05, 0x00, 0x43, + 0x0a, 0x44, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x09, 0x00, 0x0e, 0x01, 0x1a, 0x38, 0x20, 0x45, + 0x63, 0x69, 0x65, 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, + 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x45, 0x43, 0x49, + 0x45, 0x53, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x09, + 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x08, 0x00, 0x12, 0x04, 0x0a, 0x02, 0x0d, 0x03, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x08, 0x00, 0x01, 0x12, 0x03, 0x0a, 0x08, 0x0f, 0x0a, 0x3e, + 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0c, 0x04, 0x11, 0x1a, 0x31, 0x20, 0x45, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, + 0x45, 0x43, 0x49, 0x45, 0x53, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0c, 0x04, 0x09, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0c, 0x0a, 0x0c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x0c, 0x0f, 0x10, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0xd5, 0x15, 0x0a, 0x1d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd6, + 0x02, 0x0a, 0x0f, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x55, 0x72, 0x6c, 0x12, + 0x21, 0x0a, 0x0c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x12, 0x20, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x12, 0x44, 0x0a, 0x1e, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1c, 0x6f, 0x70, + 0x61, 0x71, 0x75, 0x65, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, + 0x69, 0x78, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0d, 0x75, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x65, 0x78, 0x74, + 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xd5, 0x01, 0x0a, 0x0b, 0x46, 0x72, 0x61, 0x6d, + 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x65, 0x0a, 0x18, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, + 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x15, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x64, 0x79, 0x42, + 0xc7, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0b, 0x46, + 0x72, 0x61, 0x6d, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x58, + 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, + 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xd4, 0x0e, 0x0a, 0x06, 0x12, 0x04, + 0x01, 0x00, 0x2e, 0x01, 0x0a, 0x47, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x3d, + 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, + 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, + 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x08, 0x0a, + 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, + 0x00, 0x2b, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x01, 0x12, 0x03, 0x06, 0x00, 0x2a, 0x0a, 0x08, 0x0a, + 0x01, 0x08, 0x12, 0x03, 0x08, 0x00, 0x43, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x08, + 0x00, 0x43, 0x0a, 0x83, 0x01, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0d, 0x00, 0x22, 0x01, 0x1a, + 0x77, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x74, 0x68, + 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x73, + 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x60, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x60, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, + 0x03, 0x0d, 0x08, 0x17, 0x0a, 0x56, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x10, 0x02, + 0x17, 0x1a, 0x49, 0x20, 0x54, 0x68, 0x65, 0x20, 0x55, 0x52, 0x4c, 0x20, 0x6f, 0x66, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, + 0x73, 0x20, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x0a, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x62, + 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, + 0x20, 0x60, 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x60, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x10, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x10, 0x09, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x10, 0x15, 0x16, 0x0a, 0x34, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, + 0x12, 0x02, 0x19, 0x1a, 0x27, 0x20, 0x54, 0x68, 0x65, 0x20, 0x31, 0x2d, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x65, 0x64, 0x20, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, + 0x77, 0x61, 0x73, 0x20, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x12, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x12, 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x12, 0x17, 0x18, 0x0a, 0x45, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, + 0x14, 0x02, 0x2b, 0x1a, 0x38, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20, + 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x20, 0x69, 0x6e, 0x20, + 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x20, 0x73, 0x69, 0x6e, + 0x63, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x0a, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x14, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x14, 0x09, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x02, 0x03, 0x12, 0x03, 0x14, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x08, + 0x12, 0x03, 0x14, 0x17, 0x2a, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x02, 0x02, 0x08, 0x03, 0x12, + 0x03, 0x14, 0x18, 0x29, 0x0a, 0x8a, 0x01, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x17, + 0x02, 0x2c, 0x1a, 0x7d, 0x20, 0x41, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x74, 0x69, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, + 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x2e, 0x20, 0x57, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x61, + 0x74, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x20, 0x6f, 0x72, + 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x17, 0x02, 0x08, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x17, 0x09, 0x27, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x17, 0x2a, 0x2b, 0x0a, 0x1d, 0x0a, 0x04, 0x04, + 0x00, 0x02, 0x04, 0x12, 0x03, 0x19, 0x02, 0x1c, 0x1a, 0x10, 0x20, 0x55, 0x6e, 0x69, 0x78, 0x20, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x04, 0x05, 0x12, 0x03, 0x19, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, + 0x01, 0x12, 0x03, 0x19, 0x09, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x03, 0x12, + 0x03, 0x19, 0x1a, 0x1b, 0x0a, 0x31, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x05, 0x12, 0x03, 0x1b, 0x02, + 0x18, 0x1a, 0x24, 0x20, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x66, + 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x05, + 0x12, 0x03, 0x1b, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x01, 0x12, 0x03, + 0x1b, 0x09, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x05, 0x03, 0x12, 0x03, 0x1b, 0x16, + 0x17, 0x0a, 0x65, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x06, 0x12, 0x03, 0x1d, 0x02, 0x13, 0x1a, 0x58, + 0x20, 0x41, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, + 0x28, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x76, 0x69, 0x61, + 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66, 0x79, 0x28, + 0x29, 0x29, 0x2e, 0x20, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x20, 0x34, 0x30, 0x39, 0x36, + 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x06, + 0x05, 0x12, 0x03, 0x1d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x06, 0x01, 0x12, + 0x03, 0x1d, 0x09, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x06, 0x03, 0x12, 0x03, 0x1d, + 0x11, 0x12, 0x0a, 0x22, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x07, 0x12, 0x03, 0x1f, 0x02, 0x15, 0x1a, + 0x15, 0x20, 0x41, 0x20, 0x30, 0x78, 0x20, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x07, 0x05, 0x12, + 0x03, 0x1f, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x07, 0x01, 0x12, 0x03, 0x1f, + 0x09, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x07, 0x03, 0x12, 0x03, 0x1f, 0x13, 0x14, + 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x08, 0x12, 0x03, 0x21, 0x02, 0x1c, 0x1a, 0x1b, 0x20, + 0x41, 0x20, 0x68, 0x61, 0x73, 0x68, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x08, 0x05, 0x12, 0x03, 0x21, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, + 0x01, 0x12, 0x03, 0x21, 0x09, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x08, 0x03, 0x12, + 0x03, 0x21, 0x1a, 0x1b, 0x0a, 0x79, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x26, 0x00, 0x2e, 0x01, + 0x1a, 0x6d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x20, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, + 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x60, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x60, 0x20, 0x69, 0x6e, 0x20, + 0x74, 0x68, 0x65, 0x0a, 0x20, 0x60, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x60, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, + 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x26, 0x08, 0x13, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x01, 0x02, 0x00, 0x12, 0x03, 0x27, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, + 0x06, 0x12, 0x03, 0x27, 0x02, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x27, 0x0c, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x27, + 0x18, 0x19, 0x0a, 0x92, 0x01, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x2a, 0x02, 0x35, + 0x1a, 0x84, 0x01, 0x20, 0x54, 0x68, 0x65, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x2c, 0x20, 0x75, 0x73, 0x65, + 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x58, 0x4d, + 0x54, 0x50, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x61, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, + 0x61, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, + 0x12, 0x03, 0x2a, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, + 0x2a, 0x18, 0x30, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x2a, 0x33, + 0x34, 0x0a, 0x92, 0x01, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x2d, 0x02, 0x18, 0x1a, + 0x84, 0x01, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x46, 0x72, + 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x64, 0x79, 0x20, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x0a, 0x20, 0x68, + 0x61, 0x70, 0x70, 0x65, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x62, 0x79, 0x74, 0x65, 0x2d, + 0x70, 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x05, 0x12, + 0x03, 0x2d, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x2d, + 0x08, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x2d, 0x16, 0x17, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xb5, 0x20, 0x0a, 0x1e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb5, 0x01, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x31, 0x12, 0x3e, 0x0a, 0x06, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x09, 0x72, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, + 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, + 0x71, 0x0a, 0x09, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x31, 0x12, 0x21, 0x0a, 0x0c, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0b, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, + 0x41, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, + 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x74, 0x22, 0x46, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x56, 0x32, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x4e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x22, 0xdd, 0x01, 0x0a, 0x09, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x41, 0x0a, 0x0a, 0x63, + 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x21, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, + 0x78, 0x74, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x12, 0x24, + 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0a, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x48, 0x6d, 0x61, + 0x63, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x70, + 0x75, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x01, 0x52, 0x0a, 0x73, 0x68, 0x6f, + 0x75, 0x6c, 0x64, 0x50, 0x75, 0x73, 0x68, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x73, + 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x22, 0x7c, 0x0a, 0x07, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x32, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x12, 0x32, 0x0a, 0x02, 0x76, 0x32, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, 0x02, 0x76, 0x32, 0x42, 0x09, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xed, 0x02, 0x0a, 0x0e, 0x44, 0x65, 0x63, + 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x30, 0x0a, 0x11, 0x72, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, + 0x07, 0x73, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, + 0x73, 0x65, 0x6e, 0x74, 0x4e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x5f, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x50, 0x0a, 0x0c, 0x63, + 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, + 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, + 0x0c, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, + 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x74, + 0x65, 0x73, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, + 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0xc8, 0x01, 0x0a, 0x19, 0x63, 0x6f, 0x6d, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, + 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x58, 0x6d, 0x74, + 0x70, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x73, 0xca, 0x02, 0x14, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x20, 0x58, 0x6d, 0x74, 0x70, 0x5c, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x15, 0x58, 0x6d, + 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x73, 0x4a, 0xf2, 0x14, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x4d, 0x01, 0x0a, 0x4a, + 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x40, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, + 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, + 0x03, 0x03, 0x00, 0x1e, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, 0x00, 0x2b, 0x0a, + 0x09, 0x0a, 0x02, 0x03, 0x01, 0x12, 0x03, 0x06, 0x00, 0x37, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, + 0x12, 0x03, 0x07, 0x00, 0x2b, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x09, 0x00, 0x43, 0x0a, + 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x09, 0x00, 0x43, 0x0a, 0x8c, 0x01, 0x0a, 0x02, 0x04, + 0x00, 0x12, 0x04, 0x10, 0x00, 0x14, 0x01, 0x1a, 0x72, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, + 0x64, 0x65, 0x64, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x20, 0x61, + 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, + 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x64, 0x0a, 0x20, 0x61, 0x73, 0x20, 0x61, 0x73, + 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, + 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x32, 0x0c, 0x20, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x56, 0x31, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, + 0x12, 0x03, 0x10, 0x08, 0x17, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x11, + 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x11, 0x02, 0x11, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x11, 0x12, 0x18, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x11, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x12, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x01, 0x06, 0x12, 0x03, 0x12, 0x02, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, + 0x12, 0x03, 0x12, 0x12, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, + 0x12, 0x1e, 0x1f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x13, 0x02, 0x17, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x13, 0x02, 0x08, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x13, 0x09, 0x12, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x13, 0x15, 0x16, 0x0a, 0x37, 0x0a, 0x02, 0x04, 0x01, + 0x12, 0x04, 0x17, 0x00, 0x1c, 0x01, 0x1a, 0x2b, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x17, 0x08, 0x11, 0x0a, + 0x33, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x19, 0x02, 0x19, 0x1a, 0x26, 0x20, 0x65, + 0x6e, 0x63, 0x61, 0x70, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, + 0x64, 0x65, 0x64, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x56, 0x31, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x19, + 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x19, 0x08, 0x14, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x19, 0x17, 0x18, 0x0a, 0x47, + 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x1b, 0x02, 0x1c, 0x1a, 0x3a, 0x20, 0x43, 0x69, + 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x65, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, + 0x12, 0x03, 0x1b, 0x02, 0x0c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, + 0x1b, 0x0d, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x1b, 0x1a, + 0x1b, 0x0a, 0x88, 0x02, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x24, 0x00, 0x29, 0x01, 0x1a, 0xed, + 0x01, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x20, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, + 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x0a, 0x20, 0x6f, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x68, + 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, + 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x41, 0x45, 0x41, 0x44, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x0a, 0x20, 0x74, 0x68, + 0x75, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x61, 0x6d, + 0x70, 0x65, 0x72, 0x20, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x0a, 0x32, 0x0c, + 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x56, 0x32, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, + 0x04, 0x02, 0x01, 0x12, 0x03, 0x24, 0x08, 0x17, 0x0a, 0x35, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, + 0x12, 0x03, 0x26, 0x02, 0x18, 0x1a, 0x28, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x73, + 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, 0x26, 0x02, 0x08, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x26, 0x09, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x26, 0x16, 0x17, 0x0a, 0x2f, 0x0a, 0x04, 0x04, 0x02, 0x02, + 0x01, 0x12, 0x03, 0x28, 0x02, 0x13, 0x1a, 0x22, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, + 0x69, 0x63, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x62, + 0x65, 0x6c, 0x6f, 0x6e, 0x67, 0x73, 0x20, 0x74, 0x6f, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x01, 0x05, 0x12, 0x03, 0x28, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, + 0x01, 0x12, 0x03, 0x28, 0x09, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, + 0x03, 0x28, 0x11, 0x12, 0x0a, 0x4d, 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x2c, 0x00, 0x37, 0x01, + 0x1a, 0x41, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, + 0x6e, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, + 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x2c, 0x08, 0x11, 0x0a, + 0x33, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x2e, 0x02, 0x19, 0x1a, 0x26, 0x20, 0x65, + 0x6e, 0x63, 0x61, 0x70, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, + 0x64, 0x65, 0x64, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x56, 0x32, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2e, + 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2e, 0x08, 0x14, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2e, 0x17, 0x18, 0x0a, 0x46, + 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, 0x30, 0x02, 0x1c, 0x1a, 0x39, 0x20, 0x43, 0x69, + 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x65, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x06, 0x12, + 0x03, 0x30, 0x02, 0x0c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, 0x03, 0x30, + 0x0d, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x03, 0x12, 0x03, 0x30, 0x1a, 0x1b, + 0x0a, 0x5c, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x02, 0x12, 0x03, 0x33, 0x02, 0x21, 0x1a, 0x4f, 0x20, + 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x20, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x2c, 0x20, + 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x6b, 0x65, + 0x79, 0x20, 0x64, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x0a, 0x20, 0x6b, 0x65, 0x79, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x04, 0x12, 0x03, 0x33, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x03, 0x02, 0x02, 0x05, 0x12, 0x03, 0x33, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, + 0x02, 0x02, 0x01, 0x12, 0x03, 0x33, 0x11, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, + 0x03, 0x12, 0x03, 0x33, 0x1f, 0x20, 0x0a, 0x5f, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x03, 0x12, 0x03, + 0x36, 0x02, 0x20, 0x1a, 0x52, 0x20, 0x46, 0x6c, 0x61, 0x67, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, + 0x20, 0x62, 0x65, 0x20, 0x70, 0x75, 0x73, 0x68, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, + 0x61, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x03, 0x04, + 0x12, 0x03, 0x36, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x03, 0x05, 0x12, 0x03, + 0x36, 0x0b, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x03, 0x01, 0x12, 0x03, 0x36, 0x10, + 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x03, 0x03, 0x12, 0x03, 0x36, 0x1e, 0x1f, 0x0a, + 0x1f, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x3a, 0x00, 0x3f, 0x01, 0x1a, 0x13, 0x20, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x64, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x3a, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x04, 0x08, 0x00, 0x12, 0x04, 0x3b, 0x02, 0x3e, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, + 0x08, 0x00, 0x01, 0x12, 0x03, 0x3b, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, + 0x12, 0x03, 0x3c, 0x04, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x06, 0x12, 0x03, + 0x3c, 0x04, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x3c, 0x0e, + 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3c, 0x13, 0x14, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, 0x03, 0x3d, 0x04, 0x15, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x04, 0x02, 0x01, 0x06, 0x12, 0x03, 0x3d, 0x04, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x3d, 0x0e, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x3d, 0x13, 0x14, 0x0a, 0xae, 0x01, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x44, + 0x00, 0x4d, 0x01, 0x1a, 0xa1, 0x01, 0x20, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x73, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, + 0x0a, 0x20, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x0a, 0x20, 0x6d, + 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, + 0x44, 0x08, 0x16, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x45, 0x02, 0x10, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x05, 0x12, 0x03, 0x45, 0x02, 0x08, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x45, 0x09, 0x0b, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x45, 0x0e, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, + 0x02, 0x01, 0x12, 0x03, 0x46, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x05, + 0x12, 0x03, 0x46, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x01, 0x12, 0x03, + 0x46, 0x09, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x03, 0x12, 0x03, 0x46, 0x1b, + 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x02, 0x12, 0x03, 0x47, 0x02, 0x1c, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x05, 0x02, 0x02, 0x05, 0x12, 0x03, 0x47, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x05, 0x02, 0x02, 0x01, 0x12, 0x03, 0x47, 0x09, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, + 0x02, 0x02, 0x03, 0x12, 0x03, 0x47, 0x1a, 0x1b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x03, + 0x12, 0x03, 0x48, 0x02, 0x28, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x03, 0x04, 0x12, 0x03, + 0x48, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x03, 0x05, 0x12, 0x03, 0x48, 0x0b, + 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x03, 0x01, 0x12, 0x03, 0x48, 0x12, 0x23, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x03, 0x03, 0x12, 0x03, 0x48, 0x26, 0x27, 0x0a, 0x0b, 0x0a, + 0x04, 0x04, 0x05, 0x02, 0x04, 0x12, 0x03, 0x49, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, + 0x02, 0x04, 0x05, 0x12, 0x03, 0x49, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x04, + 0x01, 0x12, 0x03, 0x49, 0x09, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x04, 0x03, 0x12, + 0x03, 0x49, 0x13, 0x14, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x05, 0x12, 0x03, 0x4a, 0x02, + 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x05, 0x05, 0x12, 0x03, 0x4a, 0x02, 0x08, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x05, 0x01, 0x12, 0x03, 0x4a, 0x09, 0x16, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x05, 0x02, 0x05, 0x03, 0x12, 0x03, 0x4a, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x05, 0x02, 0x06, 0x12, 0x03, 0x4b, 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x06, + 0x06, 0x12, 0x03, 0x4b, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x06, 0x01, 0x12, + 0x03, 0x4b, 0x18, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x06, 0x03, 0x12, 0x03, 0x4b, + 0x27, 0x28, 0x0a, 0x2a, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x07, 0x12, 0x03, 0x4c, 0x02, 0x1a, 0x22, + 0x1d, 0x20, 0x65, 0x6e, 0x63, 0x61, 0x70, 0x73, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x20, 0x45, + 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x05, 0x02, 0x07, 0x05, 0x12, 0x03, 0x4c, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x05, 0x02, 0x07, 0x01, 0x12, 0x03, 0x4c, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, + 0x02, 0x07, 0x03, 0x12, 0x03, 0x4c, 0x18, 0x19, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0xe0, 0x05, 0x0a, 0x25, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x78, 0x6d, 0x74, 0x70, diff --git a/xmtp_proto/src/gen/xmtp.mls.message_contents.rs b/xmtp_proto/src/gen/xmtp.mls.message_contents.rs index 64881f6f3..0e4185a94 100644 --- a/xmtp_proto/src/gen/xmtp.mls.message_contents.rs +++ b/xmtp_proto/src/gen/xmtp.mls.message_contents.rs @@ -1,90 +1,5 @@ // @generated // This file is @generated by prost-build. -/// Used for "Grant Messaging Access" associations -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GrantMessagingAccessAssociation { - #[prost(enumeration="AssociationTextVersion", tag="1")] - pub association_text_version: i32, - /// EIP-191 signature - #[prost(message, optional, tag="2")] - pub signature: ::core::option::Option, - #[prost(string, tag="3")] - pub account_address: ::prost::alloc::string::String, - #[prost(uint64, tag="4")] - pub created_ns: u64, -} -/// Used for "Revoke Messaging Access" associations -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RevokeMessagingAccessAssociation { - #[prost(enumeration="AssociationTextVersion", tag="1")] - pub association_text_version: i32, - /// EIP-191 signature - #[prost(message, optional, tag="2")] - pub signature: ::core::option::Option, - #[prost(string, tag="3")] - pub account_address: ::prost::alloc::string::String, - #[prost(uint64, tag="4")] - pub created_ns: u64, -} -/// LegacyCreateIdentityAssociation is used when a v3 installation key -/// is signed by a v2 identity key, which in turn is signed via a -/// 'CreateIdentity' wallet signature -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct LegacyCreateIdentityAssociation { - /// Signs SHA-256 hash of installation key - #[prost(message, optional, tag="1")] - pub signature: ::core::option::Option, - /// created_ns is encoded inside serialized key, account_address is recoverable - /// from the SignedPublicKey signature - #[prost(message, optional, tag="2")] - pub signed_legacy_create_identity_key: ::core::option::Option, -} -/// RecoverableEcdsaSignature -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct RecoverableEcdsaSignature { - /// 65-bytes \[ R || S || V \], with recovery id as the last byte - #[prost(bytes="vec", tag="1")] - pub bytes: ::prost::alloc::vec::Vec, -} -/// EdDSA signature bytes matching RFC 8032 -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct EdDsaSignature { - #[prost(bytes="vec", tag="1")] - pub bytes: ::prost::alloc::vec::Vec, -} -/// Allows for us to update the format of the association text without -/// incrementing the entire proto -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] -#[repr(i32)] -pub enum AssociationTextVersion { - Unspecified = 0, - AssociationTextVersion1 = 1, -} -impl AssociationTextVersion { - /// String value of the enum field names used in the ProtoBuf definition. - /// - /// The values are not transformed in any way and thus are considered stable - /// (if the ProtoBuf definition does not change) and safe for programmatic use. - pub fn as_str_name(&self) -> &'static str { - match self { - AssociationTextVersion::Unspecified => "ASSOCIATION_TEXT_VERSION_UNSPECIFIED", - AssociationTextVersion::AssociationTextVersion1 => "ASSOCIATION_TEXT_VERSION_1", - } - } - /// Creates an enum from field names used in the ProtoBuf definition. - pub fn from_str_name(value: &str) -> ::core::option::Option { - match value { - "ASSOCIATION_TEXT_VERSION_UNSPECIFIED" => Some(Self::Unspecified), - "ASSOCIATION_TEXT_VERSION_1" => Some(Self::AssociationTextVersion1), - _ => None, - } - } -} /// ContentTypeId is used to identify the type of content stored in a Message. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -256,54 +171,6 @@ impl Compression { } } } -/// A credential that can be used in MLS leaf nodes -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct MlsCredential { - #[prost(bytes="vec", tag="1")] - pub installation_public_key: ::prost::alloc::vec::Vec, - #[prost(oneof="mls_credential::Association", tags="2, 3")] - pub association: ::core::option::Option, -} -/// Nested message and enum types in `MlsCredential`. -pub mod mls_credential { - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Association { - #[prost(message, tag="2")] - MessagingAccess(super::GrantMessagingAccessAssociation), - #[prost(message, tag="3")] - LegacyCreateIdentity(super::LegacyCreateIdentityAssociation), - } -} -/// A declaration and proof that a credential is no longer valid -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct CredentialRevocation { - #[prost(oneof="credential_revocation::PublicKey", tags="1, 2")] - pub public_key: ::core::option::Option, - #[prost(oneof="credential_revocation::Association", tags="3")] - pub association: ::core::option::Option, -} -/// Nested message and enum types in `CredentialRevocation`. -pub mod credential_revocation { - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum PublicKey { - /// The 'installation_public_key' field of the MlsCredential proto - #[prost(bytes, tag="1")] - InstallationKey(::prost::alloc::vec::Vec), - /// The 'key_bytes' field of the legacy SignedPublicKey proto - #[prost(bytes, tag="2")] - UnsignedLegacyCreateIdentityKey(::prost::alloc::vec::Vec), - } - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Oneof)] - pub enum Association { - #[prost(message, tag="3")] - MessagingAccess(super::RevokeMessagingAccessAssociation), - } -} /// Contains a mapping of `inbox_id` -> `sequence_id` for all members of a group. /// Designed to be stored in the group context extension of the MLS group #[allow(clippy::derive_partial_eq_without_eq)] @@ -701,657 +568,357 @@ pub mod group_updated { } /// Encoded file descriptor set for the `xmtp.mls.message_contents` package pub const FILE_DESCRIPTOR_SET: &[u8] = &[ - 0x0a, 0xf0, 0x17, 0x0a, 0x26, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, - 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x21, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xaa, 0x02, 0x0a, 0x1f, 0x47, 0x72, - 0x61, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6b, 0x0a, - 0x18, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x78, - 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x31, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x6f, - 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x16, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, - 0x65, 0x78, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x27, - 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x4e, 0x73, 0x22, 0xab, 0x02, 0x0a, 0x20, 0x52, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6b, 0x0a, 0x18, 0x61, - 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x16, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x78, - 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, - 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x27, 0x0a, 0x0f, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x4e, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x78, 0x6d, + 0x0a, 0xec, 0x2b, 0x0a, 0x22, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, + 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x79, 0x70, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x79, 0x70, 0x65, 0x49, 0x64, + 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x6a, 0x6f, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x8f, 0x03, 0x0a, 0x0e, 0x45, + 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x3c, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, - 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x70, 0x0a, 0x21, - 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x52, - 0x1d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x22, 0x31, - 0x0a, 0x19, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, - 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x22, 0x26, 0x0a, 0x0e, 0x45, 0x64, 0x44, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x2a, 0x62, 0x0a, 0x16, 0x41, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x24, 0x41, 0x53, 0x53, 0x4f, 0x43, 0x49, 0x41, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, - 0x1a, 0x41, 0x53, 0x53, 0x4f, 0x43, 0x49, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x45, 0x58, - 0x54, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x10, 0x01, 0x42, 0xe5, 0x01, - 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, - 0x10, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, - 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, 0x58, 0x6d, - 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, - 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x3a, - 0x3a, 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0x93, 0x0d, 0x0a, 0x06, 0x12, 0x04, 0x01, 0x00, 0x35, 0x01, - 0x0a, 0x27, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x1d, 0x20, 0x41, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, - 0x03, 0x00, 0x22, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, 0x00, 0x2b, 0x0a, 0x08, - 0x0a, 0x01, 0x08, 0x12, 0x03, 0x07, 0x00, 0x47, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, - 0x07, 0x00, 0x47, 0x0a, 0x6f, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, 0x0c, 0x00, 0x0f, 0x01, 0x1a, - 0x63, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x73, 0x20, - 0x74, 0x6f, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, - 0x72, 0x6d, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x73, 0x73, 0x6f, - 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x77, 0x69, 0x74, - 0x68, 0x6f, 0x75, 0x74, 0x0a, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x69, 0x72, 0x65, 0x20, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, 0x01, 0x12, 0x03, 0x0c, 0x05, 0x1b, - 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0d, 0x02, 0x2b, 0x0a, 0x0c, 0x0a, - 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0d, 0x02, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x05, - 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x0d, 0x29, 0x2a, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, - 0x01, 0x12, 0x03, 0x0e, 0x02, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, - 0x03, 0x0e, 0x02, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x0e, - 0x1f, 0x20, 0x0a, 0x3c, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x12, 0x00, 0x17, 0x01, 0x1a, 0x30, - 0x20, 0x55, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x22, 0x47, 0x72, 0x61, 0x6e, 0x74, - 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x22, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x12, 0x08, 0x27, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x13, 0x02, 0x36, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x00, 0x06, 0x12, 0x03, 0x13, 0x02, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x13, 0x19, 0x31, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x13, 0x34, 0x35, 0x0a, 0x20, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x14, 0x02, 0x2a, - 0x22, 0x13, 0x20, 0x45, 0x49, 0x50, 0x2d, 0x31, 0x39, 0x31, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, - 0x14, 0x02, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x14, 0x1c, - 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x14, 0x28, 0x29, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x15, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x15, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x02, 0x02, 0x01, 0x12, 0x03, 0x15, 0x09, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, - 0x03, 0x12, 0x03, 0x15, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, - 0x16, 0x02, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x16, 0x02, - 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x16, 0x09, 0x13, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x16, 0x16, 0x17, 0x0a, 0x3d, 0x0a, - 0x02, 0x04, 0x01, 0x12, 0x04, 0x1a, 0x00, 0x1f, 0x01, 0x1a, 0x31, 0x20, 0x55, 0x73, 0x65, 0x64, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x22, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x20, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x20, 0x61, - 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, - 0x04, 0x01, 0x01, 0x12, 0x03, 0x1a, 0x08, 0x28, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, - 0x12, 0x03, 0x1b, 0x02, 0x36, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x1b, 0x02, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x1b, 0x19, - 0x31, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x1b, 0x34, 0x35, 0x0a, - 0x20, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x1c, 0x02, 0x2a, 0x22, 0x13, 0x20, 0x45, - 0x49, 0x50, 0x2d, 0x31, 0x39, 0x31, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x1c, 0x02, 0x1b, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x1c, 0x1c, 0x25, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x1c, 0x28, 0x29, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x01, 0x02, 0x02, 0x12, 0x03, 0x1d, 0x02, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, - 0x05, 0x12, 0x03, 0x1d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x1d, 0x09, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x1d, - 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x1e, 0x02, 0x18, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x05, 0x12, 0x03, 0x1e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x03, 0x01, 0x12, 0x03, 0x1e, 0x09, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x01, 0x02, 0x03, 0x03, 0x12, 0x03, 0x1e, 0x16, 0x17, 0x0a, 0xb3, 0x01, 0x0a, 0x02, 0x04, 0x02, - 0x12, 0x04, 0x24, 0x00, 0x2a, 0x01, 0x1a, 0xa6, 0x01, 0x20, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x41, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x20, 0x76, 0x33, 0x20, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x0a, 0x20, 0x69, 0x73, - 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x61, 0x20, 0x76, 0x32, 0x20, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x77, 0x68, - 0x69, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x73, - 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x76, 0x69, 0x61, 0x20, 0x61, 0x0a, 0x20, 0x27, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x27, 0x20, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x0a, - 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x24, 0x08, 0x27, 0x0a, 0x35, 0x0a, 0x04, 0x04, - 0x02, 0x02, 0x00, 0x12, 0x03, 0x26, 0x02, 0x2a, 0x1a, 0x28, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x73, - 0x20, 0x53, 0x48, 0x41, 0x2d, 0x32, 0x35, 0x36, 0x20, 0x68, 0x61, 0x73, 0x68, 0x20, 0x6f, 0x66, - 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, - 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x26, 0x02, 0x1b, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x26, 0x1c, 0x25, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x26, 0x28, 0x29, 0x0a, 0x7e, 0x0a, 0x04, - 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x29, 0x02, 0x4e, 0x1a, 0x71, 0x20, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x73, 0x20, 0x69, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, - 0x64, 0x20, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x29, 0x02, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, - 0x02, 0x01, 0x01, 0x12, 0x03, 0x29, 0x28, 0x49, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, - 0x03, 0x12, 0x03, 0x29, 0x4c, 0x4d, 0x0a, 0x27, 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x2d, 0x00, - 0x30, 0x01, 0x1a, 0x1b, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, - 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x0a, - 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x2d, 0x08, 0x21, 0x0a, 0x4a, 0x0a, 0x04, 0x04, - 0x03, 0x02, 0x00, 0x12, 0x03, 0x2f, 0x02, 0x12, 0x1a, 0x3d, 0x20, 0x36, 0x35, 0x2d, 0x62, 0x79, - 0x74, 0x65, 0x73, 0x20, 0x5b, 0x20, 0x52, 0x20, 0x7c, 0x7c, 0x20, 0x53, 0x20, 0x7c, 0x7c, 0x20, - 0x56, 0x20, 0x5d, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x79, 0x20, 0x69, 0x64, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, - 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x05, - 0x12, 0x03, 0x2f, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, - 0x2f, 0x08, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2f, 0x10, - 0x11, 0x0a, 0x35, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x33, 0x00, 0x35, 0x01, 0x1a, 0x29, 0x20, - 0x45, 0x64, 0x44, 0x53, 0x41, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x52, - 0x46, 0x43, 0x20, 0x38, 0x30, 0x33, 0x32, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, - 0x03, 0x33, 0x08, 0x16, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x34, 0x02, - 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x05, 0x12, 0x03, 0x34, 0x02, 0x07, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x34, 0x08, 0x0d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x34, 0x10, 0x11, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, 0x0a, 0xec, 0x2b, 0x0a, 0x22, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x79, - 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x79, 0x70, - 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, - 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0x8f, 0x03, - 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x49, 0x64, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x59, 0x0a, 0x0a, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x39, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x6e, 0x63, 0x6f, + 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, + 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x66, 0x61, 0x6c, 0x6c, + 0x62, 0x61, 0x63, 0x6b, 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, + 0x0b, 0x0a, 0x09, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x42, 0x0e, 0x0a, 0x0c, + 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xdf, 0x03, 0x0a, + 0x11, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, + 0x70, 0x65, 0x12, 0x41, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x59, - 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, - 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x66, 0x61, 0x6c, - 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x66, - 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x88, 0x01, 0x01, 0x12, 0x4d, 0x0a, 0x0b, 0x63, 0x6f, - 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x26, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, - 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x42, - 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0xdf, 0x03, 0x0a, 0x11, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x76, - 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x02, 0x76, 0x31, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x69, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x2e, 0x56, 0x31, 0x48, + 0x00, 0x52, 0x02, 0x76, 0x31, 0x12, 0x41, 0x0a, 0x02, 0x76, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x2e, - 0x56, 0x31, 0x48, 0x00, 0x52, 0x02, 0x76, 0x31, 0x12, 0x41, 0x0a, 0x02, 0x76, 0x32, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x2e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x02, 0x76, 0x32, 0x1a, 0x47, 0x0a, 0x02, 0x56, - 0x31, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, - 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, - 0x79, 0x4b, 0x65, 0x79, 0x1a, 0xef, 0x01, 0x0a, 0x02, 0x56, 0x32, 0x12, 0x27, 0x0a, 0x0f, 0x69, - 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, - 0x79, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x12, 0x4c, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, - 0x0a, 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x48, 0x00, 0x52, - 0x05, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x42, 0x0e, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x22, 0x51, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x69, 0x6e, - 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x69, 0x6e, - 0x43, 0x6f, 0x64, 0x65, 0x22, 0x9f, 0x01, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, - 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x57, 0x0a, - 0x0e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, - 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x22, 0x4d, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x2d, 0x0a, 0x11, 0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x5f, 0x70, 0x6f, 0x6c, 0x79, - 0x31, 0x33, 0x30, 0x35, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x10, 0x63, 0x68, - 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x42, 0x05, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x2a, 0x3c, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, - 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x14, 0x0a, - 0x10, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x5a, 0x49, - 0x50, 0x10, 0x01, 0x42, 0xe1, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, - 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, - 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, - 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, - 0x70, 0x3a, 0x3a, 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xb0, 0x1e, 0x0a, 0x06, 0x12, 0x04, 0x02, 0x00, - 0x65, 0x01, 0x0a, 0x7c, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x02, 0x00, 0x12, 0x1a, 0x72, 0x20, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x65, - 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x0a, 0x20, 0x43, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x56, 0x32, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, - 0x77, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x61, 0x6c, 0x6c, - 0x79, 0x20, 0x72, 0x65, 0x74, 0x69, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x56, 0x32, 0x20, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, - 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x04, 0x00, 0x22, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, - 0x03, 0x06, 0x00, 0x47, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x06, 0x00, 0x47, 0x0a, - 0x58, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0a, 0x00, 0x0f, 0x01, 0x1a, 0x4c, 0x20, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x20, 0x69, 0x73, 0x20, 0x75, - 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, - 0x12, 0x03, 0x0a, 0x08, 0x15, 0x0a, 0x34, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0b, - 0x02, 0x1a, 0x22, 0x27, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x67, - 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0b, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x00, 0x01, 0x12, 0x03, 0x0b, 0x09, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x0b, 0x18, 0x19, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0c, - 0x02, 0x15, 0x22, 0x11, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, - 0x0c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0c, 0x09, - 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0c, 0x13, 0x14, 0x0a, - 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0d, 0x02, 0x1b, 0x22, 0x1b, 0x20, 0x6d, - 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x02, 0x05, 0x12, 0x03, 0x0d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, - 0x12, 0x03, 0x0d, 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, - 0x0d, 0x19, 0x1a, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x0e, 0x02, 0x1b, - 0x22, 0x1b, 0x20, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x0e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x0e, 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x03, 0x03, 0x12, 0x03, 0x0e, 0x19, 0x1a, 0x0a, 0x67, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, 0x13, - 0x00, 0x16, 0x01, 0x1a, 0x5b, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x7a, 0x65, 0x64, - 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6c, 0x69, - 0x6e, 0x74, 0x3a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x45, 0x4e, 0x55, 0x4d, 0x5f, - 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x5f, 0x5a, 0x45, 0x52, 0x4f, - 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x5f, 0x45, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, 0x01, 0x12, 0x03, 0x13, 0x05, 0x10, 0x0a, 0x0b, 0x0a, 0x04, - 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, 0x14, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, - 0x00, 0x01, 0x12, 0x03, 0x14, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, - 0x12, 0x03, 0x14, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x15, - 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x15, 0x02, 0x12, - 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x15, 0x15, 0x16, 0x0a, 0xa3, - 0x01, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x1b, 0x00, 0x29, 0x01, 0x1a, 0x96, 0x01, 0x20, 0x45, - 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x73, 0x20, - 0x74, 0x79, 0x70, 0x65, 0x0a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x69, - 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x1b, 0x08, 0x16, - 0x0a, 0x65, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x1e, 0x02, 0x19, 0x1a, 0x58, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, - 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x63, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x63, - 0x68, 0x69, 0x6e, 0x65, 0x72, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, - 0x12, 0x03, 0x1e, 0x02, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, - 0x1e, 0x10, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x1e, 0x17, - 0x18, 0x0a, 0x54, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x20, 0x02, 0x25, 0x1a, 0x47, - 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, - 0x6e, 0x67, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, - 0x74, 0x6c, 0x79, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, - 0x12, 0x03, 0x20, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, - 0x20, 0x16, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x20, 0x23, - 0x24, 0x0a, 0x84, 0x01, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x23, 0x02, 0x1f, 0x1a, - 0x77, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x61, 0x6c, 0x6c, 0x62, - 0x61, 0x63, 0x6b, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, - 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, - 0x69, 0x6e, 0x20, 0x63, 0x61, 0x73, 0x65, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x20, 0x6f, 0x72, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, - 0x04, 0x12, 0x03, 0x23, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x05, 0x12, - 0x03, 0x23, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x23, - 0x12, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x23, 0x1d, 0x1e, - 0x0a, 0x6e, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x26, 0x02, 0x27, 0x1a, 0x61, 0x20, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, - 0x69, 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, - 0x74, 0x68, 0x6d, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x63, 0x6f, 0x6d, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, - 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x04, 0x12, 0x03, 0x26, 0x02, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x06, 0x12, 0x03, 0x26, 0x0b, 0x16, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x03, 0x01, 0x12, 0x03, 0x26, 0x17, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x03, 0x03, 0x12, 0x03, 0x26, 0x25, 0x26, 0x0a, 0x25, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x04, - 0x12, 0x03, 0x28, 0x02, 0x14, 0x1a, 0x18, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x05, 0x12, 0x03, 0x28, 0x02, 0x07, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x04, 0x01, 0x12, 0x03, 0x28, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x01, 0x02, 0x04, 0x03, 0x12, 0x03, 0x28, 0x12, 0x13, 0x0a, 0x55, 0x0a, 0x02, 0x04, 0x02, 0x12, - 0x04, 0x2c, 0x00, 0x4c, 0x01, 0x1a, 0x49, 0x20, 0x41, 0x20, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x70, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x65, 0x74, 0x73, 0x20, 0x65, - 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x4d, 0x4c, 0x53, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x2c, 0x08, 0x19, 0x0a, 0x33, 0x0a, 0x04, - 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x2e, 0x02, 0x34, 0x03, 0x1a, 0x25, 0x20, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, - 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x00, 0x01, 0x12, 0x03, 0x2e, 0x0a, 0x0c, 0x0a, - 0x2e, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x30, 0x04, 0x16, 0x1a, 0x1f, - 0x20, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, - 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x30, 0x04, 0x09, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x30, 0x0a, 0x11, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x30, 0x14, 0x15, 0x0a, - 0x8c, 0x01, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x33, 0x04, 0x1f, 0x1a, - 0x7d, 0x20, 0x41, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, - 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x20, 0x63, 0x61, 0x6e, 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x64, - 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x2e, - 0x20, 0x4d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, - 0x65, 0x72, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x0a, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x33, 0x04, 0x0a, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x33, 0x0b, 0x1a, 0x0a, 0x0e, - 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x33, 0x1d, 0x1e, 0x0a, 0x33, - 0x0a, 0x04, 0x04, 0x02, 0x03, 0x01, 0x12, 0x04, 0x37, 0x02, 0x44, 0x03, 0x1a, 0x25, 0x20, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x01, 0x01, 0x12, 0x03, 0x37, 0x0a, - 0x0c, 0x0a, 0x8c, 0x01, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x3a, 0x04, - 0x1f, 0x1a, 0x7d, 0x20, 0x41, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, - 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, - 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, - 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x2e, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, - 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x0a, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x3a, 0x04, 0x0a, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x3a, 0x0b, 0x1a, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3a, 0x1d, 0x1e, - 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x08, 0x00, 0x12, 0x04, 0x3c, 0x04, 0x43, 0x05, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x08, 0x00, 0x01, 0x12, 0x03, 0x3c, 0x0a, 0x16, - 0x0a, 0x2e, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x12, 0x03, 0x3e, 0x06, 0x18, 0x1a, - 0x1f, 0x20, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, - 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x05, 0x12, 0x03, 0x3e, 0x06, 0x0b, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x3e, 0x0c, 0x13, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x3e, 0x16, 0x17, - 0x0a, 0x45, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x12, 0x03, 0x40, 0x06, 0x28, 0x1a, - 0x36, 0x20, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x6e, 0x64, - 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, - 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, - 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, - 0x02, 0x06, 0x12, 0x03, 0x40, 0x06, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, - 0x02, 0x01, 0x12, 0x03, 0x40, 0x1c, 0x23, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, - 0x02, 0x03, 0x12, 0x03, 0x40, 0x26, 0x27, 0x0a, 0x41, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, - 0x03, 0x12, 0x03, 0x42, 0x06, 0x24, 0x1a, 0x32, 0x20, 0x53, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x74, - 0x68, 0x65, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x6e, 0x64, - 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, - 0x03, 0x01, 0x02, 0x03, 0x06, 0x12, 0x03, 0x42, 0x06, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, - 0x03, 0x01, 0x02, 0x03, 0x01, 0x12, 0x03, 0x42, 0x1a, 0x1f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, - 0x03, 0x01, 0x02, 0x03, 0x03, 0x12, 0x03, 0x42, 0x22, 0x23, 0x0a, 0x66, 0x0a, 0x04, 0x04, 0x02, - 0x08, 0x00, 0x12, 0x04, 0x48, 0x02, 0x4b, 0x03, 0x1a, 0x58, 0x20, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, - 0x65, 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x20, 0x50, 0x6c, 0x61, - 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x69, - 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x08, 0x00, 0x01, 0x12, 0x03, 0x48, 0x08, 0x0f, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x49, 0x04, 0x0e, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x49, 0x04, 0x06, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x49, 0x07, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, - 0x00, 0x03, 0x12, 0x03, 0x49, 0x0c, 0x0d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x4a, 0x04, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x4a, - 0x04, 0x06, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x4a, 0x07, 0x09, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x4a, 0x0c, 0x0d, 0x0a, 0x57, - 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x4f, 0x00, 0x54, 0x01, 0x1a, 0x4b, 0x20, 0x49, 0x6e, 0x69, - 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x64, 0x20, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, - 0x4f, 0x08, 0x1d, 0x0a, 0x31, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x51, 0x02, 0x18, - 0x1a, 0x24, 0x20, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x66, 0x69, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x05, 0x12, - 0x03, 0x51, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x51, - 0x09, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x51, 0x16, 0x17, - 0x0a, 0x2d, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, 0x53, 0x02, 0x16, 0x1a, 0x20, 0x20, - 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x73, 0x20, 0x61, 0x20, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x20, - 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x05, 0x12, 0x03, 0x53, 0x02, 0x08, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, 0x03, 0x53, 0x09, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x03, 0x02, 0x01, 0x03, 0x12, 0x03, 0x53, 0x14, 0x15, 0x0a, 0x5a, 0x0a, 0x02, 0x04, 0x04, 0x12, - 0x04, 0x57, 0x00, 0x5e, 0x01, 0x1a, 0x4e, 0x20, 0x50, 0x72, 0x65, 0x2d, 0x65, 0x78, 0x69, 0x73, - 0x74, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x69, 0x64, 0x20, 0x63, 0x61, 0x70, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x73, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x68, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x79, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x72, - 0x65, 0x70, 0x6c, 0x79, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x57, 0x08, - 0x1b, 0x0a, 0x4f, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x59, 0x02, 0x18, 0x1a, 0x42, - 0x20, 0x4d, 0x75, 0x73, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x65, - 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, - 0x69, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x05, 0x12, 0x03, 0x59, 0x02, 0x08, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x59, 0x09, 0x13, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x59, 0x16, 0x17, 0x0a, 0x37, 0x0a, 0x04, - 0x04, 0x04, 0x02, 0x01, 0x12, 0x03, 0x5b, 0x02, 0x11, 0x1a, 0x2a, 0x20, 0x57, 0x68, 0x65, 0x72, - 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x63, - 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x20, - 0x66, 0x72, 0x6f, 0x6d, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x05, 0x12, 0x03, - 0x5b, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x5b, 0x09, - 0x0c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x5b, 0x0f, 0x10, 0x0a, - 0x5a, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x02, 0x12, 0x03, 0x5d, 0x02, 0x2b, 0x1a, 0x4d, 0x20, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x27, - 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x27, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x41, 0x45, 0x53, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, - 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x2d, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x04, 0x02, 0x02, 0x06, 0x12, 0x03, 0x5d, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, - 0x02, 0x01, 0x12, 0x03, 0x5d, 0x18, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x03, - 0x12, 0x03, 0x5d, 0x29, 0x2a, 0x0a, 0x34, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x61, 0x00, 0x65, - 0x01, 0x1a, 0x28, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, - 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x2d, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, - 0x05, 0x01, 0x12, 0x03, 0x61, 0x08, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x05, 0x08, 0x00, 0x12, - 0x04, 0x62, 0x02, 0x64, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x08, 0x00, 0x01, 0x12, 0x03, - 0x62, 0x08, 0x0b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x63, 0x04, 0x20, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x05, 0x12, 0x03, 0x63, 0x04, 0x09, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x63, 0x0a, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x63, 0x1e, 0x1f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, 0x0a, 0xca, 0x0d, 0x0a, 0x25, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x1a, 0x26, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x61, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xb3, 0x02, 0x0a, 0x0d, 0x4d, 0x6c, 0x73, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x67, 0x0a, 0x10, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x47, 0x72, 0x61, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, - 0x00, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x12, 0x72, 0x0a, 0x16, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4c, - 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x74, 0x79, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, - 0x52, 0x14, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x42, 0x0d, 0x0a, 0x0b, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x9a, 0x02, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, - 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0f, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x4e, 0x0a, 0x23, 0x75, - 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6b, - 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x1f, 0x75, 0x6e, 0x73, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x68, 0x0a, 0x10, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, - 0x67, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x42, 0x0d, 0x0a, 0x0b, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x42, 0xe4, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0f, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, - 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, 0xaa, - 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, 0x74, - 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x73, 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, + 0x56, 0x32, 0x48, 0x00, 0x52, 0x02, 0x76, 0x32, 0x1a, 0x47, 0x0a, 0x02, 0x56, 0x31, 0x12, 0x18, + 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x64, 0x65, 0x6d, + 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4b, 0x65, + 0x79, 0x1a, 0xef, 0x01, 0x0a, 0x02, 0x56, 0x32, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x64, 0x65, 0x6d, + 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4b, 0x65, + 0x79, 0x12, 0x1a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x4c, 0x0a, + 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x05, 0x72, + 0x65, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x48, 0x00, 0x52, 0x05, 0x72, 0x65, + 0x70, 0x6c, 0x79, 0x42, 0x0e, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x51, + 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x69, 0x6e, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x69, 0x6e, 0x43, 0x6f, 0x64, + 0x65, 0x22, 0x9f, 0x01, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x57, 0x0a, 0x0e, 0x65, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4b, 0x65, 0x79, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x4b, 0x65, 0x79, 0x22, 0x4d, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2d, 0x0a, 0x11, + 0x63, 0x68, 0x61, 0x63, 0x68, 0x61, 0x32, 0x30, 0x5f, 0x70, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, + 0x35, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x10, 0x63, 0x68, 0x61, 0x63, 0x68, + 0x61, 0x32, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35, 0x42, 0x05, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x2a, 0x3c, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, + 0x5f, 0x44, 0x45, 0x46, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, + 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x47, 0x5a, 0x49, 0x50, 0x10, 0x01, + 0x42, 0xe1, 0x01, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, + 0x73, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x73, 0x42, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, + 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, + 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0xa2, 0x02, 0x03, 0x58, 0x4d, 0x4d, 0xaa, 0x02, 0x18, 0x58, 0x6d, 0x74, + 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x73, 0xca, 0x02, 0x18, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x58, - 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x4a, 0x9b, 0x06, 0x0a, 0x06, 0x12, 0x04, - 0x01, 0x00, 0x1e, 0x01, 0x0a, 0x27, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x1d, - 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x72, 0x65, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x08, 0x0a, - 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x22, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, - 0x00, 0x30, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x07, 0x00, 0x47, 0x0a, 0x09, 0x0a, 0x02, - 0x08, 0x0b, 0x12, 0x03, 0x07, 0x00, 0x47, 0x0a, 0x3d, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0b, - 0x00, 0x11, 0x01, 0x1a, 0x31, 0x20, 0x41, 0x20, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x61, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, - 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x4d, 0x4c, 0x53, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, - 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0b, - 0x08, 0x15, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0c, 0x02, 0x24, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0c, 0x02, 0x07, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0c, 0x08, 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0c, 0x22, 0x23, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x00, 0x08, - 0x00, 0x12, 0x04, 0x0d, 0x02, 0x10, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x08, 0x00, 0x01, - 0x12, 0x03, 0x0d, 0x08, 0x13, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0e, - 0x04, 0x39, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x06, 0x12, 0x03, 0x0e, 0x04, 0x23, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0e, 0x24, 0x34, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0e, 0x37, 0x38, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0f, 0x04, 0x3f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, - 0x02, 0x06, 0x12, 0x03, 0x0f, 0x04, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, - 0x12, 0x03, 0x0f, 0x24, 0x3a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, - 0x0f, 0x3d, 0x3e, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x14, 0x00, 0x1e, 0x01, 0x1a, - 0x3e, 0x20, 0x41, 0x20, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, - 0x20, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x69, 0x73, 0x20, 0x6e, - 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x0a, 0x0a, - 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x14, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, - 0x01, 0x08, 0x00, 0x12, 0x04, 0x15, 0x02, 0x1a, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x08, - 0x00, 0x01, 0x12, 0x03, 0x15, 0x08, 0x12, 0x0a, 0x4d, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, - 0x03, 0x17, 0x04, 0x1f, 0x1a, 0x40, 0x20, 0x54, 0x68, 0x65, 0x20, 0x27, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x27, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x4d, 0x6c, 0x73, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x20, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, - 0x03, 0x17, 0x04, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x17, - 0x0a, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x17, 0x1d, 0x1e, - 0x0a, 0x48, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x19, 0x04, 0x32, 0x1a, 0x3b, 0x20, - 0x54, 0x68, 0x65, 0x20, 0x27, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x27, 0x20, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x67, - 0x61, 0x63, 0x79, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x4b, 0x65, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x01, 0x05, 0x12, 0x03, 0x19, 0x04, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, - 0x01, 0x12, 0x03, 0x19, 0x0a, 0x2d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, - 0x03, 0x19, 0x30, 0x31, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x01, 0x08, 0x01, 0x12, 0x04, 0x1b, 0x02, - 0x1d, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x08, 0x01, 0x01, 0x12, 0x03, 0x1b, 0x08, 0x13, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x1c, 0x04, 0x3a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x02, 0x06, 0x12, 0x03, 0x1c, 0x04, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x1c, 0x25, 0x35, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, - 0x02, 0x03, 0x12, 0x03, 0x1c, 0x38, 0x39, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, + 0xe2, 0x02, 0x24, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x5c, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1a, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, + 0x4d, 0x6c, 0x73, 0x3a, 0x3a, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x4a, 0xb0, 0x1e, 0x0a, 0x06, 0x12, 0x04, 0x02, 0x00, 0x65, 0x01, 0x0a, + 0x7c, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x02, 0x00, 0x12, 0x1a, 0x72, 0x20, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x0a, + 0x20, 0x43, 0x6f, 0x70, 0x69, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x56, 0x32, 0x20, + 0x63, 0x6f, 0x64, 0x65, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x20, + 0x63, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x72, + 0x65, 0x74, 0x69, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x56, 0x32, 0x20, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x08, 0x0a, + 0x01, 0x02, 0x12, 0x03, 0x04, 0x00, 0x22, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x06, 0x00, + 0x47, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x06, 0x00, 0x47, 0x0a, 0x58, 0x0a, 0x02, + 0x04, 0x00, 0x12, 0x04, 0x0a, 0x00, 0x0f, 0x01, 0x1a, 0x4c, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x49, 0x64, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, + 0x20, 0x74, 0x6f, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x79, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0a, + 0x08, 0x15, 0x0a, 0x34, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0b, 0x02, 0x1a, 0x22, + 0x27, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x67, 0x6f, 0x76, 0x65, + 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, + 0x05, 0x12, 0x03, 0x0b, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x0b, 0x09, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0b, + 0x18, 0x19, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0c, 0x02, 0x15, 0x22, + 0x11, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x0c, 0x02, 0x08, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0c, 0x09, 0x10, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0c, 0x13, 0x14, 0x0a, 0x28, 0x0a, 0x04, + 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0d, 0x02, 0x1b, 0x22, 0x1b, 0x20, 0x6d, 0x61, 0x6a, 0x6f, + 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, + 0x03, 0x0d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x0d, + 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x0d, 0x19, 0x1a, + 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x03, 0x12, 0x03, 0x0e, 0x02, 0x1b, 0x22, 0x1b, 0x20, + 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, + 0x02, 0x03, 0x05, 0x12, 0x03, 0x0e, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, + 0x01, 0x12, 0x03, 0x0e, 0x09, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x03, 0x12, + 0x03, 0x0e, 0x19, 0x1a, 0x0a, 0x67, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, 0x13, 0x00, 0x16, 0x01, + 0x1a, 0x5b, 0x20, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x63, 0x6f, + 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, + 0x74, 0x68, 0x6d, 0x73, 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6c, 0x69, 0x6e, 0x74, 0x3a, + 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x46, 0x49, 0x45, + 0x4c, 0x44, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x5f, 0x56, 0x41, + 0x4c, 0x55, 0x45, 0x5f, 0x45, 0x4e, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x48, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x05, 0x00, 0x01, 0x12, 0x03, 0x13, 0x05, 0x10, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, + 0x00, 0x12, 0x03, 0x14, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, + 0x03, 0x14, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x14, + 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x15, 0x02, 0x17, 0x0a, + 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x15, 0x02, 0x12, 0x0a, 0x0c, 0x0a, + 0x05, 0x05, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x15, 0x15, 0x16, 0x0a, 0xa3, 0x01, 0x0a, 0x02, + 0x04, 0x01, 0x12, 0x04, 0x1b, 0x00, 0x29, 0x01, 0x1a, 0x96, 0x01, 0x20, 0x45, 0x6e, 0x63, 0x6f, + 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x20, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x73, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x0a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, + 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2e, + 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x1b, 0x08, 0x16, 0x0a, 0x65, 0x0a, + 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x1e, 0x02, 0x19, 0x1a, 0x58, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x66, 0x69, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x74, + 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, + 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, + 0x65, 0x72, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, 0x1e, + 0x02, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x1e, 0x10, 0x14, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x1e, 0x17, 0x18, 0x0a, 0x54, + 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x20, 0x02, 0x25, 0x1a, 0x47, 0x20, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, + 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, + 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x20, + 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x20, 0x16, 0x20, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x20, 0x23, 0x24, 0x0a, 0x84, + 0x01, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x23, 0x02, 0x1f, 0x1a, 0x77, 0x20, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, + 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, + 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, + 0x63, 0x61, 0x73, 0x65, 0x0a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x04, 0x12, 0x03, + 0x23, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x05, 0x12, 0x03, 0x23, 0x0b, + 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x23, 0x12, 0x1a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x23, 0x1d, 0x1e, 0x0a, 0x6e, 0x0a, + 0x04, 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x26, 0x02, 0x27, 0x1a, 0x61, 0x20, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x6e, 0x64, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, + 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x03, 0x04, 0x12, 0x03, 0x26, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x03, 0x06, 0x12, 0x03, 0x26, 0x0b, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x03, 0x01, 0x12, 0x03, 0x26, 0x17, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x03, + 0x12, 0x03, 0x26, 0x25, 0x26, 0x0a, 0x25, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x04, 0x12, 0x03, 0x28, + 0x02, 0x14, 0x1a, 0x18, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x01, 0x02, 0x04, 0x05, 0x12, 0x03, 0x28, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, + 0x02, 0x04, 0x01, 0x12, 0x03, 0x28, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, + 0x03, 0x12, 0x03, 0x28, 0x12, 0x13, 0x0a, 0x55, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x2c, 0x00, + 0x4c, 0x01, 0x1a, 0x49, 0x20, 0x41, 0x20, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6f, 0x75, 0x74, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x65, 0x74, 0x73, 0x20, 0x65, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x4d, 0x4c, 0x53, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x2c, 0x08, 0x19, 0x0a, 0x33, 0x0a, 0x04, 0x04, 0x02, 0x03, + 0x00, 0x12, 0x04, 0x2e, 0x02, 0x34, 0x03, 0x1a, 0x25, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x20, 0x31, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x02, 0x03, 0x00, 0x01, 0x12, 0x03, 0x2e, 0x0a, 0x0c, 0x0a, 0x2e, 0x0a, 0x06, + 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x30, 0x04, 0x16, 0x1a, 0x1f, 0x20, 0x45, 0x78, + 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x45, 0x6e, 0x63, + 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x30, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x30, 0x0a, 0x11, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x30, 0x14, 0x15, 0x0a, 0x8c, 0x01, 0x0a, + 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x33, 0x04, 0x1f, 0x1a, 0x7d, 0x20, 0x41, + 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x74, 0x68, + 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, + 0x6f, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x63, + 0x61, 0x6e, 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, + 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x2e, 0x20, 0x4d, 0x61, + 0x79, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x33, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x33, 0x0b, 0x1a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, + 0x02, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x33, 0x1d, 0x1e, 0x0a, 0x33, 0x0a, 0x04, 0x04, + 0x02, 0x03, 0x01, 0x12, 0x04, 0x37, 0x02, 0x44, 0x03, 0x1a, 0x25, 0x20, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x01, 0x01, 0x12, 0x03, 0x37, 0x0a, 0x0c, 0x0a, 0x8c, + 0x01, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x12, 0x03, 0x3a, 0x04, 0x1f, 0x1a, 0x7d, + 0x20, 0x41, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, + 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, + 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x20, 0x63, 0x61, 0x6e, 0x0a, 0x20, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x20, 0x64, 0x69, + 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x2e, 0x20, + 0x4d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x65, + 0x72, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x0a, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x3a, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x3a, 0x0b, 0x1a, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3a, 0x1d, 0x1e, 0x0a, 0x0e, 0x0a, + 0x06, 0x04, 0x02, 0x03, 0x01, 0x08, 0x00, 0x12, 0x04, 0x3c, 0x04, 0x43, 0x05, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x02, 0x03, 0x01, 0x08, 0x00, 0x01, 0x12, 0x03, 0x3c, 0x0a, 0x16, 0x0a, 0x2e, 0x0a, + 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x12, 0x03, 0x3e, 0x06, 0x18, 0x1a, 0x1f, 0x20, 0x45, + 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x45, 0x6e, + 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x0a, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x05, 0x12, 0x03, 0x3e, 0x06, 0x0b, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x01, 0x12, 0x03, 0x3e, 0x0c, 0x13, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x3e, 0x16, 0x17, 0x0a, 0x45, 0x0a, + 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x12, 0x03, 0x40, 0x06, 0x28, 0x1a, 0x36, 0x20, 0x49, + 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x61, + 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x79, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x06, 0x12, + 0x03, 0x40, 0x06, 0x1b, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x01, 0x12, + 0x03, 0x40, 0x1c, 0x23, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x12, + 0x03, 0x40, 0x26, 0x27, 0x0a, 0x41, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x01, 0x02, 0x03, 0x12, 0x03, + 0x42, 0x06, 0x24, 0x1a, 0x32, 0x20, 0x53, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, + 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x61, + 0x20, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, + 0x03, 0x06, 0x12, 0x03, 0x42, 0x06, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, + 0x03, 0x01, 0x12, 0x03, 0x42, 0x1a, 0x1f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x01, 0x02, + 0x03, 0x03, 0x12, 0x03, 0x42, 0x22, 0x23, 0x0a, 0x66, 0x0a, 0x04, 0x04, 0x02, 0x08, 0x00, 0x12, + 0x04, 0x48, 0x02, 0x4b, 0x03, 0x1a, 0x58, 0x20, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, + 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x0a, 0x20, 0x50, 0x6c, 0x61, 0x69, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x69, 0x73, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x08, 0x00, 0x01, 0x12, 0x03, 0x48, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, + 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x49, 0x04, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x00, 0x06, 0x12, 0x03, 0x49, 0x04, 0x06, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, + 0x01, 0x12, 0x03, 0x49, 0x07, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, + 0x03, 0x49, 0x0c, 0x0d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x4a, 0x04, + 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x4a, 0x04, 0x06, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x4a, 0x07, 0x09, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x4a, 0x0c, 0x0d, 0x0a, 0x57, 0x0a, 0x02, 0x04, + 0x03, 0x12, 0x04, 0x4f, 0x00, 0x54, 0x01, 0x1a, 0x4b, 0x20, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, + 0x74, 0x6f, 0x72, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x64, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x20, + 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x4f, 0x08, 0x1d, + 0x0a, 0x31, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x51, 0x02, 0x18, 0x1a, 0x24, 0x20, + 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x05, 0x12, 0x03, 0x51, 0x02, + 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x51, 0x09, 0x13, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x51, 0x16, 0x17, 0x0a, 0x2d, 0x0a, + 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, 0x53, 0x02, 0x16, 0x1a, 0x20, 0x20, 0x45, 0x6e, 0x73, + 0x75, 0x72, 0x65, 0x73, 0x20, 0x61, 0x20, 0x68, 0x75, 0x6d, 0x61, 0x6e, 0x20, 0x69, 0x73, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x03, 0x02, 0x01, 0x05, 0x12, 0x03, 0x53, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x53, 0x09, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x53, 0x14, 0x15, 0x0a, 0x5a, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x57, 0x00, + 0x5e, 0x01, 0x1a, 0x4e, 0x20, 0x50, 0x72, 0x65, 0x2d, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, + 0x67, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, + 0x64, 0x20, 0x63, 0x61, 0x70, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x70, + 0x70, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x20, 0x73, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x72, 0x65, 0x70, 0x6c, + 0x79, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x57, 0x08, 0x1b, 0x0a, 0x4f, + 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x59, 0x02, 0x18, 0x1a, 0x42, 0x20, 0x4d, 0x75, + 0x73, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, + 0x74, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x20, + 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x68, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x05, 0x12, 0x03, 0x59, 0x02, 0x08, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x59, 0x09, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x59, 0x16, 0x17, 0x0a, 0x37, 0x0a, 0x04, 0x04, 0x04, 0x02, + 0x01, 0x12, 0x03, 0x5b, 0x02, 0x11, 0x1a, 0x2a, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, + 0x62, 0x65, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x05, 0x12, 0x03, 0x5b, 0x02, 0x08, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x5b, 0x09, 0x0c, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x5b, 0x0f, 0x10, 0x0a, 0x5a, 0x0a, 0x04, + 0x04, 0x04, 0x02, 0x02, 0x12, 0x03, 0x5d, 0x02, 0x2b, 0x1a, 0x4d, 0x20, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x27, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x27, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x45, 0x53, + 0x20, 0x4b, 0x65, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2d, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, + 0x06, 0x12, 0x03, 0x5d, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, + 0x03, 0x5d, 0x18, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, 0x03, 0x5d, + 0x29, 0x2a, 0x0a, 0x34, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x61, 0x00, 0x65, 0x01, 0x1a, 0x28, + 0x20, 0x4b, 0x65, 0x79, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2d, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, + 0x03, 0x61, 0x08, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x05, 0x08, 0x00, 0x12, 0x04, 0x62, 0x02, + 0x64, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x08, 0x00, 0x01, 0x12, 0x03, 0x62, 0x08, 0x0b, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x63, 0x04, 0x20, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x05, 0x02, 0x00, 0x05, 0x12, 0x03, 0x63, 0x04, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, 0x63, 0x0a, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, + 0x00, 0x03, 0x12, 0x03, 0x63, 0x1e, 0x1f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0a, 0x90, 0x06, 0x0a, 0x2b, 0x6d, 0x6c, 0x73, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, diff --git a/xmtp_proto/src/gen/xmtp.mls.message_contents.serde.rs b/xmtp_proto/src/gen/xmtp.mls.message_contents.serde.rs index 6b8b584f8..550fe8166 100644 --- a/xmtp_proto/src/gen/xmtp.mls.message_contents.serde.rs +++ b/xmtp_proto/src/gen/xmtp.mls.message_contents.serde.rs @@ -1,75 +1,4 @@ // @generated -impl serde::Serialize for AssociationTextVersion { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - let variant = match self { - Self::Unspecified => "ASSOCIATION_TEXT_VERSION_UNSPECIFIED", - Self::AssociationTextVersion1 => "ASSOCIATION_TEXT_VERSION_1", - }; - serializer.serialize_str(variant) - } -} -impl<'de> serde::Deserialize<'de> for AssociationTextVersion { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "ASSOCIATION_TEXT_VERSION_UNSPECIFIED", - "ASSOCIATION_TEXT_VERSION_1", - ]; - - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = AssociationTextVersion; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - fn visit_i64(self, v: i64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) - }) - } - - fn visit_u64(self, v: u64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) - }) - } - - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "ASSOCIATION_TEXT_VERSION_UNSPECIFIED" => Ok(AssociationTextVersion::Unspecified), - "ASSOCIATION_TEXT_VERSION_1" => Ok(AssociationTextVersion::AssociationTextVersion1), - _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), - } - } - } - deserializer.deserialize_any(GeneratedVisitor) - } -} impl serde::Serialize for Compression { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -368,142 +297,6 @@ impl<'de> serde::Deserialize<'de> for ConversationType { deserializer.deserialize_any(GeneratedVisitor) } } -impl serde::Serialize for CredentialRevocation { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.public_key.is_some() { - len += 1; - } - if self.association.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.CredentialRevocation", len)?; - if let Some(v) = self.public_key.as_ref() { - match v { - credential_revocation::PublicKey::InstallationKey(v) => { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("installationKey", pbjson::private::base64::encode(&v).as_str())?; - } - credential_revocation::PublicKey::UnsignedLegacyCreateIdentityKey(v) => { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("unsignedLegacyCreateIdentityKey", pbjson::private::base64::encode(&v).as_str())?; - } - } - } - if let Some(v) = self.association.as_ref() { - match v { - credential_revocation::Association::MessagingAccess(v) => { - struct_ser.serialize_field("messagingAccess", v)?; - } - } - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for CredentialRevocation { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "installation_key", - "installationKey", - "unsigned_legacy_create_identity_key", - "unsignedLegacyCreateIdentityKey", - "messaging_access", - "messagingAccess", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - InstallationKey, - UnsignedLegacyCreateIdentityKey, - MessagingAccess, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "installationKey" | "installation_key" => Ok(GeneratedField::InstallationKey), - "unsignedLegacyCreateIdentityKey" | "unsigned_legacy_create_identity_key" => Ok(GeneratedField::UnsignedLegacyCreateIdentityKey), - "messagingAccess" | "messaging_access" => Ok(GeneratedField::MessagingAccess), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = CredentialRevocation; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.mls.message_contents.CredentialRevocation") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut public_key__ = None; - let mut association__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::InstallationKey => { - if public_key__.is_some() { - return Err(serde::de::Error::duplicate_field("installationKey")); - } - public_key__ = map_.next_value::<::std::option::Option<::pbjson::private::BytesDeserialize<_>>>()?.map(|x| credential_revocation::PublicKey::InstallationKey(x.0)); - } - GeneratedField::UnsignedLegacyCreateIdentityKey => { - if public_key__.is_some() { - return Err(serde::de::Error::duplicate_field("unsignedLegacyCreateIdentityKey")); - } - public_key__ = map_.next_value::<::std::option::Option<::pbjson::private::BytesDeserialize<_>>>()?.map(|x| credential_revocation::PublicKey::UnsignedLegacyCreateIdentityKey(x.0)); - } - GeneratedField::MessagingAccess => { - if association__.is_some() { - return Err(serde::de::Error::duplicate_field("messagingAccess")); - } - association__ = map_.next_value::<::std::option::Option<_>>()?.map(credential_revocation::Association::MessagingAccess) -; - } - } - } - Ok(CredentialRevocation { - public_key: public_key__, - association: association__, - }) - } - } - deserializer.deserialize_struct("xmtp.mls.message_contents.CredentialRevocation", FIELDS, GeneratedVisitor) - } -} impl serde::Serialize for DmMembers { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -614,101 +407,6 @@ impl<'de> serde::Deserialize<'de> for DmMembers { deserializer.deserialize_struct("xmtp.mls.message_contents.DmMembers", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for EdDsaSignature { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.bytes.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.EdDsaSignature", len)?; - if !self.bytes.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("bytes", pbjson::private::base64::encode(&self.bytes).as_str())?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for EdDsaSignature { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "bytes", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Bytes, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "bytes" => Ok(GeneratedField::Bytes), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = EdDsaSignature; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.mls.message_contents.EdDsaSignature") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut bytes__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Bytes => { - if bytes__.is_some() { - return Err(serde::de::Error::duplicate_field("bytes")); - } - bytes__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - } - } - Ok(EdDsaSignature { - bytes: bytes__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("xmtp.mls.message_contents.EdDsaSignature", FIELDS, GeneratedVisitor) - } -} impl serde::Serialize for EncodedContent { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -743,201 +441,39 @@ impl serde::Serialize for EncodedContent { struct_ser.serialize_field("fallback", v)?; } if let Some(v) = self.compression.as_ref() { - let v = Compression::try_from(*v) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", *v)))?; - struct_ser.serialize_field("compression", &v)?; - } - if !self.content.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("content", pbjson::private::base64::encode(&self.content).as_str())?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for EncodedContent { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "type", - "parameters", - "fallback", - "compression", - "content", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Type, - Parameters, - Fallback, - Compression, - Content, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "type" => Ok(GeneratedField::Type), - "parameters" => Ok(GeneratedField::Parameters), - "fallback" => Ok(GeneratedField::Fallback), - "compression" => Ok(GeneratedField::Compression), - "content" => Ok(GeneratedField::Content), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = EncodedContent; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.mls.message_contents.EncodedContent") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut r#type__ = None; - let mut parameters__ = None; - let mut fallback__ = None; - let mut compression__ = None; - let mut content__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Type => { - if r#type__.is_some() { - return Err(serde::de::Error::duplicate_field("type")); - } - r#type__ = map_.next_value()?; - } - GeneratedField::Parameters => { - if parameters__.is_some() { - return Err(serde::de::Error::duplicate_field("parameters")); - } - parameters__ = Some( - map_.next_value::>()? - ); - } - GeneratedField::Fallback => { - if fallback__.is_some() { - return Err(serde::de::Error::duplicate_field("fallback")); - } - fallback__ = map_.next_value()?; - } - GeneratedField::Compression => { - if compression__.is_some() { - return Err(serde::de::Error::duplicate_field("compression")); - } - compression__ = map_.next_value::<::std::option::Option>()?.map(|x| x as i32); - } - GeneratedField::Content => { - if content__.is_some() { - return Err(serde::de::Error::duplicate_field("content")); - } - content__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - } - } - Ok(EncodedContent { - r#type: r#type__, - parameters: parameters__.unwrap_or_default(), - fallback: fallback__, - compression: compression__, - content: content__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("xmtp.mls.message_contents.EncodedContent", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for GrantMessagingAccessAssociation { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.association_text_version != 0 { - len += 1; - } - if self.signature.is_some() { - len += 1; - } - if !self.account_address.is_empty() { - len += 1; - } - if self.created_ns != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.GrantMessagingAccessAssociation", len)?; - if self.association_text_version != 0 { - let v = AssociationTextVersion::try_from(self.association_text_version) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.association_text_version)))?; - struct_ser.serialize_field("associationTextVersion", &v)?; - } - if let Some(v) = self.signature.as_ref() { - struct_ser.serialize_field("signature", v)?; - } - if !self.account_address.is_empty() { - struct_ser.serialize_field("accountAddress", &self.account_address)?; + let v = Compression::try_from(*v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", *v)))?; + struct_ser.serialize_field("compression", &v)?; } - if self.created_ns != 0 { + if !self.content.is_empty() { #[allow(clippy::needless_borrow)] #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("createdNs", ToString::to_string(&self.created_ns).as_str())?; + struct_ser.serialize_field("content", pbjson::private::base64::encode(&self.content).as_str())?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for GrantMessagingAccessAssociation { +impl<'de> serde::Deserialize<'de> for EncodedContent { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "association_text_version", - "associationTextVersion", - "signature", - "account_address", - "accountAddress", - "created_ns", - "createdNs", + "type", + "parameters", + "fallback", + "compression", + "content", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - AssociationTextVersion, - Signature, - AccountAddress, - CreatedNs, + Type, + Parameters, + Fallback, + Compression, + Content, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -959,10 +495,11 @@ impl<'de> serde::Deserialize<'de> for GrantMessagingAccessAssociation { E: serde::de::Error, { match value { - "associationTextVersion" | "association_text_version" => Ok(GeneratedField::AssociationTextVersion), - "signature" => Ok(GeneratedField::Signature), - "accountAddress" | "account_address" => Ok(GeneratedField::AccountAddress), - "createdNs" | "created_ns" => Ok(GeneratedField::CreatedNs), + "type" => Ok(GeneratedField::Type), + "parameters" => Ok(GeneratedField::Parameters), + "fallback" => Ok(GeneratedField::Fallback), + "compression" => Ok(GeneratedField::Compression), + "content" => Ok(GeneratedField::Content), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -972,59 +509,69 @@ impl<'de> serde::Deserialize<'de> for GrantMessagingAccessAssociation { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GrantMessagingAccessAssociation; + type Value = EncodedContent; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.mls.message_contents.GrantMessagingAccessAssociation") + formatter.write_str("struct xmtp.mls.message_contents.EncodedContent") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut association_text_version__ = None; - let mut signature__ = None; - let mut account_address__ = None; - let mut created_ns__ = None; + let mut r#type__ = None; + let mut parameters__ = None; + let mut fallback__ = None; + let mut compression__ = None; + let mut content__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::AssociationTextVersion => { - if association_text_version__.is_some() { - return Err(serde::de::Error::duplicate_field("associationTextVersion")); + GeneratedField::Type => { + if r#type__.is_some() { + return Err(serde::de::Error::duplicate_field("type")); } - association_text_version__ = Some(map_.next_value::()? as i32); + r#type__ = map_.next_value()?; } - GeneratedField::Signature => { - if signature__.is_some() { - return Err(serde::de::Error::duplicate_field("signature")); + GeneratedField::Parameters => { + if parameters__.is_some() { + return Err(serde::de::Error::duplicate_field("parameters")); } - signature__ = map_.next_value()?; + parameters__ = Some( + map_.next_value::>()? + ); } - GeneratedField::AccountAddress => { - if account_address__.is_some() { - return Err(serde::de::Error::duplicate_field("accountAddress")); + GeneratedField::Fallback => { + if fallback__.is_some() { + return Err(serde::de::Error::duplicate_field("fallback")); } - account_address__ = Some(map_.next_value()?); + fallback__ = map_.next_value()?; } - GeneratedField::CreatedNs => { - if created_ns__.is_some() { - return Err(serde::de::Error::duplicate_field("createdNs")); + GeneratedField::Compression => { + if compression__.is_some() { + return Err(serde::de::Error::duplicate_field("compression")); } - created_ns__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + compression__ = map_.next_value::<::std::option::Option>()?.map(|x| x as i32); + } + GeneratedField::Content => { + if content__.is_some() { + return Err(serde::de::Error::duplicate_field("content")); + } + content__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) ; } } } - Ok(GrantMessagingAccessAssociation { - association_text_version: association_text_version__.unwrap_or_default(), - signature: signature__, - account_address: account_address__.unwrap_or_default(), - created_ns: created_ns__.unwrap_or_default(), + Ok(EncodedContent { + r#type: r#type__, + parameters: parameters__.unwrap_or_default(), + fallback: fallback__, + compression: compression__, + content: content__.unwrap_or_default(), }) } } - deserializer.deserialize_struct("xmtp.mls.message_contents.GrantMessagingAccessAssociation", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("xmtp.mls.message_contents.EncodedContent", FIELDS, GeneratedVisitor) } } impl serde::Serialize for GroupMembership { @@ -2187,115 +1734,6 @@ impl<'de> serde::Deserialize<'de> for Inboxes { deserializer.deserialize_struct("xmtp.mls.message_contents.Inboxes", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for LegacyCreateIdentityAssociation { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.signature.is_some() { - len += 1; - } - if self.signed_legacy_create_identity_key.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.LegacyCreateIdentityAssociation", len)?; - if let Some(v) = self.signature.as_ref() { - struct_ser.serialize_field("signature", v)?; - } - if let Some(v) = self.signed_legacy_create_identity_key.as_ref() { - struct_ser.serialize_field("signedLegacyCreateIdentityKey", v)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for LegacyCreateIdentityAssociation { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "signature", - "signed_legacy_create_identity_key", - "signedLegacyCreateIdentityKey", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Signature, - SignedLegacyCreateIdentityKey, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "signature" => Ok(GeneratedField::Signature), - "signedLegacyCreateIdentityKey" | "signed_legacy_create_identity_key" => Ok(GeneratedField::SignedLegacyCreateIdentityKey), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = LegacyCreateIdentityAssociation; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.mls.message_contents.LegacyCreateIdentityAssociation") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut signature__ = None; - let mut signed_legacy_create_identity_key__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Signature => { - if signature__.is_some() { - return Err(serde::de::Error::duplicate_field("signature")); - } - signature__ = map_.next_value()?; - } - GeneratedField::SignedLegacyCreateIdentityKey => { - if signed_legacy_create_identity_key__.is_some() { - return Err(serde::de::Error::duplicate_field("signedLegacyCreateIdentityKey")); - } - signed_legacy_create_identity_key__ = map_.next_value()?; - } - } - } - Ok(LegacyCreateIdentityAssociation { - signature: signature__, - signed_legacy_create_identity_key: signed_legacy_create_identity_key__, - }) - } - } - deserializer.deserialize_struct("xmtp.mls.message_contents.LegacyCreateIdentityAssociation", FIELDS, GeneratedVisitor) - } -} impl serde::Serialize for MembershipChange { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -3474,199 +2912,66 @@ impl serde::Serialize for metadata_policy::MetadataBasePolicy { } impl<'de> serde::Deserialize<'de> for metadata_policy::MetadataBasePolicy { #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "METADATA_BASE_POLICY_UNSPECIFIED", - "METADATA_BASE_POLICY_ALLOW", - "METADATA_BASE_POLICY_DENY", - "METADATA_BASE_POLICY_ALLOW_IF_ADMIN", - "METADATA_BASE_POLICY_ALLOW_IF_SUPER_ADMIN", - ]; - - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = metadata_policy::MetadataBasePolicy; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - fn visit_i64(self, v: i64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) - }) - } - - fn visit_u64(self, v: u64) -> std::result::Result - where - E: serde::de::Error, - { - i32::try_from(v) - .ok() - .and_then(|x| x.try_into().ok()) - .ok_or_else(|| { - serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) - }) - } - - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "METADATA_BASE_POLICY_UNSPECIFIED" => Ok(metadata_policy::MetadataBasePolicy::Unspecified), - "METADATA_BASE_POLICY_ALLOW" => Ok(metadata_policy::MetadataBasePolicy::Allow), - "METADATA_BASE_POLICY_DENY" => Ok(metadata_policy::MetadataBasePolicy::Deny), - "METADATA_BASE_POLICY_ALLOW_IF_ADMIN" => Ok(metadata_policy::MetadataBasePolicy::AllowIfAdmin), - "METADATA_BASE_POLICY_ALLOW_IF_SUPER_ADMIN" => Ok(metadata_policy::MetadataBasePolicy::AllowIfSuperAdmin), - _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), - } - } - } - deserializer.deserialize_any(GeneratedVisitor) - } -} -impl serde::Serialize for MlsCredential { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.installation_public_key.is_empty() { - len += 1; - } - if self.association.is_some() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.MlsCredential", len)?; - if !self.installation_public_key.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("installationPublicKey", pbjson::private::base64::encode(&self.installation_public_key).as_str())?; - } - if let Some(v) = self.association.as_ref() { - match v { - mls_credential::Association::MessagingAccess(v) => { - struct_ser.serialize_field("messagingAccess", v)?; - } - mls_credential::Association::LegacyCreateIdentity(v) => { - struct_ser.serialize_field("legacyCreateIdentity", v)?; - } - } - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for MlsCredential { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "installation_public_key", - "installationPublicKey", - "messaging_access", - "messagingAccess", - "legacy_create_identity", - "legacyCreateIdentity", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - InstallationPublicKey, - MessagingAccess, - LegacyCreateIdentity, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "METADATA_BASE_POLICY_UNSPECIFIED", + "METADATA_BASE_POLICY_ALLOW", + "METADATA_BASE_POLICY_DENY", + "METADATA_BASE_POLICY_ALLOW_IF_ADMIN", + "METADATA_BASE_POLICY_ALLOW_IF_SUPER_ADMIN", + ]; - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "installationPublicKey" | "installation_public_key" => Ok(GeneratedField::InstallationPublicKey), - "messagingAccess" | "messaging_access" => Ok(GeneratedField::MessagingAccess), - "legacyCreateIdentity" | "legacy_create_identity" => Ok(GeneratedField::LegacyCreateIdentity), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = MlsCredential; + type Value = metadata_policy::MetadataBasePolicy; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.mls.message_contents.MlsCredential") + write!(formatter, "expected one of: {:?}", &FIELDS) } - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, { - let mut installation_public_key__ = None; - let mut association__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::InstallationPublicKey => { - if installation_public_key__.is_some() { - return Err(serde::de::Error::duplicate_field("installationPublicKey")); - } - installation_public_key__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - GeneratedField::MessagingAccess => { - if association__.is_some() { - return Err(serde::de::Error::duplicate_field("messagingAccess")); - } - association__ = map_.next_value::<::std::option::Option<_>>()?.map(mls_credential::Association::MessagingAccess) -; - } - GeneratedField::LegacyCreateIdentity => { - if association__.is_some() { - return Err(serde::de::Error::duplicate_field("legacyCreateIdentity")); - } - association__ = map_.next_value::<::std::option::Option<_>>()?.map(mls_credential::Association::LegacyCreateIdentity) -; - } - } + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "METADATA_BASE_POLICY_UNSPECIFIED" => Ok(metadata_policy::MetadataBasePolicy::Unspecified), + "METADATA_BASE_POLICY_ALLOW" => Ok(metadata_policy::MetadataBasePolicy::Allow), + "METADATA_BASE_POLICY_DENY" => Ok(metadata_policy::MetadataBasePolicy::Deny), + "METADATA_BASE_POLICY_ALLOW_IF_ADMIN" => Ok(metadata_policy::MetadataBasePolicy::AllowIfAdmin), + "METADATA_BASE_POLICY_ALLOW_IF_SUPER_ADMIN" => Ok(metadata_policy::MetadataBasePolicy::AllowIfSuperAdmin), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), } - Ok(MlsCredential { - installation_public_key: installation_public_key__.unwrap_or_default(), - association: association__, - }) } } - deserializer.deserialize_struct("xmtp.mls.message_contents.MlsCredential", FIELDS, GeneratedVisitor) + deserializer.deserialize_any(GeneratedVisitor) } } impl serde::Serialize for PermissionsUpdatePolicy { @@ -4600,249 +3905,3 @@ impl<'de> serde::Deserialize<'de> for PolicySet { deserializer.deserialize_struct("xmtp.mls.message_contents.PolicySet", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for RecoverableEcdsaSignature { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.bytes.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.RecoverableEcdsaSignature", len)?; - if !self.bytes.is_empty() { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("bytes", pbjson::private::base64::encode(&self.bytes).as_str())?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for RecoverableEcdsaSignature { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "bytes", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Bytes, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "bytes" => Ok(GeneratedField::Bytes), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = RecoverableEcdsaSignature; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.mls.message_contents.RecoverableEcdsaSignature") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut bytes__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::Bytes => { - if bytes__.is_some() { - return Err(serde::de::Error::duplicate_field("bytes")); - } - bytes__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - } - } - Ok(RecoverableEcdsaSignature { - bytes: bytes__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("xmtp.mls.message_contents.RecoverableEcdsaSignature", FIELDS, GeneratedVisitor) - } -} -impl serde::Serialize for RevokeMessagingAccessAssociation { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if self.association_text_version != 0 { - len += 1; - } - if self.signature.is_some() { - len += 1; - } - if !self.account_address.is_empty() { - len += 1; - } - if self.created_ns != 0 { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("xmtp.mls.message_contents.RevokeMessagingAccessAssociation", len)?; - if self.association_text_version != 0 { - let v = AssociationTextVersion::try_from(self.association_text_version) - .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", self.association_text_version)))?; - struct_ser.serialize_field("associationTextVersion", &v)?; - } - if let Some(v) = self.signature.as_ref() { - struct_ser.serialize_field("signature", v)?; - } - if !self.account_address.is_empty() { - struct_ser.serialize_field("accountAddress", &self.account_address)?; - } - if self.created_ns != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("createdNs", ToString::to_string(&self.created_ns).as_str())?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for RevokeMessagingAccessAssociation { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "association_text_version", - "associationTextVersion", - "signature", - "account_address", - "accountAddress", - "created_ns", - "createdNs", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - AssociationTextVersion, - Signature, - AccountAddress, - CreatedNs, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "associationTextVersion" | "association_text_version" => Ok(GeneratedField::AssociationTextVersion), - "signature" => Ok(GeneratedField::Signature), - "accountAddress" | "account_address" => Ok(GeneratedField::AccountAddress), - "createdNs" | "created_ns" => Ok(GeneratedField::CreatedNs), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = RevokeMessagingAccessAssociation; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.mls.message_contents.RevokeMessagingAccessAssociation") - } - - fn visit_map(self, mut map_: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut association_text_version__ = None; - let mut signature__ = None; - let mut account_address__ = None; - let mut created_ns__ = None; - while let Some(k) = map_.next_key()? { - match k { - GeneratedField::AssociationTextVersion => { - if association_text_version__.is_some() { - return Err(serde::de::Error::duplicate_field("associationTextVersion")); - } - association_text_version__ = Some(map_.next_value::()? as i32); - } - GeneratedField::Signature => { - if signature__.is_some() { - return Err(serde::de::Error::duplicate_field("signature")); - } - signature__ = map_.next_value()?; - } - GeneratedField::AccountAddress => { - if account_address__.is_some() { - return Err(serde::de::Error::duplicate_field("accountAddress")); - } - account_address__ = Some(map_.next_value()?); - } - GeneratedField::CreatedNs => { - if created_ns__.is_some() { - return Err(serde::de::Error::duplicate_field("createdNs")); - } - created_ns__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; - } - } - } - Ok(RevokeMessagingAccessAssociation { - association_text_version: association_text_version__.unwrap_or_default(), - signature: signature__, - account_address: account_address__.unwrap_or_default(), - created_ns: created_ns__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("xmtp.mls.message_contents.RevokeMessagingAccessAssociation", FIELDS, GeneratedVisitor) - } -} diff --git a/xmtp_proto/src/gen/xmtp.mls_validation.v1.rs b/xmtp_proto/src/gen/xmtp.mls_validation.v1.rs index c1a1c1bdf..9a83e9d4b 100644 --- a/xmtp_proto/src/gen/xmtp.mls_validation.v1.rs +++ b/xmtp_proto/src/gen/xmtp.mls_validation.v1.rs @@ -1,5 +1,24 @@ // @generated // This file is @generated by prost-build. +/// Contains a batch of serialized Key Packages +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ValidateInboxIdKeyPackagesRequest { + #[prost(message, repeated, tag="1")] + pub key_packages: ::prost::alloc::vec::Vec, +} +/// Nested message and enum types in `ValidateInboxIdKeyPackagesRequest`. +pub mod validate_inbox_id_key_packages_request { + /// Wrapper for each key package + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct KeyPackage { + #[prost(bytes="vec", tag="1")] + pub key_package_bytes_tls_serialized: ::prost::alloc::vec::Vec, + #[prost(bool, tag="2")] + pub is_inbox_id_credential: bool, + } +} /// Validates a Inbox-ID Key Package Type #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -175,498 +194,565 @@ pub mod validate_inbox_ids_response { } /// Encoded file descriptor set for the `xmtp.mls_validation.v1` package pub const FILE_DESCRIPTOR_SET: &[u8] = &[ - 0x0a, 0xb5, 0x3d, 0x0a, 0x1f, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x0a, 0xe9, 0x45, 0x0a, 0x1f, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x1a, 0x27, 0x69, 0x64, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x1a, 0x1e, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0xe4, 0x02, 0x0a, 0x22, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, - 0x6f, 0x78, 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x25, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, + 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x02, 0x0a, 0x21, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x67, 0x0a, + 0x0c, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4b, + 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x0b, 0x6b, 0x65, 0x79, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x89, 0x01, 0x0a, 0x0a, 0x4b, 0x65, 0x79, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x46, 0x0a, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x73, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x1c, 0x6b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x54, 0x6c, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x33, 0x0a, + 0x16, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x5f, 0x63, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, + 0x73, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x22, 0xe4, 0x02, 0x0a, 0x22, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, + 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x09, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, + 0x62, 0x6f, 0x78, 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0xda, 0x01, 0x0a, + 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x69, 0x73, 0x5f, + 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x12, 0x23, + 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x3c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x4d, 0x6c, 0x73, 0x43, 0x72, 0x65, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, + 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8a, 0x02, 0x0a, 0x1a, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x60, 0x0a, 0x0c, 0x6b, 0x65, 0x79, 0x5f, + 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x0b, 0x6b, + 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x89, 0x01, 0x0a, 0x0a, 0x4b, + 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x46, 0x0a, 0x20, 0x6b, 0x65, 0x79, + 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x74, + 0x6c, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x1c, 0x6b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x42, + 0x79, 0x74, 0x65, 0x73, 0x54, 0x6c, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x64, 0x12, 0x33, 0x0a, 0x16, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, + 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x13, 0x69, 0x73, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x43, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x82, 0x03, 0x0a, 0x1b, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0xfc, 0x01, 0x0a, + 0x12, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x69, 0x73, 0x5f, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, + 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x3a, 0x0a, 0x19, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x17, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xe4, 0x01, 0x0a, 0x1c, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x68, 0x0a, 0x0e, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x5a, 0x0a, 0x0c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4a, 0x0a, 0x22, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6c, + 0x73, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x1e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x42, 0x79, 0x74, 0x65, 0x73, 0x54, 0x6c, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x64, 0x22, 0xf2, 0x01, 0x0a, 0x1d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, + 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x69, 0x0a, 0x12, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x69, 0x73, 0x5f, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x22, 0xb6, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x41, + 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x6f, 0x6c, 0x64, 0x5f, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, + 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6f, 0x6c, 0x64, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6e, 0x65, 0x77, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, + 0x22, 0xc9, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x59, 0x0a, 0x11, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, + 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x10, 0x61, 0x73, 0x73, 0x6f, 0x63, + 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x4f, 0x0a, 0x0a, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, + 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x73, 0x73, + 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x66, + 0x66, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x66, 0x66, 0x22, 0xdb, 0x02, 0x0a, + 0x17, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, + 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0xe0, 0x01, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, + 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2e, 0x4d, 0x6c, 0x73, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, + 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x17, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x4b, 0x65, 0x79, 0x12, 0x55, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, + 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0xe8, 0x01, 0x0a, 0x18, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, - 0x78, 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, - 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0xda, 0x01, 0x0a, 0x08, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x69, 0x73, 0x5f, 0x6f, 0x6b, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x12, 0x23, 0x0a, 0x0d, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x3c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x4d, 0x6c, 0x73, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x61, 0x6c, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, - 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x8a, 0x02, 0x0a, 0x1a, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x60, 0x0a, 0x0c, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, - 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x0b, 0x6b, 0x65, 0x79, - 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x89, 0x01, 0x0a, 0x0a, 0x4b, 0x65, 0x79, - 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x46, 0x0a, 0x20, 0x6b, 0x65, 0x79, 0x5f, 0x70, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6c, 0x73, - 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x1c, 0x6b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x54, 0x6c, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, - 0x33, 0x0a, 0x16, 0x69, 0x73, 0x5f, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x5f, 0x63, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x13, 0x69, 0x73, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x61, 0x6c, 0x22, 0x82, 0x03, 0x0a, 0x1b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, - 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0xfc, 0x01, 0x0a, 0x12, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x13, 0x0a, 0x05, 0x69, 0x73, 0x5f, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3a, 0x0a, - 0x19, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x17, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x65, - 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xe4, 0x01, 0x0a, 0x1c, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x68, 0x0a, 0x0e, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x73, 0x1a, 0x5a, 0x0a, 0x0c, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x4a, 0x0a, 0x22, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6c, 0x73, 0x5f, - 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x1e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x54, 0x6c, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, - 0x22, 0xf2, 0x01, 0x0a, 0x1d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x66, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, - 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, + 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x69, 0x0a, 0x12, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x13, 0x0a, 0x05, 0x69, 0x73, 0x5f, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x73, 0x4f, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x49, 0x64, 0x22, 0xb6, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x6f, 0x6c, 0x64, 0x5f, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6f, 0x6c, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x73, 0x12, 0x4b, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x52, 0x0a, 0x6e, 0x65, 0x77, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0xc9, - 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, - 0x0a, 0x11, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x10, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x4f, 0x0a, 0x0a, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x41, 0x73, 0x73, 0x6f, 0x63, - 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x66, 0x66, 0x52, - 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x44, 0x69, 0x66, 0x66, 0x22, 0xdb, 0x02, 0x0a, 0x17, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, - 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0xe0, 0x01, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0a, 0x63, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, - 0x4d, 0x6c, 0x73, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x0a, 0x63, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, - 0x79, 0x12, 0x55, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, - 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0xe8, 0x01, 0x0a, 0x18, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x69, 0x0a, 0x12, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x13, - 0x0a, 0x05, 0x69, 0x73, 0x5f, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, - 0x73, 0x4f, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, - 0x78, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, - 0x78, 0x49, 0x64, 0x32, 0xa8, 0x05, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x41, 0x70, 0x69, 0x12, 0x80, 0x01, 0x0a, 0x13, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x32, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, - 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x33, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x86, 0x01, 0x0a, 0x15, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x73, 0x12, 0x34, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x80, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x8e, 0x01, 0x0a, 0x1a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, + 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6e, + 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x6e, + 0x62, 0x6f, 0x78, 0x49, 0x64, 0x32, 0xd7, 0x06, 0x0a, 0x0d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x70, 0x69, 0x12, 0x80, 0x01, 0x0a, 0x13, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, + 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, - 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x77, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x12, 0x2f, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x86, 0x01, 0x0a, 0x15, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x73, 0x12, 0x34, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, 0x63, + 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x32, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x33, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, + 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x8e, 0x01, 0x0a, 0x1a, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, + 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, - 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, - 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xcf, - 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x5f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x58, - 0x4d, 0x58, 0xaa, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x58, 0x6d, 0x74, - 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, - 0x56, 0x31, 0xe2, 0x02, 0x21, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x17, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x4d, - 0x6c, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, 0x31, - 0x4a, 0x8d, 0x22, 0x0a, 0x07, 0x12, 0x05, 0x01, 0x00, 0x80, 0x01, 0x01, 0x0a, 0x17, 0x0a, 0x01, - 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x0d, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x02, 0x00, 0x1f, 0x0a, - 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x04, 0x00, 0x31, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x01, - 0x12, 0x03, 0x05, 0x00, 0x23, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x07, 0x00, 0x44, 0x0a, - 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x07, 0x00, 0x44, 0x0a, 0x26, 0x0a, 0x02, 0x06, 0x00, - 0x12, 0x04, 0x0a, 0x00, 0x1b, 0x01, 0x1a, 0x1a, 0x20, 0x52, 0x50, 0x43, 0x73, 0x20, 0x66, 0x6f, - 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x4d, 0x4c, 0x53, 0x20, 0x41, 0x50, - 0x49, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x06, 0x00, 0x01, 0x12, 0x03, 0x0a, 0x08, 0x15, 0x0a, 0x58, - 0x0a, 0x04, 0x06, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0c, 0x02, 0x5e, 0x1a, 0x4b, 0x20, 0x56, 0x61, - 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x73, - 0x65, 0x73, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x65, - 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, - 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x0c, 0x06, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x02, 0x12, - 0x03, 0x0c, 0x1a, 0x34, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0c, - 0x3f, 0x5a, 0x0a, 0x50, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x01, 0x12, 0x03, 0x0f, 0x02, 0x64, 0x1a, - 0x43, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x73, 0x20, 0x61, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x73, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x64, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0f, - 0x06, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x0f, 0x1c, 0x38, - 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0f, 0x43, 0x60, 0x0a, 0x4f, - 0x0a, 0x04, 0x06, 0x00, 0x02, 0x02, 0x12, 0x03, 0x12, 0x02, 0x5e, 0x1a, 0x42, 0x20, 0x47, 0x65, - 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, - 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x66, - 0x6f, 0x72, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x12, 0x06, 0x19, 0x0a, 0x0c, 0x0a, - 0x05, 0x06, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x12, 0x1a, 0x34, 0x0a, 0x0c, 0x0a, 0x05, 0x06, - 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x12, 0x3f, 0x5a, 0x0a, 0xaf, 0x01, 0x0a, 0x04, 0x06, 0x00, - 0x02, 0x03, 0x12, 0x03, 0x16, 0x02, 0x6c, 0x1a, 0xa1, 0x01, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, - 0x61, 0x74, 0x65, 0x73, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x44, 0x20, 0x6b, 0x65, 0x79, - 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x0a, 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, - 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x20, 0x3c, 0x3e, 0x20, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x4b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x69, 0x72, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x61, - 0x6c, 0x6c, 0x79, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, - 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x16, 0x06, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, - 0x03, 0x02, 0x12, 0x03, 0x16, 0x21, 0x3b, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x03, - 0x12, 0x03, 0x16, 0x46, 0x68, 0x0a, 0x48, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x04, 0x12, 0x03, 0x1a, - 0x02, 0x55, 0x1a, 0x3b, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, - 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x44, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x50, 0x61, 0x63, - 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x79, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, 0x1a, 0x06, 0x16, 0x0a, 0x0c, 0x0a, - 0x05, 0x06, 0x00, 0x02, 0x04, 0x02, 0x12, 0x03, 0x1a, 0x17, 0x2e, 0x0a, 0x0c, 0x0a, 0x05, 0x06, - 0x00, 0x02, 0x04, 0x03, 0x12, 0x03, 0x1a, 0x39, 0x51, 0x0a, 0x33, 0x0a, 0x02, 0x04, 0x00, 0x12, - 0x04, 0x1e, 0x00, 0x29, 0x01, 0x1a, 0x27, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x73, 0x20, 0x61, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x2d, 0x49, 0x44, 0x20, 0x4b, 0x65, 0x79, - 0x20, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x20, 0x54, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x1e, 0x08, 0x2a, 0x0a, 0x4f, 0x0a, 0x04, 0x04, 0x00, - 0x03, 0x00, 0x12, 0x04, 0x20, 0x02, 0x26, 0x03, 0x1a, 0x41, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6b, - 0x65, 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x03, 0x00, 0x01, 0x12, 0x03, 0x20, 0x0a, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x03, - 0x00, 0x02, 0x00, 0x12, 0x03, 0x21, 0x04, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x05, 0x12, 0x03, 0x21, 0x04, 0x08, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x01, 0x12, 0x03, 0x21, 0x09, 0x0e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x21, 0x11, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, - 0x02, 0x01, 0x12, 0x03, 0x22, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, - 0x01, 0x05, 0x12, 0x03, 0x22, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, - 0x01, 0x01, 0x12, 0x03, 0x22, 0x0b, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, - 0x01, 0x03, 0x12, 0x03, 0x22, 0x1b, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, - 0x02, 0x12, 0x03, 0x23, 0x04, 0x2f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x02, - 0x06, 0x12, 0x03, 0x23, 0x04, 0x1f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x02, - 0x01, 0x12, 0x03, 0x23, 0x20, 0x2a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x02, - 0x03, 0x12, 0x03, 0x23, 0x2d, 0x2e, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x03, - 0x12, 0x03, 0x24, 0x04, 0x26, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x03, 0x05, - 0x12, 0x03, 0x24, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x03, 0x01, - 0x12, 0x03, 0x24, 0x0a, 0x21, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x03, 0x03, - 0x12, 0x03, 0x24, 0x24, 0x25, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x04, 0x12, - 0x03, 0x25, 0x04, 0x1a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x04, 0x05, 0x12, - 0x03, 0x25, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x04, 0x01, 0x12, - 0x03, 0x25, 0x0b, 0x15, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x04, 0x03, 0x12, - 0x03, 0x25, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x28, 0x02, - 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x04, 0x12, 0x03, 0x28, 0x02, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x28, 0x0b, 0x13, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x28, 0x14, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x28, 0x20, 0x21, 0x0a, 0x39, 0x0a, 0x02, 0x04, 0x01, 0x12, - 0x04, 0x2c, 0x00, 0x34, 0x01, 0x1a, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, - 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x2c, 0x08, 0x22, - 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x01, 0x03, 0x00, 0x12, 0x04, 0x2e, 0x02, 0x31, 0x03, 0x1a, 0x1e, - 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, - 0x68, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x01, 0x03, 0x00, 0x01, 0x12, 0x03, 0x2e, 0x0a, 0x14, 0x0a, 0x0d, 0x0a, 0x06, - 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x2f, 0x04, 0x2f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x01, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2f, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2f, 0x0a, 0x2a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x01, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2f, 0x2d, 0x2e, 0x0a, 0x0d, 0x0a, 0x06, 0x04, - 0x01, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x30, 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, - 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x30, 0x04, 0x08, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, - 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x30, 0x09, 0x1f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, - 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x30, 0x22, 0x23, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, - 0x02, 0x00, 0x12, 0x03, 0x33, 0x02, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x04, - 0x12, 0x03, 0x33, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x33, 0x0b, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x33, 0x16, - 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x33, 0x25, 0x26, 0x0a, - 0x34, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x37, 0x00, 0x43, 0x01, 0x1a, 0x28, 0x20, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x37, 0x08, - 0x23, 0x0a, 0x39, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x00, 0x12, 0x04, 0x39, 0x02, 0x40, 0x03, 0x1a, - 0x2b, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x20, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, - 0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x02, 0x03, 0x00, 0x01, 0x12, 0x03, 0x39, 0x0a, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, - 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x3a, 0x04, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, - 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x3a, 0x04, 0x08, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, - 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x3a, 0x09, 0x0e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, - 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3a, 0x11, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, - 0x00, 0x02, 0x01, 0x12, 0x03, 0x3b, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, - 0x02, 0x01, 0x05, 0x12, 0x03, 0x3b, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, - 0x02, 0x01, 0x01, 0x12, 0x03, 0x3b, 0x0b, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, - 0x02, 0x01, 0x03, 0x12, 0x03, 0x3b, 0x1b, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, - 0x02, 0x02, 0x12, 0x03, 0x3c, 0x04, 0x1e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, - 0x02, 0x05, 0x12, 0x03, 0x3c, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, - 0x02, 0x01, 0x12, 0x03, 0x3c, 0x0a, 0x19, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, - 0x02, 0x03, 0x12, 0x03, 0x3c, 0x1c, 0x1d, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, - 0x03, 0x12, 0x03, 0x3d, 0x04, 0x1f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x03, - 0x05, 0x12, 0x03, 0x3d, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x03, - 0x01, 0x12, 0x03, 0x3d, 0x0b, 0x1a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x03, - 0x03, 0x12, 0x03, 0x3d, 0x1d, 0x1e, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x04, - 0x12, 0x03, 0x3e, 0x04, 0x28, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x04, 0x05, - 0x12, 0x03, 0x3e, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x04, 0x01, - 0x12, 0x03, 0x3e, 0x0a, 0x23, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x04, 0x03, - 0x12, 0x03, 0x3e, 0x26, 0x27, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x05, 0x12, - 0x03, 0x3f, 0x04, 0x1a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x05, 0x05, 0x12, - 0x03, 0x3f, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x05, 0x01, 0x12, - 0x03, 0x3f, 0x0b, 0x15, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x05, 0x03, 0x12, - 0x03, 0x3f, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x42, 0x02, - 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x04, 0x12, 0x03, 0x42, 0x02, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x42, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x42, 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x02, 0x02, 0x00, 0x03, 0x12, 0x03, 0x42, 0x2a, 0x2b, 0x0a, 0x3b, 0x0a, 0x02, 0x04, 0x03, 0x12, - 0x04, 0x46, 0x00, 0x4d, 0x01, 0x1a, 0x2f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, - 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x46, - 0x08, 0x24, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x03, 0x03, 0x00, 0x12, 0x04, 0x48, 0x02, 0x4a, 0x03, - 0x1a, 0x1a, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, - 0x61, 0x63, 0x68, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x03, 0x03, 0x00, 0x01, 0x12, 0x03, 0x48, 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, - 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x49, 0x04, 0x31, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, - 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x49, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, - 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x49, 0x0a, 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, - 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x49, 0x2f, 0x30, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, - 0x00, 0x12, 0x03, 0x4c, 0x02, 0x2b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x04, 0x12, - 0x03, 0x4c, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, 0x12, 0x03, 0x4c, - 0x0b, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x4c, 0x18, 0x26, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x4c, 0x29, 0x2a, 0x0a, 0x36, - 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x50, 0x00, 0x59, 0x01, 0x1a, 0x2a, 0x20, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, - 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x50, - 0x08, 0x25, 0x0a, 0x35, 0x0a, 0x04, 0x04, 0x04, 0x03, 0x00, 0x12, 0x04, 0x52, 0x02, 0x56, 0x03, - 0x1a, 0x27, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x6e, 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, - 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, - 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x03, - 0x00, 0x01, 0x12, 0x03, 0x52, 0x0a, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, - 0x00, 0x12, 0x03, 0x53, 0x04, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, - 0x05, 0x12, 0x03, 0x53, 0x04, 0x08, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x53, 0x09, 0x0e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, - 0x03, 0x12, 0x03, 0x53, 0x11, 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, - 0x12, 0x03, 0x54, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x05, - 0x12, 0x03, 0x54, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x01, - 0x12, 0x03, 0x54, 0x0b, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x01, 0x03, - 0x12, 0x03, 0x54, 0x1b, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x12, - 0x03, 0x55, 0x04, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, - 0x03, 0x55, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x55, 0x0b, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, - 0x03, 0x55, 0x16, 0x17, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x58, 0x02, - 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x04, 0x12, 0x03, 0x58, 0x02, 0x0a, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x06, 0x12, 0x03, 0x58, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x58, 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x04, 0x02, 0x00, 0x03, 0x12, 0x03, 0x58, 0x2a, 0x2b, 0x0a, 0x4b, 0x0a, 0x02, 0x04, 0x05, 0x12, - 0x04, 0x5c, 0x00, 0x60, 0x01, 0x1a, 0x3f, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, - 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x61, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x61, - 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, 0x5c, - 0x08, 0x22, 0x0a, 0x27, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x5e, 0x02, 0x45, 0x1a, - 0x1a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x05, 0x02, 0x00, 0x04, 0x12, 0x03, 0x5e, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, - 0x00, 0x06, 0x12, 0x03, 0x5e, 0x0b, 0x34, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x5e, 0x35, 0x40, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x5e, 0x43, 0x44, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x01, 0x12, 0x03, 0x5f, 0x02, 0x45, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x04, 0x12, 0x03, 0x5f, 0x02, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x06, 0x12, 0x03, 0x5f, 0x0b, 0x34, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x05, 0x02, 0x01, 0x01, 0x12, 0x03, 0x5f, 0x35, 0x40, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, - 0x02, 0x01, 0x03, 0x12, 0x03, 0x5f, 0x43, 0x44, 0x0a, 0x6c, 0x0a, 0x02, 0x04, 0x06, 0x12, 0x04, - 0x64, 0x00, 0x67, 0x01, 0x1a, 0x60, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, - 0x74, 0x6f, 0x20, 0x47, 0x65, 0x74, 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, + 0x49, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x77, 0x0a, 0x10, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x12, 0x2f, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, + 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, + 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0xac, 0x01, 0x0a, 0x23, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x6d, 0x61, 0x72, 0x74, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x40, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, + 0xcf, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, + 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x0c, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x6d, 0x6c, 0x73, 0x5f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0xa2, 0x02, 0x03, + 0x58, 0x4d, 0x58, 0xaa, 0x02, 0x15, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x4d, 0x6c, 0x73, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x15, 0x58, 0x6d, + 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x21, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x4d, 0x6c, 0x73, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x17, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, + 0x4d, 0x6c, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, + 0x31, 0x4a, 0xb0, 0x26, 0x0a, 0x07, 0x12, 0x05, 0x01, 0x00, 0x95, 0x01, 0x01, 0x0a, 0x17, 0x0a, + 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x0d, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x02, 0x00, 0x1f, + 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x04, 0x00, 0x28, 0x0a, 0x09, 0x0a, 0x02, 0x03, + 0x01, 0x12, 0x03, 0x05, 0x00, 0x31, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, 0x12, 0x03, 0x06, 0x00, + 0x2f, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x03, 0x12, 0x03, 0x07, 0x00, 0x23, 0x0a, 0x08, 0x0a, 0x01, + 0x08, 0x12, 0x03, 0x09, 0x00, 0x44, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x09, 0x00, + 0x44, 0x0a, 0x26, 0x0a, 0x02, 0x06, 0x00, 0x12, 0x04, 0x0c, 0x00, 0x25, 0x01, 0x1a, 0x1a, 0x20, + 0x52, 0x50, 0x43, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, + 0x20, 0x4d, 0x4c, 0x53, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x06, 0x00, 0x01, + 0x12, 0x03, 0x0c, 0x08, 0x15, 0x0a, 0x58, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0e, + 0x02, 0x5e, 0x1a, 0x4b, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x73, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, + 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x72, 0x65, + 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x0a, 0x0a, + 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0e, 0x06, 0x19, 0x0a, 0x0c, 0x0a, + 0x05, 0x06, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x0e, 0x1a, 0x34, 0x0a, 0x0c, 0x0a, 0x05, 0x06, + 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x0e, 0x3f, 0x5a, 0x0a, 0x50, 0x0a, 0x04, 0x06, 0x00, 0x02, + 0x01, 0x12, 0x03, 0x11, 0x02, 0x64, 0x1a, 0x43, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x73, 0x20, 0x61, 0x20, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, + 0x6e, 0x74, 0x20, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, + 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x11, 0x06, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, + 0x01, 0x02, 0x12, 0x03, 0x11, 0x1c, 0x38, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x03, + 0x12, 0x03, 0x11, 0x43, 0x60, 0x0a, 0x4f, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x02, 0x12, 0x03, 0x14, + 0x02, 0x5e, 0x1a, 0x42, 0x20, 0x47, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, - 0x62, 0x6f, 0x78, 0x49, 0x44, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x64, - 0x08, 0x23, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x00, 0x12, 0x03, 0x65, 0x02, 0x44, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x06, 0x12, 0x03, 0x65, 0x02, 0x2d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, 0x03, 0x65, 0x2e, 0x3f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x65, 0x42, 0x43, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, - 0x01, 0x12, 0x03, 0x66, 0x02, 0x41, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x06, 0x12, - 0x03, 0x66, 0x02, 0x31, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x01, 0x12, 0x03, 0x66, - 0x32, 0x3c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x03, 0x12, 0x03, 0x66, 0x3f, 0x40, - 0x0a, 0x79, 0x0a, 0x02, 0x04, 0x07, 0x12, 0x04, 0x6a, 0x00, 0x74, 0x01, 0x1a, 0x6d, 0x20, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, - 0x74, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x44, 0x20, 0x77, 0x69, - 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x20, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x20, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x73, 0x20, - 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x20, 0x49, 0x64, 0x20, 0x3c, 0x3e, 0x20, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x20, - 0x61, 0x72, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, - 0x07, 0x01, 0x12, 0x03, 0x6a, 0x08, 0x1f, 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x07, 0x03, 0x00, 0x12, - 0x04, 0x6c, 0x02, 0x70, 0x03, 0x1a, 0x1d, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, + 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x01, 0x12, + 0x03, 0x14, 0x06, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x14, + 0x1a, 0x34, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x14, 0x3f, 0x5a, + 0x0a, 0xaf, 0x01, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x03, 0x12, 0x03, 0x18, 0x02, 0x6c, 0x1a, 0xa1, + 0x01, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x49, 0x6e, 0x62, 0x6f, + 0x78, 0x49, 0x44, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x63, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x0a, 0x20, + 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, + 0x49, 0x64, 0x20, 0x3c, 0x3e, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x69, 0x72, + 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x2e, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x18, 0x06, 0x20, + 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, 0x18, 0x21, 0x3b, 0x0a, 0x0c, + 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x18, 0x46, 0x68, 0x0a, 0x48, 0x0a, 0x04, + 0x06, 0x00, 0x02, 0x04, 0x12, 0x03, 0x1c, 0x02, 0x55, 0x1a, 0x3b, 0x20, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x44, 0x20, + 0x4b, 0x65, 0x79, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x20, 0x6e, 0x65, 0x65, + 0x64, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x6f, 0x73, + 0x73, 0x69, 0x62, 0x6c, 0x79, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x01, 0x12, + 0x03, 0x1c, 0x06, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x02, 0x12, 0x03, 0x1c, + 0x17, 0x2e, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x04, 0x03, 0x12, 0x03, 0x1c, 0x39, 0x51, + 0x0a, 0x6f, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x05, 0x12, 0x04, 0x20, 0x02, 0x24, 0x06, 0x1a, 0x61, + 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x20, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x0a, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x78, 0x69, + 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x64, 0x65, + 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x77, 0x65, 0x27, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x75, 0x73, 0x65, + 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x67, 0x61, 0x65, 0x73, 0x2e, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x05, 0x01, 0x12, 0x03, 0x20, 0x06, 0x29, 0x0a, + 0x0c, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x05, 0x02, 0x12, 0x03, 0x21, 0x04, 0x43, 0x0a, 0x0c, 0x0a, + 0x05, 0x06, 0x00, 0x02, 0x05, 0x03, 0x12, 0x03, 0x23, 0x04, 0x44, 0x0a, 0x39, 0x0a, 0x02, 0x04, + 0x00, 0x12, 0x04, 0x28, 0x00, 0x30, 0x01, 0x1a, 0x2d, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x73, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x50, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x28, + 0x08, 0x29, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x00, 0x03, 0x00, 0x12, 0x04, 0x2a, 0x02, 0x2d, 0x03, + 0x1a, 0x1e, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, + 0x61, 0x63, 0x68, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x03, 0x00, 0x01, 0x12, 0x03, 0x2a, 0x0a, 0x14, 0x0a, 0x0d, + 0x0a, 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x2b, 0x04, 0x2f, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2b, 0x04, 0x09, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2b, 0x0a, 0x2a, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2b, 0x2d, 0x2e, 0x0a, 0x0d, 0x0a, + 0x06, 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x2c, 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x2c, 0x04, 0x08, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x2c, 0x09, 0x1f, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x00, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x2c, 0x22, 0x23, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x2f, 0x02, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x00, 0x04, 0x12, 0x03, 0x2f, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x06, + 0x12, 0x03, 0x2f, 0x0b, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x2f, 0x16, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x2f, 0x25, + 0x26, 0x0a, 0x33, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x33, 0x00, 0x3e, 0x01, 0x1a, 0x27, 0x20, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x49, 0x6e, 0x62, 0x6f, + 0x78, 0x2d, 0x49, 0x44, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x20, 0x54, 0x79, 0x70, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x33, + 0x08, 0x2a, 0x0a, 0x4f, 0x0a, 0x04, 0x04, 0x01, 0x03, 0x00, 0x12, 0x04, 0x35, 0x02, 0x3b, 0x03, + 0x1a, 0x41, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, + 0x63, 0x6f, 0x72, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, + 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, + 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x61, + 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x03, 0x00, 0x01, 0x12, 0x03, 0x35, 0x0a, + 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x36, 0x04, 0x13, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x36, 0x04, 0x08, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x36, 0x09, 0x0e, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x36, 0x11, 0x12, + 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x37, 0x04, 0x1d, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x37, 0x04, 0x0a, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x37, 0x0b, 0x18, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x37, 0x1b, 0x1c, 0x0a, + 0x0d, 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x38, 0x04, 0x2f, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x06, 0x12, 0x03, 0x38, 0x04, 0x1f, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x38, 0x20, 0x2a, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x38, 0x2d, 0x2e, 0x0a, 0x0d, + 0x0a, 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x12, 0x03, 0x39, 0x04, 0x26, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x39, 0x04, 0x09, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x39, 0x0a, 0x21, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x39, 0x24, 0x25, 0x0a, 0x0d, 0x0a, + 0x06, 0x04, 0x01, 0x03, 0x00, 0x02, 0x04, 0x12, 0x03, 0x3a, 0x04, 0x1a, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x01, 0x03, 0x00, 0x02, 0x04, 0x05, 0x12, 0x03, 0x3a, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x01, 0x03, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, 0x3a, 0x0b, 0x15, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x01, 0x03, 0x00, 0x02, 0x04, 0x03, 0x12, 0x03, 0x3a, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x3d, 0x02, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, + 0x00, 0x04, 0x12, 0x03, 0x3d, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, + 0x12, 0x03, 0x3d, 0x0b, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x3d, 0x14, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3d, 0x20, + 0x21, 0x0a, 0x39, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x41, 0x00, 0x49, 0x01, 0x1a, 0x2d, 0x20, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, + 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x4b, + 0x65, 0x79, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, + 0x04, 0x02, 0x01, 0x12, 0x03, 0x41, 0x08, 0x22, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x02, 0x03, 0x00, + 0x12, 0x04, 0x43, 0x02, 0x46, 0x03, 0x1a, 0x1e, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x03, 0x00, 0x01, 0x12, + 0x03, 0x43, 0x0a, 0x14, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, + 0x44, 0x04, 0x2f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, + 0x44, 0x04, 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x44, 0x0a, 0x2a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x44, 0x2d, 0x2e, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x45, + 0x04, 0x24, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x45, + 0x04, 0x08, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x45, + 0x09, 0x1f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x02, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x45, + 0x22, 0x23, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x48, 0x02, 0x27, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x04, 0x12, 0x03, 0x48, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x00, 0x06, 0x12, 0x03, 0x48, 0x0b, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x02, 0x02, 0x00, 0x01, 0x12, 0x03, 0x48, 0x16, 0x22, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, + 0x00, 0x03, 0x12, 0x03, 0x48, 0x25, 0x26, 0x0a, 0x34, 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x4c, + 0x00, 0x58, 0x01, 0x1a, 0x28, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, + 0x6f, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, + 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x4c, 0x08, 0x23, 0x0a, 0x39, 0x0a, 0x04, 0x04, 0x03, 0x03, + 0x00, 0x12, 0x04, 0x4e, 0x02, 0x55, 0x03, 0x1a, 0x2b, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x6e, 0x64, + 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x70, 0x61, 0x63, 0x6b, + 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x03, 0x00, 0x01, 0x12, 0x03, 0x4e, + 0x0a, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x4f, 0x04, + 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x4f, 0x04, + 0x08, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x4f, 0x09, + 0x0e, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x4f, 0x11, + 0x12, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x50, 0x04, 0x1d, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x50, 0x04, 0x0a, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x50, 0x0b, 0x18, + 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x50, 0x1b, 0x1c, + 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x51, 0x04, 0x1e, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x51, 0x04, 0x09, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x51, 0x0a, 0x19, 0x0a, + 0x0e, 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x51, 0x1c, 0x1d, 0x0a, + 0x0d, 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x03, 0x12, 0x03, 0x52, 0x04, 0x1f, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x03, 0x05, 0x12, 0x03, 0x52, 0x04, 0x0a, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x52, 0x0b, 0x1a, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x52, 0x1d, 0x1e, 0x0a, 0x0d, + 0x0a, 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x04, 0x12, 0x03, 0x53, 0x04, 0x28, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x04, 0x05, 0x12, 0x03, 0x53, 0x04, 0x09, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x04, 0x01, 0x12, 0x03, 0x53, 0x0a, 0x23, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x03, 0x03, 0x00, 0x02, 0x04, 0x03, 0x12, 0x03, 0x53, 0x26, 0x27, 0x0a, 0x0d, 0x0a, + 0x06, 0x04, 0x03, 0x03, 0x00, 0x02, 0x05, 0x12, 0x03, 0x54, 0x04, 0x1a, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x03, 0x03, 0x00, 0x02, 0x05, 0x05, 0x12, 0x03, 0x54, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x03, 0x03, 0x00, 0x02, 0x05, 0x01, 0x12, 0x03, 0x54, 0x0b, 0x15, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x03, 0x03, 0x00, 0x02, 0x05, 0x03, 0x12, 0x03, 0x54, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x57, 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, + 0x00, 0x04, 0x12, 0x03, 0x57, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x06, + 0x12, 0x03, 0x57, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x57, 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x57, 0x2a, + 0x2b, 0x0a, 0x3b, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x5b, 0x00, 0x62, 0x01, 0x1a, 0x2f, 0x20, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, + 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0a, 0x0a, 0x0a, + 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x5b, 0x08, 0x24, 0x0a, 0x28, 0x0a, 0x04, 0x04, 0x04, + 0x03, 0x00, 0x12, 0x04, 0x5d, 0x02, 0x5f, 0x03, 0x1a, 0x1a, 0x20, 0x57, 0x72, 0x61, 0x70, 0x70, + 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x03, 0x00, 0x01, 0x12, 0x03, 0x5d, + 0x0a, 0x16, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x5e, 0x04, + 0x31, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x5e, 0x04, + 0x09, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x5e, 0x0a, + 0x2c, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x04, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x5e, 0x2f, + 0x30, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x61, 0x02, 0x2b, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, 0x04, 0x12, 0x03, 0x61, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x04, 0x02, 0x00, 0x06, 0x12, 0x03, 0x61, 0x0b, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x61, 0x18, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x61, 0x29, 0x2a, 0x0a, 0x36, 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x65, 0x00, + 0x6e, 0x01, 0x1a, 0x2a, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, + 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, + 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, 0x65, 0x08, 0x25, 0x0a, 0x35, 0x0a, 0x04, 0x04, 0x05, + 0x03, 0x00, 0x12, 0x04, 0x67, 0x02, 0x6b, 0x03, 0x1a, 0x27, 0x20, 0x41, 0x6e, 0x20, 0x69, 0x6e, + 0x64, 0x69, 0x76, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x03, 0x00, 0x01, 0x12, 0x03, 0x67, 0x0a, 0x1c, 0x0a, + 0x0d, 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x68, 0x04, 0x13, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x68, 0x04, 0x08, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x68, 0x09, 0x0e, 0x0a, 0x0e, + 0x0a, 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x68, 0x11, 0x12, 0x0a, 0x0d, + 0x0a, 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x69, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x69, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x69, 0x0b, 0x18, 0x0a, 0x0e, 0x0a, + 0x07, 0x04, 0x05, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x69, 0x1b, 0x1c, 0x0a, 0x0d, 0x0a, + 0x06, 0x04, 0x05, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x6a, 0x04, 0x18, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x05, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x6a, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x05, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x6a, 0x0b, 0x13, 0x0a, 0x0e, 0x0a, 0x07, + 0x04, 0x05, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x6a, 0x16, 0x17, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x6d, 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, + 0x00, 0x04, 0x12, 0x03, 0x6d, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x06, + 0x12, 0x03, 0x6d, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x6d, 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x6d, 0x2a, + 0x2b, 0x0a, 0x4b, 0x0a, 0x02, 0x04, 0x06, 0x12, 0x04, 0x71, 0x00, 0x75, 0x01, 0x1a, 0x3f, 0x20, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65, 0x74, 0x20, 0x61, + 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x0a, 0x0a, 0x0a, + 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x71, 0x08, 0x22, 0x0a, 0x27, 0x0a, 0x04, 0x04, 0x06, + 0x02, 0x00, 0x12, 0x03, 0x73, 0x02, 0x45, 0x1a, 0x1a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, + 0x66, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x04, 0x12, 0x03, 0x73, 0x02, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x06, 0x12, 0x03, 0x73, 0x0b, 0x34, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, 0x03, 0x73, 0x35, 0x40, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x73, 0x43, 0x44, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x06, 0x02, 0x01, 0x12, 0x03, 0x74, 0x02, 0x45, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, + 0x04, 0x12, 0x03, 0x74, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x06, 0x12, + 0x03, 0x74, 0x0b, 0x34, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x01, 0x12, 0x03, 0x74, + 0x35, 0x40, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x03, 0x12, 0x03, 0x74, 0x43, 0x44, + 0x0a, 0x6c, 0x0a, 0x02, 0x04, 0x07, 0x12, 0x04, 0x79, 0x00, 0x7c, 0x01, 0x1a, 0x60, 0x20, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x47, 0x65, 0x74, 0x41, 0x73, + 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, + 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x61, 0x73, 0x73, 0x6f, + 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x0a, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x44, 0x0a, 0x0a, 0x0a, + 0x0a, 0x03, 0x04, 0x07, 0x01, 0x12, 0x03, 0x79, 0x08, 0x23, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, + 0x02, 0x00, 0x12, 0x03, 0x7a, 0x02, 0x44, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x06, + 0x12, 0x03, 0x7a, 0x02, 0x2d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x7a, 0x2e, 0x3f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x03, 0x12, 0x03, 0x7a, 0x42, + 0x43, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x01, 0x12, 0x03, 0x7b, 0x02, 0x41, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x06, 0x12, 0x03, 0x7b, 0x02, 0x31, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x07, 0x02, 0x01, 0x01, 0x12, 0x03, 0x7b, 0x32, 0x3c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, + 0x02, 0x01, 0x03, 0x12, 0x03, 0x7b, 0x3f, 0x40, 0x0a, 0x7a, 0x0a, 0x02, 0x04, 0x08, 0x12, 0x05, + 0x7f, 0x00, 0x89, 0x01, 0x01, 0x1a, 0x6d, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, + 0x74, 0x6f, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x44, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x20, 0x45, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x6e, 0x62, 0x6f, + 0x78, 0x20, 0x49, 0x64, 0x20, 0x3c, 0x3e, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x61, 0x72, 0x65, 0x20, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x08, 0x01, 0x12, 0x03, 0x7f, 0x08, 0x1f, + 0x0a, 0x2d, 0x0a, 0x04, 0x04, 0x08, 0x03, 0x00, 0x12, 0x06, 0x81, 0x01, 0x02, 0x85, 0x01, 0x03, + 0x1a, 0x1d, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x03, 0x00, 0x01, 0x12, 0x04, 0x81, 0x01, 0x0a, 0x1b, 0x0a, 0x0e, + 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0x82, 0x01, 0x04, 0x2f, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x04, 0x82, 0x01, 0x04, 0x1f, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x82, 0x01, 0x20, 0x2a, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0x82, 0x01, 0x2d, + 0x2e, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0x83, 0x01, 0x04, + 0x26, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x04, 0x83, 0x01, + 0x04, 0x09, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x83, + 0x01, 0x0a, 0x21, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, + 0x83, 0x01, 0x24, 0x25, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, 0x02, 0x02, 0x12, 0x04, + 0x84, 0x01, 0x04, 0x4c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x02, 0x04, 0x12, + 0x04, 0x84, 0x01, 0x04, 0x0c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x02, 0x06, + 0x12, 0x04, 0x84, 0x01, 0x0d, 0x36, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x02, + 0x01, 0x12, 0x04, 0x84, 0x01, 0x37, 0x47, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, + 0x02, 0x03, 0x12, 0x04, 0x84, 0x01, 0x4a, 0x4b, 0x0a, 0x2b, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x00, + 0x12, 0x04, 0x88, 0x01, 0x02, 0x2a, 0x1a, 0x1d, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x03, 0x00, 0x01, 0x12, 0x03, 0x6c, - 0x0a, 0x1b, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x6d, 0x04, - 0x2f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x6d, 0x04, - 0x1f, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x6d, 0x20, - 0x2a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x6d, 0x2d, - 0x2e, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x07, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x6e, 0x04, 0x26, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x6e, 0x04, 0x09, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x6e, 0x0a, 0x21, - 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x6e, 0x24, 0x25, - 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x07, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x6f, 0x04, 0x4c, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x02, 0x04, 0x12, 0x03, 0x6f, 0x04, 0x0c, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x02, 0x06, 0x12, 0x03, 0x6f, 0x0d, 0x36, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x6f, 0x37, 0x47, 0x0a, - 0x0e, 0x0a, 0x07, 0x04, 0x07, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x6f, 0x4a, 0x4b, 0x0a, - 0x2a, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x00, 0x12, 0x03, 0x73, 0x02, 0x2a, 0x1a, 0x1d, 0x20, 0x6c, - 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x07, 0x02, 0x00, 0x04, 0x12, 0x03, 0x73, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, - 0x00, 0x06, 0x12, 0x03, 0x73, 0x0b, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x73, 0x1d, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x73, 0x28, 0x29, 0x0a, 0x31, 0x0a, 0x02, 0x04, 0x08, 0x12, 0x05, 0x77, 0x00, 0x80, 0x01, 0x01, - 0x1a, 0x24, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x08, 0x01, 0x12, 0x03, 0x77, - 0x08, 0x20, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x08, 0x03, 0x00, 0x12, 0x04, 0x79, 0x02, 0x7d, 0x03, - 0x1a, 0x1e, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x03, 0x00, 0x01, 0x12, 0x03, 0x79, 0x0a, 0x1c, 0x0a, 0x0d, - 0x0a, 0x06, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x7a, 0x04, 0x13, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x7a, 0x04, 0x08, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x7a, 0x09, 0x0e, 0x0a, 0x0e, 0x0a, - 0x07, 0x04, 0x08, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x7a, 0x11, 0x12, 0x0a, 0x0d, 0x0a, - 0x06, 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x12, 0x03, 0x7b, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, - 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x7b, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, - 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x7b, 0x0b, 0x18, 0x0a, 0x0e, 0x0a, 0x07, - 0x04, 0x08, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x7b, 0x1b, 0x1c, 0x0a, 0x0d, 0x0a, 0x06, - 0x04, 0x08, 0x03, 0x00, 0x02, 0x02, 0x12, 0x03, 0x7c, 0x04, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x08, 0x03, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x7c, 0x04, 0x0a, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x08, 0x03, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x7c, 0x0b, 0x13, 0x0a, 0x0e, 0x0a, 0x07, 0x04, - 0x08, 0x03, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x7c, 0x16, 0x17, 0x0a, 0x2b, 0x0a, 0x04, 0x04, - 0x08, 0x02, 0x00, 0x12, 0x03, 0x7f, 0x02, 0x2c, 0x1a, 0x1e, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x20, + 0x65, 0x73, 0x74, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x04, 0x12, 0x04, + 0x88, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x06, 0x12, 0x04, 0x88, + 0x01, 0x0b, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x01, 0x12, 0x04, 0x88, 0x01, + 0x1d, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x03, 0x12, 0x04, 0x88, 0x01, 0x28, + 0x29, 0x0a, 0x32, 0x0a, 0x02, 0x04, 0x09, 0x12, 0x06, 0x8c, 0x01, 0x00, 0x95, 0x01, 0x01, 0x1a, + 0x24, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x56, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x09, 0x01, 0x12, 0x04, 0x8c, 0x01, + 0x08, 0x20, 0x0a, 0x2e, 0x0a, 0x04, 0x04, 0x09, 0x03, 0x00, 0x12, 0x06, 0x8e, 0x01, 0x02, 0x92, + 0x01, 0x03, 0x1a, 0x1e, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x03, 0x00, 0x01, 0x12, 0x04, 0x8e, 0x01, 0x0a, + 0x1c, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0x8f, 0x01, 0x04, + 0x13, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0x8f, 0x01, + 0x04, 0x08, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8f, + 0x01, 0x09, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, + 0x8f, 0x01, 0x11, 0x12, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x09, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, + 0x90, 0x01, 0x04, 0x1d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x01, 0x05, 0x12, + 0x04, 0x90, 0x01, 0x04, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x01, 0x01, + 0x12, 0x04, 0x90, 0x01, 0x0b, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x01, + 0x03, 0x12, 0x04, 0x90, 0x01, 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x09, 0x03, 0x00, 0x02, + 0x02, 0x12, 0x04, 0x91, 0x01, 0x04, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, + 0x02, 0x05, 0x12, 0x04, 0x91, 0x01, 0x04, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, + 0x02, 0x02, 0x01, 0x12, 0x04, 0x91, 0x01, 0x0b, 0x13, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x09, 0x03, + 0x00, 0x02, 0x02, 0x03, 0x12, 0x04, 0x91, 0x01, 0x16, 0x17, 0x0a, 0x2c, 0x0a, 0x04, 0x04, 0x09, + 0x02, 0x00, 0x12, 0x04, 0x94, 0x01, 0x02, 0x2c, 0x1a, 0x1e, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, - 0x04, 0x12, 0x03, 0x7f, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x06, 0x12, - 0x03, 0x7f, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x01, 0x12, 0x03, 0x7f, - 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x03, 0x12, 0x03, 0x7f, 0x2a, 0x2b, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, + 0x04, 0x12, 0x04, 0x94, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x06, + 0x12, 0x04, 0x94, 0x01, 0x0b, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x01, 0x12, + 0x04, 0x94, 0x01, 0x1e, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x03, 0x12, 0x04, + 0x94, 0x01, 0x2a, 0x2b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ]; include!("xmtp.mls_validation.v1.serde.rs"); include!("xmtp.mls_validation.v1.tonic.rs"); diff --git a/xmtp_proto/src/gen/xmtp.mls_validation.v1.serde.rs b/xmtp_proto/src/gen/xmtp.mls_validation.v1.serde.rs index 599dc577b..baaf9f523 100644 --- a/xmtp_proto/src/gen/xmtp.mls_validation.v1.serde.rs +++ b/xmtp_proto/src/gen/xmtp.mls_validation.v1.serde.rs @@ -626,6 +626,212 @@ impl<'de> serde::Deserialize<'de> for validate_group_messages_response::Validati deserializer.deserialize_struct("xmtp.mls_validation.v1.ValidateGroupMessagesResponse.ValidationResponse", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for ValidateInboxIdKeyPackagesRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.key_packages.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls_validation.v1.ValidateInboxIdKeyPackagesRequest", len)?; + if !self.key_packages.is_empty() { + struct_ser.serialize_field("keyPackages", &self.key_packages)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for ValidateInboxIdKeyPackagesRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "key_packages", + "keyPackages", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + KeyPackages, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "keyPackages" | "key_packages" => Ok(GeneratedField::KeyPackages), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = ValidateInboxIdKeyPackagesRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls_validation.v1.ValidateInboxIdKeyPackagesRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut key_packages__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::KeyPackages => { + if key_packages__.is_some() { + return Err(serde::de::Error::duplicate_field("keyPackages")); + } + key_packages__ = Some(map_.next_value()?); + } + } + } + Ok(ValidateInboxIdKeyPackagesRequest { + key_packages: key_packages__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls_validation.v1.ValidateInboxIdKeyPackagesRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for validate_inbox_id_key_packages_request::KeyPackage { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.key_package_bytes_tls_serialized.is_empty() { + len += 1; + } + if self.is_inbox_id_credential { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls_validation.v1.ValidateInboxIdKeyPackagesRequest.KeyPackage", len)?; + if !self.key_package_bytes_tls_serialized.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("keyPackageBytesTlsSerialized", pbjson::private::base64::encode(&self.key_package_bytes_tls_serialized).as_str())?; + } + if self.is_inbox_id_credential { + struct_ser.serialize_field("isInboxIdCredential", &self.is_inbox_id_credential)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for validate_inbox_id_key_packages_request::KeyPackage { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "key_package_bytes_tls_serialized", + "keyPackageBytesTlsSerialized", + "is_inbox_id_credential", + "isInboxIdCredential", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + KeyPackageBytesTlsSerialized, + IsInboxIdCredential, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "keyPackageBytesTlsSerialized" | "key_package_bytes_tls_serialized" => Ok(GeneratedField::KeyPackageBytesTlsSerialized), + "isInboxIdCredential" | "is_inbox_id_credential" => Ok(GeneratedField::IsInboxIdCredential), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = validate_inbox_id_key_packages_request::KeyPackage; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls_validation.v1.ValidateInboxIdKeyPackagesRequest.KeyPackage") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut key_package_bytes_tls_serialized__ = None; + let mut is_inbox_id_credential__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::KeyPackageBytesTlsSerialized => { + if key_package_bytes_tls_serialized__.is_some() { + return Err(serde::de::Error::duplicate_field("keyPackageBytesTlsSerialized")); + } + key_package_bytes_tls_serialized__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::IsInboxIdCredential => { + if is_inbox_id_credential__.is_some() { + return Err(serde::de::Error::duplicate_field("isInboxIdCredential")); + } + is_inbox_id_credential__ = Some(map_.next_value()?); + } + } + } + Ok(validate_inbox_id_key_packages_request::KeyPackage { + key_package_bytes_tls_serialized: key_package_bytes_tls_serialized__.unwrap_or_default(), + is_inbox_id_credential: is_inbox_id_credential__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls_validation.v1.ValidateInboxIdKeyPackagesRequest.KeyPackage", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for ValidateInboxIdKeyPackagesResponse { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result diff --git a/xmtp_proto/src/gen/xmtp.mls_validation.v1.tonic.rs b/xmtp_proto/src/gen/xmtp.mls_validation.v1.tonic.rs index 706b7c66f..4473c4594 100644 --- a/xmtp_proto/src/gen/xmtp.mls_validation.v1.tonic.rs +++ b/xmtp_proto/src/gen/xmtp.mls_validation.v1.tonic.rs @@ -235,6 +235,40 @@ pub mod validation_api_client { ); self.inner.unary(req, path, codec).await } + pub async fn verify_smart_contract_wallet_signatures( + &mut self, + request: impl tonic::IntoRequest< + super::super::super::identity::api::v1::VerifySmartContractWalletSignaturesRequest, + >, + ) -> std::result::Result< + tonic::Response< + super::super::super::identity::api::v1::VerifySmartContractWalletSignaturesResponse, + >, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/xmtp.mls_validation.v1.ValidationApi/VerifySmartContractWalletSignatures", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert( + GrpcMethod::new( + "xmtp.mls_validation.v1.ValidationApi", + "VerifySmartContractWalletSignatures", + ), + ); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -280,6 +314,17 @@ pub mod validation_api_server { tonic::Response, tonic::Status, >; + async fn verify_smart_contract_wallet_signatures( + &self, + request: tonic::Request< + super::super::super::identity::api::v1::VerifySmartContractWalletSignaturesRequest, + >, + ) -> std::result::Result< + tonic::Response< + super::super::super::identity::api::v1::VerifySmartContractWalletSignaturesResponse, + >, + tonic::Status, + >; } #[derive(Debug)] pub struct ValidationApiServer { @@ -593,6 +638,60 @@ pub mod validation_api_server { }; Box::pin(fut) } + "/xmtp.mls_validation.v1.ValidationApi/VerifySmartContractWalletSignatures" => { + #[allow(non_camel_case_types)] + struct VerifySmartContractWalletSignaturesSvc( + pub Arc, + ); + impl< + T: ValidationApi, + > tonic::server::UnaryService< + super::super::super::identity::api::v1::VerifySmartContractWalletSignaturesRequest, + > for VerifySmartContractWalletSignaturesSvc { + type Response = super::super::super::identity::api::v1::VerifySmartContractWalletSignaturesResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::super::super::identity::api::v1::VerifySmartContractWalletSignaturesRequest, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::verify_smart_contract_wallet_signatures( + &inner, + request, + ) + .await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = VerifySmartContractWalletSignaturesSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { Ok( diff --git a/xmtp_proto/src/gen/xmtp.xmtpv4.rs b/xmtp_proto/src/gen/xmtp.xmtpv4.rs index 50f7a5533..59c20d24b 100644 --- a/xmtp_proto/src/gen/xmtp.xmtpv4.rs +++ b/xmtp_proto/src/gen/xmtp.xmtpv4.rs @@ -1,5 +1,13 @@ // @generated // This file is @generated by prost-build. +/// The last seen entry per originator. Originators that have not been seen are omitted. +/// Entries MUST be sorted in ascending order, so that smaller node ID's appear first. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VectorClock { + #[prost(map="uint32, uint64", tag="1")] + pub node_id_to_sequence_id: ::std::collections::HashMap, +} /// Data visible to the server that has been authenticated by the client. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -8,8 +16,8 @@ pub struct AuthenticatedData { pub target_originator: u32, #[prost(bytes="vec", tag="2")] pub target_topic: ::prost::alloc::vec::Vec, - #[prost(uint64, repeated, tag="3")] - pub last_originator_sids: ::prost::alloc::vec::Vec, + #[prost(message, optional, tag="3")] + pub last_seen: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -51,11 +59,13 @@ pub struct PayerEnvelope { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct UnsignedOriginatorEnvelope { - #[prost(uint64, tag="1")] - pub originator_sid: u64, - #[prost(int64, tag="2")] + #[prost(uint32, tag="1")] + pub originator_node_id: u32, + #[prost(uint64, tag="2")] + pub originator_sequence_id: u64, + #[prost(int64, tag="3")] pub originator_ns: i64, - #[prost(message, optional, tag="3")] + #[prost(message, optional, tag="4")] pub payer_envelope: ::core::option::Option, } /// An alternative to a signature for blockchain payloads @@ -65,7 +75,7 @@ pub struct BlockchainProof { #[prost(uint64, tag="1")] pub block_number: u64, #[prost(uint32, tag="2")] - pub publisher_id: u32, + pub publisher_node_id: u32, } /// Signed originator envelope #[allow(clippy::derive_partial_eq_without_eq)] @@ -88,15 +98,6 @@ pub mod originator_envelope { BlockchainProof(super::BlockchainProof), } } -/// Wraps originator envelope with a sequence ID assigned by the gateway -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct GatewayEnvelope { - #[prost(uint64, tag="1")] - pub gateway_sid: u64, - #[prost(message, optional, tag="2")] - pub originator_envelope: ::core::option::Option, -} /// Reports node misbehavior, submittable by nodes or by clients #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -110,10 +111,10 @@ pub struct MisbehaviorReport { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct EnvelopesQuery { + #[prost(message, optional, tag="3")] + pub last_seen: ::core::option::Option, #[prost(oneof="envelopes_query::Filter", tags="1, 2")] pub filter: ::core::option::Option, - #[prost(oneof="envelopes_query::LastSeen", tags="3, 4")] - pub last_seen: ::core::option::Option, } /// Nested message and enum types in `EnvelopesQuery`. pub mod envelopes_query { @@ -125,15 +126,7 @@ pub mod envelopes_query { Topic(::prost::alloc::vec::Vec), /// Node queries #[prost(uint32, tag="2")] - OriginatorId(u32), - } - #[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, Copy, PartialEq, ::prost::Oneof)] - pub enum LastSeen { - #[prost(uint64, tag="3")] - OriginatorSid(u64), - #[prost(uint64, tag="4")] - GatewaySid(u64), + OriginatorNodeId(u32), } } /// Batch subscribe to envelopes @@ -158,7 +151,7 @@ pub mod batch_subscribe_envelopes_request { #[derive(Clone, PartialEq, ::prost::Message)] pub struct BatchSubscribeEnvelopesResponse { #[prost(message, repeated, tag="1")] - pub envelopes: ::prost::alloc::vec::Vec, + pub envelopes: ::prost::alloc::vec::Vec, } /// Query envelopes request #[allow(clippy::derive_partial_eq_without_eq)] @@ -174,7 +167,7 @@ pub struct QueryEnvelopesRequest { #[derive(Clone, PartialEq, ::prost::Message)] pub struct QueryEnvelopesResponse { #[prost(message, repeated, tag="1")] - pub envelopes: ::prost::alloc::vec::Vec, + pub envelopes: ::prost::alloc::vec::Vec, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -188,6 +181,42 @@ pub struct PublishEnvelopeResponse { #[prost(message, optional, tag="1")] pub originator_envelope: ::core::option::Option, } +/// Request to retrieve the XIDs for the given addresses +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetInboxIdsRequest { + #[prost(message, repeated, tag="1")] + pub requests: ::prost::alloc::vec::Vec, +} +/// Nested message and enum types in `GetInboxIdsRequest`. +pub mod get_inbox_ids_request { + /// A single request for a given address + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct Request { + #[prost(string, tag="1")] + pub address: ::prost::alloc::string::String, + } +} +/// Response with the XIDs for the requested addresses +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetInboxIdsResponse { + #[prost(message, repeated, tag="1")] + pub responses: ::prost::alloc::vec::Vec, +} +/// Nested message and enum types in `GetInboxIdsResponse`. +pub mod get_inbox_ids_response { + /// A single response for a given address + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] + pub struct Response { + #[prost(string, tag="1")] + pub address: ::prost::alloc::string::String, + #[prost(string, optional, tag="2")] + pub inbox_id: ::core::option::Option<::prost::alloc::string::String>, + } +} /// Misbehavior types #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] @@ -226,7 +255,7 @@ impl Misbehavior { } /// Encoded file descriptor set for the `xmtp.xmtpv4` package pub const FILE_DESCRIPTOR_SET: &[u8] = &[ - 0x0a, 0xb1, 0x3c, 0x0a, 0x24, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2f, 0x6d, 0x65, 0x73, 0x73, + 0x0a, 0x85, 0x47, 0x0a, 0x24, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, @@ -235,481 +264,566 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x14, 0x6d, 0x6c, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0x95, 0x01, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, - 0x61, 0x74, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, - 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x73, 0x74, 0x5f, - 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, 0x64, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x04, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x4f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x69, 0x64, 0x73, 0x22, 0x87, 0x04, 0x0a, 0x0e, 0x43, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x49, 0x0a, 0x0d, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4f, 0x0a, 0x0f, 0x77, 0x65, 0x6c, 0x63, 0x6f, - 0x6d, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x65, 0x6c, 0x63, 0x6f, 0x6d, - 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x63, 0x0a, 0x15, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, - 0x6c, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x58, 0x0a, - 0x12, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x78, 0x6d, 0x74, 0x70, - 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x10, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4b, 0x65, 0x79, - 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x5d, 0x0a, 0x13, 0x72, 0x65, 0x76, 0x6f, 0x6b, - 0x65, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x03, 0x61, 0x61, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, - 0x34, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x44, - 0x61, 0x74, 0x61, 0x52, 0x03, 0x61, 0x61, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x22, 0xa9, 0x01, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, - 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x18, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, - 0x5e, 0x0a, 0x0f, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, - 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, - 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x0e, 0x70, 0x61, 0x79, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, - 0xab, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x25, - 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x6f, 0x72, 0x53, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, - 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x72, - 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x70, 0x61, - 0x79, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, - 0x2e, 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x0d, - 0x70, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x22, 0x57, 0x0a, - 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x73, 0x68, 0x65, 0x72, 0x49, 0x64, 0x22, 0x96, 0x02, 0x0a, 0x12, 0x4f, 0x72, 0x69, 0x67, 0x69, - 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x40, 0x0a, - 0x1c, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, - 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x1a, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x72, 0x69, - 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, - 0x6a, 0x0a, 0x14, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, - 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x6f, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x49, 0x0a, 0x10, 0x62, - 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x76, 0x34, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x48, 0x00, 0x52, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x07, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, - 0x84, 0x01, 0x0a, 0x0f, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, - 0x6f, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x73, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x53, 0x69, 0x64, 0x12, 0x50, 0x0a, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x6f, 0x72, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, - 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x52, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x22, 0x80, 0x01, 0x0a, 0x11, 0x4d, 0x69, 0x73, 0x62, 0x65, - 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x4d, 0x69, 0x73, 0x62, 0x65, 0x68, 0x61, - 0x76, 0x69, 0x6f, 0x72, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3d, 0x0a, 0x09, 0x65, 0x6e, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x6f, 0x22, 0xba, 0x01, 0x0a, 0x0b, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, + 0x6b, 0x12, 0x64, 0x0a, 0x16, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x74, 0x6f, 0x5f, + 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x30, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, + 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x49, 0x64, 0x54, 0x6f, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x12, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x54, 0x6f, 0x53, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x1a, 0x45, 0x0a, 0x17, 0x4e, 0x6f, 0x64, 0x65, 0x49, + 0x64, 0x54, 0x6f, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9a, + 0x01, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x44, 0x61, 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, + 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x6f, 0x70, 0x69, + 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, + 0x6f, 0x70, 0x69, 0x63, 0x12, 0x35, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x22, 0x87, 0x04, 0x0a, 0x0e, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x49, + 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x4f, 0x0a, 0x0f, 0x77, 0x65, 0x6c, + 0x63, 0x6f, 0x6d, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x65, 0x6c, 0x63, + 0x6f, 0x6d, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x63, 0x0a, 0x15, 0x72, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x14, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x58, 0x0a, 0x12, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, + 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x6d, 0x6c, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, + 0x6c, 0x6f, 0x61, 0x64, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x10, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x4b, + 0x65, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x5d, 0x0a, 0x13, 0x72, 0x65, 0x76, + 0x6f, 0x6b, 0x65, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x6d, 0x6c, + 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x03, 0x61, 0x61, 0x64, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x76, 0x34, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x03, 0x61, 0x61, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, + 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xa9, 0x01, 0x0a, 0x0d, 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, + 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x18, 0x75, 0x6e, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x75, 0x6e, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x12, 0x5e, 0x0a, 0x0f, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x78, 0x6d, 0x74, + 0x70, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, + 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, + 0x62, 0x6c, 0x65, 0x45, 0x63, 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x0e, 0x70, 0x61, 0x79, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0xe8, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x72, + 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, + 0x12, 0x2c, 0x0a, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x6f, 0x72, + 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x34, + 0x0a, 0x16, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, + 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, + 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x72, 0x69, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x4e, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x70, 0x61, 0x79, + 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, + 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x0d, 0x70, + 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x22, 0x60, 0x0a, 0x0f, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, + 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x5f, + 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x96, + 0x02, 0x0a, 0x12, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, + 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x40, 0x0a, 0x1c, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, + 0x64, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x65, 0x6e, 0x76, + 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x1a, 0x75, 0x6e, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, + 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x6a, 0x0a, 0x14, 0x6f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x63, + 0x64, 0x73, 0x61, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x48, 0x00, 0x52, 0x13, + 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x12, 0x49, 0x0a, 0x10, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x00, 0x52, 0x0f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x07, + 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x80, 0x01, 0x0a, 0x11, 0x4d, 0x69, 0x73, 0x62, + 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2c, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x4d, 0x69, 0x73, 0x62, 0x65, 0x68, + 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3d, 0x0a, 0x09, 0x65, + 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x4f, 0x72, 0x69, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, + 0x09, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x22, 0x99, 0x01, 0x0a, 0x0e, 0x45, + 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, 0x0a, + 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, + 0x74, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x2e, 0x0a, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x48, 0x00, 0x52, 0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x4e, + 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x35, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, + 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6c, 0x6f, + 0x63, 0x6b, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x42, 0x08, 0x0a, 0x06, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xd3, 0x01, 0x0a, 0x1e, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x61, 0x0a, 0x08, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x4e, 0x0a, 0x19, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x05, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, + 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0x60, 0x0a, 0x1f, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, + 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3d, 0x0a, 0x09, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, + 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x52, 0x09, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x22, 0x60, + 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x76, 0x34, 0x2e, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x22, 0x57, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x09, 0x65, 0x6e, + 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x09, - 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x22, 0xb2, 0x01, 0x0a, 0x0e, 0x45, 0x6e, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x05, - 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x74, - 0x6f, 0x70, 0x69, 0x63, 0x12, 0x25, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, - 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x0c, 0x6f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0e, 0x6f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, - 0x72, 0x53, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, - 0x73, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x0a, 0x67, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x53, 0x69, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x42, 0x0b, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x22, 0xd3, - 0x01, 0x0a, 0x1e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x61, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, - 0x34, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x73, 0x1a, 0x4e, 0x0a, 0x19, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x31, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x45, - 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x22, 0x5d, 0x0a, 0x1f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x65, 0x6e, 0x76, 0x65, 0x6c, - 0x6f, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x09, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x73, 0x22, 0x60, 0x0a, 0x15, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x6e, 0x76, 0x65, - 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x05, - 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x6d, - 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x73, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x54, 0x0a, 0x16, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x6e, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3a, 0x0a, 0x09, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, - 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x52, 0x09, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x16, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x65, - 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x50, 0x61, 0x79, 0x65, - 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x65, 0x72, - 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x22, 0x6b, 0x0a, 0x17, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, - 0x72, 0x5f, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x4f, - 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, - 0x65, 0x52, 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, - 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x2a, 0xce, 0x01, 0x0a, 0x0b, 0x4d, 0x69, 0x73, 0x62, 0x65, 0x68, - 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x49, 0x53, 0x42, 0x45, 0x48, 0x41, - 0x56, 0x49, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x4d, 0x49, 0x53, 0x42, 0x45, 0x48, 0x41, 0x56, 0x49, 0x4f, - 0x52, 0x5f, 0x55, 0x4e, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x4e, 0x4f, - 0x44, 0x45, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x4d, 0x49, 0x53, 0x42, 0x45, 0x48, 0x41, 0x56, - 0x49, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x4f, 0x52, 0x44, 0x45, 0x52, - 0x5f, 0x4f, 0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x53, 0x49, 0x44, 0x10, - 0x02, 0x12, 0x28, 0x0a, 0x24, 0x4d, 0x49, 0x53, 0x42, 0x45, 0x48, 0x41, 0x56, 0x49, 0x4f, 0x52, - 0x5f, 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x4f, 0x52, 0x49, 0x47, 0x49, - 0x4e, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x53, 0x49, 0x44, 0x10, 0x03, 0x12, 0x29, 0x0a, 0x25, 0x4d, - 0x49, 0x53, 0x42, 0x45, 0x48, 0x41, 0x56, 0x49, 0x4f, 0x52, 0x5f, 0x43, 0x59, 0x43, 0x4c, 0x49, - 0x43, 0x41, 0x4c, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x4f, 0x52, 0x44, 0x45, - 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x32, 0xb4, 0x03, 0x0a, 0x0e, 0x52, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x70, 0x69, 0x12, 0x9e, 0x01, 0x0a, 0x17, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, - 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, - 0x70, 0x76, 0x34, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, - 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, - 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x6d, 0x6c, - 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2d, 0x65, - 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x30, 0x01, 0x12, 0x7d, 0x0a, 0x0e, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x78, - 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x01, 0x2a, - 0x22, 0x17, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2d, - 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x81, 0x01, 0x0a, 0x0f, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x23, 0x2e, - 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, - 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, - 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x73, 0x68, 0x2d, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x42, 0x9f, 0x01, - 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, - 0x34, 0x42, 0x0f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, - 0x6f, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x5f, 0x61, 0x70, 0x69, 0xa2, 0x02, 0x03, 0x58, 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x58, 0x6d, 0x74, - 0x70, 0x2e, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0xca, 0x02, 0x0b, 0x58, 0x6d, 0x74, 0x70, 0x5c, - 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0xe2, 0x02, 0x17, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x58, 0x6d, - 0x74, 0x70, 0x76, 0x34, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x0c, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x4a, - 0x8a, 0x21, 0x0a, 0x07, 0x12, 0x05, 0x01, 0x00, 0x98, 0x01, 0x01, 0x0a, 0x23, 0x0a, 0x01, 0x0c, - 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x19, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, - 0x41, 0x50, 0x49, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x58, 0x4d, 0x54, 0x50, 0x20, 0x56, 0x34, 0x0a, - 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x14, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, - 0x12, 0x03, 0x05, 0x00, 0x26, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x01, 0x12, 0x03, 0x06, 0x00, 0x2f, - 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, 0x12, 0x03, 0x07, 0x00, 0x1e, 0x0a, 0x08, 0x0a, 0x01, 0x08, - 0x12, 0x03, 0x09, 0x00, 0x45, 0x0a, 0x09, 0x0a, 0x02, 0x08, 0x0b, 0x12, 0x03, 0x09, 0x00, 0x45, - 0x0a, 0x53, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0c, 0x00, 0x10, 0x01, 0x1a, 0x47, 0x20, 0x44, - 0x61, 0x74, 0x61, 0x20, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, - 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0c, 0x08, - 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0d, 0x02, 0x1f, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03, 0x0d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x0d, 0x09, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x02, 0x00, 0x03, 0x12, 0x03, 0x0d, 0x1d, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, - 0x12, 0x03, 0x0e, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, - 0x0e, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x0e, 0x08, - 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x0e, 0x17, 0x18, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x0f, 0x02, 0x2b, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x00, 0x02, 0x02, 0x04, 0x12, 0x03, 0x0f, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, - 0x02, 0x02, 0x05, 0x12, 0x03, 0x0f, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, - 0x01, 0x12, 0x03, 0x0f, 0x12, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, - 0x03, 0x0f, 0x29, 0x2a, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x12, 0x00, 0x1b, 0x01, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, 0x03, 0x12, 0x08, 0x16, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x01, 0x08, 0x00, 0x12, 0x04, 0x13, 0x02, 0x19, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x08, 0x00, 0x01, 0x12, 0x03, 0x13, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, - 0x12, 0x03, 0x14, 0x04, 0x38, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x14, 0x04, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x14, 0x26, - 0x33, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x14, 0x36, 0x37, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x01, 0x12, 0x03, 0x15, 0x04, 0x3c, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x01, 0x02, 0x01, 0x06, 0x12, 0x03, 0x15, 0x04, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x01, 0x01, 0x12, 0x03, 0x15, 0x28, 0x37, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, - 0x03, 0x12, 0x03, 0x15, 0x3a, 0x3b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, - 0x16, 0x04, 0x4a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x06, 0x12, 0x03, 0x16, 0x04, - 0x2f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x16, 0x30, 0x45, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x16, 0x48, 0x49, 0x0a, 0x0b, 0x0a, - 0x04, 0x04, 0x01, 0x02, 0x03, 0x12, 0x03, 0x17, 0x04, 0x43, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, - 0x02, 0x03, 0x06, 0x12, 0x03, 0x17, 0x04, 0x2b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, - 0x01, 0x12, 0x03, 0x17, 0x2c, 0x3e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x03, 0x03, 0x12, - 0x03, 0x17, 0x41, 0x42, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x04, 0x12, 0x03, 0x18, 0x04, - 0x46, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x06, 0x12, 0x03, 0x18, 0x04, 0x2d, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x04, 0x01, 0x12, 0x03, 0x18, 0x2e, 0x41, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x01, 0x02, 0x04, 0x03, 0x12, 0x03, 0x18, 0x44, 0x45, 0x0a, 0x0b, 0x0a, 0x04, 0x04, - 0x01, 0x02, 0x05, 0x12, 0x03, 0x1a, 0x02, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, - 0x06, 0x12, 0x03, 0x1a, 0x02, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, 0x01, 0x12, - 0x03, 0x1a, 0x14, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x05, 0x03, 0x12, 0x03, 0x1a, - 0x1a, 0x1b, 0x0a, 0x38, 0x0a, 0x02, 0x04, 0x02, 0x12, 0x04, 0x1e, 0x00, 0x21, 0x01, 0x1a, 0x2c, - 0x20, 0x57, 0x72, 0x61, 0x70, 0x73, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x65, 0x6e, - 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70, 0x61, 0x79, 0x65, - 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, - 0x04, 0x02, 0x01, 0x12, 0x03, 0x1e, 0x08, 0x15, 0x0a, 0x22, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x00, - 0x12, 0x03, 0x1f, 0x02, 0x25, 0x22, 0x15, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x02, 0x02, 0x00, 0x05, 0x12, 0x03, 0x1f, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, - 0x02, 0x00, 0x01, 0x12, 0x03, 0x1f, 0x08, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, - 0x03, 0x12, 0x03, 0x1f, 0x23, 0x24, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, - 0x20, 0x02, 0x4b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x20, 0x02, - 0x36, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x20, 0x37, 0x46, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x20, 0x49, 0x4a, 0x0a, 0x8e, 0x01, - 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x25, 0x00, 0x29, 0x01, 0x1a, 0x81, 0x01, 0x20, 0x46, 0x6f, - 0x72, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x65, 0x6e, 0x76, - 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, 0x64, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, - 0x74, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2c, 0x0a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x6e, 0x73, 0x20, - 0x69, 0x73, 0x20, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x25, 0x08, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, - 0x02, 0x00, 0x12, 0x03, 0x26, 0x02, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x05, - 0x12, 0x03, 0x26, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, - 0x26, 0x09, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x26, 0x1a, - 0x1b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x01, 0x12, 0x03, 0x27, 0x02, 0x1a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x05, 0x12, 0x03, 0x27, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, 0x03, 0x27, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, - 0x02, 0x01, 0x03, 0x12, 0x03, 0x27, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x03, 0x02, 0x02, - 0x12, 0x03, 0x28, 0x02, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x06, 0x12, 0x03, - 0x28, 0x02, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x01, 0x12, 0x03, 0x28, 0x10, - 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x12, 0x03, 0x28, 0x21, 0x22, 0x0a, - 0x43, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x2c, 0x00, 0x2f, 0x01, 0x1a, 0x37, 0x20, 0x41, 0x6e, - 0x20, 0x61, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, - 0x61, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x2c, 0x08, 0x17, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x2d, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x04, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2d, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x04, 0x02, 0x00, 0x01, 0x12, 0x03, 0x2d, 0x09, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, - 0x00, 0x03, 0x12, 0x03, 0x2d, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, - 0x03, 0x2e, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x05, 0x12, 0x03, 0x2e, - 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x2e, 0x09, 0x15, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x2e, 0x18, 0x19, 0x0a, 0x28, - 0x0a, 0x02, 0x04, 0x05, 0x12, 0x04, 0x32, 0x00, 0x38, 0x01, 0x1a, 0x1c, 0x20, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x65, - 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, - 0x03, 0x32, 0x08, 0x1a, 0x0a, 0x22, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x33, 0x02, - 0x29, 0x22, 0x15, 0x20, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x20, 0x73, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, - 0x05, 0x12, 0x03, 0x33, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, 0x12, - 0x03, 0x33, 0x08, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, 0x33, - 0x27, 0x28, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x05, 0x08, 0x00, 0x12, 0x04, 0x34, 0x02, 0x37, 0x03, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x08, 0x00, 0x01, 0x12, 0x03, 0x34, 0x08, 0x0d, 0x0a, 0x0b, - 0x0a, 0x04, 0x04, 0x05, 0x02, 0x01, 0x12, 0x03, 0x35, 0x04, 0x52, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x05, 0x02, 0x01, 0x06, 0x12, 0x03, 0x35, 0x04, 0x38, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, - 0x01, 0x01, 0x12, 0x03, 0x35, 0x39, 0x4d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x03, - 0x12, 0x03, 0x35, 0x50, 0x51, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x02, 0x12, 0x03, 0x36, - 0x04, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x02, 0x06, 0x12, 0x03, 0x36, 0x04, 0x13, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x02, 0x01, 0x12, 0x03, 0x36, 0x14, 0x24, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x05, 0x02, 0x02, 0x03, 0x12, 0x03, 0x36, 0x27, 0x28, 0x0a, 0x52, 0x0a, 0x02, - 0x04, 0x06, 0x12, 0x04, 0x3b, 0x00, 0x3e, 0x01, 0x1a, 0x46, 0x20, 0x57, 0x72, 0x61, 0x70, 0x73, - 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x65, 0x6e, 0x76, 0x65, - 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x73, 0x65, 0x71, 0x75, - 0x65, 0x6e, 0x63, 0x65, 0x20, 0x49, 0x44, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x3b, 0x08, 0x17, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x06, 0x02, 0x00, 0x12, 0x03, 0x3c, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, - 0x00, 0x05, 0x12, 0x03, 0x3c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x3c, 0x09, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x3c, 0x17, 0x18, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x01, 0x12, 0x03, 0x3d, 0x02, 0x2d, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x06, 0x12, 0x03, 0x3d, 0x02, 0x14, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x01, 0x12, 0x03, 0x3d, 0x15, 0x28, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x06, 0x02, 0x01, 0x03, 0x12, 0x03, 0x3d, 0x2b, 0x2c, 0x0a, 0x1f, 0x0a, 0x02, 0x05, 0x00, - 0x12, 0x04, 0x41, 0x00, 0x47, 0x01, 0x1a, 0x13, 0x20, 0x4d, 0x69, 0x73, 0x62, 0x65, 0x68, 0x61, - 0x76, 0x69, 0x6f, 0x72, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x05, - 0x00, 0x01, 0x12, 0x03, 0x41, 0x05, 0x10, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, - 0x03, 0x42, 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x42, - 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x42, 0x1c, 0x1d, - 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x43, 0x02, 0x23, 0x0a, 0x0c, 0x0a, - 0x05, 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x43, 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x05, - 0x00, 0x02, 0x01, 0x02, 0x12, 0x03, 0x43, 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, - 0x02, 0x12, 0x03, 0x44, 0x02, 0x2e, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x01, 0x12, - 0x03, 0x44, 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x44, - 0x2c, 0x2d, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x03, 0x12, 0x03, 0x45, 0x02, 0x2b, 0x0a, - 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x45, 0x02, 0x26, 0x0a, 0x0c, 0x0a, - 0x05, 0x05, 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, 0x45, 0x29, 0x2a, 0x0a, 0x0b, 0x0a, 0x04, 0x05, - 0x00, 0x02, 0x04, 0x12, 0x03, 0x46, 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x04, - 0x01, 0x12, 0x03, 0x46, 0x02, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x04, 0x02, 0x12, - 0x03, 0x46, 0x2a, 0x2b, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x07, 0x12, 0x04, 0x4a, 0x00, 0x4d, 0x01, - 0x1a, 0x3e, 0x20, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, - 0x6d, 0x69, 0x73, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2c, 0x20, 0x73, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x20, 0x6f, 0x72, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x0a, - 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x07, 0x01, 0x12, 0x03, 0x4a, 0x08, 0x19, 0x0a, 0x0b, 0x0a, 0x04, - 0x04, 0x07, 0x02, 0x00, 0x12, 0x03, 0x4b, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, - 0x00, 0x06, 0x12, 0x03, 0x4b, 0x02, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x01, - 0x12, 0x03, 0x4b, 0x0e, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x03, 0x12, 0x03, - 0x4b, 0x15, 0x16, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x01, 0x12, 0x03, 0x4c, 0x02, 0x2c, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x04, 0x12, 0x03, 0x4c, 0x02, 0x0a, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x06, 0x12, 0x03, 0x4c, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x07, 0x02, 0x01, 0x01, 0x12, 0x03, 0x4c, 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, - 0x02, 0x01, 0x03, 0x12, 0x03, 0x4c, 0x2a, 0x2b, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x08, 0x12, 0x04, - 0x50, 0x00, 0x5c, 0x01, 0x1a, 0x3e, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x2c, 0x20, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, - 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x08, 0x01, 0x12, 0x03, 0x50, 0x08, 0x16, - 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x08, 0x08, 0x00, 0x12, 0x04, 0x51, 0x02, 0x56, 0x03, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x08, 0x08, 0x00, 0x01, 0x12, 0x03, 0x51, 0x08, 0x0e, 0x0a, 0x1d, 0x0a, 0x04, - 0x04, 0x08, 0x02, 0x00, 0x12, 0x03, 0x53, 0x04, 0x14, 0x1a, 0x10, 0x20, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x20, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x08, 0x02, 0x00, 0x05, 0x12, 0x03, 0x53, 0x04, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, - 0x00, 0x01, 0x12, 0x03, 0x53, 0x0a, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x53, 0x12, 0x13, 0x0a, 0x1b, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x01, 0x12, 0x03, 0x55, - 0x04, 0x1d, 0x1a, 0x0e, 0x20, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, - 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x05, 0x12, 0x03, 0x55, 0x04, 0x0a, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x01, 0x12, 0x03, 0x55, 0x0b, 0x18, 0x0a, 0x0c, - 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x03, 0x12, 0x03, 0x55, 0x1b, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x08, 0x08, 0x01, 0x12, 0x04, 0x58, 0x02, 0x5b, 0x03, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, - 0x08, 0x01, 0x01, 0x12, 0x03, 0x58, 0x08, 0x11, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x02, - 0x12, 0x03, 0x59, 0x04, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x05, 0x12, 0x03, - 0x59, 0x04, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x01, 0x12, 0x03, 0x59, 0x0b, - 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x03, 0x12, 0x03, 0x59, 0x1c, 0x1d, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x03, 0x12, 0x03, 0x5a, 0x04, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x08, 0x02, 0x03, 0x05, 0x12, 0x03, 0x5a, 0x04, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, - 0x02, 0x03, 0x01, 0x12, 0x03, 0x5a, 0x0b, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x03, - 0x03, 0x12, 0x03, 0x5a, 0x19, 0x1a, 0x0a, 0x2a, 0x0a, 0x02, 0x04, 0x09, 0x12, 0x04, 0x5f, 0x00, - 0x65, 0x01, 0x1a, 0x1e, 0x20, 0x42, 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x09, 0x01, 0x12, 0x03, 0x5f, 0x08, 0x26, 0x0a, 0x39, - 0x0a, 0x04, 0x04, 0x09, 0x03, 0x00, 0x12, 0x04, 0x61, 0x02, 0x63, 0x03, 0x1a, 0x2b, 0x20, 0x53, - 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, - 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x03, - 0x00, 0x01, 0x12, 0x03, 0x61, 0x0a, 0x23, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x09, 0x03, 0x00, 0x02, - 0x00, 0x12, 0x03, 0x62, 0x04, 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, - 0x06, 0x12, 0x03, 0x62, 0x04, 0x12, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, - 0x01, 0x12, 0x03, 0x62, 0x13, 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, - 0x03, 0x12, 0x03, 0x62, 0x1b, 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x09, 0x02, 0x00, 0x12, 0x03, - 0x64, 0x02, 0x32, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x04, 0x12, 0x03, 0x64, 0x02, - 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x06, 0x12, 0x03, 0x64, 0x0b, 0x24, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x01, 0x12, 0x03, 0x64, 0x25, 0x2d, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x09, 0x02, 0x00, 0x03, 0x12, 0x03, 0x64, 0x30, 0x31, 0x0a, 0x57, 0x0a, 0x02, 0x04, - 0x0a, 0x12, 0x04, 0x68, 0x00, 0x6a, 0x01, 0x1a, 0x4b, 0x20, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x65, 0x64, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, - 0x62, 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, - 0x2d, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, - 0x65, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x6f, - 0x6e, 0x63, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x0a, 0x01, 0x12, 0x03, 0x68, 0x08, 0x27, - 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0a, 0x02, 0x00, 0x12, 0x03, 0x69, 0x02, 0x29, 0x0a, 0x0c, 0x0a, - 0x05, 0x04, 0x0a, 0x02, 0x00, 0x04, 0x12, 0x03, 0x69, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, - 0x0a, 0x02, 0x00, 0x06, 0x12, 0x03, 0x69, 0x0b, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, - 0x00, 0x01, 0x12, 0x03, 0x69, 0x1b, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x03, - 0x12, 0x03, 0x69, 0x27, 0x28, 0x0a, 0x25, 0x0a, 0x02, 0x04, 0x0b, 0x12, 0x04, 0x6d, 0x00, 0x70, - 0x01, 0x1a, 0x19, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, - 0x70, 0x65, 0x73, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, - 0x04, 0x0b, 0x01, 0x12, 0x03, 0x6d, 0x08, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0b, 0x02, 0x00, - 0x12, 0x03, 0x6e, 0x02, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x6e, 0x02, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x01, 0x12, 0x03, 0x6e, 0x11, - 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x03, 0x12, 0x03, 0x6e, 0x19, 0x1a, 0x0a, - 0x0b, 0x0a, 0x04, 0x04, 0x0b, 0x02, 0x01, 0x12, 0x03, 0x6f, 0x02, 0x13, 0x0a, 0x0c, 0x0a, 0x05, - 0x04, 0x0b, 0x02, 0x01, 0x05, 0x12, 0x03, 0x6f, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, - 0x02, 0x01, 0x01, 0x12, 0x03, 0x6f, 0x09, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, - 0x03, 0x12, 0x03, 0x6f, 0x11, 0x12, 0x0a, 0x26, 0x0a, 0x02, 0x04, 0x0c, 0x12, 0x04, 0x73, 0x00, - 0x75, 0x01, 0x1a, 0x1a, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, - 0x6f, 0x70, 0x65, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0a, - 0x0a, 0x03, 0x04, 0x0c, 0x01, 0x12, 0x03, 0x73, 0x08, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0c, - 0x02, 0x00, 0x12, 0x03, 0x74, 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x04, - 0x12, 0x03, 0x74, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x06, 0x12, 0x03, - 0x74, 0x0b, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x01, 0x12, 0x03, 0x74, 0x1b, - 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x03, 0x12, 0x03, 0x74, 0x27, 0x28, 0x0a, - 0x0a, 0x0a, 0x02, 0x04, 0x0d, 0x12, 0x04, 0x77, 0x00, 0x79, 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, - 0x0d, 0x01, 0x12, 0x03, 0x77, 0x08, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0d, 0x02, 0x00, 0x12, - 0x03, 0x78, 0x02, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0d, 0x02, 0x00, 0x06, 0x12, 0x03, 0x78, - 0x02, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0d, 0x02, 0x00, 0x01, 0x12, 0x03, 0x78, 0x10, 0x1e, - 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0d, 0x02, 0x00, 0x03, 0x12, 0x03, 0x78, 0x21, 0x22, 0x0a, 0x0a, - 0x0a, 0x02, 0x04, 0x0e, 0x12, 0x04, 0x7b, 0x00, 0x7d, 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x0e, - 0x01, 0x12, 0x03, 0x7b, 0x08, 0x1f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0e, 0x02, 0x00, 0x12, 0x03, - 0x7c, 0x02, 0x2d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x06, 0x12, 0x03, 0x7c, 0x02, - 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x01, 0x12, 0x03, 0x7c, 0x15, 0x28, 0x0a, - 0x0c, 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x03, 0x12, 0x03, 0x7c, 0x2b, 0x2c, 0x0a, 0x1f, 0x0a, - 0x02, 0x06, 0x00, 0x12, 0x06, 0x80, 0x01, 0x00, 0x98, 0x01, 0x01, 0x1a, 0x11, 0x20, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x0b, - 0x0a, 0x03, 0x06, 0x00, 0x01, 0x12, 0x04, 0x80, 0x01, 0x08, 0x16, 0x0a, 0x28, 0x0a, 0x04, 0x06, - 0x00, 0x02, 0x00, 0x12, 0x06, 0x82, 0x01, 0x02, 0x87, 0x01, 0x03, 0x1a, 0x18, 0x20, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, - 0x6f, 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, - 0x82, 0x01, 0x06, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0x82, - 0x01, 0x1e, 0x3c, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x06, 0x12, 0x04, 0x82, 0x01, - 0x47, 0x4d, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0x82, 0x01, 0x4e, - 0x6d, 0x0a, 0x0f, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x00, 0x04, 0x12, 0x06, 0x83, 0x01, 0x04, 0x86, - 0x01, 0x06, 0x0a, 0x13, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, - 0x06, 0x83, 0x01, 0x04, 0x86, 0x01, 0x06, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x04, - 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x04, 0x84, 0x01, 0x06, 0x29, 0x0a, 0x12, 0x0a, 0x0a, 0x06, - 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x04, 0x85, 0x01, 0x06, 0x0f, 0x0a, - 0x21, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x01, 0x12, 0x06, 0x8a, 0x01, 0x02, 0x8f, 0x01, 0x03, 0x1a, - 0x11, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x8a, 0x01, 0x06, - 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0x8a, 0x01, 0x15, 0x2a, - 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0x8a, 0x01, 0x35, 0x4b, 0x0a, - 0x0f, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x04, 0x12, 0x06, 0x8b, 0x01, 0x04, 0x8e, 0x01, 0x06, - 0x0a, 0x13, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x06, 0x8b, - 0x01, 0x04, 0x8e, 0x01, 0x06, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, - 0xbc, 0x22, 0x04, 0x12, 0x04, 0x8c, 0x01, 0x06, 0x25, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, - 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x04, 0x8d, 0x01, 0x06, 0x0f, 0x0a, 0x22, 0x0a, - 0x04, 0x06, 0x00, 0x02, 0x02, 0x12, 0x06, 0x92, 0x01, 0x02, 0x97, 0x01, 0x03, 0x1a, 0x12, 0x20, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, - 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0x92, 0x01, 0x06, 0x15, - 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0x92, 0x01, 0x16, 0x2c, 0x0a, - 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x03, 0x12, 0x04, 0x92, 0x01, 0x37, 0x4e, 0x0a, 0x0f, - 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x04, 0x12, 0x06, 0x93, 0x01, 0x04, 0x96, 0x01, 0x06, 0x0a, - 0x13, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x06, 0x93, 0x01, - 0x04, 0x96, 0x01, 0x06, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, - 0x22, 0x04, 0x12, 0x04, 0x94, 0x01, 0x06, 0x26, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x02, - 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x04, 0x95, 0x01, 0x06, 0x0f, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x16, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x65, 0x6e, 0x76, + 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x50, 0x61, 0x79, 0x65, 0x72, 0x45, + 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x65, 0x72, 0x45, 0x6e, + 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x22, 0x6b, 0x0a, 0x17, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x50, 0x0a, 0x13, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, + 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x4f, 0x72, 0x69, + 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, + 0x12, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x22, 0x7e, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, + 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x6d, + 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, + 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x1a, 0x23, + 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, + 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x09, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x1a, 0x51, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x08, 0x69, 0x6e, + 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, + 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x69, + 0x6e, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x2a, 0xce, 0x01, 0x0a, 0x0b, 0x4d, 0x69, 0x73, 0x62, + 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x17, 0x4d, 0x49, 0x53, 0x42, 0x45, + 0x48, 0x41, 0x56, 0x49, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x4d, 0x49, 0x53, 0x42, 0x45, 0x48, 0x41, 0x56, + 0x49, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x5f, + 0x4e, 0x4f, 0x44, 0x45, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x4d, 0x49, 0x53, 0x42, 0x45, 0x48, + 0x41, 0x56, 0x49, 0x4f, 0x52, 0x5f, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x4f, 0x52, 0x44, + 0x45, 0x52, 0x5f, 0x4f, 0x52, 0x49, 0x47, 0x49, 0x4e, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x53, 0x49, + 0x44, 0x10, 0x02, 0x12, 0x28, 0x0a, 0x24, 0x4d, 0x49, 0x53, 0x42, 0x45, 0x48, 0x41, 0x56, 0x49, + 0x4f, 0x52, 0x5f, 0x44, 0x55, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x5f, 0x4f, 0x52, 0x49, + 0x47, 0x49, 0x4e, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x53, 0x49, 0x44, 0x10, 0x03, 0x12, 0x29, 0x0a, + 0x25, 0x4d, 0x49, 0x53, 0x42, 0x45, 0x48, 0x41, 0x56, 0x49, 0x4f, 0x52, 0x5f, 0x43, 0x59, 0x43, + 0x4c, 0x49, 0x43, 0x41, 0x4c, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x4f, 0x52, + 0x44, 0x45, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x32, 0xa8, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x70, 0x69, 0x12, 0x9e, 0x01, 0x0a, 0x17, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, + 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, + 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x62, 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x76, 0x34, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, + 0x6d, 0x6c, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x2d, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x30, 0x01, 0x12, 0x7d, 0x0a, 0x0e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x22, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, + 0x01, 0x2a, 0x22, 0x17, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2d, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x81, 0x01, 0x0a, 0x0f, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, + 0x23, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x76, 0x34, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, + 0x70, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x6d, 0x6c, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x2d, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, + 0x72, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x12, 0x1f, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x20, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2e, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15, 0x2f, 0x6d, + 0x6c, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x67, 0x65, 0x74, 0x2d, 0x69, 0x6e, 0x62, 0x6f, 0x78, 0x2d, + 0x69, 0x64, 0x73, 0x42, 0x9f, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x6d, 0x74, 0x70, + 0x2e, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x42, 0x0f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x76, 0x33, 0x2f, 0x67, 0x6f, 0x2f, 0x78, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x2f, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x61, 0x70, 0x69, 0xa2, 0x02, 0x03, 0x58, 0x58, 0x58, + 0xaa, 0x02, 0x0b, 0x58, 0x6d, 0x74, 0x70, 0x2e, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0xca, 0x02, + 0x0b, 0x58, 0x6d, 0x74, 0x70, 0x5c, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0xe2, 0x02, 0x17, 0x58, + 0x6d, 0x74, 0x70, 0x5c, 0x58, 0x6d, 0x74, 0x70, 0x76, 0x34, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0c, 0x58, 0x6d, 0x74, 0x70, 0x3a, 0x3a, 0x58, + 0x6d, 0x74, 0x70, 0x76, 0x34, 0x4a, 0xc8, 0x27, 0x0a, 0x07, 0x12, 0x05, 0x01, 0x00, 0xb1, 0x01, + 0x01, 0x0a, 0x23, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x01, 0x00, 0x12, 0x1a, 0x19, 0x20, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x41, 0x50, 0x49, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x58, 0x4d, + 0x54, 0x50, 0x20, 0x56, 0x34, 0x0a, 0x0a, 0x08, 0x0a, 0x01, 0x02, 0x12, 0x03, 0x03, 0x00, 0x14, + 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x00, 0x12, 0x03, 0x05, 0x00, 0x26, 0x0a, 0x09, 0x0a, 0x02, 0x03, + 0x01, 0x12, 0x03, 0x06, 0x00, 0x2f, 0x0a, 0x09, 0x0a, 0x02, 0x03, 0x02, 0x12, 0x03, 0x07, 0x00, + 0x1e, 0x0a, 0x08, 0x0a, 0x01, 0x08, 0x12, 0x03, 0x09, 0x00, 0x45, 0x0a, 0x09, 0x0a, 0x02, 0x08, + 0x0b, 0x12, 0x03, 0x09, 0x00, 0x45, 0x0a, 0xb7, 0x01, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x0d, + 0x00, 0x0f, 0x01, 0x1a, 0xaa, 0x01, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, + 0x73, 0x65, 0x65, 0x6e, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x70, 0x65, 0x72, 0x20, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x2e, 0x20, 0x4f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x6f, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x2e, 0x0a, 0x20, 0x45, 0x6e, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x20, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x73, 0x63, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, + 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x49, 0x44, 0x27, + 0x73, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x2e, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x0d, 0x08, 0x13, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x0e, 0x02, 0x31, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, + 0x00, 0x06, 0x12, 0x03, 0x0e, 0x02, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, + 0x12, 0x03, 0x0e, 0x16, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x0e, 0x2f, 0x30, 0x0a, 0x53, 0x0a, 0x02, 0x04, 0x01, 0x12, 0x04, 0x12, 0x00, 0x16, 0x01, 0x1a, + 0x47, 0x20, 0x44, 0x61, 0x74, 0x61, 0x20, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, + 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x01, 0x01, 0x12, + 0x03, 0x12, 0x08, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x00, 0x12, 0x03, 0x13, 0x02, + 0x1f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x05, 0x12, 0x03, 0x13, 0x02, 0x08, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x00, 0x01, 0x12, 0x03, 0x13, 0x09, 0x1a, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x00, 0x03, 0x12, 0x03, 0x13, 0x1d, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x01, 0x02, 0x01, 0x12, 0x03, 0x14, 0x02, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, + 0x05, 0x12, 0x03, 0x14, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x01, 0x12, + 0x03, 0x14, 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x01, 0x03, 0x12, 0x03, 0x14, + 0x17, 0x18, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x01, 0x02, 0x02, 0x12, 0x03, 0x15, 0x02, 0x1c, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x01, 0x02, 0x02, 0x06, 0x12, 0x03, 0x15, 0x02, 0x0d, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x01, 0x02, 0x02, 0x01, 0x12, 0x03, 0x15, 0x0e, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x01, 0x02, 0x02, 0x03, 0x12, 0x03, 0x15, 0x1a, 0x1b, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x02, 0x12, + 0x04, 0x18, 0x00, 0x21, 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x02, 0x01, 0x12, 0x03, 0x18, 0x08, + 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x02, 0x08, 0x00, 0x12, 0x04, 0x19, 0x02, 0x1f, 0x03, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x08, 0x00, 0x01, 0x12, 0x03, 0x19, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, + 0x04, 0x04, 0x02, 0x02, 0x00, 0x12, 0x03, 0x1a, 0x04, 0x38, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, + 0x02, 0x00, 0x06, 0x12, 0x03, 0x1a, 0x04, 0x25, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, + 0x01, 0x12, 0x03, 0x1a, 0x26, 0x33, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x00, 0x03, 0x12, + 0x03, 0x1a, 0x36, 0x37, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x01, 0x12, 0x03, 0x1b, 0x04, + 0x3c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x06, 0x12, 0x03, 0x1b, 0x04, 0x27, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x01, 0x01, 0x12, 0x03, 0x1b, 0x28, 0x37, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x01, 0x03, 0x12, 0x03, 0x1b, 0x3a, 0x3b, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x02, 0x02, 0x02, 0x12, 0x03, 0x1c, 0x04, 0x4a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, + 0x06, 0x12, 0x03, 0x1c, 0x04, 0x2f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x01, 0x12, + 0x03, 0x1c, 0x30, 0x45, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x02, 0x03, 0x12, 0x03, 0x1c, + 0x48, 0x49, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, 0x03, 0x1d, 0x04, 0x43, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x03, 0x06, 0x12, 0x03, 0x1d, 0x04, 0x2b, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x03, 0x01, 0x12, 0x03, 0x1d, 0x2c, 0x3e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x02, 0x02, 0x03, 0x03, 0x12, 0x03, 0x1d, 0x41, 0x42, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, + 0x04, 0x12, 0x03, 0x1e, 0x04, 0x46, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x04, 0x06, 0x12, + 0x03, 0x1e, 0x04, 0x2d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x04, 0x01, 0x12, 0x03, 0x1e, + 0x2e, 0x41, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, 0x04, 0x03, 0x12, 0x03, 0x1e, 0x44, 0x45, + 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x02, 0x02, 0x05, 0x12, 0x03, 0x20, 0x02, 0x1c, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x02, 0x02, 0x05, 0x06, 0x12, 0x03, 0x20, 0x02, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x02, 0x02, 0x05, 0x01, 0x12, 0x03, 0x20, 0x14, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x02, 0x02, + 0x05, 0x03, 0x12, 0x03, 0x20, 0x1a, 0x1b, 0x0a, 0x38, 0x0a, 0x02, 0x04, 0x03, 0x12, 0x04, 0x24, + 0x00, 0x27, 0x01, 0x1a, 0x2c, 0x20, 0x57, 0x72, 0x61, 0x70, 0x73, 0x20, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, + 0x20, 0x70, 0x61, 0x79, 0x65, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x03, 0x01, 0x12, 0x03, 0x24, 0x08, 0x15, 0x0a, 0x22, 0x0a, + 0x04, 0x04, 0x03, 0x02, 0x00, 0x12, 0x03, 0x25, 0x02, 0x25, 0x22, 0x15, 0x20, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, + 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x05, 0x12, 0x03, 0x25, 0x02, 0x07, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x00, 0x01, 0x12, 0x03, 0x25, 0x08, 0x20, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x03, 0x02, 0x00, 0x03, 0x12, 0x03, 0x25, 0x23, 0x24, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x03, 0x02, 0x01, 0x12, 0x03, 0x26, 0x02, 0x4b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, + 0x06, 0x12, 0x03, 0x26, 0x02, 0x36, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x12, + 0x03, 0x26, 0x37, 0x46, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x03, 0x02, 0x01, 0x03, 0x12, 0x03, 0x26, + 0x49, 0x4a, 0x0a, 0x8e, 0x01, 0x0a, 0x02, 0x04, 0x04, 0x12, 0x04, 0x2b, 0x00, 0x30, 0x01, 0x1a, + 0x81, 0x01, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, 0x64, 0x20, + 0x69, 0x73, 0x20, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, + 0x61, 0x72, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2c, 0x0a, 0x20, 0x62, + 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, + 0x72, 0x5f, 0x6e, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f, + 0x64, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x04, 0x01, 0x12, 0x03, 0x2b, 0x08, 0x22, 0x0a, + 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x00, 0x12, 0x03, 0x2c, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x04, 0x02, 0x00, 0x05, 0x12, 0x03, 0x2c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x2c, 0x09, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x2c, 0x1e, 0x1f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x01, 0x12, 0x03, + 0x2d, 0x02, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x05, 0x12, 0x03, 0x2d, 0x02, + 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x01, 0x12, 0x03, 0x2d, 0x09, 0x1f, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x01, 0x03, 0x12, 0x03, 0x2d, 0x22, 0x23, 0x0a, 0x0b, 0x0a, + 0x04, 0x04, 0x04, 0x02, 0x02, 0x12, 0x03, 0x2e, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, + 0x02, 0x02, 0x05, 0x12, 0x03, 0x2e, 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, + 0x01, 0x12, 0x03, 0x2e, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x02, 0x03, 0x12, + 0x03, 0x2e, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x04, 0x02, 0x03, 0x12, 0x03, 0x2f, 0x02, + 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x03, 0x06, 0x12, 0x03, 0x2f, 0x02, 0x0f, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x04, 0x02, 0x03, 0x01, 0x12, 0x03, 0x2f, 0x10, 0x1e, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x04, 0x02, 0x03, 0x03, 0x12, 0x03, 0x2f, 0x21, 0x22, 0x0a, 0x43, 0x0a, 0x02, 0x04, + 0x05, 0x12, 0x04, 0x33, 0x00, 0x36, 0x01, 0x1a, 0x37, 0x20, 0x41, 0x6e, 0x20, 0x61, 0x6c, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6c, 0x6f, 0x63, + 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x0a, + 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x05, 0x01, 0x12, 0x03, 0x33, 0x08, 0x17, 0x0a, 0x0b, 0x0a, 0x04, + 0x04, 0x05, 0x02, 0x00, 0x12, 0x03, 0x34, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, + 0x00, 0x05, 0x12, 0x03, 0x34, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x01, + 0x12, 0x03, 0x34, 0x09, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x34, 0x18, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x05, 0x02, 0x01, 0x12, 0x03, 0x35, 0x02, 0x1f, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x05, 0x12, 0x03, 0x35, 0x02, 0x08, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x05, 0x02, 0x01, 0x01, 0x12, 0x03, 0x35, 0x09, 0x1a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x05, 0x02, 0x01, 0x03, 0x12, 0x03, 0x35, 0x1d, 0x1e, 0x0a, 0x28, 0x0a, 0x02, 0x04, 0x06, + 0x12, 0x04, 0x39, 0x00, 0x3f, 0x01, 0x1a, 0x1c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, + 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x06, 0x01, 0x12, 0x03, 0x39, 0x08, 0x1a, + 0x0a, 0x22, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x00, 0x12, 0x03, 0x3a, 0x02, 0x29, 0x22, 0x15, 0x20, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x64, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x05, 0x12, 0x03, 0x3a, + 0x02, 0x07, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x01, 0x12, 0x03, 0x3a, 0x08, 0x24, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x00, 0x03, 0x12, 0x03, 0x3a, 0x27, 0x28, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x06, 0x08, 0x00, 0x12, 0x04, 0x3b, 0x02, 0x3e, 0x03, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x06, 0x08, 0x00, 0x01, 0x12, 0x03, 0x3b, 0x08, 0x0d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, + 0x02, 0x01, 0x12, 0x03, 0x3c, 0x04, 0x52, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x06, + 0x12, 0x03, 0x3c, 0x04, 0x38, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x01, 0x12, 0x03, + 0x3c, 0x39, 0x4d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, 0x02, 0x01, 0x03, 0x12, 0x03, 0x3c, 0x50, + 0x51, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x06, 0x02, 0x02, 0x12, 0x03, 0x3d, 0x04, 0x29, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x06, 0x02, 0x02, 0x06, 0x12, 0x03, 0x3d, 0x04, 0x13, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x06, 0x02, 0x02, 0x01, 0x12, 0x03, 0x3d, 0x14, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x06, + 0x02, 0x02, 0x03, 0x12, 0x03, 0x3d, 0x27, 0x28, 0x0a, 0x1f, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, + 0x42, 0x00, 0x48, 0x01, 0x1a, 0x13, 0x20, 0x4d, 0x69, 0x73, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, + 0x6f, 0x72, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, 0x01, + 0x12, 0x03, 0x42, 0x05, 0x10, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, 0x43, + 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x43, 0x02, 0x19, + 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x03, 0x43, 0x1c, 0x1d, 0x0a, 0x0b, + 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x03, 0x44, 0x02, 0x23, 0x0a, 0x0c, 0x0a, 0x05, 0x05, + 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x44, 0x02, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, + 0x01, 0x02, 0x12, 0x03, 0x44, 0x21, 0x22, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x02, 0x12, + 0x03, 0x45, 0x02, 0x2e, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x45, + 0x02, 0x29, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x12, 0x03, 0x45, 0x2c, 0x2d, + 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x03, 0x12, 0x03, 0x46, 0x02, 0x2b, 0x0a, 0x0c, 0x0a, + 0x05, 0x05, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x46, 0x02, 0x26, 0x0a, 0x0c, 0x0a, 0x05, 0x05, + 0x00, 0x02, 0x03, 0x02, 0x12, 0x03, 0x46, 0x29, 0x2a, 0x0a, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x02, + 0x04, 0x12, 0x03, 0x47, 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x04, 0x01, 0x12, + 0x03, 0x47, 0x02, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x04, 0x02, 0x12, 0x03, 0x47, + 0x2a, 0x2b, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x07, 0x12, 0x04, 0x4b, 0x00, 0x4e, 0x01, 0x1a, 0x3e, + 0x20, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x20, 0x6d, 0x69, + 0x73, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x20, + 0x6f, 0x72, 0x20, 0x62, 0x79, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x0a, 0x0a, 0x0a, + 0x0a, 0x03, 0x04, 0x07, 0x01, 0x12, 0x03, 0x4b, 0x08, 0x19, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, + 0x02, 0x00, 0x12, 0x03, 0x4c, 0x02, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x06, + 0x12, 0x03, 0x4c, 0x02, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x01, 0x12, 0x03, + 0x4c, 0x0e, 0x12, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x00, 0x03, 0x12, 0x03, 0x4c, 0x15, + 0x16, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x07, 0x02, 0x01, 0x12, 0x03, 0x4d, 0x02, 0x2c, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, 0x04, 0x12, 0x03, 0x4d, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x07, 0x02, 0x01, 0x06, 0x12, 0x03, 0x4d, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, + 0x02, 0x01, 0x01, 0x12, 0x03, 0x4d, 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x07, 0x02, 0x01, + 0x03, 0x12, 0x03, 0x4d, 0x2a, 0x2b, 0x0a, 0x4a, 0x0a, 0x02, 0x04, 0x08, 0x12, 0x04, 0x51, 0x00, + 0x59, 0x01, 0x1a, 0x3e, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, + 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x2c, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, + 0x20, 0x62, 0x79, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x73, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x08, 0x01, 0x12, 0x03, 0x51, 0x08, 0x16, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x08, 0x08, 0x00, 0x12, 0x04, 0x52, 0x02, 0x57, 0x03, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x08, 0x08, 0x00, 0x01, 0x12, 0x03, 0x52, 0x08, 0x0e, 0x0a, 0x1d, 0x0a, 0x04, 0x04, 0x08, + 0x02, 0x00, 0x12, 0x03, 0x54, 0x04, 0x14, 0x1a, 0x10, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x20, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, + 0x00, 0x05, 0x12, 0x03, 0x54, 0x04, 0x09, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x01, + 0x12, 0x03, 0x54, 0x0a, 0x0f, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x00, 0x03, 0x12, 0x03, + 0x54, 0x12, 0x13, 0x0a, 0x1b, 0x0a, 0x04, 0x04, 0x08, 0x02, 0x01, 0x12, 0x03, 0x56, 0x04, 0x22, + 0x1a, 0x0e, 0x20, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x05, 0x12, 0x03, 0x56, 0x04, 0x0a, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x08, 0x02, 0x01, 0x01, 0x12, 0x03, 0x56, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x08, 0x02, 0x01, 0x03, 0x12, 0x03, 0x56, 0x20, 0x21, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x08, + 0x02, 0x02, 0x12, 0x03, 0x58, 0x02, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x06, + 0x12, 0x03, 0x58, 0x02, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x01, 0x12, 0x03, + 0x58, 0x0e, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x08, 0x02, 0x02, 0x03, 0x12, 0x03, 0x58, 0x1a, + 0x1b, 0x0a, 0x2a, 0x0a, 0x02, 0x04, 0x09, 0x12, 0x04, 0x5c, 0x00, 0x62, 0x01, 0x1a, 0x1e, 0x20, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, + 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x09, 0x01, 0x12, 0x03, 0x5c, 0x08, 0x26, 0x0a, 0x39, 0x0a, 0x04, 0x04, 0x09, 0x03, + 0x00, 0x12, 0x04, 0x5e, 0x02, 0x60, 0x03, 0x1a, 0x2b, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, + 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, + 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x03, 0x00, 0x01, 0x12, 0x03, 0x5e, + 0x0a, 0x23, 0x0a, 0x0d, 0x0a, 0x06, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x12, 0x03, 0x5f, 0x04, + 0x1d, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x06, 0x12, 0x03, 0x5f, 0x04, + 0x12, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x5f, 0x13, + 0x18, 0x0a, 0x0e, 0x0a, 0x07, 0x04, 0x09, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x5f, 0x1b, + 0x1c, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x09, 0x02, 0x00, 0x12, 0x03, 0x61, 0x02, 0x32, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, 0x04, 0x12, 0x03, 0x61, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x09, 0x02, 0x00, 0x06, 0x12, 0x03, 0x61, 0x0b, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, + 0x02, 0x00, 0x01, 0x12, 0x03, 0x61, 0x25, 0x2d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x09, 0x02, 0x00, + 0x03, 0x12, 0x03, 0x61, 0x30, 0x31, 0x0a, 0x57, 0x0a, 0x02, 0x04, 0x0a, 0x12, 0x04, 0x65, 0x00, + 0x67, 0x01, 0x1a, 0x4b, 0x20, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x64, 0x20, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x61, 0x74, 0x63, 0x68, + 0x20, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, 0x2d, 0x20, 0x63, 0x61, 0x6e, + 0x20, 0x62, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x65, 0x6e, 0x76, + 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x0a, 0x0a, + 0x0a, 0x0a, 0x03, 0x04, 0x0a, 0x01, 0x12, 0x03, 0x65, 0x08, 0x27, 0x0a, 0x0b, 0x0a, 0x04, 0x04, + 0x0a, 0x02, 0x00, 0x12, 0x03, 0x66, 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, + 0x04, 0x12, 0x03, 0x66, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x06, 0x12, + 0x03, 0x66, 0x0b, 0x1d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x01, 0x12, 0x03, 0x66, + 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0a, 0x02, 0x00, 0x03, 0x12, 0x03, 0x66, 0x2a, 0x2b, + 0x0a, 0x25, 0x0a, 0x02, 0x04, 0x0b, 0x12, 0x04, 0x6a, 0x00, 0x6d, 0x01, 0x1a, 0x19, 0x20, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x20, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x0b, 0x01, 0x12, 0x03, + 0x6a, 0x08, 0x1d, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0b, 0x02, 0x00, 0x12, 0x03, 0x6b, 0x02, 0x1b, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x06, 0x12, 0x03, 0x6b, 0x02, 0x10, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x00, 0x01, 0x12, 0x03, 0x6b, 0x11, 0x16, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x0b, 0x02, 0x00, 0x03, 0x12, 0x03, 0x6b, 0x19, 0x1a, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0b, + 0x02, 0x01, 0x12, 0x03, 0x6c, 0x02, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x05, + 0x12, 0x03, 0x6c, 0x02, 0x08, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x01, 0x12, 0x03, + 0x6c, 0x09, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0b, 0x02, 0x01, 0x03, 0x12, 0x03, 0x6c, 0x11, + 0x12, 0x0a, 0x26, 0x0a, 0x02, 0x04, 0x0c, 0x12, 0x04, 0x70, 0x00, 0x72, 0x01, 0x1a, 0x1a, 0x20, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x20, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x0a, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x0c, 0x01, + 0x12, 0x03, 0x70, 0x08, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0c, 0x02, 0x00, 0x12, 0x03, 0x71, + 0x02, 0x2c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x04, 0x12, 0x03, 0x71, 0x02, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x06, 0x12, 0x03, 0x71, 0x0b, 0x1d, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x0c, 0x02, 0x00, 0x01, 0x12, 0x03, 0x71, 0x1e, 0x27, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x0c, 0x02, 0x00, 0x03, 0x12, 0x03, 0x71, 0x2a, 0x2b, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x0d, + 0x12, 0x04, 0x74, 0x00, 0x76, 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x0d, 0x01, 0x12, 0x03, 0x74, + 0x08, 0x1e, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0d, 0x02, 0x00, 0x12, 0x03, 0x75, 0x02, 0x23, 0x0a, + 0x0c, 0x0a, 0x05, 0x04, 0x0d, 0x02, 0x00, 0x06, 0x12, 0x03, 0x75, 0x02, 0x0f, 0x0a, 0x0c, 0x0a, + 0x05, 0x04, 0x0d, 0x02, 0x00, 0x01, 0x12, 0x03, 0x75, 0x10, 0x1e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, + 0x0d, 0x02, 0x00, 0x03, 0x12, 0x03, 0x75, 0x21, 0x22, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x0e, 0x12, + 0x04, 0x78, 0x00, 0x7a, 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x0e, 0x01, 0x12, 0x03, 0x78, 0x08, + 0x1f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x0e, 0x02, 0x00, 0x12, 0x03, 0x79, 0x02, 0x2d, 0x0a, 0x0c, + 0x0a, 0x05, 0x04, 0x0e, 0x02, 0x00, 0x06, 0x12, 0x03, 0x79, 0x02, 0x14, 0x0a, 0x0c, 0x0a, 0x05, + 0x04, 0x0e, 0x02, 0x00, 0x01, 0x12, 0x03, 0x79, 0x15, 0x28, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0e, + 0x02, 0x00, 0x03, 0x12, 0x03, 0x79, 0x2b, 0x2c, 0x0a, 0x43, 0x0a, 0x02, 0x04, 0x0f, 0x12, 0x05, + 0x7d, 0x00, 0x84, 0x01, 0x01, 0x1a, 0x36, 0x20, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, + 0x74, 0x6f, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x58, 0x49, 0x44, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x69, 0x76, + 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, 0x0a, 0x0a, 0x0a, + 0x03, 0x04, 0x0f, 0x01, 0x12, 0x03, 0x7d, 0x08, 0x1a, 0x0a, 0x35, 0x0a, 0x04, 0x04, 0x0f, 0x03, + 0x00, 0x12, 0x05, 0x7f, 0x02, 0x81, 0x01, 0x03, 0x1a, 0x26, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, + 0x67, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0a, + 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x0f, 0x03, 0x00, 0x01, 0x12, 0x03, 0x7f, 0x0a, 0x11, 0x0a, 0x0e, + 0x0a, 0x06, 0x04, 0x0f, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0x80, 0x01, 0x04, 0x17, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x0f, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0x80, 0x01, 0x04, 0x0a, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x0f, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x80, 0x01, 0x0b, 0x12, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x0f, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0x80, 0x01, 0x15, + 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x0f, 0x02, 0x00, 0x12, 0x04, 0x83, 0x01, 0x02, 0x20, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x04, 0x12, 0x04, 0x83, 0x01, 0x02, 0x0a, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x0f, 0x02, 0x00, 0x06, 0x12, 0x04, 0x83, 0x01, 0x0b, 0x12, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x0f, 0x02, 0x00, 0x01, 0x12, 0x04, 0x83, 0x01, 0x13, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x0f, 0x02, 0x00, 0x03, 0x12, 0x04, 0x83, 0x01, 0x1e, 0x1f, 0x0a, 0x42, 0x0a, 0x02, 0x04, + 0x10, 0x12, 0x06, 0x87, 0x01, 0x00, 0x8f, 0x01, 0x01, 0x1a, 0x34, 0x20, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x58, 0x49, + 0x44, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x65, 0x64, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, 0x0a, + 0x0b, 0x0a, 0x03, 0x04, 0x10, 0x01, 0x12, 0x04, 0x87, 0x01, 0x08, 0x1b, 0x0a, 0x37, 0x0a, 0x04, + 0x04, 0x10, 0x03, 0x00, 0x12, 0x06, 0x89, 0x01, 0x02, 0x8c, 0x01, 0x03, 0x1a, 0x27, 0x20, 0x41, + 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x10, 0x03, 0x00, 0x01, 0x12, 0x04, + 0x89, 0x01, 0x0a, 0x12, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x10, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, + 0x8a, 0x01, 0x04, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x10, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, + 0x04, 0x8a, 0x01, 0x04, 0x0a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x10, 0x03, 0x00, 0x02, 0x00, 0x01, + 0x12, 0x04, 0x8a, 0x01, 0x0b, 0x12, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x10, 0x03, 0x00, 0x02, 0x00, + 0x03, 0x12, 0x04, 0x8a, 0x01, 0x15, 0x16, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x10, 0x03, 0x00, 0x02, + 0x01, 0x12, 0x04, 0x8b, 0x01, 0x04, 0x21, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x10, 0x03, 0x00, 0x02, + 0x01, 0x04, 0x12, 0x04, 0x8b, 0x01, 0x04, 0x0c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x10, 0x03, 0x00, + 0x02, 0x01, 0x05, 0x12, 0x04, 0x8b, 0x01, 0x0d, 0x13, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x10, 0x03, + 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x8b, 0x01, 0x14, 0x1c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x10, + 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0x8b, 0x01, 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x10, 0x02, 0x00, 0x12, 0x04, 0x8e, 0x01, 0x02, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x10, 0x02, + 0x00, 0x04, 0x12, 0x04, 0x8e, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x10, 0x02, 0x00, + 0x06, 0x12, 0x04, 0x8e, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x10, 0x02, 0x00, 0x01, + 0x12, 0x04, 0x8e, 0x01, 0x14, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x10, 0x02, 0x00, 0x03, 0x12, + 0x04, 0x8e, 0x01, 0x20, 0x21, 0x0a, 0x1f, 0x0a, 0x02, 0x06, 0x00, 0x12, 0x06, 0x92, 0x01, 0x00, + 0xb1, 0x01, 0x01, 0x1a, 0x11, 0x20, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x41, 0x50, 0x49, 0x0a, 0x0a, 0x0b, 0x0a, 0x03, 0x06, 0x00, 0x01, 0x12, 0x04, 0x92, + 0x01, 0x08, 0x16, 0x0a, 0x28, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x00, 0x12, 0x06, 0x94, 0x01, 0x02, + 0x99, 0x01, 0x03, 0x1a, 0x18, 0x20, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x20, + 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, + 0x05, 0x06, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x94, 0x01, 0x06, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, + 0x06, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0x94, 0x01, 0x1e, 0x3c, 0x0a, 0x0d, 0x0a, 0x05, 0x06, + 0x00, 0x02, 0x00, 0x06, 0x12, 0x04, 0x94, 0x01, 0x47, 0x4d, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, + 0x02, 0x00, 0x03, 0x12, 0x04, 0x94, 0x01, 0x4e, 0x6d, 0x0a, 0x0f, 0x0a, 0x05, 0x06, 0x00, 0x02, + 0x00, 0x04, 0x12, 0x06, 0x95, 0x01, 0x04, 0x98, 0x01, 0x06, 0x0a, 0x13, 0x0a, 0x09, 0x06, 0x00, + 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x06, 0x95, 0x01, 0x04, 0x98, 0x01, 0x06, 0x0a, + 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x04, 0x96, + 0x01, 0x06, 0x29, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x04, 0xb0, 0xca, 0xbc, 0x22, + 0x07, 0x12, 0x04, 0x97, 0x01, 0x06, 0x0f, 0x0a, 0x21, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x01, 0x12, + 0x06, 0x9c, 0x01, 0x02, 0xa1, 0x01, 0x03, 0x1a, 0x11, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x20, + 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, + 0x02, 0x01, 0x01, 0x12, 0x04, 0x9c, 0x01, 0x06, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, + 0x01, 0x02, 0x12, 0x04, 0x9c, 0x01, 0x15, 0x2a, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, + 0x03, 0x12, 0x04, 0x9c, 0x01, 0x35, 0x4b, 0x0a, 0x0f, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x01, 0x04, + 0x12, 0x06, 0x9d, 0x01, 0x04, 0xa0, 0x01, 0x06, 0x0a, 0x13, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x01, + 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x06, 0x9d, 0x01, 0x04, 0xa0, 0x01, 0x06, 0x0a, 0x12, 0x0a, + 0x0a, 0x06, 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x04, 0x9e, 0x01, 0x06, + 0x25, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x01, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, + 0x04, 0x9f, 0x01, 0x06, 0x0f, 0x0a, 0x22, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x02, 0x12, 0x06, 0xa4, + 0x01, 0x02, 0xa9, 0x01, 0x03, 0x1a, 0x12, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, + 0x65, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, + 0x02, 0x01, 0x12, 0x04, 0xa4, 0x01, 0x06, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, + 0x02, 0x12, 0x04, 0xa4, 0x01, 0x16, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x03, + 0x12, 0x04, 0xa4, 0x01, 0x37, 0x4e, 0x0a, 0x0f, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x02, 0x04, 0x12, + 0x06, 0xa5, 0x01, 0x04, 0xa8, 0x01, 0x06, 0x0a, 0x13, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x02, 0x04, + 0xb0, 0xca, 0xbc, 0x22, 0x12, 0x06, 0xa5, 0x01, 0x04, 0xa8, 0x01, 0x06, 0x0a, 0x12, 0x0a, 0x0a, + 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x04, 0xa6, 0x01, 0x06, 0x26, + 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x02, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x04, + 0xa7, 0x01, 0x06, 0x0f, 0x0a, 0x1f, 0x0a, 0x04, 0x06, 0x00, 0x02, 0x03, 0x12, 0x06, 0xab, 0x01, + 0x02, 0xb0, 0x01, 0x03, 0x1a, 0x0f, 0x20, 0x47, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x62, 0x6f, 0x78, + 0x20, 0x69, 0x64, 0x73, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, + 0xab, 0x01, 0x06, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0xab, + 0x01, 0x12, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x03, 0x12, 0x04, 0xab, 0x01, + 0x2f, 0x42, 0x0a, 0x0f, 0x0a, 0x05, 0x06, 0x00, 0x02, 0x03, 0x04, 0x12, 0x06, 0xac, 0x01, 0x04, + 0xaf, 0x01, 0x06, 0x0a, 0x13, 0x0a, 0x09, 0x06, 0x00, 0x02, 0x03, 0x04, 0xb0, 0xca, 0xbc, 0x22, + 0x12, 0x06, 0xac, 0x01, 0x04, 0xaf, 0x01, 0x06, 0x0a, 0x12, 0x0a, 0x0a, 0x06, 0x00, 0x02, 0x03, + 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x04, 0x12, 0x04, 0xad, 0x01, 0x06, 0x23, 0x0a, 0x12, 0x0a, 0x0a, + 0x06, 0x00, 0x02, 0x03, 0x04, 0xb0, 0xca, 0xbc, 0x22, 0x07, 0x12, 0x04, 0xae, 0x01, 0x06, 0x0f, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, ]; include!("xmtp.xmtpv4.serde.rs"); include!("xmtp.xmtpv4.tonic.rs"); diff --git a/xmtp_proto/src/gen/xmtp.xmtpv4.serde.rs b/xmtp_proto/src/gen/xmtp.xmtpv4.serde.rs index 59ddc3e60..de9f87e49 100644 --- a/xmtp_proto/src/gen/xmtp.xmtpv4.serde.rs +++ b/xmtp_proto/src/gen/xmtp.xmtpv4.serde.rs @@ -13,7 +13,7 @@ impl serde::Serialize for AuthenticatedData { if !self.target_topic.is_empty() { len += 1; } - if !self.last_originator_sids.is_empty() { + if self.last_seen.is_some() { len += 1; } let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.AuthenticatedData", len)?; @@ -25,8 +25,8 @@ impl serde::Serialize for AuthenticatedData { #[allow(clippy::needless_borrows_for_generic_args)] struct_ser.serialize_field("targetTopic", pbjson::private::base64::encode(&self.target_topic).as_str())?; } - if !self.last_originator_sids.is_empty() { - struct_ser.serialize_field("lastOriginatorSids", &self.last_originator_sids.iter().map(ToString::to_string).collect::>())?; + if let Some(v) = self.last_seen.as_ref() { + struct_ser.serialize_field("lastSeen", v)?; } struct_ser.end() } @@ -42,15 +42,15 @@ impl<'de> serde::Deserialize<'de> for AuthenticatedData { "targetOriginator", "target_topic", "targetTopic", - "last_originator_sids", - "lastOriginatorSids", + "last_seen", + "lastSeen", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { TargetOriginator, TargetTopic, - LastOriginatorSids, + LastSeen, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -74,7 +74,7 @@ impl<'de> serde::Deserialize<'de> for AuthenticatedData { match value { "targetOriginator" | "target_originator" => Ok(GeneratedField::TargetOriginator), "targetTopic" | "target_topic" => Ok(GeneratedField::TargetTopic), - "lastOriginatorSids" | "last_originator_sids" => Ok(GeneratedField::LastOriginatorSids), + "lastSeen" | "last_seen" => Ok(GeneratedField::LastSeen), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -96,7 +96,7 @@ impl<'de> serde::Deserialize<'de> for AuthenticatedData { { let mut target_originator__ = None; let mut target_topic__ = None; - let mut last_originator_sids__ = None; + let mut last_seen__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::TargetOriginator => { @@ -115,21 +115,18 @@ impl<'de> serde::Deserialize<'de> for AuthenticatedData { Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) ; } - GeneratedField::LastOriginatorSids => { - if last_originator_sids__.is_some() { - return Err(serde::de::Error::duplicate_field("lastOriginatorSids")); + GeneratedField::LastSeen => { + if last_seen__.is_some() { + return Err(serde::de::Error::duplicate_field("lastSeen")); } - last_originator_sids__ = - Some(map_.next_value::>>()? - .into_iter().map(|x| x.0).collect()) - ; + last_seen__ = map_.next_value()?; } } } Ok(AuthenticatedData { target_originator: target_originator__.unwrap_or_default(), target_topic: target_topic__.unwrap_or_default(), - last_originator_sids: last_originator_sids__.unwrap_or_default(), + last_seen: last_seen__, }) } } @@ -420,7 +417,7 @@ impl serde::Serialize for BlockchainProof { if self.block_number != 0 { len += 1; } - if self.publisher_id != 0 { + if self.publisher_node_id != 0 { len += 1; } let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.BlockchainProof", len)?; @@ -429,8 +426,8 @@ impl serde::Serialize for BlockchainProof { #[allow(clippy::needless_borrows_for_generic_args)] struct_ser.serialize_field("blockNumber", ToString::to_string(&self.block_number).as_str())?; } - if self.publisher_id != 0 { - struct_ser.serialize_field("publisherId", &self.publisher_id)?; + if self.publisher_node_id != 0 { + struct_ser.serialize_field("publisherNodeId", &self.publisher_node_id)?; } struct_ser.end() } @@ -444,14 +441,14 @@ impl<'de> serde::Deserialize<'de> for BlockchainProof { const FIELDS: &[&str] = &[ "block_number", "blockNumber", - "publisher_id", - "publisherId", + "publisher_node_id", + "publisherNodeId", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { BlockNumber, - PublisherId, + PublisherNodeId, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -474,7 +471,7 @@ impl<'de> serde::Deserialize<'de> for BlockchainProof { { match value { "blockNumber" | "block_number" => Ok(GeneratedField::BlockNumber), - "publisherId" | "publisher_id" => Ok(GeneratedField::PublisherId), + "publisherNodeId" | "publisher_node_id" => Ok(GeneratedField::PublisherNodeId), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -495,7 +492,7 @@ impl<'de> serde::Deserialize<'de> for BlockchainProof { V: serde::de::MapAccess<'de>, { let mut block_number__ = None; - let mut publisher_id__ = None; + let mut publisher_node_id__ = None; while let Some(k) = map_.next_key()? { match k { GeneratedField::BlockNumber => { @@ -506,11 +503,11 @@ impl<'de> serde::Deserialize<'de> for BlockchainProof { Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) ; } - GeneratedField::PublisherId => { - if publisher_id__.is_some() { - return Err(serde::de::Error::duplicate_field("publisherId")); + GeneratedField::PublisherNodeId => { + if publisher_node_id__.is_some() { + return Err(serde::de::Error::duplicate_field("publisherNodeId")); } - publisher_id__ = + publisher_node_id__ = Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) ; } @@ -518,7 +515,7 @@ impl<'de> serde::Deserialize<'de> for BlockchainProof { } Ok(BlockchainProof { block_number: block_number__.unwrap_or_default(), - publisher_id: publisher_id__.unwrap_or_default(), + publisher_node_id: publisher_node_id__.unwrap_or_default(), }) } } @@ -703,13 +700,16 @@ impl serde::Serialize for EnvelopesQuery { { use serde::ser::SerializeStruct; let mut len = 0; - if self.filter.is_some() { + if self.last_seen.is_some() { len += 1; } - if self.last_seen.is_some() { + if self.filter.is_some() { len += 1; } let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.EnvelopesQuery", len)?; + if let Some(v) = self.last_seen.as_ref() { + struct_ser.serialize_field("lastSeen", v)?; + } if let Some(v) = self.filter.as_ref() { match v { envelopes_query::Filter::Topic(v) => { @@ -717,22 +717,8 @@ impl serde::Serialize for EnvelopesQuery { #[allow(clippy::needless_borrows_for_generic_args)] struct_ser.serialize_field("topic", pbjson::private::base64::encode(&v).as_str())?; } - envelopes_query::Filter::OriginatorId(v) => { - struct_ser.serialize_field("originatorId", v)?; - } - } - } - if let Some(v) = self.last_seen.as_ref() { - match v { - envelopes_query::LastSeen::OriginatorSid(v) => { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("originatorSid", ToString::to_string(&v).as_str())?; - } - envelopes_query::LastSeen::GatewaySid(v) => { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("gatewaySid", ToString::to_string(&v).as_str())?; + envelopes_query::Filter::OriginatorNodeId(v) => { + struct_ser.serialize_field("originatorNodeId", v)?; } } } @@ -746,21 +732,18 @@ impl<'de> serde::Deserialize<'de> for EnvelopesQuery { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ + "last_seen", + "lastSeen", "topic", - "originator_id", - "originatorId", - "originator_sid", - "originatorSid", - "gateway_sid", - "gatewaySid", + "originator_node_id", + "originatorNodeId", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { + LastSeen, Topic, - OriginatorId, - OriginatorSid, - GatewaySid, + OriginatorNodeId, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -782,10 +765,9 @@ impl<'de> serde::Deserialize<'de> for EnvelopesQuery { E: serde::de::Error, { match value { + "lastSeen" | "last_seen" => Ok(GeneratedField::LastSeen), "topic" => Ok(GeneratedField::Topic), - "originatorId" | "originator_id" => Ok(GeneratedField::OriginatorId), - "originatorSid" | "originator_sid" => Ok(GeneratedField::OriginatorSid), - "gatewaySid" | "gateway_sid" => Ok(GeneratedField::GatewaySid), + "originatorNodeId" | "originator_node_id" => Ok(GeneratedField::OriginatorNodeId), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -805,46 +787,222 @@ impl<'de> serde::Deserialize<'de> for EnvelopesQuery { where V: serde::de::MapAccess<'de>, { - let mut filter__ = None; let mut last_seen__ = None; + let mut filter__ = None; while let Some(k) = map_.next_key()? { match k { + GeneratedField::LastSeen => { + if last_seen__.is_some() { + return Err(serde::de::Error::duplicate_field("lastSeen")); + } + last_seen__ = map_.next_value()?; + } GeneratedField::Topic => { if filter__.is_some() { return Err(serde::de::Error::duplicate_field("topic")); } filter__ = map_.next_value::<::std::option::Option<::pbjson::private::BytesDeserialize<_>>>()?.map(|x| envelopes_query::Filter::Topic(x.0)); } - GeneratedField::OriginatorId => { + GeneratedField::OriginatorNodeId => { if filter__.is_some() { - return Err(serde::de::Error::duplicate_field("originatorId")); + return Err(serde::de::Error::duplicate_field("originatorNodeId")); } - filter__ = map_.next_value::<::std::option::Option<::pbjson::private::NumberDeserialize<_>>>()?.map(|x| envelopes_query::Filter::OriginatorId(x.0)); + filter__ = map_.next_value::<::std::option::Option<::pbjson::private::NumberDeserialize<_>>>()?.map(|x| envelopes_query::Filter::OriginatorNodeId(x.0)); } - GeneratedField::OriginatorSid => { - if last_seen__.is_some() { - return Err(serde::de::Error::duplicate_field("originatorSid")); + } + } + Ok(EnvelopesQuery { + last_seen: last_seen__, + filter: filter__, + }) + } + } + deserializer.deserialize_struct("xmtp.xmtpv4.EnvelopesQuery", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for GetInboxIdsRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.requests.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.GetInboxIdsRequest", len)?; + if !self.requests.is_empty() { + struct_ser.serialize_field("requests", &self.requests)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for GetInboxIdsRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "requests", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Requests, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "requests" => Ok(GeneratedField::Requests), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GetInboxIdsRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.xmtpv4.GetInboxIdsRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut requests__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Requests => { + if requests__.is_some() { + return Err(serde::de::Error::duplicate_field("requests")); } - last_seen__ = map_.next_value::<::std::option::Option<::pbjson::private::NumberDeserialize<_>>>()?.map(|x| envelopes_query::LastSeen::OriginatorSid(x.0)); + requests__ = Some(map_.next_value()?); } - GeneratedField::GatewaySid => { - if last_seen__.is_some() { - return Err(serde::de::Error::duplicate_field("gatewaySid")); + } + } + Ok(GetInboxIdsRequest { + requests: requests__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.xmtpv4.GetInboxIdsRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for get_inbox_ids_request::Request { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.address.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.GetInboxIdsRequest.Request", len)?; + if !self.address.is_empty() { + struct_ser.serialize_field("address", &self.address)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for get_inbox_ids_request::Request { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "address", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Address, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "address" => Ok(GeneratedField::Address), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = get_inbox_ids_request::Request; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.xmtpv4.GetInboxIdsRequest.Request") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut address__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Address => { + if address__.is_some() { + return Err(serde::de::Error::duplicate_field("address")); } - last_seen__ = map_.next_value::<::std::option::Option<::pbjson::private::NumberDeserialize<_>>>()?.map(|x| envelopes_query::LastSeen::GatewaySid(x.0)); + address__ = Some(map_.next_value()?); } } } - Ok(EnvelopesQuery { - filter: filter__, - last_seen: last_seen__, + Ok(get_inbox_ids_request::Request { + address: address__.unwrap_or_default(), }) } } - deserializer.deserialize_struct("xmtp.xmtpv4.EnvelopesQuery", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("xmtp.xmtpv4.GetInboxIdsRequest.Request", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for GatewayEnvelope { +impl serde::Serialize for GetInboxIdsResponse { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result where @@ -852,41 +1010,129 @@ impl serde::Serialize for GatewayEnvelope { { use serde::ser::SerializeStruct; let mut len = 0; - if self.gateway_sid != 0 { + if !self.responses.is_empty() { len += 1; } - if self.originator_envelope.is_some() { + let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.GetInboxIdsResponse", len)?; + if !self.responses.is_empty() { + struct_ser.serialize_field("responses", &self.responses)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for GetInboxIdsResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "responses", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Responses, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "responses" => Ok(GeneratedField::Responses), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GetInboxIdsResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.xmtpv4.GetInboxIdsResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut responses__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Responses => { + if responses__.is_some() { + return Err(serde::de::Error::duplicate_field("responses")); + } + responses__ = Some(map_.next_value()?); + } + } + } + Ok(GetInboxIdsResponse { + responses: responses__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.xmtpv4.GetInboxIdsResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for get_inbox_ids_response::Response { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.address.is_empty() { len += 1; } - let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.GatewayEnvelope", len)?; - if self.gateway_sid != 0 { - #[allow(clippy::needless_borrow)] - #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("gatewaySid", ToString::to_string(&self.gateway_sid).as_str())?; + if self.inbox_id.is_some() { + len += 1; } - if let Some(v) = self.originator_envelope.as_ref() { - struct_ser.serialize_field("originatorEnvelope", v)?; + let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.GetInboxIdsResponse.Response", len)?; + if !self.address.is_empty() { + struct_ser.serialize_field("address", &self.address)?; + } + if let Some(v) = self.inbox_id.as_ref() { + struct_ser.serialize_field("inboxId", v)?; } struct_ser.end() } } -impl<'de> serde::Deserialize<'de> for GatewayEnvelope { +impl<'de> serde::Deserialize<'de> for get_inbox_ids_response::Response { #[allow(deprecated)] fn deserialize(deserializer: D) -> std::result::Result where D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "gateway_sid", - "gatewaySid", - "originator_envelope", - "originatorEnvelope", + "address", + "inbox_id", + "inboxId", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - GatewaySid, - OriginatorEnvelope, + Address, + InboxId, } impl<'de> serde::Deserialize<'de> for GeneratedField { fn deserialize(deserializer: D) -> std::result::Result @@ -908,8 +1154,8 @@ impl<'de> serde::Deserialize<'de> for GatewayEnvelope { E: serde::de::Error, { match value { - "gatewaySid" | "gateway_sid" => Ok(GeneratedField::GatewaySid), - "originatorEnvelope" | "originator_envelope" => Ok(GeneratedField::OriginatorEnvelope), + "address" => Ok(GeneratedField::Address), + "inboxId" | "inbox_id" => Ok(GeneratedField::InboxId), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } } @@ -919,43 +1165,41 @@ impl<'de> serde::Deserialize<'de> for GatewayEnvelope { } struct GeneratedVisitor; impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GatewayEnvelope; + type Value = get_inbox_ids_response::Response; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct xmtp.xmtpv4.GatewayEnvelope") + formatter.write_str("struct xmtp.xmtpv4.GetInboxIdsResponse.Response") } - fn visit_map(self, mut map_: V) -> std::result::Result + fn visit_map(self, mut map_: V) -> std::result::Result where V: serde::de::MapAccess<'de>, { - let mut gateway_sid__ = None; - let mut originator_envelope__ = None; + let mut address__ = None; + let mut inbox_id__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::GatewaySid => { - if gateway_sid__.is_some() { - return Err(serde::de::Error::duplicate_field("gatewaySid")); + GeneratedField::Address => { + if address__.is_some() { + return Err(serde::de::Error::duplicate_field("address")); } - gateway_sid__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; + address__ = Some(map_.next_value()?); } - GeneratedField::OriginatorEnvelope => { - if originator_envelope__.is_some() { - return Err(serde::de::Error::duplicate_field("originatorEnvelope")); + GeneratedField::InboxId => { + if inbox_id__.is_some() { + return Err(serde::de::Error::duplicate_field("inboxId")); } - originator_envelope__ = map_.next_value()?; + inbox_id__ = map_.next_value()?; } } } - Ok(GatewayEnvelope { - gateway_sid: gateway_sid__.unwrap_or_default(), - originator_envelope: originator_envelope__, + Ok(get_inbox_ids_response::Response { + address: address__.unwrap_or_default(), + inbox_id: inbox_id__, }) } } - deserializer.deserialize_struct("xmtp.xmtpv4.GatewayEnvelope", FIELDS, GeneratedVisitor) + deserializer.deserialize_struct("xmtp.xmtpv4.GetInboxIdsResponse.Response", FIELDS, GeneratedVisitor) } } impl serde::Serialize for Misbehavior { @@ -1788,7 +2032,10 @@ impl serde::Serialize for UnsignedOriginatorEnvelope { { use serde::ser::SerializeStruct; let mut len = 0; - if self.originator_sid != 0 { + if self.originator_node_id != 0 { + len += 1; + } + if self.originator_sequence_id != 0 { len += 1; } if self.originator_ns != 0 { @@ -1798,10 +2045,13 @@ impl serde::Serialize for UnsignedOriginatorEnvelope { len += 1; } let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.UnsignedOriginatorEnvelope", len)?; - if self.originator_sid != 0 { + if self.originator_node_id != 0 { + struct_ser.serialize_field("originatorNodeId", &self.originator_node_id)?; + } + if self.originator_sequence_id != 0 { #[allow(clippy::needless_borrow)] #[allow(clippy::needless_borrows_for_generic_args)] - struct_ser.serialize_field("originatorSid", ToString::to_string(&self.originator_sid).as_str())?; + struct_ser.serialize_field("originatorSequenceId", ToString::to_string(&self.originator_sequence_id).as_str())?; } if self.originator_ns != 0 { #[allow(clippy::needless_borrow)] @@ -1821,8 +2071,10 @@ impl<'de> serde::Deserialize<'de> for UnsignedOriginatorEnvelope { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "originator_sid", - "originatorSid", + "originator_node_id", + "originatorNodeId", + "originator_sequence_id", + "originatorSequenceId", "originator_ns", "originatorNs", "payer_envelope", @@ -1831,7 +2083,8 @@ impl<'de> serde::Deserialize<'de> for UnsignedOriginatorEnvelope { #[allow(clippy::enum_variant_names)] enum GeneratedField { - OriginatorSid, + OriginatorNodeId, + OriginatorSequenceId, OriginatorNs, PayerEnvelope, } @@ -1855,7 +2108,8 @@ impl<'de> serde::Deserialize<'de> for UnsignedOriginatorEnvelope { E: serde::de::Error, { match value { - "originatorSid" | "originator_sid" => Ok(GeneratedField::OriginatorSid), + "originatorNodeId" | "originator_node_id" => Ok(GeneratedField::OriginatorNodeId), + "originatorSequenceId" | "originator_sequence_id" => Ok(GeneratedField::OriginatorSequenceId), "originatorNs" | "originator_ns" => Ok(GeneratedField::OriginatorNs), "payerEnvelope" | "payer_envelope" => Ok(GeneratedField::PayerEnvelope), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -1877,16 +2131,25 @@ impl<'de> serde::Deserialize<'de> for UnsignedOriginatorEnvelope { where V: serde::de::MapAccess<'de>, { - let mut originator_sid__ = None; + let mut originator_node_id__ = None; + let mut originator_sequence_id__ = None; let mut originator_ns__ = None; let mut payer_envelope__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::OriginatorSid => { - if originator_sid__.is_some() { - return Err(serde::de::Error::duplicate_field("originatorSid")); + GeneratedField::OriginatorNodeId => { + if originator_node_id__.is_some() { + return Err(serde::de::Error::duplicate_field("originatorNodeId")); + } + originator_node_id__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::OriginatorSequenceId => { + if originator_sequence_id__.is_some() { + return Err(serde::de::Error::duplicate_field("originatorSequenceId")); } - originator_sid__ = + originator_sequence_id__ = Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) ; } @@ -1907,7 +2170,8 @@ impl<'de> serde::Deserialize<'de> for UnsignedOriginatorEnvelope { } } Ok(UnsignedOriginatorEnvelope { - originator_sid: originator_sid__.unwrap_or_default(), + originator_node_id: originator_node_id__.unwrap_or_default(), + originator_sequence_id: originator_sequence_id__.unwrap_or_default(), originator_ns: originator_ns__.unwrap_or_default(), payer_envelope: payer_envelope__, }) @@ -1916,3 +2180,100 @@ impl<'de> serde::Deserialize<'de> for UnsignedOriginatorEnvelope { deserializer.deserialize_struct("xmtp.xmtpv4.UnsignedOriginatorEnvelope", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for VectorClock { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.node_id_to_sequence_id.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.xmtpv4.VectorClock", len)?; + if !self.node_id_to_sequence_id.is_empty() { + let v: std::collections::HashMap<_, _> = self.node_id_to_sequence_id.iter() + .map(|(k, v)| (k, v.to_string())).collect(); + struct_ser.serialize_field("nodeIdToSequenceId", &v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for VectorClock { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "node_id_to_sequence_id", + "nodeIdToSequenceId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + NodeIdToSequenceId, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "nodeIdToSequenceId" | "node_id_to_sequence_id" => Ok(GeneratedField::NodeIdToSequenceId), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = VectorClock; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.xmtpv4.VectorClock") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut node_id_to_sequence_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::NodeIdToSequenceId => { + if node_id_to_sequence_id__.is_some() { + return Err(serde::de::Error::duplicate_field("nodeIdToSequenceId")); + } + node_id_to_sequence_id__ = Some( + map_.next_value::, ::pbjson::private::NumberDeserialize>>()? + .into_iter().map(|(k,v)| (k.0, v.0)).collect() + ); + } + } + } + Ok(VectorClock { + node_id_to_sequence_id: node_id_to_sequence_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.xmtpv4.VectorClock", FIELDS, GeneratedVisitor) + } +} diff --git a/xmtp_proto/src/gen/xmtp.xmtpv4.tonic.rs b/xmtp_proto/src/gen/xmtp.xmtpv4.tonic.rs index 3f775e2e1..d88291dba 100644 --- a/xmtp_proto/src/gen/xmtp.xmtpv4.tonic.rs +++ b/xmtp_proto/src/gen/xmtp.xmtpv4.tonic.rs @@ -177,6 +177,33 @@ pub mod replication_api_client { ); self.inner.unary(req, path, codec).await } + /** Get inbox ids +*/ + pub async fn get_inbox_ids( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/xmtp.xmtpv4.ReplicationApi/GetInboxIds", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("xmtp.xmtpv4.ReplicationApi", "GetInboxIds")); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -223,6 +250,15 @@ pub mod replication_api_server { tonic::Response, tonic::Status, >; + /** Get inbox ids +*/ + async fn get_inbox_ids( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; } /** Replication API */ @@ -447,6 +483,51 @@ pub mod replication_api_server { }; Box::pin(fut) } + "/xmtp.xmtpv4.ReplicationApi/GetInboxIds" => { + #[allow(non_camel_case_types)] + struct GetInboxIdsSvc(pub Arc); + impl< + T: ReplicationApi, + > tonic::server::UnaryService + for GetInboxIdsSvc { + type Response = super::GetInboxIdsResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_inbox_ids(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetInboxIdsSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { Ok( diff --git a/xmtp_user_preferences/Cargo.toml b/xmtp_user_preferences/Cargo.toml index 11f887f8d..7f7ba0f27 100644 --- a/xmtp_user_preferences/Cargo.toml +++ b/xmtp_user_preferences/Cargo.toml @@ -4,9 +4,8 @@ name = "xmtp_user_preferences" version.workspace = true [dependencies] -base64 = "0.21.4" +base64 = "0.22.1" # Need to include this as a dep or compile will fail because of a version mismatch -once_cell = "1.18.0" prost = { workspace = true, features = ["prost-derive"] } xmtp_proto = { path = "../xmtp_proto", features = ["xmtp-message_contents"] } xmtp_v2 = { path = "../xmtp_v2" }