From bdceeed116036f9f0c1b213f7c41b5cf5d30c6be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 13:09:12 +0200 Subject: [PATCH 01/32] feat(cvm-deployment): optional PRELAUNCH_SCRIPT for test-asset collection The MPC node generates its NEAR signer key inside the enclave and writes it only to the CVM's encrypted disk. Collecting test assets needs that key alongside the quote it is bound to, and an app-compose pre-launch script is the only way in: the dev image ships no sshd and the guest agent serves only node info and container logs. vmm-cli already supports --prelaunch-script; this just plumbs an optional PRELAUNCH_SCRIPT through. Attestation verification rejects any app-compose carrying a script, so a CVM deployed this way cannot join a network - the deploy guide, default.env and the script itself now say so loudly. --- deployment/cvm-deployment/default.env | 6 ++ .../cvm-deployment/deploy-launcher-guide.md | 8 +++ deployment/cvm-deployment/deploy-launcher.sh | 18 ++++++ localnet/tee/scripts/rust-launcher/README.md | 61 ++++++++++++++++++- .../rust-launcher/single-node-readme.md | 7 +++ .../tee/scripts/rust-launcher/single-node.sh | 5 ++ 6 files changed, 103 insertions(+), 2 deletions(-) diff --git a/deployment/cvm-deployment/default.env b/deployment/cvm-deployment/default.env index da6d2bd16e..794053fd95 100644 --- a/deployment/cvm-deployment/default.env +++ b/deployment/cvm-deployment/default.env @@ -69,5 +69,11 @@ OS_IMAGE=dstack-dev-0.5.8 # Path of the user_config file USER_CONFIG_FILE_PATH=user-config.toml +# Leave unset. A pre-launch script runs as root inside the CVM, and attestation +# verification rejects any app-compose carrying one, so the CVM cannot join the +# network. Only fixture collection sets this; see +# localnet/tee/scripts/rust-launcher/README.md +#PRELAUNCH_SCRIPT= + # for testing use a smaller disk size 128G DISK=1000G diff --git a/deployment/cvm-deployment/deploy-launcher-guide.md b/deployment/cvm-deployment/deploy-launcher-guide.md index 7599408472..5e2da46351 100644 --- a/deployment/cvm-deployment/deploy-launcher-guide.md +++ b/deployment/cvm-deployment/deploy-launcher-guide.md @@ -162,6 +162,14 @@ USER_CONFIG_FILE_PATH=user-config.toml DISK=1000G ``` +> **Never set `PRELAUNCH_SCRIPT` for a real deployment.** It bakes a script into +> the app-compose that runs as root inside the CVM before the node starts. +> Attestation verification rejects any app-compose carrying one, so such a CVM +> can never join the network; it exists only to collect test fixtures (see +> `localnet/tee/scripts/rust-launcher/README.md`). The `.env` file is sourced +> under `set -a`, so a leftover line takes effect silently — `deploy-launcher.sh` +> prints a warning when it finds one. + --- Based on: [Original Dstack deploy script](https://github.com/Dstack-TEE/dstack/blob/be9d0476a63e937eda4c13659547a25088393394/kms/dstack-app/deploy-to-vmm.sh) diff --git a/deployment/cvm-deployment/deploy-launcher.sh b/deployment/cvm-deployment/deploy-launcher.sh index d1a8bc76bb..ed2f7244cc 100755 --- a/deployment/cvm-deployment/deploy-launcher.sh +++ b/deployment/cvm-deployment/deploy-launcher.sh @@ -262,6 +262,23 @@ case $SEALING_KEY_TYPE in esac +# Optional pre-launch script baked into the app-compose, executed inside the +# CVM before docker compose up. It is the only way to run anything of our own +# in a CVM, which test-asset collection needs to export the node's in-enclave +# signer key. Attestation verification rejects an app-compose carrying one, so +# never set this outside fixture collection. +PRELAUNCH_ARGS=() +if [ -n "${PRELAUNCH_SCRIPT:-}" ]; then + if [ ! -f "$PRELAUNCH_SCRIPT" ]; then + echo "Error: PRELAUNCH_SCRIPT '$PRELAUNCH_SCRIPT' does not exist" + exit 1 + fi + echo "WARNING: baking pre-launch script '$PRELAUNCH_SCRIPT' into the app-compose." + echo " Attestation verification rejects any app-compose carrying a script," + echo " so this CVM will FAIL attestation. Use only for fixture collection." + PRELAUNCH_ARGS=(--prelaunch-script "$PRELAUNCH_SCRIPT") +fi + echo -e "\nCreating app-compose.json..." $CLI compose \ --docker-compose "$COMPOSE_TMP" \ @@ -270,6 +287,7 @@ $CLI compose \ --public-logs \ --public-sysinfo \ --no-instance-id \ + "${PRELAUNCH_ARGS[@]}" \ --output .app-compose.json echo "app-compose.json" diff --git a/localnet/tee/scripts/rust-launcher/README.md b/localnet/tee/scripts/rust-launcher/README.md index ebda4f53d4..f15374299e 100644 --- a/localnet/tee/scripts/rust-launcher/README.md +++ b/localnet/tee/scripts/rust-launcher/README.md @@ -35,14 +35,71 @@ The node env template `../node.env.tpl` also lives here (one level up) and is sh To regenerate test assets from real TDX attestation: ```bash -# Deploy single node -bash localnet/tee/scripts/rust-launcher/single-node.sh +# Deploy single node. PRELAUNCH_SCRIPT is what makes the node's signer secret +# key recoverable; see below. +PRELAUNCH_SCRIPT=/path/to/prelaunch.sh bash localnet/tee/scripts/rust-launcher/single-node.sh # Extract assets cp /public_data.json crates/test-utils/assets/public_data.json cd crates/test-utils/assets && bash ./create-assets.sh public_data.json . cp crates/test-utils/assets/tcb_info.json crates/attestation/assets/tcb_info.json # Update VALID_ATTESTATION_TIMESTAMP in crates/test-utils/src/attestation.rs +# Regenerate the verifier's borsh arg fixture and the expected report: +UPDATE_FIXTURES=1 cargo test -p tee-verifier --test verify_quote verify_quote_args_fixture +cargo test -p tee-verifier --test verify_quote # update the hardcoded report values it prints ``` +### Exporting the node's signer key + +Sandbox tests that store a Verified attestation must sign as the fixture node, +because the quote's `report_data` binds the node's account key and the contract +reads that key from the transaction signer. That key is generated inside the +CVM, so it has to be exported during collection or the fixture is unusable for +those tests (this is what issue #3787 was about). + +`PRELAUNCH_SCRIPT` points at a script baked into the app-compose and run inside +the CVM before the node starts. Notes from making this work: + +- The guest is BusyBox: stick to shell built-ins and globs. GNU-only options + such as `head -1` fail, and there is no `sshd`, no `/root`, and no + `/usr/local/bin`. +- `/etc` (overlay) and `/dstack/.host-shared` are writable; `/` is not. +- The node writes `secrets.json` only after the hook returns, so the wait must + run as its own systemd unit. A plain background process is reaped with + `app-compose.service`'s cgroup. +- Anything echoed to `/dev/console` lands in the host's + `run/vm//serial.log`, which is the simplest way to read a value out. + +A hook that copies the key to the host-visible shared dir: + +```sh +cat > /etc/fixture-exfil.sh <<'EOF' +#!/bin/sh +i=0 +while [ "$i" -lt 900 ]; do + for f in /var/lib/docker/volumes/*/_data/secrets.json; do + [ -f "$f" ] && { cp "$f" /dstack/.host-shared/fixture-secrets.json; exit 0; } + done + i=$((i + 1)); sleep 2 +done +EOF +cat > /etc/systemd/system/fixture-exfil.service <<'EOF' +[Unit] +Description=Export the MPC node signer key for test-asset collection +[Service] +Type=oneshot +ExecStart=/bin/sh /etc/fixture-exfil.sh +EOF +systemctl daemon-reload && systemctl start --no-block fixture-exfil.service +``` + +Then put `near_signer_key` from that file into +`crates/test-utils/assets/near_account_secret_key` (one line, `ed25519:`) +and check that its public half equals `near_account_public_key.pub`. Only ever do +this for a throwaway localnet node: the key ends up in the repo. + +The hook is measured into the app-compose, and production verification rejects any +app-compose carrying a script. Test builds accept this one field via +`attestation/allow-pre-launch-script`, so keep the hook to what the export needs. + See [single-node-readme.md](single-node-readme.md) for details. diff --git a/localnet/tee/scripts/rust-launcher/single-node-readme.md b/localnet/tee/scripts/rust-launcher/single-node-readme.md index b460fea5f8..8ca21aba2a 100644 --- a/localnet/tee/scripts/rust-launcher/single-node-readme.md +++ b/localnet/tee/scripts/rust-launcher/single-node-readme.md @@ -44,6 +44,13 @@ export OS_IMAGE=dstack-0.5.8 # Custom NEAR accounts export NODE_ACCOUNT=frodo.test.near export CONTRACT_ACCOUNT=mpc-contract.test.near + +# Script executed inside the CVM before docker compose up, and the only way to +# run anything of your own in there. Needed when collecting test assets, to +# export the node's in-enclave signer key; the dev image has no sshd, and the +# guest agent serves only node info and container logs. README.md in this +# directory has a working script. +export PRELAUNCH_SCRIPT=/path/to/prelaunch.sh ``` ## Run diff --git a/localnet/tee/scripts/rust-launcher/single-node.sh b/localnet/tee/scripts/rust-launcher/single-node.sh index e55bf29007..c9c3df0852 100644 --- a/localnet/tee/scripts/rust-launcher/single-node.sh +++ b/localnet/tee/scripts/rust-launcher/single-node.sh @@ -132,6 +132,11 @@ OS_IMAGE="${OS_IMAGE:-dstack-dev-0.5.8}" SEALING_KEY_TYPE="${SEALING_KEY_TYPE:-SGX}" DISK="${DISK:-500G}" +# Optional: path to a script baked into the app-compose and executed inside the +# CVM before docker compose up. Collecting test assets needs one, to export the +# node's in-enclave signer key; see the README. Consumed by deploy-launcher.sh. +export PRELAUNCH_SCRIPT="${PRELAUNCH_SCRIPT:-}" + # Paths REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}" TEE_LAUNCHER_DIR="$REPO_ROOT/deployment/cvm-deployment" From a695d7416be2d2c5d5ca82f74c63e0d46ab32ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 13:09:23 +0200 Subject: [PATCH 02/32] test(attestation): feature-gate the pre-launch-script rejection Collecting the attestation fixtures requires a pre-launch script to export the node's in-enclave signer key, which makes the resulting app-compose one that production verification rejects as arbitrary root code. The new allow-pre-launch-script feature relaxes exactly that field for test builds; init_script and bash_script stay rejected, and the production wasm never enables it. The check takes the policy as an argument so the strict behaviour keeps its unit test in test builds too, and a further test pins the compiled-in policy at the call site. --- crates/attestation/Cargo.toml | 6 +- crates/attestation/src/attestation.rs | 79 ++++++++++++++++++++++++--- crates/mpc-attestation/Cargo.toml | 2 + 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/crates/attestation/Cargo.toml b/crates/attestation/Cargo.toml index ee6931d59f..bf7fc3abc1 100644 --- a/crates/attestation/Cargo.toml +++ b/crates/attestation/Cargo.toml @@ -7,7 +7,11 @@ edition = { workspace = true } [features] borsh-schema = ["borsh/unstable__schema", "tee-verifier-interface/borsh-schema"] dstack-conversions = ["dep:dstack-sdk-types"] -test-utils = [] +test-utils = ["allow-pre-launch-script"] +# Accepts an app-compose carrying a `pre_launch_script`, which production rejects as +# arbitrary root code. The test fixture needs one: it is how the node's in-enclave signer +# key is exported during collection. `init_script` and `bash_script` stay rejected. +allow-pre-launch-script = [] # Pulls in `dcap-qvl` for full local DCAP + post-DCAP verification. Meant for # off-chain callers; `mpc-contract` enables it today. # TODO(#3264): contract drops this once DCAP moves to the verifier contract. diff --git a/crates/attestation/src/attestation.rs b/crates/attestation/src/attestation.rs index 44248bd620..6231736e7c 100644 --- a/crates/attestation/src/attestation.rs +++ b/crates/attestation/src/attestation.rs @@ -409,11 +409,19 @@ impl DstackAttestation { && app_compose.local_key_provider_enabled && app_compose.allowed_envs.is_empty() && app_compose.no_instance_id - // Reject all three arbitrary-root-code fields. `pre_launch_script` and `init_script` run - // unconditionally; `bash_script` only runs when `runner == "bash"` (so the runner pin - // above already neutralizes it), but we reject it explicitly so the guarantee does not - // silently depend on that pin. - && app_compose.pre_launch_script.is_none() + && Self::scripts_absent(app_compose) + } + + /// Rejects the arbitrary-root-code fields. `bash_script` only runs when + /// `runner == "bash"`, but is rejected explicitly so the guarantee does not depend on + /// the runner pin above. + fn scripts_absent(app_compose: &AppCompose) -> bool { + Self::scripts_absent_with(app_compose, cfg!(feature = "allow-pre-launch-script")) + } + + /// Takes the policy as an argument so tests can assert both, whatever features are on. + fn scripts_absent_with(app_compose: &AppCompose, allow_pre_launch_script: bool) -> bool { + (allow_pre_launch_script || app_compose.pre_launch_script.is_none()) && app_compose.init_script.is_none() && app_compose.bash_script.is_none() } @@ -620,19 +628,76 @@ mod tests { } #[test] - fn validate_app_compose_config__rejects_present_pre_launch_script() { + fn scripts_absent_with__should_reject_pre_launch_script_when_disallowed() { + // Asserts the production policy, which test builds relax for the fixture. + // Given let app_compose = AppCompose { pre_launch_script: Some("echo pwn".to_string()), ..valid_app_compose() }; // When - let result = DstackAttestation::validate_app_compose_config(&app_compose); + let result = DstackAttestation::scripts_absent_with(&app_compose, false); // Then assert!(!result) } + #[test] + fn validate_app_compose_config__should_follow_the_compiled_in_pre_launch_policy() { + // Covers the wired-in policy at the call site, which the tests below reach + // only through the helper. + + // Given + let app_compose = AppCompose { + pre_launch_script: Some("echo collecting fixtures".to_string()), + ..valid_app_compose() + }; + + // When + let result = DstackAttestation::validate_app_compose_config(&app_compose); + + // Then + assert_eq!(result, cfg!(feature = "allow-pre-launch-script")); + } + + #[test] + fn scripts_absent_with__should_accept_pre_launch_script_when_allowed() { + // Given + let app_compose = AppCompose { + pre_launch_script: Some("echo collecting fixtures".to_string()), + ..valid_app_compose() + }; + // When + let result = DstackAttestation::scripts_absent_with(&app_compose, true); + + // Then + assert!(result) + } + + #[test] + fn scripts_absent_with__should_reject_other_scripts_when_pre_launch_is_allowed() { + // The relaxation must stay scoped to `pre_launch_script`. + + // Given + let with_init = AppCompose { + init_script: Some("echo pwn".to_string()), + ..valid_app_compose() + }; + let with_bash = AppCompose { + bash_script: Some("echo pwn".to_string()), + ..valid_app_compose() + }; + + // When + let init_result = DstackAttestation::scripts_absent_with(&with_init, true); + let bash_result = DstackAttestation::scripts_absent_with(&with_bash, true); + + // Then + assert!(!init_result); + assert!(!bash_result); + } + #[test] fn validate_app_compose_config__rejects_present_init_script() { // `init_script` is arbitrary root code run before dockerd. It is diff --git a/crates/mpc-attestation/Cargo.toml b/crates/mpc-attestation/Cargo.toml index b0c32c17d2..d5af841b64 100644 --- a/crates/mpc-attestation/Cargo.toml +++ b/crates/mpc-attestation/Cargo.toml @@ -8,6 +8,8 @@ edition = { workspace = true } abi = ["borsh/unstable__schema", "mpc-primitives/abi", "attestation/borsh-schema"] dstack-conversions = ["attestation/dstack-conversions"] test-utils = ["attestation/test-utils"] +# Forwards `attestation/allow-pre-launch-script`; see that crate for the rationale. +allow-pre-launch-script = ["attestation/allow-pre-launch-script"] # Enables full local DCAP + post-DCAP verification, forwarding to # `attestation/local-verify` which pulls in `dcap-qvl`. Used off-chain (node, # tee-authority, attestation-cli) and, for now, by the contract's synchronous From 782e500555a434d8a0c22e766b0ee182bd72b252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 13:10:10 +0200 Subject: [PATCH 03/32] test(test-utils): regenerate attestation fixtures with a retained signer key Regenerated from a fresh localnet CVM on a TDX host, keeping the node's NEAR signer key this time so tests can sign submit_participant_info as the fixture node. The quote's report_data binds that key and the contract reads it from the transaction signer, so without it the Verified store path is unreachable (near/mpc#3787). create-assets.sh had been producing collateral our own parser cannot read since the tee-verifier-interface refactor: nodes serialize the DER and signature fields as JSON byte arrays while collateral_from_json expects hex strings. It now hex-encodes those fields, and strips the NUL that terminates the PEM chains so the fixture stays valid PEM. The regeneration reminder is unconditional, since the committed key is normally present but stale. .editorconfig no longer asserts the borsh fixture's final byte: it is whatever the encoded collateral ends with. --- .editorconfig | 4 +- crates/attestation/assets/tcb_info.json | 18 ++++---- .../tests/fixtures/verify_quote_args.borsh | Bin 19085 -> 22767 bytes crates/tee-verifier/tests/verify_quote.rs | 6 +-- crates/test-utils/assets/README.md | 43 +++++++++++++++++- crates/test-utils/assets/app_compose.json | 7 +-- crates/test-utils/assets/collateral.json | 11 +++-- crates/test-utils/assets/create-assets.sh | 34 +++++++++++++- .../assets/launcher_image_compose.yaml | 4 +- crates/test-utils/assets/mpc_image_digest.txt | 2 +- .../assets/near_account_public_key.pub | 2 +- .../test-utils/assets/near_account_secret_key | 1 + .../test-utils/assets/near_p2p_public_key.pub | 2 +- crates/test-utils/assets/public_data.json | 39 ++++++++-------- crates/test-utils/assets/quote.json | 2 +- crates/test-utils/assets/tcb_info.json | 18 ++++---- crates/test-utils/src/attestation.rs | 16 ++++++- docs/deploy-tee-verifier.md | 7 +-- docs/localnet/localnet.md | 11 +++-- 19 files changed, 158 insertions(+), 69 deletions(-) create mode 100644 crates/test-utils/assets/near_account_secret_key diff --git a/.editorconfig b/.editorconfig index 68f7277369..c02c04ed8b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -29,6 +29,8 @@ insert_final_newline = false # localnet verify_quote call; the text rules do not apply. [crates/tee-verifier/tests/fixtures/*.borsh] end_of_line = unset -insert_final_newline = false +# `unset`, not `false`: the last byte is whatever the encoded collateral ends +# with, so asserting either way breaks on the next fixture regeneration. +insert_final_newline = unset trim_trailing_whitespace = false charset = unset diff --git a/crates/attestation/assets/tcb_info.json b/crates/attestation/assets/tcb_info.json index f1c777e178..46da8f1ceb 100644 --- a/crates/attestation/assets/tcb_info.json +++ b/crates/attestation/assets/tcb_info.json @@ -3,11 +3,11 @@ "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "b7662ac19c27af648a939be042684bbdb43bb3dddf4cd17bb21f4d455ab1926c6ee57038152fc46ddea392c47eb2af27", + "rtmr3": "8050d4769527c84cb066078854ef8eb50ea7b150e072eeec7007240aca01b556041273ea3d20a1b1d48736f650ce13f0", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "cb9b2d6204f5e44238b75f69e3a3069550734c0d99ebdd3be507c238a261d8fa", + "compose_hash": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1774945636\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:1f54b55bad22c45067228a9262bc6377e393ca1a07edb64e691e80704f49b74e\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786102851\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\n# Test-asset collection hook, sourced by the CVM's app-compose.sh before the\\n# node starts. The node generates its NEAR signer key in-enclave, so exporting\\n# that key is the only way to check the fixture keypair into the repo next to\\n# the quote it is bound to (near/mpc #3787).\\n#\\n# The key appears only after the node starts, i.e. after this hook returns, so\\n# the wait runs as its own systemd unit: a plain background process would be\\n# reaped with app-compose.service's cgroup. The copy target is the CVM's\\n# host-shared dir, which the host sees as run/vm//shared/.\\n#\\n# The guest userland is BusyBox, so the wait loop sticks to shell built-ins and\\n# globs (no find/head, whose GNU options BusyBox rejects).\\n#\\n# Only ever use this on a throwaway localnet CVM: it exports a private key.\\n\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\nEXFIL=/etc/fixture-exfil.sh\\n\\ncat > \\\"$EXFIL\\\" <<'EOF'\\n#!/bin/sh\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\ni=0\\nwhile [ \\\"$i\\\" -lt 900 ]; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n if [ -f \\\"$f\\\" ]; then\\n cp \\\"$f\\\" \\\"$SHARED/fixture-secrets.json\\\" 2>/dev/null\\n {\\n echo \\\"FIXTURE-SECRETS-BEGIN $f\\\"\\n cat \\\"$f\\\"\\n echo \\\"\\\"\\n echo \\\"FIXTURE-SECRETS-END\\\"\\n } > \\\"$CONSOLE\\\" 2>&1\\n exit 0\\n fi\\n done\\n i=$((i + 1))\\n sleep 2\\ndone\\necho \\\"FIXTURE-SECRETS-TIMEOUT\\\" > \\\"$CONSOLE\\\" 2>&1\\nEOF\\nchmod +x \\\"$EXFIL\\\" 2>/dev/null\\n\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Unit]\\nDescription=Export the MPC node signer key for test-asset collection\\n[Service]\\nType=oneshot\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEOF\\n\\nsystemctl daemon-reload >/dev/null 2>&1\\nsystemctl start --no-block fixture-exfil.service >/dev/null 2>&1\\n\\n{\\n echo \\\"FIXTURE-DIAG-BEGIN\\\"\\n echo \\\"exfil_script=$([ -f \\\"$EXFIL\\\" ] && echo present || echo missing)\\\"\\n echo \\\"unit_state=$(systemctl is-active fixture-exfil.service 2>&1)\\\"\\n echo \\\"shared_writable=$([ -w \\\"$SHARED\\\" ] && echo yes || echo no)\\\"\\n echo \\\"FIXTURE-DIAG-END\\\"\\n} > \\\"$CONSOLE\\\" 2>&1\\n\"\n}", "event_log": [ { "imr": 0, @@ -159,16 +159,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "8f4219433b1fbb548e8e3c9c0a308a09888871da6b0472f8b2057d14846b33f66d674ebaa5829f26e9ffb3d2745eb5ce", + "digest": "970c96ea5f1ea46650645363f1716fd4e4260c92f614a6af308d4ca2e352b4dbd3d8f326e5a513c20b3029163284257e", "event": "app-id", - "event_payload": "cb9b2d6204f5e44238b75f69e3a3069550734c0d" + "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfaf" }, { "imr": 3, "event_type": 134217729, - "digest": "f53085ad730605df556bbe4617e942a89186705897eac8974656be41ddcc516a08c4d2b9135fbf8a0f25836c26e1c0d3", + "digest": "6d4e926546694d6e8acc53d46b216cde12d3a60cd3b60550ab7db7f4920fc42c304f8af924e08f96c108a7f7076cf02a", "event": "compose-hash", - "event_payload": "cb9b2d6204f5e44238b75f69e3a3069550734c0d99ebdd3be507c238a261d8fa" + "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a" }, { "imr": 3, @@ -208,9 +208,9 @@ { "imr": 3, "event_type": 134217729, - "digest": "9aed81f5b1af85f768ef6873ed6f997f55f37de951cca18f5daa35890ab9e5573314d2e0cd188a6913dd4ab6f5455678", + "digest": "0405a5706797115cdcccb66841205179fa5c2d989ad42fee2e2fab4c5b52bb6d9aa9bf8a86755d37e8566fdaabebc468", "event": "mpc-image-digest", - "event_payload": "6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980" + "event_payload": "564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3" } ] } diff --git a/crates/tee-verifier/tests/fixtures/verify_quote_args.borsh b/crates/tee-verifier/tests/fixtures/verify_quote_args.borsh index b8d5ff1005f28ea644ed69face0492e6a8a571b6..3302726634987c244592d373660c7f0b12e5095b 100644 GIT binary patch delta 1747 zcmeC3%J_aGg$I4@TXKz=xStN7S``NaI?UOa`uiv*d;M>&dCOJiYUa!f5jM)<> zuuQIDoKW8oaHVXj`U#&6Y3v;#@B6m$E#DaMpy=J30(KRyQ;b`~ScHmS*(xmDc%|L! zTfjNt4-AYK!}cDFi+=z7VPgG_{pXI|wU=GmP`3A3#)acHkGH90`E_zAm>pwCy#Md_ z%_-YfCwVZSfHMLN3@6-=RON=+GYee|GiB=iw6p8Uhrha6zt$fAD!^SJWT=)b%yQ6D z#dhDpk^qfJDSPoF65BE-#0Hlv*~mJVb6;HQ9b*c(Z=c9_rY!M` z92KnJ5Zbas$gaa}`tOR8kkGX2?9wluy^P4-bMf)a^FD`MYoj+G zW62WdkmhAzFlgcxpKKx1C2nD0ZeU>z-U7!_RU^lYBK^2k7ACLtE<@68+f@GuR&}^89EC5n*3|Ro=s6WU8AQgu4XlA6N z3(Q3qxQr|SGJ`__$qbNyExJGvy1;UDfjh_oAeRa$q8aLrE>MFk0MfDvUEl?>0LWpo zN=Sx+v;?CIbfOFFM;G{tEC4c8OBu;fkU%`Tz!YQwkhQ0f1wdNMY|+s`G880`ge(BEWjeCJ4h=s~4+aBQCPjvK z`Rsg#6JH&wR8A6oDjjp~z>YsWj0Xdy_wYr{e7qsNn@Pd(Jf9+0ty6jL59iA(zcKYs zPkXw$C}4x)?b*LA@0Bd$-pucq!9IDLfxfeau7P=ofrXWcrIm?!l#-58UTQ^2XhBM1 zNve{Sl97RtnXZAQu7MefnzY>Ff@GkylYz5=ncHLyLpw&x&FO|G7}-p94NP?nCkNU~ zP4+kbi^}ENTxKG|f-bhjLYl*YKla{(nVQuG^JY69IhVcb^|zgKmM{C#bg$p|#EGZV z`%bKV)%AYG&PhjBDK-?v%q!n1m-D)(;I)wqv-lMA9g!++K>y5SH-z}bz{=Rf%G46C zU!ZCx-}I0Jy8MTS3YyD#+#P^ry`{?ME9EwUvkID0mZ$fwu(nEa2~1kOGEePc)3sp7 z+(+ShYj-4Q$Jj1uIoMFYlSAfi7|Sgr)TRXv3z~vWU)Oy^YLP~sR6}4yfa_lwSLNe$YN3AjbD=m8M7x& zV3}OQIH7)fn%2QN>g!XwCeME0l;OR1i}mKa_kAu_Z<6wBW>gd*1nx^xr}|6xZ>smOve}BGXi z;YOxncDrL=t^2In^Ek$FrcOmf_s8|z_U$j(d!)>>DnOl-eczG zV=P(X98$at3w*qYJd63+zS~IH)2r`2(_mpqw7UK#**-9GVRikp)01jv)(x9Q6lT0HnfD9?gt& zbb-0(0+*2mKxS|#AejLYutgUrLKj$$E^r4~0OV33MKnX*(FJOd1wdLhp$oh~763U+ zRtd>akd|O{flhRR{pbQ;kp)18YAGWb3KED%7np)90J8QJvH(cSe`EoW3R4v%LqP)B z$O0fO3s41gQPT#ODw=)=WPwCgq@)BgeGRfKNZ=8&0LVIVH8cZ#kp)01n$QKdBMX2G zeTysr(xRk}WGF}=99^IXUEmkmTnvB2*c_wPW*ov2)Gz z4!bE6xnEsztO{zWI@FfFS->%aee!k#eP?4`V}lSw11l2)D+ALgB^{-_)QXbOf|SIP zR3$4VBLgEdT>}$cBTE!DX}QG($w28OgJc7PA~QL_ z_%AYtYje4Y2n(vnRtsqkhtLfNH$G)CdsV8jGq_|e-d5>^cfNzr-f?U!2gK{9@@g{}1Nz`X;NDfIgYYZV2&(p_QSTm9ZIKUqIDN zzU3hYbn{OS6%;q~xH`, matching the format of the `.pub` files). Sandbox tests sign + `submit_participant_info` with it, because the quote's `report_data` binds that key + and the contract reads it from the transaction signer. It is not part of + `public_data.json`: it lives in `secrets.json` inside the CVM and has to be + exported during collection, which is what the `PRELAUNCH_SCRIPT` in + [the rust-launcher README](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key) + is for. The fixture node is a throwaway localnet node, which is the only reason its + secret key may live in the repo: its account (`frodo.test.near`) exists on no + public network, and the quote and collateral that bind the key are public anyway. + Re-check that before committing a regenerated key. + + Because of that export hook, the fixture's app-compose carries a + `pre_launch_script`, which production verification rejects as arbitrary root code. + Test builds accept it via `attestation/allow-pre-launch-script` (and, for the + sandbox wasm, `mpc-contract/sandbox-test-attestation`). Keep the hook minimal, and + do not treat this fixture as an example of a production-valid attestation. + +6. Update `crates/attestation/assets/tcb_info.json` — copy the newly generated `tcb_info.json` there as well, since unit tests in the `attestation` crate use it for deserialization tests. This is optional — the tests only verify parsing, not measurement values — but keeping it in sync avoids confusion. -6. Update the compiled-in measurements in `crates/mpc-attestation/assets/`: +7. Update the compiled-in measurements in `crates/mpc-attestation/assets/`: - `tcb_info_dev.json` — replace with the `tcb_info.json` from a **dev** image attestation - `tcb_info.json` — replace with the `tcb_info.json` from a **release** (non-dev) image attestation @@ -71,6 +89,19 @@ All files will be written into the specified output directory. > will be managed entirely through on-chain voting (`vote_add_os_measurement`), and these > files will no longer need to be kept in sync with the deployed OS image. +8. Regenerate the verifier's borsh argument fixture and refresh the report values + the verifier test hardcodes (`mr_config_id`, `rt_mr3`, `report_data` change with + every new node): + + ```shell + UPDATE_FIXTURES=1 cargo test -p tee-verifier --test verify_quote verify_quote_args_fixture + cargo test -p tee-verifier --test verify_quote + ``` + + The second run fails on `verify_quote__should_return_verified_td10_report_for_valid_fixture` + and prints the values actually produced; copy them into + `crates/tee-verifier/tests/verify_quote.rs`. + ## Tests that depend on these assets After updating assets, these tests should pass: @@ -82,3 +113,11 @@ cargo test -p mpc-contract test_submit_participant_info_fails_without_approved_m cargo test -p mpc-contract test_verify_tee_triggers_resharing_and_kickout_on_expired_attestation cargo test -p test-utils ``` + +The cross-contract sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` +also depend on these assets (including `near_account_secret_key` for the tests that +sign as the fixture account): + +```shell +cargo nextest run --cargo-profile=test-release -p mpc-contract tee_verifier +``` diff --git a/crates/test-utils/assets/app_compose.json b/crates/test-utils/assets/app_compose.json index f1247684f1..15e014b9e8 100644 --- a/crates/test-utils/assets/app_compose.json +++ b/crates/test-utils/assets/app_compose.json @@ -1,8 +1,8 @@ { "manifest_version": 2, - "name": "mpc-localnet-one-node-1774945636", + "name": "mpc-localnet-one-node-1786102851", "runner": "docker-compose", - "docker_compose_file": "version: '3.8'\n\nservices:\n launcher:\n image: nearone/mpc-launcher@sha256:1f54b55bad22c45067228a9262bc6377e393ca1a07edb64e691e80704f49b74e\n\n container_name: launcher\n\n environment:\n - PLATFORM=TEE\n - DOCKER_CONTENT_TRUST=1\n - DEFAULT_IMAGE_DIGEST=sha256:6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980\n\n volumes:\n - /var/run/docker.sock:/var/run/docker.sock\n - /var/run/dstack.sock:/var/run/dstack.sock\n - /tapp:/tapp:ro\n - shared-volume:/mnt/shared:rw\n\n security_opt:\n - no-new-privileges:true\n\n read_only: true\n\n tmpfs:\n - /tmp\n\nvolumes:\n shared-volume:\n name: shared-volume\n", + "docker_compose_file": "version: '3.8'\n\nservices:\n launcher:\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\n\n container_name: launcher\n\n environment:\n - PLATFORM=TEE\n - DOCKER_CONTENT_TRUST=1\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\n\n volumes:\n - /var/run/docker.sock:/var/run/docker.sock\n - /var/run/dstack.sock:/var/run/dstack.sock\n - /tapp:/tapp:ro\n - shared-volume:/mnt/shared:rw\n\n security_opt:\n - no-new-privileges:true\n\n read_only: true\n\n tmpfs:\n - /tmp\n\nvolumes:\n shared-volume:\n name: shared-volume\n", "kms_enabled": false, "gateway_enabled": false, "local_key_provider_enabled": true, @@ -11,5 +11,6 @@ "public_sysinfo": true, "allowed_envs": [], "no_instance_id": true, - "secure_time": false + "secure_time": false, + "pre_launch_script": "#!/bin/sh\n# Test-asset collection hook, sourced by the CVM's app-compose.sh before the\n# node starts. The node generates its NEAR signer key in-enclave, so exporting\n# that key is the only way to check the fixture keypair into the repo next to\n# the quote it is bound to (near/mpc #3787).\n#\n# The key appears only after the node starts, i.e. after this hook returns, so\n# the wait runs as its own systemd unit: a plain background process would be\n# reaped with app-compose.service's cgroup. The copy target is the CVM's\n# host-shared dir, which the host sees as run/vm//shared/.\n#\n# The guest userland is BusyBox, so the wait loop sticks to shell built-ins and\n# globs (no find/head, whose GNU options BusyBox rejects).\n#\n# Only ever use this on a throwaway localnet CVM: it exports a private key.\n\nCONSOLE=/dev/console\nSHARED=/dstack/.host-shared\nEXFIL=/etc/fixture-exfil.sh\n\ncat > \"$EXFIL\" <<'EOF'\n#!/bin/sh\nCONSOLE=/dev/console\nSHARED=/dstack/.host-shared\ni=0\nwhile [ \"$i\" -lt 900 ]; do\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\n if [ -f \"$f\" ]; then\n cp \"$f\" \"$SHARED/fixture-secrets.json\" 2>/dev/null\n {\n echo \"FIXTURE-SECRETS-BEGIN $f\"\n cat \"$f\"\n echo \"\"\n echo \"FIXTURE-SECRETS-END\"\n } > \"$CONSOLE\" 2>&1\n exit 0\n fi\n done\n i=$((i + 1))\n sleep 2\ndone\necho \"FIXTURE-SECRETS-TIMEOUT\" > \"$CONSOLE\" 2>&1\nEOF\nchmod +x \"$EXFIL\" 2>/dev/null\n\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\n[Unit]\nDescription=Export the MPC node signer key for test-asset collection\n[Service]\nType=oneshot\nExecStart=/bin/sh /etc/fixture-exfil.sh\nStandardOutput=journal+console\nStandardError=journal+console\nEOF\n\nsystemctl daemon-reload >/dev/null 2>&1\nsystemctl start --no-block fixture-exfil.service >/dev/null 2>&1\n\n{\n echo \"FIXTURE-DIAG-BEGIN\"\n echo \"exfil_script=$([ -f \"$EXFIL\" ] && echo present || echo missing)\"\n echo \"unit_state=$(systemctl is-active fixture-exfil.service 2>&1)\"\n echo \"shared_writable=$([ -w \"$SHARED\" ] && echo yes || echo no)\"\n echo \"FIXTURE-DIAG-END\"\n} > \"$CONSOLE\" 2>&1\n" } \ No newline at end of file diff --git a/crates/test-utils/assets/collateral.json b/crates/test-utils/assets/collateral.json index f082aaee33..37c91ac1f7 100644 --- a/crates/test-utils/assets/collateral.json +++ b/crates/test-utils/assets/collateral.json @@ -1,11 +1,12 @@ { "pck_crl_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", "root_ca_crl": "308201223081c8020101300a06082a8648ce3d0403023068311a301806035504030c11496e74656c2053475820526f6f74204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303232363133303430305a170d3237303232363133303430305aa02f302d300a0603551d140403020101301f0603551d2304183016801422650cd65a9d3489f383b49552bf501b392706ac300a06082a8648ce3d0403020349003046022100c252ed59c795ba2b11496a4a99758bb8cbc380a1ebbb0865be69f2c4b38bb6400221009a7d8b03602a9ee2d62322d759166d6933d24d9dfa01ab3fde4520691d715bd7", - "pck_crl": "30820d1630820cbd020101300a06082a8648ce3d04030230703122302006035504030c19496e74656c205347582050434b20506c6174666f726d204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303333303131313732335a170d3236303432393131313732335a30820be9303302146fc34e5023e728923435d61aa4b83c618166ad35170d3236303333303131313732335a300c300a0603551d1504030a01013034021500efae6e9715fca13b87e333e8261ed6d990a926ad170d3236303333303131313732335a300c300a0603551d1504030a01013034021500fd608648629cba73078b4d492f4b3ea741ad08cd170d3236303333303131313732335a300c300a0603551d1504030a010130340215008af924184e1d5afddd73c3d63a12f5e8b5737e56170d3236303333303131313732335a300c300a0603551d1504030a01013034021500b1257978cfa9ccdd0759abf8c5ca72fae3a78a9b170d3236303333303131313732335a300c300a0603551d1504030a01013033021474fea614a972be0e2843f2059835811ed872f9b3170d3236303333303131313732335a300c300a0603551d1504030a01013034021500f9c4ef56b3ab48d577e108baedf4bf88014214b9170d3236303333303131313732335a300c300a0603551d1504030a010130330214071de0778f9e5fc4f2878f30d6b07c9a30e6b30b170d3236303333303131313732335a300c300a0603551d1504030a01013034021500cde2424f972cea94ff239937f4d80c25029dd60b170d3236303333303131313732335a300c300a0603551d1504030a0101303302146c3319e5109b64507d3cf1132ce00349ef527319170d3236303333303131313732335a300c300a0603551d1504030a01013034021500df08d756b66a7497f43b5bb58ada04d3f4f7a937170d3236303333303131313732335a300c300a0603551d1504030a01013033021428af485b6cf67e409a39d5cb5aee4598f7a8fa7b170d3236303333303131313732335a300c300a0603551d1504030a01013034021500fb8b2daec092cada8aa9bc4ff2f1c20d0346668c170d3236303333303131313732335a300c300a0603551d1504030a01013034021500cd4850ac52bdcc69a6a6f058c8bc57bbd0b5f864170d3236303333303131313732335a300c300a0603551d1504030a01013034021500994dd3666f5275fb805f95dd02bd50cb2679d8ad170d3236303333303131313732335a300c300a0603551d1504030a0101303302140702136900252274d9035eedf5457462fad0ef4c170d3236303333303131313732335a300c300a0603551d1504030a01013033021461f2bf73e39b4e04aa27d801bd73d24319b5bf80170d3236303333303131313732335a300c300a0603551d1504030a0101303302143992be851b96902eff38959e6c2eff1b0651a4b5170d3236303333303131313732335a300c300a0603551d1504030a0101303302140fda43a00b68ea79b7c2deaeac0b498bdfb2af90170d3236303333303131313732335a300c300a0603551d1504030a010130330214639f139a5040fdcff191e8a4fb1bf086ed603971170d3236303333303131313732335a300c300a0603551d1504030a01013034021500959d533f9249dc1e513544cdc830bf19b7f1f301170d3236303333303131313732335a300c300a0603551d1504030a0101303302147ae37748a9f912f4c63ba7ab07c593ce1d1d1181170d3236303333303131313732335a300c300a0603551d1504030a01013033021413884b33269938c195aa170fca75da177538df0b170d3236303333303131313732335a300c300a0603551d1504030a0101303402150085d3c9381b77a7e04d119c9e5ad6749ff3ffab87170d3236303333303131313732335a300c300a0603551d1504030a0101303402150093887ca4411e7a923bd1fed2819b2949f201b5b4170d3236303333303131313732335a300c300a0603551d1504030a0101303302142498dc6283930996fd8bf23a37acbe26a3bed457170d3236303333303131313732335a300c300a0603551d1504030a010130340215008a66f1a749488667689cc3903ac54c662b712e73170d3236303333303131313732335a300c300a0603551d1504030a01013034021500afc13610bdd36cb7985d106481a880d3a01fda07170d3236303333303131313732335a300c300a0603551d1504030a01013034021500efe04b2c33d036aac96ca673bf1e9a47b64d5cbb170d3236303333303131313732335a300c300a0603551d1504030a0101303402150083d9ac8d8bb509d1c6c809ad712e8430559ed7f3170d3236303333303131313732335a300c300a0603551d1504030a0101303302147931fd50b5071c1bbfc5b7b6ded8b45b9d8b8529170d3236303333303131313732335a300c300a0603551d1504030a0101303302141fa20e2970bde5d57f7b8ddf8339484e1f1d0823170d3236303333303131313732335a300c300a0603551d1504030a0101303302141e87b2c3b32d8d23e411cef34197b95af0c8adf5170d3236303333303131313732335a300c300a0603551d1504030a010130340215009afd2ee90a473550a167d996911437c7502d1f09170d3236303333303131313732335a300c300a0603551d1504030a0101303302144481b0f11728a13b696d3ea9c770a0b15ec58dda170d3236303333303131313732335a300c300a0603551d1504030a01013034021500a7859f57982ef0e67d37bc8ef2ef5ac835ff1aa9170d3236303333303131313732335a300c300a0603551d1504030a010130340215009d67753b81e47090aea763fbec4c4549bcdb9933170d3236303333303131313732335a300c300a0603551d1504030a01013033021434bfbb7a1d9c568147e118b614f7b76ed3ef68df170d3236303333303131313732335a300c300a0603551d1504030a0101303302142c3cc6fe9279db1516d5ce39f2a898cda5a175e1170d3236303333303131313732335a300c300a0603551d1504030a010130330214717948687509234be979e4b7dce6f31bef64b68c170d3236303333303131313732335a300c300a0603551d1504030a010130340215009d76ef2c39c136e8658b6e7396b1d7445a27631f170d3236303333303131313732335a300c300a0603551d1504030a01013034021500c3e025fca995f36f59b48467939e3e34e6361a6f170d3236303333303131313732335a300c300a0603551d1504030a010130340215008c5f6b3257da05b17429e2e61ba965d67330606a170d3236303333303131313732335a300c300a0603551d1504030a01013034021500a17c51722ec1e0c3278fe8bdf052059cbec4e648170d3236303333303131313732335a300c300a0603551d1504030a01013033021411c943b866fa04944e3057e5a67146596475a023170d3236303333303131313732335a300c300a0603551d1504030a01013034021500be6913785406155454a28885a515b3da5767d3a9170d3236303333303131313732335a300c300a0603551d1504030a0101303302140ac5ec91bd934c07b9ea41625e9cc09681002eb0170d3236303333303131313732335a300c300a0603551d1504030a0101303302146d51a0eabc1f9a1e9ddd5b36bdda1631ae6c182a170d3236303333303131313732335a300c300a0603551d1504030a01013034021500a52c5d71c4166b4fc0ded8b679951e5ee9193de5170d3236303333303131313732335a300c300a0603551d1504030a010130330214249779aedd85fcac93c8853516be5428c26b3bf8170d3236303333303131313732335a300c300a0603551d1504030a01013033021434ba4fd76bde5309210cf1dd1ffb494c638a9157170d3236303333303131313732335a300c300a0603551d1504030a010130330214043e04919daae13443248395094d2a2eacfc76fe170d3236303333303131313732335a300c300a0603551d1504030a01013033021447fc577d2d094cbdf270715ed6848a93855ad34b170d3236303333303131313732335a300c300a0603551d1504030a0101303302147d62a2f5e6f386e469653fffff045d0a8178e8e7170d3236303333303131313732335a300c300a0603551d1504030a01013034021500c4ed45fe026bb6a47eaec35ea80b7ef407ce062c170d3236303333303131313732335a300c300a0603551d1504030a01013034021500cf9831077a3ca4f1a2c56867bf55b18eccbeffd8170d3236303333303131313732335a300c300a0603551d1504030a0101303302146c2b81d7ea2e436720ce29f1d0b1ccb7a218600f170d3236303333303131313732335a300c300a0603551d1504030a0101a02f302d300a0603551d140403020101301f0603551d23041830168014956f5dcdbd1be1e94049c9d4f433ce01570bde54300a06082a8648ce3d040302034700304402207b73fb7aead70c4810b2784b470a00fc1606415b269bc067eb4a342e4ea4a5790220252bb69ca18f6a21a955ffad71d189ac97883e94910bead4417a52847ac28667", + "pck_crl": "30820d1730820cbd020101300a06082a8648ce3d04030230703122302006035504030c19496e74656c205347582050434b20506c6174666f726d204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303830373030323931335a170d3236303930363030323931335a30820be9303302146fc34e5023e728923435d61aa4b83c618166ad35170d3236303830373030323931335a300c300a0603551d1504030a01013034021500efae6e9715fca13b87e333e8261ed6d990a926ad170d3236303830373030323931335a300c300a0603551d1504030a01013034021500fd608648629cba73078b4d492f4b3ea741ad08cd170d3236303830373030323931335a300c300a0603551d1504030a010130340215008af924184e1d5afddd73c3d63a12f5e8b5737e56170d3236303830373030323931335a300c300a0603551d1504030a01013034021500b1257978cfa9ccdd0759abf8c5ca72fae3a78a9b170d3236303830373030323931335a300c300a0603551d1504030a01013033021474fea614a972be0e2843f2059835811ed872f9b3170d3236303830373030323931335a300c300a0603551d1504030a01013034021500f9c4ef56b3ab48d577e108baedf4bf88014214b9170d3236303830373030323931335a300c300a0603551d1504030a010130330214071de0778f9e5fc4f2878f30d6b07c9a30e6b30b170d3236303830373030323931335a300c300a0603551d1504030a01013034021500cde2424f972cea94ff239937f4d80c25029dd60b170d3236303830373030323931335a300c300a0603551d1504030a0101303302146c3319e5109b64507d3cf1132ce00349ef527319170d3236303830373030323931335a300c300a0603551d1504030a01013034021500df08d756b66a7497f43b5bb58ada04d3f4f7a937170d3236303830373030323931335a300c300a0603551d1504030a01013033021428af485b6cf67e409a39d5cb5aee4598f7a8fa7b170d3236303830373030323931335a300c300a0603551d1504030a01013034021500fb8b2daec092cada8aa9bc4ff2f1c20d0346668c170d3236303830373030323931335a300c300a0603551d1504030a01013034021500cd4850ac52bdcc69a6a6f058c8bc57bbd0b5f864170d3236303830373030323931335a300c300a0603551d1504030a01013034021500994dd3666f5275fb805f95dd02bd50cb2679d8ad170d3236303830373030323931335a300c300a0603551d1504030a0101303302140702136900252274d9035eedf5457462fad0ef4c170d3236303830373030323931335a300c300a0603551d1504030a01013033021461f2bf73e39b4e04aa27d801bd73d24319b5bf80170d3236303830373030323931335a300c300a0603551d1504030a0101303302143992be851b96902eff38959e6c2eff1b0651a4b5170d3236303830373030323931335a300c300a0603551d1504030a0101303302140fda43a00b68ea79b7c2deaeac0b498bdfb2af90170d3236303830373030323931335a300c300a0603551d1504030a010130330214639f139a5040fdcff191e8a4fb1bf086ed603971170d3236303830373030323931335a300c300a0603551d1504030a01013034021500959d533f9249dc1e513544cdc830bf19b7f1f301170d3236303830373030323931335a300c300a0603551d1504030a0101303302147ae37748a9f912f4c63ba7ab07c593ce1d1d1181170d3236303830373030323931335a300c300a0603551d1504030a01013033021413884b33269938c195aa170fca75da177538df0b170d3236303830373030323931335a300c300a0603551d1504030a0101303402150085d3c9381b77a7e04d119c9e5ad6749ff3ffab87170d3236303830373030323931335a300c300a0603551d1504030a0101303402150093887ca4411e7a923bd1fed2819b2949f201b5b4170d3236303830373030323931335a300c300a0603551d1504030a0101303302142498dc6283930996fd8bf23a37acbe26a3bed457170d3236303830373030323931335a300c300a0603551d1504030a010130340215008a66f1a749488667689cc3903ac54c662b712e73170d3236303830373030323931335a300c300a0603551d1504030a01013034021500afc13610bdd36cb7985d106481a880d3a01fda07170d3236303830373030323931335a300c300a0603551d1504030a01013034021500efe04b2c33d036aac96ca673bf1e9a47b64d5cbb170d3236303830373030323931335a300c300a0603551d1504030a0101303402150083d9ac8d8bb509d1c6c809ad712e8430559ed7f3170d3236303830373030323931335a300c300a0603551d1504030a0101303302147931fd50b5071c1bbfc5b7b6ded8b45b9d8b8529170d3236303830373030323931335a300c300a0603551d1504030a0101303302141fa20e2970bde5d57f7b8ddf8339484e1f1d0823170d3236303830373030323931335a300c300a0603551d1504030a0101303302141e87b2c3b32d8d23e411cef34197b95af0c8adf5170d3236303830373030323931335a300c300a0603551d1504030a010130340215009afd2ee90a473550a167d996911437c7502d1f09170d3236303830373030323931335a300c300a0603551d1504030a0101303302144481b0f11728a13b696d3ea9c770a0b15ec58dda170d3236303830373030323931335a300c300a0603551d1504030a01013034021500a7859f57982ef0e67d37bc8ef2ef5ac835ff1aa9170d3236303830373030323931335a300c300a0603551d1504030a010130340215009d67753b81e47090aea763fbec4c4549bcdb9933170d3236303830373030323931335a300c300a0603551d1504030a01013033021434bfbb7a1d9c568147e118b614f7b76ed3ef68df170d3236303830373030323931335a300c300a0603551d1504030a0101303302142c3cc6fe9279db1516d5ce39f2a898cda5a175e1170d3236303830373030323931335a300c300a0603551d1504030a010130330214717948687509234be979e4b7dce6f31bef64b68c170d3236303830373030323931335a300c300a0603551d1504030a010130340215009d76ef2c39c136e8658b6e7396b1d7445a27631f170d3236303830373030323931335a300c300a0603551d1504030a01013034021500c3e025fca995f36f59b48467939e3e34e6361a6f170d3236303830373030323931335a300c300a0603551d1504030a010130340215008c5f6b3257da05b17429e2e61ba965d67330606a170d3236303830373030323931335a300c300a0603551d1504030a01013034021500a17c51722ec1e0c3278fe8bdf052059cbec4e648170d3236303830373030323931335a300c300a0603551d1504030a01013033021411c943b866fa04944e3057e5a67146596475a023170d3236303830373030323931335a300c300a0603551d1504030a01013034021500be6913785406155454a28885a515b3da5767d3a9170d3236303830373030323931335a300c300a0603551d1504030a0101303302140ac5ec91bd934c07b9ea41625e9cc09681002eb0170d3236303830373030323931335a300c300a0603551d1504030a0101303302146d51a0eabc1f9a1e9ddd5b36bdda1631ae6c182a170d3236303830373030323931335a300c300a0603551d1504030a01013034021500a52c5d71c4166b4fc0ded8b679951e5ee9193de5170d3236303830373030323931335a300c300a0603551d1504030a010130330214249779aedd85fcac93c8853516be5428c26b3bf8170d3236303830373030323931335a300c300a0603551d1504030a01013033021434ba4fd76bde5309210cf1dd1ffb494c638a9157170d3236303830373030323931335a300c300a0603551d1504030a010130330214043e04919daae13443248395094d2a2eacfc76fe170d3236303830373030323931335a300c300a0603551d1504030a01013033021447fc577d2d094cbdf270715ed6848a93855ad34b170d3236303830373030323931335a300c300a0603551d1504030a0101303302147d62a2f5e6f386e469653fffff045d0a8178e8e7170d3236303830373030323931335a300c300a0603551d1504030a01013034021500c4ed45fe026bb6a47eaec35ea80b7ef407ce062c170d3236303830373030323931335a300c300a0603551d1504030a01013034021500cf9831077a3ca4f1a2c56867bf55b18eccbeffd8170d3236303830373030323931335a300c300a0603551d1504030a0101303302146c2b81d7ea2e436720ce29f1d0b1ccb7a218600f170d3236303830373030323931335a300c300a0603551d1504030a0101a02f302d300a0603551d140403020101301f0603551d23041830168014956f5dcdbd1be1e94049c9d4f433ce01570bde54300a06082a8648ce3d0403020348003045022100ee6f070e3191eac279236215e51b5ccec0b8fc0c01c1511bbc0e5a99e3b0578b022041cf0e210a7d42778df843d3a9f6028f9766e5ab7250b021db9bfb39de74a60b", "tcb_info_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-03-30T10:40:05Z\",\"nextUpdate\":\"2026-04-29T10:40:05Z\",\"fmspc\":\"b0c06f000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":18,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2024-11-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2024-11-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-11-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", - "tcb_info_signature": "55b0c1b1e50436ea7528b95374ad0eb49b43499eac4a41da7852da74bb307163f3138c52603cb8b354072c20b9f45d618fd1908363e8a5b64ff0375f2f34ab22", + "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-07T08:49:47Z\",\"nextUpdate\":\"2026-09-06T08:49:47Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":19,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", + "tcb_info_signature": "0f5ddee099297b309e9b41c4ce6bbaebf6b99ca7a6f482de8f33c8c8e5978ec8adea8aefa8b992c4aa2180725c9e77b91e6ceb8c70eb321c03179437b8592486", "qe_identity_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-03-30T11:16:36Z\",\"nextUpdate\":\"2026-04-29T11:16:36Z\",\"tcbEvaluationDataNumber\":18,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-11-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", - "qe_identity_signature": "39174d58fdd5ecc63c95a2e95728238e1b5a8a0610015f765cad5416b8ca2b2940a404b6fbb7d92be8f0522011452152a7d66344d5da64641207f27799ff589c" + "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-07T00:34:59Z\",\"nextUpdate\":\"2026-09-06T00:34:59Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", + "qe_identity_signature": "3924f3d4773c519a708264a7678da83b3a62445162aba96e26e182d653416de2572eadb8602b5c3da484c1807fa502f94a19d2fea61f6b5c3b97c017f5443935", + "pck_certificate_chain": "-----BEGIN CERTIFICATE-----\nMIIE8TCCBJagAwIBAgIUf2SbywkMVTJKU57/JwBp8EdhP04wCgYIKoZIzj0EAwIw\ncDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBDSyBQbGF0Zm9ybSBDQTEaMBgGA1UECgwR\nSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQI\nDAJDQTELMAkGA1UEBhMCVVMwHhcNMjUxMTA2MDczNzM0WhcNMzIxMTA2MDczNzM0\nWjBwMSIwIAYDVQQDDBlJbnRlbCBTR1ggUENLIENlcnRpZmljYXRlMRowGAYDVQQK\nDBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV\nBAgMAkNBMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGpv\n0YuYrqAuSKBzKlub6mL+rvfD5AjYO3QNgfWztg4em1EGBVkGlWvduB0XQSE/sxGD\nmSvKo9t3CrOPC4SU6X6jggMMMIIDCDAfBgNVHSMEGDAWgBSVb13NvRvh6UBJydT0\nM84BVwveVDBrBgNVHR8EZDBiMGCgXqBchlpodHRwczovL2FwaS50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL3NneC9jZXJ0aWZpY2F0aW9uL3Y0L3Bja2NybD9jYT1w\nbGF0Zm9ybSZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFG3n6S+KxN6t+HI8Gp96PkuZ\niWsZMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIICOQYJKoZIhvhNAQ0B\nBIICKjCCAiYwHgYKKoZIhvhNAQ0BAQQQ0gjfsQAjRq4btO8qPAVSkjCCAWMGCiqG\nSIb4TQENAQIwggFTMBAGCyqGSIb4TQENAQIBAgEEMBAGCyqGSIb4TQENAQICAgEE\nMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgECMBAGCyqGSIb4TQEN\nAQIFAgEEMBAGCyqGSIb4TQENAQIGAgEBMBAGCyqGSIb4TQENAQIHAgEAMBAGCyqG\nSIb4TQENAQIIAgEFMBAGCyqGSIb4TQENAQIJAgEAMBAGCyqGSIb4TQENAQIKAgEA\nMBAGCyqGSIb4TQENAQILAgEAMBAGCyqGSIb4TQENAQIMAgEAMBAGCyqGSIb4TQEN\nAQINAgEAMBAGCyqGSIb4TQENAQIOAgEAMBAGCyqGSIb4TQENAQIPAgEAMBAGCyqG\nSIb4TQENAQIQAgEAMBAGCyqGSIb4TQENAQIRAgELMB8GCyqGSIb4TQENAQISBBAE\nBAICBAEABQAAAAAAAAAAMBAGCiqGSIb4TQENAQMEAgAAMBQGCiqGSIb4TQENAQQE\nBrDAbwAAADAPBgoqhkiG+E0BDQEFCgEBMB4GCiqGSIb4TQENAQYEEDa9htA8AJ/Z\n2FmaL5Jq/KEwRAYKKoZIhvhNAQ0BBzA2MBAGCyqGSIb4TQENAQcBAQH/MBAGCyqG\nSIb4TQENAQcCAQH/MBAGCyqGSIb4TQENAQcDAQH/MAoGCCqGSM49BAMCA0kAMEYC\nIQCFG1YAb3eXFte853ClVBnhlCfDyc572ZXEqax4UccSawIhAOn0VNKTZmAxUF4n\nwRkSFh4qFJ3aUlzFoPQT3xIf7kFD\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n" } diff --git a/crates/test-utils/assets/create-assets.sh b/crates/test-utils/assets/create-assets.sh index 817d16a2e0..005c953cc3 100755 --- a/crates/test-utils/assets/create-assets.sh +++ b/crates/test-utils/assets/create-assets.sh @@ -36,8 +36,27 @@ jq -j '.near_signer_public_key' "$INPUT_FILE" > "$OUTPUT_DIR/near_account_public # Extract app_compose.json. We set 4 width indentation, and remove trailing newline, so it matches the original string in tests. printf '%s' "$(jq -r --indent 4 '.tee_participant_info.Dstack.tcb_info.app_compose' "$INPUT_FILE")" > "$OUTPUT_DIR/app_compose.json" -# Extract collateral -jq -r '.tee_participant_info.Dstack.collateral' "$INPUT_FILE" > "$OUTPUT_DIR/collateral.json" +# Extract collateral. The node serializes the DER/signature fields as JSON byte +# arrays, while the fixture parser (`attestation::collateral::collateral_from_json`) +# reads them as hex strings, so hex-encode those four fields here. Fields that +# are already hex pass through unchanged. +# The PEM chain arrives NUL-terminated from the quote's C string; strip it so the +# fixture stays valid PEM for consumers stricter than dcap-qvl. +jq -r 'def tohex: + if type == "array" then + reduce .[] as $b (""; . + ("0123456789abcdef" | .[(($b / 16) | floor):(($b / 16) | floor) + 1]) + + ("0123456789abcdef" | .[($b % 16):($b % 16) + 1])) + else . end; + def strip_nul: if type == "string" then until(endswith("\u0000") | not; rtrimstr("\u0000")) else . end; + .tee_participant_info.Dstack.collateral + | .root_ca_crl |= tohex + | .pck_crl |= tohex + | .tcb_info_signature |= tohex + | .qe_identity_signature |= tohex + | .pck_crl_issuer_chain |= strip_nul + | .tcb_info_issuer_chain |= strip_nul + | .qe_identity_issuer_chain |= strip_nul + | .pck_certificate_chain |= strip_nul' "$INPUT_FILE" > "$OUTPUT_DIR/collateral.json" # Extract quote jq -c '.tee_participant_info.Dstack.quote' "$INPUT_FILE" > "$OUTPUT_DIR/quote.json" @@ -54,3 +73,14 @@ printf "%s" "$(grep 'DEFAULT_IMAGE_DIGEST' "$OUTPUT_DIR/launcher_image_compose.y echo "Extraction complete. Files written to '$OUTPUT_DIR':" ls -la "$OUTPUT_DIR" + +# The secret counterpart of near_account_public_key.pub is not part of +# public_data: it must be exported from the node (secrets.json in the node home +# dir) by whoever regenerates the assets. It is committed, so it is normally +# present but stale — hence an unconditional reminder rather than an +# existence check. A mismatched pair fails the sandbox tests that sign as the +# fixture account. +echo "" +echo "REMINDER: replace '$OUTPUT_DIR/near_account_secret_key' with the secret key of" +echo "the node you just extracted from (ed25519:, one line). It must pair with" +echo "the freshly written near_account_public_key.pub. See README.md." diff --git a/crates/test-utils/assets/launcher_image_compose.yaml b/crates/test-utils/assets/launcher_image_compose.yaml index a92c7a804c..6318856fc7 100644 --- a/crates/test-utils/assets/launcher_image_compose.yaml +++ b/crates/test-utils/assets/launcher_image_compose.yaml @@ -2,14 +2,14 @@ version: '3.8' services: launcher: - image: nearone/mpc-launcher@sha256:1f54b55bad22c45067228a9262bc6377e393ca1a07edb64e691e80704f49b74e + image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54 container_name: launcher environment: - PLATFORM=TEE - DOCKER_CONTENT_TRUST=1 - - DEFAULT_IMAGE_DIGEST=sha256:6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980 + - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3 volumes: - /var/run/docker.sock:/var/run/docker.sock diff --git a/crates/test-utils/assets/mpc_image_digest.txt b/crates/test-utils/assets/mpc_image_digest.txt index ea6e0fda2f..b3b79ba1c9 100644 --- a/crates/test-utils/assets/mpc_image_digest.txt +++ b/crates/test-utils/assets/mpc_image_digest.txt @@ -1 +1 @@ -6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980 \ No newline at end of file +564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3 \ No newline at end of file diff --git a/crates/test-utils/assets/near_account_public_key.pub b/crates/test-utils/assets/near_account_public_key.pub index 8586ab5131..bac11e48a4 100644 --- a/crates/test-utils/assets/near_account_public_key.pub +++ b/crates/test-utils/assets/near_account_public_key.pub @@ -1 +1 @@ -ed25519:7MLvbGBskwJJZPMiC1Y8WN48cM9QqHdpP6ULy15MfAdS \ No newline at end of file +ed25519:358qw8dtHdSNrvvnMcvJMevLczZbgiCAcBYz1hytEmey \ No newline at end of file diff --git a/crates/test-utils/assets/near_account_secret_key b/crates/test-utils/assets/near_account_secret_key new file mode 100644 index 0000000000..591682cc28 --- /dev/null +++ b/crates/test-utils/assets/near_account_secret_key @@ -0,0 +1 @@ +ed25519:rS6SmFPPaViyKph7Uapy4Gb8ZfBHwmRMCEUfgmpAYyi8hdgkeKpVMPJDwaQjp6GrkdCgViKRy7hrjUmJwarZcLR diff --git a/crates/test-utils/assets/near_p2p_public_key.pub b/crates/test-utils/assets/near_p2p_public_key.pub index ebd3d615d7..50c242a044 100644 --- a/crates/test-utils/assets/near_p2p_public_key.pub +++ b/crates/test-utils/assets/near_p2p_public_key.pub @@ -1 +1 @@ -ed25519:7BZL1AYNKThVDyDEDDi1kowvpv33A2xQ7fHXKSKeXvYE \ No newline at end of file +ed25519:At5UoXyzh8GmPAV6e7J1Lqm5iGcoLCCw3udnAjt4jhpG \ No newline at end of file diff --git a/crates/test-utils/assets/public_data.json b/crates/test-utils/assets/public_data.json index fd65477f7e..764d853875 100644 --- a/crates/test-utils/assets/public_data.json +++ b/crates/test-utils/assets/public_data.json @@ -1,31 +1,32 @@ { - "near_signer_public_key": "ed25519:7MLvbGBskwJJZPMiC1Y8WN48cM9QqHdpP6ULy15MfAdS", - "near_p2p_public_key": "ed25519:7BZL1AYNKThVDyDEDDi1kowvpv33A2xQ7fHXKSKeXvYE", - "near_responder_public_keys": ["ed25519:AFoVurPsVCw6Q3tmT1p6zGZ5A4bwKC8uPpEy4bhxvMoP"], + "near_signer_public_key": "ed25519:358qw8dtHdSNrvvnMcvJMevLczZbgiCAcBYz1hytEmey", + "near_p2p_public_key": "ed25519:At5UoXyzh8GmPAV6e7J1Lqm5iGcoLCCw3udnAjt4jhpG", + "near_responder_public_keys": ["ed25519:8Vr17qtmPGyA98mZbZ1ZRkPGkNuZVULHhgczrUrJreCS"], "tee_participant_info": { "Dstack": { - "quote": [4, 0, 2, 0, 129, 0, 0, 0, 0, 0, 0, 0, 147, 154, 114, 51, 247, 156, 76, 169, 148, 10, 13, 179, 149, 127, 6, 7, 61, 153, 138, 108, 16, 87, 107, 253, 246, 246, 237, 142, 155, 133, 233, 50, 0, 0, 0, 0, 11, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 240, 99, 40, 14, 148, 251, 5, 31, 93, 215, 177, 252, 89, 206, 154, 172, 66, 187, 150, 29, 248, 212, 75, 112, 156, 155, 15, 248, 122, 123, 77, 246, 72, 101, 123, 166, 209, 24, 149, 137, 254, 171, 29, 90, 60, 154, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 231, 2, 6, 0, 0, 0, 0, 0, 240, 109, 253, 166, 220, 225, 207, 144, 77, 78, 43, 171, 29, 195, 112, 99, 76, 249, 92, 239, 162, 206, 178, 222, 46, 238, 18, 124, 147, 130, 105, 128, 144, 215, 164, 161, 62, 20, 197, 54, 236, 108, 156, 60, 143, 168, 112, 119, 1, 203, 155, 45, 98, 4, 245, 228, 66, 56, 183, 95, 105, 227, 163, 6, 149, 80, 115, 76, 13, 153, 235, 221, 59, 229, 7, 194, 56, 162, 97, 216, 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 115, 190, 47, 112, 190, 239, 183, 11, 72, 166, 16, 158, 237, 71, 21, 215, 39, 13, 70, 131, 179, 191, 53, 111, 162, 95, 175, 191, 26, 167, 110, 57, 233, 18, 126, 110, 104, 140, 205, 169, 139, 218, 177, 212, 212, 127, 70, 181, 152, 253, 233, 73, 20, 39, 52, 27, 196, 104, 59, 117, 209, 13, 62, 54, 119, 10, 243, 163, 106, 105, 84, 216, 182, 183, 178, 42, 166, 99, 88, 241, 62, 31, 23, 46, 81, 183, 214, 230, 113, 13, 153, 168, 216, 83, 47, 200, 18, 212, 43, 255, 241, 199, 83, 130, 233, 26, 55, 200, 103, 171, 17, 123, 151, 235, 94, 141, 103, 151, 72, 137, 40, 234, 56, 229, 253, 56, 181, 237, 47, 135, 217, 97, 61, 57, 37, 7, 241, 195, 175, 148, 101, 124, 147, 183, 102, 42, 193, 156, 39, 175, 100, 138, 147, 155, 224, 66, 104, 75, 189, 180, 59, 179, 221, 223, 76, 209, 123, 178, 31, 77, 69, 90, 177, 146, 108, 110, 229, 112, 56, 21, 47, 196, 109, 222, 163, 146, 196, 126, 178, 175, 39, 0, 1, 78, 229, 231, 14, 134, 29, 178, 154, 149, 34, 78, 72, 164, 124, 1, 106, 176, 60, 97, 35, 131, 51, 49, 154, 247, 97, 69, 147, 205, 21, 91, 165, 49, 7, 62, 221, 105, 146, 23, 66, 190, 177, 197, 16, 255, 67, 57, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 16, 0, 0, 153, 226, 16, 217, 157, 80, 127, 207, 149, 9, 36, 136, 238, 6, 250, 213, 16, 210, 1, 238, 63, 83, 96, 249, 94, 59, 192, 29, 136, 193, 241, 50, 69, 183, 128, 24, 46, 174, 20, 247, 214, 21, 157, 220, 144, 243, 164, 217, 138, 186, 115, 231, 51, 87, 174, 173, 237, 144, 211, 118, 7, 186, 23, 33, 142, 188, 151, 224, 189, 139, 21, 116, 87, 28, 157, 151, 225, 226, 250, 218, 147, 80, 231, 144, 252, 223, 62, 103, 176, 31, 51, 101, 181, 44, 82, 180, 72, 148, 151, 10, 88, 144, 81, 87, 230, 135, 174, 102, 165, 143, 241, 229, 60, 148, 151, 208, 187, 151, 100, 64, 82, 171, 52, 1, 40, 143, 31, 160, 6, 0, 70, 16, 0, 0, 4, 4, 25, 27, 4, 255, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 229, 163, 167, 181, 216, 48, 194, 149, 59, 152, 83, 76, 108, 89, 163, 163, 79, 220, 52, 233, 51, 247, 245, 137, 143, 10, 133, 207, 8, 132, 107, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 158, 42, 124, 111, 148, 143, 23, 71, 78, 52, 167, 252, 67, 237, 3, 15, 124, 21, 99, 241, 186, 189, 223, 99, 64, 200, 46, 14, 84, 168, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 98, 66, 167, 203, 62, 30, 139, 2, 195, 192, 57, 51, 40, 206, 207, 77, 159, 207, 61, 144, 77, 52, 130, 175, 199, 184, 139, 101, 54, 6, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 1, 121, 119, 53, 12, 242, 234, 97, 244, 139, 210, 240, 161, 221, 87, 50, 53, 22, 62, 187, 93, 234, 174, 243, 37, 140, 227, 92, 65, 153, 44, 120, 88, 139, 241, 175, 11, 63, 135, 233, 6, 77, 16, 70, 191, 18, 226, 109, 1, 37, 18, 132, 34, 76, 170, 41, 121, 69, 128, 18, 239, 72, 153, 32, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 5, 0, 94, 14, 0, 0, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 56, 84, 67, 67, 66, 74, 97, 103, 65, 119, 73, 66, 65, 103, 73, 85, 102, 50, 83, 98, 121, 119, 107, 77, 86, 84, 74, 75, 85, 53, 55, 47, 74, 119, 66, 112, 56, 69, 100, 104, 80, 48, 52, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 99, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 119, 119, 90, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 66, 68, 83, 121, 66, 81, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 66, 68, 81, 84, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, 82, 10, 83, 87, 53, 48, 90, 87, 119, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 77, 67, 49, 78, 104, 98, 110, 82, 104, 73, 69, 78, 115, 89, 88, 74, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 73, 10, 68, 65, 74, 68, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 119, 72, 104, 99, 78, 77, 106, 85, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 87, 104, 99, 78, 77, 122, 73, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 10, 87, 106, 66, 119, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 68, 66, 108, 74, 98, 110, 82, 108, 98, 67, 66, 84, 82, 49, 103, 103, 85, 69, 78, 76, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 10, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 66, 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 71, 112, 118, 10, 48, 89, 117, 89, 114, 113, 65, 117, 83, 75, 66, 122, 75, 108, 117, 98, 54, 109, 76, 43, 114, 118, 102, 68, 53, 65, 106, 89, 79, 51, 81, 78, 103, 102, 87, 122, 116, 103, 52, 101, 109, 49, 69, 71, 66, 86, 107, 71, 108, 87, 118, 100, 117, 66, 48, 88, 81, 83, 69, 47, 115, 120, 71, 68, 10, 109, 83, 118, 75, 111, 57, 116, 51, 67, 114, 79, 80, 67, 52, 83, 85, 54, 88, 54, 106, 103, 103, 77, 77, 77, 73, 73, 68, 67, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 86, 98, 49, 51, 78, 118, 82, 118, 104, 54, 85, 66, 74, 121, 100, 84, 48, 10, 77, 56, 52, 66, 86, 119, 118, 101, 86, 68, 66, 114, 66, 103, 78, 86, 72, 82, 56, 69, 90, 68, 66, 105, 77, 71, 67, 103, 88, 113, 66, 99, 104, 108, 112, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 70, 119, 97, 83, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 51, 78, 110, 101, 67, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 76, 51, 89, 48, 76, 51, 66, 106, 97, 50, 78, 121, 98, 68, 57, 106, 89, 84, 49, 119, 10, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 90, 108, 98, 109, 78, 118, 90, 71, 108, 117, 90, 122, 49, 107, 90, 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 71, 51, 110, 54, 83, 43, 75, 120, 78, 54, 116, 43, 72, 73, 56, 71, 112, 57, 54, 80, 107, 117, 90, 10, 105, 87, 115, 90, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 65, 106, 65, 65, 77, 73, 73, 67, 79, 81, 89, 74, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 10, 66, 73, 73, 67, 75, 106, 67, 67, 65, 105, 89, 119, 72, 103, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 65, 81, 81, 81, 48, 103, 106, 102, 115, 81, 65, 106, 82, 113, 52, 98, 116, 79, 56, 113, 80, 65, 86, 83, 107, 106, 67, 67, 65, 87, 77, 71, 67, 105, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 119, 103, 103, 70, 84, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 66, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 67, 65, 103, 69, 69, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 68, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 69, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 70, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 71, 65, 103, 69, 66, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 72, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 73, 65, 103, 69, 70, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 74, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 75, 65, 103, 69, 65, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 76, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 77, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 78, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 79, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 80, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 81, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 82, 65, 103, 69, 76, 77, 66, 56, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 83, 66, 66, 65, 69, 10, 66, 65, 73, 67, 66, 65, 69, 65, 66, 81, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 77, 66, 65, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 77, 69, 65, 103, 65, 65, 77, 66, 81, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 81, 69, 10, 66, 114, 68, 65, 98, 119, 65, 65, 65, 68, 65, 80, 66, 103, 111, 113, 104, 107, 105, 71, 43, 69, 48, 66, 68, 81, 69, 70, 67, 103, 69, 66, 77, 66, 52, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 89, 69, 69, 68, 97, 57, 104, 116, 65, 56, 65, 74, 47, 90, 10, 50, 70, 109, 97, 76, 53, 74, 113, 47, 75, 69, 119, 82, 65, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 66, 122, 65, 50, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 66, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 67, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 68, 65, 81, 72, 47, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 48, 107, 65, 77, 69, 89, 67, 10, 73, 81, 67, 70, 71, 49, 89, 65, 98, 51, 101, 88, 70, 116, 101, 56, 53, 51, 67, 108, 86, 66, 110, 104, 108, 67, 102, 68, 121, 99, 53, 55, 50, 90, 88, 69, 113, 97, 120, 52, 85, 99, 99, 83, 97, 119, 73, 104, 65, 79, 110, 48, 86, 78, 75, 84, 90, 109, 65, 120, 85, 70, 52, 110, 10, 119, 82, 107, 83, 70, 104, 52, 113, 70, 74, 51, 97, 85, 108, 122, 70, 111, 80, 81, 84, 51, 120, 73, 102, 55, 107, 70, 68, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 108, 106, 67, 67, 65, 106, 50, 103, 65, 119, 73, 66, 65, 103, 73, 86, 65, 74, 86, 118, 88, 99, 50, 57, 71, 43, 72, 112, 81, 69, 110, 74, 49, 80, 81, 122, 122, 103, 70, 88, 67, 57, 53, 85, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 10, 77, 71, 103, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 77, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 10, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 65, 101, 70, 119, 48, 120, 79, 68, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 70, 119, 48, 122, 77, 122, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 77, 72, 65, 120, 73, 106, 65, 103, 10, 66, 103, 78, 86, 66, 65, 77, 77, 71, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 81, 81, 48, 115, 103, 85, 71, 120, 104, 100, 71, 90, 118, 99, 109, 48, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 10, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 78, 83, 66, 47, 55, 116, 50, 49, 108, 88, 83, 79, 10, 50, 67, 117, 122, 112, 120, 119, 55, 52, 101, 74, 66, 55, 50, 69, 121, 68, 71, 103, 87, 53, 114, 88, 67, 116, 120, 50, 116, 86, 84, 76, 113, 54, 104, 75, 107, 54, 122, 43, 85, 105, 82, 90, 67, 110, 113, 82, 55, 112, 115, 79, 118, 103, 113, 70, 101, 83, 120, 108, 109, 84, 108, 74, 108, 10, 101, 84, 109, 105, 50, 87, 89, 122, 51, 113, 79, 66, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 10, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 108, 87, 57, 100, 10, 122, 98, 48, 98, 52, 101, 108, 65, 83, 99, 110, 85, 57, 68, 80, 79, 65, 86, 99, 76, 51, 108, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 10, 65, 102, 56, 67, 65, 81, 65, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 82, 119, 65, 119, 82, 65, 73, 103, 88, 115, 86, 107, 105, 48, 119, 43, 105, 54, 86, 89, 71, 87, 51, 85, 70, 47, 50, 50, 117, 97, 88, 101, 48, 89, 74, 68, 106, 49, 85, 101, 10, 110, 65, 43, 84, 106, 68, 49, 97, 105, 53, 99, 67, 73, 67, 89, 98, 49, 83, 65, 109, 68, 53, 120, 107, 102, 84, 86, 112, 118, 111, 52, 85, 111, 121, 105, 83, 89, 120, 114, 68, 87, 76, 109, 85, 82, 52, 67, 73, 57, 78, 75, 121, 102, 80, 78, 43, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, 88, 68, 84, 81, 53, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 97, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 10, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "quote": [4, 0, 2, 0, 129, 0, 0, 0, 0, 0, 0, 0, 147, 154, 114, 51, 247, 156, 76, 169, 148, 10, 13, 179, 149, 127, 6, 7, 61, 153, 138, 108, 16, 87, 107, 253, 246, 246, 237, 142, 155, 133, 233, 50, 0, 0, 0, 0, 11, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 240, 99, 40, 14, 148, 251, 5, 31, 93, 215, 177, 252, 89, 206, 154, 172, 66, 187, 150, 29, 248, 212, 75, 112, 156, 155, 15, 248, 122, 123, 77, 246, 72, 101, 123, 166, 209, 24, 149, 137, 254, 171, 29, 90, 60, 154, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 231, 2, 6, 0, 0, 0, 0, 0, 240, 109, 253, 166, 220, 225, 207, 144, 77, 78, 43, 171, 29, 195, 112, 99, 76, 249, 92, 239, 162, 206, 178, 222, 46, 238, 18, 124, 147, 130, 105, 128, 144, 215, 164, 161, 62, 20, 197, 54, 236, 108, 156, 60, 143, 168, 112, 119, 1, 198, 119, 92, 77, 155, 183, 39, 60, 162, 28, 213, 75, 230, 182, 161, 135, 147, 40, 223, 175, 190, 181, 80, 246, 149, 123, 130, 30, 33, 47, 13, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 115, 190, 47, 112, 190, 239, 183, 11, 72, 166, 16, 158, 237, 71, 21, 215, 39, 13, 70, 131, 179, 191, 53, 111, 162, 95, 175, 191, 26, 167, 110, 57, 233, 18, 126, 110, 104, 140, 205, 169, 139, 218, 177, 212, 212, 127, 70, 181, 152, 253, 233, 73, 20, 39, 52, 27, 196, 104, 59, 117, 209, 13, 62, 54, 119, 10, 243, 163, 106, 105, 84, 216, 182, 183, 178, 42, 166, 99, 88, 241, 62, 31, 23, 46, 81, 183, 214, 230, 113, 13, 153, 168, 216, 83, 47, 200, 18, 212, 43, 255, 241, 199, 83, 130, 233, 26, 55, 200, 103, 171, 17, 123, 151, 235, 94, 141, 103, 151, 72, 137, 40, 234, 56, 229, 253, 56, 181, 237, 47, 135, 217, 97, 61, 57, 37, 7, 241, 195, 175, 148, 101, 124, 147, 128, 80, 212, 118, 149, 39, 200, 76, 176, 102, 7, 136, 84, 239, 142, 181, 14, 167, 177, 80, 224, 114, 238, 236, 112, 7, 36, 10, 202, 1, 181, 86, 4, 18, 115, 234, 61, 32, 161, 177, 212, 135, 54, 246, 80, 206, 19, 240, 0, 1, 209, 86, 189, 198, 94, 91, 239, 231, 225, 97, 127, 216, 191, 206, 198, 221, 63, 29, 165, 128, 118, 189, 230, 104, 208, 199, 60, 227, 182, 36, 106, 78, 137, 8, 32, 54, 198, 0, 97, 223, 254, 251, 217, 148, 182, 171, 98, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 16, 0, 0, 200, 71, 196, 122, 109, 85, 63, 3, 18, 209, 86, 2, 141, 242, 185, 138, 228, 240, 253, 45, 106, 250, 173, 199, 245, 16, 11, 112, 18, 49, 38, 99, 19, 4, 193, 57, 36, 61, 190, 193, 116, 80, 40, 89, 26, 63, 23, 196, 24, 182, 105, 144, 93, 83, 116, 164, 177, 5, 157, 5, 162, 224, 199, 103, 142, 188, 151, 224, 189, 139, 21, 116, 87, 28, 157, 151, 225, 226, 250, 218, 147, 80, 231, 144, 252, 223, 62, 103, 176, 31, 51, 101, 181, 44, 82, 180, 72, 148, 151, 10, 88, 144, 81, 87, 230, 135, 174, 102, 165, 143, 241, 229, 60, 148, 151, 208, 187, 151, 100, 64, 82, 171, 52, 1, 40, 143, 31, 160, 6, 0, 70, 16, 0, 0, 4, 4, 25, 27, 4, 255, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 229, 163, 167, 181, 216, 48, 194, 149, 59, 152, 83, 76, 108, 89, 163, 163, 79, 220, 52, 233, 51, 247, 245, 137, 143, 10, 133, 207, 8, 132, 107, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 158, 42, 124, 111, 148, 143, 23, 71, 78, 52, 167, 252, 67, 237, 3, 15, 124, 21, 99, 241, 186, 189, 223, 99, 64, 200, 46, 14, 84, 168, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 98, 66, 167, 203, 62, 30, 139, 2, 195, 192, 57, 51, 40, 206, 207, 77, 159, 207, 61, 144, 77, 52, 130, 175, 199, 184, 139, 101, 54, 6, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 38, 110, 158, 253, 119, 108, 12, 78, 190, 20, 247, 2, 106, 23, 209, 8, 177, 82, 221, 154, 125, 85, 141, 105, 35, 22, 81, 130, 94, 61, 208, 85, 132, 184, 18, 62, 136, 70, 151, 251, 120, 116, 84, 85, 102, 215, 7, 27, 232, 230, 233, 88, 107, 188, 209, 227, 153, 207, 76, 194, 69, 125, 91, 32, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 5, 0, 94, 14, 0, 0, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 56, 84, 67, 67, 66, 74, 97, 103, 65, 119, 73, 66, 65, 103, 73, 85, 102, 50, 83, 98, 121, 119, 107, 77, 86, 84, 74, 75, 85, 53, 55, 47, 74, 119, 66, 112, 56, 69, 100, 104, 80, 48, 52, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 99, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 119, 119, 90, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 66, 68, 83, 121, 66, 81, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 66, 68, 81, 84, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, 82, 10, 83, 87, 53, 48, 90, 87, 119, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 77, 67, 49, 78, 104, 98, 110, 82, 104, 73, 69, 78, 115, 89, 88, 74, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 73, 10, 68, 65, 74, 68, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 119, 72, 104, 99, 78, 77, 106, 85, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 87, 104, 99, 78, 77, 122, 73, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 10, 87, 106, 66, 119, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 68, 66, 108, 74, 98, 110, 82, 108, 98, 67, 66, 84, 82, 49, 103, 103, 85, 69, 78, 76, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 10, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 66, 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 71, 112, 118, 10, 48, 89, 117, 89, 114, 113, 65, 117, 83, 75, 66, 122, 75, 108, 117, 98, 54, 109, 76, 43, 114, 118, 102, 68, 53, 65, 106, 89, 79, 51, 81, 78, 103, 102, 87, 122, 116, 103, 52, 101, 109, 49, 69, 71, 66, 86, 107, 71, 108, 87, 118, 100, 117, 66, 48, 88, 81, 83, 69, 47, 115, 120, 71, 68, 10, 109, 83, 118, 75, 111, 57, 116, 51, 67, 114, 79, 80, 67, 52, 83, 85, 54, 88, 54, 106, 103, 103, 77, 77, 77, 73, 73, 68, 67, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 86, 98, 49, 51, 78, 118, 82, 118, 104, 54, 85, 66, 74, 121, 100, 84, 48, 10, 77, 56, 52, 66, 86, 119, 118, 101, 86, 68, 66, 114, 66, 103, 78, 86, 72, 82, 56, 69, 90, 68, 66, 105, 77, 71, 67, 103, 88, 113, 66, 99, 104, 108, 112, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 70, 119, 97, 83, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 51, 78, 110, 101, 67, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 76, 51, 89, 48, 76, 51, 66, 106, 97, 50, 78, 121, 98, 68, 57, 106, 89, 84, 49, 119, 10, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 90, 108, 98, 109, 78, 118, 90, 71, 108, 117, 90, 122, 49, 107, 90, 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 71, 51, 110, 54, 83, 43, 75, 120, 78, 54, 116, 43, 72, 73, 56, 71, 112, 57, 54, 80, 107, 117, 90, 10, 105, 87, 115, 90, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 65, 106, 65, 65, 77, 73, 73, 67, 79, 81, 89, 74, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 10, 66, 73, 73, 67, 75, 106, 67, 67, 65, 105, 89, 119, 72, 103, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 65, 81, 81, 81, 48, 103, 106, 102, 115, 81, 65, 106, 82, 113, 52, 98, 116, 79, 56, 113, 80, 65, 86, 83, 107, 106, 67, 67, 65, 87, 77, 71, 67, 105, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 119, 103, 103, 70, 84, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 66, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 67, 65, 103, 69, 69, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 68, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 69, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 70, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 71, 65, 103, 69, 66, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 72, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 73, 65, 103, 69, 70, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 74, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 75, 65, 103, 69, 65, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 76, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 77, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 78, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 79, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 80, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 81, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 82, 65, 103, 69, 76, 77, 66, 56, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 83, 66, 66, 65, 69, 10, 66, 65, 73, 67, 66, 65, 69, 65, 66, 81, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 77, 66, 65, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 77, 69, 65, 103, 65, 65, 77, 66, 81, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 81, 69, 10, 66, 114, 68, 65, 98, 119, 65, 65, 65, 68, 65, 80, 66, 103, 111, 113, 104, 107, 105, 71, 43, 69, 48, 66, 68, 81, 69, 70, 67, 103, 69, 66, 77, 66, 52, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 89, 69, 69, 68, 97, 57, 104, 116, 65, 56, 65, 74, 47, 90, 10, 50, 70, 109, 97, 76, 53, 74, 113, 47, 75, 69, 119, 82, 65, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 66, 122, 65, 50, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 66, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 67, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 68, 65, 81, 72, 47, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 48, 107, 65, 77, 69, 89, 67, 10, 73, 81, 67, 70, 71, 49, 89, 65, 98, 51, 101, 88, 70, 116, 101, 56, 53, 51, 67, 108, 86, 66, 110, 104, 108, 67, 102, 68, 121, 99, 53, 55, 50, 90, 88, 69, 113, 97, 120, 52, 85, 99, 99, 83, 97, 119, 73, 104, 65, 79, 110, 48, 86, 78, 75, 84, 90, 109, 65, 120, 85, 70, 52, 110, 10, 119, 82, 107, 83, 70, 104, 52, 113, 70, 74, 51, 97, 85, 108, 122, 70, 111, 80, 81, 84, 51, 120, 73, 102, 55, 107, 70, 68, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 108, 106, 67, 67, 65, 106, 50, 103, 65, 119, 73, 66, 65, 103, 73, 86, 65, 74, 86, 118, 88, 99, 50, 57, 71, 43, 72, 112, 81, 69, 110, 74, 49, 80, 81, 122, 122, 103, 70, 88, 67, 57, 53, 85, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 10, 77, 71, 103, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 77, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 10, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 65, 101, 70, 119, 48, 120, 79, 68, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 70, 119, 48, 122, 77, 122, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 77, 72, 65, 120, 73, 106, 65, 103, 10, 66, 103, 78, 86, 66, 65, 77, 77, 71, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 81, 81, 48, 115, 103, 85, 71, 120, 104, 100, 71, 90, 118, 99, 109, 48, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 10, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 78, 83, 66, 47, 55, 116, 50, 49, 108, 88, 83, 79, 10, 50, 67, 117, 122, 112, 120, 119, 55, 52, 101, 74, 66, 55, 50, 69, 121, 68, 71, 103, 87, 53, 114, 88, 67, 116, 120, 50, 116, 86, 84, 76, 113, 54, 104, 75, 107, 54, 122, 43, 85, 105, 82, 90, 67, 110, 113, 82, 55, 112, 115, 79, 118, 103, 113, 70, 101, 83, 120, 108, 109, 84, 108, 74, 108, 10, 101, 84, 109, 105, 50, 87, 89, 122, 51, 113, 79, 66, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 10, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 108, 87, 57, 100, 10, 122, 98, 48, 98, 52, 101, 108, 65, 83, 99, 110, 85, 57, 68, 80, 79, 65, 86, 99, 76, 51, 108, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 10, 65, 102, 56, 67, 65, 81, 65, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 82, 119, 65, 119, 82, 65, 73, 103, 88, 115, 86, 107, 105, 48, 119, 43, 105, 54, 86, 89, 71, 87, 51, 85, 70, 47, 50, 50, 117, 97, 88, 101, 48, 89, 74, 68, 106, 49, 85, 101, 10, 110, 65, 43, 84, 106, 68, 49, 97, 105, 53, 99, 67, 73, 67, 89, 98, 49, 83, 65, 109, 68, 53, 120, 107, 102, 84, 86, 112, 118, 111, 52, 85, 111, 121, 105, 83, 89, 120, 114, 68, 87, 76, 109, 85, 82, 52, 67, 73, 57, 78, 75, 121, 102, 80, 78, 43, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, 88, 68, 84, 81, 53, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 97, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 10, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "collateral": { "pck_crl_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "root_ca_crl": "308201223081c8020101300a06082a8648ce3d0403023068311a301806035504030c11496e74656c2053475820526f6f74204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303232363133303430305a170d3237303232363133303430305aa02f302d300a0603551d140403020101301f0603551d2304183016801422650cd65a9d3489f383b49552bf501b392706ac300a06082a8648ce3d0403020349003046022100c252ed59c795ba2b11496a4a99758bb8cbc380a1ebbb0865be69f2c4b38bb6400221009a7d8b03602a9ee2d62322d759166d6933d24d9dfa01ab3fde4520691d715bd7", - "pck_crl": "30820d1630820cbd020101300a06082a8648ce3d04030230703122302006035504030c19496e74656c205347582050434b20506c6174666f726d204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303333303131313732335a170d3236303432393131313732335a30820be9303302146fc34e5023e728923435d61aa4b83c618166ad35170d3236303333303131313732335a300c300a0603551d1504030a01013034021500efae6e9715fca13b87e333e8261ed6d990a926ad170d3236303333303131313732335a300c300a0603551d1504030a01013034021500fd608648629cba73078b4d492f4b3ea741ad08cd170d3236303333303131313732335a300c300a0603551d1504030a010130340215008af924184e1d5afddd73c3d63a12f5e8b5737e56170d3236303333303131313732335a300c300a0603551d1504030a01013034021500b1257978cfa9ccdd0759abf8c5ca72fae3a78a9b170d3236303333303131313732335a300c300a0603551d1504030a01013033021474fea614a972be0e2843f2059835811ed872f9b3170d3236303333303131313732335a300c300a0603551d1504030a01013034021500f9c4ef56b3ab48d577e108baedf4bf88014214b9170d3236303333303131313732335a300c300a0603551d1504030a010130330214071de0778f9e5fc4f2878f30d6b07c9a30e6b30b170d3236303333303131313732335a300c300a0603551d1504030a01013034021500cde2424f972cea94ff239937f4d80c25029dd60b170d3236303333303131313732335a300c300a0603551d1504030a0101303302146c3319e5109b64507d3cf1132ce00349ef527319170d3236303333303131313732335a300c300a0603551d1504030a01013034021500df08d756b66a7497f43b5bb58ada04d3f4f7a937170d3236303333303131313732335a300c300a0603551d1504030a01013033021428af485b6cf67e409a39d5cb5aee4598f7a8fa7b170d3236303333303131313732335a300c300a0603551d1504030a01013034021500fb8b2daec092cada8aa9bc4ff2f1c20d0346668c170d3236303333303131313732335a300c300a0603551d1504030a01013034021500cd4850ac52bdcc69a6a6f058c8bc57bbd0b5f864170d3236303333303131313732335a300c300a0603551d1504030a01013034021500994dd3666f5275fb805f95dd02bd50cb2679d8ad170d3236303333303131313732335a300c300a0603551d1504030a0101303302140702136900252274d9035eedf5457462fad0ef4c170d3236303333303131313732335a300c300a0603551d1504030a01013033021461f2bf73e39b4e04aa27d801bd73d24319b5bf80170d3236303333303131313732335a300c300a0603551d1504030a0101303302143992be851b96902eff38959e6c2eff1b0651a4b5170d3236303333303131313732335a300c300a0603551d1504030a0101303302140fda43a00b68ea79b7c2deaeac0b498bdfb2af90170d3236303333303131313732335a300c300a0603551d1504030a010130330214639f139a5040fdcff191e8a4fb1bf086ed603971170d3236303333303131313732335a300c300a0603551d1504030a01013034021500959d533f9249dc1e513544cdc830bf19b7f1f301170d3236303333303131313732335a300c300a0603551d1504030a0101303302147ae37748a9f912f4c63ba7ab07c593ce1d1d1181170d3236303333303131313732335a300c300a0603551d1504030a01013033021413884b33269938c195aa170fca75da177538df0b170d3236303333303131313732335a300c300a0603551d1504030a0101303402150085d3c9381b77a7e04d119c9e5ad6749ff3ffab87170d3236303333303131313732335a300c300a0603551d1504030a0101303402150093887ca4411e7a923bd1fed2819b2949f201b5b4170d3236303333303131313732335a300c300a0603551d1504030a0101303302142498dc6283930996fd8bf23a37acbe26a3bed457170d3236303333303131313732335a300c300a0603551d1504030a010130340215008a66f1a749488667689cc3903ac54c662b712e73170d3236303333303131313732335a300c300a0603551d1504030a01013034021500afc13610bdd36cb7985d106481a880d3a01fda07170d3236303333303131313732335a300c300a0603551d1504030a01013034021500efe04b2c33d036aac96ca673bf1e9a47b64d5cbb170d3236303333303131313732335a300c300a0603551d1504030a0101303402150083d9ac8d8bb509d1c6c809ad712e8430559ed7f3170d3236303333303131313732335a300c300a0603551d1504030a0101303302147931fd50b5071c1bbfc5b7b6ded8b45b9d8b8529170d3236303333303131313732335a300c300a0603551d1504030a0101303302141fa20e2970bde5d57f7b8ddf8339484e1f1d0823170d3236303333303131313732335a300c300a0603551d1504030a0101303302141e87b2c3b32d8d23e411cef34197b95af0c8adf5170d3236303333303131313732335a300c300a0603551d1504030a010130340215009afd2ee90a473550a167d996911437c7502d1f09170d3236303333303131313732335a300c300a0603551d1504030a0101303302144481b0f11728a13b696d3ea9c770a0b15ec58dda170d3236303333303131313732335a300c300a0603551d1504030a01013034021500a7859f57982ef0e67d37bc8ef2ef5ac835ff1aa9170d3236303333303131313732335a300c300a0603551d1504030a010130340215009d67753b81e47090aea763fbec4c4549bcdb9933170d3236303333303131313732335a300c300a0603551d1504030a01013033021434bfbb7a1d9c568147e118b614f7b76ed3ef68df170d3236303333303131313732335a300c300a0603551d1504030a0101303302142c3cc6fe9279db1516d5ce39f2a898cda5a175e1170d3236303333303131313732335a300c300a0603551d1504030a010130330214717948687509234be979e4b7dce6f31bef64b68c170d3236303333303131313732335a300c300a0603551d1504030a010130340215009d76ef2c39c136e8658b6e7396b1d7445a27631f170d3236303333303131313732335a300c300a0603551d1504030a01013034021500c3e025fca995f36f59b48467939e3e34e6361a6f170d3236303333303131313732335a300c300a0603551d1504030a010130340215008c5f6b3257da05b17429e2e61ba965d67330606a170d3236303333303131313732335a300c300a0603551d1504030a01013034021500a17c51722ec1e0c3278fe8bdf052059cbec4e648170d3236303333303131313732335a300c300a0603551d1504030a01013033021411c943b866fa04944e3057e5a67146596475a023170d3236303333303131313732335a300c300a0603551d1504030a01013034021500be6913785406155454a28885a515b3da5767d3a9170d3236303333303131313732335a300c300a0603551d1504030a0101303302140ac5ec91bd934c07b9ea41625e9cc09681002eb0170d3236303333303131313732335a300c300a0603551d1504030a0101303302146d51a0eabc1f9a1e9ddd5b36bdda1631ae6c182a170d3236303333303131313732335a300c300a0603551d1504030a01013034021500a52c5d71c4166b4fc0ded8b679951e5ee9193de5170d3236303333303131313732335a300c300a0603551d1504030a010130330214249779aedd85fcac93c8853516be5428c26b3bf8170d3236303333303131313732335a300c300a0603551d1504030a01013033021434ba4fd76bde5309210cf1dd1ffb494c638a9157170d3236303333303131313732335a300c300a0603551d1504030a010130330214043e04919daae13443248395094d2a2eacfc76fe170d3236303333303131313732335a300c300a0603551d1504030a01013033021447fc577d2d094cbdf270715ed6848a93855ad34b170d3236303333303131313732335a300c300a0603551d1504030a0101303302147d62a2f5e6f386e469653fffff045d0a8178e8e7170d3236303333303131313732335a300c300a0603551d1504030a01013034021500c4ed45fe026bb6a47eaec35ea80b7ef407ce062c170d3236303333303131313732335a300c300a0603551d1504030a01013034021500cf9831077a3ca4f1a2c56867bf55b18eccbeffd8170d3236303333303131313732335a300c300a0603551d1504030a0101303302146c2b81d7ea2e436720ce29f1d0b1ccb7a218600f170d3236303333303131313732335a300c300a0603551d1504030a0101a02f302d300a0603551d140403020101301f0603551d23041830168014956f5dcdbd1be1e94049c9d4f433ce01570bde54300a06082a8648ce3d040302034700304402207b73fb7aead70c4810b2784b470a00fc1606415b269bc067eb4a342e4ea4a5790220252bb69ca18f6a21a955ffad71d189ac97883e94910bead4417a52847ac28667", + "root_ca_crl": [48, 130, 1, 34, 48, 129, 200, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 104, 49, 26, 48, 24, 6, 3, 85, 4, 3, 12, 17, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, 82, 111, 111, 116, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 54, 48, 50, 50, 54, 49, 51, 48, 52, 48, 48, 90, 23, 13, 50, 55, 48, 50, 50, 54, 49, 51, 48, 52, 48, 48, 90, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 34, 101, 12, 214, 90, 157, 52, 137, 243, 131, 180, 149, 82, 191, 80, 27, 57, 39, 6, 172, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 73, 0, 48, 70, 2, 33, 0, 194, 82, 237, 89, 199, 149, 186, 43, 17, 73, 106, 74, 153, 117, 139, 184, 203, 195, 128, 161, 235, 187, 8, 101, 190, 105, 242, 196, 179, 139, 182, 64, 2, 33, 0, 154, 125, 139, 3, 96, 42, 158, 226, 214, 35, 34, 215, 89, 22, 109, 105, 51, 210, 77, 157, 250, 1, 171, 63, 222, 69, 32, 105, 29, 113, 91, 215], + "pck_crl": [48, 130, 13, 23, 48, 130, 12, 189, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 112, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, 80, 67, 75, 32, 80, 108, 97, 116, 102, 111, 114, 109, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 23, 13, 50, 54, 48, 57, 48, 54, 48, 48, 50, 57, 49, 51, 90, 48, 130, 11, 233, 48, 51, 2, 20, 111, 195, 78, 80, 35, 231, 40, 146, 52, 53, 214, 26, 164, 184, 60, 97, 129, 102, 173, 53, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 174, 110, 151, 21, 252, 161, 59, 135, 227, 51, 232, 38, 30, 214, 217, 144, 169, 38, 173, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 253, 96, 134, 72, 98, 156, 186, 115, 7, 139, 77, 73, 47, 75, 62, 167, 65, 173, 8, 205, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 249, 36, 24, 78, 29, 90, 253, 221, 115, 195, 214, 58, 18, 245, 232, 181, 115, 126, 86, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 177, 37, 121, 120, 207, 169, 204, 221, 7, 89, 171, 248, 197, 202, 114, 250, 227, 167, 138, 155, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 116, 254, 166, 20, 169, 114, 190, 14, 40, 67, 242, 5, 152, 53, 129, 30, 216, 114, 249, 179, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 249, 196, 239, 86, 179, 171, 72, 213, 119, 225, 8, 186, 237, 244, 191, 136, 1, 66, 20, 185, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 29, 224, 119, 143, 158, 95, 196, 242, 135, 143, 48, 214, 176, 124, 154, 48, 230, 179, 11, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 226, 66, 79, 151, 44, 234, 148, 255, 35, 153, 55, 244, 216, 12, 37, 2, 157, 214, 11, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 51, 25, 229, 16, 155, 100, 80, 125, 60, 241, 19, 44, 224, 3, 73, 239, 82, 115, 25, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 223, 8, 215, 86, 182, 106, 116, 151, 244, 59, 91, 181, 138, 218, 4, 211, 244, 247, 169, 55, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 40, 175, 72, 91, 108, 246, 126, 64, 154, 57, 213, 203, 90, 238, 69, 152, 247, 168, 250, 123, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 251, 139, 45, 174, 192, 146, 202, 218, 138, 169, 188, 79, 242, 241, 194, 13, 3, 70, 102, 140, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 72, 80, 172, 82, 189, 204, 105, 166, 166, 240, 88, 200, 188, 87, 187, 208, 181, 248, 100, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 153, 77, 211, 102, 111, 82, 117, 251, 128, 95, 149, 221, 2, 189, 80, 203, 38, 121, 216, 173, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 2, 19, 105, 0, 37, 34, 116, 217, 3, 94, 237, 245, 69, 116, 98, 250, 208, 239, 76, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 97, 242, 191, 115, 227, 155, 78, 4, 170, 39, 216, 1, 189, 115, 210, 67, 25, 181, 191, 128, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 57, 146, 190, 133, 27, 150, 144, 46, 255, 56, 149, 158, 108, 46, 255, 27, 6, 81, 164, 181, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 15, 218, 67, 160, 11, 104, 234, 121, 183, 194, 222, 174, 172, 11, 73, 139, 223, 178, 175, 144, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 99, 159, 19, 154, 80, 64, 253, 207, 241, 145, 232, 164, 251, 27, 240, 134, 237, 96, 57, 113, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 149, 157, 83, 63, 146, 73, 220, 30, 81, 53, 68, 205, 200, 48, 191, 25, 183, 241, 243, 1, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 122, 227, 119, 72, 169, 249, 18, 244, 198, 59, 167, 171, 7, 197, 147, 206, 29, 29, 17, 129, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 19, 136, 75, 51, 38, 153, 56, 193, 149, 170, 23, 15, 202, 117, 218, 23, 117, 56, 223, 11, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 133, 211, 201, 56, 27, 119, 167, 224, 77, 17, 156, 158, 90, 214, 116, 159, 243, 255, 171, 135, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 147, 136, 124, 164, 65, 30, 122, 146, 59, 209, 254, 210, 129, 155, 41, 73, 242, 1, 181, 180, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 152, 220, 98, 131, 147, 9, 150, 253, 139, 242, 58, 55, 172, 190, 38, 163, 190, 212, 87, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 102, 241, 167, 73, 72, 134, 103, 104, 156, 195, 144, 58, 197, 76, 102, 43, 113, 46, 115, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 175, 193, 54, 16, 189, 211, 108, 183, 152, 93, 16, 100, 129, 168, 128, 211, 160, 31, 218, 7, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 224, 75, 44, 51, 208, 54, 170, 201, 108, 166, 115, 191, 30, 154, 71, 182, 77, 92, 187, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 131, 217, 172, 141, 139, 181, 9, 209, 198, 200, 9, 173, 113, 46, 132, 48, 85, 158, 215, 243, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 121, 49, 253, 80, 181, 7, 28, 27, 191, 197, 183, 182, 222, 216, 180, 91, 157, 139, 133, 41, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 31, 162, 14, 41, 112, 189, 229, 213, 127, 123, 141, 223, 131, 57, 72, 78, 31, 29, 8, 35, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 30, 135, 178, 195, 179, 45, 141, 35, 228, 17, 206, 243, 65, 151, 185, 90, 240, 200, 173, 245, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 154, 253, 46, 233, 10, 71, 53, 80, 161, 103, 217, 150, 145, 20, 55, 199, 80, 45, 31, 9, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 68, 129, 176, 241, 23, 40, 161, 59, 105, 109, 62, 169, 199, 112, 160, 177, 94, 197, 141, 218, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 167, 133, 159, 87, 152, 46, 240, 230, 125, 55, 188, 142, 242, 239, 90, 200, 53, 255, 26, 169, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 103, 117, 59, 129, 228, 112, 144, 174, 167, 99, 251, 236, 76, 69, 73, 188, 219, 153, 51, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 191, 187, 122, 29, 156, 86, 129, 71, 225, 24, 182, 20, 247, 183, 110, 211, 239, 104, 223, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 44, 60, 198, 254, 146, 121, 219, 21, 22, 213, 206, 57, 242, 168, 152, 205, 165, 161, 117, 225, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 113, 121, 72, 104, 117, 9, 35, 75, 233, 121, 228, 183, 220, 230, 243, 27, 239, 100, 182, 140, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 118, 239, 44, 57, 193, 54, 232, 101, 139, 110, 115, 150, 177, 215, 68, 90, 39, 99, 31, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 195, 224, 37, 252, 169, 149, 243, 111, 89, 180, 132, 103, 147, 158, 62, 52, 230, 54, 26, 111, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 140, 95, 107, 50, 87, 218, 5, 177, 116, 41, 226, 230, 27, 169, 101, 214, 115, 48, 96, 106, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 161, 124, 81, 114, 46, 193, 224, 195, 39, 143, 232, 189, 240, 82, 5, 156, 190, 196, 230, 72, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 17, 201, 67, 184, 102, 250, 4, 148, 78, 48, 87, 229, 166, 113, 70, 89, 100, 117, 160, 35, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 190, 105, 19, 120, 84, 6, 21, 84, 84, 162, 136, 133, 165, 21, 179, 218, 87, 103, 211, 169, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 10, 197, 236, 145, 189, 147, 76, 7, 185, 234, 65, 98, 94, 156, 192, 150, 129, 0, 46, 176, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 109, 81, 160, 234, 188, 31, 154, 30, 157, 221, 91, 54, 189, 218, 22, 49, 174, 108, 24, 42, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 165, 44, 93, 113, 196, 22, 107, 79, 192, 222, 216, 182, 121, 149, 30, 94, 233, 25, 61, 229, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 151, 121, 174, 221, 133, 252, 172, 147, 200, 133, 53, 22, 190, 84, 40, 194, 107, 59, 248, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 186, 79, 215, 107, 222, 83, 9, 33, 12, 241, 221, 31, 251, 73, 76, 99, 138, 145, 87, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 4, 62, 4, 145, 157, 170, 225, 52, 67, 36, 131, 149, 9, 77, 42, 46, 172, 252, 118, 254, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 71, 252, 87, 125, 45, 9, 76, 189, 242, 112, 113, 94, 214, 132, 138, 147, 133, 90, 211, 75, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 125, 98, 162, 245, 230, 243, 134, 228, 105, 101, 63, 255, 255, 4, 93, 10, 129, 120, 232, 231, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 196, 237, 69, 254, 2, 107, 182, 164, 126, 174, 195, 94, 168, 11, 126, 244, 7, 206, 6, 44, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 207, 152, 49, 7, 122, 60, 164, 241, 162, 197, 104, 103, 191, 85, 177, 142, 204, 190, 255, 216, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 43, 129, 215, 234, 46, 67, 103, 32, 206, 41, 241, 208, 177, 204, 183, 162, 24, 96, 15, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 149, 111, 93, 205, 189, 27, 225, 233, 64, 73, 201, 212, 244, 51, 206, 1, 87, 11, 222, 84, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 33, 0, 238, 111, 7, 14, 49, 145, 234, 194, 121, 35, 98, 21, 229, 27, 92, 206, 192, 184, 252, 12, 1, 193, 81, 27, 188, 14, 90, 153, 227, 176, 87, 139, 2, 32, 65, 207, 14, 33, 10, 125, 66, 119, 141, 248, 67, 211, 169, 246, 2, 143, 151, 102, 229, 171, 114, 80, 176, 33, 219, 155, 251, 57, 222, 116, 166, 11], "tcb_info_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-03-30T10:40:05Z\",\"nextUpdate\":\"2026-04-29T10:40:05Z\",\"fmspc\":\"b0c06f000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":18,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2024-11-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2024-11-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-11-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", - "tcb_info_signature": "55b0c1b1e50436ea7528b95374ad0eb49b43499eac4a41da7852da74bb307163f3138c52603cb8b354072c20b9f45d618fd1908363e8a5b64ff0375f2f34ab22", + "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-07T08:49:47Z\",\"nextUpdate\":\"2026-09-06T08:49:47Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":19,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", + "tcb_info_signature": [15, 93, 222, 224, 153, 41, 123, 48, 158, 155, 65, 196, 206, 107, 186, 235, 246, 185, 156, 167, 166, 244, 130, 222, 143, 51, 200, 200, 229, 151, 142, 200, 173, 234, 138, 239, 168, 185, 146, 196, 170, 33, 128, 114, 92, 158, 119, 185, 30, 108, 235, 140, 112, 235, 50, 28, 3, 23, 148, 55, 184, 89, 36, 134], "qe_identity_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-03-30T11:16:36Z\",\"nextUpdate\":\"2026-04-29T11:16:36Z\",\"tcbEvaluationDataNumber\":18,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-11-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", - "qe_identity_signature": "39174d58fdd5ecc63c95a2e95728238e1b5a8a0610015f765cad5416b8ca2b2940a404b6fbb7d92be8f0522011452152a7d66344d5da64641207f27799ff589c" + "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-07T00:34:59Z\",\"nextUpdate\":\"2026-09-06T00:34:59Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", + "qe_identity_signature": [57, 36, 243, 212, 119, 60, 81, 154, 112, 130, 100, 167, 103, 141, 168, 59, 58, 98, 68, 81, 98, 171, 169, 110, 38, 225, 130, 214, 83, 65, 109, 226, 87, 46, 173, 184, 96, 43, 92, 61, 164, 132, 193, 128, 127, 165, 2, 249, 74, 25, 210, 254, 166, 31, 107, 92, 59, 151, 192, 23, 245, 68, 57, 53], + "pck_certificate_chain": "-----BEGIN CERTIFICATE-----\nMIIE8TCCBJagAwIBAgIUf2SbywkMVTJKU57/JwBp8EdhP04wCgYIKoZIzj0EAwIw\ncDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBDSyBQbGF0Zm9ybSBDQTEaMBgGA1UECgwR\nSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQI\nDAJDQTELMAkGA1UEBhMCVVMwHhcNMjUxMTA2MDczNzM0WhcNMzIxMTA2MDczNzM0\nWjBwMSIwIAYDVQQDDBlJbnRlbCBTR1ggUENLIENlcnRpZmljYXRlMRowGAYDVQQK\nDBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV\nBAgMAkNBMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGpv\n0YuYrqAuSKBzKlub6mL+rvfD5AjYO3QNgfWztg4em1EGBVkGlWvduB0XQSE/sxGD\nmSvKo9t3CrOPC4SU6X6jggMMMIIDCDAfBgNVHSMEGDAWgBSVb13NvRvh6UBJydT0\nM84BVwveVDBrBgNVHR8EZDBiMGCgXqBchlpodHRwczovL2FwaS50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL3NneC9jZXJ0aWZpY2F0aW9uL3Y0L3Bja2NybD9jYT1w\nbGF0Zm9ybSZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFG3n6S+KxN6t+HI8Gp96PkuZ\niWsZMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIICOQYJKoZIhvhNAQ0B\nBIICKjCCAiYwHgYKKoZIhvhNAQ0BAQQQ0gjfsQAjRq4btO8qPAVSkjCCAWMGCiqG\nSIb4TQENAQIwggFTMBAGCyqGSIb4TQENAQIBAgEEMBAGCyqGSIb4TQENAQICAgEE\nMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgECMBAGCyqGSIb4TQEN\nAQIFAgEEMBAGCyqGSIb4TQENAQIGAgEBMBAGCyqGSIb4TQENAQIHAgEAMBAGCyqG\nSIb4TQENAQIIAgEFMBAGCyqGSIb4TQENAQIJAgEAMBAGCyqGSIb4TQENAQIKAgEA\nMBAGCyqGSIb4TQENAQILAgEAMBAGCyqGSIb4TQENAQIMAgEAMBAGCyqGSIb4TQEN\nAQINAgEAMBAGCyqGSIb4TQENAQIOAgEAMBAGCyqGSIb4TQENAQIPAgEAMBAGCyqG\nSIb4TQENAQIQAgEAMBAGCyqGSIb4TQENAQIRAgELMB8GCyqGSIb4TQENAQISBBAE\nBAICBAEABQAAAAAAAAAAMBAGCiqGSIb4TQENAQMEAgAAMBQGCiqGSIb4TQENAQQE\nBrDAbwAAADAPBgoqhkiG+E0BDQEFCgEBMB4GCiqGSIb4TQENAQYEEDa9htA8AJ/Z\n2FmaL5Jq/KEwRAYKKoZIhvhNAQ0BBzA2MBAGCyqGSIb4TQENAQcBAQH/MBAGCyqG\nSIb4TQENAQcCAQH/MBAGCyqGSIb4TQENAQcDAQH/MAoGCCqGSM49BAMCA0kAMEYC\nIQCFG1YAb3eXFte853ClVBnhlCfDyc572ZXEqax4UccSawIhAOn0VNKTZmAxUF4n\nwRkSFh4qFJ3aUlzFoPQT3xIf7kFD\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\u0000" }, "tcb_info": { "mrtd": "f06dfda6dce1cf904d4e2bab1dc370634cf95cefa2ceb2de2eee127c9382698090d7a4a13e14c536ec6c9c3c8fa87077", "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "b7662ac19c27af648a939be042684bbdb43bb3dddf4cd17bb21f4d455ab1926c6ee57038152fc46ddea392c47eb2af27", + "rtmr3": "8050d4769527c84cb066078854ef8eb50ea7b150e072eeec7007240aca01b556041273ea3d20a1b1d48736f650ce13f0", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "cb9b2d6204f5e44238b75f69e3a3069550734c0d99ebdd3be507c238a261d8fa", + "compose_hash": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1774945636\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:1f54b55bad22c45067228a9262bc6377e393ca1a07edb64e691e80704f49b74e\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786102851\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\n# Test-asset collection hook, sourced by the CVM's app-compose.sh before the\\n# node starts. The node generates its NEAR signer key in-enclave, so exporting\\n# that key is the only way to check the fixture keypair into the repo next to\\n# the quote it is bound to (near/mpc #3787).\\n#\\n# The key appears only after the node starts, i.e. after this hook returns, so\\n# the wait runs as its own systemd unit: a plain background process would be\\n# reaped with app-compose.service's cgroup. The copy target is the CVM's\\n# host-shared dir, which the host sees as run/vm//shared/.\\n#\\n# The guest userland is BusyBox, so the wait loop sticks to shell built-ins and\\n# globs (no find/head, whose GNU options BusyBox rejects).\\n#\\n# Only ever use this on a throwaway localnet CVM: it exports a private key.\\n\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\nEXFIL=/etc/fixture-exfil.sh\\n\\ncat > \\\"$EXFIL\\\" <<'EOF'\\n#!/bin/sh\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\ni=0\\nwhile [ \\\"$i\\\" -lt 900 ]; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n if [ -f \\\"$f\\\" ]; then\\n cp \\\"$f\\\" \\\"$SHARED/fixture-secrets.json\\\" 2>/dev/null\\n {\\n echo \\\"FIXTURE-SECRETS-BEGIN $f\\\"\\n cat \\\"$f\\\"\\n echo \\\"\\\"\\n echo \\\"FIXTURE-SECRETS-END\\\"\\n } > \\\"$CONSOLE\\\" 2>&1\\n exit 0\\n fi\\n done\\n i=$((i + 1))\\n sleep 2\\ndone\\necho \\\"FIXTURE-SECRETS-TIMEOUT\\\" > \\\"$CONSOLE\\\" 2>&1\\nEOF\\nchmod +x \\\"$EXFIL\\\" 2>/dev/null\\n\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Unit]\\nDescription=Export the MPC node signer key for test-asset collection\\n[Service]\\nType=oneshot\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEOF\\n\\nsystemctl daemon-reload >/dev/null 2>&1\\nsystemctl start --no-block fixture-exfil.service >/dev/null 2>&1\\n\\n{\\n echo \\\"FIXTURE-DIAG-BEGIN\\\"\\n echo \\\"exfil_script=$([ -f \\\"$EXFIL\\\" ] && echo present || echo missing)\\\"\\n echo \\\"unit_state=$(systemctl is-active fixture-exfil.service 2>&1)\\\"\\n echo \\\"shared_writable=$([ -w \\\"$SHARED\\\" ] && echo yes || echo no)\\\"\\n echo \\\"FIXTURE-DIAG-END\\\"\\n} > \\\"$CONSOLE\\\" 2>&1\\n\"\n}", "event_log": [ { "imr": 0, @@ -177,16 +178,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "8f4219433b1fbb548e8e3c9c0a308a09888871da6b0472f8b2057d14846b33f66d674ebaa5829f26e9ffb3d2745eb5ce", + "digest": "970c96ea5f1ea46650645363f1716fd4e4260c92f614a6af308d4ca2e352b4dbd3d8f326e5a513c20b3029163284257e", "event": "app-id", - "event_payload": "cb9b2d6204f5e44238b75f69e3a3069550734c0d" + "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfaf" }, { "imr": 3, "event_type": 134217729, - "digest": "f53085ad730605df556bbe4617e942a89186705897eac8974656be41ddcc516a08c4d2b9135fbf8a0f25836c26e1c0d3", + "digest": "6d4e926546694d6e8acc53d46b216cde12d3a60cd3b60550ab7db7f4920fc42c304f8af924e08f96c108a7f7076cf02a", "event": "compose-hash", - "event_payload": "cb9b2d6204f5e44238b75f69e3a3069550734c0d99ebdd3be507c238a261d8fa" + "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a" }, { "imr": 3, @@ -226,9 +227,9 @@ { "imr": 3, "event_type": 134217729, - "digest": "9aed81f5b1af85f768ef6873ed6f997f55f37de951cca18f5daa35890ab9e5573314d2e0cd188a6913dd4ab6f5455678", + "digest": "0405a5706797115cdcccb66841205179fa5c2d989ad42fee2e2fab4c5b52bb6d9aa9bf8a86755d37e8566fdaabebc468", "event": "mpc-image-digest", - "event_payload": "6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980" + "event_payload": "564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3" } ] } diff --git a/crates/test-utils/assets/quote.json b/crates/test-utils/assets/quote.json index fa4b32ba10..b4a18b209c 100644 --- a/crates/test-utils/assets/quote.json +++ b/crates/test-utils/assets/quote.json @@ -1 +1 @@ -[4,0,2,0,129,0,0,0,0,0,0,0,147,154,114,51,247,156,76,169,148,10,13,179,149,127,6,7,61,153,138,108,16,87,107,253,246,246,237,142,155,133,233,50,0,0,0,0,11,1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,123,240,99,40,14,148,251,5,31,93,215,177,252,89,206,154,172,66,187,150,29,248,212,75,112,156,155,15,248,122,123,77,246,72,101,123,166,209,24,149,137,254,171,29,90,60,154,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,231,2,6,0,0,0,0,0,240,109,253,166,220,225,207,144,77,78,43,171,29,195,112,99,76,249,92,239,162,206,178,222,46,238,18,124,147,130,105,128,144,215,164,161,62,20,197,54,236,108,156,60,143,168,112,119,1,203,155,45,98,4,245,228,66,56,183,95,105,227,163,6,149,80,115,76,13,153,235,221,59,229,7,194,56,162,97,216,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,115,190,47,112,190,239,183,11,72,166,16,158,237,71,21,215,39,13,70,131,179,191,53,111,162,95,175,191,26,167,110,57,233,18,126,110,104,140,205,169,139,218,177,212,212,127,70,181,152,253,233,73,20,39,52,27,196,104,59,117,209,13,62,54,119,10,243,163,106,105,84,216,182,183,178,42,166,99,88,241,62,31,23,46,81,183,214,230,113,13,153,168,216,83,47,200,18,212,43,255,241,199,83,130,233,26,55,200,103,171,17,123,151,235,94,141,103,151,72,137,40,234,56,229,253,56,181,237,47,135,217,97,61,57,37,7,241,195,175,148,101,124,147,183,102,42,193,156,39,175,100,138,147,155,224,66,104,75,189,180,59,179,221,223,76,209,123,178,31,77,69,90,177,146,108,110,229,112,56,21,47,196,109,222,163,146,196,126,178,175,39,0,1,78,229,231,14,134,29,178,154,149,34,78,72,164,124,1,106,176,60,97,35,131,51,49,154,247,97,69,147,205,21,91,165,49,7,62,221,105,146,23,66,190,177,197,16,255,67,57,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,204,16,0,0,153,226,16,217,157,80,127,207,149,9,36,136,238,6,250,213,16,210,1,238,63,83,96,249,94,59,192,29,136,193,241,50,69,183,128,24,46,174,20,247,214,21,157,220,144,243,164,217,138,186,115,231,51,87,174,173,237,144,211,118,7,186,23,33,142,188,151,224,189,139,21,116,87,28,157,151,225,226,250,218,147,80,231,144,252,223,62,103,176,31,51,101,181,44,82,180,72,148,151,10,88,144,81,87,230,135,174,102,165,143,241,229,60,148,151,208,187,151,100,64,82,171,52,1,40,143,31,160,6,0,70,16,0,0,4,4,25,27,4,255,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,231,0,0,0,0,0,0,0,229,163,167,181,216,48,194,149,59,152,83,76,108,89,163,163,79,220,52,233,51,247,245,137,143,10,133,207,8,132,107,202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,158,42,124,111,148,143,23,71,78,52,167,252,67,237,3,15,124,21,99,241,186,189,223,99,64,200,46,14,84,168,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,98,66,167,203,62,30,139,2,195,192,57,51,40,206,207,77,159,207,61,144,77,52,130,175,199,184,139,101,54,6,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,1,121,119,53,12,242,234,97,244,139,210,240,161,221,87,50,53,22,62,187,93,234,174,243,37,140,227,92,65,153,44,120,88,139,241,175,11,63,135,233,6,77,16,70,191,18,226,109,1,37,18,132,34,76,170,41,121,69,128,18,239,72,153,32,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,5,0,94,14,0,0,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,69,56,84,67,67,66,74,97,103,65,119,73,66,65,103,73,85,102,50,83,98,121,119,107,77,86,84,74,75,85,53,55,47,74,119,66,112,56,69,100,104,80,48,52,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,99,68,69,105,77,67,65,71,65,49,85,69,65,119,119,90,83,87,53,48,90,87,119,103,85,48,100,89,73,70,66,68,83,121,66,81,98,71,70,48,90,109,57,121,98,83,66,68,81,84,69,97,77,66,103,71,65,49,85,69,67,103,119,82,10,83,87,53,48,90,87,119,103,81,50,57,121,99,71,57,121,89,88,82,112,98,50,52,120,70,68,65,83,66,103,78,86,66,65,99,77,67,49,78,104,98,110,82,104,73,69,78,115,89,88,74,104,77,81,115,119,67,81,89,68,86,81,81,73,10,68,65,74,68,81,84,69,76,77,65,107,71,65,49,85,69,66,104,77,67,86,86,77,119,72,104,99,78,77,106,85,120,77,84,65,50,77,68,99,122,78,122,77,48,87,104,99,78,77,122,73,120,77,84,65,50,77,68,99,122,78,122,77,48,10,87,106,66,119,77,83,73,119,73,65,89,68,86,81,81,68,68,66,108,74,98,110,82,108,98,67,66,84,82,49,103,103,85,69,78,76,73,69,78,108,99,110,82,112,90,109,108,106,89,88,82,108,77,82,111,119,71,65,89,68,86,81,81,75,10,68,66,70,74,98,110,82,108,98,67,66,68,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,10,66,65,103,77,65,107,78,66,77,81,115,119,67,81,89,68,86,81,81,71,69,119,74,86,85,122,66,90,77,66,77,71,66,121,113,71,83,77,52,57,65,103,69,71,67,67,113,71,83,77,52,57,65,119,69,72,65,48,73,65,66,71,112,118,10,48,89,117,89,114,113,65,117,83,75,66,122,75,108,117,98,54,109,76,43,114,118,102,68,53,65,106,89,79,51,81,78,103,102,87,122,116,103,52,101,109,49,69,71,66,86,107,71,108,87,118,100,117,66,48,88,81,83,69,47,115,120,71,68,10,109,83,118,75,111,57,116,51,67,114,79,80,67,52,83,85,54,88,54,106,103,103,77,77,77,73,73,68,67,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,83,86,98,49,51,78,118,82,118,104,54,85,66,74,121,100,84,48,10,77,56,52,66,86,119,118,101,86,68,66,114,66,103,78,86,72,82,56,69,90,68,66,105,77,71,67,103,88,113,66,99,104,108,112,111,100,72,82,119,99,122,111,118,76,50,70,119,97,83,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,51,78,110,101,67,57,106,90,88,74,48,97,87,90,112,89,50,70,48,97,87,57,117,76,51,89,48,76,51,66,106,97,50,78,121,98,68,57,106,89,84,49,119,10,98,71,70,48,90,109,57,121,98,83,90,108,98,109,78,118,90,71,108,117,90,122,49,107,90,88,73,119,72,81,89,68,86,82,48,79,66,66,89,69,70,71,51,110,54,83,43,75,120,78,54,116,43,72,73,56,71,112,57,54,80,107,117,90,10,105,87,115,90,77,65,52,71,65,49,85,100,68,119,69,66,47,119,81,69,65,119,73,71,119,68,65,77,66,103,78,86,72,82,77,66,65,102,56,69,65,106,65,65,77,73,73,67,79,81,89,74,75,111,90,73,104,118,104,78,65,81,48,66,10,66,73,73,67,75,106,67,67,65,105,89,119,72,103,89,75,75,111,90,73,104,118,104,78,65,81,48,66,65,81,81,81,48,103,106,102,115,81,65,106,82,113,52,98,116,79,56,113,80,65,86,83,107,106,67,67,65,87,77,71,67,105,113,71,10,83,73,98,52,84,81,69,78,65,81,73,119,103,103,70,84,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,66,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,67,65,103,69,69,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,68,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,69,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,70,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,71,65,103,69,66,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,72,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,73,65,103,69,70,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,74,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,75,65,103,69,65,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,76,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,77,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,78,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,79,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,80,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,81,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,82,65,103,69,76,77,66,56,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,83,66,66,65,69,10,66,65,73,67,66,65,69,65,66,81,65,65,65,65,65,65,65,65,65,65,77,66,65,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,77,69,65,103,65,65,77,66,81,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,81,69,10,66,114,68,65,98,119,65,65,65,68,65,80,66,103,111,113,104,107,105,71,43,69,48,66,68,81,69,70,67,103,69,66,77,66,52,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,89,69,69,68,97,57,104,116,65,56,65,74,47,90,10,50,70,109,97,76,53,74,113,47,75,69,119,82,65,89,75,75,111,90,73,104,118,104,78,65,81,48,66,66,122,65,50,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,66,65,81,72,47,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,99,67,65,81,72,47,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,68,65,81,72,47,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,65,48,107,65,77,69,89,67,10,73,81,67,70,71,49,89,65,98,51,101,88,70,116,101,56,53,51,67,108,86,66,110,104,108,67,102,68,121,99,53,55,50,90,88,69,113,97,120,52,85,99,99,83,97,119,73,104,65,79,110,48,86,78,75,84,90,109,65,120,85,70,52,110,10,119,82,107,83,70,104,52,113,70,74,51,97,85,108,122,70,111,80,81,84,51,120,73,102,55,107,70,68,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,108,106,67,67,65,106,50,103,65,119,73,66,65,103,73,86,65,74,86,118,88,99,50,57,71,43,72,112,81,69,110,74,49,80,81,122,122,103,70,88,67,57,53,85,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,10,77,71,103,120,71,106,65,89,66,103,78,86,66,65,77,77,69,85,108,117,100,71,86,115,73,70,78,72,87,67,66,83,98,50,57,48,73,69,78,66,77,82,111,119,71,65,89,68,86,81,81,75,68,66,70,74,98,110,82,108,98,67,66,68,10,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,66,65,103,77,65,107,78,66,77,81,115,119,10,67,81,89,68,86,81,81,71,69,119,74,86,85,122,65,101,70,119,48,120,79,68,65,49,77,106,69,120,77,68,85,119,77,84,66,97,70,119,48,122,77,122,65,49,77,106,69,120,77,68,85,119,77,84,66,97,77,72,65,120,73,106,65,103,10,66,103,78,86,66,65,77,77,71,85,108,117,100,71,86,115,73,70,78,72,87,67,66,81,81,48,115,103,85,71,120,104,100,71,90,118,99,109,48,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,10,73,69,78,118,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,10,67,122,65,74,66,103,78,86,66,65,89,84,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,78,83,66,47,55,116,50,49,108,88,83,79,10,50,67,117,122,112,120,119,55,52,101,74,66,55,50,69,121,68,71,103,87,53,114,88,67,116,120,50,116,86,84,76,113,54,104,75,107,54,122,43,85,105,82,90,67,110,113,82,55,112,115,79,118,103,113,70,101,83,120,108,109,84,108,74,108,10,101,84,109,105,50,87,89,122,51,113,79,66,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,10,66,103,78,86,72,82,56,69,83,122,66,74,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,108,87,57,100,10,122,98,48,98,52,101,108,65,83,99,110,85,57,68,80,79,65,86,99,76,51,108,81,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,10,65,102,56,67,65,81,65,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,68,82,119,65,119,82,65,73,103,88,115,86,107,105,48,119,43,105,54,86,89,71,87,51,85,70,47,50,50,117,97,88,101,48,89,74,68,106,49,85,101,10,110,65,43,84,106,68,49,97,105,53,99,67,73,67,89,98,49,83,65,109,68,53,120,107,102,84,86,112,118,111,52,85,111,121,105,83,89,120,114,68,87,76,109,85,82,52,67,73,57,78,75,121,102,80,78,43,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,106,122,67,67,65,106,83,103,65,119,73,66,65,103,73,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,85,114,57,81,71,122,107,110,66,113,119,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,97,68,69,97,77,66,103,71,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,10,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,10,66,103,78,86,66,65,89,84,65,108,86,84,77,66,52,88,68,84,69,52,77,68,85,121,77,84,69,119,78,68,85,120,77,70,111,88,68,84,81,53,77,84,73,122,77,84,73,122,78,84,107,49,79,86,111,119,97,68,69,97,77,66,103,71,10,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,99,110,66,118,99,109,70,48,10,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,66,103,78,86,66,65,89,84,10,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,67,54,110,69,119,77,68,73,89,90,79,106,47,105,80,87,115,67,122,97,69,75,105,55,10,49,79,105,79,83,76,82,70,104,87,71,106,98,110,66,86,74,102,86,110,107,89,52,117,51,73,106,107,68,89,89,76,48,77,120,79,52,109,113,115,121,89,106,108,66,97,108,84,86,89,120,70,80,50,115,74,66,75,53,122,108,75,79,66,10,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,66,103,78,86,72,82,56,69,83,122,66,74,10,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,100,109,108,106,90,88,77,117,97,87,53,48,10,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,10,85,114,57,81,71,122,107,110,66,113,119,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,65,102,56,67,65,81,69,119,67,103,89,73,10,75,111,90,73,122,106,48,69,65,119,73,68,83,81,65,119,82,103,73,104,65,79,87,47,53,81,107,82,43,83,57,67,105,83,68,99,78,111,111,119,76,117,80,82,76,115,87,71,102,47,89,105,55,71,83,88,57,52,66,103,119,84,119,103,10,65,105,69,65,52,74,48,108,114,72,111,77,115,43,88,111,53,111,47,115,88,54,79,57,81,87,120,72,82,65,118,90,85,71,79,100,82,81,55,99,118,113,82,88,97,113,73,61,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] +[4,0,2,0,129,0,0,0,0,0,0,0,147,154,114,51,247,156,76,169,148,10,13,179,149,127,6,7,61,153,138,108,16,87,107,253,246,246,237,142,155,133,233,50,0,0,0,0,11,1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,123,240,99,40,14,148,251,5,31,93,215,177,252,89,206,154,172,66,187,150,29,248,212,75,112,156,155,15,248,122,123,77,246,72,101,123,166,209,24,149,137,254,171,29,90,60,154,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,231,2,6,0,0,0,0,0,240,109,253,166,220,225,207,144,77,78,43,171,29,195,112,99,76,249,92,239,162,206,178,222,46,238,18,124,147,130,105,128,144,215,164,161,62,20,197,54,236,108,156,60,143,168,112,119,1,198,119,92,77,155,183,39,60,162,28,213,75,230,182,161,135,147,40,223,175,190,181,80,246,149,123,130,30,33,47,13,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,115,190,47,112,190,239,183,11,72,166,16,158,237,71,21,215,39,13,70,131,179,191,53,111,162,95,175,191,26,167,110,57,233,18,126,110,104,140,205,169,139,218,177,212,212,127,70,181,152,253,233,73,20,39,52,27,196,104,59,117,209,13,62,54,119,10,243,163,106,105,84,216,182,183,178,42,166,99,88,241,62,31,23,46,81,183,214,230,113,13,153,168,216,83,47,200,18,212,43,255,241,199,83,130,233,26,55,200,103,171,17,123,151,235,94,141,103,151,72,137,40,234,56,229,253,56,181,237,47,135,217,97,61,57,37,7,241,195,175,148,101,124,147,128,80,212,118,149,39,200,76,176,102,7,136,84,239,142,181,14,167,177,80,224,114,238,236,112,7,36,10,202,1,181,86,4,18,115,234,61,32,161,177,212,135,54,246,80,206,19,240,0,1,209,86,189,198,94,91,239,231,225,97,127,216,191,206,198,221,63,29,165,128,118,189,230,104,208,199,60,227,182,36,106,78,137,8,32,54,198,0,97,223,254,251,217,148,182,171,98,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,204,16,0,0,200,71,196,122,109,85,63,3,18,209,86,2,141,242,185,138,228,240,253,45,106,250,173,199,245,16,11,112,18,49,38,99,19,4,193,57,36,61,190,193,116,80,40,89,26,63,23,196,24,182,105,144,93,83,116,164,177,5,157,5,162,224,199,103,142,188,151,224,189,139,21,116,87,28,157,151,225,226,250,218,147,80,231,144,252,223,62,103,176,31,51,101,181,44,82,180,72,148,151,10,88,144,81,87,230,135,174,102,165,143,241,229,60,148,151,208,187,151,100,64,82,171,52,1,40,143,31,160,6,0,70,16,0,0,4,4,25,27,4,255,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,231,0,0,0,0,0,0,0,229,163,167,181,216,48,194,149,59,152,83,76,108,89,163,163,79,220,52,233,51,247,245,137,143,10,133,207,8,132,107,202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,158,42,124,111,148,143,23,71,78,52,167,252,67,237,3,15,124,21,99,241,186,189,223,99,64,200,46,14,84,168,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,98,66,167,203,62,30,139,2,195,192,57,51,40,206,207,77,159,207,61,144,77,52,130,175,199,184,139,101,54,6,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,38,110,158,253,119,108,12,78,190,20,247,2,106,23,209,8,177,82,221,154,125,85,141,105,35,22,81,130,94,61,208,85,132,184,18,62,136,70,151,251,120,116,84,85,102,215,7,27,232,230,233,88,107,188,209,227,153,207,76,194,69,125,91,32,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,5,0,94,14,0,0,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,69,56,84,67,67,66,74,97,103,65,119,73,66,65,103,73,85,102,50,83,98,121,119,107,77,86,84,74,75,85,53,55,47,74,119,66,112,56,69,100,104,80,48,52,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,99,68,69,105,77,67,65,71,65,49,85,69,65,119,119,90,83,87,53,48,90,87,119,103,85,48,100,89,73,70,66,68,83,121,66,81,98,71,70,48,90,109,57,121,98,83,66,68,81,84,69,97,77,66,103,71,65,49,85,69,67,103,119,82,10,83,87,53,48,90,87,119,103,81,50,57,121,99,71,57,121,89,88,82,112,98,50,52,120,70,68,65,83,66,103,78,86,66,65,99,77,67,49,78,104,98,110,82,104,73,69,78,115,89,88,74,104,77,81,115,119,67,81,89,68,86,81,81,73,10,68,65,74,68,81,84,69,76,77,65,107,71,65,49,85,69,66,104,77,67,86,86,77,119,72,104,99,78,77,106,85,120,77,84,65,50,77,68,99,122,78,122,77,48,87,104,99,78,77,122,73,120,77,84,65,50,77,68,99,122,78,122,77,48,10,87,106,66,119,77,83,73,119,73,65,89,68,86,81,81,68,68,66,108,74,98,110,82,108,98,67,66,84,82,49,103,103,85,69,78,76,73,69,78,108,99,110,82,112,90,109,108,106,89,88,82,108,77,82,111,119,71,65,89,68,86,81,81,75,10,68,66,70,74,98,110,82,108,98,67,66,68,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,10,66,65,103,77,65,107,78,66,77,81,115,119,67,81,89,68,86,81,81,71,69,119,74,86,85,122,66,90,77,66,77,71,66,121,113,71,83,77,52,57,65,103,69,71,67,67,113,71,83,77,52,57,65,119,69,72,65,48,73,65,66,71,112,118,10,48,89,117,89,114,113,65,117,83,75,66,122,75,108,117,98,54,109,76,43,114,118,102,68,53,65,106,89,79,51,81,78,103,102,87,122,116,103,52,101,109,49,69,71,66,86,107,71,108,87,118,100,117,66,48,88,81,83,69,47,115,120,71,68,10,109,83,118,75,111,57,116,51,67,114,79,80,67,52,83,85,54,88,54,106,103,103,77,77,77,73,73,68,67,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,83,86,98,49,51,78,118,82,118,104,54,85,66,74,121,100,84,48,10,77,56,52,66,86,119,118,101,86,68,66,114,66,103,78,86,72,82,56,69,90,68,66,105,77,71,67,103,88,113,66,99,104,108,112,111,100,72,82,119,99,122,111,118,76,50,70,119,97,83,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,51,78,110,101,67,57,106,90,88,74,48,97,87,90,112,89,50,70,48,97,87,57,117,76,51,89,48,76,51,66,106,97,50,78,121,98,68,57,106,89,84,49,119,10,98,71,70,48,90,109,57,121,98,83,90,108,98,109,78,118,90,71,108,117,90,122,49,107,90,88,73,119,72,81,89,68,86,82,48,79,66,66,89,69,70,71,51,110,54,83,43,75,120,78,54,116,43,72,73,56,71,112,57,54,80,107,117,90,10,105,87,115,90,77,65,52,71,65,49,85,100,68,119,69,66,47,119,81,69,65,119,73,71,119,68,65,77,66,103,78,86,72,82,77,66,65,102,56,69,65,106,65,65,77,73,73,67,79,81,89,74,75,111,90,73,104,118,104,78,65,81,48,66,10,66,73,73,67,75,106,67,67,65,105,89,119,72,103,89,75,75,111,90,73,104,118,104,78,65,81,48,66,65,81,81,81,48,103,106,102,115,81,65,106,82,113,52,98,116,79,56,113,80,65,86,83,107,106,67,67,65,87,77,71,67,105,113,71,10,83,73,98,52,84,81,69,78,65,81,73,119,103,103,70,84,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,66,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,67,65,103,69,69,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,68,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,69,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,70,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,71,65,103,69,66,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,72,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,73,65,103,69,70,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,74,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,75,65,103,69,65,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,76,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,77,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,78,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,79,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,80,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,81,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,82,65,103,69,76,77,66,56,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,83,66,66,65,69,10,66,65,73,67,66,65,69,65,66,81,65,65,65,65,65,65,65,65,65,65,77,66,65,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,77,69,65,103,65,65,77,66,81,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,81,69,10,66,114,68,65,98,119,65,65,65,68,65,80,66,103,111,113,104,107,105,71,43,69,48,66,68,81,69,70,67,103,69,66,77,66,52,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,89,69,69,68,97,57,104,116,65,56,65,74,47,90,10,50,70,109,97,76,53,74,113,47,75,69,119,82,65,89,75,75,111,90,73,104,118,104,78,65,81,48,66,66,122,65,50,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,66,65,81,72,47,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,99,67,65,81,72,47,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,68,65,81,72,47,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,65,48,107,65,77,69,89,67,10,73,81,67,70,71,49,89,65,98,51,101,88,70,116,101,56,53,51,67,108,86,66,110,104,108,67,102,68,121,99,53,55,50,90,88,69,113,97,120,52,85,99,99,83,97,119,73,104,65,79,110,48,86,78,75,84,90,109,65,120,85,70,52,110,10,119,82,107,83,70,104,52,113,70,74,51,97,85,108,122,70,111,80,81,84,51,120,73,102,55,107,70,68,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,108,106,67,67,65,106,50,103,65,119,73,66,65,103,73,86,65,74,86,118,88,99,50,57,71,43,72,112,81,69,110,74,49,80,81,122,122,103,70,88,67,57,53,85,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,10,77,71,103,120,71,106,65,89,66,103,78,86,66,65,77,77,69,85,108,117,100,71,86,115,73,70,78,72,87,67,66,83,98,50,57,48,73,69,78,66,77,82,111,119,71,65,89,68,86,81,81,75,68,66,70,74,98,110,82,108,98,67,66,68,10,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,66,65,103,77,65,107,78,66,77,81,115,119,10,67,81,89,68,86,81,81,71,69,119,74,86,85,122,65,101,70,119,48,120,79,68,65,49,77,106,69,120,77,68,85,119,77,84,66,97,70,119,48,122,77,122,65,49,77,106,69,120,77,68,85,119,77,84,66,97,77,72,65,120,73,106,65,103,10,66,103,78,86,66,65,77,77,71,85,108,117,100,71,86,115,73,70,78,72,87,67,66,81,81,48,115,103,85,71,120,104,100,71,90,118,99,109,48,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,10,73,69,78,118,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,10,67,122,65,74,66,103,78,86,66,65,89,84,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,78,83,66,47,55,116,50,49,108,88,83,79,10,50,67,117,122,112,120,119,55,52,101,74,66,55,50,69,121,68,71,103,87,53,114,88,67,116,120,50,116,86,84,76,113,54,104,75,107,54,122,43,85,105,82,90,67,110,113,82,55,112,115,79,118,103,113,70,101,83,120,108,109,84,108,74,108,10,101,84,109,105,50,87,89,122,51,113,79,66,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,10,66,103,78,86,72,82,56,69,83,122,66,74,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,108,87,57,100,10,122,98,48,98,52,101,108,65,83,99,110,85,57,68,80,79,65,86,99,76,51,108,81,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,10,65,102,56,67,65,81,65,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,68,82,119,65,119,82,65,73,103,88,115,86,107,105,48,119,43,105,54,86,89,71,87,51,85,70,47,50,50,117,97,88,101,48,89,74,68,106,49,85,101,10,110,65,43,84,106,68,49,97,105,53,99,67,73,67,89,98,49,83,65,109,68,53,120,107,102,84,86,112,118,111,52,85,111,121,105,83,89,120,114,68,87,76,109,85,82,52,67,73,57,78,75,121,102,80,78,43,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,106,122,67,67,65,106,83,103,65,119,73,66,65,103,73,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,85,114,57,81,71,122,107,110,66,113,119,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,97,68,69,97,77,66,103,71,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,10,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,10,66,103,78,86,66,65,89,84,65,108,86,84,77,66,52,88,68,84,69,52,77,68,85,121,77,84,69,119,78,68,85,120,77,70,111,88,68,84,81,53,77,84,73,122,77,84,73,122,78,84,107,49,79,86,111,119,97,68,69,97,77,66,103,71,10,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,99,110,66,118,99,109,70,48,10,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,66,103,78,86,66,65,89,84,10,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,67,54,110,69,119,77,68,73,89,90,79,106,47,105,80,87,115,67,122,97,69,75,105,55,10,49,79,105,79,83,76,82,70,104,87,71,106,98,110,66,86,74,102,86,110,107,89,52,117,51,73,106,107,68,89,89,76,48,77,120,79,52,109,113,115,121,89,106,108,66,97,108,84,86,89,120,70,80,50,115,74,66,75,53,122,108,75,79,66,10,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,66,103,78,86,72,82,56,69,83,122,66,74,10,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,100,109,108,106,90,88,77,117,97,87,53,48,10,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,10,85,114,57,81,71,122,107,110,66,113,119,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,65,102,56,67,65,81,69,119,67,103,89,73,10,75,111,90,73,122,106,48,69,65,119,73,68,83,81,65,119,82,103,73,104,65,79,87,47,53,81,107,82,43,83,57,67,105,83,68,99,78,111,111,119,76,117,80,82,76,115,87,71,102,47,89,105,55,71,83,88,57,52,66,103,119,84,119,103,10,65,105,69,65,52,74,48,108,114,72,111,77,115,43,88,111,53,111,47,115,88,54,79,57,81,87,120,72,82,65,118,90,85,71,79,100,82,81,55,99,118,113,82,88,97,113,73,61,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] diff --git a/crates/test-utils/assets/tcb_info.json b/crates/test-utils/assets/tcb_info.json index f1c777e178..46da8f1ceb 100644 --- a/crates/test-utils/assets/tcb_info.json +++ b/crates/test-utils/assets/tcb_info.json @@ -3,11 +3,11 @@ "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "b7662ac19c27af648a939be042684bbdb43bb3dddf4cd17bb21f4d455ab1926c6ee57038152fc46ddea392c47eb2af27", + "rtmr3": "8050d4769527c84cb066078854ef8eb50ea7b150e072eeec7007240aca01b556041273ea3d20a1b1d48736f650ce13f0", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "cb9b2d6204f5e44238b75f69e3a3069550734c0d99ebdd3be507c238a261d8fa", + "compose_hash": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1774945636\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:1f54b55bad22c45067228a9262bc6377e393ca1a07edb64e691e80704f49b74e\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786102851\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\n# Test-asset collection hook, sourced by the CVM's app-compose.sh before the\\n# node starts. The node generates its NEAR signer key in-enclave, so exporting\\n# that key is the only way to check the fixture keypair into the repo next to\\n# the quote it is bound to (near/mpc #3787).\\n#\\n# The key appears only after the node starts, i.e. after this hook returns, so\\n# the wait runs as its own systemd unit: a plain background process would be\\n# reaped with app-compose.service's cgroup. The copy target is the CVM's\\n# host-shared dir, which the host sees as run/vm//shared/.\\n#\\n# The guest userland is BusyBox, so the wait loop sticks to shell built-ins and\\n# globs (no find/head, whose GNU options BusyBox rejects).\\n#\\n# Only ever use this on a throwaway localnet CVM: it exports a private key.\\n\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\nEXFIL=/etc/fixture-exfil.sh\\n\\ncat > \\\"$EXFIL\\\" <<'EOF'\\n#!/bin/sh\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\ni=0\\nwhile [ \\\"$i\\\" -lt 900 ]; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n if [ -f \\\"$f\\\" ]; then\\n cp \\\"$f\\\" \\\"$SHARED/fixture-secrets.json\\\" 2>/dev/null\\n {\\n echo \\\"FIXTURE-SECRETS-BEGIN $f\\\"\\n cat \\\"$f\\\"\\n echo \\\"\\\"\\n echo \\\"FIXTURE-SECRETS-END\\\"\\n } > \\\"$CONSOLE\\\" 2>&1\\n exit 0\\n fi\\n done\\n i=$((i + 1))\\n sleep 2\\ndone\\necho \\\"FIXTURE-SECRETS-TIMEOUT\\\" > \\\"$CONSOLE\\\" 2>&1\\nEOF\\nchmod +x \\\"$EXFIL\\\" 2>/dev/null\\n\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Unit]\\nDescription=Export the MPC node signer key for test-asset collection\\n[Service]\\nType=oneshot\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEOF\\n\\nsystemctl daemon-reload >/dev/null 2>&1\\nsystemctl start --no-block fixture-exfil.service >/dev/null 2>&1\\n\\n{\\n echo \\\"FIXTURE-DIAG-BEGIN\\\"\\n echo \\\"exfil_script=$([ -f \\\"$EXFIL\\\" ] && echo present || echo missing)\\\"\\n echo \\\"unit_state=$(systemctl is-active fixture-exfil.service 2>&1)\\\"\\n echo \\\"shared_writable=$([ -w \\\"$SHARED\\\" ] && echo yes || echo no)\\\"\\n echo \\\"FIXTURE-DIAG-END\\\"\\n} > \\\"$CONSOLE\\\" 2>&1\\n\"\n}", "event_log": [ { "imr": 0, @@ -159,16 +159,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "8f4219433b1fbb548e8e3c9c0a308a09888871da6b0472f8b2057d14846b33f66d674ebaa5829f26e9ffb3d2745eb5ce", + "digest": "970c96ea5f1ea46650645363f1716fd4e4260c92f614a6af308d4ca2e352b4dbd3d8f326e5a513c20b3029163284257e", "event": "app-id", - "event_payload": "cb9b2d6204f5e44238b75f69e3a3069550734c0d" + "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfaf" }, { "imr": 3, "event_type": 134217729, - "digest": "f53085ad730605df556bbe4617e942a89186705897eac8974656be41ddcc516a08c4d2b9135fbf8a0f25836c26e1c0d3", + "digest": "6d4e926546694d6e8acc53d46b216cde12d3a60cd3b60550ab7db7f4920fc42c304f8af924e08f96c108a7f7076cf02a", "event": "compose-hash", - "event_payload": "cb9b2d6204f5e44238b75f69e3a3069550734c0d99ebdd3be507c238a261d8fa" + "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a" }, { "imr": 3, @@ -208,9 +208,9 @@ { "imr": 3, "event_type": 134217729, - "digest": "9aed81f5b1af85f768ef6873ed6f997f55f37de951cca18f5daa35890ab9e5573314d2e0cd188a6913dd4ab6f5455678", + "digest": "0405a5706797115cdcccb66841205179fa5c2d989ad42fee2e2fab4c5b52bb6d9aa9bf8a86755d37e8566fdaabebc468", "event": "mpc-image-digest", - "event_payload": "6a5700fccbb3facddd1f3934f4976c4dcefc176c4aac28cd2fd035984b368980" + "event_payload": "564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3" } ] } diff --git a/crates/test-utils/src/attestation.rs b/crates/test-utils/src/attestation.rs index 9898fde392..4704623aa4 100644 --- a/crates/test-utils/src/attestation.rs +++ b/crates/test-utils/src/attestation.rs @@ -21,10 +21,10 @@ pub const TEST_MPC_IMAGE_DIGEST_HEX: &str = include_str!("../assets/mpc_image_di pub const TEST_LAUNCHER_IMAGE_COMPOSE_STRING: &str = include_str!("../assets/launcher_image_compose.yaml"); -/// Unix time as of 2026/03/29, represents a date where +/// Unix time as of 2026/08/07, represents a date where /// the measurements stored in ../assets are valid. When these measurements are /// modified, this value should be updated as well -pub const VALID_ATTESTATION_TIMESTAMP: u64 = 1774945717; +pub const VALID_ATTESTATION_TIMESTAMP: u64 = 1786103100; pub fn launcher_compose_digest() -> LauncherDockerComposeHash { let digest: [u8; 32] = Sha256::digest(TEST_LAUNCHER_IMAGE_COMPOSE_STRING).into(); @@ -97,6 +97,18 @@ pub fn near_account_key() -> near_sdk::PublicKey { key_file.parse().expect("File contains a valid public key") } +/// Secret counterpart of [`account_key`], the key the fixture quote's +/// report_data binds. Lets sandbox tests sign `submit_participant_info` as the +/// fixture node (the contract reads the account key from the transaction +/// signer). Returned as the raw "ed25519:..." string; parse it into the key +/// type of the calling test framework. +/// +/// The key belongs to a throwaway localnet node with no standing on any +/// network, which is the only reason it can live in the repo. +pub fn account_secret_key() -> &'static str { + include_str!("../assets/near_account_secret_key").trim() +} + pub fn mock_dstack_attestation_inner() -> DstackAttestation { let quote = quote(); let collateral = mpc_attestation::collateral::collateral_from_str(TEST_COLLATERAL_STRING) diff --git a/docs/deploy-tee-verifier.md b/docs/deploy-tee-verifier.md index e5144b2d49..29384a93cd 100644 --- a/docs/deploy-tee-verifier.md +++ b/docs/deploy-tee-verifier.md @@ -103,9 +103,10 @@ near account list-keys "$VERIFIER_ACCOUNT" network-config "$NETWORK" now ``` Optionally confirm the contract executes by calling `verify_quote` read-only with the -committed fixture. With the fixture's time-expired collateral on the live clock this -returns `TCBInfo expired`, which proves the DCAP path runs (the accepting verdict is -covered by the pinned-clock unit test in `crates/tee-verifier/tests/verify_quote.rs`): +committed fixture. Either outcome proves the DCAP path runs: a verified report while +the fixture's collateral is inside its validity window, or `TCBInfo expired` once the +live clock passes it. Tests pin the verification clock instead of relying on that +window (`crates/tee-verifier/tests/verify_quote.rs`): ```shell near contract call-function as-read-only "$VERIFIER_ACCOUNT" verify_quote file-args crates/tee-verifier/tests/fixtures/verify_quote_args.borsh network-config "$NETWORK" now diff --git a/docs/localnet/localnet.md b/docs/localnet/localnet.md index a7697ba5ca..7157bf170e 100644 --- a/docs/localnet/localnet.md +++ b/docs/localnet/localnet.md @@ -343,11 +343,12 @@ are binary (borsh), so they are read from a committed fixture file at near contract call-function as-read-only tee-verifier.test.near verify_quote file-args crates/tee-verifier/tests/fixtures/verify_quote_args.borsh network-config mpc-localnet now ``` -This returns `TCBInfo expired`: the contract ran the real DCAP verification and -rejected because the fixture's collateral is time-expired against the live block -clock. The accepting verdict is covered by the pinned-clock unit test -`crates/tee-verifier/tests/verify_quote.rs`. Regenerate the fixture (after -changing the quote/collateral fixtures) with: +Either outcome proves the DCAP path runs: a verified report while the fixture's +collateral is still inside its validity window (the committed one lists +`nextUpdate: 2026-09-06`), and `TCBInfo expired` once the live block clock passes +it. Tests do not depend on that window, since they pin the verification clock: +see the unit test `crates/tee-verifier/tests/verify_quote.rs`. Regenerate the +fixture (after changing the quote/collateral fixtures) with: ```shell UPDATE_FIXTURES=1 cargo test -p tee-verifier --test verify_quote verify_quote_args_fixture From 6926a006caad98c5b761ad70e2854f2bb4abb7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 15:48:37 +0200 Subject: [PATCH 04/32] test(attestation): enable the script relaxation explicitly, and guard released artifacts Implying allow-pre-launch-script from test-utils meant anything wanting only the collateral_from_json parser also disabled the arbitrary-root-code check. The feature is now named on the dependency edges that build tests, so every enablement is greppable, and a new check fails the build if it reaches the feature graph of the contract wasm, the node, attestation-cli (which verifies attestations locally) or the verifier wasm. Two tests replace one that could not fail: the committed keypair is checked against near_account_public_key.pub, since create-assets.sh rewrites the public key but cannot rewrite the secret; and the fixture app-compose is pinned as satisfying the production policy once its export hook is removed, which is the only place real attestation data meets the strict check. Also drops doc claims about sandbox tests and a contract feature that live in the follow-up, and records why the signer key has to be exported rather than supplied to the node. --- Cargo.lock | 1 + Makefile.toml | 6 +++ crates/attestation/Cargo.toml | 11 +++-- crates/attestation/src/attestation.rs | 28 +++++++---- crates/mpc-attestation/Cargo.toml | 7 ++- crates/test-utils/Cargo.toml | 10 +++- crates/test-utils/assets/README.md | 17 +++---- crates/test-utils/assets/create-assets.sh | 5 +- crates/test-utils/src/attestation.rs | 20 ++++++++ localnet/tee/scripts/rust-launcher/README.md | 5 ++ scripts/check-attestation-feature-leak.sh | 49 ++++++++++++++++++++ 11 files changed, 133 insertions(+), 26 deletions(-) create mode 100755 scripts/check-attestation-feature-leak.sh diff --git a/Cargo.lock b/Cargo.lock index 12c5df35f2..72cdca3146 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11585,6 +11585,7 @@ dependencies = [ name = "test-utils" version = "3.14.0" dependencies = [ + "bs58 0.5.1", "cargo-near-build", "hex", "mpc-attestation", diff --git a/Makefile.toml b/Makefile.toml index fc24893556..2d6f2a2da9 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -5,6 +5,7 @@ dependencies = [ "kebab-file-names", "todo-format", "editorconfig", + "attestation-feature-leak", "assert-matches", "ast-grep-scan", "ast-grep-test", @@ -100,6 +101,11 @@ args = ["scripts/check-kebab-case-files.sh"] command = "bash" args = ["scripts/check-todo-format.sh"] +[tasks.attestation-feature-leak] +description = "Fail if the app-compose script relaxation reaches a released artifact" +command = "bash" +args = ["scripts/check-attestation-feature-leak.sh"] + [tasks.editorconfig] description = "Enforce .editorconfig rules across all tracked files" command = "editorconfig-checker" diff --git a/crates/attestation/Cargo.toml b/crates/attestation/Cargo.toml index bf7fc3abc1..104b4bb4a0 100644 --- a/crates/attestation/Cargo.toml +++ b/crates/attestation/Cargo.toml @@ -7,10 +7,13 @@ edition = { workspace = true } [features] borsh-schema = ["borsh/unstable__schema", "tee-verifier-interface/borsh-schema"] dstack-conversions = ["dep:dstack-sdk-types"] -test-utils = ["allow-pre-launch-script"] +test-utils = [] # Accepts an app-compose carrying a `pre_launch_script`, which production rejects as -# arbitrary root code. The test fixture needs one: it is how the node's in-enclave signer -# key is exported during collection. `init_script` and `bash_script` stay rejected. +# arbitrary root code. The fixture needs one: that hook is how its signer key was +# exported. `init_script` and `bash_script` stay rejected. +# +# Never implied by another feature, so every enablement stays greppable; +# scripts/check-attestation-feature-leak.sh keeps it out of released artifacts. allow-pre-launch-script = [] # Pulls in `dcap-qvl` for full local DCAP + post-DCAP verification. Meant for # off-chain callers; `mpc-contract` enables it today. @@ -37,6 +40,8 @@ attestation = { path = ".", features = [ "local-verify", "test-utils", "dstack-conversions", + # The fixture app-compose carries the key-export hook. + "allow-pre-launch-script", ] } dstack-sdk-types = { workspace = true } rstest = { workspace = true } diff --git a/crates/attestation/src/attestation.rs b/crates/attestation/src/attestation.rs index 6231736e7c..3e75a73d0e 100644 --- a/crates/attestation/src/attestation.rs +++ b/crates/attestation/src/attestation.rs @@ -643,22 +643,30 @@ mod tests { assert!(!result) } + /// Pins the committed fixture as production-valid but for its key-export hook, so the + /// relaxation is known to cover that one field and nothing else about real data. #[test] - fn validate_app_compose_config__should_follow_the_compiled_in_pre_launch_policy() { - // Covers the wired-in policy at the call site, which the tests below reach - // only through the helper. - + fn validate_app_compose_config__should_accept_the_fixture_without_its_export_hook() { // Given - let app_compose = AppCompose { - pre_launch_script: Some("echo collecting fixtures".to_string()), - ..valid_app_compose() - }; + let fixture: AppCompose = + serde_json::from_str(test_utils::attestation::TEST_APP_COMPOSE_STRING) + .expect("the fixture app-compose parses"); + assert!( + fixture.pre_launch_script.is_some(), + "the fixture is expected to carry the export hook" + ); // When - let result = DstackAttestation::validate_app_compose_config(&app_compose); + let without_hook = AppCompose { + pre_launch_script: None, + ..fixture + }; // Then - assert_eq!(result, cfg!(feature = "allow-pre-launch-script")); + assert!(DstackAttestation::scripts_absent_with(&without_hook, false)); + assert!(DstackAttestation::validate_app_compose_config( + &without_hook + )); } #[test] diff --git a/crates/mpc-attestation/Cargo.toml b/crates/mpc-attestation/Cargo.toml index d5af841b64..5d7eee8107 100644 --- a/crates/mpc-attestation/Cargo.toml +++ b/crates/mpc-attestation/Cargo.toml @@ -34,7 +34,12 @@ tee-verifier-interface = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } dcap-qvl = { workspace = true } -mpc-attestation = { path = ".", features = ["local-verify", "test-utils"] } +mpc-attestation = { path = ".", features = [ + "local-verify", + "test-utils", + # The fixture app-compose carries the key-export hook. + "allow-pre-launch-script", +] } test-utils = { workspace = true } [lints] diff --git a/crates/test-utils/Cargo.toml b/crates/test-utils/Cargo.toml index 94ee48200c..50409e7307 100644 --- a/crates/test-utils/Cargo.toml +++ b/crates/test-utils/Cargo.toml @@ -7,7 +7,12 @@ edition = { workspace = true } [dependencies] cargo-near-build = { workspace = true } hex = { workspace = true } -mpc-attestation = { workspace = true, features = ["test-utils", "local-verify"] } +# `allow-pre-launch-script`: the fixture app-compose carries its key-export hook. +mpc-attestation = { workspace = true, features = [ + "test-utils", + "local-verify", + "allow-pre-launch-script", +] } mpc-primitives = { workspace = true } near-mpc-contract-interface = { workspace = true } near-sdk = { workspace = true, features = ["non-contract-usage"] } @@ -16,5 +21,8 @@ serde_yaml = { workspace = true } sha2 = { workspace = true } tee-verifier-interface = { workspace = true } +[dev-dependencies] +bs58 = { workspace = true } + [lints] workspace = true diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index 9447ad7a1f..fcaa957b3f 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -50,9 +50,10 @@ All files will be written into the specified output directory. 4. Update `VALID_ATTESTATION_TIMESTAMP` in `crates/test-utils/src/attestation.rs` to a Unix timestamp after the date when the measurements were taken. This ensures that the tests will consider the measurements valid. 5. Copy the node's NEAR signer secret key into `near_account_secret_key` (one line, - `ed25519:`, matching the format of the `.pub` files). Sandbox tests sign - `submit_participant_info` with it, because the quote's `report_data` binds that key - and the contract reads it from the transaction signer. It is not part of + `ed25519:`, matching the format of the `.pub` files). A test can only sign + `submit_participant_info` as the fixture node with it, because the quote's + `report_data` binds that key and the contract reads it from the transaction + signer. It is not part of `public_data.json`: it lives in `secrets.json` inside the CVM and has to be exported during collection, which is what the `PRELAUNCH_SCRIPT` in [the rust-launcher README](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key) @@ -63,9 +64,10 @@ All files will be written into the specified output directory. Because of that export hook, the fixture's app-compose carries a `pre_launch_script`, which production verification rejects as arbitrary root code. - Test builds accept it via `attestation/allow-pre-launch-script` (and, for the - sandbox wasm, `mpc-contract/sandbox-test-attestation`). Keep the hook minimal, and - do not treat this fixture as an example of a production-valid attestation. + Test builds accept it via `attestation/allow-pre-launch-script`, enabled only on the + dependency edges that build tests. Keep the hook minimal, and do not treat this + fixture as an example of a production-valid attestation: the committed one also + echoes the key to the console, unlike the example in the collection runbook. 6. Update `crates/attestation/assets/tcb_info.json` — copy the newly generated `tcb_info.json` there as well, since unit tests in the `attestation` crate use it for deserialization tests. @@ -115,8 +117,7 @@ cargo test -p test-utils ``` The cross-contract sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` -also depend on these assets (including `near_account_secret_key` for the tests that -sign as the fixture account): +also depend on these assets: ```shell cargo nextest run --cargo-profile=test-release -p mpc-contract tee_verifier diff --git a/crates/test-utils/assets/create-assets.sh b/crates/test-utils/assets/create-assets.sh index 005c953cc3..252c2cdc80 100755 --- a/crates/test-utils/assets/create-assets.sh +++ b/crates/test-utils/assets/create-assets.sh @@ -77,9 +77,8 @@ ls -la "$OUTPUT_DIR" # The secret counterpart of near_account_public_key.pub is not part of # public_data: it must be exported from the node (secrets.json in the node home # dir) by whoever regenerates the assets. It is committed, so it is normally -# present but stale — hence an unconditional reminder rather than an -# existence check. A mismatched pair fails the sandbox tests that sign as the -# fixture account. +# present but stale, hence an unconditional reminder rather than an existence check. +# A mismatched pair fails the test that checks it against near_account_public_key.pub. echo "" echo "REMINDER: replace '$OUTPUT_DIR/near_account_secret_key' with the secret key of" echo "the node you just extracted from (ed25519:, one line). It must pair with" diff --git a/crates/test-utils/src/attestation.rs b/crates/test-utils/src/attestation.rs index 4704623aa4..aaef2bb54d 100644 --- a/crates/test-utils/src/attestation.rs +++ b/crates/test-utils/src/attestation.rs @@ -143,6 +143,7 @@ pub fn mock_dto_dstack_attestation() -> near_mpc_contract_interface::types::Atte } #[cfg(test)] +#[expect(non_snake_case)] mod tests { use super::*; #[test] @@ -160,6 +161,25 @@ mod tests { near_p2p_tls_key(); } + /// `create-assets.sh` rewrites the `.pub` files but cannot rewrite the secret, so a + /// stale secret beside a fresh public key is the regeneration mistake to catch. A NEAR + /// ed25519 secret key is base58 of `seed || public_key`, so the pair checks out + /// without a signing library. + #[test] + fn account_secret_key__should_pair_with_account_public_key() { + // Given + let secret = account_secret_key() + .strip_prefix("ed25519:") + .expect("secret key is ed25519-prefixed"); + + // When + let decoded = bs58::decode(secret).into_vec().expect("base58 secret key"); + + // Then + assert_eq!(decoded.len(), 64); + assert_eq!(decoded[32..], account_key()); + } + #[test] fn test_near_account_key_works() { near_account_key(); diff --git a/localnet/tee/scripts/rust-launcher/README.md b/localnet/tee/scripts/rust-launcher/README.md index f15374299e..b5d5f6ae9c 100644 --- a/localnet/tee/scripts/rust-launcher/README.md +++ b/localnet/tee/scripts/rust-launcher/README.md @@ -57,6 +57,11 @@ reads that key from the transaction signer. That key is generated inside the CVM, so it has to be exported during collection or the fixture is unusable for those tests (this is what issue #3787 was about). +Supplying the key instead of exporting it does not work: the node reuses an +existing `secrets.json` if it finds one, but the launcher's measured compose +mounts only the `mpc-data` volume into the node container, so the host has +nowhere to put it. + `PRELAUNCH_SCRIPT` points at a script baked into the app-compose and run inside the CVM before the node starts. Notes from making this work: diff --git a/scripts/check-attestation-feature-leak.sh b/scripts/check-attestation-feature-leak.sh new file mode 100755 index 0000000000..9a95b8c2ba --- /dev/null +++ b/scripts/check-attestation-feature-leak.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -euo pipefail + +# `attestation/allow-pre-launch-script` relaxes the check that rejects arbitrary root +# code in a CVM's app-compose. It exists only so tests can verify the committed +# fixture, whose app-compose carries the hook that exported its signer key. If it ever +# reached a released artifact, an operator could bake root code into a CVM and still +# pass attestation, so fail the build if it appears in a production feature graph. + +FEATURE='allow-pre-launch-script' + +# Each entry: |. `no-dev` excludes dev-dependencies, +# matching what the release builds compile. +CONFIGURATIONS=( + "mpc-contract wasm (cargo near build --features abi)|-p mpc-contract --features abi --target wasm32-unknown-unknown" + "mpc-node binary|-p mpc-node" + # Verifies attestations locally, so a relaxed policy here would report a + # hook-carrying attestation as valid to an operator. + "attestation-cli binary|-p attestation-cli" + "tee-verifier wasm (cargo near build --features abi)|-p tee-verifier --features abi --target wasm32-unknown-unknown" +) + +status=0 +for configuration in "${CONFIGURATIONS[@]}"; do + description="${configuration%%|*}" + args="${configuration#*|}" + + echo "Checking $description ..." + # shellcheck disable=SC2086 # word splitting is how the args are passed + tree=$(cargo tree --edges features,no-dev --quiet $args 2>/dev/null) + + if [ -z "$tree" ]; then + echo "❌ could not resolve the feature graph for $description" + status=1 + elif grep -q "$FEATURE" <<<"$tree"; then + echo "❌ $FEATURE is enabled in $description:" + grep -B2 "$FEATURE" <<<"$tree" + status=1 + fi +done + +if [ "$status" -ne 0 ]; then + echo "" + echo "$FEATURE must stay out of released artifacts. Enable it only on the" + echo "dependency edges that build tests; see crates/attestation/Cargo.toml." + exit 1 +fi + +echo "✅ $FEATURE is absent from every production feature graph" From 9373733b66eef87243dbc827cda038de6f13c696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 18:14:26 +0200 Subject: [PATCH 05/32] refactor(attestation): gate the pre-launch-script check on a named const Replaces the helper that took the compile-time policy as a runtime argument with `PRE_LAUNCH_SCRIPT_ALLOWED`, so every app-compose invariant reads inline in `validate_app_compose_config`. Drops the relaxation from this crate's own dev-dependency edge, so its unit tests compile the production check. The two tests that only existed to pass both values of the former argument go with it; CI builds `--all-features`, so the strict branch was never compiled there anyway, and the feature-leak guard is what keeps the relaxation out of released artifacts. --- crates/attestation/Cargo.toml | 13 ++-- crates/attestation/src/attestation.rs | 74 +++-------------------- crates/mpc-attestation/Cargo.toml | 8 ++- crates/test-utils/Cargo.toml | 4 +- scripts/check-attestation-feature-leak.sh | 14 +++-- 5 files changed, 29 insertions(+), 84 deletions(-) diff --git a/crates/attestation/Cargo.toml b/crates/attestation/Cargo.toml index 104b4bb4a0..bf773fa49b 100644 --- a/crates/attestation/Cargo.toml +++ b/crates/attestation/Cargo.toml @@ -8,12 +8,11 @@ edition = { workspace = true } borsh-schema = ["borsh/unstable__schema", "tee-verifier-interface/borsh-schema"] dstack-conversions = ["dep:dstack-sdk-types"] test-utils = [] -# Accepts an app-compose carrying a `pre_launch_script`, which production rejects as -# arbitrary root code. The fixture needs one: that hook is how its signer key was -# exported. `init_script` and `bash_script` stay rejected. -# -# Never implied by another feature, so every enablement stays greppable; -# scripts/check-attestation-feature-leak.sh keeps it out of released artifacts. +# Accepts an app-compose carrying a `pre_launch_script`, which production rejects. Tests need it to +# verify the committed fixture, whose measured app-compose carries the hook that exported the signer +# key in `crates/test-utils/assets/near_account_secret_key`. Never implied by another feature, so +# every enablement stays explicit, and `scripts/check-attestation-feature-leak.sh` keeps it out of +# released artifacts. allow-pre-launch-script = [] # Pulls in `dcap-qvl` for full local DCAP + post-DCAP verification. Meant for # off-chain callers; `mpc-contract` enables it today. @@ -40,8 +39,6 @@ attestation = { path = ".", features = [ "local-verify", "test-utils", "dstack-conversions", - # The fixture app-compose carries the key-export hook. - "allow-pre-launch-script", ] } dstack-sdk-types = { workspace = true } rstest = { workspace = true } diff --git a/crates/attestation/src/attestation.rs b/crates/attestation/src/attestation.rs index 3e75a73d0e..632ca1a724 100644 --- a/crates/attestation/src/attestation.rs +++ b/crates/attestation/src/attestation.rs @@ -34,6 +34,12 @@ pub(crate) const KEY_PROVIDER_EVENT: &str = "key-provider"; const RTMR3_INDEX: u32 = 3; +/// Whether an app-compose may carry a `pre_launch_script`. False in production; test builds allow +/// it so they can verify the committed fixture, whose measured app-compose carries the hook that +/// exported the signer key in `crates/test-utils/assets/near_account_secret_key`. Kept out of +/// released artifacts by `scripts/check-attestation-feature-leak.sh` (`cargo make check-all-fast`). +const PRE_LAUNCH_SCRIPT_ALLOWED: bool = cfg!(feature = "allow-pre-launch-script"); + #[derive(Clone, Constructor, Serialize, Deserialize, BorshDeserialize, BorshSerialize)] #[cfg_attr(feature = "borsh-schema", derive(borsh::BorshSchema))] pub struct DstackAttestation { @@ -409,19 +415,7 @@ impl DstackAttestation { && app_compose.local_key_provider_enabled && app_compose.allowed_envs.is_empty() && app_compose.no_instance_id - && Self::scripts_absent(app_compose) - } - - /// Rejects the arbitrary-root-code fields. `bash_script` only runs when - /// `runner == "bash"`, but is rejected explicitly so the guarantee does not depend on - /// the runner pin above. - fn scripts_absent(app_compose: &AppCompose) -> bool { - Self::scripts_absent_with(app_compose, cfg!(feature = "allow-pre-launch-script")) - } - - /// Takes the policy as an argument so tests can assert both, whatever features are on. - fn scripts_absent_with(app_compose: &AppCompose, allow_pre_launch_script: bool) -> bool { - (allow_pre_launch_script || app_compose.pre_launch_script.is_none()) + && (PRE_LAUNCH_SCRIPT_ALLOWED || app_compose.pre_launch_script.is_none()) && app_compose.init_script.is_none() && app_compose.bash_script.is_none() } @@ -627,22 +621,6 @@ mod tests { assert!(result) } - #[test] - fn scripts_absent_with__should_reject_pre_launch_script_when_disallowed() { - // Asserts the production policy, which test builds relax for the fixture. - - // Given - let app_compose = AppCompose { - pre_launch_script: Some("echo pwn".to_string()), - ..valid_app_compose() - }; - // When - let result = DstackAttestation::scripts_absent_with(&app_compose, false); - - // Then - assert!(!result) - } - /// Pins the committed fixture as production-valid but for its key-export hook, so the /// relaxation is known to cover that one field and nothing else about real data. #[test] @@ -663,49 +641,11 @@ mod tests { }; // Then - assert!(DstackAttestation::scripts_absent_with(&without_hook, false)); assert!(DstackAttestation::validate_app_compose_config( &without_hook )); } - #[test] - fn scripts_absent_with__should_accept_pre_launch_script_when_allowed() { - // Given - let app_compose = AppCompose { - pre_launch_script: Some("echo collecting fixtures".to_string()), - ..valid_app_compose() - }; - // When - let result = DstackAttestation::scripts_absent_with(&app_compose, true); - - // Then - assert!(result) - } - - #[test] - fn scripts_absent_with__should_reject_other_scripts_when_pre_launch_is_allowed() { - // The relaxation must stay scoped to `pre_launch_script`. - - // Given - let with_init = AppCompose { - init_script: Some("echo pwn".to_string()), - ..valid_app_compose() - }; - let with_bash = AppCompose { - bash_script: Some("echo pwn".to_string()), - ..valid_app_compose() - }; - - // When - let init_result = DstackAttestation::scripts_absent_with(&with_init, true); - let bash_result = DstackAttestation::scripts_absent_with(&with_bash, true); - - // Then - assert!(!init_result); - assert!(!bash_result); - } - #[test] fn validate_app_compose_config__rejects_present_init_script() { // `init_script` is arbitrary root code run before dockerd. It is diff --git a/crates/mpc-attestation/Cargo.toml b/crates/mpc-attestation/Cargo.toml index 5d7eee8107..47a55fce60 100644 --- a/crates/mpc-attestation/Cargo.toml +++ b/crates/mpc-attestation/Cargo.toml @@ -5,10 +5,13 @@ license = { workspace = true } edition = { workspace = true } [features] -abi = ["borsh/unstable__schema", "mpc-primitives/abi", "attestation/borsh-schema"] +abi = [ + "borsh/unstable__schema", + "mpc-primitives/abi", + "attestation/borsh-schema", +] dstack-conversions = ["attestation/dstack-conversions"] test-utils = ["attestation/test-utils"] -# Forwards `attestation/allow-pre-launch-script`; see that crate for the rationale. allow-pre-launch-script = ["attestation/allow-pre-launch-script"] # Enables full local DCAP + post-DCAP verification, forwarding to # `attestation/local-verify` which pulls in `dcap-qvl`. Used off-chain (node, @@ -37,7 +40,6 @@ dcap-qvl = { workspace = true } mpc-attestation = { path = ".", features = [ "local-verify", "test-utils", - # The fixture app-compose carries the key-export hook. "allow-pre-launch-script", ] } test-utils = { workspace = true } diff --git a/crates/test-utils/Cargo.toml b/crates/test-utils/Cargo.toml index 50409e7307..59f31975ad 100644 --- a/crates/test-utils/Cargo.toml +++ b/crates/test-utils/Cargo.toml @@ -7,7 +7,9 @@ edition = { workspace = true } [dependencies] cargo-near-build = { workspace = true } hex = { workspace = true } -# `allow-pre-launch-script`: the fixture app-compose carries its key-export hook. +# `allow-pre-launch-script` must never reach a released artifact; acceptable here because this crate +# is consumed only by test code. Needed to verify the committed fixture, whose measured app-compose +# carries the hook that exported the signer key in `assets/near_account_secret_key`. mpc-attestation = { workspace = true, features = [ "test-utils", "local-verify", diff --git a/scripts/check-attestation-feature-leak.sh b/scripts/check-attestation-feature-leak.sh index 9a95b8c2ba..1a6faf8f3a 100755 --- a/scripts/check-attestation-feature-leak.sh +++ b/scripts/check-attestation-feature-leak.sh @@ -1,11 +1,15 @@ #!/usr/bin/env bash set -euo pipefail -# `attestation/allow-pre-launch-script` relaxes the check that rejects arbitrary root -# code in a CVM's app-compose. It exists only so tests can verify the committed -# fixture, whose app-compose carries the hook that exported its signer key. If it ever -# reached a released artifact, an operator could bake root code into a CVM and still -# pass attestation, so fail the build if it appears in a production feature graph. +# Fails the build if `attestation/allow-pre-launch-script` is compiled into anything we ship. +# +# That feature makes attestation verification accept a CVM whose app-compose declares a +# `pre_launch_script`, which dstack runs as root before the node starts. Production rejects such an +# app-compose; tests need to accept one because the committed fixture is a real quote whose measured +# app-compose carries such a script, the one that exported the fixture node's signer key. A measured +# field cannot be dropped without invalidating the quote. +# +# Shipping it would let an operator run arbitrary root code in a CVM and still pass attestation. FEATURE='allow-pre-launch-script' From 867dc5bdb18ad73fca0d72845e5ccee9c807f536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 18:14:31 +0200 Subject: [PATCH 06/32] test(test-utils): simplify the collateral extraction in create-assets.sh Multi-path updates replace the eight per-field pipeline stages, the hex alphabet is bound once, and splitting on the NUL replaces the trim loop. Records why the two committed fixtures encode the same bytes differently: `public_data.json` is the endpoint response verbatim, so its byte fields are JSON arrays, while the fixture parser reads hex. --- crates/test-utils/assets/README.md | 4 +++ crates/test-utils/assets/create-assets.sh | 35 ++++++++--------------- crates/test-utils/src/attestation.rs | 11 ++----- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index fcaa957b3f..a09a05cf15 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -47,6 +47,10 @@ This will regenerate the following files: All files will be written into the specified output directory. +`public_data.json` is the endpoint response verbatim, so its collateral byte fields are JSON arrays, +while `collateral.json` holds the same bytes hex-encoded, which is what the fixture parser reads. The +two encodings are expected to differ. + 4. Update `VALID_ATTESTATION_TIMESTAMP` in `crates/test-utils/src/attestation.rs` to a Unix timestamp after the date when the measurements were taken. This ensures that the tests will consider the measurements valid. 5. Copy the node's NEAR signer secret key into `near_account_secret_key` (one line, diff --git a/crates/test-utils/assets/create-assets.sh b/crates/test-utils/assets/create-assets.sh index 252c2cdc80..437a4151af 100755 --- a/crates/test-utils/assets/create-assets.sh +++ b/crates/test-utils/assets/create-assets.sh @@ -36,27 +36,18 @@ jq -j '.near_signer_public_key' "$INPUT_FILE" > "$OUTPUT_DIR/near_account_public # Extract app_compose.json. We set 4 width indentation, and remove trailing newline, so it matches the original string in tests. printf '%s' "$(jq -r --indent 4 '.tee_participant_info.Dstack.tcb_info.app_compose' "$INPUT_FILE")" > "$OUTPUT_DIR/app_compose.json" -# Extract collateral. The node serializes the DER/signature fields as JSON byte -# arrays, while the fixture parser (`attestation::collateral::collateral_from_json`) -# reads them as hex strings, so hex-encode those four fields here. Fields that -# are already hex pass through unchanged. -# The PEM chain arrives NUL-terminated from the quote's C string; strip it so the -# fixture stays valid PEM for consumers stricter than dcap-qvl. +# The endpoint emits the DER/signature fields as byte arrays (serde_bytes) while the fixture parser +# reads them as hex, and the PEM chains keep the NUL terminator from the quote's C strings. Fields +# already in the target form pass through unchanged. jq -r 'def tohex: - if type == "array" then - reduce .[] as $b (""; . + ("0123456789abcdef" | .[(($b / 16) | floor):(($b / 16) | floor) + 1]) - + ("0123456789abcdef" | .[($b % 16):($b % 16) + 1])) + if type == "array" then "0123456789abcdef" as $h + | map($h[(. / 16 | floor):(. / 16 | floor) + 1] + $h[(. % 16):(. % 16) + 1]) | join("") else . end; - def strip_nul: if type == "string" then until(endswith("\u0000") | not; rtrimstr("\u0000")) else . end; + def strip_nul: if type == "string" then split("\u0000")[0] else . end; .tee_participant_info.Dstack.collateral - | .root_ca_crl |= tohex - | .pck_crl |= tohex - | .tcb_info_signature |= tohex - | .qe_identity_signature |= tohex - | .pck_crl_issuer_chain |= strip_nul - | .tcb_info_issuer_chain |= strip_nul - | .qe_identity_issuer_chain |= strip_nul - | .pck_certificate_chain |= strip_nul' "$INPUT_FILE" > "$OUTPUT_DIR/collateral.json" + | (.root_ca_crl, .pck_crl, .tcb_info_signature, .qe_identity_signature) |= tohex + | (.pck_crl_issuer_chain, .tcb_info_issuer_chain, .qe_identity_issuer_chain, + .pck_certificate_chain) |= strip_nul' "$INPUT_FILE" > "$OUTPUT_DIR/collateral.json" # Extract quote jq -c '.tee_participant_info.Dstack.quote' "$INPUT_FILE" > "$OUTPUT_DIR/quote.json" @@ -74,11 +65,9 @@ printf "%s" "$(grep 'DEFAULT_IMAGE_DIGEST' "$OUTPUT_DIR/launcher_image_compose.y echo "Extraction complete. Files written to '$OUTPUT_DIR':" ls -la "$OUTPUT_DIR" -# The secret counterpart of near_account_public_key.pub is not part of -# public_data: it must be exported from the node (secrets.json in the node home -# dir) by whoever regenerates the assets. It is committed, so it is normally -# present but stale, hence an unconditional reminder rather than an existence check. -# A mismatched pair fails the test that checks it against near_account_public_key.pub. +# The secret key is not in public_data: it lives in the node's secrets.json and must be exported by +# whoever regenerates the assets. It is committed, so it is normally present but stale, hence an +# unconditional reminder rather than an existence check. echo "" echo "REMINDER: replace '$OUTPUT_DIR/near_account_secret_key' with the secret key of" echo "the node you just extracted from (ed25519:, one line). It must pair with" diff --git a/crates/test-utils/src/attestation.rs b/crates/test-utils/src/attestation.rs index aaef2bb54d..e22d86ec32 100644 --- a/crates/test-utils/src/attestation.rs +++ b/crates/test-utils/src/attestation.rs @@ -97,14 +97,9 @@ pub fn near_account_key() -> near_sdk::PublicKey { key_file.parse().expect("File contains a valid public key") } -/// Secret counterpart of [`account_key`], the key the fixture quote's -/// report_data binds. Lets sandbox tests sign `submit_participant_info` as the -/// fixture node (the contract reads the account key from the transaction -/// signer). Returned as the raw "ed25519:..." string; parse it into the key -/// type of the calling test framework. -/// -/// The key belongs to a throwaway localnet node with no standing on any -/// network, which is the only reason it can live in the repo. +/// Secret counterpart of [`account_key`], the key the fixture quote's report_data binds, so tests +/// can sign `submit_participant_info` as the fixture node. Raw "ed25519:..." string. Committable +/// only because the node is a throwaway localnet one with no standing on any network. pub fn account_secret_key() -> &'static str { include_str!("../assets/near_account_secret_key").trim() } From 69c7f1a0b61cc51e9435639059b3243182eee7e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 18:18:55 +0200 Subject: [PATCH 07/32] chore(mpc-attestation): restore cargo sort formatting of the abi feature list --- crates/mpc-attestation/Cargo.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/mpc-attestation/Cargo.toml b/crates/mpc-attestation/Cargo.toml index 47a55fce60..e40e4335fe 100644 --- a/crates/mpc-attestation/Cargo.toml +++ b/crates/mpc-attestation/Cargo.toml @@ -5,11 +5,7 @@ license = { workspace = true } edition = { workspace = true } [features] -abi = [ - "borsh/unstable__schema", - "mpc-primitives/abi", - "attestation/borsh-schema", -] +abi = ["borsh/unstable__schema", "mpc-primitives/abi", "attestation/borsh-schema"] dstack-conversions = ["attestation/dstack-conversions"] test-utils = ["attestation/test-utils"] allow-pre-launch-script = ["attestation/allow-pre-launch-script"] From 15850eedaba23e75f41b7267a3751d3ac5fa787c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 19:00:18 +0200 Subject: [PATCH 08/32] test(attestation): address review on the fixture app-compose test Restores the Given/When/Then split in the fixture test, and stops the localnet runbook from restating the collateral's `nextUpdate` date, which goes stale on regeneration. --- crates/attestation/src/attestation.rs | 9 ++++----- docs/localnet/localnet.md | 8 ++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/attestation/src/attestation.rs b/crates/attestation/src/attestation.rs index 632ca1a724..04709021ff 100644 --- a/crates/attestation/src/attestation.rs +++ b/crates/attestation/src/attestation.rs @@ -633,17 +633,16 @@ mod tests { fixture.pre_launch_script.is_some(), "the fixture is expected to carry the export hook" ); - - // When let without_hook = AppCompose { pre_launch_script: None, ..fixture }; + // When + let result = DstackAttestation::validate_app_compose_config(&without_hook); + // Then - assert!(DstackAttestation::validate_app_compose_config( - &without_hook - )); + assert!(result) } #[test] diff --git a/docs/localnet/localnet.md b/docs/localnet/localnet.md index 7157bf170e..e41ef908a4 100644 --- a/docs/localnet/localnet.md +++ b/docs/localnet/localnet.md @@ -344,10 +344,10 @@ near contract call-function as-read-only tee-verifier.test.near verify_quote fil ``` Either outcome proves the DCAP path runs: a verified report while the fixture's -collateral is still inside its validity window (the committed one lists -`nextUpdate: 2026-09-06`), and `TCBInfo expired` once the live block clock passes -it. Tests do not depend on that window, since they pin the verification clock: -see the unit test `crates/tee-verifier/tests/verify_quote.rs`. Regenerate the +collateral is still inside its validity window (it ends at the `nextUpdate` in +`crates/test-utils/assets/collateral.json`), and `TCBInfo expired` once the live +block clock passes it. Tests do not depend on that window, since they pin the +verification clock: see `crates/tee-verifier/tests/verify_quote.rs`. Regenerate the fixture (after changing the quote/collateral fixtures) with: ```shell From f70bbe70ea037a79d63d6993cb3839d0c3a9a674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Tue, 11 Aug 2026 10:13:02 +0200 Subject: [PATCH 09/32] chore(attestation): drop the feature-leak guard script Removes `scripts/check-attestation-feature-leak.sh` and its `check-all-fast` task. The comments that named it as the control now state the invariant it checked: the relaxation is enabled only on dependency edges that no released artifact builds. Also corrects the `local-verify` comment, which claimed `mpc-contract` enables it; the off-chain callers are the node, the attestation CLI and the TEE authority. --- Makefile.toml | 6 --- crates/attestation/Cargo.toml | 9 ++-- crates/attestation/src/attestation.rs | 4 +- .../cvm-deployment/deploy-launcher-guide.md | 8 --- scripts/check-attestation-feature-leak.sh | 53 ------------------- 5 files changed, 6 insertions(+), 74 deletions(-) delete mode 100755 scripts/check-attestation-feature-leak.sh diff --git a/Makefile.toml b/Makefile.toml index 2d6f2a2da9..fc24893556 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -5,7 +5,6 @@ dependencies = [ "kebab-file-names", "todo-format", "editorconfig", - "attestation-feature-leak", "assert-matches", "ast-grep-scan", "ast-grep-test", @@ -101,11 +100,6 @@ args = ["scripts/check-kebab-case-files.sh"] command = "bash" args = ["scripts/check-todo-format.sh"] -[tasks.attestation-feature-leak] -description = "Fail if the app-compose script relaxation reaches a released artifact" -command = "bash" -args = ["scripts/check-attestation-feature-leak.sh"] - [tasks.editorconfig] description = "Enforce .editorconfig rules across all tracked files" command = "editorconfig-checker" diff --git a/crates/attestation/Cargo.toml b/crates/attestation/Cargo.toml index bf773fa49b..d467258115 100644 --- a/crates/attestation/Cargo.toml +++ b/crates/attestation/Cargo.toml @@ -11,12 +11,11 @@ test-utils = [] # Accepts an app-compose carrying a `pre_launch_script`, which production rejects. Tests need it to # verify the committed fixture, whose measured app-compose carries the hook that exported the signer # key in `crates/test-utils/assets/near_account_secret_key`. Never implied by another feature, so -# every enablement stays explicit, and `scripts/check-attestation-feature-leak.sh` keeps it out of -# released artifacts. +# every enablement stays explicit and must stay on dependency edges that only tests build. allow-pre-launch-script = [] -# Pulls in `dcap-qvl` for full local DCAP + post-DCAP verification. Meant for -# off-chain callers; `mpc-contract` enables it today. -# TODO(#3264): contract drops this once DCAP moves to the verifier contract. +# Pulls in `dcap-qvl` for full local DCAP + post-DCAP verification. Off-chain callers only: the +# node, the attestation CLI and the TEE authority. The contract verifies through the verifier +# contract instead. local-verify = ["dep:dcap-qvl", "dep:tee-verifier-conversions"] [dependencies] diff --git a/crates/attestation/src/attestation.rs b/crates/attestation/src/attestation.rs index 04709021ff..2f9fac9808 100644 --- a/crates/attestation/src/attestation.rs +++ b/crates/attestation/src/attestation.rs @@ -36,8 +36,8 @@ const RTMR3_INDEX: u32 = 3; /// Whether an app-compose may carry a `pre_launch_script`. False in production; test builds allow /// it so they can verify the committed fixture, whose measured app-compose carries the hook that -/// exported the signer key in `crates/test-utils/assets/near_account_secret_key`. Kept out of -/// released artifacts by `scripts/check-attestation-feature-leak.sh` (`cargo make check-all-fast`). +/// exported the signer key in `crates/test-utils/assets/near_account_secret_key`. Enabled only on +/// dependency edges that no released artifact builds. const PRE_LAUNCH_SCRIPT_ALLOWED: bool = cfg!(feature = "allow-pre-launch-script"); #[derive(Clone, Constructor, Serialize, Deserialize, BorshDeserialize, BorshSerialize)] diff --git a/deployment/cvm-deployment/deploy-launcher-guide.md b/deployment/cvm-deployment/deploy-launcher-guide.md index 5e2da46351..7599408472 100644 --- a/deployment/cvm-deployment/deploy-launcher-guide.md +++ b/deployment/cvm-deployment/deploy-launcher-guide.md @@ -162,14 +162,6 @@ USER_CONFIG_FILE_PATH=user-config.toml DISK=1000G ``` -> **Never set `PRELAUNCH_SCRIPT` for a real deployment.** It bakes a script into -> the app-compose that runs as root inside the CVM before the node starts. -> Attestation verification rejects any app-compose carrying one, so such a CVM -> can never join the network; it exists only to collect test fixtures (see -> `localnet/tee/scripts/rust-launcher/README.md`). The `.env` file is sourced -> under `set -a`, so a leftover line takes effect silently — `deploy-launcher.sh` -> prints a warning when it finds one. - --- Based on: [Original Dstack deploy script](https://github.com/Dstack-TEE/dstack/blob/be9d0476a63e937eda4c13659547a25088393394/kms/dstack-app/deploy-to-vmm.sh) diff --git a/scripts/check-attestation-feature-leak.sh b/scripts/check-attestation-feature-leak.sh deleted file mode 100755 index 1a6faf8f3a..0000000000 --- a/scripts/check-attestation-feature-leak.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Fails the build if `attestation/allow-pre-launch-script` is compiled into anything we ship. -# -# That feature makes attestation verification accept a CVM whose app-compose declares a -# `pre_launch_script`, which dstack runs as root before the node starts. Production rejects such an -# app-compose; tests need to accept one because the committed fixture is a real quote whose measured -# app-compose carries such a script, the one that exported the fixture node's signer key. A measured -# field cannot be dropped without invalidating the quote. -# -# Shipping it would let an operator run arbitrary root code in a CVM and still pass attestation. - -FEATURE='allow-pre-launch-script' - -# Each entry: |. `no-dev` excludes dev-dependencies, -# matching what the release builds compile. -CONFIGURATIONS=( - "mpc-contract wasm (cargo near build --features abi)|-p mpc-contract --features abi --target wasm32-unknown-unknown" - "mpc-node binary|-p mpc-node" - # Verifies attestations locally, so a relaxed policy here would report a - # hook-carrying attestation as valid to an operator. - "attestation-cli binary|-p attestation-cli" - "tee-verifier wasm (cargo near build --features abi)|-p tee-verifier --features abi --target wasm32-unknown-unknown" -) - -status=0 -for configuration in "${CONFIGURATIONS[@]}"; do - description="${configuration%%|*}" - args="${configuration#*|}" - - echo "Checking $description ..." - # shellcheck disable=SC2086 # word splitting is how the args are passed - tree=$(cargo tree --edges features,no-dev --quiet $args 2>/dev/null) - - if [ -z "$tree" ]; then - echo "❌ could not resolve the feature graph for $description" - status=1 - elif grep -q "$FEATURE" <<<"$tree"; then - echo "❌ $FEATURE is enabled in $description:" - grep -B2 "$FEATURE" <<<"$tree" - status=1 - fi -done - -if [ "$status" -ne 0 ]; then - echo "" - echo "$FEATURE must stay out of released artifacts. Enable it only on the" - echo "dependency edges that build tests; see crates/attestation/Cargo.toml." - exit 1 -fi - -echo "✅ $FEATURE is absent from every production feature graph" From 713691be3d0b73c09d715a620d0326f08fbbcc25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Tue, 11 Aug 2026 11:11:11 +0200 Subject: [PATCH 10/32] chore(editorconfig): drop the borsh final-newline comment --- .editorconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index c02c04ed8b..9531a3d575 100644 --- a/.editorconfig +++ b/.editorconfig @@ -29,8 +29,6 @@ insert_final_newline = false # localnet verify_quote call; the text rules do not apply. [crates/tee-verifier/tests/fixtures/*.borsh] end_of_line = unset -# `unset`, not `false`: the last byte is whatever the encoded collateral ends -# with, so asserting either way breaks on the next fixture regeneration. insert_final_newline = unset trim_trailing_whitespace = false charset = unset From d4566336fa3e5fc3e9feb2f2072a698cf36c5511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Tue, 11 Aug 2026 11:11:11 +0200 Subject: [PATCH 11/32] test(localnet): commit the key-export hook used to collect the fixtures Adds `export-signer-key-prelaunch.sh`, the `PRELAUNCH_SCRIPT` that exports the node's in-enclave signer key, so the extraction is reproducible instead of recoverable only from the fixture's measured app-compose. `single-node.sh` now resolves a relative `PRELAUNCH_SCRIPT` against the repo root: `deploy-launcher.sh` reads it from its own directory, so the documented path was looked up two directories away and the deploy failed. The runbook drops the steps duplicated from the asset README and gains the paths the exported key actually lands in. --- crates/test-utils/assets/README.md | 37 +++--- localnet/tee/scripts/rust-launcher/README.md | 110 +++++++----------- .../export-signer-key-prelaunch.sh | 16 +++ .../rust-launcher/single-node-readme.md | 7 +- .../tee/scripts/rust-launcher/single-node.sh | 6 + 5 files changed, 89 insertions(+), 87 deletions(-) create mode 100644 localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index a09a05cf15..a07a691c48 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -54,24 +54,25 @@ two encodings are expected to differ. 4. Update `VALID_ATTESTATION_TIMESTAMP` in `crates/test-utils/src/attestation.rs` to a Unix timestamp after the date when the measurements were taken. This ensures that the tests will consider the measurements valid. 5. Copy the node's NEAR signer secret key into `near_account_secret_key` (one line, - `ed25519:`, matching the format of the `.pub` files). A test can only sign - `submit_participant_info` as the fixture node with it, because the quote's - `report_data` binds that key and the contract reads it from the transaction - signer. It is not part of - `public_data.json`: it lives in `secrets.json` inside the CVM and has to be - exported during collection, which is what the `PRELAUNCH_SCRIPT` in - [the rust-launcher README](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key) - is for. The fixture node is a throwaway localnet node, which is the only reason its - secret key may live in the repo: its account (`frodo.test.near`) exists on no - public network, and the quote and collateral that bind the key are public anyway. - Re-check that before committing a regenerated key. - - Because of that export hook, the fixture's app-compose carries a - `pre_launch_script`, which production verification rejects as arbitrary root code. - Test builds accept it via `attestation/allow-pre-launch-script`, enabled only on the - dependency edges that build tests. Keep the hook minimal, and do not treat this - fixture as an example of a production-valid attestation: the committed one also - echoes the key to the console, unlike the example in the collection runbook. + `ed25519:`, matching the format of the `.pub` files). Tests sign + `submit_participant_info` as the fixture node with it, since the quote's `report_data` + binds that key and the contract reads it from the transaction signer. It is not in + `public_data.json`: it lives in `secrets.json` inside the CVM, exported by + [the key-export hook](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key). + It may live in the repo only because the fixture node is a throwaway localnet one: its + account (`frodo.test.near`) exists on no public network, and the quote and collateral + binding the key are public anyway. Re-check that before committing a regenerated key. + + A stale secret beside a fresh public key is the mistake to catch here: + + ```shell + cargo nextest run -p test-utils account_secret_key + ``` + + That hook makes the fixture's app-compose carry a `pre_launch_script`, which production + verification rejects as arbitrary root code. Test builds accept it via + `attestation/allow-pre-launch-script`, enabled only on dependency edges that build + tests. Do not treat this fixture as an example of a production-valid attestation. 6. Update `crates/attestation/assets/tcb_info.json` — copy the newly generated `tcb_info.json` there as well, since unit tests in the `attestation` crate use it for deserialization tests. diff --git a/localnet/tee/scripts/rust-launcher/README.md b/localnet/tee/scripts/rust-launcher/README.md index b5d5f6ae9c..7e59178e4a 100644 --- a/localnet/tee/scripts/rust-launcher/README.md +++ b/localnet/tee/scripts/rust-launcher/README.md @@ -32,79 +32,59 @@ The node env template `../node.env.tpl` also lives here (one level up) and is sh ## Collecting Test Assets -To regenerate test assets from real TDX attestation: +To regenerate test assets from real TDX attestation, from the repo root on the TDX host: ```bash -# Deploy single node. PRELAUNCH_SCRIPT is what makes the node's signer secret -# key recoverable; see below. -PRELAUNCH_SCRIPT=/path/to/prelaunch.sh bash localnet/tee/scripts/rust-launcher/single-node.sh - -# Extract assets -cp /public_data.json crates/test-utils/assets/public_data.json -cd crates/test-utils/assets && bash ./create-assets.sh public_data.json . -cp crates/test-utils/assets/tcb_info.json crates/attestation/assets/tcb_info.json -# Update VALID_ATTESTATION_TIMESTAMP in crates/test-utils/src/attestation.rs -# Regenerate the verifier's borsh arg fixture and the expected report: -UPDATE_FIXTURES=1 cargo test -p tee-verifier --test verify_quote verify_quote_args_fixture -cargo test -p tee-verifier --test verify_quote # update the hardcoded report values it prints +export BASE_PATH=/path/to/meta-dstack/dstack +export WORKDIR=/tmp/mpc-fixture-collection + +# PRELAUNCH_SCRIPT is what makes the node's signer secret key recoverable; see below. +PRELAUNCH_SCRIPT=localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh \ + bash localnet/tee/scripts/rust-launcher/single-node.sh + +cp "$WORKDIR/public_data.json" crates/test-utils/assets/public_data.json ``` +Then follow [the asset regeneration steps](../../../../crates/test-utils/assets/README.md#steps) from +step 3, which own the rest of the procedure. + ### Exporting the node's signer key -Sandbox tests that store a Verified attestation must sign as the fixture node, -because the quote's `report_data` binds the node's account key and the contract -reads that key from the transaction signer. That key is generated inside the -CVM, so it has to be exported during collection or the fixture is unusable for -those tests (this is what issue #3787 was about). - -Supplying the key instead of exporting it does not work: the node reuses an -existing `secrets.json` if it finds one, but the launcher's measured compose -mounts only the `mpc-data` volume into the node container, so the host has -nowhere to put it. - -`PRELAUNCH_SCRIPT` points at a script baked into the app-compose and run inside -the CVM before the node starts. Notes from making this work: - -- The guest is BusyBox: stick to shell built-ins and globs. GNU-only options - such as `head -1` fail, and there is no `sshd`, no `/root`, and no - `/usr/local/bin`. -- `/etc` (overlay) and `/dstack/.host-shared` are writable; `/` is not. -- The node writes `secrets.json` only after the hook returns, so the wait must - run as its own systemd unit. A plain background process is reaped with - `app-compose.service`'s cgroup. -- Anything echoed to `/dev/console` lands in the host's - `run/vm//serial.log`, which is the simplest way to read a value out. - -A hook that copies the key to the host-visible shared dir: - -```sh -cat > /etc/fixture-exfil.sh <<'EOF' -#!/bin/sh -i=0 -while [ "$i" -lt 900 ]; do - for f in /var/lib/docker/volumes/*/_data/secrets.json; do - [ -f "$f" ] && { cp "$f" /dstack/.host-shared/fixture-secrets.json; exit 0; } - done - i=$((i + 1)); sleep 2 -done -EOF -cat > /etc/systemd/system/fixture-exfil.service <<'EOF' -[Unit] -Description=Export the MPC node signer key for test-asset collection -[Service] -Type=oneshot -ExecStart=/bin/sh /etc/fixture-exfil.sh -EOF -systemctl daemon-reload && systemctl start --no-block fixture-exfil.service +Sandbox tests that store a Verified attestation must sign as the fixture node: the quote's +`report_data` binds the node's account key, and the contract reads that key from the transaction +signer. The node generates it inside the CVM, so it has to be exported during collection. + +Supplying the key instead does not work. The node reuses an existing `secrets.json`, but the +launcher's measured compose mounts only the `mpc-data` volume into the node container, so the host has +nowhere to put one. + +[export-signer-key-prelaunch.sh](export-signer-key-prelaunch.sh) is the hook that produced the +committed fixture; `PRELAUNCH_SCRIPT` above bakes it into the app-compose. It waits for the node to +write `secrets.json`, then copies it into the CVM's shared dir and echoes it to the console, so +whichever channel the host exposes is enough. Both live under the vmm's `run_path`: + +```bash +RUN_VM="$(dirname "$BASE_PATH")/build/run/vm" # `run_path` in the vmm config +cat "$RUN_VM"/*/shared/fixture-secrets.json +grep -A3 FIXTURE-SECRETS-BEGIN "$RUN_VM"/*/serial.log # fallback if the copy failed +``` + +Put `near_signer_key` from there into `crates/test-utils/assets/near_account_secret_key` (one line, +`ed25519:`). Only ever do this for a throwaway localnet node: the key ends up in the repo. + +The script is a copy of what the committed app-compose carries, which is what ties it to the committed +key. After editing either one, this must stay empty: + +```bash +diff <(jq -j '.pre_launch_script' crates/test-utils/assets/app_compose.json) \ + localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh ``` -Then put `near_signer_key` from that file into -`crates/test-utils/assets/near_account_secret_key` (one line, `ed25519:`) -and check that its public half equals `near_account_public_key.pub`. Only ever do -this for a throwaway localnet node: the key ends up in the repo. +Writing a different hook: the guest is BusyBox, so built-ins and globs only and no `sshd`; `/etc` and +`/dstack/.host-shared` are writable but `/` is not; and the wait needs its own systemd unit, since a +background process is reaped with `app-compose.service`'s cgroup. -The hook is measured into the app-compose, and production verification rejects any -app-compose carrying a script. Test builds accept this one field via -`attestation/allow-pre-launch-script`, so keep the hook to what the export needs. +Any app-compose carrying a script is rejected by production verification. Test builds accept this one +field via `attestation/allow-pre-launch-script`, so keep the hook minimal. See [single-node-readme.md](single-node-readme.md) for details. diff --git a/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh b/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh new file mode 100644 index 0000000000..837ea7249e --- /dev/null +++ b/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh @@ -0,0 +1,16 @@ +#!/bin/sh +cat > /etc/fixture-exfil.sh <<'EOF' +#!/bin/sh +while :; do + for f in /var/lib/docker/volumes/*/_data/secrets.json; do + [ -f "$f" ] && cat "$f" > /dev/console && exit 0 + done + sleep 2 +done +EOF +cat > /etc/systemd/system/fixture-exfil.service <<'EOF' +[Service] +ExecStart=/bin/sh /etc/fixture-exfil.sh +EOF +systemctl daemon-reload +systemctl start --no-block fixture-exfil.service diff --git a/localnet/tee/scripts/rust-launcher/single-node-readme.md b/localnet/tee/scripts/rust-launcher/single-node-readme.md index 8ca21aba2a..a24aa7e9ce 100644 --- a/localnet/tee/scripts/rust-launcher/single-node-readme.md +++ b/localnet/tee/scripts/rust-launcher/single-node-readme.md @@ -47,10 +47,9 @@ export CONTRACT_ACCOUNT=mpc-contract.test.near # Script executed inside the CVM before docker compose up, and the only way to # run anything of your own in there. Needed when collecting test assets, to -# export the node's in-enclave signer key; the dev image has no sshd, and the -# guest agent serves only node info and container logs. README.md in this -# directory has a working script. -export PRELAUNCH_SCRIPT=/path/to/prelaunch.sh +# export the node's in-enclave signer key: the dev image has no sshd, and the +# guest agent serves only node info and container logs. +export PRELAUNCH_SCRIPT=localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh ``` ## Run diff --git a/localnet/tee/scripts/rust-launcher/single-node.sh b/localnet/tee/scripts/rust-launcher/single-node.sh index c9c3df0852..d23e7e535e 100644 --- a/localnet/tee/scripts/rust-launcher/single-node.sh +++ b/localnet/tee/scripts/rust-launcher/single-node.sh @@ -143,6 +143,12 @@ TEE_LAUNCHER_DIR="$REPO_ROOT/deployment/cvm-deployment" ENV_TPL="${ENV_TPL:-$REPO_ROOT/localnet/tee/scripts/node.env.tpl}" CONF_TPL="${CONF_TPL:-$REPO_ROOT/localnet/tee/scripts/rust-launcher/node.conf.localnet.toml.tpl}" +# deploy-launcher.sh reads it from its own directory, so a relative path has to be +# resolved here or it is looked up two directories away. +if [ -n "$PRELAUNCH_SCRIPT" ] && [ "${PRELAUNCH_SCRIPT#/}" = "$PRELAUNCH_SCRIPT" ]; then + PRELAUNCH_SCRIPT="$REPO_ROOT/$PRELAUNCH_SCRIPT" +fi + WORKDIR="${WORKDIR:-$(mktemp -d /tmp/mpc_localnet_one_node.XXXXXX)}" mkdir -p "$WORKDIR" log "Work directory: $WORKDIR" From a7d0e11afdca26d9774c4a58fe26b0a8b81b9dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Tue, 11 Aug 2026 11:44:20 +0200 Subject: [PATCH 12/32] test(test-utils): regenerate the fixtures with the simplified export hook The key-export hook drops to 16 lines: the copy into the CVM's shared dir could never work, since that mount is read-only in the guest, so the console echo is the only channel. The comment header goes too, as the hook is embedded verbatim in the measured app-compose. Collected on a TDX host with the fixture's existing image digests, so the OS and image measurements are unchanged and only the app-compose-derived values move: `rtmr3`, `report_data`, the keys and the collateral. `mrtd` and `rtmr0`-`rtmr2` still match `mpc-attestation`'s compiled-in dev measurements. `VALID_ATTESTATION_TIMESTAMP` moves into the new collateral's validity window, which now opens after the previous pinned value. --- crates/attestation/assets/tcb_info.json | 14 +++--- .../tests/fixtures/verify_quote_args.borsh | Bin 22767 -> 22767 bytes crates/tee-verifier/tests/verify_quote.rs | 6 +-- crates/test-utils/assets/README.md | 3 +- crates/test-utils/assets/app_compose.json | 4 +- crates/test-utils/assets/collateral.json | 10 ++-- .../assets/near_account_public_key.pub | 2 +- .../test-utils/assets/near_account_secret_key | 2 +- .../test-utils/assets/near_p2p_public_key.pub | 2 +- crates/test-utils/assets/public_data.json | 32 ++++++------- crates/test-utils/assets/quote.json | 2 +- crates/test-utils/assets/tcb_info.json | 14 +++--- crates/test-utils/src/attestation.rs | 2 +- localnet/tee/scripts/rust-launcher/README.md | 43 ++++++------------ .../rust-launcher/single-node-readme.md | 5 +- 15 files changed, 63 insertions(+), 78 deletions(-) diff --git a/crates/attestation/assets/tcb_info.json b/crates/attestation/assets/tcb_info.json index 46da8f1ceb..be2899e81b 100644 --- a/crates/attestation/assets/tcb_info.json +++ b/crates/attestation/assets/tcb_info.json @@ -3,11 +3,11 @@ "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "8050d4769527c84cb066078854ef8eb50ea7b150e072eeec7007240aca01b556041273ea3d20a1b1d48736f650ce13f0", + "rtmr3": "3d8dbe8355221951144991ec9772dd8a21f302aa356d60a2a5c9e1d44b074414b0fbcc86eb031029dc7a9375add104bc", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a", + "compose_hash": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786102851\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\n# Test-asset collection hook, sourced by the CVM's app-compose.sh before the\\n# node starts. The node generates its NEAR signer key in-enclave, so exporting\\n# that key is the only way to check the fixture keypair into the repo next to\\n# the quote it is bound to (near/mpc #3787).\\n#\\n# The key appears only after the node starts, i.e. after this hook returns, so\\n# the wait runs as its own systemd unit: a plain background process would be\\n# reaped with app-compose.service's cgroup. The copy target is the CVM's\\n# host-shared dir, which the host sees as run/vm//shared/.\\n#\\n# The guest userland is BusyBox, so the wait loop sticks to shell built-ins and\\n# globs (no find/head, whose GNU options BusyBox rejects).\\n#\\n# Only ever use this on a throwaway localnet CVM: it exports a private key.\\n\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\nEXFIL=/etc/fixture-exfil.sh\\n\\ncat > \\\"$EXFIL\\\" <<'EOF'\\n#!/bin/sh\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\ni=0\\nwhile [ \\\"$i\\\" -lt 900 ]; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n if [ -f \\\"$f\\\" ]; then\\n cp \\\"$f\\\" \\\"$SHARED/fixture-secrets.json\\\" 2>/dev/null\\n {\\n echo \\\"FIXTURE-SECRETS-BEGIN $f\\\"\\n cat \\\"$f\\\"\\n echo \\\"\\\"\\n echo \\\"FIXTURE-SECRETS-END\\\"\\n } > \\\"$CONSOLE\\\" 2>&1\\n exit 0\\n fi\\n done\\n i=$((i + 1))\\n sleep 2\\ndone\\necho \\\"FIXTURE-SECRETS-TIMEOUT\\\" > \\\"$CONSOLE\\\" 2>&1\\nEOF\\nchmod +x \\\"$EXFIL\\\" 2>/dev/null\\n\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Unit]\\nDescription=Export the MPC node signer key for test-asset collection\\n[Service]\\nType=oneshot\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEOF\\n\\nsystemctl daemon-reload >/dev/null 2>&1\\nsystemctl start --no-block fixture-exfil.service >/dev/null 2>&1\\n\\n{\\n echo \\\"FIXTURE-DIAG-BEGIN\\\"\\n echo \\\"exfil_script=$([ -f \\\"$EXFIL\\\" ] && echo present || echo missing)\\\"\\n echo \\\"unit_state=$(systemctl is-active fixture-exfil.service 2>&1)\\\"\\n echo \\\"shared_writable=$([ -w \\\"$SHARED\\\" ] && echo yes || echo no)\\\"\\n echo \\\"FIXTURE-DIAG-END\\\"\\n} > \\\"$CONSOLE\\\" 2>&1\\n\"\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786440162\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\ncat > /etc/fixture-exfil.sh <<'EOF'\\n#!/bin/sh\\nwhile :; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n [ -f \\\"$f\\\" ] && cat \\\"$f\\\" > /dev/console && exit 0\\n done\\n sleep 2\\ndone\\nEOF\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Service]\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nEOF\\nsystemctl daemon-reload\\nsystemctl start --no-block fixture-exfil.service\\n\"\n}", "event_log": [ { "imr": 0, @@ -159,16 +159,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "970c96ea5f1ea46650645363f1716fd4e4260c92f614a6af308d4ca2e352b4dbd3d8f326e5a513c20b3029163284257e", + "digest": "02e1e5a9c9612830b0dfbc7e0e73ce13667254658b1177a8888ecdf2f3c729cfed158e4bde6c113e31112360f6d5df97", "event": "app-id", - "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfaf" + "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145" }, { "imr": 3, "event_type": 134217729, - "digest": "6d4e926546694d6e8acc53d46b216cde12d3a60cd3b60550ab7db7f4920fc42c304f8af924e08f96c108a7f7076cf02a", + "digest": "0724a946d4c56944af69a502165a07082875b44e15abaa15171dcd44c1c2955303a6bdfa59f2e58e63d206b079a6e5cc", "event": "compose-hash", - "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a" + "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4" }, { "imr": 3, diff --git a/crates/tee-verifier/tests/fixtures/verify_quote_args.borsh b/crates/tee-verifier/tests/fixtures/verify_quote_args.borsh index 3302726634987c244592d373660c7f0b12e5095b..854a0ef7f1245c4699ae9ee06bbd996e99bb6e39 100644 GIT binary patch delta 1615 zcmaFAk@5XT#tCl~SoZQfcz4No-SO4j@eIC!g=cjQUDto~a&NnT=)3*$nkAD38M7x& zV3}OQIHBIQcVBa;l4PKW=fpSDi|%$Qer8%_nwzj_>B)yzyxCnuHvB%*_L^Bh^G?;| z(zO>^_AoG}ed5ddDG|GrIW}kByZtGdn>D9NFgX7Tm71o{qmf}|uzYHz%-+{Gv=xFT z{CHsd@i+qtI3vKo@KN}%AXoP#bC&9frUmg{n~QQo&+2@zi;NaY+oN0{o2F5?`f;CD zbI(qe4RJCy&BtbCozHAPQf6Bcu5EM9Ud@wr^8uz~j1F%zL>4bJeUS6%bL2mrIJUbN ziZZ@-%=liU#yfwR&!t<+8;m^bqKw@a?fG=|xUuoaYi4DcruXLGKbF9++_CucevZw@ zSpJHO8yXrI7#o@zM2YhnnHg9Dd0_73TQbTVFuBQvvLcfuWu;IB{80t;P-S-`%Qh+t zPyT=`05VWb4#_}}ifCj3kcx@O0w5K~kOe?0{vZp0R2a%5846O7jxI14UEngZ0LTmu z1tc>-0=DP^Md$*{(FN`x3xM1qq=;syJGwv(vH(cSCUk)p$O0gT$tockS|}?zIYdbk zH5ximRftU9k1X&|2`Sb<25KoI83+=HM-|XTHT@K-tnlRj$O4KgNT!24l&ykh`T}%; ztLOq;sz_QuW;mb=l%Wf(K^J(0ECBM9xEh+FzQ_U~6;0>@+mQu8?s$tV0MeqQj$|lE zARJww2VLMGy1+MN0gx>^8c2qM1d@;iK(+d`Fp@8$S&k)<19Z zx*9L)$;p26A-}ZSp9CQ$1)+w1Bvr{u$;iOSOxM6t*U$j2X0y2A zPJRa&!NoH(izF>xNqKz#!}RH^X!#}16W@+;7j|us43_L?vFzwOy?^`pTRN9s2D&jh zw$6UNBIk=q=L~uNsvw!kKW751pUn=l+S1C%fRNQ7HJfjF6f-)nk6gxgOIAGfU1Zl6 z?uPs)yyE?;GI8Hzy1t2&RTOW2EHa@`USajSh*b_v&si6It(WEcDrCB_DS1vy^3Eye T6-60i`6dTyDsJXwwc`T-JTdap delta 1615 zcmaFAk@5XT#tCl~j+Mvw&fczWvqU%zi_z_+Q@O>&C*yk3(98M7x& zV3}OQIHA5F;7Zw4^%FiD(%3sf-uG?gTfQ;iLD9Q61?(zZrx>?}u?Q8vvQ=2P@k+bd zw}5lP9~c-fhV4BT7ybVE!^HX<`_CP_YcIRBp=|H7j0?wY9&c00^6TVKFgwPOc>mw; zn^U%}PV!(t0cQjl7*4n!smcwtXBN5`X3Et2X=m4y4}W#Deyu(JRe-xd$WSd=nB}0Q zitWCGB>@_dQug9UB(`Nvhz%}TvXONz>!Jt8(>EVrI>zV_qLw%BZ+Q-n-#(G=Oj+U= zIW`8}omCs!o2e`o*c4}bA+%+OkX?t{^xqXFA)#s4*`;4Rdl`|v=i=j;=Y0;j)<$nW z#`0HO+`!zxz{t|jI7*z?$jrdfzzo8jd`m`|112}QP*!BJq^uOGfIq5$9;)naWZ6b# z;mIG61waO>$srjCQW1?T08%j#SpcNs7_tCJ#UEq=kP1V2BttnIL>KsmEC8}aM+3=FkU$c$0LYf<$O1bxLY&^^v-25Fe08W&IZ5=Xbj-N} zJO1!69t@P;!xuI4@rLkjCI!dye2QGPPUXEnoG-8Z#?(JO?dj^GfDMYbXaBamSF((I zvw&j;`{eBghWZBPAqEy!CYDwv=21#IN_nXjC7}f=i6yB@R!T+&MrOJOmbwOJa5bC7 z4R`W8@WVrz5cdy&hlknn(p-*pE&V!df$n)ue#o^*g5IQD#eDP zn0e(p<#Jy46udT)VHTfaz9Ukl4QTyrcCgh3R>me)rj~fEhN{_o%cGdl*;3{6m2#WF zSp`ig%hP*TSX(8z1SYLsnWy%!=~}R3?xS$MwL22DV{DhS9Bimx%JkDq^3uO$^4T%g Y(+`M$b+I&MjOCjgsHwP_m(`9B02xXEsQ>@~ diff --git a/crates/tee-verifier/tests/verify_quote.rs b/crates/tee-verifier/tests/verify_quote.rs index ce491d56a9..b2e068bcc1 100644 --- a/crates/tee-verifier/tests/verify_quote.rs +++ b/crates/tee-verifier/tests/verify_quote.rs @@ -90,7 +90,7 @@ fn verify_quote__should_return_verified_td10_report_for_valid_fixture() { "f06dfda6dce1cf904d4e2bab1dc370634cf95cefa2ceb2de2eee127c9382698090d7a4a13e14c536ec6c9c3c8fa87077", ), mr_config_id: hex_arr( - "01c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a000000000000000000000000000000", + "0104bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4000000000000000000000000000000", ), mr_owner: hex_arr( "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", @@ -108,10 +108,10 @@ fn verify_quote__should_return_verified_td10_report_for_valid_fixture() { "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", ), rt_mr3: hex_arr( - "8050d4769527c84cb066078854ef8eb50ea7b150e072eeec7007240aca01b556041273ea3d20a1b1d48736f650ce13f0", + "3d8dbe8355221951144991ec9772dd8a21f302aa356d60a2a5c9e1d44b074414b0fbcc86eb031029dc7a9375add104bc", ), report_data: hex_arr( - "0001d156bdc65e5befe7e1617fd8bfcec6dd3f1da58076bde668d0c73ce3b6246a4e89082036c60061dffefbd994b6ab62480000000000000000000000000000", + "000166f20e6af9185da5035d6c9eeebf6469b32996180043fa551a962f0c28683630a795791cbdebd82b205290f8e03df1c70000000000000000000000000000", ), }), ppid: hex::decode("d208dfb1002346ae1bb4ef2a3c055292").unwrap(), diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index a07a691c48..1c2e269ded 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -79,7 +79,8 @@ two encodings are expected to differ. This is optional — the tests only verify parsing, not measurement values — but keeping it in sync avoids confusion. -7. Update the compiled-in measurements in `crates/mpc-attestation/assets/`: +7. Update the compiled-in measurements in `crates/mpc-attestation/assets/`. Skippable when only the + app-compose changed: these cover `mrtd` and `rtmr0`-`rtmr2`, while the app-compose feeds `rtmr3`. - `tcb_info_dev.json` — replace with the `tcb_info.json` from a **dev** image attestation - `tcb_info.json` — replace with the `tcb_info.json` from a **release** (non-dev) image attestation diff --git a/crates/test-utils/assets/app_compose.json b/crates/test-utils/assets/app_compose.json index 15e014b9e8..db139628a1 100644 --- a/crates/test-utils/assets/app_compose.json +++ b/crates/test-utils/assets/app_compose.json @@ -1,6 +1,6 @@ { "manifest_version": 2, - "name": "mpc-localnet-one-node-1786102851", + "name": "mpc-localnet-one-node-1786440162", "runner": "docker-compose", "docker_compose_file": "version: '3.8'\n\nservices:\n launcher:\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\n\n container_name: launcher\n\n environment:\n - PLATFORM=TEE\n - DOCKER_CONTENT_TRUST=1\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\n\n volumes:\n - /var/run/docker.sock:/var/run/docker.sock\n - /var/run/dstack.sock:/var/run/dstack.sock\n - /tapp:/tapp:ro\n - shared-volume:/mnt/shared:rw\n\n security_opt:\n - no-new-privileges:true\n\n read_only: true\n\n tmpfs:\n - /tmp\n\nvolumes:\n shared-volume:\n name: shared-volume\n", "kms_enabled": false, @@ -12,5 +12,5 @@ "allowed_envs": [], "no_instance_id": true, "secure_time": false, - "pre_launch_script": "#!/bin/sh\n# Test-asset collection hook, sourced by the CVM's app-compose.sh before the\n# node starts. The node generates its NEAR signer key in-enclave, so exporting\n# that key is the only way to check the fixture keypair into the repo next to\n# the quote it is bound to (near/mpc #3787).\n#\n# The key appears only after the node starts, i.e. after this hook returns, so\n# the wait runs as its own systemd unit: a plain background process would be\n# reaped with app-compose.service's cgroup. The copy target is the CVM's\n# host-shared dir, which the host sees as run/vm//shared/.\n#\n# The guest userland is BusyBox, so the wait loop sticks to shell built-ins and\n# globs (no find/head, whose GNU options BusyBox rejects).\n#\n# Only ever use this on a throwaway localnet CVM: it exports a private key.\n\nCONSOLE=/dev/console\nSHARED=/dstack/.host-shared\nEXFIL=/etc/fixture-exfil.sh\n\ncat > \"$EXFIL\" <<'EOF'\n#!/bin/sh\nCONSOLE=/dev/console\nSHARED=/dstack/.host-shared\ni=0\nwhile [ \"$i\" -lt 900 ]; do\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\n if [ -f \"$f\" ]; then\n cp \"$f\" \"$SHARED/fixture-secrets.json\" 2>/dev/null\n {\n echo \"FIXTURE-SECRETS-BEGIN $f\"\n cat \"$f\"\n echo \"\"\n echo \"FIXTURE-SECRETS-END\"\n } > \"$CONSOLE\" 2>&1\n exit 0\n fi\n done\n i=$((i + 1))\n sleep 2\ndone\necho \"FIXTURE-SECRETS-TIMEOUT\" > \"$CONSOLE\" 2>&1\nEOF\nchmod +x \"$EXFIL\" 2>/dev/null\n\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\n[Unit]\nDescription=Export the MPC node signer key for test-asset collection\n[Service]\nType=oneshot\nExecStart=/bin/sh /etc/fixture-exfil.sh\nStandardOutput=journal+console\nStandardError=journal+console\nEOF\n\nsystemctl daemon-reload >/dev/null 2>&1\nsystemctl start --no-block fixture-exfil.service >/dev/null 2>&1\n\n{\n echo \"FIXTURE-DIAG-BEGIN\"\n echo \"exfil_script=$([ -f \"$EXFIL\" ] && echo present || echo missing)\"\n echo \"unit_state=$(systemctl is-active fixture-exfil.service 2>&1)\"\n echo \"shared_writable=$([ -w \"$SHARED\" ] && echo yes || echo no)\"\n echo \"FIXTURE-DIAG-END\"\n} > \"$CONSOLE\" 2>&1\n" + "pre_launch_script": "#!/bin/sh\ncat > /etc/fixture-exfil.sh <<'EOF'\n#!/bin/sh\nwhile :; do\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\n [ -f \"$f\" ] && cat \"$f\" > /dev/console && exit 0\n done\n sleep 2\ndone\nEOF\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\n[Service]\nExecStart=/bin/sh /etc/fixture-exfil.sh\nEOF\nsystemctl daemon-reload\nsystemctl start --no-block fixture-exfil.service\n" } \ No newline at end of file diff --git a/crates/test-utils/assets/collateral.json b/crates/test-utils/assets/collateral.json index 37c91ac1f7..c65dc802f8 100644 --- a/crates/test-utils/assets/collateral.json +++ b/crates/test-utils/assets/collateral.json @@ -1,12 +1,12 @@ { "pck_crl_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", "root_ca_crl": "308201223081c8020101300a06082a8648ce3d0403023068311a301806035504030c11496e74656c2053475820526f6f74204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303232363133303430305a170d3237303232363133303430305aa02f302d300a0603551d140403020101301f0603551d2304183016801422650cd65a9d3489f383b49552bf501b392706ac300a06082a8648ce3d0403020349003046022100c252ed59c795ba2b11496a4a99758bb8cbc380a1ebbb0865be69f2c4b38bb6400221009a7d8b03602a9ee2d62322d759166d6933d24d9dfa01ab3fde4520691d715bd7", - "pck_crl": "30820d1730820cbd020101300a06082a8648ce3d04030230703122302006035504030c19496e74656c205347582050434b20506c6174666f726d204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303830373030323931335a170d3236303930363030323931335a30820be9303302146fc34e5023e728923435d61aa4b83c618166ad35170d3236303830373030323931335a300c300a0603551d1504030a01013034021500efae6e9715fca13b87e333e8261ed6d990a926ad170d3236303830373030323931335a300c300a0603551d1504030a01013034021500fd608648629cba73078b4d492f4b3ea741ad08cd170d3236303830373030323931335a300c300a0603551d1504030a010130340215008af924184e1d5afddd73c3d63a12f5e8b5737e56170d3236303830373030323931335a300c300a0603551d1504030a01013034021500b1257978cfa9ccdd0759abf8c5ca72fae3a78a9b170d3236303830373030323931335a300c300a0603551d1504030a01013033021474fea614a972be0e2843f2059835811ed872f9b3170d3236303830373030323931335a300c300a0603551d1504030a01013034021500f9c4ef56b3ab48d577e108baedf4bf88014214b9170d3236303830373030323931335a300c300a0603551d1504030a010130330214071de0778f9e5fc4f2878f30d6b07c9a30e6b30b170d3236303830373030323931335a300c300a0603551d1504030a01013034021500cde2424f972cea94ff239937f4d80c25029dd60b170d3236303830373030323931335a300c300a0603551d1504030a0101303302146c3319e5109b64507d3cf1132ce00349ef527319170d3236303830373030323931335a300c300a0603551d1504030a01013034021500df08d756b66a7497f43b5bb58ada04d3f4f7a937170d3236303830373030323931335a300c300a0603551d1504030a01013033021428af485b6cf67e409a39d5cb5aee4598f7a8fa7b170d3236303830373030323931335a300c300a0603551d1504030a01013034021500fb8b2daec092cada8aa9bc4ff2f1c20d0346668c170d3236303830373030323931335a300c300a0603551d1504030a01013034021500cd4850ac52bdcc69a6a6f058c8bc57bbd0b5f864170d3236303830373030323931335a300c300a0603551d1504030a01013034021500994dd3666f5275fb805f95dd02bd50cb2679d8ad170d3236303830373030323931335a300c300a0603551d1504030a0101303302140702136900252274d9035eedf5457462fad0ef4c170d3236303830373030323931335a300c300a0603551d1504030a01013033021461f2bf73e39b4e04aa27d801bd73d24319b5bf80170d3236303830373030323931335a300c300a0603551d1504030a0101303302143992be851b96902eff38959e6c2eff1b0651a4b5170d3236303830373030323931335a300c300a0603551d1504030a0101303302140fda43a00b68ea79b7c2deaeac0b498bdfb2af90170d3236303830373030323931335a300c300a0603551d1504030a010130330214639f139a5040fdcff191e8a4fb1bf086ed603971170d3236303830373030323931335a300c300a0603551d1504030a01013034021500959d533f9249dc1e513544cdc830bf19b7f1f301170d3236303830373030323931335a300c300a0603551d1504030a0101303302147ae37748a9f912f4c63ba7ab07c593ce1d1d1181170d3236303830373030323931335a300c300a0603551d1504030a01013033021413884b33269938c195aa170fca75da177538df0b170d3236303830373030323931335a300c300a0603551d1504030a0101303402150085d3c9381b77a7e04d119c9e5ad6749ff3ffab87170d3236303830373030323931335a300c300a0603551d1504030a0101303402150093887ca4411e7a923bd1fed2819b2949f201b5b4170d3236303830373030323931335a300c300a0603551d1504030a0101303302142498dc6283930996fd8bf23a37acbe26a3bed457170d3236303830373030323931335a300c300a0603551d1504030a010130340215008a66f1a749488667689cc3903ac54c662b712e73170d3236303830373030323931335a300c300a0603551d1504030a01013034021500afc13610bdd36cb7985d106481a880d3a01fda07170d3236303830373030323931335a300c300a0603551d1504030a01013034021500efe04b2c33d036aac96ca673bf1e9a47b64d5cbb170d3236303830373030323931335a300c300a0603551d1504030a0101303402150083d9ac8d8bb509d1c6c809ad712e8430559ed7f3170d3236303830373030323931335a300c300a0603551d1504030a0101303302147931fd50b5071c1bbfc5b7b6ded8b45b9d8b8529170d3236303830373030323931335a300c300a0603551d1504030a0101303302141fa20e2970bde5d57f7b8ddf8339484e1f1d0823170d3236303830373030323931335a300c300a0603551d1504030a0101303302141e87b2c3b32d8d23e411cef34197b95af0c8adf5170d3236303830373030323931335a300c300a0603551d1504030a010130340215009afd2ee90a473550a167d996911437c7502d1f09170d3236303830373030323931335a300c300a0603551d1504030a0101303302144481b0f11728a13b696d3ea9c770a0b15ec58dda170d3236303830373030323931335a300c300a0603551d1504030a01013034021500a7859f57982ef0e67d37bc8ef2ef5ac835ff1aa9170d3236303830373030323931335a300c300a0603551d1504030a010130340215009d67753b81e47090aea763fbec4c4549bcdb9933170d3236303830373030323931335a300c300a0603551d1504030a01013033021434bfbb7a1d9c568147e118b614f7b76ed3ef68df170d3236303830373030323931335a300c300a0603551d1504030a0101303302142c3cc6fe9279db1516d5ce39f2a898cda5a175e1170d3236303830373030323931335a300c300a0603551d1504030a010130330214717948687509234be979e4b7dce6f31bef64b68c170d3236303830373030323931335a300c300a0603551d1504030a010130340215009d76ef2c39c136e8658b6e7396b1d7445a27631f170d3236303830373030323931335a300c300a0603551d1504030a01013034021500c3e025fca995f36f59b48467939e3e34e6361a6f170d3236303830373030323931335a300c300a0603551d1504030a010130340215008c5f6b3257da05b17429e2e61ba965d67330606a170d3236303830373030323931335a300c300a0603551d1504030a01013034021500a17c51722ec1e0c3278fe8bdf052059cbec4e648170d3236303830373030323931335a300c300a0603551d1504030a01013033021411c943b866fa04944e3057e5a67146596475a023170d3236303830373030323931335a300c300a0603551d1504030a01013034021500be6913785406155454a28885a515b3da5767d3a9170d3236303830373030323931335a300c300a0603551d1504030a0101303302140ac5ec91bd934c07b9ea41625e9cc09681002eb0170d3236303830373030323931335a300c300a0603551d1504030a0101303302146d51a0eabc1f9a1e9ddd5b36bdda1631ae6c182a170d3236303830373030323931335a300c300a0603551d1504030a01013034021500a52c5d71c4166b4fc0ded8b679951e5ee9193de5170d3236303830373030323931335a300c300a0603551d1504030a010130330214249779aedd85fcac93c8853516be5428c26b3bf8170d3236303830373030323931335a300c300a0603551d1504030a01013033021434ba4fd76bde5309210cf1dd1ffb494c638a9157170d3236303830373030323931335a300c300a0603551d1504030a010130330214043e04919daae13443248395094d2a2eacfc76fe170d3236303830373030323931335a300c300a0603551d1504030a01013033021447fc577d2d094cbdf270715ed6848a93855ad34b170d3236303830373030323931335a300c300a0603551d1504030a0101303302147d62a2f5e6f386e469653fffff045d0a8178e8e7170d3236303830373030323931335a300c300a0603551d1504030a01013034021500c4ed45fe026bb6a47eaec35ea80b7ef407ce062c170d3236303830373030323931335a300c300a0603551d1504030a01013034021500cf9831077a3ca4f1a2c56867bf55b18eccbeffd8170d3236303830373030323931335a300c300a0603551d1504030a0101303302146c2b81d7ea2e436720ce29f1d0b1ccb7a218600f170d3236303830373030323931335a300c300a0603551d1504030a0101a02f302d300a0603551d140403020101301f0603551d23041830168014956f5dcdbd1be1e94049c9d4f433ce01570bde54300a06082a8648ce3d0403020348003045022100ee6f070e3191eac279236215e51b5ccec0b8fc0c01c1511bbc0e5a99e3b0578b022041cf0e210a7d42778df843d3a9f6028f9766e5ab7250b021db9bfb39de74a60b", + "pck_crl": "30820d1730820cbd020101300a06082a8648ce3d04030230703122302006035504030c19496e74656c205347582050434b20506c6174666f726d204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303831313030333135305a170d3236303931303030333135305a30820be9303302146fc34e5023e728923435d61aa4b83c618166ad35170d3236303831313030333135305a300c300a0603551d1504030a01013034021500efae6e9715fca13b87e333e8261ed6d990a926ad170d3236303831313030333135305a300c300a0603551d1504030a01013034021500fd608648629cba73078b4d492f4b3ea741ad08cd170d3236303831313030333135305a300c300a0603551d1504030a010130340215008af924184e1d5afddd73c3d63a12f5e8b5737e56170d3236303831313030333135305a300c300a0603551d1504030a01013034021500b1257978cfa9ccdd0759abf8c5ca72fae3a78a9b170d3236303831313030333135305a300c300a0603551d1504030a01013033021474fea614a972be0e2843f2059835811ed872f9b3170d3236303831313030333135305a300c300a0603551d1504030a01013034021500f9c4ef56b3ab48d577e108baedf4bf88014214b9170d3236303831313030333135305a300c300a0603551d1504030a010130330214071de0778f9e5fc4f2878f30d6b07c9a30e6b30b170d3236303831313030333135305a300c300a0603551d1504030a01013034021500cde2424f972cea94ff239937f4d80c25029dd60b170d3236303831313030333135305a300c300a0603551d1504030a0101303302146c3319e5109b64507d3cf1132ce00349ef527319170d3236303831313030333135305a300c300a0603551d1504030a01013034021500df08d756b66a7497f43b5bb58ada04d3f4f7a937170d3236303831313030333135305a300c300a0603551d1504030a01013033021428af485b6cf67e409a39d5cb5aee4598f7a8fa7b170d3236303831313030333135305a300c300a0603551d1504030a01013034021500fb8b2daec092cada8aa9bc4ff2f1c20d0346668c170d3236303831313030333135305a300c300a0603551d1504030a01013034021500cd4850ac52bdcc69a6a6f058c8bc57bbd0b5f864170d3236303831313030333135305a300c300a0603551d1504030a01013034021500994dd3666f5275fb805f95dd02bd50cb2679d8ad170d3236303831313030333135305a300c300a0603551d1504030a0101303302140702136900252274d9035eedf5457462fad0ef4c170d3236303831313030333135305a300c300a0603551d1504030a01013033021461f2bf73e39b4e04aa27d801bd73d24319b5bf80170d3236303831313030333135305a300c300a0603551d1504030a0101303302143992be851b96902eff38959e6c2eff1b0651a4b5170d3236303831313030333135305a300c300a0603551d1504030a0101303302140fda43a00b68ea79b7c2deaeac0b498bdfb2af90170d3236303831313030333135305a300c300a0603551d1504030a010130330214639f139a5040fdcff191e8a4fb1bf086ed603971170d3236303831313030333135305a300c300a0603551d1504030a01013034021500959d533f9249dc1e513544cdc830bf19b7f1f301170d3236303831313030333135305a300c300a0603551d1504030a0101303302147ae37748a9f912f4c63ba7ab07c593ce1d1d1181170d3236303831313030333135305a300c300a0603551d1504030a01013033021413884b33269938c195aa170fca75da177538df0b170d3236303831313030333135305a300c300a0603551d1504030a0101303402150085d3c9381b77a7e04d119c9e5ad6749ff3ffab87170d3236303831313030333135305a300c300a0603551d1504030a0101303402150093887ca4411e7a923bd1fed2819b2949f201b5b4170d3236303831313030333135305a300c300a0603551d1504030a0101303302142498dc6283930996fd8bf23a37acbe26a3bed457170d3236303831313030333135305a300c300a0603551d1504030a010130340215008a66f1a749488667689cc3903ac54c662b712e73170d3236303831313030333135305a300c300a0603551d1504030a01013034021500afc13610bdd36cb7985d106481a880d3a01fda07170d3236303831313030333135305a300c300a0603551d1504030a01013034021500efe04b2c33d036aac96ca673bf1e9a47b64d5cbb170d3236303831313030333135305a300c300a0603551d1504030a0101303402150083d9ac8d8bb509d1c6c809ad712e8430559ed7f3170d3236303831313030333135305a300c300a0603551d1504030a0101303302147931fd50b5071c1bbfc5b7b6ded8b45b9d8b8529170d3236303831313030333135305a300c300a0603551d1504030a0101303302141fa20e2970bde5d57f7b8ddf8339484e1f1d0823170d3236303831313030333135305a300c300a0603551d1504030a0101303302141e87b2c3b32d8d23e411cef34197b95af0c8adf5170d3236303831313030333135305a300c300a0603551d1504030a010130340215009afd2ee90a473550a167d996911437c7502d1f09170d3236303831313030333135305a300c300a0603551d1504030a0101303302144481b0f11728a13b696d3ea9c770a0b15ec58dda170d3236303831313030333135305a300c300a0603551d1504030a01013034021500a7859f57982ef0e67d37bc8ef2ef5ac835ff1aa9170d3236303831313030333135305a300c300a0603551d1504030a010130340215009d67753b81e47090aea763fbec4c4549bcdb9933170d3236303831313030333135305a300c300a0603551d1504030a01013033021434bfbb7a1d9c568147e118b614f7b76ed3ef68df170d3236303831313030333135305a300c300a0603551d1504030a0101303302142c3cc6fe9279db1516d5ce39f2a898cda5a175e1170d3236303831313030333135305a300c300a0603551d1504030a010130330214717948687509234be979e4b7dce6f31bef64b68c170d3236303831313030333135305a300c300a0603551d1504030a010130340215009d76ef2c39c136e8658b6e7396b1d7445a27631f170d3236303831313030333135305a300c300a0603551d1504030a01013034021500c3e025fca995f36f59b48467939e3e34e6361a6f170d3236303831313030333135305a300c300a0603551d1504030a010130340215008c5f6b3257da05b17429e2e61ba965d67330606a170d3236303831313030333135305a300c300a0603551d1504030a01013034021500a17c51722ec1e0c3278fe8bdf052059cbec4e648170d3236303831313030333135305a300c300a0603551d1504030a01013033021411c943b866fa04944e3057e5a67146596475a023170d3236303831313030333135305a300c300a0603551d1504030a01013034021500be6913785406155454a28885a515b3da5767d3a9170d3236303831313030333135305a300c300a0603551d1504030a0101303302140ac5ec91bd934c07b9ea41625e9cc09681002eb0170d3236303831313030333135305a300c300a0603551d1504030a0101303302146d51a0eabc1f9a1e9ddd5b36bdda1631ae6c182a170d3236303831313030333135305a300c300a0603551d1504030a01013034021500a52c5d71c4166b4fc0ded8b679951e5ee9193de5170d3236303831313030333135305a300c300a0603551d1504030a010130330214249779aedd85fcac93c8853516be5428c26b3bf8170d3236303831313030333135305a300c300a0603551d1504030a01013033021434ba4fd76bde5309210cf1dd1ffb494c638a9157170d3236303831313030333135305a300c300a0603551d1504030a010130330214043e04919daae13443248395094d2a2eacfc76fe170d3236303831313030333135305a300c300a0603551d1504030a01013033021447fc577d2d094cbdf270715ed6848a93855ad34b170d3236303831313030333135305a300c300a0603551d1504030a0101303302147d62a2f5e6f386e469653fffff045d0a8178e8e7170d3236303831313030333135305a300c300a0603551d1504030a01013034021500c4ed45fe026bb6a47eaec35ea80b7ef407ce062c170d3236303831313030333135305a300c300a0603551d1504030a01013034021500cf9831077a3ca4f1a2c56867bf55b18eccbeffd8170d3236303831313030333135305a300c300a0603551d1504030a0101303302146c2b81d7ea2e436720ce29f1d0b1ccb7a218600f170d3236303831313030333135305a300c300a0603551d1504030a0101a02f302d300a0603551d140403020101301f0603551d23041830168014956f5dcdbd1be1e94049c9d4f433ce01570bde54300a06082a8648ce3d0403020348003045022100d27ee98df01b6f411c7cd8f93040afe7824ad55f15490907d9e10f1b46fc60120220125df01334c0c7d3e810b3212eb0c22ba01cd204e16734816003287a742b2780", "tcb_info_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-07T08:49:47Z\",\"nextUpdate\":\"2026-09-06T08:49:47Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":19,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", - "tcb_info_signature": "0f5ddee099297b309e9b41c4ce6bbaebf6b99ca7a6f482de8f33c8c8e5978ec8adea8aefa8b992c4aa2180725c9e77b91e6ceb8c70eb321c03179437b8592486", + "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-11T00:36:45Z\",\"nextUpdate\":\"2026-09-10T00:36:45Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":19,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", + "tcb_info_signature": "1c11a39969721938ea1a48f7fc02f2f51577d209c8f6c60b718ab01953198f0439888ecbbfb7cfda2cd2e951460241859beba86cf43489981f0f7a521c93f999", "qe_identity_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-07T00:34:59Z\",\"nextUpdate\":\"2026-09-06T00:34:59Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", - "qe_identity_signature": "3924f3d4773c519a708264a7678da83b3a62445162aba96e26e182d653416de2572eadb8602b5c3da484c1807fa502f94a19d2fea61f6b5c3b97c017f5443935", + "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-11T00:39:20Z\",\"nextUpdate\":\"2026-09-10T00:39:20Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", + "qe_identity_signature": "af59a60eda1d1765ee598af40b806fe40d178f251c5ef61c8af614767873b3e31490711f20abee58aa4082e705a0f57f1d0af51235a182639c8463b994cf2115", "pck_certificate_chain": "-----BEGIN CERTIFICATE-----\nMIIE8TCCBJagAwIBAgIUf2SbywkMVTJKU57/JwBp8EdhP04wCgYIKoZIzj0EAwIw\ncDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBDSyBQbGF0Zm9ybSBDQTEaMBgGA1UECgwR\nSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQI\nDAJDQTELMAkGA1UEBhMCVVMwHhcNMjUxMTA2MDczNzM0WhcNMzIxMTA2MDczNzM0\nWjBwMSIwIAYDVQQDDBlJbnRlbCBTR1ggUENLIENlcnRpZmljYXRlMRowGAYDVQQK\nDBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV\nBAgMAkNBMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGpv\n0YuYrqAuSKBzKlub6mL+rvfD5AjYO3QNgfWztg4em1EGBVkGlWvduB0XQSE/sxGD\nmSvKo9t3CrOPC4SU6X6jggMMMIIDCDAfBgNVHSMEGDAWgBSVb13NvRvh6UBJydT0\nM84BVwveVDBrBgNVHR8EZDBiMGCgXqBchlpodHRwczovL2FwaS50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL3NneC9jZXJ0aWZpY2F0aW9uL3Y0L3Bja2NybD9jYT1w\nbGF0Zm9ybSZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFG3n6S+KxN6t+HI8Gp96PkuZ\niWsZMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIICOQYJKoZIhvhNAQ0B\nBIICKjCCAiYwHgYKKoZIhvhNAQ0BAQQQ0gjfsQAjRq4btO8qPAVSkjCCAWMGCiqG\nSIb4TQENAQIwggFTMBAGCyqGSIb4TQENAQIBAgEEMBAGCyqGSIb4TQENAQICAgEE\nMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgECMBAGCyqGSIb4TQEN\nAQIFAgEEMBAGCyqGSIb4TQENAQIGAgEBMBAGCyqGSIb4TQENAQIHAgEAMBAGCyqG\nSIb4TQENAQIIAgEFMBAGCyqGSIb4TQENAQIJAgEAMBAGCyqGSIb4TQENAQIKAgEA\nMBAGCyqGSIb4TQENAQILAgEAMBAGCyqGSIb4TQENAQIMAgEAMBAGCyqGSIb4TQEN\nAQINAgEAMBAGCyqGSIb4TQENAQIOAgEAMBAGCyqGSIb4TQENAQIPAgEAMBAGCyqG\nSIb4TQENAQIQAgEAMBAGCyqGSIb4TQENAQIRAgELMB8GCyqGSIb4TQENAQISBBAE\nBAICBAEABQAAAAAAAAAAMBAGCiqGSIb4TQENAQMEAgAAMBQGCiqGSIb4TQENAQQE\nBrDAbwAAADAPBgoqhkiG+E0BDQEFCgEBMB4GCiqGSIb4TQENAQYEEDa9htA8AJ/Z\n2FmaL5Jq/KEwRAYKKoZIhvhNAQ0BBzA2MBAGCyqGSIb4TQENAQcBAQH/MBAGCyqG\nSIb4TQENAQcCAQH/MBAGCyqGSIb4TQENAQcDAQH/MAoGCCqGSM49BAMCA0kAMEYC\nIQCFG1YAb3eXFte853ClVBnhlCfDyc572ZXEqax4UccSawIhAOn0VNKTZmAxUF4n\nwRkSFh4qFJ3aUlzFoPQT3xIf7kFD\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n" } diff --git a/crates/test-utils/assets/near_account_public_key.pub b/crates/test-utils/assets/near_account_public_key.pub index bac11e48a4..0499745b14 100644 --- a/crates/test-utils/assets/near_account_public_key.pub +++ b/crates/test-utils/assets/near_account_public_key.pub @@ -1 +1 @@ -ed25519:358qw8dtHdSNrvvnMcvJMevLczZbgiCAcBYz1hytEmey \ No newline at end of file +ed25519:7QgyPZrqjThDLHk7fhTZudhZJepK7kuRZbuyfKk8o2N5 \ No newline at end of file diff --git a/crates/test-utils/assets/near_account_secret_key b/crates/test-utils/assets/near_account_secret_key index 591682cc28..5cc3d59ae7 100644 --- a/crates/test-utils/assets/near_account_secret_key +++ b/crates/test-utils/assets/near_account_secret_key @@ -1 +1 @@ -ed25519:rS6SmFPPaViyKph7Uapy4Gb8ZfBHwmRMCEUfgmpAYyi8hdgkeKpVMPJDwaQjp6GrkdCgViKRy7hrjUmJwarZcLR +ed25519:3ih6YgrZivpBXHY86XKtKf5XFmDnLGDwbvPSzZGrwuwJetkDt9NhC1D5889vMnsLBrf82U4QHC5NatoX6umd3AmX diff --git a/crates/test-utils/assets/near_p2p_public_key.pub b/crates/test-utils/assets/near_p2p_public_key.pub index 50c242a044..d59aa91a91 100644 --- a/crates/test-utils/assets/near_p2p_public_key.pub +++ b/crates/test-utils/assets/near_p2p_public_key.pub @@ -1 +1 @@ -ed25519:At5UoXyzh8GmPAV6e7J1Lqm5iGcoLCCw3udnAjt4jhpG \ No newline at end of file +ed25519:Dd8m9GntLsd8LFwS1XyPdnat3qNwi6sGN3fHGBTekWXZ \ No newline at end of file diff --git a/crates/test-utils/assets/public_data.json b/crates/test-utils/assets/public_data.json index 764d853875..57921c5927 100644 --- a/crates/test-utils/assets/public_data.json +++ b/crates/test-utils/assets/public_data.json @@ -1,20 +1,20 @@ { - "near_signer_public_key": "ed25519:358qw8dtHdSNrvvnMcvJMevLczZbgiCAcBYz1hytEmey", - "near_p2p_public_key": "ed25519:At5UoXyzh8GmPAV6e7J1Lqm5iGcoLCCw3udnAjt4jhpG", - "near_responder_public_keys": ["ed25519:8Vr17qtmPGyA98mZbZ1ZRkPGkNuZVULHhgczrUrJreCS"], + "near_signer_public_key": "ed25519:7QgyPZrqjThDLHk7fhTZudhZJepK7kuRZbuyfKk8o2N5", + "near_p2p_public_key": "ed25519:Dd8m9GntLsd8LFwS1XyPdnat3qNwi6sGN3fHGBTekWXZ", + "near_responder_public_keys": ["ed25519:8e1LvK9dj1miMWL3ixab8a3gkAFo7F5RXapvhZSmcgJE"], "tee_participant_info": { "Dstack": { - "quote": [4, 0, 2, 0, 129, 0, 0, 0, 0, 0, 0, 0, 147, 154, 114, 51, 247, 156, 76, 169, 148, 10, 13, 179, 149, 127, 6, 7, 61, 153, 138, 108, 16, 87, 107, 253, 246, 246, 237, 142, 155, 133, 233, 50, 0, 0, 0, 0, 11, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 240, 99, 40, 14, 148, 251, 5, 31, 93, 215, 177, 252, 89, 206, 154, 172, 66, 187, 150, 29, 248, 212, 75, 112, 156, 155, 15, 248, 122, 123, 77, 246, 72, 101, 123, 166, 209, 24, 149, 137, 254, 171, 29, 90, 60, 154, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 231, 2, 6, 0, 0, 0, 0, 0, 240, 109, 253, 166, 220, 225, 207, 144, 77, 78, 43, 171, 29, 195, 112, 99, 76, 249, 92, 239, 162, 206, 178, 222, 46, 238, 18, 124, 147, 130, 105, 128, 144, 215, 164, 161, 62, 20, 197, 54, 236, 108, 156, 60, 143, 168, 112, 119, 1, 198, 119, 92, 77, 155, 183, 39, 60, 162, 28, 213, 75, 230, 182, 161, 135, 147, 40, 223, 175, 190, 181, 80, 246, 149, 123, 130, 30, 33, 47, 13, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 115, 190, 47, 112, 190, 239, 183, 11, 72, 166, 16, 158, 237, 71, 21, 215, 39, 13, 70, 131, 179, 191, 53, 111, 162, 95, 175, 191, 26, 167, 110, 57, 233, 18, 126, 110, 104, 140, 205, 169, 139, 218, 177, 212, 212, 127, 70, 181, 152, 253, 233, 73, 20, 39, 52, 27, 196, 104, 59, 117, 209, 13, 62, 54, 119, 10, 243, 163, 106, 105, 84, 216, 182, 183, 178, 42, 166, 99, 88, 241, 62, 31, 23, 46, 81, 183, 214, 230, 113, 13, 153, 168, 216, 83, 47, 200, 18, 212, 43, 255, 241, 199, 83, 130, 233, 26, 55, 200, 103, 171, 17, 123, 151, 235, 94, 141, 103, 151, 72, 137, 40, 234, 56, 229, 253, 56, 181, 237, 47, 135, 217, 97, 61, 57, 37, 7, 241, 195, 175, 148, 101, 124, 147, 128, 80, 212, 118, 149, 39, 200, 76, 176, 102, 7, 136, 84, 239, 142, 181, 14, 167, 177, 80, 224, 114, 238, 236, 112, 7, 36, 10, 202, 1, 181, 86, 4, 18, 115, 234, 61, 32, 161, 177, 212, 135, 54, 246, 80, 206, 19, 240, 0, 1, 209, 86, 189, 198, 94, 91, 239, 231, 225, 97, 127, 216, 191, 206, 198, 221, 63, 29, 165, 128, 118, 189, 230, 104, 208, 199, 60, 227, 182, 36, 106, 78, 137, 8, 32, 54, 198, 0, 97, 223, 254, 251, 217, 148, 182, 171, 98, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 16, 0, 0, 200, 71, 196, 122, 109, 85, 63, 3, 18, 209, 86, 2, 141, 242, 185, 138, 228, 240, 253, 45, 106, 250, 173, 199, 245, 16, 11, 112, 18, 49, 38, 99, 19, 4, 193, 57, 36, 61, 190, 193, 116, 80, 40, 89, 26, 63, 23, 196, 24, 182, 105, 144, 93, 83, 116, 164, 177, 5, 157, 5, 162, 224, 199, 103, 142, 188, 151, 224, 189, 139, 21, 116, 87, 28, 157, 151, 225, 226, 250, 218, 147, 80, 231, 144, 252, 223, 62, 103, 176, 31, 51, 101, 181, 44, 82, 180, 72, 148, 151, 10, 88, 144, 81, 87, 230, 135, 174, 102, 165, 143, 241, 229, 60, 148, 151, 208, 187, 151, 100, 64, 82, 171, 52, 1, 40, 143, 31, 160, 6, 0, 70, 16, 0, 0, 4, 4, 25, 27, 4, 255, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 229, 163, 167, 181, 216, 48, 194, 149, 59, 152, 83, 76, 108, 89, 163, 163, 79, 220, 52, 233, 51, 247, 245, 137, 143, 10, 133, 207, 8, 132, 107, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 158, 42, 124, 111, 148, 143, 23, 71, 78, 52, 167, 252, 67, 237, 3, 15, 124, 21, 99, 241, 186, 189, 223, 99, 64, 200, 46, 14, 84, 168, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 98, 66, 167, 203, 62, 30, 139, 2, 195, 192, 57, 51, 40, 206, 207, 77, 159, 207, 61, 144, 77, 52, 130, 175, 199, 184, 139, 101, 54, 6, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 38, 110, 158, 253, 119, 108, 12, 78, 190, 20, 247, 2, 106, 23, 209, 8, 177, 82, 221, 154, 125, 85, 141, 105, 35, 22, 81, 130, 94, 61, 208, 85, 132, 184, 18, 62, 136, 70, 151, 251, 120, 116, 84, 85, 102, 215, 7, 27, 232, 230, 233, 88, 107, 188, 209, 227, 153, 207, 76, 194, 69, 125, 91, 32, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 5, 0, 94, 14, 0, 0, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 56, 84, 67, 67, 66, 74, 97, 103, 65, 119, 73, 66, 65, 103, 73, 85, 102, 50, 83, 98, 121, 119, 107, 77, 86, 84, 74, 75, 85, 53, 55, 47, 74, 119, 66, 112, 56, 69, 100, 104, 80, 48, 52, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 99, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 119, 119, 90, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 66, 68, 83, 121, 66, 81, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 66, 68, 81, 84, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, 82, 10, 83, 87, 53, 48, 90, 87, 119, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 77, 67, 49, 78, 104, 98, 110, 82, 104, 73, 69, 78, 115, 89, 88, 74, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 73, 10, 68, 65, 74, 68, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 119, 72, 104, 99, 78, 77, 106, 85, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 87, 104, 99, 78, 77, 122, 73, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 10, 87, 106, 66, 119, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 68, 66, 108, 74, 98, 110, 82, 108, 98, 67, 66, 84, 82, 49, 103, 103, 85, 69, 78, 76, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 10, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 66, 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 71, 112, 118, 10, 48, 89, 117, 89, 114, 113, 65, 117, 83, 75, 66, 122, 75, 108, 117, 98, 54, 109, 76, 43, 114, 118, 102, 68, 53, 65, 106, 89, 79, 51, 81, 78, 103, 102, 87, 122, 116, 103, 52, 101, 109, 49, 69, 71, 66, 86, 107, 71, 108, 87, 118, 100, 117, 66, 48, 88, 81, 83, 69, 47, 115, 120, 71, 68, 10, 109, 83, 118, 75, 111, 57, 116, 51, 67, 114, 79, 80, 67, 52, 83, 85, 54, 88, 54, 106, 103, 103, 77, 77, 77, 73, 73, 68, 67, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 86, 98, 49, 51, 78, 118, 82, 118, 104, 54, 85, 66, 74, 121, 100, 84, 48, 10, 77, 56, 52, 66, 86, 119, 118, 101, 86, 68, 66, 114, 66, 103, 78, 86, 72, 82, 56, 69, 90, 68, 66, 105, 77, 71, 67, 103, 88, 113, 66, 99, 104, 108, 112, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 70, 119, 97, 83, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 51, 78, 110, 101, 67, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 76, 51, 89, 48, 76, 51, 66, 106, 97, 50, 78, 121, 98, 68, 57, 106, 89, 84, 49, 119, 10, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 90, 108, 98, 109, 78, 118, 90, 71, 108, 117, 90, 122, 49, 107, 90, 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 71, 51, 110, 54, 83, 43, 75, 120, 78, 54, 116, 43, 72, 73, 56, 71, 112, 57, 54, 80, 107, 117, 90, 10, 105, 87, 115, 90, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 65, 106, 65, 65, 77, 73, 73, 67, 79, 81, 89, 74, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 10, 66, 73, 73, 67, 75, 106, 67, 67, 65, 105, 89, 119, 72, 103, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 65, 81, 81, 81, 48, 103, 106, 102, 115, 81, 65, 106, 82, 113, 52, 98, 116, 79, 56, 113, 80, 65, 86, 83, 107, 106, 67, 67, 65, 87, 77, 71, 67, 105, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 119, 103, 103, 70, 84, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 66, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 67, 65, 103, 69, 69, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 68, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 69, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 70, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 71, 65, 103, 69, 66, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 72, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 73, 65, 103, 69, 70, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 74, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 75, 65, 103, 69, 65, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 76, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 77, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 78, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 79, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 80, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 81, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 82, 65, 103, 69, 76, 77, 66, 56, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 83, 66, 66, 65, 69, 10, 66, 65, 73, 67, 66, 65, 69, 65, 66, 81, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 77, 66, 65, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 77, 69, 65, 103, 65, 65, 77, 66, 81, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 81, 69, 10, 66, 114, 68, 65, 98, 119, 65, 65, 65, 68, 65, 80, 66, 103, 111, 113, 104, 107, 105, 71, 43, 69, 48, 66, 68, 81, 69, 70, 67, 103, 69, 66, 77, 66, 52, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 89, 69, 69, 68, 97, 57, 104, 116, 65, 56, 65, 74, 47, 90, 10, 50, 70, 109, 97, 76, 53, 74, 113, 47, 75, 69, 119, 82, 65, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 66, 122, 65, 50, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 66, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 67, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 68, 65, 81, 72, 47, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 48, 107, 65, 77, 69, 89, 67, 10, 73, 81, 67, 70, 71, 49, 89, 65, 98, 51, 101, 88, 70, 116, 101, 56, 53, 51, 67, 108, 86, 66, 110, 104, 108, 67, 102, 68, 121, 99, 53, 55, 50, 90, 88, 69, 113, 97, 120, 52, 85, 99, 99, 83, 97, 119, 73, 104, 65, 79, 110, 48, 86, 78, 75, 84, 90, 109, 65, 120, 85, 70, 52, 110, 10, 119, 82, 107, 83, 70, 104, 52, 113, 70, 74, 51, 97, 85, 108, 122, 70, 111, 80, 81, 84, 51, 120, 73, 102, 55, 107, 70, 68, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 108, 106, 67, 67, 65, 106, 50, 103, 65, 119, 73, 66, 65, 103, 73, 86, 65, 74, 86, 118, 88, 99, 50, 57, 71, 43, 72, 112, 81, 69, 110, 74, 49, 80, 81, 122, 122, 103, 70, 88, 67, 57, 53, 85, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 10, 77, 71, 103, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 77, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 10, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 65, 101, 70, 119, 48, 120, 79, 68, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 70, 119, 48, 122, 77, 122, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 77, 72, 65, 120, 73, 106, 65, 103, 10, 66, 103, 78, 86, 66, 65, 77, 77, 71, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 81, 81, 48, 115, 103, 85, 71, 120, 104, 100, 71, 90, 118, 99, 109, 48, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 10, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 78, 83, 66, 47, 55, 116, 50, 49, 108, 88, 83, 79, 10, 50, 67, 117, 122, 112, 120, 119, 55, 52, 101, 74, 66, 55, 50, 69, 121, 68, 71, 103, 87, 53, 114, 88, 67, 116, 120, 50, 116, 86, 84, 76, 113, 54, 104, 75, 107, 54, 122, 43, 85, 105, 82, 90, 67, 110, 113, 82, 55, 112, 115, 79, 118, 103, 113, 70, 101, 83, 120, 108, 109, 84, 108, 74, 108, 10, 101, 84, 109, 105, 50, 87, 89, 122, 51, 113, 79, 66, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 10, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 108, 87, 57, 100, 10, 122, 98, 48, 98, 52, 101, 108, 65, 83, 99, 110, 85, 57, 68, 80, 79, 65, 86, 99, 76, 51, 108, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 10, 65, 102, 56, 67, 65, 81, 65, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 82, 119, 65, 119, 82, 65, 73, 103, 88, 115, 86, 107, 105, 48, 119, 43, 105, 54, 86, 89, 71, 87, 51, 85, 70, 47, 50, 50, 117, 97, 88, 101, 48, 89, 74, 68, 106, 49, 85, 101, 10, 110, 65, 43, 84, 106, 68, 49, 97, 105, 53, 99, 67, 73, 67, 89, 98, 49, 83, 65, 109, 68, 53, 120, 107, 102, 84, 86, 112, 118, 111, 52, 85, 111, 121, 105, 83, 89, 120, 114, 68, 87, 76, 109, 85, 82, 52, 67, 73, 57, 78, 75, 121, 102, 80, 78, 43, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, 88, 68, 84, 81, 53, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 97, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 10, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "quote": [4, 0, 2, 0, 129, 0, 0, 0, 0, 0, 0, 0, 147, 154, 114, 51, 247, 156, 76, 169, 148, 10, 13, 179, 149, 127, 6, 7, 61, 153, 138, 108, 16, 87, 107, 253, 246, 246, 237, 142, 155, 133, 233, 50, 0, 0, 0, 0, 11, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 240, 99, 40, 14, 148, 251, 5, 31, 93, 215, 177, 252, 89, 206, 154, 172, 66, 187, 150, 29, 248, 212, 75, 112, 156, 155, 15, 248, 122, 123, 77, 246, 72, 101, 123, 166, 209, 24, 149, 137, 254, 171, 29, 90, 60, 154, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 231, 2, 6, 0, 0, 0, 0, 0, 240, 109, 253, 166, 220, 225, 207, 144, 77, 78, 43, 171, 29, 195, 112, 99, 76, 249, 92, 239, 162, 206, 178, 222, 46, 238, 18, 124, 147, 130, 105, 128, 144, 215, 164, 161, 62, 20, 197, 54, 236, 108, 156, 60, 143, 168, 112, 119, 1, 4, 189, 12, 224, 238, 210, 51, 174, 199, 171, 11, 95, 0, 77, 81, 113, 205, 45, 49, 69, 175, 241, 74, 71, 134, 223, 194, 247, 63, 167, 124, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 115, 190, 47, 112, 190, 239, 183, 11, 72, 166, 16, 158, 237, 71, 21, 215, 39, 13, 70, 131, 179, 191, 53, 111, 162, 95, 175, 191, 26, 167, 110, 57, 233, 18, 126, 110, 104, 140, 205, 169, 139, 218, 177, 212, 212, 127, 70, 181, 152, 253, 233, 73, 20, 39, 52, 27, 196, 104, 59, 117, 209, 13, 62, 54, 119, 10, 243, 163, 106, 105, 84, 216, 182, 183, 178, 42, 166, 99, 88, 241, 62, 31, 23, 46, 81, 183, 214, 230, 113, 13, 153, 168, 216, 83, 47, 200, 18, 212, 43, 255, 241, 199, 83, 130, 233, 26, 55, 200, 103, 171, 17, 123, 151, 235, 94, 141, 103, 151, 72, 137, 40, 234, 56, 229, 253, 56, 181, 237, 47, 135, 217, 97, 61, 57, 37, 7, 241, 195, 175, 148, 101, 124, 147, 61, 141, 190, 131, 85, 34, 25, 81, 20, 73, 145, 236, 151, 114, 221, 138, 33, 243, 2, 170, 53, 109, 96, 162, 165, 201, 225, 212, 75, 7, 68, 20, 176, 251, 204, 134, 235, 3, 16, 41, 220, 122, 147, 117, 173, 209, 4, 188, 0, 1, 102, 242, 14, 106, 249, 24, 93, 165, 3, 93, 108, 158, 238, 191, 100, 105, 179, 41, 150, 24, 0, 67, 250, 85, 26, 150, 47, 12, 40, 104, 54, 48, 167, 149, 121, 28, 189, 235, 216, 43, 32, 82, 144, 248, 224, 61, 241, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 16, 0, 0, 241, 19, 195, 17, 10, 139, 210, 55, 4, 123, 145, 112, 95, 74, 179, 114, 109, 85, 205, 44, 240, 62, 89, 91, 20, 102, 188, 35, 112, 29, 102, 40, 113, 171, 227, 142, 42, 131, 140, 185, 4, 176, 94, 28, 60, 131, 198, 154, 106, 207, 105, 135, 196, 118, 61, 116, 87, 43, 60, 206, 63, 38, 73, 5, 142, 188, 151, 224, 189, 139, 21, 116, 87, 28, 157, 151, 225, 226, 250, 218, 147, 80, 231, 144, 252, 223, 62, 103, 176, 31, 51, 101, 181, 44, 82, 180, 72, 148, 151, 10, 88, 144, 81, 87, 230, 135, 174, 102, 165, 143, 241, 229, 60, 148, 151, 208, 187, 151, 100, 64, 82, 171, 52, 1, 40, 143, 31, 160, 6, 0, 70, 16, 0, 0, 4, 4, 25, 27, 4, 255, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 229, 163, 167, 181, 216, 48, 194, 149, 59, 152, 83, 76, 108, 89, 163, 163, 79, 220, 52, 233, 51, 247, 245, 137, 143, 10, 133, 207, 8, 132, 107, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 158, 42, 124, 111, 148, 143, 23, 71, 78, 52, 167, 252, 67, 237, 3, 15, 124, 21, 99, 241, 186, 189, 223, 99, 64, 200, 46, 14, 84, 168, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 98, 66, 167, 203, 62, 30, 139, 2, 195, 192, 57, 51, 40, 206, 207, 77, 159, 207, 61, 144, 77, 52, 130, 175, 199, 184, 139, 101, 54, 6, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 104, 20, 163, 161, 53, 224, 108, 242, 243, 89, 254, 44, 94, 6, 221, 208, 114, 104, 245, 136, 152, 247, 114, 38, 13, 159, 166, 76, 210, 218, 35, 176, 50, 73, 126, 90, 51, 71, 162, 188, 242, 213, 199, 51, 51, 241, 214, 54, 118, 105, 53, 222, 159, 223, 198, 96, 15, 35, 136, 163, 243, 191, 8, 32, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 5, 0, 94, 14, 0, 0, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 56, 84, 67, 67, 66, 74, 97, 103, 65, 119, 73, 66, 65, 103, 73, 85, 102, 50, 83, 98, 121, 119, 107, 77, 86, 84, 74, 75, 85, 53, 55, 47, 74, 119, 66, 112, 56, 69, 100, 104, 80, 48, 52, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 99, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 119, 119, 90, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 66, 68, 83, 121, 66, 81, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 66, 68, 81, 84, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, 82, 10, 83, 87, 53, 48, 90, 87, 119, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 77, 67, 49, 78, 104, 98, 110, 82, 104, 73, 69, 78, 115, 89, 88, 74, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 73, 10, 68, 65, 74, 68, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 119, 72, 104, 99, 78, 77, 106, 85, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 87, 104, 99, 78, 77, 122, 73, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 10, 87, 106, 66, 119, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 68, 66, 108, 74, 98, 110, 82, 108, 98, 67, 66, 84, 82, 49, 103, 103, 85, 69, 78, 76, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 10, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 66, 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 71, 112, 118, 10, 48, 89, 117, 89, 114, 113, 65, 117, 83, 75, 66, 122, 75, 108, 117, 98, 54, 109, 76, 43, 114, 118, 102, 68, 53, 65, 106, 89, 79, 51, 81, 78, 103, 102, 87, 122, 116, 103, 52, 101, 109, 49, 69, 71, 66, 86, 107, 71, 108, 87, 118, 100, 117, 66, 48, 88, 81, 83, 69, 47, 115, 120, 71, 68, 10, 109, 83, 118, 75, 111, 57, 116, 51, 67, 114, 79, 80, 67, 52, 83, 85, 54, 88, 54, 106, 103, 103, 77, 77, 77, 73, 73, 68, 67, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 86, 98, 49, 51, 78, 118, 82, 118, 104, 54, 85, 66, 74, 121, 100, 84, 48, 10, 77, 56, 52, 66, 86, 119, 118, 101, 86, 68, 66, 114, 66, 103, 78, 86, 72, 82, 56, 69, 90, 68, 66, 105, 77, 71, 67, 103, 88, 113, 66, 99, 104, 108, 112, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 70, 119, 97, 83, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 51, 78, 110, 101, 67, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 76, 51, 89, 48, 76, 51, 66, 106, 97, 50, 78, 121, 98, 68, 57, 106, 89, 84, 49, 119, 10, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 90, 108, 98, 109, 78, 118, 90, 71, 108, 117, 90, 122, 49, 107, 90, 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 71, 51, 110, 54, 83, 43, 75, 120, 78, 54, 116, 43, 72, 73, 56, 71, 112, 57, 54, 80, 107, 117, 90, 10, 105, 87, 115, 90, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 65, 106, 65, 65, 77, 73, 73, 67, 79, 81, 89, 74, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 10, 66, 73, 73, 67, 75, 106, 67, 67, 65, 105, 89, 119, 72, 103, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 65, 81, 81, 81, 48, 103, 106, 102, 115, 81, 65, 106, 82, 113, 52, 98, 116, 79, 56, 113, 80, 65, 86, 83, 107, 106, 67, 67, 65, 87, 77, 71, 67, 105, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 119, 103, 103, 70, 84, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 66, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 67, 65, 103, 69, 69, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 68, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 69, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 70, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 71, 65, 103, 69, 66, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 72, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 73, 65, 103, 69, 70, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 74, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 75, 65, 103, 69, 65, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 76, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 77, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 78, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 79, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 80, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 81, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 82, 65, 103, 69, 76, 77, 66, 56, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 83, 66, 66, 65, 69, 10, 66, 65, 73, 67, 66, 65, 69, 65, 66, 81, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 77, 66, 65, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 77, 69, 65, 103, 65, 65, 77, 66, 81, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 81, 69, 10, 66, 114, 68, 65, 98, 119, 65, 65, 65, 68, 65, 80, 66, 103, 111, 113, 104, 107, 105, 71, 43, 69, 48, 66, 68, 81, 69, 70, 67, 103, 69, 66, 77, 66, 52, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 89, 69, 69, 68, 97, 57, 104, 116, 65, 56, 65, 74, 47, 90, 10, 50, 70, 109, 97, 76, 53, 74, 113, 47, 75, 69, 119, 82, 65, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 66, 122, 65, 50, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 66, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 67, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 68, 65, 81, 72, 47, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 48, 107, 65, 77, 69, 89, 67, 10, 73, 81, 67, 70, 71, 49, 89, 65, 98, 51, 101, 88, 70, 116, 101, 56, 53, 51, 67, 108, 86, 66, 110, 104, 108, 67, 102, 68, 121, 99, 53, 55, 50, 90, 88, 69, 113, 97, 120, 52, 85, 99, 99, 83, 97, 119, 73, 104, 65, 79, 110, 48, 86, 78, 75, 84, 90, 109, 65, 120, 85, 70, 52, 110, 10, 119, 82, 107, 83, 70, 104, 52, 113, 70, 74, 51, 97, 85, 108, 122, 70, 111, 80, 81, 84, 51, 120, 73, 102, 55, 107, 70, 68, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 108, 106, 67, 67, 65, 106, 50, 103, 65, 119, 73, 66, 65, 103, 73, 86, 65, 74, 86, 118, 88, 99, 50, 57, 71, 43, 72, 112, 81, 69, 110, 74, 49, 80, 81, 122, 122, 103, 70, 88, 67, 57, 53, 85, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 10, 77, 71, 103, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 77, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 10, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 65, 101, 70, 119, 48, 120, 79, 68, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 70, 119, 48, 122, 77, 122, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 77, 72, 65, 120, 73, 106, 65, 103, 10, 66, 103, 78, 86, 66, 65, 77, 77, 71, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 81, 81, 48, 115, 103, 85, 71, 120, 104, 100, 71, 90, 118, 99, 109, 48, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 10, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 78, 83, 66, 47, 55, 116, 50, 49, 108, 88, 83, 79, 10, 50, 67, 117, 122, 112, 120, 119, 55, 52, 101, 74, 66, 55, 50, 69, 121, 68, 71, 103, 87, 53, 114, 88, 67, 116, 120, 50, 116, 86, 84, 76, 113, 54, 104, 75, 107, 54, 122, 43, 85, 105, 82, 90, 67, 110, 113, 82, 55, 112, 115, 79, 118, 103, 113, 70, 101, 83, 120, 108, 109, 84, 108, 74, 108, 10, 101, 84, 109, 105, 50, 87, 89, 122, 51, 113, 79, 66, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 10, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 108, 87, 57, 100, 10, 122, 98, 48, 98, 52, 101, 108, 65, 83, 99, 110, 85, 57, 68, 80, 79, 65, 86, 99, 76, 51, 108, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 10, 65, 102, 56, 67, 65, 81, 65, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 82, 119, 65, 119, 82, 65, 73, 103, 88, 115, 86, 107, 105, 48, 119, 43, 105, 54, 86, 89, 71, 87, 51, 85, 70, 47, 50, 50, 117, 97, 88, 101, 48, 89, 74, 68, 106, 49, 85, 101, 10, 110, 65, 43, 84, 106, 68, 49, 97, 105, 53, 99, 67, 73, 67, 89, 98, 49, 83, 65, 109, 68, 53, 120, 107, 102, 84, 86, 112, 118, 111, 52, 85, 111, 121, 105, 83, 89, 120, 114, 68, 87, 76, 109, 85, 82, 52, 67, 73, 57, 78, 75, 121, 102, 80, 78, 43, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, 88, 68, 84, 81, 53, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 97, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 10, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "collateral": { "pck_crl_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", "root_ca_crl": [48, 130, 1, 34, 48, 129, 200, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 104, 49, 26, 48, 24, 6, 3, 85, 4, 3, 12, 17, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, 82, 111, 111, 116, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 54, 48, 50, 50, 54, 49, 51, 48, 52, 48, 48, 90, 23, 13, 50, 55, 48, 50, 50, 54, 49, 51, 48, 52, 48, 48, 90, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 34, 101, 12, 214, 90, 157, 52, 137, 243, 131, 180, 149, 82, 191, 80, 27, 57, 39, 6, 172, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 73, 0, 48, 70, 2, 33, 0, 194, 82, 237, 89, 199, 149, 186, 43, 17, 73, 106, 74, 153, 117, 139, 184, 203, 195, 128, 161, 235, 187, 8, 101, 190, 105, 242, 196, 179, 139, 182, 64, 2, 33, 0, 154, 125, 139, 3, 96, 42, 158, 226, 214, 35, 34, 215, 89, 22, 109, 105, 51, 210, 77, 157, 250, 1, 171, 63, 222, 69, 32, 105, 29, 113, 91, 215], - "pck_crl": [48, 130, 13, 23, 48, 130, 12, 189, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 112, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, 80, 67, 75, 32, 80, 108, 97, 116, 102, 111, 114, 109, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 23, 13, 50, 54, 48, 57, 48, 54, 48, 48, 50, 57, 49, 51, 90, 48, 130, 11, 233, 48, 51, 2, 20, 111, 195, 78, 80, 35, 231, 40, 146, 52, 53, 214, 26, 164, 184, 60, 97, 129, 102, 173, 53, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 174, 110, 151, 21, 252, 161, 59, 135, 227, 51, 232, 38, 30, 214, 217, 144, 169, 38, 173, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 253, 96, 134, 72, 98, 156, 186, 115, 7, 139, 77, 73, 47, 75, 62, 167, 65, 173, 8, 205, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 249, 36, 24, 78, 29, 90, 253, 221, 115, 195, 214, 58, 18, 245, 232, 181, 115, 126, 86, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 177, 37, 121, 120, 207, 169, 204, 221, 7, 89, 171, 248, 197, 202, 114, 250, 227, 167, 138, 155, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 116, 254, 166, 20, 169, 114, 190, 14, 40, 67, 242, 5, 152, 53, 129, 30, 216, 114, 249, 179, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 249, 196, 239, 86, 179, 171, 72, 213, 119, 225, 8, 186, 237, 244, 191, 136, 1, 66, 20, 185, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 29, 224, 119, 143, 158, 95, 196, 242, 135, 143, 48, 214, 176, 124, 154, 48, 230, 179, 11, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 226, 66, 79, 151, 44, 234, 148, 255, 35, 153, 55, 244, 216, 12, 37, 2, 157, 214, 11, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 51, 25, 229, 16, 155, 100, 80, 125, 60, 241, 19, 44, 224, 3, 73, 239, 82, 115, 25, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 223, 8, 215, 86, 182, 106, 116, 151, 244, 59, 91, 181, 138, 218, 4, 211, 244, 247, 169, 55, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 40, 175, 72, 91, 108, 246, 126, 64, 154, 57, 213, 203, 90, 238, 69, 152, 247, 168, 250, 123, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 251, 139, 45, 174, 192, 146, 202, 218, 138, 169, 188, 79, 242, 241, 194, 13, 3, 70, 102, 140, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 72, 80, 172, 82, 189, 204, 105, 166, 166, 240, 88, 200, 188, 87, 187, 208, 181, 248, 100, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 153, 77, 211, 102, 111, 82, 117, 251, 128, 95, 149, 221, 2, 189, 80, 203, 38, 121, 216, 173, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 2, 19, 105, 0, 37, 34, 116, 217, 3, 94, 237, 245, 69, 116, 98, 250, 208, 239, 76, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 97, 242, 191, 115, 227, 155, 78, 4, 170, 39, 216, 1, 189, 115, 210, 67, 25, 181, 191, 128, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 57, 146, 190, 133, 27, 150, 144, 46, 255, 56, 149, 158, 108, 46, 255, 27, 6, 81, 164, 181, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 15, 218, 67, 160, 11, 104, 234, 121, 183, 194, 222, 174, 172, 11, 73, 139, 223, 178, 175, 144, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 99, 159, 19, 154, 80, 64, 253, 207, 241, 145, 232, 164, 251, 27, 240, 134, 237, 96, 57, 113, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 149, 157, 83, 63, 146, 73, 220, 30, 81, 53, 68, 205, 200, 48, 191, 25, 183, 241, 243, 1, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 122, 227, 119, 72, 169, 249, 18, 244, 198, 59, 167, 171, 7, 197, 147, 206, 29, 29, 17, 129, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 19, 136, 75, 51, 38, 153, 56, 193, 149, 170, 23, 15, 202, 117, 218, 23, 117, 56, 223, 11, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 133, 211, 201, 56, 27, 119, 167, 224, 77, 17, 156, 158, 90, 214, 116, 159, 243, 255, 171, 135, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 147, 136, 124, 164, 65, 30, 122, 146, 59, 209, 254, 210, 129, 155, 41, 73, 242, 1, 181, 180, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 152, 220, 98, 131, 147, 9, 150, 253, 139, 242, 58, 55, 172, 190, 38, 163, 190, 212, 87, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 102, 241, 167, 73, 72, 134, 103, 104, 156, 195, 144, 58, 197, 76, 102, 43, 113, 46, 115, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 175, 193, 54, 16, 189, 211, 108, 183, 152, 93, 16, 100, 129, 168, 128, 211, 160, 31, 218, 7, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 224, 75, 44, 51, 208, 54, 170, 201, 108, 166, 115, 191, 30, 154, 71, 182, 77, 92, 187, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 131, 217, 172, 141, 139, 181, 9, 209, 198, 200, 9, 173, 113, 46, 132, 48, 85, 158, 215, 243, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 121, 49, 253, 80, 181, 7, 28, 27, 191, 197, 183, 182, 222, 216, 180, 91, 157, 139, 133, 41, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 31, 162, 14, 41, 112, 189, 229, 213, 127, 123, 141, 223, 131, 57, 72, 78, 31, 29, 8, 35, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 30, 135, 178, 195, 179, 45, 141, 35, 228, 17, 206, 243, 65, 151, 185, 90, 240, 200, 173, 245, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 154, 253, 46, 233, 10, 71, 53, 80, 161, 103, 217, 150, 145, 20, 55, 199, 80, 45, 31, 9, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 68, 129, 176, 241, 23, 40, 161, 59, 105, 109, 62, 169, 199, 112, 160, 177, 94, 197, 141, 218, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 167, 133, 159, 87, 152, 46, 240, 230, 125, 55, 188, 142, 242, 239, 90, 200, 53, 255, 26, 169, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 103, 117, 59, 129, 228, 112, 144, 174, 167, 99, 251, 236, 76, 69, 73, 188, 219, 153, 51, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 191, 187, 122, 29, 156, 86, 129, 71, 225, 24, 182, 20, 247, 183, 110, 211, 239, 104, 223, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 44, 60, 198, 254, 146, 121, 219, 21, 22, 213, 206, 57, 242, 168, 152, 205, 165, 161, 117, 225, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 113, 121, 72, 104, 117, 9, 35, 75, 233, 121, 228, 183, 220, 230, 243, 27, 239, 100, 182, 140, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 118, 239, 44, 57, 193, 54, 232, 101, 139, 110, 115, 150, 177, 215, 68, 90, 39, 99, 31, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 195, 224, 37, 252, 169, 149, 243, 111, 89, 180, 132, 103, 147, 158, 62, 52, 230, 54, 26, 111, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 140, 95, 107, 50, 87, 218, 5, 177, 116, 41, 226, 230, 27, 169, 101, 214, 115, 48, 96, 106, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 161, 124, 81, 114, 46, 193, 224, 195, 39, 143, 232, 189, 240, 82, 5, 156, 190, 196, 230, 72, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 17, 201, 67, 184, 102, 250, 4, 148, 78, 48, 87, 229, 166, 113, 70, 89, 100, 117, 160, 35, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 190, 105, 19, 120, 84, 6, 21, 84, 84, 162, 136, 133, 165, 21, 179, 218, 87, 103, 211, 169, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 10, 197, 236, 145, 189, 147, 76, 7, 185, 234, 65, 98, 94, 156, 192, 150, 129, 0, 46, 176, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 109, 81, 160, 234, 188, 31, 154, 30, 157, 221, 91, 54, 189, 218, 22, 49, 174, 108, 24, 42, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 165, 44, 93, 113, 196, 22, 107, 79, 192, 222, 216, 182, 121, 149, 30, 94, 233, 25, 61, 229, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 151, 121, 174, 221, 133, 252, 172, 147, 200, 133, 53, 22, 190, 84, 40, 194, 107, 59, 248, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 186, 79, 215, 107, 222, 83, 9, 33, 12, 241, 221, 31, 251, 73, 76, 99, 138, 145, 87, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 4, 62, 4, 145, 157, 170, 225, 52, 67, 36, 131, 149, 9, 77, 42, 46, 172, 252, 118, 254, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 71, 252, 87, 125, 45, 9, 76, 189, 242, 112, 113, 94, 214, 132, 138, 147, 133, 90, 211, 75, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 125, 98, 162, 245, 230, 243, 134, 228, 105, 101, 63, 255, 255, 4, 93, 10, 129, 120, 232, 231, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 196, 237, 69, 254, 2, 107, 182, 164, 126, 174, 195, 94, 168, 11, 126, 244, 7, 206, 6, 44, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 207, 152, 49, 7, 122, 60, 164, 241, 162, 197, 104, 103, 191, 85, 177, 142, 204, 190, 255, 216, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 43, 129, 215, 234, 46, 67, 103, 32, 206, 41, 241, 208, 177, 204, 183, 162, 24, 96, 15, 23, 13, 50, 54, 48, 56, 48, 55, 48, 48, 50, 57, 49, 51, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 149, 111, 93, 205, 189, 27, 225, 233, 64, 73, 201, 212, 244, 51, 206, 1, 87, 11, 222, 84, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 33, 0, 238, 111, 7, 14, 49, 145, 234, 194, 121, 35, 98, 21, 229, 27, 92, 206, 192, 184, 252, 12, 1, 193, 81, 27, 188, 14, 90, 153, 227, 176, 87, 139, 2, 32, 65, 207, 14, 33, 10, 125, 66, 119, 141, 248, 67, 211, 169, 246, 2, 143, 151, 102, 229, 171, 114, 80, 176, 33, 219, 155, 251, 57, 222, 116, 166, 11], + "pck_crl": [48, 130, 13, 23, 48, 130, 12, 189, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 112, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, 80, 67, 75, 32, 80, 108, 97, 116, 102, 111, 114, 109, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 23, 13, 50, 54, 48, 57, 49, 48, 48, 48, 51, 49, 53, 48, 90, 48, 130, 11, 233, 48, 51, 2, 20, 111, 195, 78, 80, 35, 231, 40, 146, 52, 53, 214, 26, 164, 184, 60, 97, 129, 102, 173, 53, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 174, 110, 151, 21, 252, 161, 59, 135, 227, 51, 232, 38, 30, 214, 217, 144, 169, 38, 173, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 253, 96, 134, 72, 98, 156, 186, 115, 7, 139, 77, 73, 47, 75, 62, 167, 65, 173, 8, 205, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 249, 36, 24, 78, 29, 90, 253, 221, 115, 195, 214, 58, 18, 245, 232, 181, 115, 126, 86, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 177, 37, 121, 120, 207, 169, 204, 221, 7, 89, 171, 248, 197, 202, 114, 250, 227, 167, 138, 155, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 116, 254, 166, 20, 169, 114, 190, 14, 40, 67, 242, 5, 152, 53, 129, 30, 216, 114, 249, 179, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 249, 196, 239, 86, 179, 171, 72, 213, 119, 225, 8, 186, 237, 244, 191, 136, 1, 66, 20, 185, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 29, 224, 119, 143, 158, 95, 196, 242, 135, 143, 48, 214, 176, 124, 154, 48, 230, 179, 11, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 226, 66, 79, 151, 44, 234, 148, 255, 35, 153, 55, 244, 216, 12, 37, 2, 157, 214, 11, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 51, 25, 229, 16, 155, 100, 80, 125, 60, 241, 19, 44, 224, 3, 73, 239, 82, 115, 25, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 223, 8, 215, 86, 182, 106, 116, 151, 244, 59, 91, 181, 138, 218, 4, 211, 244, 247, 169, 55, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 40, 175, 72, 91, 108, 246, 126, 64, 154, 57, 213, 203, 90, 238, 69, 152, 247, 168, 250, 123, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 251, 139, 45, 174, 192, 146, 202, 218, 138, 169, 188, 79, 242, 241, 194, 13, 3, 70, 102, 140, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 72, 80, 172, 82, 189, 204, 105, 166, 166, 240, 88, 200, 188, 87, 187, 208, 181, 248, 100, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 153, 77, 211, 102, 111, 82, 117, 251, 128, 95, 149, 221, 2, 189, 80, 203, 38, 121, 216, 173, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 2, 19, 105, 0, 37, 34, 116, 217, 3, 94, 237, 245, 69, 116, 98, 250, 208, 239, 76, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 97, 242, 191, 115, 227, 155, 78, 4, 170, 39, 216, 1, 189, 115, 210, 67, 25, 181, 191, 128, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 57, 146, 190, 133, 27, 150, 144, 46, 255, 56, 149, 158, 108, 46, 255, 27, 6, 81, 164, 181, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 15, 218, 67, 160, 11, 104, 234, 121, 183, 194, 222, 174, 172, 11, 73, 139, 223, 178, 175, 144, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 99, 159, 19, 154, 80, 64, 253, 207, 241, 145, 232, 164, 251, 27, 240, 134, 237, 96, 57, 113, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 149, 157, 83, 63, 146, 73, 220, 30, 81, 53, 68, 205, 200, 48, 191, 25, 183, 241, 243, 1, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 122, 227, 119, 72, 169, 249, 18, 244, 198, 59, 167, 171, 7, 197, 147, 206, 29, 29, 17, 129, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 19, 136, 75, 51, 38, 153, 56, 193, 149, 170, 23, 15, 202, 117, 218, 23, 117, 56, 223, 11, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 133, 211, 201, 56, 27, 119, 167, 224, 77, 17, 156, 158, 90, 214, 116, 159, 243, 255, 171, 135, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 147, 136, 124, 164, 65, 30, 122, 146, 59, 209, 254, 210, 129, 155, 41, 73, 242, 1, 181, 180, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 152, 220, 98, 131, 147, 9, 150, 253, 139, 242, 58, 55, 172, 190, 38, 163, 190, 212, 87, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 102, 241, 167, 73, 72, 134, 103, 104, 156, 195, 144, 58, 197, 76, 102, 43, 113, 46, 115, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 175, 193, 54, 16, 189, 211, 108, 183, 152, 93, 16, 100, 129, 168, 128, 211, 160, 31, 218, 7, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 224, 75, 44, 51, 208, 54, 170, 201, 108, 166, 115, 191, 30, 154, 71, 182, 77, 92, 187, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 131, 217, 172, 141, 139, 181, 9, 209, 198, 200, 9, 173, 113, 46, 132, 48, 85, 158, 215, 243, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 121, 49, 253, 80, 181, 7, 28, 27, 191, 197, 183, 182, 222, 216, 180, 91, 157, 139, 133, 41, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 31, 162, 14, 41, 112, 189, 229, 213, 127, 123, 141, 223, 131, 57, 72, 78, 31, 29, 8, 35, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 30, 135, 178, 195, 179, 45, 141, 35, 228, 17, 206, 243, 65, 151, 185, 90, 240, 200, 173, 245, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 154, 253, 46, 233, 10, 71, 53, 80, 161, 103, 217, 150, 145, 20, 55, 199, 80, 45, 31, 9, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 68, 129, 176, 241, 23, 40, 161, 59, 105, 109, 62, 169, 199, 112, 160, 177, 94, 197, 141, 218, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 167, 133, 159, 87, 152, 46, 240, 230, 125, 55, 188, 142, 242, 239, 90, 200, 53, 255, 26, 169, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 103, 117, 59, 129, 228, 112, 144, 174, 167, 99, 251, 236, 76, 69, 73, 188, 219, 153, 51, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 191, 187, 122, 29, 156, 86, 129, 71, 225, 24, 182, 20, 247, 183, 110, 211, 239, 104, 223, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 44, 60, 198, 254, 146, 121, 219, 21, 22, 213, 206, 57, 242, 168, 152, 205, 165, 161, 117, 225, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 113, 121, 72, 104, 117, 9, 35, 75, 233, 121, 228, 183, 220, 230, 243, 27, 239, 100, 182, 140, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 118, 239, 44, 57, 193, 54, 232, 101, 139, 110, 115, 150, 177, 215, 68, 90, 39, 99, 31, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 195, 224, 37, 252, 169, 149, 243, 111, 89, 180, 132, 103, 147, 158, 62, 52, 230, 54, 26, 111, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 140, 95, 107, 50, 87, 218, 5, 177, 116, 41, 226, 230, 27, 169, 101, 214, 115, 48, 96, 106, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 161, 124, 81, 114, 46, 193, 224, 195, 39, 143, 232, 189, 240, 82, 5, 156, 190, 196, 230, 72, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 17, 201, 67, 184, 102, 250, 4, 148, 78, 48, 87, 229, 166, 113, 70, 89, 100, 117, 160, 35, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 190, 105, 19, 120, 84, 6, 21, 84, 84, 162, 136, 133, 165, 21, 179, 218, 87, 103, 211, 169, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 10, 197, 236, 145, 189, 147, 76, 7, 185, 234, 65, 98, 94, 156, 192, 150, 129, 0, 46, 176, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 109, 81, 160, 234, 188, 31, 154, 30, 157, 221, 91, 54, 189, 218, 22, 49, 174, 108, 24, 42, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 165, 44, 93, 113, 196, 22, 107, 79, 192, 222, 216, 182, 121, 149, 30, 94, 233, 25, 61, 229, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 151, 121, 174, 221, 133, 252, 172, 147, 200, 133, 53, 22, 190, 84, 40, 194, 107, 59, 248, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 186, 79, 215, 107, 222, 83, 9, 33, 12, 241, 221, 31, 251, 73, 76, 99, 138, 145, 87, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 4, 62, 4, 145, 157, 170, 225, 52, 67, 36, 131, 149, 9, 77, 42, 46, 172, 252, 118, 254, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 71, 252, 87, 125, 45, 9, 76, 189, 242, 112, 113, 94, 214, 132, 138, 147, 133, 90, 211, 75, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 125, 98, 162, 245, 230, 243, 134, 228, 105, 101, 63, 255, 255, 4, 93, 10, 129, 120, 232, 231, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 196, 237, 69, 254, 2, 107, 182, 164, 126, 174, 195, 94, 168, 11, 126, 244, 7, 206, 6, 44, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 207, 152, 49, 7, 122, 60, 164, 241, 162, 197, 104, 103, 191, 85, 177, 142, 204, 190, 255, 216, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 43, 129, 215, 234, 46, 67, 103, 32, 206, 41, 241, 208, 177, 204, 183, 162, 24, 96, 15, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 149, 111, 93, 205, 189, 27, 225, 233, 64, 73, 201, 212, 244, 51, 206, 1, 87, 11, 222, 84, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 33, 0, 210, 126, 233, 141, 240, 27, 111, 65, 28, 124, 216, 249, 48, 64, 175, 231, 130, 74, 213, 95, 21, 73, 9, 7, 217, 225, 15, 27, 70, 252, 96, 18, 2, 32, 18, 93, 240, 19, 52, 192, 199, 211, 232, 16, 179, 33, 46, 176, 194, 43, 160, 28, 210, 4, 225, 103, 52, 129, 96, 3, 40, 122, 116, 43, 39, 128], "tcb_info_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-07T08:49:47Z\",\"nextUpdate\":\"2026-09-06T08:49:47Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":19,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", - "tcb_info_signature": [15, 93, 222, 224, 153, 41, 123, 48, 158, 155, 65, 196, 206, 107, 186, 235, 246, 185, 156, 167, 166, 244, 130, 222, 143, 51, 200, 200, 229, 151, 142, 200, 173, 234, 138, 239, 168, 185, 146, 196, 170, 33, 128, 114, 92, 158, 119, 185, 30, 108, 235, 140, 112, 235, 50, 28, 3, 23, 148, 55, 184, 89, 36, 134], + "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-11T00:36:45Z\",\"nextUpdate\":\"2026-09-10T00:36:45Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":19,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", + "tcb_info_signature": [28, 17, 163, 153, 105, 114, 25, 56, 234, 26, 72, 247, 252, 2, 242, 245, 21, 119, 210, 9, 200, 246, 198, 11, 113, 138, 176, 25, 83, 25, 143, 4, 57, 136, 142, 203, 191, 183, 207, 218, 44, 210, 233, 81, 70, 2, 65, 133, 155, 235, 168, 108, 244, 52, 137, 152, 31, 15, 122, 82, 28, 147, 249, 153], "qe_identity_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-07T00:34:59Z\",\"nextUpdate\":\"2026-09-06T00:34:59Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", - "qe_identity_signature": [57, 36, 243, 212, 119, 60, 81, 154, 112, 130, 100, 167, 103, 141, 168, 59, 58, 98, 68, 81, 98, 171, 169, 110, 38, 225, 130, 214, 83, 65, 109, 226, 87, 46, 173, 184, 96, 43, 92, 61, 164, 132, 193, 128, 127, 165, 2, 249, 74, 25, 210, 254, 166, 31, 107, 92, 59, 151, 192, 23, 245, 68, 57, 53], + "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-11T00:39:20Z\",\"nextUpdate\":\"2026-09-10T00:39:20Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", + "qe_identity_signature": [175, 89, 166, 14, 218, 29, 23, 101, 238, 89, 138, 244, 11, 128, 111, 228, 13, 23, 143, 37, 28, 94, 246, 28, 138, 246, 20, 118, 120, 115, 179, 227, 20, 144, 113, 31, 32, 171, 238, 88, 170, 64, 130, 231, 5, 160, 245, 127, 29, 10, 245, 18, 53, 161, 130, 99, 156, 132, 99, 185, 148, 207, 33, 21], "pck_certificate_chain": "-----BEGIN CERTIFICATE-----\nMIIE8TCCBJagAwIBAgIUf2SbywkMVTJKU57/JwBp8EdhP04wCgYIKoZIzj0EAwIw\ncDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBDSyBQbGF0Zm9ybSBDQTEaMBgGA1UECgwR\nSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQI\nDAJDQTELMAkGA1UEBhMCVVMwHhcNMjUxMTA2MDczNzM0WhcNMzIxMTA2MDczNzM0\nWjBwMSIwIAYDVQQDDBlJbnRlbCBTR1ggUENLIENlcnRpZmljYXRlMRowGAYDVQQK\nDBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV\nBAgMAkNBMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGpv\n0YuYrqAuSKBzKlub6mL+rvfD5AjYO3QNgfWztg4em1EGBVkGlWvduB0XQSE/sxGD\nmSvKo9t3CrOPC4SU6X6jggMMMIIDCDAfBgNVHSMEGDAWgBSVb13NvRvh6UBJydT0\nM84BVwveVDBrBgNVHR8EZDBiMGCgXqBchlpodHRwczovL2FwaS50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL3NneC9jZXJ0aWZpY2F0aW9uL3Y0L3Bja2NybD9jYT1w\nbGF0Zm9ybSZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFG3n6S+KxN6t+HI8Gp96PkuZ\niWsZMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIICOQYJKoZIhvhNAQ0B\nBIICKjCCAiYwHgYKKoZIhvhNAQ0BAQQQ0gjfsQAjRq4btO8qPAVSkjCCAWMGCiqG\nSIb4TQENAQIwggFTMBAGCyqGSIb4TQENAQIBAgEEMBAGCyqGSIb4TQENAQICAgEE\nMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgECMBAGCyqGSIb4TQEN\nAQIFAgEEMBAGCyqGSIb4TQENAQIGAgEBMBAGCyqGSIb4TQENAQIHAgEAMBAGCyqG\nSIb4TQENAQIIAgEFMBAGCyqGSIb4TQENAQIJAgEAMBAGCyqGSIb4TQENAQIKAgEA\nMBAGCyqGSIb4TQENAQILAgEAMBAGCyqGSIb4TQENAQIMAgEAMBAGCyqGSIb4TQEN\nAQINAgEAMBAGCyqGSIb4TQENAQIOAgEAMBAGCyqGSIb4TQENAQIPAgEAMBAGCyqG\nSIb4TQENAQIQAgEAMBAGCyqGSIb4TQENAQIRAgELMB8GCyqGSIb4TQENAQISBBAE\nBAICBAEABQAAAAAAAAAAMBAGCiqGSIb4TQENAQMEAgAAMBQGCiqGSIb4TQENAQQE\nBrDAbwAAADAPBgoqhkiG+E0BDQEFCgEBMB4GCiqGSIb4TQENAQYEEDa9htA8AJ/Z\n2FmaL5Jq/KEwRAYKKoZIhvhNAQ0BBzA2MBAGCyqGSIb4TQENAQcBAQH/MBAGCyqG\nSIb4TQENAQcCAQH/MBAGCyqGSIb4TQENAQcDAQH/MAoGCCqGSM49BAMCA0kAMEYC\nIQCFG1YAb3eXFte853ClVBnhlCfDyc572ZXEqax4UccSawIhAOn0VNKTZmAxUF4n\nwRkSFh4qFJ3aUlzFoPQT3xIf7kFD\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\u0000" }, "tcb_info": { @@ -22,11 +22,11 @@ "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "8050d4769527c84cb066078854ef8eb50ea7b150e072eeec7007240aca01b556041273ea3d20a1b1d48736f650ce13f0", + "rtmr3": "3d8dbe8355221951144991ec9772dd8a21f302aa356d60a2a5c9e1d44b074414b0fbcc86eb031029dc7a9375add104bc", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a", + "compose_hash": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786102851\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\n# Test-asset collection hook, sourced by the CVM's app-compose.sh before the\\n# node starts. The node generates its NEAR signer key in-enclave, so exporting\\n# that key is the only way to check the fixture keypair into the repo next to\\n# the quote it is bound to (near/mpc #3787).\\n#\\n# The key appears only after the node starts, i.e. after this hook returns, so\\n# the wait runs as its own systemd unit: a plain background process would be\\n# reaped with app-compose.service's cgroup. The copy target is the CVM's\\n# host-shared dir, which the host sees as run/vm//shared/.\\n#\\n# The guest userland is BusyBox, so the wait loop sticks to shell built-ins and\\n# globs (no find/head, whose GNU options BusyBox rejects).\\n#\\n# Only ever use this on a throwaway localnet CVM: it exports a private key.\\n\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\nEXFIL=/etc/fixture-exfil.sh\\n\\ncat > \\\"$EXFIL\\\" <<'EOF'\\n#!/bin/sh\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\ni=0\\nwhile [ \\\"$i\\\" -lt 900 ]; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n if [ -f \\\"$f\\\" ]; then\\n cp \\\"$f\\\" \\\"$SHARED/fixture-secrets.json\\\" 2>/dev/null\\n {\\n echo \\\"FIXTURE-SECRETS-BEGIN $f\\\"\\n cat \\\"$f\\\"\\n echo \\\"\\\"\\n echo \\\"FIXTURE-SECRETS-END\\\"\\n } > \\\"$CONSOLE\\\" 2>&1\\n exit 0\\n fi\\n done\\n i=$((i + 1))\\n sleep 2\\ndone\\necho \\\"FIXTURE-SECRETS-TIMEOUT\\\" > \\\"$CONSOLE\\\" 2>&1\\nEOF\\nchmod +x \\\"$EXFIL\\\" 2>/dev/null\\n\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Unit]\\nDescription=Export the MPC node signer key for test-asset collection\\n[Service]\\nType=oneshot\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEOF\\n\\nsystemctl daemon-reload >/dev/null 2>&1\\nsystemctl start --no-block fixture-exfil.service >/dev/null 2>&1\\n\\n{\\n echo \\\"FIXTURE-DIAG-BEGIN\\\"\\n echo \\\"exfil_script=$([ -f \\\"$EXFIL\\\" ] && echo present || echo missing)\\\"\\n echo \\\"unit_state=$(systemctl is-active fixture-exfil.service 2>&1)\\\"\\n echo \\\"shared_writable=$([ -w \\\"$SHARED\\\" ] && echo yes || echo no)\\\"\\n echo \\\"FIXTURE-DIAG-END\\\"\\n} > \\\"$CONSOLE\\\" 2>&1\\n\"\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786440162\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\ncat > /etc/fixture-exfil.sh <<'EOF'\\n#!/bin/sh\\nwhile :; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n [ -f \\\"$f\\\" ] && cat \\\"$f\\\" > /dev/console && exit 0\\n done\\n sleep 2\\ndone\\nEOF\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Service]\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nEOF\\nsystemctl daemon-reload\\nsystemctl start --no-block fixture-exfil.service\\n\"\n}", "event_log": [ { "imr": 0, @@ -178,16 +178,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "970c96ea5f1ea46650645363f1716fd4e4260c92f614a6af308d4ca2e352b4dbd3d8f326e5a513c20b3029163284257e", + "digest": "02e1e5a9c9612830b0dfbc7e0e73ce13667254658b1177a8888ecdf2f3c729cfed158e4bde6c113e31112360f6d5df97", "event": "app-id", - "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfaf" + "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145" }, { "imr": 3, "event_type": 134217729, - "digest": "6d4e926546694d6e8acc53d46b216cde12d3a60cd3b60550ab7db7f4920fc42c304f8af924e08f96c108a7f7076cf02a", + "digest": "0724a946d4c56944af69a502165a07082875b44e15abaa15171dcd44c1c2955303a6bdfa59f2e58e63d206b079a6e5cc", "event": "compose-hash", - "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a" + "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4" }, { "imr": 3, diff --git a/crates/test-utils/assets/quote.json b/crates/test-utils/assets/quote.json index b4a18b209c..78f8356574 100644 --- a/crates/test-utils/assets/quote.json +++ b/crates/test-utils/assets/quote.json @@ -1 +1 @@ -[4,0,2,0,129,0,0,0,0,0,0,0,147,154,114,51,247,156,76,169,148,10,13,179,149,127,6,7,61,153,138,108,16,87,107,253,246,246,237,142,155,133,233,50,0,0,0,0,11,1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,123,240,99,40,14,148,251,5,31,93,215,177,252,89,206,154,172,66,187,150,29,248,212,75,112,156,155,15,248,122,123,77,246,72,101,123,166,209,24,149,137,254,171,29,90,60,154,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,231,2,6,0,0,0,0,0,240,109,253,166,220,225,207,144,77,78,43,171,29,195,112,99,76,249,92,239,162,206,178,222,46,238,18,124,147,130,105,128,144,215,164,161,62,20,197,54,236,108,156,60,143,168,112,119,1,198,119,92,77,155,183,39,60,162,28,213,75,230,182,161,135,147,40,223,175,190,181,80,246,149,123,130,30,33,47,13,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,115,190,47,112,190,239,183,11,72,166,16,158,237,71,21,215,39,13,70,131,179,191,53,111,162,95,175,191,26,167,110,57,233,18,126,110,104,140,205,169,139,218,177,212,212,127,70,181,152,253,233,73,20,39,52,27,196,104,59,117,209,13,62,54,119,10,243,163,106,105,84,216,182,183,178,42,166,99,88,241,62,31,23,46,81,183,214,230,113,13,153,168,216,83,47,200,18,212,43,255,241,199,83,130,233,26,55,200,103,171,17,123,151,235,94,141,103,151,72,137,40,234,56,229,253,56,181,237,47,135,217,97,61,57,37,7,241,195,175,148,101,124,147,128,80,212,118,149,39,200,76,176,102,7,136,84,239,142,181,14,167,177,80,224,114,238,236,112,7,36,10,202,1,181,86,4,18,115,234,61,32,161,177,212,135,54,246,80,206,19,240,0,1,209,86,189,198,94,91,239,231,225,97,127,216,191,206,198,221,63,29,165,128,118,189,230,104,208,199,60,227,182,36,106,78,137,8,32,54,198,0,97,223,254,251,217,148,182,171,98,72,0,0,0,0,0,0,0,0,0,0,0,0,0,0,204,16,0,0,200,71,196,122,109,85,63,3,18,209,86,2,141,242,185,138,228,240,253,45,106,250,173,199,245,16,11,112,18,49,38,99,19,4,193,57,36,61,190,193,116,80,40,89,26,63,23,196,24,182,105,144,93,83,116,164,177,5,157,5,162,224,199,103,142,188,151,224,189,139,21,116,87,28,157,151,225,226,250,218,147,80,231,144,252,223,62,103,176,31,51,101,181,44,82,180,72,148,151,10,88,144,81,87,230,135,174,102,165,143,241,229,60,148,151,208,187,151,100,64,82,171,52,1,40,143,31,160,6,0,70,16,0,0,4,4,25,27,4,255,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,231,0,0,0,0,0,0,0,229,163,167,181,216,48,194,149,59,152,83,76,108,89,163,163,79,220,52,233,51,247,245,137,143,10,133,207,8,132,107,202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,158,42,124,111,148,143,23,71,78,52,167,252,67,237,3,15,124,21,99,241,186,189,223,99,64,200,46,14,84,168,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,98,66,167,203,62,30,139,2,195,192,57,51,40,206,207,77,159,207,61,144,77,52,130,175,199,184,139,101,54,6,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,38,110,158,253,119,108,12,78,190,20,247,2,106,23,209,8,177,82,221,154,125,85,141,105,35,22,81,130,94,61,208,85,132,184,18,62,136,70,151,251,120,116,84,85,102,215,7,27,232,230,233,88,107,188,209,227,153,207,76,194,69,125,91,32,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,5,0,94,14,0,0,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,69,56,84,67,67,66,74,97,103,65,119,73,66,65,103,73,85,102,50,83,98,121,119,107,77,86,84,74,75,85,53,55,47,74,119,66,112,56,69,100,104,80,48,52,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,99,68,69,105,77,67,65,71,65,49,85,69,65,119,119,90,83,87,53,48,90,87,119,103,85,48,100,89,73,70,66,68,83,121,66,81,98,71,70,48,90,109,57,121,98,83,66,68,81,84,69,97,77,66,103,71,65,49,85,69,67,103,119,82,10,83,87,53,48,90,87,119,103,81,50,57,121,99,71,57,121,89,88,82,112,98,50,52,120,70,68,65,83,66,103,78,86,66,65,99,77,67,49,78,104,98,110,82,104,73,69,78,115,89,88,74,104,77,81,115,119,67,81,89,68,86,81,81,73,10,68,65,74,68,81,84,69,76,77,65,107,71,65,49,85,69,66,104,77,67,86,86,77,119,72,104,99,78,77,106,85,120,77,84,65,50,77,68,99,122,78,122,77,48,87,104,99,78,77,122,73,120,77,84,65,50,77,68,99,122,78,122,77,48,10,87,106,66,119,77,83,73,119,73,65,89,68,86,81,81,68,68,66,108,74,98,110,82,108,98,67,66,84,82,49,103,103,85,69,78,76,73,69,78,108,99,110,82,112,90,109,108,106,89,88,82,108,77,82,111,119,71,65,89,68,86,81,81,75,10,68,66,70,74,98,110,82,108,98,67,66,68,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,10,66,65,103,77,65,107,78,66,77,81,115,119,67,81,89,68,86,81,81,71,69,119,74,86,85,122,66,90,77,66,77,71,66,121,113,71,83,77,52,57,65,103,69,71,67,67,113,71,83,77,52,57,65,119,69,72,65,48,73,65,66,71,112,118,10,48,89,117,89,114,113,65,117,83,75,66,122,75,108,117,98,54,109,76,43,114,118,102,68,53,65,106,89,79,51,81,78,103,102,87,122,116,103,52,101,109,49,69,71,66,86,107,71,108,87,118,100,117,66,48,88,81,83,69,47,115,120,71,68,10,109,83,118,75,111,57,116,51,67,114,79,80,67,52,83,85,54,88,54,106,103,103,77,77,77,73,73,68,67,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,83,86,98,49,51,78,118,82,118,104,54,85,66,74,121,100,84,48,10,77,56,52,66,86,119,118,101,86,68,66,114,66,103,78,86,72,82,56,69,90,68,66,105,77,71,67,103,88,113,66,99,104,108,112,111,100,72,82,119,99,122,111,118,76,50,70,119,97,83,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,51,78,110,101,67,57,106,90,88,74,48,97,87,90,112,89,50,70,48,97,87,57,117,76,51,89,48,76,51,66,106,97,50,78,121,98,68,57,106,89,84,49,119,10,98,71,70,48,90,109,57,121,98,83,90,108,98,109,78,118,90,71,108,117,90,122,49,107,90,88,73,119,72,81,89,68,86,82,48,79,66,66,89,69,70,71,51,110,54,83,43,75,120,78,54,116,43,72,73,56,71,112,57,54,80,107,117,90,10,105,87,115,90,77,65,52,71,65,49,85,100,68,119,69,66,47,119,81,69,65,119,73,71,119,68,65,77,66,103,78,86,72,82,77,66,65,102,56,69,65,106,65,65,77,73,73,67,79,81,89,74,75,111,90,73,104,118,104,78,65,81,48,66,10,66,73,73,67,75,106,67,67,65,105,89,119,72,103,89,75,75,111,90,73,104,118,104,78,65,81,48,66,65,81,81,81,48,103,106,102,115,81,65,106,82,113,52,98,116,79,56,113,80,65,86,83,107,106,67,67,65,87,77,71,67,105,113,71,10,83,73,98,52,84,81,69,78,65,81,73,119,103,103,70,84,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,66,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,67,65,103,69,69,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,68,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,69,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,70,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,71,65,103,69,66,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,72,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,73,65,103,69,70,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,74,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,75,65,103,69,65,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,76,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,77,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,78,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,79,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,80,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,81,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,82,65,103,69,76,77,66,56,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,83,66,66,65,69,10,66,65,73,67,66,65,69,65,66,81,65,65,65,65,65,65,65,65,65,65,77,66,65,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,77,69,65,103,65,65,77,66,81,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,81,69,10,66,114,68,65,98,119,65,65,65,68,65,80,66,103,111,113,104,107,105,71,43,69,48,66,68,81,69,70,67,103,69,66,77,66,52,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,89,69,69,68,97,57,104,116,65,56,65,74,47,90,10,50,70,109,97,76,53,74,113,47,75,69,119,82,65,89,75,75,111,90,73,104,118,104,78,65,81,48,66,66,122,65,50,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,66,65,81,72,47,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,99,67,65,81,72,47,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,68,65,81,72,47,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,65,48,107,65,77,69,89,67,10,73,81,67,70,71,49,89,65,98,51,101,88,70,116,101,56,53,51,67,108,86,66,110,104,108,67,102,68,121,99,53,55,50,90,88,69,113,97,120,52,85,99,99,83,97,119,73,104,65,79,110,48,86,78,75,84,90,109,65,120,85,70,52,110,10,119,82,107,83,70,104,52,113,70,74,51,97,85,108,122,70,111,80,81,84,51,120,73,102,55,107,70,68,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,108,106,67,67,65,106,50,103,65,119,73,66,65,103,73,86,65,74,86,118,88,99,50,57,71,43,72,112,81,69,110,74,49,80,81,122,122,103,70,88,67,57,53,85,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,10,77,71,103,120,71,106,65,89,66,103,78,86,66,65,77,77,69,85,108,117,100,71,86,115,73,70,78,72,87,67,66,83,98,50,57,48,73,69,78,66,77,82,111,119,71,65,89,68,86,81,81,75,68,66,70,74,98,110,82,108,98,67,66,68,10,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,66,65,103,77,65,107,78,66,77,81,115,119,10,67,81,89,68,86,81,81,71,69,119,74,86,85,122,65,101,70,119,48,120,79,68,65,49,77,106,69,120,77,68,85,119,77,84,66,97,70,119,48,122,77,122,65,49,77,106,69,120,77,68,85,119,77,84,66,97,77,72,65,120,73,106,65,103,10,66,103,78,86,66,65,77,77,71,85,108,117,100,71,86,115,73,70,78,72,87,67,66,81,81,48,115,103,85,71,120,104,100,71,90,118,99,109,48,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,10,73,69,78,118,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,10,67,122,65,74,66,103,78,86,66,65,89,84,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,78,83,66,47,55,116,50,49,108,88,83,79,10,50,67,117,122,112,120,119,55,52,101,74,66,55,50,69,121,68,71,103,87,53,114,88,67,116,120,50,116,86,84,76,113,54,104,75,107,54,122,43,85,105,82,90,67,110,113,82,55,112,115,79,118,103,113,70,101,83,120,108,109,84,108,74,108,10,101,84,109,105,50,87,89,122,51,113,79,66,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,10,66,103,78,86,72,82,56,69,83,122,66,74,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,108,87,57,100,10,122,98,48,98,52,101,108,65,83,99,110,85,57,68,80,79,65,86,99,76,51,108,81,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,10,65,102,56,67,65,81,65,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,68,82,119,65,119,82,65,73,103,88,115,86,107,105,48,119,43,105,54,86,89,71,87,51,85,70,47,50,50,117,97,88,101,48,89,74,68,106,49,85,101,10,110,65,43,84,106,68,49,97,105,53,99,67,73,67,89,98,49,83,65,109,68,53,120,107,102,84,86,112,118,111,52,85,111,121,105,83,89,120,114,68,87,76,109,85,82,52,67,73,57,78,75,121,102,80,78,43,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,106,122,67,67,65,106,83,103,65,119,73,66,65,103,73,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,85,114,57,81,71,122,107,110,66,113,119,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,97,68,69,97,77,66,103,71,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,10,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,10,66,103,78,86,66,65,89,84,65,108,86,84,77,66,52,88,68,84,69,52,77,68,85,121,77,84,69,119,78,68,85,120,77,70,111,88,68,84,81,53,77,84,73,122,77,84,73,122,78,84,107,49,79,86,111,119,97,68,69,97,77,66,103,71,10,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,99,110,66,118,99,109,70,48,10,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,66,103,78,86,66,65,89,84,10,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,67,54,110,69,119,77,68,73,89,90,79,106,47,105,80,87,115,67,122,97,69,75,105,55,10,49,79,105,79,83,76,82,70,104,87,71,106,98,110,66,86,74,102,86,110,107,89,52,117,51,73,106,107,68,89,89,76,48,77,120,79,52,109,113,115,121,89,106,108,66,97,108,84,86,89,120,70,80,50,115,74,66,75,53,122,108,75,79,66,10,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,66,103,78,86,72,82,56,69,83,122,66,74,10,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,100,109,108,106,90,88,77,117,97,87,53,48,10,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,10,85,114,57,81,71,122,107,110,66,113,119,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,65,102,56,67,65,81,69,119,67,103,89,73,10,75,111,90,73,122,106,48,69,65,119,73,68,83,81,65,119,82,103,73,104,65,79,87,47,53,81,107,82,43,83,57,67,105,83,68,99,78,111,111,119,76,117,80,82,76,115,87,71,102,47,89,105,55,71,83,88,57,52,66,103,119,84,119,103,10,65,105,69,65,52,74,48,108,114,72,111,77,115,43,88,111,53,111,47,115,88,54,79,57,81,87,120,72,82,65,118,90,85,71,79,100,82,81,55,99,118,113,82,88,97,113,73,61,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] +[4,0,2,0,129,0,0,0,0,0,0,0,147,154,114,51,247,156,76,169,148,10,13,179,149,127,6,7,61,153,138,108,16,87,107,253,246,246,237,142,155,133,233,50,0,0,0,0,11,1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,123,240,99,40,14,148,251,5,31,93,215,177,252,89,206,154,172,66,187,150,29,248,212,75,112,156,155,15,248,122,123,77,246,72,101,123,166,209,24,149,137,254,171,29,90,60,154,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,231,2,6,0,0,0,0,0,240,109,253,166,220,225,207,144,77,78,43,171,29,195,112,99,76,249,92,239,162,206,178,222,46,238,18,124,147,130,105,128,144,215,164,161,62,20,197,54,236,108,156,60,143,168,112,119,1,4,189,12,224,238,210,51,174,199,171,11,95,0,77,81,113,205,45,49,69,175,241,74,71,134,223,194,247,63,167,124,164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,115,190,47,112,190,239,183,11,72,166,16,158,237,71,21,215,39,13,70,131,179,191,53,111,162,95,175,191,26,167,110,57,233,18,126,110,104,140,205,169,139,218,177,212,212,127,70,181,152,253,233,73,20,39,52,27,196,104,59,117,209,13,62,54,119,10,243,163,106,105,84,216,182,183,178,42,166,99,88,241,62,31,23,46,81,183,214,230,113,13,153,168,216,83,47,200,18,212,43,255,241,199,83,130,233,26,55,200,103,171,17,123,151,235,94,141,103,151,72,137,40,234,56,229,253,56,181,237,47,135,217,97,61,57,37,7,241,195,175,148,101,124,147,61,141,190,131,85,34,25,81,20,73,145,236,151,114,221,138,33,243,2,170,53,109,96,162,165,201,225,212,75,7,68,20,176,251,204,134,235,3,16,41,220,122,147,117,173,209,4,188,0,1,102,242,14,106,249,24,93,165,3,93,108,158,238,191,100,105,179,41,150,24,0,67,250,85,26,150,47,12,40,104,54,48,167,149,121,28,189,235,216,43,32,82,144,248,224,61,241,199,0,0,0,0,0,0,0,0,0,0,0,0,0,0,204,16,0,0,241,19,195,17,10,139,210,55,4,123,145,112,95,74,179,114,109,85,205,44,240,62,89,91,20,102,188,35,112,29,102,40,113,171,227,142,42,131,140,185,4,176,94,28,60,131,198,154,106,207,105,135,196,118,61,116,87,43,60,206,63,38,73,5,142,188,151,224,189,139,21,116,87,28,157,151,225,226,250,218,147,80,231,144,252,223,62,103,176,31,51,101,181,44,82,180,72,148,151,10,88,144,81,87,230,135,174,102,165,143,241,229,60,148,151,208,187,151,100,64,82,171,52,1,40,143,31,160,6,0,70,16,0,0,4,4,25,27,4,255,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,231,0,0,0,0,0,0,0,229,163,167,181,216,48,194,149,59,152,83,76,108,89,163,163,79,220,52,233,51,247,245,137,143,10,133,207,8,132,107,202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,158,42,124,111,148,143,23,71,78,52,167,252,67,237,3,15,124,21,99,241,186,189,223,99,64,200,46,14,84,168,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,98,66,167,203,62,30,139,2,195,192,57,51,40,206,207,77,159,207,61,144,77,52,130,175,199,184,139,101,54,6,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,104,20,163,161,53,224,108,242,243,89,254,44,94,6,221,208,114,104,245,136,152,247,114,38,13,159,166,76,210,218,35,176,50,73,126,90,51,71,162,188,242,213,199,51,51,241,214,54,118,105,53,222,159,223,198,96,15,35,136,163,243,191,8,32,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,5,0,94,14,0,0,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,69,56,84,67,67,66,74,97,103,65,119,73,66,65,103,73,85,102,50,83,98,121,119,107,77,86,84,74,75,85,53,55,47,74,119,66,112,56,69,100,104,80,48,52,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,99,68,69,105,77,67,65,71,65,49,85,69,65,119,119,90,83,87,53,48,90,87,119,103,85,48,100,89,73,70,66,68,83,121,66,81,98,71,70,48,90,109,57,121,98,83,66,68,81,84,69,97,77,66,103,71,65,49,85,69,67,103,119,82,10,83,87,53,48,90,87,119,103,81,50,57,121,99,71,57,121,89,88,82,112,98,50,52,120,70,68,65,83,66,103,78,86,66,65,99,77,67,49,78,104,98,110,82,104,73,69,78,115,89,88,74,104,77,81,115,119,67,81,89,68,86,81,81,73,10,68,65,74,68,81,84,69,76,77,65,107,71,65,49,85,69,66,104,77,67,86,86,77,119,72,104,99,78,77,106,85,120,77,84,65,50,77,68,99,122,78,122,77,48,87,104,99,78,77,122,73,120,77,84,65,50,77,68,99,122,78,122,77,48,10,87,106,66,119,77,83,73,119,73,65,89,68,86,81,81,68,68,66,108,74,98,110,82,108,98,67,66,84,82,49,103,103,85,69,78,76,73,69,78,108,99,110,82,112,90,109,108,106,89,88,82,108,77,82,111,119,71,65,89,68,86,81,81,75,10,68,66,70,74,98,110,82,108,98,67,66,68,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,10,66,65,103,77,65,107,78,66,77,81,115,119,67,81,89,68,86,81,81,71,69,119,74,86,85,122,66,90,77,66,77,71,66,121,113,71,83,77,52,57,65,103,69,71,67,67,113,71,83,77,52,57,65,119,69,72,65,48,73,65,66,71,112,118,10,48,89,117,89,114,113,65,117,83,75,66,122,75,108,117,98,54,109,76,43,114,118,102,68,53,65,106,89,79,51,81,78,103,102,87,122,116,103,52,101,109,49,69,71,66,86,107,71,108,87,118,100,117,66,48,88,81,83,69,47,115,120,71,68,10,109,83,118,75,111,57,116,51,67,114,79,80,67,52,83,85,54,88,54,106,103,103,77,77,77,73,73,68,67,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,83,86,98,49,51,78,118,82,118,104,54,85,66,74,121,100,84,48,10,77,56,52,66,86,119,118,101,86,68,66,114,66,103,78,86,72,82,56,69,90,68,66,105,77,71,67,103,88,113,66,99,104,108,112,111,100,72,82,119,99,122,111,118,76,50,70,119,97,83,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,51,78,110,101,67,57,106,90,88,74,48,97,87,90,112,89,50,70,48,97,87,57,117,76,51,89,48,76,51,66,106,97,50,78,121,98,68,57,106,89,84,49,119,10,98,71,70,48,90,109,57,121,98,83,90,108,98,109,78,118,90,71,108,117,90,122,49,107,90,88,73,119,72,81,89,68,86,82,48,79,66,66,89,69,70,71,51,110,54,83,43,75,120,78,54,116,43,72,73,56,71,112,57,54,80,107,117,90,10,105,87,115,90,77,65,52,71,65,49,85,100,68,119,69,66,47,119,81,69,65,119,73,71,119,68,65,77,66,103,78,86,72,82,77,66,65,102,56,69,65,106,65,65,77,73,73,67,79,81,89,74,75,111,90,73,104,118,104,78,65,81,48,66,10,66,73,73,67,75,106,67,67,65,105,89,119,72,103,89,75,75,111,90,73,104,118,104,78,65,81,48,66,65,81,81,81,48,103,106,102,115,81,65,106,82,113,52,98,116,79,56,113,80,65,86,83,107,106,67,67,65,87,77,71,67,105,113,71,10,83,73,98,52,84,81,69,78,65,81,73,119,103,103,70,84,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,66,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,67,65,103,69,69,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,68,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,69,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,70,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,71,65,103,69,66,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,72,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,73,65,103,69,70,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,74,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,75,65,103,69,65,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,76,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,77,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,78,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,79,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,80,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,81,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,82,65,103,69,76,77,66,56,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,83,66,66,65,69,10,66,65,73,67,66,65,69,65,66,81,65,65,65,65,65,65,65,65,65,65,77,66,65,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,77,69,65,103,65,65,77,66,81,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,81,69,10,66,114,68,65,98,119,65,65,65,68,65,80,66,103,111,113,104,107,105,71,43,69,48,66,68,81,69,70,67,103,69,66,77,66,52,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,89,69,69,68,97,57,104,116,65,56,65,74,47,90,10,50,70,109,97,76,53,74,113,47,75,69,119,82,65,89,75,75,111,90,73,104,118,104,78,65,81,48,66,66,122,65,50,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,66,65,81,72,47,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,99,67,65,81,72,47,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,68,65,81,72,47,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,65,48,107,65,77,69,89,67,10,73,81,67,70,71,49,89,65,98,51,101,88,70,116,101,56,53,51,67,108,86,66,110,104,108,67,102,68,121,99,53,55,50,90,88,69,113,97,120,52,85,99,99,83,97,119,73,104,65,79,110,48,86,78,75,84,90,109,65,120,85,70,52,110,10,119,82,107,83,70,104,52,113,70,74,51,97,85,108,122,70,111,80,81,84,51,120,73,102,55,107,70,68,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,108,106,67,67,65,106,50,103,65,119,73,66,65,103,73,86,65,74,86,118,88,99,50,57,71,43,72,112,81,69,110,74,49,80,81,122,122,103,70,88,67,57,53,85,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,10,77,71,103,120,71,106,65,89,66,103,78,86,66,65,77,77,69,85,108,117,100,71,86,115,73,70,78,72,87,67,66,83,98,50,57,48,73,69,78,66,77,82,111,119,71,65,89,68,86,81,81,75,68,66,70,74,98,110,82,108,98,67,66,68,10,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,66,65,103,77,65,107,78,66,77,81,115,119,10,67,81,89,68,86,81,81,71,69,119,74,86,85,122,65,101,70,119,48,120,79,68,65,49,77,106,69,120,77,68,85,119,77,84,66,97,70,119,48,122,77,122,65,49,77,106,69,120,77,68,85,119,77,84,66,97,77,72,65,120,73,106,65,103,10,66,103,78,86,66,65,77,77,71,85,108,117,100,71,86,115,73,70,78,72,87,67,66,81,81,48,115,103,85,71,120,104,100,71,90,118,99,109,48,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,10,73,69,78,118,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,10,67,122,65,74,66,103,78,86,66,65,89,84,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,78,83,66,47,55,116,50,49,108,88,83,79,10,50,67,117,122,112,120,119,55,52,101,74,66,55,50,69,121,68,71,103,87,53,114,88,67,116,120,50,116,86,84,76,113,54,104,75,107,54,122,43,85,105,82,90,67,110,113,82,55,112,115,79,118,103,113,70,101,83,120,108,109,84,108,74,108,10,101,84,109,105,50,87,89,122,51,113,79,66,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,10,66,103,78,86,72,82,56,69,83,122,66,74,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,108,87,57,100,10,122,98,48,98,52,101,108,65,83,99,110,85,57,68,80,79,65,86,99,76,51,108,81,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,10,65,102,56,67,65,81,65,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,68,82,119,65,119,82,65,73,103,88,115,86,107,105,48,119,43,105,54,86,89,71,87,51,85,70,47,50,50,117,97,88,101,48,89,74,68,106,49,85,101,10,110,65,43,84,106,68,49,97,105,53,99,67,73,67,89,98,49,83,65,109,68,53,120,107,102,84,86,112,118,111,52,85,111,121,105,83,89,120,114,68,87,76,109,85,82,52,67,73,57,78,75,121,102,80,78,43,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,106,122,67,67,65,106,83,103,65,119,73,66,65,103,73,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,85,114,57,81,71,122,107,110,66,113,119,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,97,68,69,97,77,66,103,71,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,10,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,10,66,103,78,86,66,65,89,84,65,108,86,84,77,66,52,88,68,84,69,52,77,68,85,121,77,84,69,119,78,68,85,120,77,70,111,88,68,84,81,53,77,84,73,122,77,84,73,122,78,84,107,49,79,86,111,119,97,68,69,97,77,66,103,71,10,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,99,110,66,118,99,109,70,48,10,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,66,103,78,86,66,65,89,84,10,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,67,54,110,69,119,77,68,73,89,90,79,106,47,105,80,87,115,67,122,97,69,75,105,55,10,49,79,105,79,83,76,82,70,104,87,71,106,98,110,66,86,74,102,86,110,107,89,52,117,51,73,106,107,68,89,89,76,48,77,120,79,52,109,113,115,121,89,106,108,66,97,108,84,86,89,120,70,80,50,115,74,66,75,53,122,108,75,79,66,10,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,66,103,78,86,72,82,56,69,83,122,66,74,10,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,100,109,108,106,90,88,77,117,97,87,53,48,10,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,10,85,114,57,81,71,122,107,110,66,113,119,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,65,102,56,67,65,81,69,119,67,103,89,73,10,75,111,90,73,122,106,48,69,65,119,73,68,83,81,65,119,82,103,73,104,65,79,87,47,53,81,107,82,43,83,57,67,105,83,68,99,78,111,111,119,76,117,80,82,76,115,87,71,102,47,89,105,55,71,83,88,57,52,66,103,119,84,119,103,10,65,105,69,65,52,74,48,108,114,72,111,77,115,43,88,111,53,111,47,115,88,54,79,57,81,87,120,72,82,65,118,90,85,71,79,100,82,81,55,99,118,113,82,88,97,113,73,61,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] diff --git a/crates/test-utils/assets/tcb_info.json b/crates/test-utils/assets/tcb_info.json index 46da8f1ceb..be2899e81b 100644 --- a/crates/test-utils/assets/tcb_info.json +++ b/crates/test-utils/assets/tcb_info.json @@ -3,11 +3,11 @@ "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "8050d4769527c84cb066078854ef8eb50ea7b150e072eeec7007240aca01b556041273ea3d20a1b1d48736f650ce13f0", + "rtmr3": "3d8dbe8355221951144991ec9772dd8a21f302aa356d60a2a5c9e1d44b074414b0fbcc86eb031029dc7a9375add104bc", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a", + "compose_hash": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786102851\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\n# Test-asset collection hook, sourced by the CVM's app-compose.sh before the\\n# node starts. The node generates its NEAR signer key in-enclave, so exporting\\n# that key is the only way to check the fixture keypair into the repo next to\\n# the quote it is bound to (near/mpc #3787).\\n#\\n# The key appears only after the node starts, i.e. after this hook returns, so\\n# the wait runs as its own systemd unit: a plain background process would be\\n# reaped with app-compose.service's cgroup. The copy target is the CVM's\\n# host-shared dir, which the host sees as run/vm//shared/.\\n#\\n# The guest userland is BusyBox, so the wait loop sticks to shell built-ins and\\n# globs (no find/head, whose GNU options BusyBox rejects).\\n#\\n# Only ever use this on a throwaway localnet CVM: it exports a private key.\\n\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\nEXFIL=/etc/fixture-exfil.sh\\n\\ncat > \\\"$EXFIL\\\" <<'EOF'\\n#!/bin/sh\\nCONSOLE=/dev/console\\nSHARED=/dstack/.host-shared\\ni=0\\nwhile [ \\\"$i\\\" -lt 900 ]; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n if [ -f \\\"$f\\\" ]; then\\n cp \\\"$f\\\" \\\"$SHARED/fixture-secrets.json\\\" 2>/dev/null\\n {\\n echo \\\"FIXTURE-SECRETS-BEGIN $f\\\"\\n cat \\\"$f\\\"\\n echo \\\"\\\"\\n echo \\\"FIXTURE-SECRETS-END\\\"\\n } > \\\"$CONSOLE\\\" 2>&1\\n exit 0\\n fi\\n done\\n i=$((i + 1))\\n sleep 2\\ndone\\necho \\\"FIXTURE-SECRETS-TIMEOUT\\\" > \\\"$CONSOLE\\\" 2>&1\\nEOF\\nchmod +x \\\"$EXFIL\\\" 2>/dev/null\\n\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Unit]\\nDescription=Export the MPC node signer key for test-asset collection\\n[Service]\\nType=oneshot\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nStandardOutput=journal+console\\nStandardError=journal+console\\nEOF\\n\\nsystemctl daemon-reload >/dev/null 2>&1\\nsystemctl start --no-block fixture-exfil.service >/dev/null 2>&1\\n\\n{\\n echo \\\"FIXTURE-DIAG-BEGIN\\\"\\n echo \\\"exfil_script=$([ -f \\\"$EXFIL\\\" ] && echo present || echo missing)\\\"\\n echo \\\"unit_state=$(systemctl is-active fixture-exfil.service 2>&1)\\\"\\n echo \\\"shared_writable=$([ -w \\\"$SHARED\\\" ] && echo yes || echo no)\\\"\\n echo \\\"FIXTURE-DIAG-END\\\"\\n} > \\\"$CONSOLE\\\" 2>&1\\n\"\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786440162\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\ncat > /etc/fixture-exfil.sh <<'EOF'\\n#!/bin/sh\\nwhile :; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n [ -f \\\"$f\\\" ] && cat \\\"$f\\\" > /dev/console && exit 0\\n done\\n sleep 2\\ndone\\nEOF\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Service]\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nEOF\\nsystemctl daemon-reload\\nsystemctl start --no-block fixture-exfil.service\\n\"\n}", "event_log": [ { "imr": 0, @@ -159,16 +159,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "970c96ea5f1ea46650645363f1716fd4e4260c92f614a6af308d4ca2e352b4dbd3d8f326e5a513c20b3029163284257e", + "digest": "02e1e5a9c9612830b0dfbc7e0e73ce13667254658b1177a8888ecdf2f3c729cfed158e4bde6c113e31112360f6d5df97", "event": "app-id", - "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfaf" + "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145" }, { "imr": 3, "event_type": 134217729, - "digest": "6d4e926546694d6e8acc53d46b216cde12d3a60cd3b60550ab7db7f4920fc42c304f8af924e08f96c108a7f7076cf02a", + "digest": "0724a946d4c56944af69a502165a07082875b44e15abaa15171dcd44c1c2955303a6bdfa59f2e58e63d206b079a6e5cc", "event": "compose-hash", - "event_payload": "c6775c4d9bb7273ca21cd54be6b6a1879328dfafbeb550f6957b821e212f0d4a" + "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4" }, { "imr": 3, diff --git a/crates/test-utils/src/attestation.rs b/crates/test-utils/src/attestation.rs index e22d86ec32..477d3188db 100644 --- a/crates/test-utils/src/attestation.rs +++ b/crates/test-utils/src/attestation.rs @@ -24,7 +24,7 @@ pub const TEST_LAUNCHER_IMAGE_COMPOSE_STRING: &str = /// Unix time as of 2026/08/07, represents a date where /// the measurements stored in ../assets are valid. When these measurements are /// modified, this value should be updated as well -pub const VALID_ATTESTATION_TIMESTAMP: u64 = 1786103100; +pub const VALID_ATTESTATION_TIMESTAMP: u64 = 1786440300; pub fn launcher_compose_digest() -> LauncherDockerComposeHash { let digest: [u8; 32] = Sha256::digest(TEST_LAUNCHER_IMAGE_COMPOSE_STRING).into(); diff --git a/localnet/tee/scripts/rust-launcher/README.md b/localnet/tee/scripts/rust-launcher/README.md index 7e59178e4a..98ed36d7c0 100644 --- a/localnet/tee/scripts/rust-launcher/README.md +++ b/localnet/tee/scripts/rust-launcher/README.md @@ -32,13 +32,15 @@ The node env template `../node.env.tpl` also lives here (one level up) and is sh ## Collecting Test Assets -To regenerate test assets from real TDX attestation, from the repo root on the TDX host: +To regenerate test assets from real TDX attestation, from the repo root on the TDX host. Set up the +prerequisites and required variables from [single-node-readme.md](single-node-readme.md) first: a +running localnet in `~/.near/mpc-localnet`, `MACHINE_IP`, and the two image digests. ```bash export BASE_PATH=/path/to/meta-dstack/dstack export WORKDIR=/tmp/mpc-fixture-collection -# PRELAUNCH_SCRIPT is what makes the node's signer secret key recoverable; see below. +# Reuse the fixture's current image digests unless changing images: steps 6-7 below then stay no-ops. PRELAUNCH_SCRIPT=localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh \ bash localnet/tee/scripts/rust-launcher/single-node.sh @@ -50,41 +52,26 @@ step 3, which own the rest of the procedure. ### Exporting the node's signer key -Sandbox tests that store a Verified attestation must sign as the fixture node: the quote's -`report_data` binds the node's account key, and the contract reads that key from the transaction -signer. The node generates it inside the CVM, so it has to be exported during collection. +The node generates its NEAR signer key inside the CVM, and sandbox tests need it to sign as the fixture +node. Handing the node a key instead does not work: the measured compose mounts only `mpc-data`. -Supplying the key instead does not work. The node reuses an existing `secrets.json`, but the -launcher's measured compose mounts only the `mpc-data` volume into the node container, so the host has -nowhere to put one. - -[export-signer-key-prelaunch.sh](export-signer-key-prelaunch.sh) is the hook that produced the -committed fixture; `PRELAUNCH_SCRIPT` above bakes it into the app-compose. It waits for the node to -write `secrets.json`, then copies it into the CVM's shared dir and echoes it to the console, so -whichever channel the host exposes is enough. Both live under the vmm's `run_path`: +[export-signer-key-prelaunch.sh](export-signer-key-prelaunch.sh) waits for `secrets.json` and echoes it +to the console, the guest's only way out — the shared dir is mounted read-only. Read it from the new +VM's log under the vmm's `run_path`: ```bash -RUN_VM="$(dirname "$BASE_PATH")/build/run/vm" # `run_path` in the vmm config -cat "$RUN_VM"/*/shared/fixture-secrets.json -grep -A3 FIXTURE-SECRETS-BEGIN "$RUN_VM"/*/serial.log # fallback if the copy failed +grep -o '"near_signer_key":"[^"]*"' "$(dirname "$BASE_PATH")/build/run/vm"/*/serial.log ``` -Put `near_signer_key` from there into `crates/test-utils/assets/near_account_secret_key` (one line, -`ed25519:`). Only ever do this for a throwaway localnet node: the key ends up in the repo. +Put that value into `crates/test-utils/assets/near_account_secret_key` (one line, `ed25519:`). +Only ever do this for a throwaway localnet node: the key ends up in the repo. -The script is a copy of what the committed app-compose carries, which is what ties it to the committed -key. After editing either one, this must stay empty: +The script is a copy of what the committed app-compose carries, so after editing either one: ```bash diff <(jq -j '.pre_launch_script' crates/test-utils/assets/app_compose.json) \ localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh ``` -Writing a different hook: the guest is BusyBox, so built-ins and globs only and no `sshd`; `/etc` and -`/dstack/.host-shared` are writable but `/` is not; and the wait needs its own systemd unit, since a -background process is reaped with `app-compose.service`'s cgroup. - -Any app-compose carrying a script is rejected by production verification. Test builds accept this one -field via `attestation/allow-pre-launch-script`, so keep the hook minimal. - -See [single-node-readme.md](single-node-readme.md) for details. +Replacing it with a different hook: BusyBox guest, built-ins and globs only, `/etc` the writable path, +and the wait needs its own systemd unit or it is reaped with `app-compose.service`'s cgroup. diff --git a/localnet/tee/scripts/rust-launcher/single-node-readme.md b/localnet/tee/scripts/rust-launcher/single-node-readme.md index a24aa7e9ce..8fee005a74 100644 --- a/localnet/tee/scripts/rust-launcher/single-node-readme.md +++ b/localnet/tee/scripts/rust-launcher/single-node-readme.md @@ -45,10 +45,7 @@ export OS_IMAGE=dstack-0.5.8 export NODE_ACCOUNT=frodo.test.near export CONTRACT_ACCOUNT=mpc-contract.test.near -# Script executed inside the CVM before docker compose up, and the only way to -# run anything of your own in there. Needed when collecting test assets, to -# export the node's in-enclave signer key: the dev image has no sshd, and the -# guest agent serves only node info and container logs. +# Exports the node's in-enclave signer key; needed when collecting test assets. export PRELAUNCH_SCRIPT=localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh ``` From cb51a9effed4d600e88f2bfdabc3d29a4a56b2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Tue, 11 Aug 2026 16:36:12 +0200 Subject: [PATCH 13/32] chore(localnet): pass `PRELAUNCH_SCRIPT` as an absolute path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing else in these scripts rewrites a user-supplied relative path: `BASE_PATH` is used verbatim, and `ENV_TPL`/`CONF_TPL` only default to paths under the repo root. Resolving this one made it behave unlike its neighbours, so the runbook passes an absolute path instead and `deploy-launcher.sh` fails fast when it does not exist. That leaves `single-node.sh` unchanged from main: re-exporting the variable was a no-op, since a value set on the command line is already in the environment that `deploy-launcher.sh` inherits. Also drops the commented-out `PRELAUNCH_SCRIPT` from `default.env`, which the collection flow never reads — `single-node.sh` overrides `--env-file` — and trims the warning at the point of use. --- crates/attestation/Cargo.toml | 3 --- deployment/cvm-deployment/default.env | 6 ------ deployment/cvm-deployment/deploy-launcher.sh | 11 +++-------- localnet/tee/scripts/rust-launcher/README.md | 2 +- .../tee/scripts/rust-launcher/single-node-readme.md | 2 +- localnet/tee/scripts/rust-launcher/single-node.sh | 11 ----------- 6 files changed, 5 insertions(+), 30 deletions(-) diff --git a/crates/attestation/Cargo.toml b/crates/attestation/Cargo.toml index d467258115..baa956ca3a 100644 --- a/crates/attestation/Cargo.toml +++ b/crates/attestation/Cargo.toml @@ -13,9 +13,6 @@ test-utils = [] # key in `crates/test-utils/assets/near_account_secret_key`. Never implied by another feature, so # every enablement stays explicit and must stay on dependency edges that only tests build. allow-pre-launch-script = [] -# Pulls in `dcap-qvl` for full local DCAP + post-DCAP verification. Off-chain callers only: the -# node, the attestation CLI and the TEE authority. The contract verifies through the verifier -# contract instead. local-verify = ["dep:dcap-qvl", "dep:tee-verifier-conversions"] [dependencies] diff --git a/deployment/cvm-deployment/default.env b/deployment/cvm-deployment/default.env index 794053fd95..da6d2bd16e 100644 --- a/deployment/cvm-deployment/default.env +++ b/deployment/cvm-deployment/default.env @@ -69,11 +69,5 @@ OS_IMAGE=dstack-dev-0.5.8 # Path of the user_config file USER_CONFIG_FILE_PATH=user-config.toml -# Leave unset. A pre-launch script runs as root inside the CVM, and attestation -# verification rejects any app-compose carrying one, so the CVM cannot join the -# network. Only fixture collection sets this; see -# localnet/tee/scripts/rust-launcher/README.md -#PRELAUNCH_SCRIPT= - # for testing use a smaller disk size 128G DISK=1000G diff --git a/deployment/cvm-deployment/deploy-launcher.sh b/deployment/cvm-deployment/deploy-launcher.sh index ed2f7244cc..764165cf25 100755 --- a/deployment/cvm-deployment/deploy-launcher.sh +++ b/deployment/cvm-deployment/deploy-launcher.sh @@ -262,20 +262,15 @@ case $SEALING_KEY_TYPE in esac -# Optional pre-launch script baked into the app-compose, executed inside the -# CVM before docker compose up. It is the only way to run anything of our own -# in a CVM, which test-asset collection needs to export the node's in-enclave -# signer key. Attestation verification rejects an app-compose carrying one, so -# never set this outside fixture collection. +# Optional script baked into the app-compose and run as root in the CVM before docker compose up. +# Only fixture collection sets it: attestation rejects an app-compose carrying a script. PRELAUNCH_ARGS=() if [ -n "${PRELAUNCH_SCRIPT:-}" ]; then if [ ! -f "$PRELAUNCH_SCRIPT" ]; then echo "Error: PRELAUNCH_SCRIPT '$PRELAUNCH_SCRIPT' does not exist" exit 1 fi - echo "WARNING: baking pre-launch script '$PRELAUNCH_SCRIPT' into the app-compose." - echo " Attestation verification rejects any app-compose carrying a script," - echo " so this CVM will FAIL attestation. Use only for fixture collection." + echo "WARNING: baking '$PRELAUNCH_SCRIPT' into the app-compose; this CVM will FAIL attestation." PRELAUNCH_ARGS=(--prelaunch-script "$PRELAUNCH_SCRIPT") fi diff --git a/localnet/tee/scripts/rust-launcher/README.md b/localnet/tee/scripts/rust-launcher/README.md index 98ed36d7c0..1fb315747f 100644 --- a/localnet/tee/scripts/rust-launcher/README.md +++ b/localnet/tee/scripts/rust-launcher/README.md @@ -41,7 +41,7 @@ export BASE_PATH=/path/to/meta-dstack/dstack export WORKDIR=/tmp/mpc-fixture-collection # Reuse the fixture's current image digests unless changing images: steps 6-7 below then stay no-ops. -PRELAUNCH_SCRIPT=localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh \ +PRELAUNCH_SCRIPT="$PWD/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh" \ bash localnet/tee/scripts/rust-launcher/single-node.sh cp "$WORKDIR/public_data.json" crates/test-utils/assets/public_data.json diff --git a/localnet/tee/scripts/rust-launcher/single-node-readme.md b/localnet/tee/scripts/rust-launcher/single-node-readme.md index 8fee005a74..dfb8d52e75 100644 --- a/localnet/tee/scripts/rust-launcher/single-node-readme.md +++ b/localnet/tee/scripts/rust-launcher/single-node-readme.md @@ -46,7 +46,7 @@ export NODE_ACCOUNT=frodo.test.near export CONTRACT_ACCOUNT=mpc-contract.test.near # Exports the node's in-enclave signer key; needed when collecting test assets. -export PRELAUNCH_SCRIPT=localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh +export PRELAUNCH_SCRIPT=$PWD/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh ``` ## Run diff --git a/localnet/tee/scripts/rust-launcher/single-node.sh b/localnet/tee/scripts/rust-launcher/single-node.sh index d23e7e535e..e55bf29007 100644 --- a/localnet/tee/scripts/rust-launcher/single-node.sh +++ b/localnet/tee/scripts/rust-launcher/single-node.sh @@ -132,23 +132,12 @@ OS_IMAGE="${OS_IMAGE:-dstack-dev-0.5.8}" SEALING_KEY_TYPE="${SEALING_KEY_TYPE:-SGX}" DISK="${DISK:-500G}" -# Optional: path to a script baked into the app-compose and executed inside the -# CVM before docker compose up. Collecting test assets needs one, to export the -# node's in-enclave signer key; see the README. Consumed by deploy-launcher.sh. -export PRELAUNCH_SCRIPT="${PRELAUNCH_SCRIPT:-}" - # Paths REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}" TEE_LAUNCHER_DIR="$REPO_ROOT/deployment/cvm-deployment" ENV_TPL="${ENV_TPL:-$REPO_ROOT/localnet/tee/scripts/node.env.tpl}" CONF_TPL="${CONF_TPL:-$REPO_ROOT/localnet/tee/scripts/rust-launcher/node.conf.localnet.toml.tpl}" -# deploy-launcher.sh reads it from its own directory, so a relative path has to be -# resolved here or it is looked up two directories away. -if [ -n "$PRELAUNCH_SCRIPT" ] && [ "${PRELAUNCH_SCRIPT#/}" = "$PRELAUNCH_SCRIPT" ]; then - PRELAUNCH_SCRIPT="$REPO_ROOT/$PRELAUNCH_SCRIPT" -fi - WORKDIR="${WORKDIR:-$(mktemp -d /tmp/mpc_localnet_one_node.XXXXXX)}" mkdir -p "$WORKDIR" log "Work directory: $WORKDIR" From 5fa0480005b77de9f640d6260dfcf3109ee39f57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Tue, 11 Aug 2026 17:19:22 +0200 Subject: [PATCH 14/32] test: note which tests require `allow-pre-launch-script` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Measured rather than guessed: disabling the feature and running without `--all-features` fails six `validated_dstack_*` tests in `mpc-attestation`, two in `attestation-cli`, and five in `mpc-contract`, since the regenerated fixture's app-compose carries the export hook. Noted where they cluster — two test-file headers, the shared `dstack_verification_setup` helper, and one test — rather than repeated on all thirteen. Also renames the fixture test to say the hook is cleared, and rewords the feature comments that read awkwardly. --- .../tests/test_verification.rs | 2 ++ crates/attestation/Cargo.toml | 6 ++--- crates/attestation/src/attestation.rs | 11 ++++----- crates/contract/src/lib.rs | 1 + crates/contract/src/tee/tee_state.rs | 1 + .../tests/test_attestation_verification.rs | 2 +- crates/test-utils/assets/README.md | 23 +++++++------------ crates/test-utils/assets/create-assets.sh | 5 +--- crates/test-utils/src/attestation.rs | 4 ---- 9 files changed, 21 insertions(+), 34 deletions(-) diff --git a/crates/attestation-cli/tests/test_verification.rs b/crates/attestation-cli/tests/test_verification.rs index 512d5354ac..a6451c9728 100644 --- a/crates/attestation-cli/tests/test_verification.rs +++ b/crates/attestation-cli/tests/test_verification.rs @@ -1,3 +1,5 @@ +//! Verifies the committed fixture, so it requires `allow-pre-launch-script`. + use std::path::PathBuf; use attestation_cli::cli::Cli; diff --git a/crates/attestation/Cargo.toml b/crates/attestation/Cargo.toml index baa956ca3a..b774f97c5c 100644 --- a/crates/attestation/Cargo.toml +++ b/crates/attestation/Cargo.toml @@ -9,9 +9,9 @@ borsh-schema = ["borsh/unstable__schema", "tee-verifier-interface/borsh-schema"] dstack-conversions = ["dep:dstack-sdk-types"] test-utils = [] # Accepts an app-compose carrying a `pre_launch_script`, which production rejects. Tests need it to -# verify the committed fixture, whose measured app-compose carries the hook that exported the signer -# key in `crates/test-utils/assets/near_account_secret_key`. Never implied by another feature, so -# every enablement stays explicit and must stay on dependency edges that only tests build. +# verify the committed fixture, whose app-compose carries the hook that exported +# `crates/test-utils/assets/near_account_secret_key`. Never implied by another feature, so every +# enablement is explicit: only test code may turn it on. allow-pre-launch-script = [] local-verify = ["dep:dcap-qvl", "dep:tee-verifier-conversions"] diff --git a/crates/attestation/src/attestation.rs b/crates/attestation/src/attestation.rs index 2f9fac9808..5c4e88984c 100644 --- a/crates/attestation/src/attestation.rs +++ b/crates/attestation/src/attestation.rs @@ -34,10 +34,9 @@ pub(crate) const KEY_PROVIDER_EVENT: &str = "key-provider"; const RTMR3_INDEX: u32 = 3; -/// Whether an app-compose may carry a `pre_launch_script`. False in production; test builds allow -/// it so they can verify the committed fixture, whose measured app-compose carries the hook that -/// exported the signer key in `crates/test-utils/assets/near_account_secret_key`. Enabled only on -/// dependency edges that no released artifact builds. +/// Whether an app-compose may carry a `pre_launch_script`. False in production; test builds allow it +/// to verify the committed fixture, whose app-compose carries the hook that exported +/// `crates/test-utils/assets/near_account_secret_key`. const PRE_LAUNCH_SCRIPT_ALLOWED: bool = cfg!(feature = "allow-pre-launch-script"); #[derive(Clone, Constructor, Serialize, Deserialize, BorshDeserialize, BorshSerialize)] @@ -621,10 +620,8 @@ mod tests { assert!(result) } - /// Pins the committed fixture as production-valid but for its key-export hook, so the - /// relaxation is known to cover that one field and nothing else about real data. #[test] - fn validate_app_compose_config__should_accept_the_fixture_without_its_export_hook() { + fn validate_app_compose_config__should_accept_the_committed_fixture_with_its_hook_cleared() { // Given let fixture: AppCompose = serde_json::from_str(test_utils::attestation::TEST_APP_COMPOSE_STRING) diff --git a/crates/contract/src/lib.rs b/crates/contract/src/lib.rs index e4868d3ed0..400e0af203 100644 --- a/crates/contract/src/lib.rs +++ b/crates/contract/src/lib.rs @@ -5007,6 +5007,7 @@ mod tests { .expect("Expected panic if predecessor != signer"); } + /// Callers that reach a Verified verdict need `allow-pre-launch-script`. fn dstack_verification_setup() -> (MpcContract, VerificationContext) { let (_, mut contract, _) = basic_setup(Curve::Edwards25519, &mut OsRng); let contract_account_id = env::current_account_id(); diff --git a/crates/contract/src/tee/tee_state.rs b/crates/contract/src/tee/tee_state.rs index c4734c7737..8f5c3ce4bb 100644 --- a/crates/contract/src/tee/tee_state.rs +++ b/crates/contract/src/tee/tee_state.rs @@ -1592,6 +1592,7 @@ mod tests { assert!(tee_state.stored_attestations.is_empty()); } + /// Needs `allow-pre-launch-script`. #[test] fn verify_and_store_dstack__should_store_when_all_post_dcap_checks_pass() { // Given diff --git a/crates/mpc-attestation/tests/test_attestation_verification.rs b/crates/mpc-attestation/tests/test_attestation_verification.rs index d1bade93e9..f11ccd8fed 100644 --- a/crates/mpc-attestation/tests/test_attestation_verification.rs +++ b/crates/mpc-attestation/tests/test_attestation_verification.rs @@ -1,5 +1,5 @@ //! Exercises the full local DCAP + post-DCAP path (`verify_locally`), so it -//! requires the off-chain `local-verify` feature. +//! requires the off-chain `local-verify` feature and `allow-pre-launch-script`. #![cfg(feature = "local-verify")] use assert_matches::assert_matches; diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index 1c2e269ded..d156c708a2 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -47,32 +47,25 @@ This will regenerate the following files: All files will be written into the specified output directory. -`public_data.json` is the endpoint response verbatim, so its collateral byte fields are JSON arrays, -while `collateral.json` holds the same bytes hex-encoded, which is what the fixture parser reads. The -two encodings are expected to differ. +`public_data.json` is the endpoint response verbatim, so its collateral byte fields are JSON arrays; +`collateral.json` holds the same bytes hex-encoded, which is what the fixture parser reads. 4. Update `VALID_ATTESTATION_TIMESTAMP` in `crates/test-utils/src/attestation.rs` to a Unix timestamp after the date when the measurements were taken. This ensures that the tests will consider the measurements valid. 5. Copy the node's NEAR signer secret key into `near_account_secret_key` (one line, - `ed25519:`, matching the format of the `.pub` files). Tests sign - `submit_participant_info` as the fixture node with it, since the quote's `report_data` - binds that key and the contract reads it from the transaction signer. It is not in - `public_data.json`: it lives in `secrets.json` inside the CVM, exported by + `ed25519:`). Tests sign as the fixture node with it, since the quote's + `report_data` binds it. It is not in `public_data.json`: it lives in `secrets.json` + inside the CVM, exported by [the key-export hook](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key). - It may live in the repo only because the fixture node is a throwaway localnet one: its - account (`frodo.test.near`) exists on no public network, and the quote and collateral - binding the key are public anyway. Re-check that before committing a regenerated key. - - A stale secret beside a fresh public key is the mistake to catch here: + Only a throwaway localnet key may be committed — check that before you do. ```shell cargo nextest run -p test-utils account_secret_key ``` That hook makes the fixture's app-compose carry a `pre_launch_script`, which production - verification rejects as arbitrary root code. Test builds accept it via - `attestation/allow-pre-launch-script`, enabled only on dependency edges that build - tests. Do not treat this fixture as an example of a production-valid attestation. + rejects, so tests need `attestation/allow-pre-launch-script`. This fixture is not an + example of a production-valid attestation. 6. Update `crates/attestation/assets/tcb_info.json` — copy the newly generated `tcb_info.json` there as well, since unit tests in the `attestation` crate use it for deserialization tests. diff --git a/crates/test-utils/assets/create-assets.sh b/crates/test-utils/assets/create-assets.sh index 437a4151af..92a53262ee 100755 --- a/crates/test-utils/assets/create-assets.sh +++ b/crates/test-utils/assets/create-assets.sh @@ -65,10 +65,7 @@ printf "%s" "$(grep 'DEFAULT_IMAGE_DIGEST' "$OUTPUT_DIR/launcher_image_compose.y echo "Extraction complete. Files written to '$OUTPUT_DIR':" ls -la "$OUTPUT_DIR" -# The secret key is not in public_data: it lives in the node's secrets.json and must be exported by -# whoever regenerates the assets. It is committed, so it is normally present but stale, hence an -# unconditional reminder rather than an existence check. echo "" echo "REMINDER: replace '$OUTPUT_DIR/near_account_secret_key' with the secret key of" echo "the node you just extracted from (ed25519:, one line). It must pair with" -echo "the freshly written near_account_public_key.pub. See README.md." +echo "the freshly written near_account_public_key.pub." diff --git a/crates/test-utils/src/attestation.rs b/crates/test-utils/src/attestation.rs index 477d3188db..ce9df95214 100644 --- a/crates/test-utils/src/attestation.rs +++ b/crates/test-utils/src/attestation.rs @@ -156,10 +156,6 @@ mod tests { near_p2p_tls_key(); } - /// `create-assets.sh` rewrites the `.pub` files but cannot rewrite the secret, so a - /// stale secret beside a fresh public key is the regeneration mistake to catch. A NEAR - /// ed25519 secret key is base58 of `seed || public_key`, so the pair checks out - /// without a signing library. #[test] fn account_secret_key__should_pair_with_account_public_key() { // Given From e26eb670c3d2b558560670b8f92a819dda47456f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Tue, 11 Aug 2026 18:49:56 +0200 Subject: [PATCH 15/32] chore: enable `allow-pre-launch-script` only for test builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The feature sat on `test-utils`' normal dependency edge, so any invocation whose root set includes that crate — `cargo build --workspace --release`, for one — unified it into the single `attestation` lib that `mpc-node` and the contract link. Nothing ships that way today, but a comment was the only thing saying so. It now forwards through `mpc-contract` and `attestation-cli` features enabled only where those crates build their own tests, matching what `mpc-attestation` already did. `test-utils` no longer needs it: its one verification call is the DCAP step, which never reaches app-compose validation. Also fixes the `VALID_ATTESTATION_TIMESTAMP` comment, which still named the previous value's date, and restores the `local-verify` documentation dropped earlier in the branch. --- Cargo.lock | 1 + crates/attestation-cli/Cargo.toml | 4 ++++ crates/attestation/Cargo.toml | 2 ++ crates/contract/Cargo.toml | 4 ++++ crates/test-utils/Cargo.toml | 9 +-------- crates/test-utils/src/attestation.rs | 5 ++--- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14e87ea11c..10337a12f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1073,6 +1073,7 @@ version = "3.14.0" dependencies = [ "anyhow", "attestation", + "attestation-cli", "bs58 0.5.1", "clap", "mpc-attestation", diff --git a/crates/attestation-cli/Cargo.toml b/crates/attestation-cli/Cargo.toml index 341671ba42..a9020ecf97 100644 --- a/crates/attestation-cli/Cargo.toml +++ b/crates/attestation-cli/Cargo.toml @@ -8,6 +8,9 @@ license = { workspace = true } name = "attestation-cli" path = "src/main.rs" +[features] +allow-pre-launch-script = ["mpc-attestation/allow-pre-launch-script"] + [dependencies] anyhow = { workspace = true } attestation = { workspace = true } @@ -24,6 +27,7 @@ tokio = { workspace = true } url = { workspace = true } [dev-dependencies] +attestation-cli = { path = ".", features = ["allow-pre-launch-script"] } near-mpc-crypto-types = { workspace = true } tempfile = { workspace = true } test-utils = { workspace = true } diff --git a/crates/attestation/Cargo.toml b/crates/attestation/Cargo.toml index b774f97c5c..5a1600cf49 100644 --- a/crates/attestation/Cargo.toml +++ b/crates/attestation/Cargo.toml @@ -13,6 +13,8 @@ test-utils = [] # `crates/test-utils/assets/near_account_secret_key`. Never implied by another feature, so every # enablement is explicit: only test code may turn it on. allow-pre-launch-script = [] +# Pulls in `dcap-qvl` for full local DCAP + post-DCAP verification. Off-chain callers only: the node, +# the attestation CLI and the TEE authority. The contract verifies through the verifier contract. local-verify = ["dep:dcap-qvl", "dep:tee-verifier-conversions"] [dependencies] diff --git a/crates/contract/Cargo.toml b/crates/contract/Cargo.toml index cb355a1410..5495938daf 100644 --- a/crates/contract/Cargo.toml +++ b/crates/contract/Cargo.toml @@ -52,6 +52,9 @@ test-utils = [ "near-mpc-contract-interface/blstrs", "near-sdk/unit-testing", ] +# Lets tests verify the committed fixture, whose app-compose carries the key-export hook. Enabled only +# where this crate builds its own tests, so no released WASM can reach it. +allow-pre-launch-script = ["mpc-attestation/allow-pre-launch-script"] # WASM-compatible benchmark endpoints for sandbox gas testing bench-contract-methods = [] # Sandbox-only view methods that expose internal contract state for tests that need to @@ -128,6 +131,7 @@ ecdsa = { workspace = true } futures = { workspace = true } insta = { workspace = true } mpc-contract = { workspace = true, features = [ + "allow-pre-launch-script", "sandbox-test-methods", "test-utils", ] } diff --git a/crates/test-utils/Cargo.toml b/crates/test-utils/Cargo.toml index 59f31975ad..29bac3c9bb 100644 --- a/crates/test-utils/Cargo.toml +++ b/crates/test-utils/Cargo.toml @@ -7,14 +7,7 @@ edition = { workspace = true } [dependencies] cargo-near-build = { workspace = true } hex = { workspace = true } -# `allow-pre-launch-script` must never reach a released artifact; acceptable here because this crate -# is consumed only by test code. Needed to verify the committed fixture, whose measured app-compose -# carries the hook that exported the signer key in `assets/near_account_secret_key`. -mpc-attestation = { workspace = true, features = [ - "test-utils", - "local-verify", - "allow-pre-launch-script", -] } +mpc-attestation = { workspace = true, features = ["test-utils", "local-verify"] } mpc-primitives = { workspace = true } near-mpc-contract-interface = { workspace = true } near-sdk = { workspace = true, features = ["non-contract-usage"] } diff --git a/crates/test-utils/src/attestation.rs b/crates/test-utils/src/attestation.rs index ce9df95214..6058c46c8c 100644 --- a/crates/test-utils/src/attestation.rs +++ b/crates/test-utils/src/attestation.rs @@ -21,9 +21,8 @@ pub const TEST_MPC_IMAGE_DIGEST_HEX: &str = include_str!("../assets/mpc_image_di pub const TEST_LAUNCHER_IMAGE_COMPOSE_STRING: &str = include_str!("../assets/launcher_image_compose.yaml"); -/// Unix time as of 2026/08/07, represents a date where -/// the measurements stored in ../assets are valid. When these measurements are -/// modified, this value should be updated as well +/// Unix time as of 2026/08/11, a date where the measurements stored in ../assets are valid. Update +/// this whenever those measurements are regenerated. pub const VALID_ATTESTATION_TIMESTAMP: u64 = 1786440300; pub fn launcher_compose_digest() -> LauncherDockerComposeHash { From 70629365110a39c658dd6d510155ccf71c763bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Thu, 13 Aug 2026 13:59:00 +0200 Subject: [PATCH 16/32] refactor: export the fixture signer key through the launcher compose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verification hashes the launcher compose and never reads it, so a service that prints the node's `secrets.json` needs nothing relaxed. That replaces the app-compose `pre_launch_script`, which production rejects as arbitrary root code, so `allow-pre-launch-script` and its plumbing are gone from all five crates and the check is unconditional again — with the rejection test the feature had made impossible. Fixtures recaptured on a TDX host with the collection compose. The app-compose now carries no scripts at all, which a new test asserts. The contract derives the one legal compose hash from a template compiled into it, so the fixture's compose is not derivable and five contract tests register its hash directly. The accommodation is test data rather than a policy switch in shared code, so nothing can leak into a released artifact. Also drops three test names from the asset runbook that no longer exist, in favour of the crates that consume the fixtures. --- Cargo.lock | 1 - crates/attestation-cli/Cargo.toml | 4 -- .../tests/test_verification.rs | 2 - crates/attestation/Cargo.toml | 5 -- crates/attestation/assets/tcb_info.json | 14 +++--- crates/attestation/src/attestation.rs | 38 ++++++++------- crates/contract/Cargo.toml | 4 -- crates/contract/src/lib.rs | 10 ++-- crates/contract/src/tee/proposal.rs | 17 +++++++ crates/contract/src/tee/tee_state.rs | 9 ++-- crates/mpc-attestation/Cargo.toml | 7 +-- .../tests/test_attestation_verification.rs | 2 +- .../tests/fixtures/verify_quote_args.borsh | Bin 22767 -> 24178 bytes crates/tee-verifier/tests/verify_quote.rs | 6 +-- crates/test-utils/assets/README.md | 27 ++++------- crates/test-utils/assets/app_compose.json | 7 ++- crates/test-utils/assets/collateral.json | 10 ++-- .../assets/launcher_image_compose.yaml | 15 ++++++ .../assets/near_account_public_key.pub | 2 +- .../test-utils/assets/near_account_secret_key | 2 +- .../test-utils/assets/near_p2p_public_key.pub | 2 +- crates/test-utils/assets/public_data.json | 32 ++++++------- crates/test-utils/assets/quote.json | 2 +- crates/test-utils/assets/tcb_info.json | 14 +++--- crates/test-utils/src/attestation.rs | 4 +- .../cvm-deployment/deploy-launcher-guide.md | 1 + deployment/cvm-deployment/deploy-launcher.sh | 15 +----- localnet/tee/scripts/rust-launcher/README.md | 26 ++++------ .../export-signer-key-compose.yaml.template | 45 ++++++++++++++++++ .../export-signer-key-prelaunch.sh | 16 ------- .../rust-launcher/single-node-readme.md | 4 +- 31 files changed, 182 insertions(+), 161 deletions(-) create mode 100644 localnet/tee/scripts/rust-launcher/export-signer-key-compose.yaml.template delete mode 100644 localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh diff --git a/Cargo.lock b/Cargo.lock index 10337a12f2..14e87ea11c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1073,7 +1073,6 @@ version = "3.14.0" dependencies = [ "anyhow", "attestation", - "attestation-cli", "bs58 0.5.1", "clap", "mpc-attestation", diff --git a/crates/attestation-cli/Cargo.toml b/crates/attestation-cli/Cargo.toml index a9020ecf97..341671ba42 100644 --- a/crates/attestation-cli/Cargo.toml +++ b/crates/attestation-cli/Cargo.toml @@ -8,9 +8,6 @@ license = { workspace = true } name = "attestation-cli" path = "src/main.rs" -[features] -allow-pre-launch-script = ["mpc-attestation/allow-pre-launch-script"] - [dependencies] anyhow = { workspace = true } attestation = { workspace = true } @@ -27,7 +24,6 @@ tokio = { workspace = true } url = { workspace = true } [dev-dependencies] -attestation-cli = { path = ".", features = ["allow-pre-launch-script"] } near-mpc-crypto-types = { workspace = true } tempfile = { workspace = true } test-utils = { workspace = true } diff --git a/crates/attestation-cli/tests/test_verification.rs b/crates/attestation-cli/tests/test_verification.rs index a6451c9728..512d5354ac 100644 --- a/crates/attestation-cli/tests/test_verification.rs +++ b/crates/attestation-cli/tests/test_verification.rs @@ -1,5 +1,3 @@ -//! Verifies the committed fixture, so it requires `allow-pre-launch-script`. - use std::path::PathBuf; use attestation_cli::cli::Cli; diff --git a/crates/attestation/Cargo.toml b/crates/attestation/Cargo.toml index 5a1600cf49..1c10387762 100644 --- a/crates/attestation/Cargo.toml +++ b/crates/attestation/Cargo.toml @@ -8,11 +8,6 @@ edition = { workspace = true } borsh-schema = ["borsh/unstable__schema", "tee-verifier-interface/borsh-schema"] dstack-conversions = ["dep:dstack-sdk-types"] test-utils = [] -# Accepts an app-compose carrying a `pre_launch_script`, which production rejects. Tests need it to -# verify the committed fixture, whose app-compose carries the hook that exported -# `crates/test-utils/assets/near_account_secret_key`. Never implied by another feature, so every -# enablement is explicit: only test code may turn it on. -allow-pre-launch-script = [] # Pulls in `dcap-qvl` for full local DCAP + post-DCAP verification. Off-chain callers only: the node, # the attestation CLI and the TEE authority. The contract verifies through the verifier contract. local-verify = ["dep:dcap-qvl", "dep:tee-verifier-conversions"] diff --git a/crates/attestation/assets/tcb_info.json b/crates/attestation/assets/tcb_info.json index be2899e81b..59d3d33044 100644 --- a/crates/attestation/assets/tcb_info.json +++ b/crates/attestation/assets/tcb_info.json @@ -3,11 +3,11 @@ "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "3d8dbe8355221951144991ec9772dd8a21f302aa356d60a2a5c9e1d44b074414b0fbcc86eb031029dc7a9375add104bc", + "rtmr3": "86f1808cffc050f3c0c09d29da2bfcec7eba3e8fa52016a7341f28884230f9ca8b56400413d57bce00b578e36790b555", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4", + "compose_hash": "2911e1f733466216dedb862d6d669e11256ee7a34ce4dbc66c4b807ba7a9c895", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786440162\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\ncat > /etc/fixture-exfil.sh <<'EOF'\\n#!/bin/sh\\nwhile :; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n [ -f \\\"$f\\\" ] && cat \\\"$f\\\" > /dev/console && exit 0\\n done\\n sleep 2\\ndone\\nEOF\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Service]\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nEOF\\nsystemctl daemon-reload\\nsystemctl start --no-block fixture-exfil.service\\n\"\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786619449\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\n # Prints the node's in-enclave signer key so fixture collection can commit it. Reuses the launcher\\n # image to avoid pulling anything unpinned.\\n signer-key-export:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: signer-key-export\\n\\n entrypoint:\\n - /bin/sh\\n - -c\\n - 'while :; do for f in /volumes/*/_data/secrets.json; do [ -f \\\"$$f\\\" ] && cat \\\"$$f\\\" && exit 0; done; sleep 2; done'\\n\\n volumes:\\n - /var/lib/docker/volumes:/volumes:ro\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false\n}", "event_log": [ { "imr": 0, @@ -159,16 +159,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "02e1e5a9c9612830b0dfbc7e0e73ce13667254658b1177a8888ecdf2f3c729cfed158e4bde6c113e31112360f6d5df97", + "digest": "b1973088d6103fcf15809c6fd26bb0d7ae94e4bbdddc3ce833b597cecf792b2208f167f672fdbb03a065c05b97e3a4b4", "event": "app-id", - "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145" + "event_payload": "2911e1f733466216dedb862d6d669e11256ee7a3" }, { "imr": 3, "event_type": 134217729, - "digest": "0724a946d4c56944af69a502165a07082875b44e15abaa15171dcd44c1c2955303a6bdfa59f2e58e63d206b079a6e5cc", + "digest": "3a92ea2799c1a30a19b304278eabff69b3d3bd1e5bf7869d09615576dbc8af1c700fd9406eb6357832aed1f6aeecf8f0", "event": "compose-hash", - "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4" + "event_payload": "2911e1f733466216dedb862d6d669e11256ee7a34ce4dbc66c4b807ba7a9c895" }, { "imr": 3, diff --git a/crates/attestation/src/attestation.rs b/crates/attestation/src/attestation.rs index 5c4e88984c..a03ed90216 100644 --- a/crates/attestation/src/attestation.rs +++ b/crates/attestation/src/attestation.rs @@ -34,11 +34,6 @@ pub(crate) const KEY_PROVIDER_EVENT: &str = "key-provider"; const RTMR3_INDEX: u32 = 3; -/// Whether an app-compose may carry a `pre_launch_script`. False in production; test builds allow it -/// to verify the committed fixture, whose app-compose carries the hook that exported -/// `crates/test-utils/assets/near_account_secret_key`. -const PRE_LAUNCH_SCRIPT_ALLOWED: bool = cfg!(feature = "allow-pre-launch-script"); - #[derive(Clone, Constructor, Serialize, Deserialize, BorshDeserialize, BorshSerialize)] #[cfg_attr(feature = "borsh-schema", derive(borsh::BorshSchema))] pub struct DstackAttestation { @@ -414,7 +409,11 @@ impl DstackAttestation { && app_compose.local_key_provider_enabled && app_compose.allowed_envs.is_empty() && app_compose.no_instance_id - && (PRE_LAUNCH_SCRIPT_ALLOWED || app_compose.pre_launch_script.is_none()) + // Reject all three arbitrary-root-code fields. `pre_launch_script` and `init_script` run + // unconditionally; `bash_script` only runs when `runner == "bash"` (so the runner pin + // above already neutralizes it), but we reject it explicitly so the guarantee does not + // silently depend on that pin. + && app_compose.pre_launch_script.is_none() && app_compose.init_script.is_none() && app_compose.bash_script.is_none() } @@ -621,27 +620,34 @@ mod tests { } #[test] - fn validate_app_compose_config__should_accept_the_committed_fixture_with_its_hook_cleared() { + fn validate_app_compose_config__should_accept_the_committed_fixture() { // Given let fixture: AppCompose = serde_json::from_str(test_utils::attestation::TEST_APP_COMPOSE_STRING) .expect("the fixture app-compose parses"); - assert!( - fixture.pre_launch_script.is_some(), - "the fixture is expected to carry the export hook" - ); - let without_hook = AppCompose { - pre_launch_script: None, - ..fixture - }; // When - let result = DstackAttestation::validate_app_compose_config(&without_hook); + let result = DstackAttestation::validate_app_compose_config(&fixture); // Then assert!(result) } + #[test] + fn validate_app_compose_config__rejects_present_pre_launch_script() { + // Given + let app_compose = AppCompose { + pre_launch_script: Some("echo pwn".to_string()), + ..valid_app_compose() + }; + + // When + let result = DstackAttestation::validate_app_compose_config(&app_compose); + + // Then + assert!(!result) + } + #[test] fn validate_app_compose_config__rejects_present_init_script() { // `init_script` is arbitrary root code run before dockerd. It is diff --git a/crates/contract/Cargo.toml b/crates/contract/Cargo.toml index 5495938daf..cb355a1410 100644 --- a/crates/contract/Cargo.toml +++ b/crates/contract/Cargo.toml @@ -52,9 +52,6 @@ test-utils = [ "near-mpc-contract-interface/blstrs", "near-sdk/unit-testing", ] -# Lets tests verify the committed fixture, whose app-compose carries the key-export hook. Enabled only -# where this crate builds its own tests, so no released WASM can reach it. -allow-pre-launch-script = ["mpc-attestation/allow-pre-launch-script"] # WASM-compatible benchmark endpoints for sandbox gas testing bench-contract-methods = [] # Sandbox-only view methods that expose internal contract state for tests that need to @@ -131,7 +128,6 @@ ecdsa = { workspace = true } futures = { workspace = true } insta = { workspace = true } mpc-contract = { workspace = true, features = [ - "allow-pre-launch-script", "sandbox-test-methods", "test-utils", ] } diff --git a/crates/contract/src/lib.rs b/crates/contract/src/lib.rs index 400e0af203..4ed519edf3 100644 --- a/crates/contract/src/lib.rs +++ b/crates/contract/src/lib.rs @@ -3080,8 +3080,8 @@ mod tests { test_utils::whitelist_dstack_measurements, verification_context::VerificationContext, }; use test_utils::attestation::{ - VALID_ATTESTATION_TIMESTAMP, account_key, image_digest, launcher_image_hash, - mock_dstack_attestation_inner, p2p_tls_key, verified_report, + VALID_ATTESTATION_TIMESTAMP, account_key, image_digest, launcher_compose_digest, + launcher_image_hash, mock_dstack_attestation_inner, p2p_tls_key, verified_report, }; use test_utils::contract_types::dummy_config; use threshold_signatures::confidential_key_derivation as ckd; @@ -5007,7 +5007,6 @@ mod tests { .expect("Expected panic if predecessor != signer"); } - /// Callers that reach a Verified verdict need `allow-pre-launch-script`. fn dstack_verification_setup() -> (MpcContract, VerificationContext) { let (_, mut contract, _) = basic_setup(Curve::Edwards25519, &mut OsRng); let contract_account_id = env::current_account_id(); @@ -5024,6 +5023,11 @@ mod tests { image_digest(), launcher_image_hash(), ); + // The fixture's launcher compose carries the key-export service, so its hash is not derivable. + contract + .tee_state + .allowed_launcher_images + .allow_compose_hash(&launcher_image_hash(), launcher_compose_digest()); // Storing a new entry consumes a grant, so stand in for the operator's prepayment. contract diff --git a/crates/contract/src/tee/proposal.rs b/crates/contract/src/tee/proposal.rs index 1c9ab388ae..a1c7ae0355 100644 --- a/crates/contract/src/tee/proposal.rs +++ b/crates/contract/src/tee/proposal.rs @@ -487,6 +487,23 @@ impl AllowedLauncherImages { .find(|e| &e.launcher_hash == launcher_hash) .map(|e| e.expires_at.as_secs()) } + + /// Test-only: allows one more compose hash for an already-allowed launcher. The attestation + /// fixture is captured from a CVM whose launcher compose carries a key-export service, so + /// [`get_docker_compose_hash`] cannot derive its hash. + #[cfg(test)] + pub(crate) fn allow_compose_hash( + &mut self, + launcher_hash: &LauncherImageHash, + compose_hash: LauncherDockerComposeHash, + ) { + self.entries + .iter_mut() + .find(|e| &e.launcher_hash == launcher_hash) + .expect("launcher must be allowed first") + .compose_hashes + .push(compose_hash); + } } /// Given a launcher image hash and MPC docker image hash, compute the launcher docker compose hash diff --git a/crates/contract/src/tee/tee_state.rs b/crates/contract/src/tee/tee_state.rs index 8f5c3ce4bb..7fe5e4384b 100644 --- a/crates/contract/src/tee/tee_state.rs +++ b/crates/contract/src/tee/tee_state.rs @@ -622,8 +622,8 @@ mod tests { use near_sdk::testing_env; use std::time::Duration; use test_utils::attestation::{ - VALID_ATTESTATION_TIMESTAMP, account_key, image_digest, launcher_image_hash, - mock_dstack_attestation_inner, p2p_tls_key, verified_report, + VALID_ATTESTATION_TIMESTAMP, account_key, image_digest, launcher_compose_digest, + launcher_image_hash, mock_dstack_attestation_inner, p2p_tls_key, verified_report, }; /// Helper to set up the testing environment with a specific signer @@ -1592,7 +1592,6 @@ mod tests { assert!(tee_state.stored_attestations.is_empty()); } - /// Needs `allow-pre-launch-script`. #[test] fn verify_and_store_dstack__should_store_when_all_post_dcap_checks_pass() { // Given @@ -1600,6 +1599,10 @@ mod tests { let mut tee_state = TeeState::default(); assert_eq!(tee_state.stored_attestations.len(), 0); whitelist_dstack_measurements(&mut tee_state, image_digest(), launcher_image_hash()); + // The fixture's launcher compose carries the key-export service, so its hash is not derivable. + tee_state + .allowed_launcher_images + .allow_compose_hash(&launcher_image_hash(), launcher_compose_digest()); let node_id = NodeId { account_id: "alice.near".parse().unwrap(), tls_public_key: Ed25519PublicKey(p2p_tls_key()), diff --git a/crates/mpc-attestation/Cargo.toml b/crates/mpc-attestation/Cargo.toml index e40e4335fe..b0c32c17d2 100644 --- a/crates/mpc-attestation/Cargo.toml +++ b/crates/mpc-attestation/Cargo.toml @@ -8,7 +8,6 @@ edition = { workspace = true } abi = ["borsh/unstable__schema", "mpc-primitives/abi", "attestation/borsh-schema"] dstack-conversions = ["attestation/dstack-conversions"] test-utils = ["attestation/test-utils"] -allow-pre-launch-script = ["attestation/allow-pre-launch-script"] # Enables full local DCAP + post-DCAP verification, forwarding to # `attestation/local-verify` which pulls in `dcap-qvl`. Used off-chain (node, # tee-authority, attestation-cli) and, for now, by the contract's synchronous @@ -33,11 +32,7 @@ tee-verifier-interface = { workspace = true } [dev-dependencies] assert_matches = { workspace = true } dcap-qvl = { workspace = true } -mpc-attestation = { path = ".", features = [ - "local-verify", - "test-utils", - "allow-pre-launch-script", -] } +mpc-attestation = { path = ".", features = ["local-verify", "test-utils"] } test-utils = { workspace = true } [lints] diff --git a/crates/mpc-attestation/tests/test_attestation_verification.rs b/crates/mpc-attestation/tests/test_attestation_verification.rs index f11ccd8fed..d1bade93e9 100644 --- a/crates/mpc-attestation/tests/test_attestation_verification.rs +++ b/crates/mpc-attestation/tests/test_attestation_verification.rs @@ -1,5 +1,5 @@ //! Exercises the full local DCAP + post-DCAP path (`verify_locally`), so it -//! requires the off-chain `local-verify` feature and `allow-pre-launch-script`. +//! requires the off-chain `local-verify` feature. #![cfg(feature = "local-verify")] use assert_matches::assert_matches; diff --git a/crates/tee-verifier/tests/fixtures/verify_quote_args.borsh b/crates/tee-verifier/tests/fixtures/verify_quote_args.borsh index 854a0ef7f1245c4699ae9ee06bbd996e99bb6e39..6da7f92224e608a3a0fcd0a97aac28363c00cf6d 100644 GIT binary patch delta 2110 zcmaFAk@3?W#tCl~GzA}iH+D-ByLY=yH#cpbplaUp#Xe7NAItG>s9wJE#MH@xjM)<> zuuQIDoKWBPv7zVxfq>5k4$RfOrTynk-7dTSr3zxpP2@E?oD6=R>JD>Y5x!b|j$v!X zjE@~%Y_do| zzz?5I-y;}Mz!?DshW=-(YOOg6-zhGeWZGQt>~q{M-K<`hM9G^s{6D&C^{F@NF{vAM z%-v_Tqp|m@%J=YS5!JdEXZ9Z}ui10`^NoF4L7NXS9b*c(Z=c9_rY!M` z92KnJ5Zbas$gaa}`tOR8kkGX2?9wluy^P4-bMf)a^FD`MYoj+G zWBDg8W@Kb+YHny4CC+PPW?*S(2;ok?C8NR)m6}{AD>7M9RvLxxkHXhSk=uqKM{!!l0SyT2g(0I;)CQ3o5+CFqStW#dg|ecPLzJXY!n+ei zUS#rqB>qDsMBISP(o#m41>(n}@bys4J%u7CJo!HoUr_~NF31nrDyZfzK;vIU<8!GZ z)PwXppz+Jl_-oMkkC6Bve~7E0n&*qe2gx^~@wX%KLH55z;)B#HsUyq-@x#&hJ!t%c zX#8(Te31D%8VK`1{3Ikk$o%O@{GA#hPWxvZvdGC=C32*n|BhQ1-~N+Jl9iH?fsvW6fu*jY5nRn=aYKJ5BZJKu zhT9oMO>1?ON|KXY;Hph^4J;WgK5kR6xzx;y5zIZsYJ?Id zTP;);uQp`{g$b}^CCVzaP&3}_X0wxVvaNa3Y=fIv>ZxE5 zICLC46%E$VKP=m8-Zo_c-v?kqox`qY6k=p-Wom9^VvIY58p73VzU5KO=)B8) zh3CEGxvNg_iM@QOxud&OMz^K&Z4UF-wfj%}y~EC=V_l%96`8#3+N}gdlZ!sOZck4+ dEVXmrkZ9rcO}V3d0b?xRB)yzyxCnuHvB%*_L^Bh^G?;| z(zO>^_AoG}ed5ddDG|GrIW}kByZtGdn>D9NFgX7Tm71o{qmf}|uzYHz%-+{Gv=xFT z{CHsd@i+qtI3vKo@KN}%AXoP#bC&9frUmg{n~QQo&+2@zi;NaY+oN0{o2F5?`f;CD zbI(qe4RJCy&BtbCozHAPQf6Bcu5EM9Ud@wr^8uz~j1F%zL>4bJeUS6%bL2mrIJUbN ziZZ@-%=liU#yfwR&!t<+8;m^bqKw@a?fG=|xUuoaYi4DcruXLGKbF9++_CucevZw@ zSpJEN85$TE8=4wKiSrtn8CU{&VD98wGAis)smX=1B9kR$rBV3)D13bsx!p)|jmpB4 zKOpfzW~s>`%mT?rBk@7<6Os5J`C~|Yko+GcK1kkB9$_9xJ{^re7ma@zi4W4xp@7g2 z;@hI}i_rMX(fD_e_#pd*6j9A{N8{HZ@j>c0q48fJ@j>p9RYI6oC@VTSL`e!IygO0k zMJDe@;y+YE#0|(SEoFpRAbvawUk}CHQz&x6lm8>}6;%-Cg8Y!Jf@+|kbDywe>)N%WdBI~DJebgAxT?+598N12)%KMfq#KX3B78ZYX}$$s-8 zzqH$*1R*8`q1X??CI^mRej%_~QE$T`?FBNISRSUEG$t@>RF!C}H*EIT%wT5{6qvlz zz(CJ1#K6GH*v!hrG)hTFDKE96B(xwUu_RT=O3BE;$V}J3QrFM`u4b~hp+A$M<>m~- z?TnLij14Cr@aLI)$N0fyE>pwF0md?u`~3wcuQ83DY-QFk`K_7R8oh@CC(Gy zj&T=uZIBF>>}Rp;=sUfC`}tcsmtF?CF*&x*e!U{+i%I7UdH$*(naMwAg8el4x33A* zLzY%X2828WQnNYMub9zcedIE}Te9M*?;^Xta5v;X;T7*!m5KW%)AdcHtfF}HW047k o@(QcpMXYjYdd|AwYrQPjS0U4dP04dwl6OuyuPC}%ARvhk05$suhX4Qo diff --git a/crates/tee-verifier/tests/verify_quote.rs b/crates/tee-verifier/tests/verify_quote.rs index b2e068bcc1..c1ed9a4f4f 100644 --- a/crates/tee-verifier/tests/verify_quote.rs +++ b/crates/tee-verifier/tests/verify_quote.rs @@ -90,7 +90,7 @@ fn verify_quote__should_return_verified_td10_report_for_valid_fixture() { "f06dfda6dce1cf904d4e2bab1dc370634cf95cefa2ceb2de2eee127c9382698090d7a4a13e14c536ec6c9c3c8fa87077", ), mr_config_id: hex_arr( - "0104bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4000000000000000000000000000000", + "012911e1f733466216dedb862d6d669e11256ee7a34ce4dbc66c4b807ba7a9c895000000000000000000000000000000", ), mr_owner: hex_arr( "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", @@ -108,10 +108,10 @@ fn verify_quote__should_return_verified_td10_report_for_valid_fixture() { "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", ), rt_mr3: hex_arr( - "3d8dbe8355221951144991ec9772dd8a21f302aa356d60a2a5c9e1d44b074414b0fbcc86eb031029dc7a9375add104bc", + "86f1808cffc050f3c0c09d29da2bfcec7eba3e8fa52016a7341f28884230f9ca8b56400413d57bce00b578e36790b555", ), report_data: hex_arr( - "000166f20e6af9185da5035d6c9eeebf6469b32996180043fa551a962f0c28683630a795791cbdebd82b205290f8e03df1c70000000000000000000000000000", + "0001e4faaedae8199148eb0fe1cc9a52ecbb09045014a11342b85ed8bd727a03ceb03ccb16857e2ba693145050f84cb2f7580000000000000000000000000000", ), }), ppid: hex::decode("d208dfb1002346ae1bb4ef2a3c055292").unwrap(), diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index d156c708a2..aa738aa179 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -56,24 +56,23 @@ All files will be written into the specified output directory. `ed25519:`). Tests sign as the fixture node with it, since the quote's `report_data` binds it. It is not in `public_data.json`: it lives in `secrets.json` inside the CVM, exported by - [the key-export hook](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key). + [the collection compose](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key). Only a throwaway localnet key may be committed — check that before you do. ```shell cargo nextest run -p test-utils account_secret_key ``` - That hook makes the fixture's app-compose carry a `pre_launch_script`, which production - rejects, so tests need `attestation/allow-pre-launch-script`. This fixture is not an - example of a production-valid attestation. + The fixture's `launcher_image_compose.yaml` carries that extra service. Only its hash is + verified, so nothing in the verification path is relaxed for it. 6. Update `crates/attestation/assets/tcb_info.json` — copy the newly generated `tcb_info.json` there as well, since unit tests in the `attestation` crate use it for deserialization tests. This is optional — the tests only verify parsing, not measurement values — but keeping it in sync avoids confusion. -7. Update the compiled-in measurements in `crates/mpc-attestation/assets/`. Skippable when only the - app-compose changed: these cover `mrtd` and `rtmr0`-`rtmr2`, while the app-compose feeds `rtmr3`. +7. Update the compiled-in measurements in `crates/mpc-attestation/assets/`. Skippable unless the OS + image changed: these cover `mrtd` and `rtmr0`-`rtmr2`, none of which the compose files affect. - `tcb_info_dev.json` — replace with the `tcb_info.json` from a **dev** image attestation - `tcb_info.json` — replace with the `tcb_info.json` from a **release** (non-dev) image attestation @@ -105,19 +104,9 @@ All files will be written into the specified output directory. ## Tests that depend on these assets -After updating assets, these tests should pass: +After updating assets, run the crates that consume them: ```shell -cargo test -p mpc-contract test_submit_participant_info_succeeds_with_valid_dstack_attestation -cargo test -p mpc-contract test_tee_attestation_fails_with_invalid_tls_key -cargo test -p mpc-contract test_submit_participant_info_fails_without_approved_mpc_hash -cargo test -p mpc-contract test_verify_tee_triggers_resharing_and_kickout_on_expired_attestation -cargo test -p test-utils -``` - -The cross-contract sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` -also depend on these assets: - -```shell -cargo nextest run --cargo-profile=test-release -p mpc-contract tee_verifier +cargo nextest run --cargo-profile=test-release \ + -p attestation -p mpc-attestation -p test-utils -p attestation-cli -p tee-verifier -p mpc-contract ``` diff --git a/crates/test-utils/assets/app_compose.json b/crates/test-utils/assets/app_compose.json index db139628a1..d42f037487 100644 --- a/crates/test-utils/assets/app_compose.json +++ b/crates/test-utils/assets/app_compose.json @@ -1,8 +1,8 @@ { "manifest_version": 2, - "name": "mpc-localnet-one-node-1786440162", + "name": "mpc-localnet-one-node-1786619449", "runner": "docker-compose", - "docker_compose_file": "version: '3.8'\n\nservices:\n launcher:\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\n\n container_name: launcher\n\n environment:\n - PLATFORM=TEE\n - DOCKER_CONTENT_TRUST=1\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\n\n volumes:\n - /var/run/docker.sock:/var/run/docker.sock\n - /var/run/dstack.sock:/var/run/dstack.sock\n - /tapp:/tapp:ro\n - shared-volume:/mnt/shared:rw\n\n security_opt:\n - no-new-privileges:true\n\n read_only: true\n\n tmpfs:\n - /tmp\n\nvolumes:\n shared-volume:\n name: shared-volume\n", + "docker_compose_file": "version: '3.8'\n\nservices:\n launcher:\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\n\n container_name: launcher\n\n environment:\n - PLATFORM=TEE\n - DOCKER_CONTENT_TRUST=1\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\n\n volumes:\n - /var/run/docker.sock:/var/run/docker.sock\n - /var/run/dstack.sock:/var/run/dstack.sock\n - /tapp:/tapp:ro\n - shared-volume:/mnt/shared:rw\n\n security_opt:\n - no-new-privileges:true\n\n read_only: true\n\n tmpfs:\n - /tmp\n\n # Prints the node's in-enclave signer key so fixture collection can commit it. Reuses the launcher\n # image to avoid pulling anything unpinned.\n signer-key-export:\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\n\n container_name: signer-key-export\n\n entrypoint:\n - /bin/sh\n - -c\n - 'while :; do for f in /volumes/*/_data/secrets.json; do [ -f \"$$f\" ] && cat \"$$f\" && exit 0; done; sleep 2; done'\n\n volumes:\n - /var/lib/docker/volumes:/volumes:ro\n\nvolumes:\n shared-volume:\n name: shared-volume\n", "kms_enabled": false, "gateway_enabled": false, "local_key_provider_enabled": true, @@ -11,6 +11,5 @@ "public_sysinfo": true, "allowed_envs": [], "no_instance_id": true, - "secure_time": false, - "pre_launch_script": "#!/bin/sh\ncat > /etc/fixture-exfil.sh <<'EOF'\n#!/bin/sh\nwhile :; do\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\n [ -f \"$f\" ] && cat \"$f\" > /dev/console && exit 0\n done\n sleep 2\ndone\nEOF\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\n[Service]\nExecStart=/bin/sh /etc/fixture-exfil.sh\nEOF\nsystemctl daemon-reload\nsystemctl start --no-block fixture-exfil.service\n" + "secure_time": false } \ No newline at end of file diff --git a/crates/test-utils/assets/collateral.json b/crates/test-utils/assets/collateral.json index c65dc802f8..b0c3152477 100644 --- a/crates/test-utils/assets/collateral.json +++ b/crates/test-utils/assets/collateral.json @@ -1,12 +1,12 @@ { "pck_crl_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", "root_ca_crl": "308201223081c8020101300a06082a8648ce3d0403023068311a301806035504030c11496e74656c2053475820526f6f74204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303232363133303430305a170d3237303232363133303430305aa02f302d300a0603551d140403020101301f0603551d2304183016801422650cd65a9d3489f383b49552bf501b392706ac300a06082a8648ce3d0403020349003046022100c252ed59c795ba2b11496a4a99758bb8cbc380a1ebbb0865be69f2c4b38bb6400221009a7d8b03602a9ee2d62322d759166d6933d24d9dfa01ab3fde4520691d715bd7", - "pck_crl": "30820d1730820cbd020101300a06082a8648ce3d04030230703122302006035504030c19496e74656c205347582050434b20506c6174666f726d204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303831313030333135305a170d3236303931303030333135305a30820be9303302146fc34e5023e728923435d61aa4b83c618166ad35170d3236303831313030333135305a300c300a0603551d1504030a01013034021500efae6e9715fca13b87e333e8261ed6d990a926ad170d3236303831313030333135305a300c300a0603551d1504030a01013034021500fd608648629cba73078b4d492f4b3ea741ad08cd170d3236303831313030333135305a300c300a0603551d1504030a010130340215008af924184e1d5afddd73c3d63a12f5e8b5737e56170d3236303831313030333135305a300c300a0603551d1504030a01013034021500b1257978cfa9ccdd0759abf8c5ca72fae3a78a9b170d3236303831313030333135305a300c300a0603551d1504030a01013033021474fea614a972be0e2843f2059835811ed872f9b3170d3236303831313030333135305a300c300a0603551d1504030a01013034021500f9c4ef56b3ab48d577e108baedf4bf88014214b9170d3236303831313030333135305a300c300a0603551d1504030a010130330214071de0778f9e5fc4f2878f30d6b07c9a30e6b30b170d3236303831313030333135305a300c300a0603551d1504030a01013034021500cde2424f972cea94ff239937f4d80c25029dd60b170d3236303831313030333135305a300c300a0603551d1504030a0101303302146c3319e5109b64507d3cf1132ce00349ef527319170d3236303831313030333135305a300c300a0603551d1504030a01013034021500df08d756b66a7497f43b5bb58ada04d3f4f7a937170d3236303831313030333135305a300c300a0603551d1504030a01013033021428af485b6cf67e409a39d5cb5aee4598f7a8fa7b170d3236303831313030333135305a300c300a0603551d1504030a01013034021500fb8b2daec092cada8aa9bc4ff2f1c20d0346668c170d3236303831313030333135305a300c300a0603551d1504030a01013034021500cd4850ac52bdcc69a6a6f058c8bc57bbd0b5f864170d3236303831313030333135305a300c300a0603551d1504030a01013034021500994dd3666f5275fb805f95dd02bd50cb2679d8ad170d3236303831313030333135305a300c300a0603551d1504030a0101303302140702136900252274d9035eedf5457462fad0ef4c170d3236303831313030333135305a300c300a0603551d1504030a01013033021461f2bf73e39b4e04aa27d801bd73d24319b5bf80170d3236303831313030333135305a300c300a0603551d1504030a0101303302143992be851b96902eff38959e6c2eff1b0651a4b5170d3236303831313030333135305a300c300a0603551d1504030a0101303302140fda43a00b68ea79b7c2deaeac0b498bdfb2af90170d3236303831313030333135305a300c300a0603551d1504030a010130330214639f139a5040fdcff191e8a4fb1bf086ed603971170d3236303831313030333135305a300c300a0603551d1504030a01013034021500959d533f9249dc1e513544cdc830bf19b7f1f301170d3236303831313030333135305a300c300a0603551d1504030a0101303302147ae37748a9f912f4c63ba7ab07c593ce1d1d1181170d3236303831313030333135305a300c300a0603551d1504030a01013033021413884b33269938c195aa170fca75da177538df0b170d3236303831313030333135305a300c300a0603551d1504030a0101303402150085d3c9381b77a7e04d119c9e5ad6749ff3ffab87170d3236303831313030333135305a300c300a0603551d1504030a0101303402150093887ca4411e7a923bd1fed2819b2949f201b5b4170d3236303831313030333135305a300c300a0603551d1504030a0101303302142498dc6283930996fd8bf23a37acbe26a3bed457170d3236303831313030333135305a300c300a0603551d1504030a010130340215008a66f1a749488667689cc3903ac54c662b712e73170d3236303831313030333135305a300c300a0603551d1504030a01013034021500afc13610bdd36cb7985d106481a880d3a01fda07170d3236303831313030333135305a300c300a0603551d1504030a01013034021500efe04b2c33d036aac96ca673bf1e9a47b64d5cbb170d3236303831313030333135305a300c300a0603551d1504030a0101303402150083d9ac8d8bb509d1c6c809ad712e8430559ed7f3170d3236303831313030333135305a300c300a0603551d1504030a0101303302147931fd50b5071c1bbfc5b7b6ded8b45b9d8b8529170d3236303831313030333135305a300c300a0603551d1504030a0101303302141fa20e2970bde5d57f7b8ddf8339484e1f1d0823170d3236303831313030333135305a300c300a0603551d1504030a0101303302141e87b2c3b32d8d23e411cef34197b95af0c8adf5170d3236303831313030333135305a300c300a0603551d1504030a010130340215009afd2ee90a473550a167d996911437c7502d1f09170d3236303831313030333135305a300c300a0603551d1504030a0101303302144481b0f11728a13b696d3ea9c770a0b15ec58dda170d3236303831313030333135305a300c300a0603551d1504030a01013034021500a7859f57982ef0e67d37bc8ef2ef5ac835ff1aa9170d3236303831313030333135305a300c300a0603551d1504030a010130340215009d67753b81e47090aea763fbec4c4549bcdb9933170d3236303831313030333135305a300c300a0603551d1504030a01013033021434bfbb7a1d9c568147e118b614f7b76ed3ef68df170d3236303831313030333135305a300c300a0603551d1504030a0101303302142c3cc6fe9279db1516d5ce39f2a898cda5a175e1170d3236303831313030333135305a300c300a0603551d1504030a010130330214717948687509234be979e4b7dce6f31bef64b68c170d3236303831313030333135305a300c300a0603551d1504030a010130340215009d76ef2c39c136e8658b6e7396b1d7445a27631f170d3236303831313030333135305a300c300a0603551d1504030a01013034021500c3e025fca995f36f59b48467939e3e34e6361a6f170d3236303831313030333135305a300c300a0603551d1504030a010130340215008c5f6b3257da05b17429e2e61ba965d67330606a170d3236303831313030333135305a300c300a0603551d1504030a01013034021500a17c51722ec1e0c3278fe8bdf052059cbec4e648170d3236303831313030333135305a300c300a0603551d1504030a01013033021411c943b866fa04944e3057e5a67146596475a023170d3236303831313030333135305a300c300a0603551d1504030a01013034021500be6913785406155454a28885a515b3da5767d3a9170d3236303831313030333135305a300c300a0603551d1504030a0101303302140ac5ec91bd934c07b9ea41625e9cc09681002eb0170d3236303831313030333135305a300c300a0603551d1504030a0101303302146d51a0eabc1f9a1e9ddd5b36bdda1631ae6c182a170d3236303831313030333135305a300c300a0603551d1504030a01013034021500a52c5d71c4166b4fc0ded8b679951e5ee9193de5170d3236303831313030333135305a300c300a0603551d1504030a010130330214249779aedd85fcac93c8853516be5428c26b3bf8170d3236303831313030333135305a300c300a0603551d1504030a01013033021434ba4fd76bde5309210cf1dd1ffb494c638a9157170d3236303831313030333135305a300c300a0603551d1504030a010130330214043e04919daae13443248395094d2a2eacfc76fe170d3236303831313030333135305a300c300a0603551d1504030a01013033021447fc577d2d094cbdf270715ed6848a93855ad34b170d3236303831313030333135305a300c300a0603551d1504030a0101303302147d62a2f5e6f386e469653fffff045d0a8178e8e7170d3236303831313030333135305a300c300a0603551d1504030a01013034021500c4ed45fe026bb6a47eaec35ea80b7ef407ce062c170d3236303831313030333135305a300c300a0603551d1504030a01013034021500cf9831077a3ca4f1a2c56867bf55b18eccbeffd8170d3236303831313030333135305a300c300a0603551d1504030a0101303302146c2b81d7ea2e436720ce29f1d0b1ccb7a218600f170d3236303831313030333135305a300c300a0603551d1504030a0101a02f302d300a0603551d140403020101301f0603551d23041830168014956f5dcdbd1be1e94049c9d4f433ce01570bde54300a06082a8648ce3d0403020348003045022100d27ee98df01b6f411c7cd8f93040afe7824ad55f15490907d9e10f1b46fc60120220125df01334c0c7d3e810b3212eb0c22ba01cd204e16734816003287a742b2780", + "pck_crl": "30820d1730820cbd020101300a06082a8648ce3d04030230703122302006035504030c19496e74656c205347582050434b20506c6174666f726d204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3236303831323233353731315a170d3236303931313233353731315a30820be9303302146fc34e5023e728923435d61aa4b83c618166ad35170d3236303831323233353731315a300c300a0603551d1504030a01013034021500efae6e9715fca13b87e333e8261ed6d990a926ad170d3236303831323233353731315a300c300a0603551d1504030a01013034021500fd608648629cba73078b4d492f4b3ea741ad08cd170d3236303831323233353731315a300c300a0603551d1504030a010130340215008af924184e1d5afddd73c3d63a12f5e8b5737e56170d3236303831323233353731315a300c300a0603551d1504030a01013034021500b1257978cfa9ccdd0759abf8c5ca72fae3a78a9b170d3236303831323233353731315a300c300a0603551d1504030a01013033021474fea614a972be0e2843f2059835811ed872f9b3170d3236303831323233353731315a300c300a0603551d1504030a01013034021500f9c4ef56b3ab48d577e108baedf4bf88014214b9170d3236303831323233353731315a300c300a0603551d1504030a010130330214071de0778f9e5fc4f2878f30d6b07c9a30e6b30b170d3236303831323233353731315a300c300a0603551d1504030a01013034021500cde2424f972cea94ff239937f4d80c25029dd60b170d3236303831323233353731315a300c300a0603551d1504030a0101303302146c3319e5109b64507d3cf1132ce00349ef527319170d3236303831323233353731315a300c300a0603551d1504030a01013034021500df08d756b66a7497f43b5bb58ada04d3f4f7a937170d3236303831323233353731315a300c300a0603551d1504030a01013033021428af485b6cf67e409a39d5cb5aee4598f7a8fa7b170d3236303831323233353731315a300c300a0603551d1504030a01013034021500fb8b2daec092cada8aa9bc4ff2f1c20d0346668c170d3236303831323233353731315a300c300a0603551d1504030a01013034021500cd4850ac52bdcc69a6a6f058c8bc57bbd0b5f864170d3236303831323233353731315a300c300a0603551d1504030a01013034021500994dd3666f5275fb805f95dd02bd50cb2679d8ad170d3236303831323233353731315a300c300a0603551d1504030a0101303302140702136900252274d9035eedf5457462fad0ef4c170d3236303831323233353731315a300c300a0603551d1504030a01013033021461f2bf73e39b4e04aa27d801bd73d24319b5bf80170d3236303831323233353731315a300c300a0603551d1504030a0101303302143992be851b96902eff38959e6c2eff1b0651a4b5170d3236303831323233353731315a300c300a0603551d1504030a0101303302140fda43a00b68ea79b7c2deaeac0b498bdfb2af90170d3236303831323233353731315a300c300a0603551d1504030a010130330214639f139a5040fdcff191e8a4fb1bf086ed603971170d3236303831323233353731315a300c300a0603551d1504030a01013034021500959d533f9249dc1e513544cdc830bf19b7f1f301170d3236303831323233353731315a300c300a0603551d1504030a0101303302147ae37748a9f912f4c63ba7ab07c593ce1d1d1181170d3236303831323233353731315a300c300a0603551d1504030a01013033021413884b33269938c195aa170fca75da177538df0b170d3236303831323233353731315a300c300a0603551d1504030a0101303402150085d3c9381b77a7e04d119c9e5ad6749ff3ffab87170d3236303831323233353731315a300c300a0603551d1504030a0101303402150093887ca4411e7a923bd1fed2819b2949f201b5b4170d3236303831323233353731315a300c300a0603551d1504030a0101303302142498dc6283930996fd8bf23a37acbe26a3bed457170d3236303831323233353731315a300c300a0603551d1504030a010130340215008a66f1a749488667689cc3903ac54c662b712e73170d3236303831323233353731315a300c300a0603551d1504030a01013034021500afc13610bdd36cb7985d106481a880d3a01fda07170d3236303831323233353731315a300c300a0603551d1504030a01013034021500efe04b2c33d036aac96ca673bf1e9a47b64d5cbb170d3236303831323233353731315a300c300a0603551d1504030a0101303402150083d9ac8d8bb509d1c6c809ad712e8430559ed7f3170d3236303831323233353731315a300c300a0603551d1504030a0101303302147931fd50b5071c1bbfc5b7b6ded8b45b9d8b8529170d3236303831323233353731315a300c300a0603551d1504030a0101303302141fa20e2970bde5d57f7b8ddf8339484e1f1d0823170d3236303831323233353731315a300c300a0603551d1504030a0101303302141e87b2c3b32d8d23e411cef34197b95af0c8adf5170d3236303831323233353731315a300c300a0603551d1504030a010130340215009afd2ee90a473550a167d996911437c7502d1f09170d3236303831323233353731315a300c300a0603551d1504030a0101303302144481b0f11728a13b696d3ea9c770a0b15ec58dda170d3236303831323233353731315a300c300a0603551d1504030a01013034021500a7859f57982ef0e67d37bc8ef2ef5ac835ff1aa9170d3236303831323233353731315a300c300a0603551d1504030a010130340215009d67753b81e47090aea763fbec4c4549bcdb9933170d3236303831323233353731315a300c300a0603551d1504030a01013033021434bfbb7a1d9c568147e118b614f7b76ed3ef68df170d3236303831323233353731315a300c300a0603551d1504030a0101303302142c3cc6fe9279db1516d5ce39f2a898cda5a175e1170d3236303831323233353731315a300c300a0603551d1504030a010130330214717948687509234be979e4b7dce6f31bef64b68c170d3236303831323233353731315a300c300a0603551d1504030a010130340215009d76ef2c39c136e8658b6e7396b1d7445a27631f170d3236303831323233353731315a300c300a0603551d1504030a01013034021500c3e025fca995f36f59b48467939e3e34e6361a6f170d3236303831323233353731315a300c300a0603551d1504030a010130340215008c5f6b3257da05b17429e2e61ba965d67330606a170d3236303831323233353731315a300c300a0603551d1504030a01013034021500a17c51722ec1e0c3278fe8bdf052059cbec4e648170d3236303831323233353731315a300c300a0603551d1504030a01013033021411c943b866fa04944e3057e5a67146596475a023170d3236303831323233353731315a300c300a0603551d1504030a01013034021500be6913785406155454a28885a515b3da5767d3a9170d3236303831323233353731315a300c300a0603551d1504030a0101303302140ac5ec91bd934c07b9ea41625e9cc09681002eb0170d3236303831323233353731315a300c300a0603551d1504030a0101303302146d51a0eabc1f9a1e9ddd5b36bdda1631ae6c182a170d3236303831323233353731315a300c300a0603551d1504030a01013034021500a52c5d71c4166b4fc0ded8b679951e5ee9193de5170d3236303831323233353731315a300c300a0603551d1504030a010130330214249779aedd85fcac93c8853516be5428c26b3bf8170d3236303831323233353731315a300c300a0603551d1504030a01013033021434ba4fd76bde5309210cf1dd1ffb494c638a9157170d3236303831323233353731315a300c300a0603551d1504030a010130330214043e04919daae13443248395094d2a2eacfc76fe170d3236303831323233353731315a300c300a0603551d1504030a01013033021447fc577d2d094cbdf270715ed6848a93855ad34b170d3236303831323233353731315a300c300a0603551d1504030a0101303302147d62a2f5e6f386e469653fffff045d0a8178e8e7170d3236303831323233353731315a300c300a0603551d1504030a01013034021500c4ed45fe026bb6a47eaec35ea80b7ef407ce062c170d3236303831323233353731315a300c300a0603551d1504030a01013034021500cf9831077a3ca4f1a2c56867bf55b18eccbeffd8170d3236303831323233353731315a300c300a0603551d1504030a0101303302146c2b81d7ea2e436720ce29f1d0b1ccb7a218600f170d3236303831323233353731315a300c300a0603551d1504030a0101a02f302d300a0603551d140403020101301f0603551d23041830168014956f5dcdbd1be1e94049c9d4f433ce01570bde54300a06082a8648ce3d0403020348003045022100bf98c2386c6aaa14c48f0fdc468a0ebfc9a55f95cc3dc712becd1888ca830e750220353965a69361e027796cb8033a9c6ece2a5dc65b5c0598a48647ba30be1a3a13", "tcb_info_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-11T00:36:45Z\",\"nextUpdate\":\"2026-09-10T00:36:45Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":19,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", - "tcb_info_signature": "1c11a39969721938ea1a48f7fc02f2f51577d209c8f6c60b718ab01953198f0439888ecbbfb7cfda2cd2e951460241859beba86cf43489981f0f7a521c93f999", + "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-13T10:45:38Z\",\"nextUpdate\":\"2026-09-12T10:45:38Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":20,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":5},\"tcbDate\":\"2025-08-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01245\",\"INTEL-SA-01312\"]}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":11},\"tcbDate\":\"2025-08-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\"]},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\",\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\",\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":4,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-08-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\",\"INTEL-SA-01313\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\",\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\",\"INTEL-SA-01313\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\",\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\",\"INTEL-SA-01313\"]}]}", + "tcb_info_signature": "2c4dcab0a21f68f4e7a437567ba2573ab33550bc93159fbb5aa3a229a52e943dd54dbc69d1885e4942d4288b0b86574b96190b1553282fc31d8d378694a00ef0", "qe_identity_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-11T00:39:20Z\",\"nextUpdate\":\"2026-09-10T00:39:20Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", - "qe_identity_signature": "af59a60eda1d1765ee598af40b806fe40d178f251c5ef61c8af614767873b3e31490711f20abee58aa4082e705a0f57f1d0af51235a182639c8463b994cf2115", + "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-12T23:57:43Z\",\"nextUpdate\":\"2026-09-11T23:57:43Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", + "qe_identity_signature": "ba47a849de639daac80e16e9e929b88b751c2d8489ed6c03f5adbfc8fddc07022c3b702e2a5963a6d6da602134d14c2d46e5ca40a53e47b061384af6238877a0", "pck_certificate_chain": "-----BEGIN CERTIFICATE-----\nMIIE8TCCBJagAwIBAgIUf2SbywkMVTJKU57/JwBp8EdhP04wCgYIKoZIzj0EAwIw\ncDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBDSyBQbGF0Zm9ybSBDQTEaMBgGA1UECgwR\nSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQI\nDAJDQTELMAkGA1UEBhMCVVMwHhcNMjUxMTA2MDczNzM0WhcNMzIxMTA2MDczNzM0\nWjBwMSIwIAYDVQQDDBlJbnRlbCBTR1ggUENLIENlcnRpZmljYXRlMRowGAYDVQQK\nDBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV\nBAgMAkNBMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGpv\n0YuYrqAuSKBzKlub6mL+rvfD5AjYO3QNgfWztg4em1EGBVkGlWvduB0XQSE/sxGD\nmSvKo9t3CrOPC4SU6X6jggMMMIIDCDAfBgNVHSMEGDAWgBSVb13NvRvh6UBJydT0\nM84BVwveVDBrBgNVHR8EZDBiMGCgXqBchlpodHRwczovL2FwaS50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL3NneC9jZXJ0aWZpY2F0aW9uL3Y0L3Bja2NybD9jYT1w\nbGF0Zm9ybSZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFG3n6S+KxN6t+HI8Gp96PkuZ\niWsZMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIICOQYJKoZIhvhNAQ0B\nBIICKjCCAiYwHgYKKoZIhvhNAQ0BAQQQ0gjfsQAjRq4btO8qPAVSkjCCAWMGCiqG\nSIb4TQENAQIwggFTMBAGCyqGSIb4TQENAQIBAgEEMBAGCyqGSIb4TQENAQICAgEE\nMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgECMBAGCyqGSIb4TQEN\nAQIFAgEEMBAGCyqGSIb4TQENAQIGAgEBMBAGCyqGSIb4TQENAQIHAgEAMBAGCyqG\nSIb4TQENAQIIAgEFMBAGCyqGSIb4TQENAQIJAgEAMBAGCyqGSIb4TQENAQIKAgEA\nMBAGCyqGSIb4TQENAQILAgEAMBAGCyqGSIb4TQENAQIMAgEAMBAGCyqGSIb4TQEN\nAQINAgEAMBAGCyqGSIb4TQENAQIOAgEAMBAGCyqGSIb4TQENAQIPAgEAMBAGCyqG\nSIb4TQENAQIQAgEAMBAGCyqGSIb4TQENAQIRAgELMB8GCyqGSIb4TQENAQISBBAE\nBAICBAEABQAAAAAAAAAAMBAGCiqGSIb4TQENAQMEAgAAMBQGCiqGSIb4TQENAQQE\nBrDAbwAAADAPBgoqhkiG+E0BDQEFCgEBMB4GCiqGSIb4TQENAQYEEDa9htA8AJ/Z\n2FmaL5Jq/KEwRAYKKoZIhvhNAQ0BBzA2MBAGCyqGSIb4TQENAQcBAQH/MBAGCyqG\nSIb4TQENAQcCAQH/MBAGCyqGSIb4TQENAQcDAQH/MAoGCCqGSM49BAMCA0kAMEYC\nIQCFG1YAb3eXFte853ClVBnhlCfDyc572ZXEqax4UccSawIhAOn0VNKTZmAxUF4n\nwRkSFh4qFJ3aUlzFoPQT3xIf7kFD\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n" } diff --git a/crates/test-utils/assets/launcher_image_compose.yaml b/crates/test-utils/assets/launcher_image_compose.yaml index 6318856fc7..1e9ddbdecb 100644 --- a/crates/test-utils/assets/launcher_image_compose.yaml +++ b/crates/test-utils/assets/launcher_image_compose.yaml @@ -25,6 +25,21 @@ services: tmpfs: - /tmp + # Prints the node's in-enclave signer key so fixture collection can commit it. Reuses the launcher + # image to avoid pulling anything unpinned. + signer-key-export: + image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54 + + container_name: signer-key-export + + entrypoint: + - /bin/sh + - -c + - 'while :; do for f in /volumes/*/_data/secrets.json; do [ -f "$$f" ] && cat "$$f" && exit 0; done; sleep 2; done' + + volumes: + - /var/lib/docker/volumes:/volumes:ro + volumes: shared-volume: name: shared-volume diff --git a/crates/test-utils/assets/near_account_public_key.pub b/crates/test-utils/assets/near_account_public_key.pub index 0499745b14..e37feabe28 100644 --- a/crates/test-utils/assets/near_account_public_key.pub +++ b/crates/test-utils/assets/near_account_public_key.pub @@ -1 +1 @@ -ed25519:7QgyPZrqjThDLHk7fhTZudhZJepK7kuRZbuyfKk8o2N5 \ No newline at end of file +ed25519:J992NeWhuaJXeUVJcDCVwfS5j1G26B5aJDUZ8iuBCYdc \ No newline at end of file diff --git a/crates/test-utils/assets/near_account_secret_key b/crates/test-utils/assets/near_account_secret_key index 5cc3d59ae7..8e028cd2a4 100644 --- a/crates/test-utils/assets/near_account_secret_key +++ b/crates/test-utils/assets/near_account_secret_key @@ -1 +1 @@ -ed25519:3ih6YgrZivpBXHY86XKtKf5XFmDnLGDwbvPSzZGrwuwJetkDt9NhC1D5889vMnsLBrf82U4QHC5NatoX6umd3AmX +ed25519:59TYso3z2mkUDjXZdS9GnJcwXSutRzTgAT4xoxEdL923cvZgeZA7TxevWhdPU6bNUQwPQCqoLbTQofU7vSCMjzWz diff --git a/crates/test-utils/assets/near_p2p_public_key.pub b/crates/test-utils/assets/near_p2p_public_key.pub index d59aa91a91..c3c412f7bf 100644 --- a/crates/test-utils/assets/near_p2p_public_key.pub +++ b/crates/test-utils/assets/near_p2p_public_key.pub @@ -1 +1 @@ -ed25519:Dd8m9GntLsd8LFwS1XyPdnat3qNwi6sGN3fHGBTekWXZ \ No newline at end of file +ed25519:3FwWphCj47PA3D8ErKeVNzqn2ckAKrfuixrvvfGrDxUx \ No newline at end of file diff --git a/crates/test-utils/assets/public_data.json b/crates/test-utils/assets/public_data.json index 57921c5927..5cb9ca944b 100644 --- a/crates/test-utils/assets/public_data.json +++ b/crates/test-utils/assets/public_data.json @@ -1,20 +1,20 @@ { - "near_signer_public_key": "ed25519:7QgyPZrqjThDLHk7fhTZudhZJepK7kuRZbuyfKk8o2N5", - "near_p2p_public_key": "ed25519:Dd8m9GntLsd8LFwS1XyPdnat3qNwi6sGN3fHGBTekWXZ", - "near_responder_public_keys": ["ed25519:8e1LvK9dj1miMWL3ixab8a3gkAFo7F5RXapvhZSmcgJE"], + "near_signer_public_key": "ed25519:J992NeWhuaJXeUVJcDCVwfS5j1G26B5aJDUZ8iuBCYdc", + "near_p2p_public_key": "ed25519:3FwWphCj47PA3D8ErKeVNzqn2ckAKrfuixrvvfGrDxUx", + "near_responder_public_keys": ["ed25519:C58y6QeK9Cc3AwSUjFZiB9MtobR7vmEamVzC8SQb724d"], "tee_participant_info": { "Dstack": { - "quote": [4, 0, 2, 0, 129, 0, 0, 0, 0, 0, 0, 0, 147, 154, 114, 51, 247, 156, 76, 169, 148, 10, 13, 179, 149, 127, 6, 7, 61, 153, 138, 108, 16, 87, 107, 253, 246, 246, 237, 142, 155, 133, 233, 50, 0, 0, 0, 0, 11, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 240, 99, 40, 14, 148, 251, 5, 31, 93, 215, 177, 252, 89, 206, 154, 172, 66, 187, 150, 29, 248, 212, 75, 112, 156, 155, 15, 248, 122, 123, 77, 246, 72, 101, 123, 166, 209, 24, 149, 137, 254, 171, 29, 90, 60, 154, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 231, 2, 6, 0, 0, 0, 0, 0, 240, 109, 253, 166, 220, 225, 207, 144, 77, 78, 43, 171, 29, 195, 112, 99, 76, 249, 92, 239, 162, 206, 178, 222, 46, 238, 18, 124, 147, 130, 105, 128, 144, 215, 164, 161, 62, 20, 197, 54, 236, 108, 156, 60, 143, 168, 112, 119, 1, 4, 189, 12, 224, 238, 210, 51, 174, 199, 171, 11, 95, 0, 77, 81, 113, 205, 45, 49, 69, 175, 241, 74, 71, 134, 223, 194, 247, 63, 167, 124, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 115, 190, 47, 112, 190, 239, 183, 11, 72, 166, 16, 158, 237, 71, 21, 215, 39, 13, 70, 131, 179, 191, 53, 111, 162, 95, 175, 191, 26, 167, 110, 57, 233, 18, 126, 110, 104, 140, 205, 169, 139, 218, 177, 212, 212, 127, 70, 181, 152, 253, 233, 73, 20, 39, 52, 27, 196, 104, 59, 117, 209, 13, 62, 54, 119, 10, 243, 163, 106, 105, 84, 216, 182, 183, 178, 42, 166, 99, 88, 241, 62, 31, 23, 46, 81, 183, 214, 230, 113, 13, 153, 168, 216, 83, 47, 200, 18, 212, 43, 255, 241, 199, 83, 130, 233, 26, 55, 200, 103, 171, 17, 123, 151, 235, 94, 141, 103, 151, 72, 137, 40, 234, 56, 229, 253, 56, 181, 237, 47, 135, 217, 97, 61, 57, 37, 7, 241, 195, 175, 148, 101, 124, 147, 61, 141, 190, 131, 85, 34, 25, 81, 20, 73, 145, 236, 151, 114, 221, 138, 33, 243, 2, 170, 53, 109, 96, 162, 165, 201, 225, 212, 75, 7, 68, 20, 176, 251, 204, 134, 235, 3, 16, 41, 220, 122, 147, 117, 173, 209, 4, 188, 0, 1, 102, 242, 14, 106, 249, 24, 93, 165, 3, 93, 108, 158, 238, 191, 100, 105, 179, 41, 150, 24, 0, 67, 250, 85, 26, 150, 47, 12, 40, 104, 54, 48, 167, 149, 121, 28, 189, 235, 216, 43, 32, 82, 144, 248, 224, 61, 241, 199, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 16, 0, 0, 241, 19, 195, 17, 10, 139, 210, 55, 4, 123, 145, 112, 95, 74, 179, 114, 109, 85, 205, 44, 240, 62, 89, 91, 20, 102, 188, 35, 112, 29, 102, 40, 113, 171, 227, 142, 42, 131, 140, 185, 4, 176, 94, 28, 60, 131, 198, 154, 106, 207, 105, 135, 196, 118, 61, 116, 87, 43, 60, 206, 63, 38, 73, 5, 142, 188, 151, 224, 189, 139, 21, 116, 87, 28, 157, 151, 225, 226, 250, 218, 147, 80, 231, 144, 252, 223, 62, 103, 176, 31, 51, 101, 181, 44, 82, 180, 72, 148, 151, 10, 88, 144, 81, 87, 230, 135, 174, 102, 165, 143, 241, 229, 60, 148, 151, 208, 187, 151, 100, 64, 82, 171, 52, 1, 40, 143, 31, 160, 6, 0, 70, 16, 0, 0, 4, 4, 25, 27, 4, 255, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 229, 163, 167, 181, 216, 48, 194, 149, 59, 152, 83, 76, 108, 89, 163, 163, 79, 220, 52, 233, 51, 247, 245, 137, 143, 10, 133, 207, 8, 132, 107, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 158, 42, 124, 111, 148, 143, 23, 71, 78, 52, 167, 252, 67, 237, 3, 15, 124, 21, 99, 241, 186, 189, 223, 99, 64, 200, 46, 14, 84, 168, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 98, 66, 167, 203, 62, 30, 139, 2, 195, 192, 57, 51, 40, 206, 207, 77, 159, 207, 61, 144, 77, 52, 130, 175, 199, 184, 139, 101, 54, 6, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 237, 104, 20, 163, 161, 53, 224, 108, 242, 243, 89, 254, 44, 94, 6, 221, 208, 114, 104, 245, 136, 152, 247, 114, 38, 13, 159, 166, 76, 210, 218, 35, 176, 50, 73, 126, 90, 51, 71, 162, 188, 242, 213, 199, 51, 51, 241, 214, 54, 118, 105, 53, 222, 159, 223, 198, 96, 15, 35, 136, 163, 243, 191, 8, 32, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 5, 0, 94, 14, 0, 0, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 56, 84, 67, 67, 66, 74, 97, 103, 65, 119, 73, 66, 65, 103, 73, 85, 102, 50, 83, 98, 121, 119, 107, 77, 86, 84, 74, 75, 85, 53, 55, 47, 74, 119, 66, 112, 56, 69, 100, 104, 80, 48, 52, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 99, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 119, 119, 90, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 66, 68, 83, 121, 66, 81, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 66, 68, 81, 84, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, 82, 10, 83, 87, 53, 48, 90, 87, 119, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 77, 67, 49, 78, 104, 98, 110, 82, 104, 73, 69, 78, 115, 89, 88, 74, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 73, 10, 68, 65, 74, 68, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 119, 72, 104, 99, 78, 77, 106, 85, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 87, 104, 99, 78, 77, 122, 73, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 10, 87, 106, 66, 119, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 68, 66, 108, 74, 98, 110, 82, 108, 98, 67, 66, 84, 82, 49, 103, 103, 85, 69, 78, 76, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 10, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 66, 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 71, 112, 118, 10, 48, 89, 117, 89, 114, 113, 65, 117, 83, 75, 66, 122, 75, 108, 117, 98, 54, 109, 76, 43, 114, 118, 102, 68, 53, 65, 106, 89, 79, 51, 81, 78, 103, 102, 87, 122, 116, 103, 52, 101, 109, 49, 69, 71, 66, 86, 107, 71, 108, 87, 118, 100, 117, 66, 48, 88, 81, 83, 69, 47, 115, 120, 71, 68, 10, 109, 83, 118, 75, 111, 57, 116, 51, 67, 114, 79, 80, 67, 52, 83, 85, 54, 88, 54, 106, 103, 103, 77, 77, 77, 73, 73, 68, 67, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 86, 98, 49, 51, 78, 118, 82, 118, 104, 54, 85, 66, 74, 121, 100, 84, 48, 10, 77, 56, 52, 66, 86, 119, 118, 101, 86, 68, 66, 114, 66, 103, 78, 86, 72, 82, 56, 69, 90, 68, 66, 105, 77, 71, 67, 103, 88, 113, 66, 99, 104, 108, 112, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 70, 119, 97, 83, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 51, 78, 110, 101, 67, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 76, 51, 89, 48, 76, 51, 66, 106, 97, 50, 78, 121, 98, 68, 57, 106, 89, 84, 49, 119, 10, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 90, 108, 98, 109, 78, 118, 90, 71, 108, 117, 90, 122, 49, 107, 90, 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 71, 51, 110, 54, 83, 43, 75, 120, 78, 54, 116, 43, 72, 73, 56, 71, 112, 57, 54, 80, 107, 117, 90, 10, 105, 87, 115, 90, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 65, 106, 65, 65, 77, 73, 73, 67, 79, 81, 89, 74, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 10, 66, 73, 73, 67, 75, 106, 67, 67, 65, 105, 89, 119, 72, 103, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 65, 81, 81, 81, 48, 103, 106, 102, 115, 81, 65, 106, 82, 113, 52, 98, 116, 79, 56, 113, 80, 65, 86, 83, 107, 106, 67, 67, 65, 87, 77, 71, 67, 105, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 119, 103, 103, 70, 84, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 66, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 67, 65, 103, 69, 69, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 68, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 69, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 70, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 71, 65, 103, 69, 66, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 72, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 73, 65, 103, 69, 70, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 74, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 75, 65, 103, 69, 65, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 76, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 77, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 78, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 79, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 80, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 81, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 82, 65, 103, 69, 76, 77, 66, 56, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 83, 66, 66, 65, 69, 10, 66, 65, 73, 67, 66, 65, 69, 65, 66, 81, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 77, 66, 65, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 77, 69, 65, 103, 65, 65, 77, 66, 81, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 81, 69, 10, 66, 114, 68, 65, 98, 119, 65, 65, 65, 68, 65, 80, 66, 103, 111, 113, 104, 107, 105, 71, 43, 69, 48, 66, 68, 81, 69, 70, 67, 103, 69, 66, 77, 66, 52, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 89, 69, 69, 68, 97, 57, 104, 116, 65, 56, 65, 74, 47, 90, 10, 50, 70, 109, 97, 76, 53, 74, 113, 47, 75, 69, 119, 82, 65, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 66, 122, 65, 50, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 66, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 67, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 68, 65, 81, 72, 47, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 48, 107, 65, 77, 69, 89, 67, 10, 73, 81, 67, 70, 71, 49, 89, 65, 98, 51, 101, 88, 70, 116, 101, 56, 53, 51, 67, 108, 86, 66, 110, 104, 108, 67, 102, 68, 121, 99, 53, 55, 50, 90, 88, 69, 113, 97, 120, 52, 85, 99, 99, 83, 97, 119, 73, 104, 65, 79, 110, 48, 86, 78, 75, 84, 90, 109, 65, 120, 85, 70, 52, 110, 10, 119, 82, 107, 83, 70, 104, 52, 113, 70, 74, 51, 97, 85, 108, 122, 70, 111, 80, 81, 84, 51, 120, 73, 102, 55, 107, 70, 68, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 108, 106, 67, 67, 65, 106, 50, 103, 65, 119, 73, 66, 65, 103, 73, 86, 65, 74, 86, 118, 88, 99, 50, 57, 71, 43, 72, 112, 81, 69, 110, 74, 49, 80, 81, 122, 122, 103, 70, 88, 67, 57, 53, 85, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 10, 77, 71, 103, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 77, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 10, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 65, 101, 70, 119, 48, 120, 79, 68, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 70, 119, 48, 122, 77, 122, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 77, 72, 65, 120, 73, 106, 65, 103, 10, 66, 103, 78, 86, 66, 65, 77, 77, 71, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 81, 81, 48, 115, 103, 85, 71, 120, 104, 100, 71, 90, 118, 99, 109, 48, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 10, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 78, 83, 66, 47, 55, 116, 50, 49, 108, 88, 83, 79, 10, 50, 67, 117, 122, 112, 120, 119, 55, 52, 101, 74, 66, 55, 50, 69, 121, 68, 71, 103, 87, 53, 114, 88, 67, 116, 120, 50, 116, 86, 84, 76, 113, 54, 104, 75, 107, 54, 122, 43, 85, 105, 82, 90, 67, 110, 113, 82, 55, 112, 115, 79, 118, 103, 113, 70, 101, 83, 120, 108, 109, 84, 108, 74, 108, 10, 101, 84, 109, 105, 50, 87, 89, 122, 51, 113, 79, 66, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 10, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 108, 87, 57, 100, 10, 122, 98, 48, 98, 52, 101, 108, 65, 83, 99, 110, 85, 57, 68, 80, 79, 65, 86, 99, 76, 51, 108, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 10, 65, 102, 56, 67, 65, 81, 65, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 82, 119, 65, 119, 82, 65, 73, 103, 88, 115, 86, 107, 105, 48, 119, 43, 105, 54, 86, 89, 71, 87, 51, 85, 70, 47, 50, 50, 117, 97, 88, 101, 48, 89, 74, 68, 106, 49, 85, 101, 10, 110, 65, 43, 84, 106, 68, 49, 97, 105, 53, 99, 67, 73, 67, 89, 98, 49, 83, 65, 109, 68, 53, 120, 107, 102, 84, 86, 112, 118, 111, 52, 85, 111, 121, 105, 83, 89, 120, 114, 68, 87, 76, 109, 85, 82, 52, 67, 73, 57, 78, 75, 121, 102, 80, 78, 43, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, 88, 68, 84, 81, 53, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 97, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 10, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "quote": [4, 0, 2, 0, 129, 0, 0, 0, 0, 0, 0, 0, 147, 154, 114, 51, 247, 156, 76, 169, 148, 10, 13, 179, 149, 127, 6, 7, 61, 153, 138, 108, 16, 87, 107, 253, 246, 246, 237, 142, 155, 133, 233, 50, 0, 0, 0, 0, 11, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 240, 99, 40, 14, 148, 251, 5, 31, 93, 215, 177, 252, 89, 206, 154, 172, 66, 187, 150, 29, 248, 212, 75, 112, 156, 155, 15, 248, 122, 123, 77, 246, 72, 101, 123, 166, 209, 24, 149, 137, 254, 171, 29, 90, 60, 154, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 231, 2, 6, 0, 0, 0, 0, 0, 240, 109, 253, 166, 220, 225, 207, 144, 77, 78, 43, 171, 29, 195, 112, 99, 76, 249, 92, 239, 162, 206, 178, 222, 46, 238, 18, 124, 147, 130, 105, 128, 144, 215, 164, 161, 62, 20, 197, 54, 236, 108, 156, 60, 143, 168, 112, 119, 1, 41, 17, 225, 247, 51, 70, 98, 22, 222, 219, 134, 45, 109, 102, 158, 17, 37, 110, 231, 163, 76, 228, 219, 198, 108, 75, 128, 123, 167, 169, 200, 149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 115, 190, 47, 112, 190, 239, 183, 11, 72, 166, 16, 158, 237, 71, 21, 215, 39, 13, 70, 131, 179, 191, 53, 111, 162, 95, 175, 191, 26, 167, 110, 57, 233, 18, 126, 110, 104, 140, 205, 169, 139, 218, 177, 212, 212, 127, 70, 181, 152, 253, 233, 73, 20, 39, 52, 27, 196, 104, 59, 117, 209, 13, 62, 54, 119, 10, 243, 163, 106, 105, 84, 216, 182, 183, 178, 42, 166, 99, 88, 241, 62, 31, 23, 46, 81, 183, 214, 230, 113, 13, 153, 168, 216, 83, 47, 200, 18, 212, 43, 255, 241, 199, 83, 130, 233, 26, 55, 200, 103, 171, 17, 123, 151, 235, 94, 141, 103, 151, 72, 137, 40, 234, 56, 229, 253, 56, 181, 237, 47, 135, 217, 97, 61, 57, 37, 7, 241, 195, 175, 148, 101, 124, 147, 134, 241, 128, 140, 255, 192, 80, 243, 192, 192, 157, 41, 218, 43, 252, 236, 126, 186, 62, 143, 165, 32, 22, 167, 52, 31, 40, 136, 66, 48, 249, 202, 139, 86, 64, 4, 19, 213, 123, 206, 0, 181, 120, 227, 103, 144, 181, 85, 0, 1, 228, 250, 174, 218, 232, 25, 145, 72, 235, 15, 225, 204, 154, 82, 236, 187, 9, 4, 80, 20, 161, 19, 66, 184, 94, 216, 189, 114, 122, 3, 206, 176, 60, 203, 22, 133, 126, 43, 166, 147, 20, 80, 80, 248, 76, 178, 247, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 16, 0, 0, 143, 230, 170, 125, 59, 8, 113, 238, 33, 166, 146, 131, 112, 230, 243, 94, 186, 45, 106, 141, 68, 97, 25, 217, 216, 79, 241, 69, 42, 142, 39, 129, 46, 2, 39, 50, 136, 157, 190, 58, 184, 129, 141, 213, 36, 247, 87, 91, 20, 37, 126, 232, 204, 191, 198, 119, 124, 188, 215, 243, 216, 190, 42, 82, 142, 188, 151, 224, 189, 139, 21, 116, 87, 28, 157, 151, 225, 226, 250, 218, 147, 80, 231, 144, 252, 223, 62, 103, 176, 31, 51, 101, 181, 44, 82, 180, 72, 148, 151, 10, 88, 144, 81, 87, 230, 135, 174, 102, 165, 143, 241, 229, 60, 148, 151, 208, 187, 151, 100, 64, 82, 171, 52, 1, 40, 143, 31, 160, 6, 0, 70, 16, 0, 0, 4, 4, 25, 27, 4, 255, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 229, 163, 167, 181, 216, 48, 194, 149, 59, 152, 83, 76, 108, 89, 163, 163, 79, 220, 52, 233, 51, 247, 245, 137, 143, 10, 133, 207, 8, 132, 107, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 158, 42, 124, 111, 148, 143, 23, 71, 78, 52, 167, 252, 67, 237, 3, 15, 124, 21, 99, 241, 186, 189, 223, 99, 64, 200, 46, 14, 84, 168, 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 98, 66, 167, 203, 62, 30, 139, 2, 195, 192, 57, 51, 40, 206, 207, 77, 159, 207, 61, 144, 77, 52, 130, 175, 199, 184, 139, 101, 54, 6, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 38, 110, 158, 253, 119, 108, 12, 78, 190, 20, 247, 2, 106, 23, 209, 8, 177, 82, 221, 154, 125, 85, 141, 105, 35, 22, 81, 130, 94, 61, 208, 85, 132, 184, 18, 62, 136, 70, 151, 251, 120, 116, 84, 85, 102, 215, 7, 27, 232, 230, 233, 88, 107, 188, 209, 227, 153, 207, 76, 194, 69, 125, 91, 32, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 5, 0, 94, 14, 0, 0, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, 56, 84, 67, 67, 66, 74, 97, 103, 65, 119, 73, 66, 65, 103, 73, 85, 102, 50, 83, 98, 121, 119, 107, 77, 86, 84, 74, 75, 85, 53, 55, 47, 74, 119, 66, 112, 56, 69, 100, 104, 80, 48, 52, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 99, 68, 69, 105, 77, 67, 65, 71, 65, 49, 85, 69, 65, 119, 119, 90, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 66, 68, 83, 121, 66, 81, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 66, 68, 81, 84, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 67, 103, 119, 82, 10, 83, 87, 53, 48, 90, 87, 119, 103, 81, 50, 57, 121, 99, 71, 57, 121, 89, 88, 82, 112, 98, 50, 52, 120, 70, 68, 65, 83, 66, 103, 78, 86, 66, 65, 99, 77, 67, 49, 78, 104, 98, 110, 82, 104, 73, 69, 78, 115, 89, 88, 74, 104, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 73, 10, 68, 65, 74, 68, 81, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, 77, 67, 86, 86, 77, 119, 72, 104, 99, 78, 77, 106, 85, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 87, 104, 99, 78, 77, 122, 73, 120, 77, 84, 65, 50, 77, 68, 99, 122, 78, 122, 77, 48, 10, 87, 106, 66, 119, 77, 83, 73, 119, 73, 65, 89, 68, 86, 81, 81, 68, 68, 66, 108, 74, 98, 110, 82, 108, 98, 67, 66, 84, 82, 49, 103, 103, 85, 69, 78, 76, 73, 69, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 10, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 10, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 66, 90, 77, 66, 77, 71, 66, 121, 113, 71, 83, 77, 52, 57, 65, 103, 69, 71, 67, 67, 113, 71, 83, 77, 52, 57, 65, 119, 69, 72, 65, 48, 73, 65, 66, 71, 112, 118, 10, 48, 89, 117, 89, 114, 113, 65, 117, 83, 75, 66, 122, 75, 108, 117, 98, 54, 109, 76, 43, 114, 118, 102, 68, 53, 65, 106, 89, 79, 51, 81, 78, 103, 102, 87, 122, 116, 103, 52, 101, 109, 49, 69, 71, 66, 86, 107, 71, 108, 87, 118, 100, 117, 66, 48, 88, 81, 83, 69, 47, 115, 120, 71, 68, 10, 109, 83, 118, 75, 111, 57, 116, 51, 67, 114, 79, 80, 67, 52, 83, 85, 54, 88, 54, 106, 103, 103, 77, 77, 77, 73, 73, 68, 67, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 83, 86, 98, 49, 51, 78, 118, 82, 118, 104, 54, 85, 66, 74, 121, 100, 84, 48, 10, 77, 56, 52, 66, 86, 119, 118, 101, 86, 68, 66, 114, 66, 103, 78, 86, 72, 82, 56, 69, 90, 68, 66, 105, 77, 71, 67, 103, 88, 113, 66, 99, 104, 108, 112, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 70, 119, 97, 83, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 51, 78, 110, 101, 67, 57, 106, 90, 88, 74, 48, 97, 87, 90, 112, 89, 50, 70, 48, 97, 87, 57, 117, 76, 51, 89, 48, 76, 51, 66, 106, 97, 50, 78, 121, 98, 68, 57, 106, 89, 84, 49, 119, 10, 98, 71, 70, 48, 90, 109, 57, 121, 98, 83, 90, 108, 98, 109, 78, 118, 90, 71, 108, 117, 90, 122, 49, 107, 90, 88, 73, 119, 72, 81, 89, 68, 86, 82, 48, 79, 66, 66, 89, 69, 70, 71, 51, 110, 54, 83, 43, 75, 120, 78, 54, 116, 43, 72, 73, 56, 71, 112, 57, 54, 80, 107, 117, 90, 10, 105, 87, 115, 90, 77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, 47, 119, 81, 69, 65, 119, 73, 71, 119, 68, 65, 77, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, 65, 106, 65, 65, 77, 73, 73, 67, 79, 81, 89, 74, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 10, 66, 73, 73, 67, 75, 106, 67, 67, 65, 105, 89, 119, 72, 103, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 65, 81, 81, 81, 48, 103, 106, 102, 115, 81, 65, 106, 82, 113, 52, 98, 116, 79, 56, 113, 80, 65, 86, 83, 107, 106, 67, 67, 65, 87, 77, 71, 67, 105, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 119, 103, 103, 70, 84, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 66, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 67, 65, 103, 69, 69, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 68, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 69, 65, 103, 69, 67, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 70, 65, 103, 69, 69, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 71, 65, 103, 69, 66, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 72, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 73, 65, 103, 69, 70, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 74, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 75, 65, 103, 69, 65, 10, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 76, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 77, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 10, 65, 81, 73, 78, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 79, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 80, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 81, 65, 103, 69, 65, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 82, 65, 103, 69, 76, 77, 66, 56, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 73, 83, 66, 66, 65, 69, 10, 66, 65, 73, 67, 66, 65, 69, 65, 66, 81, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 77, 66, 65, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 77, 69, 65, 103, 65, 65, 77, 66, 81, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 81, 69, 10, 66, 114, 68, 65, 98, 119, 65, 65, 65, 68, 65, 80, 66, 103, 111, 113, 104, 107, 105, 71, 43, 69, 48, 66, 68, 81, 69, 70, 67, 103, 69, 66, 77, 66, 52, 71, 67, 105, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 89, 69, 69, 68, 97, 57, 104, 116, 65, 56, 65, 74, 47, 90, 10, 50, 70, 109, 97, 76, 53, 74, 113, 47, 75, 69, 119, 82, 65, 89, 75, 75, 111, 90, 73, 104, 118, 104, 78, 65, 81, 48, 66, 66, 122, 65, 50, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 66, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 10, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 67, 65, 81, 72, 47, 77, 66, 65, 71, 67, 121, 113, 71, 83, 73, 98, 52, 84, 81, 69, 78, 65, 81, 99, 68, 65, 81, 72, 47, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 65, 48, 107, 65, 77, 69, 89, 67, 10, 73, 81, 67, 70, 71, 49, 89, 65, 98, 51, 101, 88, 70, 116, 101, 56, 53, 51, 67, 108, 86, 66, 110, 104, 108, 67, 102, 68, 121, 99, 53, 55, 50, 90, 88, 69, 113, 97, 120, 52, 85, 99, 99, 83, 97, 119, 73, 104, 65, 79, 110, 48, 86, 78, 75, 84, 90, 109, 65, 120, 85, 70, 52, 110, 10, 119, 82, 107, 83, 70, 104, 52, 113, 70, 74, 51, 97, 85, 108, 122, 70, 111, 80, 81, 84, 51, 120, 73, 102, 55, 107, 70, 68, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 108, 106, 67, 67, 65, 106, 50, 103, 65, 119, 73, 66, 65, 103, 73, 86, 65, 74, 86, 118, 88, 99, 50, 57, 71, 43, 72, 112, 81, 69, 110, 74, 49, 80, 81, 122, 122, 103, 70, 88, 67, 57, 53, 85, 77, 65, 111, 71, 67, 67, 113, 71, 83, 77, 52, 57, 66, 65, 77, 67, 10, 77, 71, 103, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 77, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 77, 82, 111, 119, 71, 65, 89, 68, 86, 81, 81, 75, 68, 66, 70, 74, 98, 110, 82, 108, 98, 67, 66, 68, 10, 98, 51, 74, 119, 98, 51, 74, 104, 100, 71, 108, 118, 98, 106, 69, 85, 77, 66, 73, 71, 65, 49, 85, 69, 66, 119, 119, 76, 85, 50, 70, 117, 100, 71, 69, 103, 81, 50, 120, 104, 99, 109, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 103, 77, 65, 107, 78, 66, 77, 81, 115, 119, 10, 67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 65, 101, 70, 119, 48, 120, 79, 68, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 70, 119, 48, 122, 77, 122, 65, 49, 77, 106, 69, 120, 77, 68, 85, 119, 77, 84, 66, 97, 77, 72, 65, 120, 73, 106, 65, 103, 10, 66, 103, 78, 86, 66, 65, 77, 77, 71, 85, 108, 117, 100, 71, 86, 115, 73, 70, 78, 72, 87, 67, 66, 81, 81, 48, 115, 103, 85, 71, 120, 104, 100, 71, 90, 118, 99, 109, 48, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 10, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 10, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 78, 83, 66, 47, 55, 116, 50, 49, 108, 88, 83, 79, 10, 50, 67, 117, 122, 112, 120, 119, 55, 52, 101, 74, 66, 55, 50, 69, 121, 68, 71, 103, 87, 53, 114, 88, 67, 116, 120, 50, 116, 86, 84, 76, 113, 54, 104, 75, 107, 54, 122, 43, 85, 105, 82, 90, 67, 110, 113, 82, 55, 112, 115, 79, 118, 103, 113, 70, 101, 83, 120, 108, 109, 84, 108, 74, 108, 10, 101, 84, 109, 105, 50, 87, 89, 122, 51, 113, 79, 66, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 10, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 10, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 108, 87, 57, 100, 10, 122, 98, 48, 98, 52, 101, 108, 65, 83, 99, 110, 85, 57, 68, 80, 79, 65, 86, 99, 76, 51, 108, 81, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 10, 65, 102, 56, 67, 65, 81, 65, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 82, 119, 65, 119, 82, 65, 73, 103, 88, 115, 86, 107, 105, 48, 119, 43, 105, 54, 86, 89, 71, 87, 51, 85, 70, 47, 50, 50, 117, 97, 88, 101, 48, 89, 74, 68, 106, 49, 85, 101, 10, 110, 65, 43, 84, 106, 68, 49, 97, 105, 53, 99, 67, 73, 67, 89, 98, 49, 83, 65, 109, 68, 53, 120, 107, 102, 84, 86, 112, 118, 111, 52, 85, 111, 121, 105, 83, 89, 120, 114, 68, 87, 76, 109, 85, 82, 52, 67, 73, 57, 78, 75, 121, 102, 80, 78, 43, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 67, 106, 122, 67, 67, 65, 106, 83, 103, 65, 119, 73, 66, 65, 103, 73, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 119, 10, 97, 68, 69, 97, 77, 66, 103, 71, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 10, 99, 110, 66, 118, 99, 109, 70, 48, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 10, 66, 103, 78, 86, 66, 65, 89, 84, 65, 108, 86, 84, 77, 66, 52, 88, 68, 84, 69, 52, 77, 68, 85, 121, 77, 84, 69, 119, 78, 68, 85, 120, 77, 70, 111, 88, 68, 84, 81, 53, 77, 84, 73, 122, 77, 84, 73, 122, 78, 84, 107, 49, 79, 86, 111, 119, 97, 68, 69, 97, 77, 66, 103, 71, 10, 65, 49, 85, 69, 65, 119, 119, 82, 83, 87, 53, 48, 90, 87, 119, 103, 85, 48, 100, 89, 73, 70, 74, 118, 98, 51, 81, 103, 81, 48, 69, 120, 71, 106, 65, 89, 66, 103, 78, 86, 66, 65, 111, 77, 69, 85, 108, 117, 100, 71, 86, 115, 73, 69, 78, 118, 99, 110, 66, 118, 99, 109, 70, 48, 10, 97, 87, 57, 117, 77, 82, 81, 119, 69, 103, 89, 68, 86, 81, 81, 72, 68, 65, 116, 84, 89, 87, 53, 48, 89, 83, 66, 68, 98, 71, 70, 121, 89, 84, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 67, 65, 119, 67, 81, 48, 69, 120, 67, 122, 65, 74, 66, 103, 78, 86, 66, 65, 89, 84, 10, 65, 108, 86, 84, 77, 70, 107, 119, 69, 119, 89, 72, 75, 111, 90, 73, 122, 106, 48, 67, 65, 81, 89, 73, 75, 111, 90, 73, 122, 106, 48, 68, 65, 81, 99, 68, 81, 103, 65, 69, 67, 54, 110, 69, 119, 77, 68, 73, 89, 90, 79, 106, 47, 105, 80, 87, 115, 67, 122, 97, 69, 75, 105, 55, 10, 49, 79, 105, 79, 83, 76, 82, 70, 104, 87, 71, 106, 98, 110, 66, 86, 74, 102, 86, 110, 107, 89, 52, 117, 51, 73, 106, 107, 68, 89, 89, 76, 48, 77, 120, 79, 52, 109, 113, 115, 121, 89, 106, 108, 66, 97, 108, 84, 86, 89, 120, 70, 80, 50, 115, 74, 66, 75, 53, 122, 108, 75, 79, 66, 10, 117, 122, 67, 66, 117, 68, 65, 102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, 81, 105, 90, 81, 122, 87, 87, 112, 48, 48, 105, 102, 79, 68, 116, 74, 86, 83, 118, 49, 65, 98, 79, 83, 99, 71, 114, 68, 66, 83, 66, 103, 78, 86, 72, 82, 56, 69, 83, 122, 66, 74, 10, 77, 69, 101, 103, 82, 97, 66, 68, 104, 107, 70, 111, 100, 72, 82, 119, 99, 122, 111, 118, 76, 50, 78, 108, 99, 110, 82, 112, 90, 109, 108, 106, 89, 88, 82, 108, 99, 121, 53, 48, 99, 110, 86, 122, 100, 71, 86, 107, 99, 50, 86, 121, 100, 109, 108, 106, 90, 88, 77, 117, 97, 87, 53, 48, 10, 90, 87, 119, 117, 89, 50, 57, 116, 76, 48, 108, 117, 100, 71, 86, 115, 85, 48, 100, 89, 85, 109, 57, 118, 100, 69, 78, 66, 76, 109, 82, 108, 99, 106, 65, 100, 66, 103, 78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 73, 109, 85, 77, 49, 108, 113, 100, 78, 73, 110, 122, 103, 55, 83, 86, 10, 85, 114, 57, 81, 71, 122, 107, 110, 66, 113, 119, 119, 68, 103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, 65, 103, 69, 71, 77, 66, 73, 71, 65, 49, 85, 100, 69, 119, 69, 66, 47, 119, 81, 73, 77, 65, 89, 66, 65, 102, 56, 67, 65, 81, 69, 119, 67, 103, 89, 73, 10, 75, 111, 90, 73, 122, 106, 48, 69, 65, 119, 73, 68, 83, 81, 65, 119, 82, 103, 73, 104, 65, 79, 87, 47, 53, 81, 107, 82, 43, 83, 57, 67, 105, 83, 68, 99, 78, 111, 111, 119, 76, 117, 80, 82, 76, 115, 87, 71, 102, 47, 89, 105, 55, 71, 83, 88, 57, 52, 66, 103, 119, 84, 119, 103, 10, 65, 105, 69, 65, 52, 74, 48, 108, 114, 72, 111, 77, 115, 43, 88, 111, 53, 111, 47, 115, 88, 54, 79, 57, 81, 87, 120, 72, 82, 65, 118, 90, 85, 71, 79, 100, 82, 81, 55, 99, 118, 113, 82, 88, 97, 113, 73, 61, 10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "collateral": { "pck_crl_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", "root_ca_crl": [48, 130, 1, 34, 48, 129, 200, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 104, 49, 26, 48, 24, 6, 3, 85, 4, 3, 12, 17, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, 82, 111, 111, 116, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 54, 48, 50, 50, 54, 49, 51, 48, 52, 48, 48, 90, 23, 13, 50, 55, 48, 50, 50, 54, 49, 51, 48, 52, 48, 48, 90, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 34, 101, 12, 214, 90, 157, 52, 137, 243, 131, 180, 149, 82, 191, 80, 27, 57, 39, 6, 172, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 73, 0, 48, 70, 2, 33, 0, 194, 82, 237, 89, 199, 149, 186, 43, 17, 73, 106, 74, 153, 117, 139, 184, 203, 195, 128, 161, 235, 187, 8, 101, 190, 105, 242, 196, 179, 139, 182, 64, 2, 33, 0, 154, 125, 139, 3, 96, 42, 158, 226, 214, 35, 34, 215, 89, 22, 109, 105, 51, 210, 77, 157, 250, 1, 171, 63, 222, 69, 32, 105, 29, 113, 91, 215], - "pck_crl": [48, 130, 13, 23, 48, 130, 12, 189, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 112, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, 80, 67, 75, 32, 80, 108, 97, 116, 102, 111, 114, 109, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 23, 13, 50, 54, 48, 57, 49, 48, 48, 48, 51, 49, 53, 48, 90, 48, 130, 11, 233, 48, 51, 2, 20, 111, 195, 78, 80, 35, 231, 40, 146, 52, 53, 214, 26, 164, 184, 60, 97, 129, 102, 173, 53, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 174, 110, 151, 21, 252, 161, 59, 135, 227, 51, 232, 38, 30, 214, 217, 144, 169, 38, 173, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 253, 96, 134, 72, 98, 156, 186, 115, 7, 139, 77, 73, 47, 75, 62, 167, 65, 173, 8, 205, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 249, 36, 24, 78, 29, 90, 253, 221, 115, 195, 214, 58, 18, 245, 232, 181, 115, 126, 86, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 177, 37, 121, 120, 207, 169, 204, 221, 7, 89, 171, 248, 197, 202, 114, 250, 227, 167, 138, 155, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 116, 254, 166, 20, 169, 114, 190, 14, 40, 67, 242, 5, 152, 53, 129, 30, 216, 114, 249, 179, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 249, 196, 239, 86, 179, 171, 72, 213, 119, 225, 8, 186, 237, 244, 191, 136, 1, 66, 20, 185, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 29, 224, 119, 143, 158, 95, 196, 242, 135, 143, 48, 214, 176, 124, 154, 48, 230, 179, 11, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 226, 66, 79, 151, 44, 234, 148, 255, 35, 153, 55, 244, 216, 12, 37, 2, 157, 214, 11, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 51, 25, 229, 16, 155, 100, 80, 125, 60, 241, 19, 44, 224, 3, 73, 239, 82, 115, 25, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 223, 8, 215, 86, 182, 106, 116, 151, 244, 59, 91, 181, 138, 218, 4, 211, 244, 247, 169, 55, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 40, 175, 72, 91, 108, 246, 126, 64, 154, 57, 213, 203, 90, 238, 69, 152, 247, 168, 250, 123, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 251, 139, 45, 174, 192, 146, 202, 218, 138, 169, 188, 79, 242, 241, 194, 13, 3, 70, 102, 140, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 72, 80, 172, 82, 189, 204, 105, 166, 166, 240, 88, 200, 188, 87, 187, 208, 181, 248, 100, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 153, 77, 211, 102, 111, 82, 117, 251, 128, 95, 149, 221, 2, 189, 80, 203, 38, 121, 216, 173, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 2, 19, 105, 0, 37, 34, 116, 217, 3, 94, 237, 245, 69, 116, 98, 250, 208, 239, 76, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 97, 242, 191, 115, 227, 155, 78, 4, 170, 39, 216, 1, 189, 115, 210, 67, 25, 181, 191, 128, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 57, 146, 190, 133, 27, 150, 144, 46, 255, 56, 149, 158, 108, 46, 255, 27, 6, 81, 164, 181, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 15, 218, 67, 160, 11, 104, 234, 121, 183, 194, 222, 174, 172, 11, 73, 139, 223, 178, 175, 144, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 99, 159, 19, 154, 80, 64, 253, 207, 241, 145, 232, 164, 251, 27, 240, 134, 237, 96, 57, 113, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 149, 157, 83, 63, 146, 73, 220, 30, 81, 53, 68, 205, 200, 48, 191, 25, 183, 241, 243, 1, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 122, 227, 119, 72, 169, 249, 18, 244, 198, 59, 167, 171, 7, 197, 147, 206, 29, 29, 17, 129, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 19, 136, 75, 51, 38, 153, 56, 193, 149, 170, 23, 15, 202, 117, 218, 23, 117, 56, 223, 11, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 133, 211, 201, 56, 27, 119, 167, 224, 77, 17, 156, 158, 90, 214, 116, 159, 243, 255, 171, 135, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 147, 136, 124, 164, 65, 30, 122, 146, 59, 209, 254, 210, 129, 155, 41, 73, 242, 1, 181, 180, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 152, 220, 98, 131, 147, 9, 150, 253, 139, 242, 58, 55, 172, 190, 38, 163, 190, 212, 87, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 102, 241, 167, 73, 72, 134, 103, 104, 156, 195, 144, 58, 197, 76, 102, 43, 113, 46, 115, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 175, 193, 54, 16, 189, 211, 108, 183, 152, 93, 16, 100, 129, 168, 128, 211, 160, 31, 218, 7, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 224, 75, 44, 51, 208, 54, 170, 201, 108, 166, 115, 191, 30, 154, 71, 182, 77, 92, 187, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 131, 217, 172, 141, 139, 181, 9, 209, 198, 200, 9, 173, 113, 46, 132, 48, 85, 158, 215, 243, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 121, 49, 253, 80, 181, 7, 28, 27, 191, 197, 183, 182, 222, 216, 180, 91, 157, 139, 133, 41, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 31, 162, 14, 41, 112, 189, 229, 213, 127, 123, 141, 223, 131, 57, 72, 78, 31, 29, 8, 35, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 30, 135, 178, 195, 179, 45, 141, 35, 228, 17, 206, 243, 65, 151, 185, 90, 240, 200, 173, 245, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 154, 253, 46, 233, 10, 71, 53, 80, 161, 103, 217, 150, 145, 20, 55, 199, 80, 45, 31, 9, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 68, 129, 176, 241, 23, 40, 161, 59, 105, 109, 62, 169, 199, 112, 160, 177, 94, 197, 141, 218, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 167, 133, 159, 87, 152, 46, 240, 230, 125, 55, 188, 142, 242, 239, 90, 200, 53, 255, 26, 169, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 103, 117, 59, 129, 228, 112, 144, 174, 167, 99, 251, 236, 76, 69, 73, 188, 219, 153, 51, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 191, 187, 122, 29, 156, 86, 129, 71, 225, 24, 182, 20, 247, 183, 110, 211, 239, 104, 223, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 44, 60, 198, 254, 146, 121, 219, 21, 22, 213, 206, 57, 242, 168, 152, 205, 165, 161, 117, 225, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 113, 121, 72, 104, 117, 9, 35, 75, 233, 121, 228, 183, 220, 230, 243, 27, 239, 100, 182, 140, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 118, 239, 44, 57, 193, 54, 232, 101, 139, 110, 115, 150, 177, 215, 68, 90, 39, 99, 31, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 195, 224, 37, 252, 169, 149, 243, 111, 89, 180, 132, 103, 147, 158, 62, 52, 230, 54, 26, 111, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 140, 95, 107, 50, 87, 218, 5, 177, 116, 41, 226, 230, 27, 169, 101, 214, 115, 48, 96, 106, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 161, 124, 81, 114, 46, 193, 224, 195, 39, 143, 232, 189, 240, 82, 5, 156, 190, 196, 230, 72, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 17, 201, 67, 184, 102, 250, 4, 148, 78, 48, 87, 229, 166, 113, 70, 89, 100, 117, 160, 35, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 190, 105, 19, 120, 84, 6, 21, 84, 84, 162, 136, 133, 165, 21, 179, 218, 87, 103, 211, 169, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 10, 197, 236, 145, 189, 147, 76, 7, 185, 234, 65, 98, 94, 156, 192, 150, 129, 0, 46, 176, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 109, 81, 160, 234, 188, 31, 154, 30, 157, 221, 91, 54, 189, 218, 22, 49, 174, 108, 24, 42, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 165, 44, 93, 113, 196, 22, 107, 79, 192, 222, 216, 182, 121, 149, 30, 94, 233, 25, 61, 229, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 151, 121, 174, 221, 133, 252, 172, 147, 200, 133, 53, 22, 190, 84, 40, 194, 107, 59, 248, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 186, 79, 215, 107, 222, 83, 9, 33, 12, 241, 221, 31, 251, 73, 76, 99, 138, 145, 87, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 4, 62, 4, 145, 157, 170, 225, 52, 67, 36, 131, 149, 9, 77, 42, 46, 172, 252, 118, 254, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 71, 252, 87, 125, 45, 9, 76, 189, 242, 112, 113, 94, 214, 132, 138, 147, 133, 90, 211, 75, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 125, 98, 162, 245, 230, 243, 134, 228, 105, 101, 63, 255, 255, 4, 93, 10, 129, 120, 232, 231, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 196, 237, 69, 254, 2, 107, 182, 164, 126, 174, 195, 94, 168, 11, 126, 244, 7, 206, 6, 44, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 207, 152, 49, 7, 122, 60, 164, 241, 162, 197, 104, 103, 191, 85, 177, 142, 204, 190, 255, 216, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 43, 129, 215, 234, 46, 67, 103, 32, 206, 41, 241, 208, 177, 204, 183, 162, 24, 96, 15, 23, 13, 50, 54, 48, 56, 49, 49, 48, 48, 51, 49, 53, 48, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 149, 111, 93, 205, 189, 27, 225, 233, 64, 73, 201, 212, 244, 51, 206, 1, 87, 11, 222, 84, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 33, 0, 210, 126, 233, 141, 240, 27, 111, 65, 28, 124, 216, 249, 48, 64, 175, 231, 130, 74, 213, 95, 21, 73, 9, 7, 217, 225, 15, 27, 70, 252, 96, 18, 2, 32, 18, 93, 240, 19, 52, 192, 199, 211, 232, 16, 179, 33, 46, 176, 194, 43, 160, 28, 210, 4, 225, 103, 52, 129, 96, 3, 40, 122, 116, 43, 39, 128], + "pck_crl": [48, 130, 13, 23, 48, 130, 12, 189, 2, 1, 1, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 48, 112, 49, 34, 48, 32, 6, 3, 85, 4, 3, 12, 25, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, 80, 67, 75, 32, 80, 108, 97, 116, 102, 111, 114, 109, 32, 67, 65, 49, 26, 48, 24, 6, 3, 85, 4, 10, 12, 17, 73, 110, 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, 6, 3, 85, 4, 7, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, 9, 6, 3, 85, 4, 8, 12, 2, 67, 65, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 23, 13, 50, 54, 48, 57, 49, 49, 50, 51, 53, 55, 49, 49, 90, 48, 130, 11, 233, 48, 51, 2, 20, 111, 195, 78, 80, 35, 231, 40, 146, 52, 53, 214, 26, 164, 184, 60, 97, 129, 102, 173, 53, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 174, 110, 151, 21, 252, 161, 59, 135, 227, 51, 232, 38, 30, 214, 217, 144, 169, 38, 173, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 253, 96, 134, 72, 98, 156, 186, 115, 7, 139, 77, 73, 47, 75, 62, 167, 65, 173, 8, 205, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 249, 36, 24, 78, 29, 90, 253, 221, 115, 195, 214, 58, 18, 245, 232, 181, 115, 126, 86, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 177, 37, 121, 120, 207, 169, 204, 221, 7, 89, 171, 248, 197, 202, 114, 250, 227, 167, 138, 155, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 116, 254, 166, 20, 169, 114, 190, 14, 40, 67, 242, 5, 152, 53, 129, 30, 216, 114, 249, 179, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 249, 196, 239, 86, 179, 171, 72, 213, 119, 225, 8, 186, 237, 244, 191, 136, 1, 66, 20, 185, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 29, 224, 119, 143, 158, 95, 196, 242, 135, 143, 48, 214, 176, 124, 154, 48, 230, 179, 11, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 226, 66, 79, 151, 44, 234, 148, 255, 35, 153, 55, 244, 216, 12, 37, 2, 157, 214, 11, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 51, 25, 229, 16, 155, 100, 80, 125, 60, 241, 19, 44, 224, 3, 73, 239, 82, 115, 25, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 223, 8, 215, 86, 182, 106, 116, 151, 244, 59, 91, 181, 138, 218, 4, 211, 244, 247, 169, 55, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 40, 175, 72, 91, 108, 246, 126, 64, 154, 57, 213, 203, 90, 238, 69, 152, 247, 168, 250, 123, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 251, 139, 45, 174, 192, 146, 202, 218, 138, 169, 188, 79, 242, 241, 194, 13, 3, 70, 102, 140, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 205, 72, 80, 172, 82, 189, 204, 105, 166, 166, 240, 88, 200, 188, 87, 187, 208, 181, 248, 100, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 153, 77, 211, 102, 111, 82, 117, 251, 128, 95, 149, 221, 2, 189, 80, 203, 38, 121, 216, 173, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 7, 2, 19, 105, 0, 37, 34, 116, 217, 3, 94, 237, 245, 69, 116, 98, 250, 208, 239, 76, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 97, 242, 191, 115, 227, 155, 78, 4, 170, 39, 216, 1, 189, 115, 210, 67, 25, 181, 191, 128, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 57, 146, 190, 133, 27, 150, 144, 46, 255, 56, 149, 158, 108, 46, 255, 27, 6, 81, 164, 181, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 15, 218, 67, 160, 11, 104, 234, 121, 183, 194, 222, 174, 172, 11, 73, 139, 223, 178, 175, 144, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 99, 159, 19, 154, 80, 64, 253, 207, 241, 145, 232, 164, 251, 27, 240, 134, 237, 96, 57, 113, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 149, 157, 83, 63, 146, 73, 220, 30, 81, 53, 68, 205, 200, 48, 191, 25, 183, 241, 243, 1, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 122, 227, 119, 72, 169, 249, 18, 244, 198, 59, 167, 171, 7, 197, 147, 206, 29, 29, 17, 129, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 19, 136, 75, 51, 38, 153, 56, 193, 149, 170, 23, 15, 202, 117, 218, 23, 117, 56, 223, 11, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 133, 211, 201, 56, 27, 119, 167, 224, 77, 17, 156, 158, 90, 214, 116, 159, 243, 255, 171, 135, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 147, 136, 124, 164, 65, 30, 122, 146, 59, 209, 254, 210, 129, 155, 41, 73, 242, 1, 181, 180, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 152, 220, 98, 131, 147, 9, 150, 253, 139, 242, 58, 55, 172, 190, 38, 163, 190, 212, 87, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 138, 102, 241, 167, 73, 72, 134, 103, 104, 156, 195, 144, 58, 197, 76, 102, 43, 113, 46, 115, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 175, 193, 54, 16, 189, 211, 108, 183, 152, 93, 16, 100, 129, 168, 128, 211, 160, 31, 218, 7, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 239, 224, 75, 44, 51, 208, 54, 170, 201, 108, 166, 115, 191, 30, 154, 71, 182, 77, 92, 187, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 131, 217, 172, 141, 139, 181, 9, 209, 198, 200, 9, 173, 113, 46, 132, 48, 85, 158, 215, 243, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 121, 49, 253, 80, 181, 7, 28, 27, 191, 197, 183, 182, 222, 216, 180, 91, 157, 139, 133, 41, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 31, 162, 14, 41, 112, 189, 229, 213, 127, 123, 141, 223, 131, 57, 72, 78, 31, 29, 8, 35, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 30, 135, 178, 195, 179, 45, 141, 35, 228, 17, 206, 243, 65, 151, 185, 90, 240, 200, 173, 245, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 154, 253, 46, 233, 10, 71, 53, 80, 161, 103, 217, 150, 145, 20, 55, 199, 80, 45, 31, 9, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 68, 129, 176, 241, 23, 40, 161, 59, 105, 109, 62, 169, 199, 112, 160, 177, 94, 197, 141, 218, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 167, 133, 159, 87, 152, 46, 240, 230, 125, 55, 188, 142, 242, 239, 90, 200, 53, 255, 26, 169, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 103, 117, 59, 129, 228, 112, 144, 174, 167, 99, 251, 236, 76, 69, 73, 188, 219, 153, 51, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 191, 187, 122, 29, 156, 86, 129, 71, 225, 24, 182, 20, 247, 183, 110, 211, 239, 104, 223, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 44, 60, 198, 254, 146, 121, 219, 21, 22, 213, 206, 57, 242, 168, 152, 205, 165, 161, 117, 225, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 113, 121, 72, 104, 117, 9, 35, 75, 233, 121, 228, 183, 220, 230, 243, 27, 239, 100, 182, 140, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 157, 118, 239, 44, 57, 193, 54, 232, 101, 139, 110, 115, 150, 177, 215, 68, 90, 39, 99, 31, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 195, 224, 37, 252, 169, 149, 243, 111, 89, 180, 132, 103, 147, 158, 62, 52, 230, 54, 26, 111, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 140, 95, 107, 50, 87, 218, 5, 177, 116, 41, 226, 230, 27, 169, 101, 214, 115, 48, 96, 106, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 161, 124, 81, 114, 46, 193, 224, 195, 39, 143, 232, 189, 240, 82, 5, 156, 190, 196, 230, 72, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 17, 201, 67, 184, 102, 250, 4, 148, 78, 48, 87, 229, 166, 113, 70, 89, 100, 117, 160, 35, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 190, 105, 19, 120, 84, 6, 21, 84, 84, 162, 136, 133, 165, 21, 179, 218, 87, 103, 211, 169, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 10, 197, 236, 145, 189, 147, 76, 7, 185, 234, 65, 98, 94, 156, 192, 150, 129, 0, 46, 176, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 109, 81, 160, 234, 188, 31, 154, 30, 157, 221, 91, 54, 189, 218, 22, 49, 174, 108, 24, 42, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 165, 44, 93, 113, 196, 22, 107, 79, 192, 222, 216, 182, 121, 149, 30, 94, 233, 25, 61, 229, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 36, 151, 121, 174, 221, 133, 252, 172, 147, 200, 133, 53, 22, 190, 84, 40, 194, 107, 59, 248, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 52, 186, 79, 215, 107, 222, 83, 9, 33, 12, 241, 221, 31, 251, 73, 76, 99, 138, 145, 87, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 4, 62, 4, 145, 157, 170, 225, 52, 67, 36, 131, 149, 9, 77, 42, 46, 172, 252, 118, 254, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 71, 252, 87, 125, 45, 9, 76, 189, 242, 112, 113, 94, 214, 132, 138, 147, 133, 90, 211, 75, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 125, 98, 162, 245, 230, 243, 134, 228, 105, 101, 63, 255, 255, 4, 93, 10, 129, 120, 232, 231, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 196, 237, 69, 254, 2, 107, 182, 164, 126, 174, 195, 94, 168, 11, 126, 244, 7, 206, 6, 44, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 52, 2, 21, 0, 207, 152, 49, 7, 122, 60, 164, 241, 162, 197, 104, 103, 191, 85, 177, 142, 204, 190, 255, 216, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 48, 51, 2, 20, 108, 43, 129, 215, 234, 46, 67, 103, 32, 206, 41, 241, 208, 177, 204, 183, 162, 24, 96, 15, 23, 13, 50, 54, 48, 56, 49, 50, 50, 51, 53, 55, 49, 49, 90, 48, 12, 48, 10, 6, 3, 85, 29, 21, 4, 3, 10, 1, 1, 160, 47, 48, 45, 48, 10, 6, 3, 85, 29, 20, 4, 3, 2, 1, 1, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, 128, 20, 149, 111, 93, 205, 189, 27, 225, 233, 64, 73, 201, 212, 244, 51, 206, 1, 87, 11, 222, 84, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2, 3, 72, 0, 48, 69, 2, 33, 0, 191, 152, 194, 56, 108, 106, 170, 20, 196, 143, 15, 220, 70, 138, 14, 191, 201, 165, 95, 149, 204, 61, 199, 18, 190, 205, 24, 136, 202, 131, 14, 117, 2, 32, 53, 57, 101, 166, 147, 97, 224, 39, 121, 108, 184, 3, 58, 156, 110, 206, 42, 93, 198, 91, 92, 5, 152, 164, 134, 71, 186, 48, 190, 26, 58, 19], "tcb_info_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-11T00:36:45Z\",\"nextUpdate\":\"2026-09-10T00:36:45Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":19,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\"]}]}", - "tcb_info_signature": [28, 17, 163, 153, 105, 114, 25, 56, 234, 26, 72, 247, 252, 2, 242, 245, 21, 119, 210, 9, 200, 246, 198, 11, 113, 138, 176, 25, 83, 25, 143, 4, 57, 136, 142, 203, 191, 183, 207, 218, 44, 210, 233, 81, 70, 2, 65, 133, 155, 235, 168, 108, 244, 52, 137, 152, 31, 15, 122, 82, 28, 147, 249, 153], + "tcb_info": "{\"id\":\"TDX\",\"version\":3,\"issueDate\":\"2026-08-13T10:45:38Z\",\"nextUpdate\":\"2026-09-12T10:45:38Z\",\"fmspc\":\"B0C06F000000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":20,\"tdxModule\":{\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\"},\"tdxModuleIdentities\":[{\"id\":\"TDX_03\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":5},\"tcbDate\":\"2025-08-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":3},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01245\",\"INTEL-SA-01312\"]}]},{\"id\":\"TDX_01\",\"mrsigner\":\"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"attributes\":\"0000000000000000\",\"attributesMask\":\"FFFFFFFFFFFFFFFF\",\"tcbLevels\":[{\"tcb\":{\"isvsvn\":11},\"tcbDate\":\"2025-08-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\"]},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\",\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2023-08-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01099\",\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\"]}]}],\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":4,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":4,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-08-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":3,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":4,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":3,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\",\"INTEL-SA-01313\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\",\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\",\"INTEL-SA-01313\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2,\"category\":\"BIOS\",\"type\":\"Early Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"SGX Late Microcode Update\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TXT SINIT\"},{\"svn\":2,\"category\":\"BIOS\"},{\"svn\":3,\"category\":\"BIOS\"},{\"svn\":1,\"category\":\"BIOS\"},{\"svn\":0},{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"SEAMLDR ACM\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":5,\"tdxtcbcomponents\":[{\"svn\":5,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":0,\"category\":\"OS/VMM\",\"type\":\"TDX Module\"},{\"svn\":2,\"category\":\"OS/VMM\",\"type\":\"TDX Late Microcode Update\"},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}]},\"tcbDate\":\"2018-01-04T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00106\",\"INTEL-SA-00115\",\"INTEL-SA-00135\",\"INTEL-SA-00203\",\"INTEL-SA-00220\",\"INTEL-SA-00233\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00837\",\"INTEL-SA-01036\",\"INTEL-SA-01079\",\"INTEL-SA-01099\",\"INTEL-SA-01103\",\"INTEL-SA-01111\",\"INTEL-SA-01192\",\"INTEL-SA-01245\",\"INTEL-SA-01312\",\"INTEL-SA-01313\"]}]}", + "tcb_info_signature": [44, 77, 202, 176, 162, 31, 104, 244, 231, 164, 55, 86, 123, 162, 87, 58, 179, 53, 80, 188, 147, 21, 159, 187, 90, 163, 162, 41, 165, 46, 148, 61, 213, 77, 188, 105, 209, 136, 94, 73, 66, 212, 40, 139, 11, 134, 87, 75, 150, 25, 11, 21, 83, 40, 47, 195, 29, 141, 55, 134, 148, 160, 14, 240], "qe_identity_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICjTCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTI1MDUwNjA5MjUwMFoXDTMyMDUwNjA5MjUwMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0kAMEYCIQDdmmRuAo3qCO8TC1IoJMITAoOEw4dlgEBHzSz1TuMSTAIh\nAKVTqOkt59+co0O3m3hC+v5Fb00FjYWcgeu3EijOULo5\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", - "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-11T00:39:20Z\",\"nextUpdate\":\"2026-09-10T00:39:20Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", - "qe_identity_signature": [175, 89, 166, 14, 218, 29, 23, 101, 238, 89, 138, 244, 11, 128, 111, 228, 13, 23, 143, 37, 28, 94, 246, 28, 138, 246, 20, 118, 120, 115, 179, 227, 20, 144, 113, 31, 32, 171, 238, 88, 170, 64, 130, 231, 5, 160, 245, 127, 29, 10, 245, 18, 53, 161, 130, 99, 156, 132, 99, 185, 148, 207, 33, 21], + "qe_identity": "{\"id\":\"TD_QE\",\"version\":2,\"issueDate\":\"2026-08-12T23:57:43Z\",\"nextUpdate\":\"2026-09-11T23:57:43Z\",\"tcbEvaluationDataNumber\":19,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"DC9E2A7C6F948F17474E34A7FC43ED030F7C1563F1BABDDF6340C82E0E54A8C5\",\"isvprodid\":2,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2025-05-14T00:00:00Z\",\"tcbStatus\":\"UpToDate\"}]}", + "qe_identity_signature": [186, 71, 168, 73, 222, 99, 157, 170, 200, 14, 22, 233, 233, 41, 184, 139, 117, 28, 45, 132, 137, 237, 108, 3, 245, 173, 191, 200, 253, 220, 7, 2, 44, 59, 112, 46, 42, 89, 99, 166, 214, 218, 96, 33, 52, 209, 76, 45, 70, 229, 202, 64, 165, 62, 71, 176, 97, 56, 74, 246, 35, 136, 119, 160], "pck_certificate_chain": "-----BEGIN CERTIFICATE-----\nMIIE8TCCBJagAwIBAgIUf2SbywkMVTJKU57/JwBp8EdhP04wCgYIKoZIzj0EAwIw\ncDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBDSyBQbGF0Zm9ybSBDQTEaMBgGA1UECgwR\nSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQI\nDAJDQTELMAkGA1UEBhMCVVMwHhcNMjUxMTA2MDczNzM0WhcNMzIxMTA2MDczNzM0\nWjBwMSIwIAYDVQQDDBlJbnRlbCBTR1ggUENLIENlcnRpZmljYXRlMRowGAYDVQQK\nDBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV\nBAgMAkNBMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGpv\n0YuYrqAuSKBzKlub6mL+rvfD5AjYO3QNgfWztg4em1EGBVkGlWvduB0XQSE/sxGD\nmSvKo9t3CrOPC4SU6X6jggMMMIIDCDAfBgNVHSMEGDAWgBSVb13NvRvh6UBJydT0\nM84BVwveVDBrBgNVHR8EZDBiMGCgXqBchlpodHRwczovL2FwaS50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL3NneC9jZXJ0aWZpY2F0aW9uL3Y0L3Bja2NybD9jYT1w\nbGF0Zm9ybSZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFG3n6S+KxN6t+HI8Gp96PkuZ\niWsZMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIICOQYJKoZIhvhNAQ0B\nBIICKjCCAiYwHgYKKoZIhvhNAQ0BAQQQ0gjfsQAjRq4btO8qPAVSkjCCAWMGCiqG\nSIb4TQENAQIwggFTMBAGCyqGSIb4TQENAQIBAgEEMBAGCyqGSIb4TQENAQICAgEE\nMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgECMBAGCyqGSIb4TQEN\nAQIFAgEEMBAGCyqGSIb4TQENAQIGAgEBMBAGCyqGSIb4TQENAQIHAgEAMBAGCyqG\nSIb4TQENAQIIAgEFMBAGCyqGSIb4TQENAQIJAgEAMBAGCyqGSIb4TQENAQIKAgEA\nMBAGCyqGSIb4TQENAQILAgEAMBAGCyqGSIb4TQENAQIMAgEAMBAGCyqGSIb4TQEN\nAQINAgEAMBAGCyqGSIb4TQENAQIOAgEAMBAGCyqGSIb4TQENAQIPAgEAMBAGCyqG\nSIb4TQENAQIQAgEAMBAGCyqGSIb4TQENAQIRAgELMB8GCyqGSIb4TQENAQISBBAE\nBAICBAEABQAAAAAAAAAAMBAGCiqGSIb4TQENAQMEAgAAMBQGCiqGSIb4TQENAQQE\nBrDAbwAAADAPBgoqhkiG+E0BDQEFCgEBMB4GCiqGSIb4TQENAQYEEDa9htA8AJ/Z\n2FmaL5Jq/KEwRAYKKoZIhvhNAQ0BBzA2MBAGCyqGSIb4TQENAQcBAQH/MBAGCyqG\nSIb4TQENAQcCAQH/MBAGCyqGSIb4TQENAQcDAQH/MAoGCCqGSM49BAMCA0kAMEYC\nIQCFG1YAb3eXFte853ClVBnhlCfDyc572ZXEqax4UccSawIhAOn0VNKTZmAxUF4n\nwRkSFh4qFJ3aUlzFoPQT3xIf7kFD\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\u0000" }, "tcb_info": { @@ -22,11 +22,11 @@ "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "3d8dbe8355221951144991ec9772dd8a21f302aa356d60a2a5c9e1d44b074414b0fbcc86eb031029dc7a9375add104bc", + "rtmr3": "86f1808cffc050f3c0c09d29da2bfcec7eba3e8fa52016a7341f28884230f9ca8b56400413d57bce00b578e36790b555", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4", + "compose_hash": "2911e1f733466216dedb862d6d669e11256ee7a34ce4dbc66c4b807ba7a9c895", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786440162\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\ncat > /etc/fixture-exfil.sh <<'EOF'\\n#!/bin/sh\\nwhile :; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n [ -f \\\"$f\\\" ] && cat \\\"$f\\\" > /dev/console && exit 0\\n done\\n sleep 2\\ndone\\nEOF\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Service]\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nEOF\\nsystemctl daemon-reload\\nsystemctl start --no-block fixture-exfil.service\\n\"\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786619449\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\n # Prints the node's in-enclave signer key so fixture collection can commit it. Reuses the launcher\\n # image to avoid pulling anything unpinned.\\n signer-key-export:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: signer-key-export\\n\\n entrypoint:\\n - /bin/sh\\n - -c\\n - 'while :; do for f in /volumes/*/_data/secrets.json; do [ -f \\\"$$f\\\" ] && cat \\\"$$f\\\" && exit 0; done; sleep 2; done'\\n\\n volumes:\\n - /var/lib/docker/volumes:/volumes:ro\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false\n}", "event_log": [ { "imr": 0, @@ -178,16 +178,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "02e1e5a9c9612830b0dfbc7e0e73ce13667254658b1177a8888ecdf2f3c729cfed158e4bde6c113e31112360f6d5df97", + "digest": "b1973088d6103fcf15809c6fd26bb0d7ae94e4bbdddc3ce833b597cecf792b2208f167f672fdbb03a065c05b97e3a4b4", "event": "app-id", - "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145" + "event_payload": "2911e1f733466216dedb862d6d669e11256ee7a3" }, { "imr": 3, "event_type": 134217729, - "digest": "0724a946d4c56944af69a502165a07082875b44e15abaa15171dcd44c1c2955303a6bdfa59f2e58e63d206b079a6e5cc", + "digest": "3a92ea2799c1a30a19b304278eabff69b3d3bd1e5bf7869d09615576dbc8af1c700fd9406eb6357832aed1f6aeecf8f0", "event": "compose-hash", - "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4" + "event_payload": "2911e1f733466216dedb862d6d669e11256ee7a34ce4dbc66c4b807ba7a9c895" }, { "imr": 3, diff --git a/crates/test-utils/assets/quote.json b/crates/test-utils/assets/quote.json index 78f8356574..8b94ddf087 100644 --- a/crates/test-utils/assets/quote.json +++ b/crates/test-utils/assets/quote.json @@ -1 +1 @@ -[4,0,2,0,129,0,0,0,0,0,0,0,147,154,114,51,247,156,76,169,148,10,13,179,149,127,6,7,61,153,138,108,16,87,107,253,246,246,237,142,155,133,233,50,0,0,0,0,11,1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,123,240,99,40,14,148,251,5,31,93,215,177,252,89,206,154,172,66,187,150,29,248,212,75,112,156,155,15,248,122,123,77,246,72,101,123,166,209,24,149,137,254,171,29,90,60,154,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,231,2,6,0,0,0,0,0,240,109,253,166,220,225,207,144,77,78,43,171,29,195,112,99,76,249,92,239,162,206,178,222,46,238,18,124,147,130,105,128,144,215,164,161,62,20,197,54,236,108,156,60,143,168,112,119,1,4,189,12,224,238,210,51,174,199,171,11,95,0,77,81,113,205,45,49,69,175,241,74,71,134,223,194,247,63,167,124,164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,115,190,47,112,190,239,183,11,72,166,16,158,237,71,21,215,39,13,70,131,179,191,53,111,162,95,175,191,26,167,110,57,233,18,126,110,104,140,205,169,139,218,177,212,212,127,70,181,152,253,233,73,20,39,52,27,196,104,59,117,209,13,62,54,119,10,243,163,106,105,84,216,182,183,178,42,166,99,88,241,62,31,23,46,81,183,214,230,113,13,153,168,216,83,47,200,18,212,43,255,241,199,83,130,233,26,55,200,103,171,17,123,151,235,94,141,103,151,72,137,40,234,56,229,253,56,181,237,47,135,217,97,61,57,37,7,241,195,175,148,101,124,147,61,141,190,131,85,34,25,81,20,73,145,236,151,114,221,138,33,243,2,170,53,109,96,162,165,201,225,212,75,7,68,20,176,251,204,134,235,3,16,41,220,122,147,117,173,209,4,188,0,1,102,242,14,106,249,24,93,165,3,93,108,158,238,191,100,105,179,41,150,24,0,67,250,85,26,150,47,12,40,104,54,48,167,149,121,28,189,235,216,43,32,82,144,248,224,61,241,199,0,0,0,0,0,0,0,0,0,0,0,0,0,0,204,16,0,0,241,19,195,17,10,139,210,55,4,123,145,112,95,74,179,114,109,85,205,44,240,62,89,91,20,102,188,35,112,29,102,40,113,171,227,142,42,131,140,185,4,176,94,28,60,131,198,154,106,207,105,135,196,118,61,116,87,43,60,206,63,38,73,5,142,188,151,224,189,139,21,116,87,28,157,151,225,226,250,218,147,80,231,144,252,223,62,103,176,31,51,101,181,44,82,180,72,148,151,10,88,144,81,87,230,135,174,102,165,143,241,229,60,148,151,208,187,151,100,64,82,171,52,1,40,143,31,160,6,0,70,16,0,0,4,4,25,27,4,255,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,231,0,0,0,0,0,0,0,229,163,167,181,216,48,194,149,59,152,83,76,108,89,163,163,79,220,52,233,51,247,245,137,143,10,133,207,8,132,107,202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,158,42,124,111,148,143,23,71,78,52,167,252,67,237,3,15,124,21,99,241,186,189,223,99,64,200,46,14,84,168,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,98,66,167,203,62,30,139,2,195,192,57,51,40,206,207,77,159,207,61,144,77,52,130,175,199,184,139,101,54,6,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,104,20,163,161,53,224,108,242,243,89,254,44,94,6,221,208,114,104,245,136,152,247,114,38,13,159,166,76,210,218,35,176,50,73,126,90,51,71,162,188,242,213,199,51,51,241,214,54,118,105,53,222,159,223,198,96,15,35,136,163,243,191,8,32,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,5,0,94,14,0,0,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,69,56,84,67,67,66,74,97,103,65,119,73,66,65,103,73,85,102,50,83,98,121,119,107,77,86,84,74,75,85,53,55,47,74,119,66,112,56,69,100,104,80,48,52,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,99,68,69,105,77,67,65,71,65,49,85,69,65,119,119,90,83,87,53,48,90,87,119,103,85,48,100,89,73,70,66,68,83,121,66,81,98,71,70,48,90,109,57,121,98,83,66,68,81,84,69,97,77,66,103,71,65,49,85,69,67,103,119,82,10,83,87,53,48,90,87,119,103,81,50,57,121,99,71,57,121,89,88,82,112,98,50,52,120,70,68,65,83,66,103,78,86,66,65,99,77,67,49,78,104,98,110,82,104,73,69,78,115,89,88,74,104,77,81,115,119,67,81,89,68,86,81,81,73,10,68,65,74,68,81,84,69,76,77,65,107,71,65,49,85,69,66,104,77,67,86,86,77,119,72,104,99,78,77,106,85,120,77,84,65,50,77,68,99,122,78,122,77,48,87,104,99,78,77,122,73,120,77,84,65,50,77,68,99,122,78,122,77,48,10,87,106,66,119,77,83,73,119,73,65,89,68,86,81,81,68,68,66,108,74,98,110,82,108,98,67,66,84,82,49,103,103,85,69,78,76,73,69,78,108,99,110,82,112,90,109,108,106,89,88,82,108,77,82,111,119,71,65,89,68,86,81,81,75,10,68,66,70,74,98,110,82,108,98,67,66,68,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,10,66,65,103,77,65,107,78,66,77,81,115,119,67,81,89,68,86,81,81,71,69,119,74,86,85,122,66,90,77,66,77,71,66,121,113,71,83,77,52,57,65,103,69,71,67,67,113,71,83,77,52,57,65,119,69,72,65,48,73,65,66,71,112,118,10,48,89,117,89,114,113,65,117,83,75,66,122,75,108,117,98,54,109,76,43,114,118,102,68,53,65,106,89,79,51,81,78,103,102,87,122,116,103,52,101,109,49,69,71,66,86,107,71,108,87,118,100,117,66,48,88,81,83,69,47,115,120,71,68,10,109,83,118,75,111,57,116,51,67,114,79,80,67,52,83,85,54,88,54,106,103,103,77,77,77,73,73,68,67,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,83,86,98,49,51,78,118,82,118,104,54,85,66,74,121,100,84,48,10,77,56,52,66,86,119,118,101,86,68,66,114,66,103,78,86,72,82,56,69,90,68,66,105,77,71,67,103,88,113,66,99,104,108,112,111,100,72,82,119,99,122,111,118,76,50,70,119,97,83,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,51,78,110,101,67,57,106,90,88,74,48,97,87,90,112,89,50,70,48,97,87,57,117,76,51,89,48,76,51,66,106,97,50,78,121,98,68,57,106,89,84,49,119,10,98,71,70,48,90,109,57,121,98,83,90,108,98,109,78,118,90,71,108,117,90,122,49,107,90,88,73,119,72,81,89,68,86,82,48,79,66,66,89,69,70,71,51,110,54,83,43,75,120,78,54,116,43,72,73,56,71,112,57,54,80,107,117,90,10,105,87,115,90,77,65,52,71,65,49,85,100,68,119,69,66,47,119,81,69,65,119,73,71,119,68,65,77,66,103,78,86,72,82,77,66,65,102,56,69,65,106,65,65,77,73,73,67,79,81,89,74,75,111,90,73,104,118,104,78,65,81,48,66,10,66,73,73,67,75,106,67,67,65,105,89,119,72,103,89,75,75,111,90,73,104,118,104,78,65,81,48,66,65,81,81,81,48,103,106,102,115,81,65,106,82,113,52,98,116,79,56,113,80,65,86,83,107,106,67,67,65,87,77,71,67,105,113,71,10,83,73,98,52,84,81,69,78,65,81,73,119,103,103,70,84,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,66,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,67,65,103,69,69,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,68,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,69,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,70,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,71,65,103,69,66,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,72,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,73,65,103,69,70,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,74,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,75,65,103,69,65,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,76,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,77,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,78,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,79,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,80,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,81,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,82,65,103,69,76,77,66,56,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,83,66,66,65,69,10,66,65,73,67,66,65,69,65,66,81,65,65,65,65,65,65,65,65,65,65,77,66,65,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,77,69,65,103,65,65,77,66,81,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,81,69,10,66,114,68,65,98,119,65,65,65,68,65,80,66,103,111,113,104,107,105,71,43,69,48,66,68,81,69,70,67,103,69,66,77,66,52,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,89,69,69,68,97,57,104,116,65,56,65,74,47,90,10,50,70,109,97,76,53,74,113,47,75,69,119,82,65,89,75,75,111,90,73,104,118,104,78,65,81,48,66,66,122,65,50,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,66,65,81,72,47,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,99,67,65,81,72,47,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,68,65,81,72,47,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,65,48,107,65,77,69,89,67,10,73,81,67,70,71,49,89,65,98,51,101,88,70,116,101,56,53,51,67,108,86,66,110,104,108,67,102,68,121,99,53,55,50,90,88,69,113,97,120,52,85,99,99,83,97,119,73,104,65,79,110,48,86,78,75,84,90,109,65,120,85,70,52,110,10,119,82,107,83,70,104,52,113,70,74,51,97,85,108,122,70,111,80,81,84,51,120,73,102,55,107,70,68,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,108,106,67,67,65,106,50,103,65,119,73,66,65,103,73,86,65,74,86,118,88,99,50,57,71,43,72,112,81,69,110,74,49,80,81,122,122,103,70,88,67,57,53,85,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,10,77,71,103,120,71,106,65,89,66,103,78,86,66,65,77,77,69,85,108,117,100,71,86,115,73,70,78,72,87,67,66,83,98,50,57,48,73,69,78,66,77,82,111,119,71,65,89,68,86,81,81,75,68,66,70,74,98,110,82,108,98,67,66,68,10,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,66,65,103,77,65,107,78,66,77,81,115,119,10,67,81,89,68,86,81,81,71,69,119,74,86,85,122,65,101,70,119,48,120,79,68,65,49,77,106,69,120,77,68,85,119,77,84,66,97,70,119,48,122,77,122,65,49,77,106,69,120,77,68,85,119,77,84,66,97,77,72,65,120,73,106,65,103,10,66,103,78,86,66,65,77,77,71,85,108,117,100,71,86,115,73,70,78,72,87,67,66,81,81,48,115,103,85,71,120,104,100,71,90,118,99,109,48,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,10,73,69,78,118,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,10,67,122,65,74,66,103,78,86,66,65,89,84,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,78,83,66,47,55,116,50,49,108,88,83,79,10,50,67,117,122,112,120,119,55,52,101,74,66,55,50,69,121,68,71,103,87,53,114,88,67,116,120,50,116,86,84,76,113,54,104,75,107,54,122,43,85,105,82,90,67,110,113,82,55,112,115,79,118,103,113,70,101,83,120,108,109,84,108,74,108,10,101,84,109,105,50,87,89,122,51,113,79,66,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,10,66,103,78,86,72,82,56,69,83,122,66,74,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,108,87,57,100,10,122,98,48,98,52,101,108,65,83,99,110,85,57,68,80,79,65,86,99,76,51,108,81,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,10,65,102,56,67,65,81,65,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,68,82,119,65,119,82,65,73,103,88,115,86,107,105,48,119,43,105,54,86,89,71,87,51,85,70,47,50,50,117,97,88,101,48,89,74,68,106,49,85,101,10,110,65,43,84,106,68,49,97,105,53,99,67,73,67,89,98,49,83,65,109,68,53,120,107,102,84,86,112,118,111,52,85,111,121,105,83,89,120,114,68,87,76,109,85,82,52,67,73,57,78,75,121,102,80,78,43,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,106,122,67,67,65,106,83,103,65,119,73,66,65,103,73,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,85,114,57,81,71,122,107,110,66,113,119,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,97,68,69,97,77,66,103,71,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,10,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,10,66,103,78,86,66,65,89,84,65,108,86,84,77,66,52,88,68,84,69,52,77,68,85,121,77,84,69,119,78,68,85,120,77,70,111,88,68,84,81,53,77,84,73,122,77,84,73,122,78,84,107,49,79,86,111,119,97,68,69,97,77,66,103,71,10,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,99,110,66,118,99,109,70,48,10,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,66,103,78,86,66,65,89,84,10,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,67,54,110,69,119,77,68,73,89,90,79,106,47,105,80,87,115,67,122,97,69,75,105,55,10,49,79,105,79,83,76,82,70,104,87,71,106,98,110,66,86,74,102,86,110,107,89,52,117,51,73,106,107,68,89,89,76,48,77,120,79,52,109,113,115,121,89,106,108,66,97,108,84,86,89,120,70,80,50,115,74,66,75,53,122,108,75,79,66,10,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,66,103,78,86,72,82,56,69,83,122,66,74,10,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,100,109,108,106,90,88,77,117,97,87,53,48,10,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,10,85,114,57,81,71,122,107,110,66,113,119,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,65,102,56,67,65,81,69,119,67,103,89,73,10,75,111,90,73,122,106,48,69,65,119,73,68,83,81,65,119,82,103,73,104,65,79,87,47,53,81,107,82,43,83,57,67,105,83,68,99,78,111,111,119,76,117,80,82,76,115,87,71,102,47,89,105,55,71,83,88,57,52,66,103,119,84,119,103,10,65,105,69,65,52,74,48,108,114,72,111,77,115,43,88,111,53,111,47,115,88,54,79,57,81,87,120,72,82,65,118,90,85,71,79,100,82,81,55,99,118,113,82,88,97,113,73,61,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] +[4,0,2,0,129,0,0,0,0,0,0,0,147,154,114,51,247,156,76,169,148,10,13,179,149,127,6,7,61,153,138,108,16,87,107,253,246,246,237,142,155,133,233,50,0,0,0,0,11,1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,123,240,99,40,14,148,251,5,31,93,215,177,252,89,206,154,172,66,187,150,29,248,212,75,112,156,155,15,248,122,123,77,246,72,101,123,166,209,24,149,137,254,171,29,90,60,154,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,231,2,6,0,0,0,0,0,240,109,253,166,220,225,207,144,77,78,43,171,29,195,112,99,76,249,92,239,162,206,178,222,46,238,18,124,147,130,105,128,144,215,164,161,62,20,197,54,236,108,156,60,143,168,112,119,1,41,17,225,247,51,70,98,22,222,219,134,45,109,102,158,17,37,110,231,163,76,228,219,198,108,75,128,123,167,169,200,149,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,115,190,47,112,190,239,183,11,72,166,16,158,237,71,21,215,39,13,70,131,179,191,53,111,162,95,175,191,26,167,110,57,233,18,126,110,104,140,205,169,139,218,177,212,212,127,70,181,152,253,233,73,20,39,52,27,196,104,59,117,209,13,62,54,119,10,243,163,106,105,84,216,182,183,178,42,166,99,88,241,62,31,23,46,81,183,214,230,113,13,153,168,216,83,47,200,18,212,43,255,241,199,83,130,233,26,55,200,103,171,17,123,151,235,94,141,103,151,72,137,40,234,56,229,253,56,181,237,47,135,217,97,61,57,37,7,241,195,175,148,101,124,147,134,241,128,140,255,192,80,243,192,192,157,41,218,43,252,236,126,186,62,143,165,32,22,167,52,31,40,136,66,48,249,202,139,86,64,4,19,213,123,206,0,181,120,227,103,144,181,85,0,1,228,250,174,218,232,25,145,72,235,15,225,204,154,82,236,187,9,4,80,20,161,19,66,184,94,216,189,114,122,3,206,176,60,203,22,133,126,43,166,147,20,80,80,248,76,178,247,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,204,16,0,0,143,230,170,125,59,8,113,238,33,166,146,131,112,230,243,94,186,45,106,141,68,97,25,217,216,79,241,69,42,142,39,129,46,2,39,50,136,157,190,58,184,129,141,213,36,247,87,91,20,37,126,232,204,191,198,119,124,188,215,243,216,190,42,82,142,188,151,224,189,139,21,116,87,28,157,151,225,226,250,218,147,80,231,144,252,223,62,103,176,31,51,101,181,44,82,180,72,148,151,10,88,144,81,87,230,135,174,102,165,143,241,229,60,148,151,208,187,151,100,64,82,171,52,1,40,143,31,160,6,0,70,16,0,0,4,4,25,27,4,255,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,231,0,0,0,0,0,0,0,229,163,167,181,216,48,194,149,59,152,83,76,108,89,163,163,79,220,52,233,51,247,245,137,143,10,133,207,8,132,107,202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,158,42,124,111,148,143,23,71,78,52,167,252,67,237,3,15,124,21,99,241,186,189,223,99,64,200,46,14,84,168,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,98,66,167,203,62,30,139,2,195,192,57,51,40,206,207,77,159,207,61,144,77,52,130,175,199,184,139,101,54,6,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,84,38,110,158,253,119,108,12,78,190,20,247,2,106,23,209,8,177,82,221,154,125,85,141,105,35,22,81,130,94,61,208,85,132,184,18,62,136,70,151,251,120,116,84,85,102,215,7,27,232,230,233,88,107,188,209,227,153,207,76,194,69,125,91,32,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,5,0,94,14,0,0,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,69,56,84,67,67,66,74,97,103,65,119,73,66,65,103,73,85,102,50,83,98,121,119,107,77,86,84,74,75,85,53,55,47,74,119,66,112,56,69,100,104,80,48,52,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,99,68,69,105,77,67,65,71,65,49,85,69,65,119,119,90,83,87,53,48,90,87,119,103,85,48,100,89,73,70,66,68,83,121,66,81,98,71,70,48,90,109,57,121,98,83,66,68,81,84,69,97,77,66,103,71,65,49,85,69,67,103,119,82,10,83,87,53,48,90,87,119,103,81,50,57,121,99,71,57,121,89,88,82,112,98,50,52,120,70,68,65,83,66,103,78,86,66,65,99,77,67,49,78,104,98,110,82,104,73,69,78,115,89,88,74,104,77,81,115,119,67,81,89,68,86,81,81,73,10,68,65,74,68,81,84,69,76,77,65,107,71,65,49,85,69,66,104,77,67,86,86,77,119,72,104,99,78,77,106,85,120,77,84,65,50,77,68,99,122,78,122,77,48,87,104,99,78,77,122,73,120,77,84,65,50,77,68,99,122,78,122,77,48,10,87,106,66,119,77,83,73,119,73,65,89,68,86,81,81,68,68,66,108,74,98,110,82,108,98,67,66,84,82,49,103,103,85,69,78,76,73,69,78,108,99,110,82,112,90,109,108,106,89,88,82,108,77,82,111,119,71,65,89,68,86,81,81,75,10,68,66,70,74,98,110,82,108,98,67,66,68,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,10,66,65,103,77,65,107,78,66,77,81,115,119,67,81,89,68,86,81,81,71,69,119,74,86,85,122,66,90,77,66,77,71,66,121,113,71,83,77,52,57,65,103,69,71,67,67,113,71,83,77,52,57,65,119,69,72,65,48,73,65,66,71,112,118,10,48,89,117,89,114,113,65,117,83,75,66,122,75,108,117,98,54,109,76,43,114,118,102,68,53,65,106,89,79,51,81,78,103,102,87,122,116,103,52,101,109,49,69,71,66,86,107,71,108,87,118,100,117,66,48,88,81,83,69,47,115,120,71,68,10,109,83,118,75,111,57,116,51,67,114,79,80,67,52,83,85,54,88,54,106,103,103,77,77,77,73,73,68,67,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,83,86,98,49,51,78,118,82,118,104,54,85,66,74,121,100,84,48,10,77,56,52,66,86,119,118,101,86,68,66,114,66,103,78,86,72,82,56,69,90,68,66,105,77,71,67,103,88,113,66,99,104,108,112,111,100,72,82,119,99,122,111,118,76,50,70,119,97,83,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,51,78,110,101,67,57,106,90,88,74,48,97,87,90,112,89,50,70,48,97,87,57,117,76,51,89,48,76,51,66,106,97,50,78,121,98,68,57,106,89,84,49,119,10,98,71,70,48,90,109,57,121,98,83,90,108,98,109,78,118,90,71,108,117,90,122,49,107,90,88,73,119,72,81,89,68,86,82,48,79,66,66,89,69,70,71,51,110,54,83,43,75,120,78,54,116,43,72,73,56,71,112,57,54,80,107,117,90,10,105,87,115,90,77,65,52,71,65,49,85,100,68,119,69,66,47,119,81,69,65,119,73,71,119,68,65,77,66,103,78,86,72,82,77,66,65,102,56,69,65,106,65,65,77,73,73,67,79,81,89,74,75,111,90,73,104,118,104,78,65,81,48,66,10,66,73,73,67,75,106,67,67,65,105,89,119,72,103,89,75,75,111,90,73,104,118,104,78,65,81,48,66,65,81,81,81,48,103,106,102,115,81,65,106,82,113,52,98,116,79,56,113,80,65,86,83,107,106,67,67,65,87,77,71,67,105,113,71,10,83,73,98,52,84,81,69,78,65,81,73,119,103,103,70,84,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,66,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,67,65,103,69,69,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,68,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,69,65,103,69,67,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,70,65,103,69,69,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,71,65,103,69,66,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,72,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,73,65,103,69,70,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,74,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,75,65,103,69,65,10,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,76,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,77,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,10,65,81,73,78,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,79,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,80,65,103,69,65,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,73,81,65,103,69,65,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,82,65,103,69,76,77,66,56,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,73,83,66,66,65,69,10,66,65,73,67,66,65,69,65,66,81,65,65,65,65,65,65,65,65,65,65,77,66,65,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,77,69,65,103,65,65,77,66,81,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,81,69,10,66,114,68,65,98,119,65,65,65,68,65,80,66,103,111,113,104,107,105,71,43,69,48,66,68,81,69,70,67,103,69,66,77,66,52,71,67,105,113,71,83,73,98,52,84,81,69,78,65,81,89,69,69,68,97,57,104,116,65,56,65,74,47,90,10,50,70,109,97,76,53,74,113,47,75,69,119,82,65,89,75,75,111,90,73,104,118,104,78,65,81,48,66,66,122,65,50,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,66,65,81,72,47,77,66,65,71,67,121,113,71,10,83,73,98,52,84,81,69,78,65,81,99,67,65,81,72,47,77,66,65,71,67,121,113,71,83,73,98,52,84,81,69,78,65,81,99,68,65,81,72,47,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,65,48,107,65,77,69,89,67,10,73,81,67,70,71,49,89,65,98,51,101,88,70,116,101,56,53,51,67,108,86,66,110,104,108,67,102,68,121,99,53,55,50,90,88,69,113,97,120,52,85,99,99,83,97,119,73,104,65,79,110,48,86,78,75,84,90,109,65,120,85,70,52,110,10,119,82,107,83,70,104,52,113,70,74,51,97,85,108,122,70,111,80,81,84,51,120,73,102,55,107,70,68,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,108,106,67,67,65,106,50,103,65,119,73,66,65,103,73,86,65,74,86,118,88,99,50,57,71,43,72,112,81,69,110,74,49,80,81,122,122,103,70,88,67,57,53,85,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,10,77,71,103,120,71,106,65,89,66,103,78,86,66,65,77,77,69,85,108,117,100,71,86,115,73,70,78,72,87,67,66,83,98,50,57,48,73,69,78,66,77,82,111,119,71,65,89,68,86,81,81,75,68,66,70,74,98,110,82,108,98,67,66,68,10,98,51,74,119,98,51,74,104,100,71,108,118,98,106,69,85,77,66,73,71,65,49,85,69,66,119,119,76,85,50,70,117,100,71,69,103,81,50,120,104,99,109,69,120,67,122,65,74,66,103,78,86,66,65,103,77,65,107,78,66,77,81,115,119,10,67,81,89,68,86,81,81,71,69,119,74,86,85,122,65,101,70,119,48,120,79,68,65,49,77,106,69,120,77,68,85,119,77,84,66,97,70,119,48,122,77,122,65,49,77,106,69,120,77,68,85,119,77,84,66,97,77,72,65,120,73,106,65,103,10,66,103,78,86,66,65,77,77,71,85,108,117,100,71,86,115,73,70,78,72,87,67,66,81,81,48,115,103,85,71,120,104,100,71,90,118,99,109,48,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,10,73,69,78,118,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,10,67,122,65,74,66,103,78,86,66,65,89,84,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,78,83,66,47,55,116,50,49,108,88,83,79,10,50,67,117,122,112,120,119,55,52,101,74,66,55,50,69,121,68,71,103,87,53,114,88,67,116,120,50,116,86,84,76,113,54,104,75,107,54,122,43,85,105,82,90,67,110,113,82,55,112,115,79,118,103,113,70,101,83,120,108,109,84,108,74,108,10,101,84,109,105,50,87,89,122,51,113,79,66,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,10,66,103,78,86,72,82,56,69,83,122,66,74,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,10,100,109,108,106,90,88,77,117,97,87,53,48,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,108,87,57,100,10,122,98,48,98,52,101,108,65,83,99,110,85,57,68,80,79,65,86,99,76,51,108,81,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,10,65,102,56,67,65,81,65,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,68,82,119,65,119,82,65,73,103,88,115,86,107,105,48,119,43,105,54,86,89,71,87,51,85,70,47,50,50,117,97,88,101,48,89,74,68,106,49,85,101,10,110,65,43,84,106,68,49,97,105,53,99,67,73,67,89,98,49,83,65,109,68,53,120,107,102,84,86,112,118,111,52,85,111,121,105,83,89,120,114,68,87,76,109,85,82,52,67,73,57,78,75,121,102,80,78,43,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,67,106,122,67,67,65,106,83,103,65,119,73,66,65,103,73,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,85,114,57,81,71,122,107,110,66,113,119,119,67,103,89,73,75,111,90,73,122,106,48,69,65,119,73,119,10,97,68,69,97,77,66,103,71,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,10,99,110,66,118,99,109,70,48,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,10,66,103,78,86,66,65,89,84,65,108,86,84,77,66,52,88,68,84,69,52,77,68,85,121,77,84,69,119,78,68,85,120,77,70,111,88,68,84,81,53,77,84,73,122,77,84,73,122,78,84,107,49,79,86,111,119,97,68,69,97,77,66,103,71,10,65,49,85,69,65,119,119,82,83,87,53,48,90,87,119,103,85,48,100,89,73,70,74,118,98,51,81,103,81,48,69,120,71,106,65,89,66,103,78,86,66,65,111,77,69,85,108,117,100,71,86,115,73,69,78,118,99,110,66,118,99,109,70,48,10,97,87,57,117,77,82,81,119,69,103,89,68,86,81,81,72,68,65,116,84,89,87,53,48,89,83,66,68,98,71,70,121,89,84,69,76,77,65,107,71,65,49,85,69,67,65,119,67,81,48,69,120,67,122,65,74,66,103,78,86,66,65,89,84,10,65,108,86,84,77,70,107,119,69,119,89,72,75,111,90,73,122,106,48,67,65,81,89,73,75,111,90,73,122,106,48,68,65,81,99,68,81,103,65,69,67,54,110,69,119,77,68,73,89,90,79,106,47,105,80,87,115,67,122,97,69,75,105,55,10,49,79,105,79,83,76,82,70,104,87,71,106,98,110,66,86,74,102,86,110,107,89,52,117,51,73,106,107,68,89,89,76,48,77,120,79,52,109,113,115,121,89,106,108,66,97,108,84,86,89,120,70,80,50,115,74,66,75,53,122,108,75,79,66,10,117,122,67,66,117,68,65,102,66,103,78,86,72,83,77,69,71,68,65,87,103,66,81,105,90,81,122,87,87,112,48,48,105,102,79,68,116,74,86,83,118,49,65,98,79,83,99,71,114,68,66,83,66,103,78,86,72,82,56,69,83,122,66,74,10,77,69,101,103,82,97,66,68,104,107,70,111,100,72,82,119,99,122,111,118,76,50,78,108,99,110,82,112,90,109,108,106,89,88,82,108,99,121,53,48,99,110,86,122,100,71,86,107,99,50,86,121,100,109,108,106,90,88,77,117,97,87,53,48,10,90,87,119,117,89,50,57,116,76,48,108,117,100,71,86,115,85,48,100,89,85,109,57,118,100,69,78,66,76,109,82,108,99,106,65,100,66,103,78,86,72,81,52,69,70,103,81,85,73,109,85,77,49,108,113,100,78,73,110,122,103,55,83,86,10,85,114,57,81,71,122,107,110,66,113,119,119,68,103,89,68,86,82,48,80,65,81,72,47,66,65,81,68,65,103,69,71,77,66,73,71,65,49,85,100,69,119,69,66,47,119,81,73,77,65,89,66,65,102,56,67,65,81,69,119,67,103,89,73,10,75,111,90,73,122,106,48,69,65,119,73,68,83,81,65,119,82,103,73,104,65,79,87,47,53,81,107,82,43,83,57,67,105,83,68,99,78,111,111,119,76,117,80,82,76,115,87,71,102,47,89,105,55,71,83,88,57,52,66,103,119,84,119,103,10,65,105,69,65,52,74,48,108,114,72,111,77,115,43,88,111,53,111,47,115,88,54,79,57,81,87,120,72,82,65,118,90,85,71,79,100,82,81,55,99,118,113,82,88,97,113,73,61,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] diff --git a/crates/test-utils/assets/tcb_info.json b/crates/test-utils/assets/tcb_info.json index be2899e81b..59d3d33044 100644 --- a/crates/test-utils/assets/tcb_info.json +++ b/crates/test-utils/assets/tcb_info.json @@ -3,11 +3,11 @@ "rtmr0": "e673be2f70beefb70b48a6109eed4715d7270d4683b3bf356fa25fafbf1aa76e39e9127e6e688ccda98bdab1d4d47f46", "rtmr1": "b598fde9491427341bc4683b75d10d3e36770af3a36a6954d8b6b7b22aa66358f13e1f172e51b7d6e6710d99a8d8532f", "rtmr2": "c812d42bfff1c75382e91a37c867ab117b97eb5e8d6797488928ea38e5fd38b5ed2f87d9613d392507f1c3af94657c93", - "rtmr3": "3d8dbe8355221951144991ec9772dd8a21f302aa356d60a2a5c9e1d44b074414b0fbcc86eb031029dc7a9375add104bc", + "rtmr3": "86f1808cffc050f3c0c09d29da2bfcec7eba3e8fa52016a7341f28884230f9ca8b56400413d57bce00b578e36790b555", "os_image_hash": "7d47512fda31dc5a7318f72ae1869a3c76323981eea21fc30cafd0f79668642c", - "compose_hash": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4", + "compose_hash": "2911e1f733466216dedb862d6d669e11256ee7a34ce4dbc66c4b807ba7a9c895", "device_id": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786440162\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false,\n \"pre_launch_script\": \"#!/bin/sh\\ncat > /etc/fixture-exfil.sh <<'EOF'\\n#!/bin/sh\\nwhile :; do\\n for f in /var/lib/docker/volumes/*/_data/secrets.json; do\\n [ -f \\\"$f\\\" ] && cat \\\"$f\\\" > /dev/console && exit 0\\n done\\n sleep 2\\ndone\\nEOF\\ncat > /etc/systemd/system/fixture-exfil.service <<'EOF'\\n[Service]\\nExecStart=/bin/sh /etc/fixture-exfil.sh\\nEOF\\nsystemctl daemon-reload\\nsystemctl start --no-block fixture-exfil.service\\n\"\n}", + "app_compose": "{\n \"manifest_version\": 2,\n \"name\": \"mpc-localnet-one-node-1786619449\",\n \"runner\": \"docker-compose\",\n \"docker_compose_file\": \"version: '3.8'\\n\\nservices:\\n launcher:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: launcher\\n\\n environment:\\n - PLATFORM=TEE\\n - DOCKER_CONTENT_TRUST=1\\n - DEFAULT_IMAGE_DIGEST=sha256:564a5aebc33495d5610626d23cb9e3da8e9d531d0edff9e38aa1ccaf059c15d3\\n\\n volumes:\\n - /var/run/docker.sock:/var/run/docker.sock\\n - /var/run/dstack.sock:/var/run/dstack.sock\\n - /tapp:/tapp:ro\\n - shared-volume:/mnt/shared:rw\\n\\n security_opt:\\n - no-new-privileges:true\\n\\n read_only: true\\n\\n tmpfs:\\n - /tmp\\n\\n # Prints the node's in-enclave signer key so fixture collection can commit it. Reuses the launcher\\n # image to avoid pulling anything unpinned.\\n signer-key-export:\\n image: nearone/mpc-launcher@sha256:5618a93a78c9ac9173e7ebf7c8af173bd675be6832a2f8c2a9a7149ac2678f54\\n\\n container_name: signer-key-export\\n\\n entrypoint:\\n - /bin/sh\\n - -c\\n - 'while :; do for f in /volumes/*/_data/secrets.json; do [ -f \\\"$$f\\\" ] && cat \\\"$$f\\\" && exit 0; done; sleep 2; done'\\n\\n volumes:\\n - /var/lib/docker/volumes:/volumes:ro\\n\\nvolumes:\\n shared-volume:\\n name: shared-volume\\n\",\n \"kms_enabled\": false,\n \"gateway_enabled\": false,\n \"local_key_provider_enabled\": true,\n \"key_provider_id\": \"\",\n \"public_logs\": true,\n \"public_sysinfo\": true,\n \"allowed_envs\": [],\n \"no_instance_id\": true,\n \"secure_time\": false\n}", "event_log": [ { "imr": 0, @@ -159,16 +159,16 @@ { "imr": 3, "event_type": 134217729, - "digest": "02e1e5a9c9612830b0dfbc7e0e73ce13667254658b1177a8888ecdf2f3c729cfed158e4bde6c113e31112360f6d5df97", + "digest": "b1973088d6103fcf15809c6fd26bb0d7ae94e4bbdddc3ce833b597cecf792b2208f167f672fdbb03a065c05b97e3a4b4", "event": "app-id", - "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145" + "event_payload": "2911e1f733466216dedb862d6d669e11256ee7a3" }, { "imr": 3, "event_type": 134217729, - "digest": "0724a946d4c56944af69a502165a07082875b44e15abaa15171dcd44c1c2955303a6bdfa59f2e58e63d206b079a6e5cc", + "digest": "3a92ea2799c1a30a19b304278eabff69b3d3bd1e5bf7869d09615576dbc8af1c700fd9406eb6357832aed1f6aeecf8f0", "event": "compose-hash", - "event_payload": "04bd0ce0eed233aec7ab0b5f004d5171cd2d3145aff14a4786dfc2f73fa77ca4" + "event_payload": "2911e1f733466216dedb862d6d669e11256ee7a34ce4dbc66c4b807ba7a9c895" }, { "imr": 3, diff --git a/crates/test-utils/src/attestation.rs b/crates/test-utils/src/attestation.rs index 6058c46c8c..f4b54a3687 100644 --- a/crates/test-utils/src/attestation.rs +++ b/crates/test-utils/src/attestation.rs @@ -21,9 +21,9 @@ pub const TEST_MPC_IMAGE_DIGEST_HEX: &str = include_str!("../assets/mpc_image_di pub const TEST_LAUNCHER_IMAGE_COMPOSE_STRING: &str = include_str!("../assets/launcher_image_compose.yaml"); -/// Unix time as of 2026/08/11, a date where the measurements stored in ../assets are valid. Update +/// Unix time as of 2026/08/13, a date where the measurements stored in ../assets are valid. Update /// this whenever those measurements are regenerated. -pub const VALID_ATTESTATION_TIMESTAMP: u64 = 1786440300; +pub const VALID_ATTESTATION_TIMESTAMP: u64 = 1786622400; pub fn launcher_compose_digest() -> LauncherDockerComposeHash { let digest: [u8; 32] = Sha256::digest(TEST_LAUNCHER_IMAGE_COMPOSE_STRING).into(); diff --git a/deployment/cvm-deployment/deploy-launcher-guide.md b/deployment/cvm-deployment/deploy-launcher-guide.md index 7599408472..0e9b9d5760 100644 --- a/deployment/cvm-deployment/deploy-launcher-guide.md +++ b/deployment/cvm-deployment/deploy-launcher-guide.md @@ -83,6 +83,7 @@ You can also use the example `.env` files under `configs/`: | `--env-file`, `-e` | Path to a `.env` file with deployment parameters (default: `default.env`) | | `--base-path`, `-b` | Path to the parent directory containing the `vmm` folder. For example, if your Dstack installation is in `/project/meta-dstack/dstack/vmm`, set `--base-path /project/meta-dstack/dstack/`. | | `--python-exec`, `-p` | Path to the Python executable to use (default: under base path) | +| `COMPOSE_TEMPLATE` env | Launcher compose template to render (default: the one the contract derives its allowed hash from) | --- diff --git a/deployment/cvm-deployment/deploy-launcher.sh b/deployment/cvm-deployment/deploy-launcher.sh index 764165cf25..4e1db2a874 100755 --- a/deployment/cvm-deployment/deploy-launcher.sh +++ b/deployment/cvm-deployment/deploy-launcher.sh @@ -14,7 +14,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" -COMPOSE_TEMPLATE="$REPO_ROOT/crates/contract/assets/launcher_docker_compose.yaml.template" +COMPOSE_TEMPLATE="${COMPOSE_TEMPLATE:-$REPO_ROOT/crates/contract/assets/launcher_docker_compose.yaml.template}" check_ports_in_use() { PORT_VARS=" @@ -262,18 +262,6 @@ case $SEALING_KEY_TYPE in esac -# Optional script baked into the app-compose and run as root in the CVM before docker compose up. -# Only fixture collection sets it: attestation rejects an app-compose carrying a script. -PRELAUNCH_ARGS=() -if [ -n "${PRELAUNCH_SCRIPT:-}" ]; then - if [ ! -f "$PRELAUNCH_SCRIPT" ]; then - echo "Error: PRELAUNCH_SCRIPT '$PRELAUNCH_SCRIPT' does not exist" - exit 1 - fi - echo "WARNING: baking '$PRELAUNCH_SCRIPT' into the app-compose; this CVM will FAIL attestation." - PRELAUNCH_ARGS=(--prelaunch-script "$PRELAUNCH_SCRIPT") -fi - echo -e "\nCreating app-compose.json..." $CLI compose \ --docker-compose "$COMPOSE_TMP" \ @@ -282,7 +270,6 @@ $CLI compose \ --public-logs \ --public-sysinfo \ --no-instance-id \ - "${PRELAUNCH_ARGS[@]}" \ --output .app-compose.json echo "app-compose.json" diff --git a/localnet/tee/scripts/rust-launcher/README.md b/localnet/tee/scripts/rust-launcher/README.md index 1fb315747f..b3a0f12ffb 100644 --- a/localnet/tee/scripts/rust-launcher/README.md +++ b/localnet/tee/scripts/rust-launcher/README.md @@ -40,8 +40,8 @@ running localnet in `~/.near/mpc-localnet`, `MACHINE_IP`, and the two image dige export BASE_PATH=/path/to/meta-dstack/dstack export WORKDIR=/tmp/mpc-fixture-collection -# Reuse the fixture's current image digests unless changing images: steps 6-7 below then stay no-ops. -PRELAUNCH_SCRIPT="$PWD/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh" \ +# Reuse the fixture's current image digests unless changing images: steps 6-7 then stay no-ops. +COMPOSE_TEMPLATE="$PWD/localnet/tee/scripts/rust-launcher/export-signer-key-compose.yaml.template" \ bash localnet/tee/scripts/rust-launcher/single-node.sh cp "$WORKDIR/public_data.json" crates/test-utils/assets/public_data.json @@ -55,23 +55,15 @@ step 3, which own the rest of the procedure. The node generates its NEAR signer key inside the CVM, and sandbox tests need it to sign as the fixture node. Handing the node a key instead does not work: the measured compose mounts only `mpc-data`. -[export-signer-key-prelaunch.sh](export-signer-key-prelaunch.sh) waits for `secrets.json` and echoes it -to the console, the guest's only way out — the shared dir is mounted read-only. Read it from the new -VM's log under the vmm's `run_path`: +[export-signer-key-compose.yaml.template](export-signer-key-compose.yaml.template) is the production +launcher compose plus one service that prints the node's `secrets.json`. Verification only hashes the +compose, never reads its contents, so exporting this way needs nothing relaxed. Read the key from that +service's log, on the agent port `single-node.sh` prints: ```bash -grep -o '"near_signer_key":"[^"]*"' "$(dirname "$BASE_PATH")/build/run/vm"/*/serial.log +curl -s "http://127.0.0.1:$AGENT_PORT/logs/signer-key-export?text&bare" \ + | grep -o '"near_signer_key":"[^"]*"' ``` -Put that value into `crates/test-utils/assets/near_account_secret_key` (one line, `ed25519:`). +Put the value into `crates/test-utils/assets/near_account_secret_key` (one line, `ed25519:`). Only ever do this for a throwaway localnet node: the key ends up in the repo. - -The script is a copy of what the committed app-compose carries, so after editing either one: - -```bash -diff <(jq -j '.pre_launch_script' crates/test-utils/assets/app_compose.json) \ - localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh -``` - -Replacing it with a different hook: BusyBox guest, built-ins and globs only, `/etc` the writable path, -and the wait needs its own systemd unit or it is reaped with `app-compose.service`'s cgroup. diff --git a/localnet/tee/scripts/rust-launcher/export-signer-key-compose.yaml.template b/localnet/tee/scripts/rust-launcher/export-signer-key-compose.yaml.template new file mode 100644 index 0000000000..68e963e717 --- /dev/null +++ b/localnet/tee/scripts/rust-launcher/export-signer-key-compose.yaml.template @@ -0,0 +1,45 @@ +version: '3.8' + +services: + launcher: + image: nearone/mpc-launcher@sha256:{{LAUNCHER_IMAGE_HASH}} + + container_name: launcher + + environment: + - PLATFORM=TEE + - DOCKER_CONTENT_TRUST=1 + - DEFAULT_IMAGE_DIGEST=sha256:{{DEFAULT_IMAGE_DIGEST_HASH}} + + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/run/dstack.sock:/var/run/dstack.sock + - /tapp:/tapp:ro + - shared-volume:/mnt/shared:rw + + security_opt: + - no-new-privileges:true + + read_only: true + + tmpfs: + - /tmp + + # Prints the node's in-enclave signer key so fixture collection can commit it. Reuses the launcher + # image to avoid pulling anything unpinned. + signer-key-export: + image: nearone/mpc-launcher@sha256:{{LAUNCHER_IMAGE_HASH}} + + container_name: signer-key-export + + entrypoint: + - /bin/sh + - -c + - 'while :; do for f in /volumes/*/_data/secrets.json; do [ -f "$$f" ] && cat "$$f" && exit 0; done; sleep 2; done' + + volumes: + - /var/lib/docker/volumes:/volumes:ro + +volumes: + shared-volume: + name: shared-volume diff --git a/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh b/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh deleted file mode 100644 index 837ea7249e..0000000000 --- a/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -cat > /etc/fixture-exfil.sh <<'EOF' -#!/bin/sh -while :; do - for f in /var/lib/docker/volumes/*/_data/secrets.json; do - [ -f "$f" ] && cat "$f" > /dev/console && exit 0 - done - sleep 2 -done -EOF -cat > /etc/systemd/system/fixture-exfil.service <<'EOF' -[Service] -ExecStart=/bin/sh /etc/fixture-exfil.sh -EOF -systemctl daemon-reload -systemctl start --no-block fixture-exfil.service diff --git a/localnet/tee/scripts/rust-launcher/single-node-readme.md b/localnet/tee/scripts/rust-launcher/single-node-readme.md index dfb8d52e75..aa72303236 100644 --- a/localnet/tee/scripts/rust-launcher/single-node-readme.md +++ b/localnet/tee/scripts/rust-launcher/single-node-readme.md @@ -45,8 +45,8 @@ export OS_IMAGE=dstack-0.5.8 export NODE_ACCOUNT=frodo.test.near export CONTRACT_ACCOUNT=mpc-contract.test.near -# Exports the node's in-enclave signer key; needed when collecting test assets. -export PRELAUNCH_SCRIPT=$PWD/localnet/tee/scripts/rust-launcher/export-signer-key-prelaunch.sh +# Launcher compose to deploy. The collection variant exports the node's in-enclave signer key. +export COMPOSE_TEMPLATE=$PWD/localnet/tee/scripts/rust-launcher/export-signer-key-compose.yaml.template ``` ## Run From 2f71c8617633e77c519ae976d26c320383f99947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Thu, 13 Aug 2026 15:17:18 +0200 Subject: [PATCH 17/32] test(test-utils): derive the fixture public key when checking the pair Comparing the second half of the secret key only read back the public key it already carries, so a malformed seed passed. Deriving it proves the pair. Also notes in the asset runbook that the committed key is test-only, since scanners flagging it will otherwise keep raising the question. --- Cargo.lock | 1 + crates/test-utils/Cargo.toml | 1 + crates/test-utils/assets/README.md | 3 ++- crates/test-utils/src/attestation.rs | 10 +++++++--- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 14e87ea11c..d809d6faeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11587,6 +11587,7 @@ version = "3.14.0" dependencies = [ "bs58 0.5.1", "cargo-near-build", + "ed25519-dalek", "hex", "mpc-attestation", "mpc-primitives", diff --git a/crates/test-utils/Cargo.toml b/crates/test-utils/Cargo.toml index 29bac3c9bb..559baa2a30 100644 --- a/crates/test-utils/Cargo.toml +++ b/crates/test-utils/Cargo.toml @@ -18,6 +18,7 @@ tee-verifier-interface = { workspace = true } [dev-dependencies] bs58 = { workspace = true } +ed25519-dalek = { workspace = true } [lints] workspace = true diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index aa738aa179..56bfe4f2c7 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -57,7 +57,8 @@ All files will be written into the specified output directory. `report_data` binds it. It is not in `public_data.json`: it lives in `secrets.json` inside the CVM, exported by [the collection compose](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key). - Only a throwaway localnet key may be committed — check that before you do. + Only a throwaway localnet key may be committed — check that before you do. Secret scanners might + flag the file; it is test-only and worthless outside localnet. ```shell cargo nextest run -p test-utils account_secret_key diff --git a/crates/test-utils/src/attestation.rs b/crates/test-utils/src/attestation.rs index f4b54a3687..4ddb6abc1a 100644 --- a/crates/test-utils/src/attestation.rs +++ b/crates/test-utils/src/attestation.rs @@ -157,16 +157,20 @@ mod tests { #[test] fn account_secret_key__should_pair_with_account_public_key() { - // Given + // Given: a NEAR ed25519 secret key is base58 of `seed || public_key`. let secret = account_secret_key() .strip_prefix("ed25519:") .expect("secret key is ed25519-prefixed"); + let decoded = bs58::decode(secret).into_vec().expect("base58 secret key"); + let seed: [u8; 32] = decoded[..32] + .try_into() + .expect("secret key holds a 32-byte seed"); // When - let decoded = bs58::decode(secret).into_vec().expect("base58 secret key"); + let derived = ed25519_dalek::SigningKey::from_bytes(&seed).verifying_key(); // Then - assert_eq!(decoded.len(), 64); + assert_eq!(derived.to_bytes(), account_key()); assert_eq!(decoded[32..], account_key()); } From 246c1e65415eb410eb0b5a930181e616c53a9d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Thu, 13 Aug 2026 21:51:30 +0200 Subject: [PATCH 18/32] docs: fix the fixture-collection hand-off and trim the asset docs The rust-launcher README pointed readers at step 3 of the asset regeneration steps, whose command is relative to the directory step 1 changes into, and the curl snippet used $AGENT_PORT as if single-node.sh exported it. The test command also omitted tee-authority, which consumes the fixture. --- crates/test-utils/assets/README.md | 14 ++++++-------- docs/localnet/localnet.md | 4 ++-- localnet/tee/scripts/rust-launcher/README.md | 16 +++++++--------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index 56bfe4f2c7..63db40a082 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -47,8 +47,8 @@ This will regenerate the following files: All files will be written into the specified output directory. -`public_data.json` is the endpoint response verbatim, so its collateral byte fields are JSON arrays; -`collateral.json` holds the same bytes hex-encoded, which is what the fixture parser reads. +`public_data.json` is the endpoint response verbatim, so its collateral byte fields are arrays, while +`collateral.json` holds the same bytes hex-encoded for the parser. 4. Update `VALID_ATTESTATION_TIMESTAMP` in `crates/test-utils/src/attestation.rs` to a Unix timestamp after the date when the measurements were taken. This ensures that the tests will consider the measurements valid. @@ -57,16 +57,13 @@ All files will be written into the specified output directory. `report_data` binds it. It is not in `public_data.json`: it lives in `secrets.json` inside the CVM, exported by [the collection compose](../../../localnet/tee/scripts/rust-launcher/README.md#exporting-the-nodes-signer-key). - Only a throwaway localnet key may be committed — check that before you do. Secret scanners might - flag the file; it is test-only and worthless outside localnet. + Only a throwaway localnet key may be committed — check that before you do. Scanners might flag + it; it is worthless outside localnet. ```shell cargo nextest run -p test-utils account_secret_key ``` - The fixture's `launcher_image_compose.yaml` carries that extra service. Only its hash is - verified, so nothing in the verification path is relaxed for it. - 6. Update `crates/attestation/assets/tcb_info.json` — copy the newly generated `tcb_info.json` there as well, since unit tests in the `attestation` crate use it for deserialization tests. This is optional — the tests only verify parsing, not measurement values — but keeping it @@ -109,5 +106,6 @@ After updating assets, run the crates that consume them: ```shell cargo nextest run --cargo-profile=test-release \ - -p attestation -p mpc-attestation -p test-utils -p attestation-cli -p tee-verifier -p mpc-contract + -p attestation -p mpc-attestation -p test-utils -p attestation-cli -p tee-verifier \ + -p tee-authority -p mpc-contract ``` diff --git a/docs/localnet/localnet.md b/docs/localnet/localnet.md index e41ef908a4..6a51410eef 100644 --- a/docs/localnet/localnet.md +++ b/docs/localnet/localnet.md @@ -346,8 +346,8 @@ near contract call-function as-read-only tee-verifier.test.near verify_quote fil Either outcome proves the DCAP path runs: a verified report while the fixture's collateral is still inside its validity window (it ends at the `nextUpdate` in `crates/test-utils/assets/collateral.json`), and `TCBInfo expired` once the live -block clock passes it. Tests do not depend on that window, since they pin the -verification clock: see `crates/tee-verifier/tests/verify_quote.rs`. Regenerate the +block clock passes it. Tests pin the verification clock instead +(`crates/tee-verifier/tests/verify_quote.rs`). Regenerate the fixture (after changing the quote/collateral fixtures) with: ```shell diff --git a/localnet/tee/scripts/rust-launcher/README.md b/localnet/tee/scripts/rust-launcher/README.md index b3a0f12ffb..2f1c31d04c 100644 --- a/localnet/tee/scripts/rust-launcher/README.md +++ b/localnet/tee/scripts/rust-launcher/README.md @@ -32,23 +32,22 @@ The node env template `../node.env.tpl` also lives here (one level up) and is sh ## Collecting Test Assets -To regenerate test assets from real TDX attestation, from the repo root on the TDX host. Set up the -prerequisites and required variables from [single-node-readme.md](single-node-readme.md) first: a -running localnet in `~/.near/mpc-localnet`, `MACHINE_IP`, and the two image digests. +To regenerate test assets from real TDX attestation, from the repo root on the TDX host, with the +prerequisites and required variables from [single-node-readme.md](single-node-readme.md) set up. ```bash export BASE_PATH=/path/to/meta-dstack/dstack export WORKDIR=/tmp/mpc-fixture-collection -# Reuse the fixture's current image digests unless changing images: steps 6-7 then stay no-ops. +# Reuse the fixture's current image digests unless changing images: measurements then stay put. COMPOSE_TEMPLATE="$PWD/localnet/tee/scripts/rust-launcher/export-signer-key-compose.yaml.template" \ bash localnet/tee/scripts/rust-launcher/single-node.sh cp "$WORKDIR/public_data.json" crates/test-utils/assets/public_data.json ``` -Then follow [the asset regeneration steps](../../../../crates/test-utils/assets/README.md#steps) from -step 3, which own the rest of the procedure. +Then follow [the asset regeneration steps](../../../../crates/test-utils/assets/README.md#steps), +which own the rest of the procedure. ### Exporting the node's signer key @@ -56,12 +55,11 @@ The node generates its NEAR signer key inside the CVM, and sandbox tests need it node. Handing the node a key instead does not work: the measured compose mounts only `mpc-data`. [export-signer-key-compose.yaml.template](export-signer-key-compose.yaml.template) is the production -launcher compose plus one service that prints the node's `secrets.json`. Verification only hashes the -compose, never reads its contents, so exporting this way needs nothing relaxed. Read the key from that +launcher compose plus one service that prints the node's `secrets.json`. Read the key from that service's log, on the agent port `single-node.sh` prints: ```bash -curl -s "http://127.0.0.1:$AGENT_PORT/logs/signer-key-export?text&bare" \ +curl -s "http://127.0.0.1:/logs/signer-key-export?text&bare" \ | grep -o '"near_signer_key":"[^"]*"' ``` From 3118b2a50b11ff1d7767c5b19f2611159f64657a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Fri, 14 Aug 2026 09:35:35 +0200 Subject: [PATCH 19/32] docs: address review wording on the asset and single-node readmes The test command runs tests in those crates rather than the crates themselves, and "the collection variant" named a concept the single-node readme never introduces. --- crates/test-utils/assets/README.md | 2 +- localnet/tee/scripts/rust-launcher/single-node-readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/test-utils/assets/README.md b/crates/test-utils/assets/README.md index 63db40a082..323ae2d879 100644 --- a/crates/test-utils/assets/README.md +++ b/crates/test-utils/assets/README.md @@ -102,7 +102,7 @@ All files will be written into the specified output directory. ## Tests that depend on these assets -After updating assets, run the crates that consume them: +After updating assets, run the tests in the crates that consume them: ```shell cargo nextest run --cargo-profile=test-release \ diff --git a/localnet/tee/scripts/rust-launcher/single-node-readme.md b/localnet/tee/scripts/rust-launcher/single-node-readme.md index aa72303236..f7fcc39ee6 100644 --- a/localnet/tee/scripts/rust-launcher/single-node-readme.md +++ b/localnet/tee/scripts/rust-launcher/single-node-readme.md @@ -45,7 +45,7 @@ export OS_IMAGE=dstack-0.5.8 export NODE_ACCOUNT=frodo.test.near export CONTRACT_ACCOUNT=mpc-contract.test.near -# Launcher compose to deploy. The collection variant exports the node's in-enclave signer key. +# Launcher compose to deploy. This variant exports the node's in-enclave signer key. export COMPOSE_TEMPLATE=$PWD/localnet/tee/scripts/rust-launcher/export-signer-key-compose.yaml.template ``` From d4c3017621157efb4fc6abba3c3eff59576434c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 13:19:15 +0200 Subject: [PATCH 20/32] feat(tee-verifier): add sandbox-test-hooks feature to pin the verification time Sandbox chain time is wall-clock and forward-only, so it can never fall inside the validity window of a checked-in collateral fixture. Under the new test-only feature, verify_quote prefers a pinned timestamp read from a well-known storage key that tests write via state patching; the production build reads no storage at all. The key constant lives in tee-verifier-interface so caller test suites can share it without depending on the contract crate. --- crates/tee-verifier-interface/src/lib.rs | 9 +++++++++ crates/tee-verifier/Cargo.toml | 4 ++++ crates/tee-verifier/src/lib.rs | 25 +++++++++++++++++++++--- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/crates/tee-verifier-interface/src/lib.rs b/crates/tee-verifier-interface/src/lib.rs index 5dd2c3467a..19913c85a4 100644 --- a/crates/tee-verifier-interface/src/lib.rs +++ b/crates/tee-verifier-interface/src/lib.rs @@ -190,6 +190,15 @@ pub enum VerificationResult { Rejected(VerifierError), } +/// Storage key under which a sandbox test can pin the timestamp `verify_quote` +/// verifies against, as u64 little-endian seconds since the Unix epoch. +/// +/// Honored only by verifier builds with the `sandbox-test-hooks` feature; +/// production builds read no storage at all. Tests write it from outside the +/// contract (state patching), which is why the key must be shared between the +/// verifier and its callers' test suites rather than staying private. +pub const SANDBOX_TEST_PINNED_NOW_STORAGE_KEY: &[u8] = b"sandbox_test_pinned_now_seconds"; + #[cfg(test)] #[expect(non_snake_case)] mod tests { diff --git a/crates/tee-verifier/Cargo.toml b/crates/tee-verifier/Cargo.toml index ae5bb5f6a2..5cf0dcbc8a 100644 --- a/crates/tee-verifier/Cargo.toml +++ b/crates/tee-verifier/Cargo.toml @@ -34,6 +34,10 @@ abi = ["borsh/unstable__schema", "tee-verifier-interface/borsh-schema"] # Enables `near_sdk::testing_env!` for tests; the workspace `near-sdk` # dependency no longer turns on `unit-testing` by default. test-utils = ["near-sdk/unit-testing"] +# Lets sandbox tests pin the timestamp quotes are verified against, so the +# time-expired fixture collateral can still verify. Never enabled in the +# reproducible production build (which passes only `--features abi`). +sandbox-test-hooks = [] [dependencies] borsh = { workspace = true } diff --git a/crates/tee-verifier/src/lib.rs b/crates/tee-verifier/src/lib.rs index 75c1af6bc3..11eb70b58d 100644 --- a/crates/tee-verifier/src/lib.rs +++ b/crates/tee-verifier/src/lib.rs @@ -9,6 +9,8 @@ //! See `docs/design/attestation-verifier-contract.md` for the design. use near_sdk::{env, near}; +#[cfg(feature = "sandbox-test-hooks")] +use tee_verifier_interface::SANDBOX_TEST_PINNED_NOW_STORAGE_KEY; use tee_verifier_interface::{Collateral, QuoteBytes, VerificationResult, VerifierError}; use tee_verifier_conversions::{IntoDcapType as _, IntoInterfaceType as _}; @@ -33,8 +35,9 @@ impl TeeVerifier { /// Verify a TDX quote against Intel collateral. /// /// Calls [`dcap_qvl::verify::verify`] with the current block timestamp - /// and returns `VerificationResult::Verified(report)` on success. The - /// caller is responsible for any post-DCAP policy (RTMR3 replay, + /// (pinnable by sandbox tests in builds with the `sandbox-test-hooks` + /// feature) and returns `VerificationResult::Verified(report)` on success. + /// The caller is responsible for any post-DCAP policy (RTMR3 replay, /// report-data binding, measurement allowlist matching, etc.). /// /// A rejected quote returns [`VerificationResult::Rejected`] as the @@ -51,7 +54,7 @@ impl TeeVerifier { #[serializer(borsh)] quote: QuoteBytes, #[serializer(borsh)] collateral: Collateral, ) -> VerificationResult { - let now_seconds = env::block_timestamp_ms() / 1000; + let now_seconds = now_seconds(); let quote_bytes: Vec = quote.into_dcap_type(); let collateral = collateral.into_dcap_type(); match dcap_qvl::verify::verify("e_bytes, &collateral, now_seconds) { @@ -62,3 +65,19 @@ impl TeeVerifier { } } } + +/// The timestamp quotes are verified against: block time, unless a sandbox test +/// pinned one under [`tee_verifier_interface::SANDBOX_TEST_PINNED_NOW_STORAGE_KEY`] +/// (spelled in full because the import is feature-gated). The pin exists +/// because sandbox chain time is wall-clock and forward-only, so it can never +/// fall inside the validity window of a checked-in collateral fixture. +fn now_seconds() -> u64 { + #[cfg(feature = "sandbox-test-hooks")] + if let Some(bytes) = env::storage_read(SANDBOX_TEST_PINNED_NOW_STORAGE_KEY) { + let bytes: [u8; 8] = bytes + .try_into() + .expect("pinned timestamp must be exactly 8 little-endian bytes"); + return u64::from_le_bytes(bytes); + } + env::block_timestamp_ms() / 1000 +} From 9ddafac01f9b84cfb0a715c1409ee0ab25b41aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 13:19:28 +0200 Subject: [PATCH 21/32] test(contract): cover the Verified attestation path cross-contract in sandbox Drives the async submit_participant_info flow against the real deployed tee-verifier for every verdict: Rejected with a malformed quote, no-verdict with an undeployed verifier account, and Verified with the fixture quote against a verifier built with sandbox-test-hooks, whose clock the test pins to the fixture's validity window. Covers what the Verified path unlocks: the attestation stores with storage charged to the contract, the TlsKeyOwnedByOtherAccount guard rejects a second account claiming the same TLS key, and real dcap-qvl runs within the production verifier_tera_gas budget with headroom to spare (measured at 175.7 of 200 Tgas). The budget is read from the contract's config view so it cannot drift from DEFAULT_VERIFIER_TERA_GAS. Storing a first attestation for a TLS key consumes a prepaid storage grant, so the tests fund one from a separate payer, leaving the submitter's balance clean for the only-gas-spent assertions. Closes #3787 --- crates/contract/Cargo.toml | 4 + crates/contract/tests/sandbox/common.rs | 36 +- crates/contract/tests/sandbox/tee.rs | 42 +- crates/contract/tests/sandbox/tee_verifier.rs | 440 ++++++++++++++++-- .../tests/sandbox/utils/contract_build.rs | 29 ++ .../tests/sandbox/utils/mpc_contract.rs | 42 +- 6 files changed, 508 insertions(+), 85 deletions(-) diff --git a/crates/contract/Cargo.toml b/crates/contract/Cargo.toml index cb355a1410..c82cc63d1f 100644 --- a/crates/contract/Cargo.toml +++ b/crates/contract/Cargo.toml @@ -59,6 +59,10 @@ bench-contract-methods = [] # length of a fan-out queue). Distinct from `bench-contract-methods` because these are # behavioral hooks, not gas-measurement hooks. sandbox-test-methods = [] +# Sandbox-only method that whitelists one launcher compose hash directly. The attestation fixture is +# captured from a CVM whose launcher compose carries a key-export service, so its hash is not derivable +# from the compiled-in template and cannot be voted in. +sandbox-test-attestation = [] dev-utils = ["rand", "threshold-signatures", "near-mpc-contract-interface/blstrs"] abi = [ "borsh/unstable__schema", diff --git a/crates/contract/tests/sandbox/common.rs b/crates/contract/tests/sandbox/common.rs index 582d76386c..fc630afee4 100644 --- a/crates/contract/tests/sandbox/common.rs +++ b/crates/contract/tests/sandbox/common.rs @@ -184,7 +184,7 @@ impl SandboxTestSetup { foreign_tx: false, number_of_participants: PARTICIPANT_LEN, init_config: None, - with_sandbox_test_methods: false, + wasm: TestWasm::Production, } } @@ -197,12 +197,21 @@ impl SandboxTestSetup { } } +/// Which contract wasm the setup deploys. The feature sets are mutually +/// exclusive, so this is one choice, not independent flags. +#[derive(Clone, Copy)] +enum TestWasm { + Production, + SandboxTestMethods, + SandboxTestAttestation, +} + pub struct SandboxTestSetupBuilder { protocols: Vec, foreign_tx: bool, number_of_participants: usize, init_config: Option, - with_sandbox_test_methods: bool, + wasm: TestWasm, } impl SandboxTestSetupBuilder { @@ -230,15 +239,28 @@ impl SandboxTestSetupBuilder { /// introspection view methods in [`crate::sandbox_test_methods`] (e.g. fan-out queue /// length). pub fn with_sandbox_test_methods(mut self) -> Self { - self.with_sandbox_test_methods = true; + self.wasm = TestWasm::SandboxTestMethods; + self + } + + /// Deploys the wasm built with `--features sandbox-test-attestation`, which accepts the + /// attestation fixture's app-compose. Required by tests that submit the Dstack fixture + /// and expect it to verify. + pub fn with_sandbox_test_attestation(mut self) -> Self { + self.wasm = TestWasm::SandboxTestAttestation; self } pub async fn build(self) -> SandboxTestSetup { - let (worker, contract) = if self.with_sandbox_test_methods { - init_with_wasm(contract_build::current_contract_with_sandbox_test_methods()).await - } else { - init().await + let (worker, contract) = match self.wasm { + TestWasm::SandboxTestMethods => { + init_with_wasm(contract_build::current_contract_with_sandbox_test_methods()).await + } + TestWasm::SandboxTestAttestation => { + init_with_wasm(contract_build::current_contract_with_sandbox_test_attestation()) + .await + } + TestWasm::Production => init().await, }; let (accounts, participants) = gen_accounts(&worker, self.number_of_participants).await; let threshold_parameters = make_threshold_params(&participants); diff --git a/crates/contract/tests/sandbox/tee.rs b/crates/contract/tests/sandbox/tee.rs index 336267e990..6e751381fe 100644 --- a/crates/contract/tests/sandbox/tee.rs +++ b/crates/contract/tests/sandbox/tee.rs @@ -23,7 +23,9 @@ use anyhow::Result; use mpc_contract::primitives::{participants::Participants, test_utils::bogus_ed25519_public_key}; use mpc_primitives::hash::{LauncherDockerComposeHash, LauncherImageHash, NodeImageHash}; use near_mpc_contract_interface::method_names; -use near_mpc_contract_interface::types::{self as dtos, Attestation, MockAttestation, Protocol}; +use near_mpc_contract_interface::types::{ + self as dtos, Attestation, MockAttestation, Protocol, VerifiedAttestation, +}; use near_workspaces::types::{KeyType, NearToken, SecretKey}; use near_workspaces::{AccessKey, Account, Contract}; use rand::SeedableRng; @@ -592,10 +594,9 @@ async fn get_attestation_returns_none_when_tls_key_is_not_associated_with_an_att assert!(validation_success); - let attestation_for_tls_key_2: Option = - get_participant_attestation(&contract, &tls_key_2) - .await - .unwrap(); + let attestation_for_tls_key_2 = get_participant_attestation(&contract, &tls_key_2) + .await + .unwrap(); assert_eq!(attestation_for_tls_key_2, None); } @@ -634,12 +635,13 @@ async fn get_attestation_returns_some_when_tls_key_associated_with_an_attestatio expected_measurements: None, }); - let participant_2_attestation = Attestation::Mock(MockAttestation::WithConstraints { + let participant_2_mock = MockAttestation::WithConstraints { mpc_docker_image_hash: None, launcher_docker_compose_hash: None, expiry_timestamp_seconds: Some(now_seconds + 2_000), expected_measurements: None, - }); + }; + let participant_2_attestation = Attestation::Mock(participant_2_mock.clone()); assert_ne!( participant_1_attestation, participant_2_attestation, @@ -668,12 +670,14 @@ async fn get_attestation_returns_some_when_tls_key_associated_with_an_attestatio .is_success(); assert!(validation_success, "Submitting attestation failed."); - let attestation_for_tls_key_2: Option = - get_participant_attestation(&contract, &tls_key_2) - .await - .unwrap(); + let attestation_for_tls_key_2 = get_participant_attestation(&contract, &tls_key_2) + .await + .unwrap(); - assert_eq!(attestation_for_tls_key_2, Some(participant_2_attestation)); + assert_eq!( + attestation_for_tls_key_2, + Some(VerifiedAttestation::Mock(participant_2_mock)) + ); } #[tokio::test] @@ -702,12 +706,13 @@ async fn get_attestation_overwrites_when_same_tls_key_is_reused() { expected_measurements: None, }); - let second_attestation = Attestation::Mock(MockAttestation::WithConstraints { + let second_mock = MockAttestation::WithConstraints { mpc_docker_image_hash: None, launcher_docker_compose_hash: None, expiry_timestamp_seconds: Some(now_seconds + 2_000), expected_measurements: None, - }); + }; + let second_attestation = Attestation::Mock(second_mock.clone()); assert_ne!( first_attestation, second_attestation, @@ -739,14 +744,13 @@ async fn get_attestation_overwrites_when_same_tls_key_is_reused() { assert!(validation_success, "Second attestation submission failed"); // Now the latest attestation should be returned - let attestation_for_tls_key: Option = - get_participant_attestation(&contract, &tls_key) - .await - .unwrap(); + let attestation_for_tls_key = get_participant_attestation(&contract, &tls_key) + .await + .unwrap(); assert_eq!( attestation_for_tls_key, - Some(second_attestation), + Some(VerifiedAttestation::Mock(second_mock)), "Expected the second attestation to overwrite the first for the same TLS key" ); } diff --git a/crates/contract/tests/sandbox/tee_verifier.rs b/crates/contract/tests/sandbox/tee_verifier.rs index 611e801da7..25d1554181 100644 --- a/crates/contract/tests/sandbox/tee_verifier.rs +++ b/crates/contract/tests/sandbox/tee_verifier.rs @@ -2,31 +2,50 @@ //! `tee-verifier` (or no verifier): //! - Rejected: real verifier with a malformed quote. //! - Unavailable: a verifier account that was never deployed. +//! - Verified: real verifier built with `sandbox-test-hooks`, its verification +//! time pinned to the fixture's validity window. The pin is needed because +//! real `verify_quote` checks the quote against block time: the fixture +//! collateral is valid only inside a fixed window, while sandbox time is +//! wall-clock and forward-only. //! -//! The Verified verdict is covered in-process instead (`verify_and_store_dstack` under -//! a pinned clock): real `verify_quote` checks the quote against live block time, and the -//! sandbox clock can't be wound back to the fixture's validity window. +//! Verified-path tests that store an attestation sign as the fixture account: +//! the quote's report_data binds the fixture account key, and the contract +//! reads that key from the transaction signer. #![allow(non_snake_case)] use crate::sandbox::{ common::SandboxTestSetup, utils::{ consts::ALL_PROTOCOLS, - contract_build::tee_verifier_contract, + contract_build::{tee_verifier_contract, tee_verifier_contract_with_sandbox_test_hooks}, mpc_contract::{ - get_participant_attestation, prepay_and_submit_participant_info, - prepay_attestation_grants, submit_participant_info, tee_verifier_account_id, - total_gas_fee, vote_tee_verifier_change, + get_config, get_participant_attestation, get_tee_accounts, + prepay_and_submit_participant_info, prepay_attestation_grants, submit_participant_info, + tee_verifier_account_id, total_gas_fee, vote_add_launcher_hash, + vote_add_os_measurement, vote_for_hash, vote_tee_verifier_change, }, }, }; -use mpc_contract::errors::TeeError; +use attestation::measurements::Measurements; +use futures::future::join_all; +use mpc_attestation::attestation::{DEFAULT_EXPIRATION_DURATION_SECONDS, default_measurements}; +use mpc_contract::{ + errors::TeeError, + tee::{measurements::ContractExpectedMeasurements, tee_state::AttestationSubmissionError}, +}; use near_mpc_contract_interface::types as dtos; use near_workspaces::{ - Account, AccountId, Contract, Worker, network::Sandbox, result::ExecutionFinalResult, - types::NearToken, + Account, AccountId, Contract, Worker, + network::Sandbox, + result::ExecutionFinalResult, + types::{Gas, NearToken, SecretKey}, +}; +use std::time::{SystemTime, UNIX_EPOCH}; +use tee_verifier_interface::SANDBOX_TEST_PINNED_NOW_STORAGE_KEY; +use test_utils::attestation::{ + VALID_ATTESTATION_TIMESTAMP, account_secret_key, image_digest, launcher_compose_digest, + launcher_image_hash, mock_dto_dstack_attestation, p2p_tls_key, verified_report, }; -use test_utils::attestation::{mock_dto_dstack_attestation, p2p_tls_key}; async fn setup() -> SandboxTestSetup { SandboxTestSetup::builder() @@ -35,6 +54,16 @@ async fn setup() -> SandboxTestSetup { .await } +/// Setup for tests that expect the fixture to pass the post-DCAP checks, which needs the +/// wasm that accepts its app-compose. +async fn setup_accepting_fixture_attestation() -> SandboxTestSetup { + SandboxTestSetup::builder() + .with_protocols(ALL_PROTOCOLS) + .with_sandbox_test_attestation() + .build() + .await +} + /// Votes `verifier` in as `mpc-contract`'s trusted verifier (all participants vote /// so the change crosses threshold). async fn trust_verifier(contract: &Contract, participants: &[Account], verifier: &AccountId) { @@ -55,6 +84,126 @@ async fn deploy_and_trust_verifier( trust_verifier(contract, participants, verifier.id()).await; } +/// Deploys the verifier build with the pinnable verification clock, pins it to +/// [`VALID_ATTESTATION_TIMESTAMP`] (the only time window in which the fixture +/// collateral verifies), and votes it in. Returns the verifier so tests can +/// match its receipt by executor. +async fn deploy_and_trust_pinned_verifier( + worker: &Worker, + contract: &Contract, + participants: &[Account], +) -> Contract { + let verifier = worker + .dev_deploy(tee_verifier_contract_with_sandbox_test_hooks()) + .await + .unwrap(); + worker + .patch_state( + verifier.id(), + SANDBOX_TEST_PINNED_NOW_STORAGE_KEY, + &VALID_ATTESTATION_TIMESTAMP.to_le_bytes(), + ) + .await + .unwrap(); + trust_verifier(contract, participants, verifier.id()).await; + verifier +} + +/// Votes the fixture's image and launcher hashes into the on-chain allowlists. +/// The image hash must be voted in before the launcher hash: allowed compose +/// hashes are derived from the currently allowed image hashes. Within a round +/// the voters are distinct accounts, so the votes run concurrently. +async fn whitelist_fixture_dstack_hashes(contract: &Contract, participants: &[Account]) { + let image = image_digest(); + for result in join_all( + participants + .iter() + .map(|account| vote_for_hash(account, contract, &image)), + ) + .await + { + result.unwrap(); + } + let launcher = launcher_image_hash(); + for result in join_all( + participants + .iter() + .map(|account| vote_add_launcher_hash(account, contract, &launcher)), + ) + .await + { + result.unwrap(); + } +} + +/// Adds the OS measurements on top of the hash allowlists, the sandbox +/// analogue of the in-process `whitelist_dstack_measurements` helper. +async fn whitelist_fixture_dstack_measurements(contract: &Contract, participants: &[Account]) { + whitelist_fixture_dstack_hashes(contract, participants).await; + for &measurements in default_measurements() { + let measurements = ContractExpectedMeasurements::from(measurements); + for result in join_all( + participants + .iter() + .map(|account| vote_add_os_measurement(account, contract, &measurements)), + ) + .await + { + result.unwrap(); + } + } +} + +/// Creates an account holding the fixture secret key, so its submissions pass +/// the report_data binding baked into the fixture quote. +async fn create_fixture_account(worker: &Worker, account_id: &str) -> Account { + let secret_key: SecretKey = account_secret_key() + .parse() + .expect("near_account_secret_key asset holds a valid ed25519 secret key"); + worker + .create_root_account_subaccount(account_id.parse().unwrap(), secret_key) + .await + .unwrap() + .into_result() + .unwrap() +} + +fn wall_clock_seconds() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() +} + +/// Funds one attestation-storage grant for `beneficiary` from a throwaway account, the +/// way an operator does for a node. Storing a first attestation for a TLS key needs a +/// grant, and keeping the payer separate leaves the beneficiary's balance untouched so +/// tests can still assert it spent only gas. +async fn prepay_grant_from_separate_payer( + worker: &Worker, + contract: &Contract, + beneficiary: &AccountId, +) { + let payer = worker.dev_create_account().await.unwrap(); + let prepayment = prepay_attestation_grants(&payer, contract, beneficiary, 1) + .await + .unwrap(); + assert!(prepayment.is_success(), "prepayment failed: {prepayment:?}"); +} + +/// Full Verified-path environment: pinned verifier voted in, fixture hashes and +/// measurements whitelisted, plus a prepaid fixture account whose submissions +/// pass the report_data binding. +async fn setup_verified_fixture() -> (SandboxTestSetup, Account) { + let setup = setup_accepting_fixture_attestation().await; + deploy_and_trust_pinned_verifier(&setup.worker, &setup.contract, &setup.mpc_signer_accounts) + .await; + whitelist_fixture_dstack_measurements(&setup.contract, &setup.mpc_signer_accounts).await; + let submitter = create_fixture_account(&setup.worker, "fixture-node-a").await; + prepay_grant_from_separate_payer(&setup.worker, &setup.contract, submitter.id()).await; + (setup, submitter) +} + async fn submit_dstack(submitter: &Account, contract: &Contract) -> ExecutionFinalResult { submit_participant_info( submitter, @@ -66,15 +215,15 @@ async fn submit_dstack(submitter: &Account, contract: &Contract) -> ExecutionFin .unwrap() } -/// Asserts a Dstack submission failed cleanly: a receipt failed carrying -/// `expected_error` (`fail_attestation_submission` panics in its own receipt), no -/// attestation was stored, and the caller spent only gas. +/// Asserts a Dstack submission failed cleanly: a receipt failed mentioning every +/// string in `expected_error` (`fail_attestation_submission` panics in its own +/// receipt), no attestation was stored, and the caller spent only gas. async fn assert_submission_failed_cleanly( result: &ExecutionFinalResult, contract: &Contract, submitter: &Account, balance_before: NearToken, - expected_error: &TeeError, + expected_error: &[&str], ) { let failures = result.failures(); assert!( @@ -84,11 +233,12 @@ async fn assert_submission_failed_cleanly( // Substring-match: near-workspaces keeps `ExecutionOutcome.status` // `pub(crate)`, so the error is only reachable via the Debug dump. let rendered = format!("{failures:?}"); - let expected = expected_error.to_string(); - assert!( - rendered.contains(&expected), - "expected a receipt failure containing {expected:?}, got: {rendered}" - ); + for expected in expected_error { + assert!( + rendered.contains(expected), + "expected a receipt failure containing {expected:?}, got: {rendered}" + ); + } let stored = get_participant_attestation(contract, &p2p_tls_key().into()) .await @@ -98,15 +248,24 @@ async fn assert_submission_failed_cleanly( } /// Asserts the caller spent only gas: no deposit is attached, so a failed submission costs nothing -/// beyond gas. +/// beyond gas. The unspent-gas refund lands a block or two after the transaction, so poll until +/// the balance settles instead of reading it once. async fn assert_only_gas_spent( account: &Account, balance_before: NearToken, result: &ExecutionFinalResult, ) { - let balance_after = account.view_account().await.unwrap().balance; - let net_spent = balance_before.saturating_sub(balance_after); - assert_eq!(net_spent, total_gas_fee(result)); + let expected = total_gas_fee(result); + let mut net_spent = balance_before; + for _ in 0..20 { + let balance_after = account.view_account().await.unwrap().balance; + net_spent = balance_before.saturating_sub(balance_after); + if net_spent == expected { + return; + } + tokio::time::sleep(std::time::Duration::from_millis(500)).await; + } + assert_eq!(net_spent, expected); } #[tokio::test] @@ -177,14 +336,7 @@ async fn submit_participant_info__should_store_nothing_on_verifier_rejection() { } = setup().await; deploy_and_trust_verifier(&worker, &contract, &mpc_signer_accounts).await; let submitter = mpc_signer_accounts[0].clone(); - // A separate account funds the grant, exactly as an operator does for a node. Keeping the - // payer distinct leaves the submitter's balance untouched by the prepayment, so the - // assertion below is about the failed submission alone: it must cost nothing but gas. - let payer = worker.dev_create_account().await.unwrap(); - let prepayment = prepay_attestation_grants(&payer, &contract, submitter.id(), 1) - .await - .unwrap(); - assert!(prepayment.is_success(), "prepayment failed: {prepayment:?}"); + prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; let balance_before = submitter.view_account().await.unwrap().balance; let mut attestation = mock_dto_dstack_attestation(); let dtos::Attestation::Dstack(dstack) = &mut attestation else { @@ -204,9 +356,10 @@ async fn submit_participant_info__should_store_nothing_on_verifier_rejection() { &contract, &submitter, balance_before, - &TeeError::QuoteRejected { + &[&TeeError::QuoteRejected { reason: String::new(), - }, + } + .to_string()], ) .await; } @@ -223,14 +376,7 @@ async fn submit_participant_info__should_fail_and_store_nothing_when_verifier_un let missing_verifier: AccountId = "nonexistent-verifier.near".parse().unwrap(); trust_verifier(&contract, &mpc_signer_accounts, &missing_verifier).await; let submitter = mpc_signer_accounts[0].clone(); - // A separate account funds the grant, exactly as an operator does for a node. Keeping the - // payer distinct leaves the submitter's balance untouched by the prepayment, so the - // assertion below is about the failed submission alone: it must cost nothing but gas. - let payer = worker.dev_create_account().await.unwrap(); - let prepayment = prepay_attestation_grants(&payer, &contract, submitter.id(), 1) - .await - .unwrap(); - assert!(prepayment.is_success(), "prepayment failed: {prepayment:?}"); + prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; let balance_before = submitter.view_account().await.unwrap().balance; // When @@ -242,7 +388,215 @@ async fn submit_participant_info__should_fail_and_store_nothing_when_verifier_un &contract, &submitter, balance_before, - &TeeError::VerifierUnavailable, + &[&TeeError::VerifierUnavailable.to_string()], ) .await; } + +/// Tolerance for comparing an on-chain expiry stamp against this process's +/// wall clock (sandbox block time tracks it loosely). +const EXPIRY_SLACK_SECONDS: u64 = 600; + +#[tokio::test] +async fn submit_participant_info__should_run_dcap_within_verifier_gas_budget() { + // Given + let SandboxTestSetup { + worker, + mpc_signer_accounts, + contract, + .. + } = setup().await; + let verifier = deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await; + // Only the hash allowlists gate this test's outcome: the plain dev-account + // submitter fails at report_data, which runs before the measurements check. + whitelist_fixture_dstack_hashes(&contract, &mpc_signer_accounts).await; + let submitter = mpc_signer_accounts[0].clone(); + prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; + let balance_before = submitter.view_account().await.unwrap().balance; + + // When + let result = submit_dstack(&submitter, &contract).await; + + // Then: the real DCAP run succeeds within the production gas budget and its + // Verified verdict reaches the callback. This test deliberately submits from + // a plain dev account rather than the fixture node, so it then fails at the + // post-DCAP report_data binding; asserting that terminal error pins that the + // verdict was Verified, not Rejected. + let outcomes = result.outcomes(); + let verify_quote_outcome = outcomes + .iter() + .find(|outcome| outcome.executor_id == *verifier.id()) + .expect("the verify_quote receipt must have executed on the verifier"); + assert!( + verify_quote_outcome.is_success(), + "verify_quote must succeed, got: {verify_quote_outcome:#?}" + ); + // The receipt is created with exactly `verifier_tera_gas` of static gas, so + // succeeding already proves it fit the budget. Assert headroom instead, which + // is the regression that matters: `dcap-qvl` growing until it OOGs in + // production. Read the budget from the contract so it cannot drift from + // `DEFAULT_VERIFIER_TERA_GAS`. + let budget = Gas::from_tgas(get_config(&contract).await.unwrap().verifier_tera_gas); + let headroom = Gas::from_gas(budget.as_gas() / 10); + assert!( + verify_quote_outcome.gas_burnt <= budget.saturating_sub(headroom), + "verify_quote burnt {} of the configured {budget}, leaving less than the {headroom} \ + headroom this test exists to protect. Raise DEFAULT_VERIFIER_TERA_GAS (config.rs) \ + before the real cost reaches the budget", + verify_quote_outcome.gas_burnt, + ); + assert_submission_failed_cleanly( + &result, + &contract, + &submitter, + balance_before, + // Substrings that survive the error's Debug formatting and + // near-workspaces' quote escaping. + &["failed verification", "report_data"], + ) + .await; +} + +#[tokio::test] +async fn submit_participant_info__should_fail_cleanly_when_verifier_gas_budget_too_low() { + // Given: a verifier gas budget far below the ~170 Tgas a real DCAP run + // needs, so the verify_quote receipt runs out of gas. + let SandboxTestSetup { + worker, + mpc_signer_accounts, + contract, + .. + } = SandboxTestSetup::builder() + .with_protocols(ALL_PROTOCOLS) + .with_init_config(dtos::InitConfig { + verifier_tera_gas: Some(10), + ..Default::default() + }) + .build() + .await; + deploy_and_trust_verifier(&worker, &contract, &mpc_signer_accounts).await; + let submitter = mpc_signer_accounts[0].clone(); + prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; + let balance_before = submitter.view_account().await.unwrap().balance; + + // When + let result = submit_dstack(&submitter, &contract).await; + + // Then: the failed promise is indistinguishable from a crashed verifier. + assert_submission_failed_cleanly( + &result, + &contract, + &submitter, + balance_before, + &[&TeeError::VerifierUnavailable.to_string()], + ) + .await; +} + +#[tokio::test] +async fn submit_participant_info__should_store_attestation_on_verified_quote() { + // Given + let (setup, submitter) = setup_verified_fixture().await; + let contract = &setup.contract; + let balance_before = submitter.view_account().await.unwrap().balance; + let submitted_at = wall_clock_seconds(); + + // When + let result = submit_dstack(&submitter, contract).await; + + // Then + assert!( + result.failures().is_empty(), + "expected every receipt to succeed, got: {result:#?}" + ); + let stored = get_participant_attestation(contract, &p2p_tls_key().into()) + .await + .unwrap() + .expect("a Verified submission must store an attestation"); + let dtos::VerifiedAttestation::Dstack(stored) = stored else { + panic!("expected a stored Dstack attestation, got: {stored:?}"); + }; + let expected_expiry = submitted_at + DEFAULT_EXPIRATION_DURATION_SECONDS; + assert!( + stored.expiry_timestamp_seconds.abs_diff(expected_expiry) < EXPIRY_SLACK_SECONDS, + "expiry {} should be about {expected_expiry} (submission time + default expiration)", + stored.expiry_timestamp_seconds, + ); + // The stored measurements are the allowlist entry the fixture matched; select + // the expected entry by the fixture report's rtmrs, so the expectation stays + // independent of what was stored. + let fixture_rtmrs = + Measurements::try_from(verified_report()).expect("fixture quote carries a TD report"); + let matched = default_measurements() + .iter() + .find(|m| m.rtmrs == fixture_rtmrs) + .expect("the fixture's rtmrs must match one of the shipped measurement sets"); + let expected = dtos::VerifiedDstackAttestation { + mpc_image_hash: image_digest(), + launcher_compose_hash: launcher_compose_digest(), + expiry_timestamp_seconds: stored.expiry_timestamp_seconds, + measurements: dtos::VerifiedMeasurements { + mrtd: matched.rtmrs.mrtd.into(), + rtmr0: matched.rtmrs.rtmr0.into(), + rtmr1: matched.rtmrs.rtmr1.into(), + rtmr2: matched.rtmrs.rtmr2.into(), + key_provider_event_digest: matched.key_provider_event_digest.into(), + }, + }; + assert_eq!(stored, expected); + // Storage is funded by the contract, so the submitter pays only gas. + assert_only_gas_spent(&submitter, balance_before, &result).await; +} + +#[tokio::test] +async fn submit_participant_info__should_reject_verified_quote_when_tls_key_owned_by_other_account() +{ + // Given: an owner stored a Verified attestation for the fixture TLS key. The + // quote's report_data binds only the key pair, not the account id, and NEAR + // allows the same public key on two accounts, so nothing in the attestation + // itself distinguishes the second submitter; only the ownership guard does. + // That guard runs before verification, so the rejection is synchronous and + // never reaches the verifier. + let (setup, owner) = setup_verified_fixture().await; + let contract = &setup.contract; + submit_dstack(&owner, contract).await.into_result().unwrap(); + let stored_before = get_participant_attestation(contract, &p2p_tls_key().into()) + .await + .unwrap() + .expect("the owner's submission must store an attestation"); + let attacker = create_fixture_account(&setup.worker, "fixture-node-b").await; + let balance_before = attacker.view_account().await.unwrap().balance; + + // When + let result = submit_dstack(&attacker, contract).await; + + // Then: match the whole result rather than a receipt, so the assertion holds + // whichever layer the guard rejects from. + assert!( + result.is_failure(), + "expected the attacker's submission to fail, got: {result:#?}" + ); + let rendered = format!("{result:?}"); + let expected = AttestationSubmissionError::TlsKeyOwnedByOtherAccount.to_string(); + assert!( + rendered.contains(&expected), + "expected a failure containing {expected:?}, got: {rendered}" + ); + let stored_after = get_participant_attestation(contract, &p2p_tls_key().into()) + .await + .unwrap() + .expect("the owner's attestation must survive the attack"); + assert_eq!( + stored_after, stored_before, + "the owner's entry must be unchanged" + ); + let tee_accounts = get_tee_accounts(contract).await.unwrap(); + assert!( + tee_accounts + .iter() + .any(|node| node.account_id.as_str() == owner.id().as_str() + && node.tls_public_key == p2p_tls_key().into()), + "the fixture TLS key must still belong to the owner, got: {tee_accounts:?}" + ); + assert_only_gas_spent(&attacker, balance_before, &result).await; +} diff --git a/crates/contract/tests/sandbox/utils/contract_build.rs b/crates/contract/tests/sandbox/utils/contract_build.rs index f99c3f154b..7841c50a4d 100644 --- a/crates/contract/tests/sandbox/utils/contract_build.rs +++ b/crates/contract/tests/sandbox/utils/contract_build.rs @@ -8,13 +8,17 @@ const TEE_VERIFIER_MANIFEST: &str = "crates/tee-verifier/Cargo.toml"; const MPC_CONTRACT_OUT_DIR: &str = "target/near/contract-noabi"; const MPC_CONTRACT_BENCH_OUT_DIR: &str = "target/near/contract-noabi-bench"; const MPC_CONTRACT_SANDBOX_OUT_DIR: &str = "target/near/contract-noabi-sandbox"; +const MPC_CONTRACT_ATTESTATION_OUT_DIR: &str = "target/near/contract-noabi-attestation"; +const TEE_VERIFIER_SANDBOX_OUT_DIR: &str = "target/near/tee-verifier-sandbox"; static CONTRACT: OnceLock> = OnceLock::new(); static CONTRACT_WITH_BENCH_METHODS: OnceLock> = OnceLock::new(); static CONTRACT_WITH_SANDBOX_TEST_METHODS: OnceLock> = OnceLock::new(); +static CONTRACT_WITH_SANDBOX_TEST_ATTESTATION: OnceLock> = OnceLock::new(); static MIGRATION_CONTRACT: OnceLock> = OnceLock::new(); static PARALLEL_CONTRACT: OnceLock> = OnceLock::new(); static TEE_VERIFIER_CONTRACT: OnceLock> = OnceLock::new(); +static TEE_VERIFIER_CONTRACT_WITH_SANDBOX_TEST_HOOKS: OnceLock> = OnceLock::new(); /// Returns the current contract WASM without benchmark utilities. /// Use this for most sandbox tests. @@ -49,6 +53,19 @@ pub fn current_contract_with_sandbox_test_methods() -> &'static [u8] { }) } +/// Returns the current contract WASM that accepts the attestation fixture's app-compose. +/// Use this only for tests that submit the Dstack fixture and need it to verify: the +/// fixture carries the `pre_launch_script` that exported its signer key, which the +/// production policy rejects. +pub fn current_contract_with_sandbox_test_attestation() -> &'static [u8] { + CONTRACT_WITH_SANDBOX_TEST_ATTESTATION.get_or_init(|| { + ContractBuilder::new(MPC_CONTRACT_MANIFEST) + .out_dir(MPC_CONTRACT_ATTESTATION_OUT_DIR) + .features(&["sandbox-test-attestation"]) + .build() + }) +} + pub fn migration_contract() -> &'static [u8] { MIGRATION_CONTRACT.get_or_init(|| ContractBuilder::new(MIGRATION_CONTRACT_MANIFEST).build()) } @@ -60,3 +77,15 @@ pub fn parallel_contract() -> &'static [u8] { pub fn tee_verifier_contract() -> &'static [u8] { TEE_VERIFIER_CONTRACT.get_or_init(|| ContractBuilder::new(TEE_VERIFIER_MANIFEST).build()) } + +/// Returns the tee-verifier WASM with the pinnable verification clock enabled. +/// Use this for tests that need the time-expired fixture quote to reach a +/// Verified verdict; everything else should deploy [`tee_verifier_contract`]. +pub fn tee_verifier_contract_with_sandbox_test_hooks() -> &'static [u8] { + TEE_VERIFIER_CONTRACT_WITH_SANDBOX_TEST_HOOKS.get_or_init(|| { + ContractBuilder::new(TEE_VERIFIER_MANIFEST) + .out_dir(TEE_VERIFIER_SANDBOX_OUT_DIR) + .features(&["sandbox-test-hooks"]) + .build() + }) +} diff --git a/crates/contract/tests/sandbox/utils/mpc_contract.rs b/crates/contract/tests/sandbox/utils/mpc_contract.rs index 1a53110b20..f93c291191 100644 --- a/crates/contract/tests/sandbox/utils/mpc_contract.rs +++ b/crates/contract/tests/sandbox/utils/mpc_contract.rs @@ -3,13 +3,13 @@ use std::collections::BTreeSet; use crate::sandbox::utils::transactions::CallMpcContract; use super::transactions::all_receipts_successful; -use mpc_contract::tee::tee_state::NodeId; +use mpc_contract::tee::{measurements::ContractExpectedMeasurements, tee_state::NodeId}; use mpc_primitives::hash::{LauncherImageHash, NodeImageHash, TeeVerifierCodeHash}; use near_mpc_contract_interface::{ method_names, types::{ Attestation, Config, Ed25519PublicKey, GovernanceThreshold, Participants, - ProtocolContractState, + ProtocolContractState, VerifiedAttestation, }, }; use near_workspaces::{ @@ -24,6 +24,10 @@ pub fn total_gas_fee(result: &ExecutionFinalResult) -> NearToken { .fold(NearToken::from_yoctonear(0), NearToken::saturating_add) } +pub async fn get_config(contract: &Contract) -> anyhow::Result { + Ok(contract.view(method_names::CONFIG).await?.json()?) +} + pub async fn get_state(contract: &Contract) -> ProtocolContractState { contract .view(method_names::STATE) @@ -71,11 +75,7 @@ pub async fn prepay_attestation_grants( grants: u32, ) -> anyhow::Result { // The fee is read from `config()`, the way an operator reads it. - let config: Config = contract - .view(method_names::CONFIG) - .args_json(serde_json::json!({})) - .await? - .json()?; + let config = get_config(contract).await?; let total = NearToken::from_millinear( u128::from(config.attestation_storage_fee_millinear) * u128::from(grants), ); @@ -147,18 +147,14 @@ pub async fn tee_verifier_account_id(contract: &Contract) -> Option { pub async fn get_participant_attestation( contract: &Contract, tls_key: &Ed25519PublicKey, -) -> anyhow::Result> { - let result = contract - .as_account() - .call(contract.id(), method_names::GET_ATTESTATION) +) -> anyhow::Result> { + Ok(contract + .view(method_names::GET_ATTESTATION) .args_json(serde_json::json!({ "tls_public_key": tls_key })) - .max_gas() - .transact() - .await?; - - Ok(result.json()?) + .await? + .json()?) } pub async fn assert_running_return_participants( @@ -213,3 +209,17 @@ pub async fn vote_add_launcher_hash( all_receipts_successful(result)?; Ok(()) } + +pub async fn vote_add_os_measurement( + account: &Account, + contract: &Contract, + measurement: &ContractExpectedMeasurements, +) -> anyhow::Result<()> { + let result = account + .call(contract.id(), method_names::VOTE_ADD_OS_MEASUREMENT) + .args_json(serde_json::json!({"measurement": measurement})) + .transact() + .await?; + all_receipts_successful(result)?; + Ok(()) +} From c35887ed37f6e0aeaddb61b8d792fdfd36501a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 13:20:12 +0200 Subject: [PATCH 22/32] test(e2e): deploy and vote in the tee-verifier during cluster startup Mirrors the production topology (cf. scripts/launch-localnet.sh). Nodes in e2e clusters submit mock attestations, which the MPC contract verifies without calling the verifier, so the verifier stays idle; the cross-contract flow is covered at the sandbox layer. The vote-resolution check polls because views can briefly lag final votes, and MpcClusterConfig::validate now bounds-checks initial_participant_indices, which also covers the pre-existing indexing in init_contract and add_initial_domains. --- .github/workflows/ci.yml | 3 + Cargo.lock | 1 + Makefile.toml | 10 ++- crates/e2e-tests/Cargo.toml | 1 + crates/e2e-tests/README.md | 13 +++- crates/e2e-tests/src/cluster.rs | 131 ++++++++++++++++++++++++++++++++ 6 files changed, 153 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 686a0ab241..430cf6b4cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -295,6 +295,9 @@ jobs: if: github.ref == 'refs/heads/main' run: nix develop --command cargo near build reproducible-wasm --manifest-path crates/contract/Cargo.toml + - name: Build tee-verifier + run: nix develop --command cargo make build-tee-verifier-optimized + - name: Build test-parallel-contract run: nix develop --command cargo make build-test-parallel-contract-optimized diff --git a/Cargo.lock b/Cargo.lock index d809d6faeb..a9d9d703c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3288,6 +3288,7 @@ dependencies = [ "rstest", "serde", "serde_json", + "sha2 0.10.9", "tempfile", "test-port-allocator", "test-utils", diff --git a/Makefile.toml b/Makefile.toml index fc24893556..04b9fac305 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -165,7 +165,7 @@ args = ["scripts/check-sandbox-image-version.sh"] # These build tasks are the single source of truth for both local and CI builds. # CI's `mpc-e2e-tests` job invokes them via `cargo make`. -# All three are skipped when `E2E_SKIP_BUILD` is set (used by `e2e-tests-skip-build`). +# Each is skipped when `E2E_SKIP_BUILD` is set (used by `e2e-tests-skip-build`). [tasks.build-mpc-node-network-hardship-simulation] description = "Build the mpc-node binary used by the E2E tests" @@ -202,7 +202,11 @@ args = [ ] [tasks.build-tee-verifier-optimized] -description = "Build the tee-verifier WASM for localnet" +description = "Build the tee-verifier WASM for localnet and the E2E tests" +# `scripts/launch-localnet.sh` tells operators to run this task by hand; with +# `E2E_SKIP_BUILD` exported it no-ops (cargo-make logs "Skipping Task"), and the E2E +# loader's panic names this task so a missing WASM points back here. +condition = { env_not_set = ["E2E_SKIP_BUILD"] } command = "cargo" args = [ "near", @@ -252,6 +256,7 @@ private = true dependencies = [ "build-mpc-node-network-hardship-simulation", "build-mpc-contract-optimized", + "build-tee-verifier-optimized", "build-test-parallel-contract-optimized", "build-backup-cli", ] @@ -272,6 +277,7 @@ args = [ [tasks._run-e2e-logic.env] MPC_CONTRACT_WASM = "${CARGO_MAKE_WORKING_DIRECTORY}/target/near/mpc_contract/mpc_contract.wasm" MPC_PARALLEL_CONTRACT_WASM = "${CARGO_MAKE_WORKING_DIRECTORY}/target/near/test_parallel_contract/test_parallel_contract.wasm" +MPC_TEE_VERIFIER_WASM = "${CARGO_MAKE_WORKING_DIRECTORY}/target/near/tee_verifier/tee_verifier.wasm" # Build the mpc-node binary and both contract WASMs, then run the E2E tests. [tasks.e2e-tests] diff --git a/crates/e2e-tests/Cargo.toml b/crates/e2e-tests/Cargo.toml index 76313cef71..85b3cb45a3 100644 --- a/crates/e2e-tests/Cargo.toml +++ b/crates/e2e-tests/Cargo.toml @@ -29,6 +29,7 @@ rand = { workspace = true } reqwest = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +sha2 = { workspace = true } tempfile = { workspace = true } test-port-allocator = { workspace = true } test-utils = { workspace = true } diff --git a/crates/e2e-tests/README.md b/crates/e2e-tests/README.md index d8cfb049ec..dddd71bb48 100644 --- a/crates/e2e-tests/README.md +++ b/crates/e2e-tests/README.md @@ -171,12 +171,16 @@ The entry point for tests. `MpcCluster::start(config)` does everything: 8. Call `init()` on the contract with the initial participants. 9. Call `submit_participant_info` for each initial participant (with a `{"Mock": "Valid"}` attestation — enough to satisfy the contract in tests). -10. Spawn the `mpc-node` binaries (start *before* adding domains so key +10. Deploy the tee-verifier WASM to `tee-verifier.sandbox` and vote it in from + every participant, for topology parity with production. Mock attestations + are verified without calling it, so the verifier stays idle; the + cross-contract flow is covered by the mpc-contract sandbox tests. +11. Spawn the `mpc-node` binaries (start *before* adding domains so key generation has running nodes to talk to). -11. Sleep briefly and assert no node exited early. -12. If `config.domains` is non-empty, vote `add_domains` from each participant +12. Sleep briefly and assert no node exited early. +13. If `config.domains` is non-empty, vote `add_domains` from each participant and wait for `Running` state. -13. Create user accounts for signing/CKD/verify requests. +14. Create user accounts for signing/CKD/verify requests. The returned cluster exposes: @@ -207,6 +211,7 @@ pub struct MpcClusterConfig { pub domains: Vec, pub binary_paths: Vec, // one or num_nodes pub contract_wasm: Vec, // pre-compiled by the test + pub tee_verifier_wasm: Vec, // loaded via MPC_TEE_VERIFIER_WASM pub port_seed: u16, pub triples_to_buffer: usize, pub presignatures_to_buffer: usize, diff --git a/crates/e2e-tests/src/cluster.rs b/crates/e2e-tests/src/cluster.rs index 058d8f0de9..582353fbf1 100644 --- a/crates/e2e-tests/src/cluster.rs +++ b/crates/e2e-tests/src/cluster.rs @@ -24,6 +24,7 @@ use near_mpc_contract_interface::{ use rand::SeedableRng; use rand::rngs::StdRng; use serde_json::json; +use sha2::{Digest, Sha256}; use crate::blockchain::{DeployedContract, NearBlockchain, NearKitCaller}; use crate::mpc_node::{MpcNode, MpcNodeSetup, MpcNodeSetupArgs, NodePorts}; @@ -71,6 +72,7 @@ const KEY_SEED_P2P: u64 = 100; const KEY_SEED_OPERATOR: u64 = 200; const KEY_SEED_MIGRATION_P2P: u64 = 300; const KEY_SEED_MIGRATION_NEAR_SIGNER: u64 = 400; +const KEY_SEED_TEE_VERIFIER: u64 = 500; /// Configuration for creating a new [`MpcCluster`]. pub struct MpcClusterConfig { @@ -84,6 +86,12 @@ pub struct MpcClusterConfig { pub binary_paths: Vec, /// Compiled contract WASM bytes (pre-compiled by the test). pub contract_wasm: Vec, + /// Compiled tee-verifier WASM bytes, deployed and voted in during cluster + /// startup for topology parity with production. Nodes in e2e clusters + /// submit mock attestations, which the MPC contract verifies without + /// calling the verifier; the cross-contract flow itself is covered by the + /// mpc-contract sandbox tests. + pub tee_verifier_wasm: Vec, /// Port seed for the port allocator (must be unique across parallel tests). pub port_seed: u16, /// Triple buffer size per node. @@ -196,6 +204,7 @@ impl MpcClusterConfig { ], binary_paths: vec![default_mpc_binary_path()], contract_wasm, + tee_verifier_wasm: must_load_tee_verifier_wasm(), port_seed, triples_to_buffer: DEFAULT_TRIPLES_TO_BUFFER, presignatures_to_buffer: DEFAULT_PRESIGNATURES_TO_BUFFER, @@ -226,6 +235,15 @@ impl MpcClusterConfig { self.num_nodes, ); } + // Startup indexes the key vectors by participant index, so an out-of-range + // entry here would otherwise surface as a panic mid-startup. + for (i, &participant_idx) in self.initial_participant_indices.iter().enumerate() { + anyhow::ensure!( + participant_idx < self.num_nodes, + "initial_participant_indices[{i}]: index {participant_idx} must be < num_nodes ({})", + self.num_nodes, + ); + } Ok(()) } } @@ -234,6 +252,41 @@ fn default_mpc_binary_path() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../target/release/mpc-node") } +/// Plumbing helper: failures here are setup bugs, not test failures, so we panic. +pub fn must_load_tee_verifier_wasm() -> Vec { + if let Ok(path) = std::env::var("MPC_TEE_VERIFIER_WASM") { + let wasm_path = PathBuf::from(&path); + return std::fs::read(&wasm_path).unwrap_or_else(|e| { + panic!( + "failed to read tee-verifier WASM at {}: {e}. Build it with \ + `cargo make build-tee-verifier-optimized` (skipped when E2E_SKIP_BUILD is set)", + wasm_path.display() + ) + }); + } + + let default_path = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../../target/near/tee_verifier/tee_verifier.wasm"); + if default_path.exists() { + return std::fs::read(&default_path).unwrap_or_else(|e| { + panic!( + "failed to read tee-verifier WASM at {}: {e}", + default_path.display() + ) + }); + } + + tracing::info!( + "MPC_TEE_VERIFIER_WASM not set and pre-built WASM not found; building tee-verifier. \ + Build it up front with `cargo make build-tee-verifier-optimized` to skip this." + ); + // Same out dir the probe above checks, so this build is found and reused + // by later test processes instead of rebuilding each time. + test_utils::contract_build::ContractBuilder::new("crates/tee-verifier/Cargo.toml") + .out_dir("target/near/tee_verifier") + .build() +} + /// A running MPC test cluster with a deployed contract and N mpc-node processes. /// /// Orchestrates the full test environment: sandbox -> contract -> @@ -322,6 +375,15 @@ impl MpcCluster { ) .await?; + deploy_and_trust_tee_verifier( + &blockchain, + &contract, + &config.tee_verifier_wasm, + &operator_keys, + &participant_indices, + ) + .await?; + // Start MPC nodes BEFORE adding domains: key generation requires running nodes. let mut nodes = start_mpc_nodes( &config, @@ -1356,6 +1418,75 @@ async fn init_contract( .context("contract did not reach Running state after init") } +/// Deploys the tee-verifier and votes it in from every participant, mirroring +/// the production topology (cf. `scripts/launch-localnet.sh`). +async fn deploy_and_trust_tee_verifier( + blockchain: &NearBlockchain, + contract: &DeployedContract, + verifier_wasm: &[u8], + operator_keys: &[SigningKey], + participant_indices: &[usize], +) -> anyhow::Result<()> { + let verifier_account = format!("tee-verifier.{SANDBOX_ROOT_ACCOUNT}"); + let verifier_key = generate_deterministic_key(KEY_SEED_TEE_VERIFIER); + tracing::info!(account = %verifier_account, "deploying tee-verifier contract"); + // The verifier is stateless, so there is no initializer to call on deploy. + blockchain + .create_account_and_deploy(&verifier_account, 100, &verifier_key, verifier_wasm) + .await?; + + // expected_code_hash commits every voter to the same audited WASM; the + // contract only compares voters' hashes against each other, not against + // the deployed bytes. + let expected_code_hash = hex::encode(Sha256::digest(verifier_wasm)); + let args = json!({ + "candidate_account_id": verifier_account, + "expected_code_hash": expected_code_hash, + }); + for &i in participant_indices { + let account = node_account(i); + let client = blockchain.client_for(&account, &operator_keys[i])?; + let outcome = contract + .call_from( + &client, + method_names::VOTE_TEE_VERIFIER_CHANGE, + args.clone(), + ) + .await + .with_context(|| format!("node {i} failed to vote for the tee-verifier"))?; + anyhow::ensure!( + outcome.is_success(), + "node {i}'s tee-verifier vote failed: {:?}", + outcome.failure_message() + ); + } + + // The votes are final, but views can briefly lag them; poll like the + // post-init state waits do. + let timeout = Duration::from_secs(30); + let max_times = (timeout.as_millis() / POLL_INTERVAL.as_millis()) as usize; + (|| async { + let resolved: Option = contract.view(method_names::TEE_VERIFIER_ACCOUNT_ID).await?; + anyhow::ensure!( + resolved.as_deref() == Some(verifier_account.as_str()), + "tee-verifier vote has not crossed threshold, resolved verifier: {resolved:?}" + ); + Ok(()) + }) + .retry( + ConstantBuilder::default() + .with_delay(POLL_INTERVAL) + .with_max_times(max_times), + ) + .await + .with_context(|| { + format!( + "tee-verifier not resolved as the trusted verifier within {}s", + timeout.as_secs() + ) + }) +} + async fn add_initial_domains( blockchain: &NearBlockchain, contract: &DeployedContract, From 3152d13f0cb559b6b0f0fec1c1a5d2766bc7da28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 13:35:19 +0200 Subject: [PATCH 23/32] docs: align attestation testing docs with the shipped sandbox coverage The design doc's Testing section described a stub verifier that was built and then dropped during implementation; it now states the shipped approach, with a status note recording the supersession. The two verifier runbooks gain a pointer to the cross-contract sandbox coverage alongside the existing unit test. --- docs/deploy-tee-verifier.md | 3 ++- docs/design/attestation-verifier-contract.md | 10 +++++++--- docs/localnet/localnet.md | 3 ++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/deploy-tee-verifier.md b/docs/deploy-tee-verifier.md index 29384a93cd..57fecb91a4 100644 --- a/docs/deploy-tee-verifier.md +++ b/docs/deploy-tee-verifier.md @@ -106,7 +106,8 @@ Optionally confirm the contract executes by calling `verify_quote` read-only wit committed fixture. Either outcome proves the DCAP path runs: a verified report while the fixture's collateral is inside its validity window, or `TCBInfo expired` once the live clock passes it. Tests pin the verification clock instead of relying on that -window (`crates/tee-verifier/tests/verify_quote.rs`): +window (`crates/tee-verifier/tests/verify_quote.rs` and, cross-contract, the sandbox +tests in `crates/contract/tests/sandbox/tee_verifier.rs`): ```shell near contract call-function as-read-only "$VERIFIER_ACCOUNT" verify_quote file-args crates/tee-verifier/tests/fixtures/verify_quote_args.borsh network-config "$NETWORK" now diff --git a/docs/design/attestation-verifier-contract.md b/docs/design/attestation-verifier-contract.md index d64cee47c0..e3e93be0b5 100644 --- a/docs/design/attestation-verifier-contract.md +++ b/docs/design/attestation-verifier-contract.md @@ -611,11 +611,15 @@ The yield-resume split adds four resolution branches the synchronous version nev The verifier-rotation design changes the test surface in three ways. First, the expiration window itself: an entry whose `expiry_timestamp_seconds` is in the past must be rejected by `re_verify` even when every post-DCAP allowlist invariant still holds, and an entry within the (shortened) window must still pass — this is the existing expiry check, now exercised against the lowered `DEFAULT_EXPIRATION_DURATION_SECONDS`. Second, rotation routing: after `vote_tee_verifier_change` crosses threshold, the next `submit_participant_info` must call `verify_quote` on the new `tee_verifier_account_id`, and existing stored entries must remain present (no purge) until they expire. Third, the in-flight case: a verification scheduled against the old verifier that resolves after the vote crosses threshold must still be stored as a normal entry — it is not treated specially and ages out via the same expiration window as any other entry. -To make that practical, we introduce a stub `tee-verifier` crate: same `tee-verifier-interface` DTOs as the real verifier, but `verify_quote` returns whatever `VerificationResult` (`Verified` or `Rejected`) the test asks for — and a stub that panics, or an undeployed account, covers the no-verdict path. Sandbox tests deploy the stub like any other verifier candidate — lock its account, then call `vote_tee_verifier_change` from the test setup to point `mpc-contract` at the stub. This runs the same code path as production; nothing in `mpc-contract` knows or cares whether it's talking to the real verifier or the stub. +Status: no stub verifier exists. The design below was superseded during implementation, because a second contract mirroring the real one duplicated it for little gain. -E2E tests in `crates/e2e-tests` deploy either the real `tee-verifier` (when the test wants real `dcap-qvl` against a fixture quote) or the stub (for everything else). The change is one extra `deploy` call in the setup helper. +Sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` deploy the real `tee-verifier` WASM and drive each verdict through `vote_tee_verifier_change` + `submit_participant_info`: `Rejected` with a malformed quote, no-verdict with an undeployed verifier account, and `Verified` with the fixture quote. `Verified` needs the verifier built with the `sandbox-test-hooks` feature, which lets the test pin the timestamp `verify_quote` verifies against: the fixture collateral is valid only inside a fixed window, while sandbox time is wall-clock and forward-only. -`Attestation::Mock` stays in this iteration. The stub eventually supersedes it — both let tests bypass real `dcap-qvl` — but removing `Mock` is a separate cleanup, not in scope here. +Tests that assert the *store* additionally sign as the fixture account, because the quote's report_data binds that account key; the committed fixture secret key (`crates/test-utils/assets/near_account_secret_key`) makes that signature possible. + +E2E tests in `crates/e2e-tests` deploy the real `tee-verifier` and vote it in during cluster startup for topology parity; nodes there submit mock attestations, which the MPC contract verifies without calling the verifier, so the cross-contract flow is covered at the sandbox layer. + +`Attestation::Mock` stays in this iteration; removing it is a separate cleanup, not in scope here. [nep-509]: https://github.com/near/NEPs/blob/master/neps/nep-0509.md [re-verify]: https://github.com/near/mpc/blob/5e47bfe93b398cb2343681fa2c0f2691d02c7285/crates/mpc-attestation/src/attestation.rs#L93 diff --git a/docs/localnet/localnet.md b/docs/localnet/localnet.md index 6a51410eef..2620f85379 100644 --- a/docs/localnet/localnet.md +++ b/docs/localnet/localnet.md @@ -347,7 +347,8 @@ Either outcome proves the DCAP path runs: a verified report while the fixture's collateral is still inside its validity window (it ends at the `nextUpdate` in `crates/test-utils/assets/collateral.json`), and `TCBInfo expired` once the live block clock passes it. Tests pin the verification clock instead -(`crates/tee-verifier/tests/verify_quote.rs`). Regenerate the +(`crates/tee-verifier/tests/verify_quote.rs`, and cross-contract +`crates/contract/tests/sandbox/tee_verifier.rs`). Regenerate the fixture (after changing the quote/collateral fixtures) with: ```shell From a43e53a38522efea0c05724af88c209dc2cc6e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 10 Aug 2026 15:56:47 +0200 Subject: [PATCH 24/32] test(e2e): use call_from_with_deposit for the tee-verifier vote DeployedContract::call_from is gone; the typed MpcContractHandle methods that replaced it do not cover vote_tee_verifier_change yet, so the vote goes through the surviving explicit-gas variant with a zero deposit. Also documents in the asset runbook that the sandbox wasm reaches the fixture's app-compose through mpc-contract/sandbox-test-attestation, and that the tests signing as the fixture account need the committed secret key. --- crates/e2e-tests/src/cluster.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/e2e-tests/src/cluster.rs b/crates/e2e-tests/src/cluster.rs index 582353fbf1..bc7b585ad5 100644 --- a/crates/e2e-tests/src/cluster.rs +++ b/crates/e2e-tests/src/cluster.rs @@ -55,6 +55,8 @@ pub fn cluster_poll_retry() -> ConstantBuilder { ) } +const VOTE_TEE_VERIFIER_GAS: near_kit::Gas = near_kit::Gas::from_tgas(100); + // The contract's default `key_event_timeout_blocks = 30` is ~18 s on // mainnet (~600 ms blocks). The e2e sandbox runs ~8 blocks/s, so the // same 30 collapses to ~3.7 s — too tight for the resharing @@ -1447,10 +1449,12 @@ async fn deploy_and_trust_tee_verifier( let account = node_account(i); let client = blockchain.client_for(&account, &operator_keys[i])?; let outcome = contract - .call_from( + .call_from_with_deposit( &client, method_names::VOTE_TEE_VERIFIER_CHANGE, args.clone(), + VOTE_TEE_VERIFIER_GAS, + near_kit::NearToken::from_yoctonear(0), ) .await .with_context(|| format!("node {i} failed to vote for the tee-verifier"))?; From f0a95b052e55c17945ed6747959f26936e77979c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Fri, 14 Aug 2026 00:30:24 +0200 Subject: [PATCH 25/32] test(contract): whitelist the fixture compose hash from a sandbox-only method The fixture is captured from a CVM whose launcher compose carries the service that exported its signer key, so its compose hash is not derivable from the compiled-in template and no vote can allow it. `sandbox-test-attestation` now gates a method that whitelists that one hash, replacing the app-compose policy relaxation the feature used to enable. --- crates/contract/Cargo.toml | 5 ++- crates/contract/src/lib.rs | 2 ++ .../contract/src/sandbox_test_attestation.rs | 23 +++++++++++++ crates/contract/src/tee/proposal.rs | 2 +- crates/contract/tests/sandbox/common.rs | 6 ++-- crates/contract/tests/sandbox/tee_verifier.rs | 34 +++++++++++++------ .../tests/sandbox/utils/contract_build.rs | 7 ++-- .../tests/sandbox/utils/mpc_contract.rs | 24 ++++++++++++- 8 files changed, 81 insertions(+), 22 deletions(-) create mode 100644 crates/contract/src/sandbox_test_attestation.rs diff --git a/crates/contract/Cargo.toml b/crates/contract/Cargo.toml index c82cc63d1f..fecfffc15d 100644 --- a/crates/contract/Cargo.toml +++ b/crates/contract/Cargo.toml @@ -59,9 +59,8 @@ bench-contract-methods = [] # length of a fan-out queue). Distinct from `bench-contract-methods` because these are # behavioral hooks, not gas-measurement hooks. sandbox-test-methods = [] -# Sandbox-only method that whitelists one launcher compose hash directly. The attestation fixture is -# captured from a CVM whose launcher compose carries a key-export service, so its hash is not derivable -# from the compiled-in template and cannot be voted in. +# Sandbox-only method that whitelists one launcher compose hash directly, for the attestation +# fixture, whose compose hash is not derivable from the compiled-in template. sandbox-test-attestation = [] dev-utils = ["rand", "threshold-signatures", "near-mpc-contract-interface/blstrs"] abi = [ diff --git a/crates/contract/src/lib.rs b/crates/contract/src/lib.rs index 0900963183..3e6a7c4bb7 100644 --- a/crates/contract/src/lib.rs +++ b/crates/contract/src/lib.rs @@ -22,6 +22,8 @@ pub mod v3_14_0_state; mod bench; mod dto_mapping; mod pending_requests; +#[cfg(feature = "sandbox-test-attestation")] +mod sandbox_test_attestation; #[cfg(feature = "sandbox-test-methods")] mod sandbox_test_methods; diff --git a/crates/contract/src/sandbox_test_attestation.rs b/crates/contract/src/sandbox_test_attestation.rs new file mode 100644 index 0000000000..60ba40b041 --- /dev/null +++ b/crates/contract/src/sandbox_test_attestation.rs @@ -0,0 +1,23 @@ +//! Sandbox-only whitelisting of the attestation fixture's launcher compose hash. +//! +//! Compose hashes otherwise enter the allowlist only by derivation from the compiled-in template, +//! and the fixture's compose carries the service that exported its signer key, so no vote can +//! allow it. Gated so no released artifact carries this. + +use crate::{MpcContract, MpcContractExt}; +use mpc_primitives::hash::{LauncherDockerComposeHash, LauncherImageHash}; +use near_sdk::near; + +#[near] +impl MpcContract { + /// Panics if `launcher_hash` is not allowed yet, so callers vote it in first. + pub fn sandbox_allow_launcher_compose_hash( + &mut self, + launcher_hash: LauncherImageHash, + compose_hash: LauncherDockerComposeHash, + ) { + self.tee_state + .allowed_launcher_images + .allow_compose_hash(&launcher_hash, compose_hash); + } +} diff --git a/crates/contract/src/tee/proposal.rs b/crates/contract/src/tee/proposal.rs index a1c7ae0355..b5ef13213c 100644 --- a/crates/contract/src/tee/proposal.rs +++ b/crates/contract/src/tee/proposal.rs @@ -491,7 +491,7 @@ impl AllowedLauncherImages { /// Test-only: allows one more compose hash for an already-allowed launcher. The attestation /// fixture is captured from a CVM whose launcher compose carries a key-export service, so /// [`get_docker_compose_hash`] cannot derive its hash. - #[cfg(test)] + #[cfg(any(test, feature = "sandbox-test-attestation"))] pub(crate) fn allow_compose_hash( &mut self, launcher_hash: &LauncherImageHash, diff --git a/crates/contract/tests/sandbox/common.rs b/crates/contract/tests/sandbox/common.rs index fc630afee4..1ba6b8dfd5 100644 --- a/crates/contract/tests/sandbox/common.rs +++ b/crates/contract/tests/sandbox/common.rs @@ -243,9 +243,9 @@ impl SandboxTestSetupBuilder { self } - /// Deploys the wasm built with `--features sandbox-test-attestation`, which accepts the - /// attestation fixture's app-compose. Required by tests that submit the Dstack fixture - /// and expect it to verify. + /// Deploys the wasm built with `--features sandbox-test-attestation`, which can whitelist + /// the attestation fixture's launcher compose hash. Required by tests that submit the + /// Dstack fixture and expect it to verify. pub fn with_sandbox_test_attestation(mut self) -> Self { self.wasm = TestWasm::SandboxTestAttestation; self diff --git a/crates/contract/tests/sandbox/tee_verifier.rs b/crates/contract/tests/sandbox/tee_verifier.rs index 25d1554181..8f2c029f1b 100644 --- a/crates/contract/tests/sandbox/tee_verifier.rs +++ b/crates/contract/tests/sandbox/tee_verifier.rs @@ -6,7 +6,9 @@ //! time pinned to the fixture's validity window. The pin is needed because //! real `verify_quote` checks the quote against block time: the fixture //! collateral is valid only inside a fixed window, while sandbox time is -//! wall-clock and forward-only. +//! wall-clock and forward-only. These tests also deploy the contract built +//! with `sandbox-test-attestation`, since the compose that exported the +//! fixture key hashes outside the derivable set. //! //! Verified-path tests that store an attestation sign as the fixture account: //! the quote's report_data binds the fixture account key, and the contract @@ -20,9 +22,10 @@ use crate::sandbox::{ contract_build::{tee_verifier_contract, tee_verifier_contract_with_sandbox_test_hooks}, mpc_contract::{ get_config, get_participant_attestation, get_tee_accounts, - prepay_and_submit_participant_info, prepay_attestation_grants, submit_participant_info, - tee_verifier_account_id, total_gas_fee, vote_add_launcher_hash, - vote_add_os_measurement, vote_for_hash, vote_tee_verifier_change, + prepay_and_submit_participant_info, prepay_attestation_grants, + sandbox_allow_launcher_compose_hash, submit_participant_info, tee_verifier_account_id, + total_gas_fee, vote_add_launcher_hash, vote_add_os_measurement, vote_for_hash, + vote_tee_verifier_change, }, }, }; @@ -55,7 +58,7 @@ async fn setup() -> SandboxTestSetup { } /// Setup for tests that expect the fixture to pass the post-DCAP checks, which needs the -/// wasm that accepts its app-compose. +/// wasm that can whitelist its launcher compose hash. async fn setup_accepting_fixture_attestation() -> SandboxTestSetup { SandboxTestSetup::builder() .with_protocols(ALL_PROTOCOLS) @@ -109,10 +112,13 @@ async fn deploy_and_trust_pinned_verifier( verifier } -/// Votes the fixture's image and launcher hashes into the on-chain allowlists. -/// The image hash must be voted in before the launcher hash: allowed compose -/// hashes are derived from the currently allowed image hashes. Within a round -/// the voters are distinct accounts, so the votes run concurrently. +/// Votes the fixture's image and launcher hashes into the on-chain allowlists, then +/// whitelists the fixture's compose hash, which derivation cannot produce. The image hash +/// must be voted in before the launcher hash: allowed compose hashes are derived from the +/// currently allowed image hashes. Within a round the voters are distinct accounts, so the +/// votes run concurrently. +/// +/// Requires the `sandbox-test-attestation` wasm. async fn whitelist_fixture_dstack_hashes(contract: &Contract, participants: &[Account]) { let image = image_digest(); for result in join_all( @@ -134,6 +140,14 @@ async fn whitelist_fixture_dstack_hashes(contract: &Contract, participants: &[Ac { result.unwrap(); } + sandbox_allow_launcher_compose_hash( + &participants[0], + contract, + &launcher, + &launcher_compose_digest(), + ) + .await + .unwrap(); } /// Adds the OS measurements on top of the hash allowlists, the sandbox @@ -405,7 +419,7 @@ async fn submit_participant_info__should_run_dcap_within_verifier_gas_budget() { mpc_signer_accounts, contract, .. - } = setup().await; + } = setup_accepting_fixture_attestation().await; let verifier = deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await; // Only the hash allowlists gate this test's outcome: the plain dev-account // submitter fails at report_data, which runs before the measurements check. diff --git a/crates/contract/tests/sandbox/utils/contract_build.rs b/crates/contract/tests/sandbox/utils/contract_build.rs index 7841c50a4d..6e48b26655 100644 --- a/crates/contract/tests/sandbox/utils/contract_build.rs +++ b/crates/contract/tests/sandbox/utils/contract_build.rs @@ -53,10 +53,9 @@ pub fn current_contract_with_sandbox_test_methods() -> &'static [u8] { }) } -/// Returns the current contract WASM that accepts the attestation fixture's app-compose. -/// Use this only for tests that submit the Dstack fixture and need it to verify: the -/// fixture carries the `pre_launch_script` that exported its signer key, which the -/// production policy rejects. +/// Returns the current contract WASM that can whitelist the fixture's launcher compose hash. +/// Use this only for tests that submit the Dstack fixture and need it to verify: that compose +/// hash is not derivable from the compiled-in template, so no vote can allow it. pub fn current_contract_with_sandbox_test_attestation() -> &'static [u8] { CONTRACT_WITH_SANDBOX_TEST_ATTESTATION.get_or_init(|| { ContractBuilder::new(MPC_CONTRACT_MANIFEST) diff --git a/crates/contract/tests/sandbox/utils/mpc_contract.rs b/crates/contract/tests/sandbox/utils/mpc_contract.rs index f93c291191..69debe968c 100644 --- a/crates/contract/tests/sandbox/utils/mpc_contract.rs +++ b/crates/contract/tests/sandbox/utils/mpc_contract.rs @@ -4,7 +4,9 @@ use crate::sandbox::utils::transactions::CallMpcContract; use super::transactions::all_receipts_successful; use mpc_contract::tee::{measurements::ContractExpectedMeasurements, tee_state::NodeId}; -use mpc_primitives::hash::{LauncherImageHash, NodeImageHash, TeeVerifierCodeHash}; +use mpc_primitives::hash::{ + LauncherDockerComposeHash, LauncherImageHash, NodeImageHash, TeeVerifierCodeHash, +}; use near_mpc_contract_interface::{ method_names, types::{ @@ -210,6 +212,26 @@ pub async fn vote_add_launcher_hash( Ok(()) } +/// Whitelists `compose_hash` for `launcher_hash` through the `sandbox-test-attestation` +/// method, which is absent from the production wasm. Vote the launcher hash in first. +pub async fn sandbox_allow_launcher_compose_hash( + account: &Account, + contract: &Contract, + launcher_hash: &LauncherImageHash, + compose_hash: &LauncherDockerComposeHash, +) -> anyhow::Result<()> { + let result = account + .call(contract.id(), "sandbox_allow_launcher_compose_hash") + .args_json(serde_json::json!({ + "launcher_hash": launcher_hash, + "compose_hash": compose_hash, + })) + .transact() + .await?; + all_receipts_successful(result)?; + Ok(()) +} + pub async fn vote_add_os_measurement( account: &Account, contract: &Contract, From 4e6f821e2b0673685de70b4c10d872df68d185a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Fri, 14 Aug 2026 00:30:24 +0200 Subject: [PATCH 26/32] docs: correct the verifier storage claim and the E2E build inventory `verify_quote` takes `&self`, so near-sdk reads the STATE key on every call: production builds never read the pinned-timestamp key, but they do read storage. The E2E task runner builds five things, not three, and passes three WASM paths. The design doc's status line pointed at the shipped design as if it were the superseded one. --- Makefile.toml | 3 --- crates/e2e-tests/README.md | 13 +++++++------ crates/tee-verifier-interface/src/lib.rs | 6 +++--- crates/tee-verifier/src/lib.rs | 7 +++---- docs/design/attestation-verifier-contract.md | 4 ++-- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Makefile.toml b/Makefile.toml index 04b9fac305..c3b243292e 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -203,9 +203,6 @@ args = [ [tasks.build-tee-verifier-optimized] description = "Build the tee-verifier WASM for localnet and the E2E tests" -# `scripts/launch-localnet.sh` tells operators to run this task by hand; with -# `E2E_SKIP_BUILD` exported it no-ops (cargo-make logs "Skipping Task"), and the E2E -# loader's panic names this task so a missing WASM points back here. condition = { env_not_set = ["E2E_SKIP_BUILD"] } command = "cargo" args = [ diff --git a/crates/e2e-tests/README.md b/crates/e2e-tests/README.md index dddd71bb48..d7d3a2d549 100644 --- a/crates/e2e-tests/README.md +++ b/crates/e2e-tests/README.md @@ -335,12 +335,13 @@ so any nextest filter or flag works (substring filters, `-E` expressions, runs with the `ci-e2e` profile. Do not put flags after a `--` separator: it is forwarded verbatim, and nextest only accepts filters, not flags, after `--`. -The task runner builds three things before tests run: the mpc-node binary -with the `network-hardship-simulation` feature, the MPC contract WASM, and -the test parallel contract WASM. Paths are passed to tests via the -`MPC_CONTRACT_WASM` and `MPC_PARALLEL_CONTRACT_WASM` environment variables -read by `must_load_contract_wasm` / `must_load_parallel_contract_wasm` in -`tests/common.rs`; if the env var is unset and no pre-built WASM is found, +The task runner builds five things before tests run: the mpc-node binary with +the `network-hardship-simulation` feature, the MPC contract WASM, the +tee-verifier WASM, the test parallel contract WASM, and the backup CLI. WASM +paths are passed to tests via the `MPC_CONTRACT_WASM`, +`MPC_TEE_VERIFIER_WASM` and `MPC_PARALLEL_CONTRACT_WASM` environment +variables, read by the `must_load_*` helpers in `tests/common.rs` and +`src/cluster.rs`; if the env var is unset and no pre-built WASM is found, `test-utils::contract_build::ContractBuilder` builds it on the fly (useful for local iteration). diff --git a/crates/tee-verifier-interface/src/lib.rs b/crates/tee-verifier-interface/src/lib.rs index 19913c85a4..48321cddaf 100644 --- a/crates/tee-verifier-interface/src/lib.rs +++ b/crates/tee-verifier-interface/src/lib.rs @@ -194,9 +194,9 @@ pub enum VerificationResult { /// verifies against, as u64 little-endian seconds since the Unix epoch. /// /// Honored only by verifier builds with the `sandbox-test-hooks` feature; -/// production builds read no storage at all. Tests write it from outside the -/// contract (state patching), which is why the key must be shared between the -/// verifier and its callers' test suites rather than staying private. +/// production builds never read it. Tests write it from outside the contract +/// (state patching), which is why the key must be shared between the verifier +/// and its callers' test suites rather than staying private. pub const SANDBOX_TEST_PINNED_NOW_STORAGE_KEY: &[u8] = b"sandbox_test_pinned_now_seconds"; #[cfg(test)] diff --git a/crates/tee-verifier/src/lib.rs b/crates/tee-verifier/src/lib.rs index 11eb70b58d..547bef16ff 100644 --- a/crates/tee-verifier/src/lib.rs +++ b/crates/tee-verifier/src/lib.rs @@ -67,10 +67,9 @@ impl TeeVerifier { } /// The timestamp quotes are verified against: block time, unless a sandbox test -/// pinned one under [`tee_verifier_interface::SANDBOX_TEST_PINNED_NOW_STORAGE_KEY`] -/// (spelled in full because the import is feature-gated). The pin exists -/// because sandbox chain time is wall-clock and forward-only, so it can never -/// fall inside the validity window of a checked-in collateral fixture. +/// pinned one under [`tee_verifier_interface::SANDBOX_TEST_PINNED_NOW_STORAGE_KEY`]. +/// The pin exists because sandbox chain time is wall-clock and forward-only, so it +/// can never fall inside the validity window of a checked-in collateral fixture. fn now_seconds() -> u64 { #[cfg(feature = "sandbox-test-hooks")] if let Some(bytes) = env::storage_read(SANDBOX_TEST_PINNED_NOW_STORAGE_KEY) { diff --git a/docs/design/attestation-verifier-contract.md b/docs/design/attestation-verifier-contract.md index e3e93be0b5..3fce98bba0 100644 --- a/docs/design/attestation-verifier-contract.md +++ b/docs/design/attestation-verifier-contract.md @@ -611,9 +611,9 @@ The yield-resume split adds four resolution branches the synchronous version nev The verifier-rotation design changes the test surface in three ways. First, the expiration window itself: an entry whose `expiry_timestamp_seconds` is in the past must be rejected by `re_verify` even when every post-DCAP allowlist invariant still holds, and an entry within the (shortened) window must still pass — this is the existing expiry check, now exercised against the lowered `DEFAULT_EXPIRATION_DURATION_SECONDS`. Second, rotation routing: after `vote_tee_verifier_change` crosses threshold, the next `submit_participant_info` must call `verify_quote` on the new `tee_verifier_account_id`, and existing stored entries must remain present (no purge) until they expire. Third, the in-flight case: a verification scheduled against the old verifier that resolves after the vote crosses threshold must still be stored as a normal entry — it is not treated specially and ages out via the same expiration window as any other entry. -Status: no stub verifier exists. The design below was superseded during implementation, because a second contract mirroring the real one duplicated it for little gain. +Status: the stub verifier this section originally proposed was dropped during implementation, because a second contract mirroring the real one duplicated it for little gain. What shipped: -Sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` deploy the real `tee-verifier` WASM and drive each verdict through `vote_tee_verifier_change` + `submit_participant_info`: `Rejected` with a malformed quote, no-verdict with an undeployed verifier account, and `Verified` with the fixture quote. `Verified` needs the verifier built with the `sandbox-test-hooks` feature, which lets the test pin the timestamp `verify_quote` verifies against: the fixture collateral is valid only inside a fixed window, while sandbox time is wall-clock and forward-only. +Sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` deploy the real `tee-verifier` WASM and drive each verdict through `vote_tee_verifier_change` + `submit_participant_info`: `Rejected` with a malformed quote, no-verdict with an undeployed verifier account, and `Verified` with the fixture quote. `Verified` needs the verifier built with `sandbox-test-hooks`, which lets the test pin the timestamp `verify_quote` verifies against (the fixture collateral is valid only inside a fixed window, while sandbox time is wall-clock and forward-only), and the contract built with `sandbox-test-attestation`, which whitelists the fixture's launcher compose hash. Tests that assert the *store* additionally sign as the fixture account, because the quote's report_data binds that account key; the committed fixture secret key (`crates/test-utils/assets/near_account_secret_key`) makes that signature possible. From fa72523299cae2e40134d5540bd95815764ac4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 17 Aug 2026 11:44:32 +0200 Subject: [PATCH 27/32] chore: make released wasm builds reject the sandbox test features --- crates/contract/src/lib.rs | 10 ++++++++++ crates/tee-verifier/src/lib.rs | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/crates/contract/src/lib.rs b/crates/contract/src/lib.rs index 11fe02921b..3f9657a32a 100644 --- a/crates/contract/src/lib.rs +++ b/crates/contract/src/lib.rs @@ -28,6 +28,16 @@ mod sandbox_test_attestation; #[cfg(feature = "sandbox-test-methods")] mod sandbox_test_methods; +// The released wasm is the only build that passes `abi` (the reproducible build +// command); sandbox test builds are wasm32 without it, and `--all-features` +// checks run on the host. +#[cfg(all( + target_arch = "wasm32", + feature = "abi", + feature = "sandbox-test-attestation" +))] +compile_error!("sandbox-test-attestation must never be enabled in a released wasm build"); + /// Re-export of the fan-out cap so sandbox tests can lock against the same source of /// truth as the contract rather than duplicating the literal. #[cfg(feature = "sandbox-test-methods")] diff --git a/crates/tee-verifier/src/lib.rs b/crates/tee-verifier/src/lib.rs index 547bef16ff..9e88a36335 100644 --- a/crates/tee-verifier/src/lib.rs +++ b/crates/tee-verifier/src/lib.rs @@ -15,6 +15,16 @@ use tee_verifier_interface::{Collateral, QuoteBytes, VerificationResult, Verifie use tee_verifier_conversions::{IntoDcapType as _, IntoInterfaceType as _}; +// The released wasm is the only build that passes `abi` (the reproducible build +// command); sandbox test builds are wasm32 without it, and `--all-features` +// checks run on the host. +#[cfg(all( + target_arch = "wasm32", + feature = "abi", + feature = "sandbox-test-hooks" +))] +compile_error!("sandbox-test-hooks must never be enabled in a released wasm build"); + // `dcap-qvl`'s `contract` feature pulls in `getrandom` but doesn't enable // any backend. On `wasm32-unknown-unknown` we register a custom impl that // returns `UNSUPPORTED`. Quote verification should not draw any randomness; From acaa5633a541ecbb655d2daf68babb1e147d8697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 17 Aug 2026 11:44:32 +0200 Subject: [PATCH 28/32] docs: drop overclaimed invariants and refresh stale figures around the verifier tests --- Makefile.toml | 2 +- crates/contract/src/tee/proposal.rs | 3 ++- crates/contract/tests/sandbox/common.rs | 4 ++-- crates/contract/tests/sandbox/tee_verifier.rs | 6 ++---- crates/contract/tests/sandbox/utils/mpc_contract.rs | 5 +++-- crates/e2e-tests/README.md | 7 ++++--- crates/e2e-tests/src/cluster.rs | 4 ++-- crates/tee-verifier/src/lib.rs | 7 ++++--- docs/deploy-tee-verifier.md | 2 +- docs/design/attestation-verifier-contract.md | 2 +- 10 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Makefile.toml b/Makefile.toml index c3b243292e..b55ad80207 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -276,7 +276,7 @@ MPC_CONTRACT_WASM = "${CARGO_MAKE_WORKING_DIRECTORY}/target/near/mpc_contract/mp MPC_PARALLEL_CONTRACT_WASM = "${CARGO_MAKE_WORKING_DIRECTORY}/target/near/test_parallel_contract/test_parallel_contract.wasm" MPC_TEE_VERIFIER_WASM = "${CARGO_MAKE_WORKING_DIRECTORY}/target/near/tee_verifier/tee_verifier.wasm" -# Build the mpc-node binary and both contract WASMs, then run the E2E tests. +# Build the mpc-node binary, the contract WASMs, and the backup CLI, then run the E2E tests. [tasks.e2e-tests] description = "Build required binaries and run the E2E tests" run_task = "_run-e2e-logic" diff --git a/crates/contract/src/tee/proposal.rs b/crates/contract/src/tee/proposal.rs index b5ef13213c..a33b766145 100644 --- a/crates/contract/src/tee/proposal.rs +++ b/crates/contract/src/tee/proposal.rs @@ -488,7 +488,8 @@ impl AllowedLauncherImages { .map(|e| e.expires_at.as_secs()) } - /// Test-only: allows one more compose hash for an already-allowed launcher. The attestation + /// Test-only, also compiled into the `sandbox-test-attestation` wasm: allows one more + /// compose hash for an already-allowed launcher. The attestation /// fixture is captured from a CVM whose launcher compose carries a key-export service, so /// [`get_docker_compose_hash`] cannot derive its hash. #[cfg(any(test, feature = "sandbox-test-attestation"))] diff --git a/crates/contract/tests/sandbox/common.rs b/crates/contract/tests/sandbox/common.rs index 1ba6b8dfd5..6cb96ec8a6 100644 --- a/crates/contract/tests/sandbox/common.rs +++ b/crates/contract/tests/sandbox/common.rs @@ -197,8 +197,8 @@ impl SandboxTestSetup { } } -/// Which contract wasm the setup deploys. The feature sets are mutually -/// exclusive, so this is one choice, not independent flags. +/// Which contract wasm the setup deploys. Exactly one wasm is deployed, so this +/// is one choice, not independent flags. #[derive(Clone, Copy)] enum TestWasm { Production, diff --git a/crates/contract/tests/sandbox/tee_verifier.rs b/crates/contract/tests/sandbox/tee_verifier.rs index 8f2c029f1b..6834beb482 100644 --- a/crates/contract/tests/sandbox/tee_verifier.rs +++ b/crates/contract/tests/sandbox/tee_verifier.rs @@ -113,10 +113,8 @@ async fn deploy_and_trust_pinned_verifier( } /// Votes the fixture's image and launcher hashes into the on-chain allowlists, then -/// whitelists the fixture's compose hash, which derivation cannot produce. The image hash -/// must be voted in before the launcher hash: allowed compose hashes are derived from the -/// currently allowed image hashes. Within a round the voters are distinct accounts, so the -/// votes run concurrently. +/// whitelists the fixture's compose hash, which derivation cannot produce. Within a +/// round the voters are distinct accounts, so the votes run concurrently. /// /// Requires the `sandbox-test-attestation` wasm. async fn whitelist_fixture_dstack_hashes(contract: &Contract, participants: &[Account]) { diff --git a/crates/contract/tests/sandbox/utils/mpc_contract.rs b/crates/contract/tests/sandbox/utils/mpc_contract.rs index 69debe968c..40576ff598 100644 --- a/crates/contract/tests/sandbox/utils/mpc_contract.rs +++ b/crates/contract/tests/sandbox/utils/mpc_contract.rs @@ -212,8 +212,9 @@ pub async fn vote_add_launcher_hash( Ok(()) } -/// Whitelists `compose_hash` for `launcher_hash` through the `sandbox-test-attestation` -/// method, which is absent from the production wasm. Vote the launcher hash in first. +/// Whitelists `compose_hash` for `launcher_hash` through the contract method of the same +/// name, which the `sandbox-test-attestation` feature gates out of the production wasm. +/// Vote the launcher hash in first. pub async fn sandbox_allow_launcher_compose_hash( account: &Account, contract: &Contract, diff --git a/crates/e2e-tests/README.md b/crates/e2e-tests/README.md index d7d3a2d549..7d9fd21bba 100644 --- a/crates/e2e-tests/README.md +++ b/crates/e2e-tests/README.md @@ -125,9 +125,10 @@ impl NearBlockchain { `DeployedContract` wraps the contract's account ID plus its own `near-kit` client. It exposes `call`/`call_final` (from the contract account, used only for `init`), `handle_for` (a typed `MpcContractHandle` calling as a given -`NearKitCaller`), `call_from_with_deposit` (untyped escape hatch for -`prepay_attestation_storage`, which has no typed method yet), `view`, and -`state()` (parsed `ProtocolContractState`). +`NearKitCaller`), `call_from_with_deposit` (untyped escape hatch for methods +without a typed wrapper yet: `prepay_attestation_storage`, +`vote_tee_verifier_change`), `view`, and `state()` (parsed +`ProtocolContractState`). `NearKitCaller` binds a signer to a non-contract account (nodes voting, users submitting sign requests) and implements the `CallContract` transport trait, diff --git a/crates/e2e-tests/src/cluster.rs b/crates/e2e-tests/src/cluster.rs index bc7b585ad5..614285d704 100644 --- a/crates/e2e-tests/src/cluster.rs +++ b/crates/e2e-tests/src/cluster.rs @@ -1465,8 +1465,8 @@ async fn deploy_and_trust_tee_verifier( ); } - // The votes are final, but views can briefly lag them; poll like the - // post-init state waits do. + // The votes are not awaited to finality, so views can lag them; poll like + // the post-init state waits do. let timeout = Duration::from_secs(30); let max_times = (timeout.as_millis() / POLL_INTERVAL.as_millis()) as usize; (|| async { diff --git a/crates/tee-verifier/src/lib.rs b/crates/tee-verifier/src/lib.rs index 9e88a36335..01a9a825ca 100644 --- a/crates/tee-verifier/src/lib.rs +++ b/crates/tee-verifier/src/lib.rs @@ -46,7 +46,7 @@ impl TeeVerifier { /// /// Calls [`dcap_qvl::verify::verify`] with the current block timestamp /// (pinnable by sandbox tests in builds with the `sandbox-test-hooks` - /// feature) and returns `VerificationResult::Verified(report)` on success. + /// feature) and returns [`VerificationResult::Verified`] with the report on success. /// The caller is responsible for any post-DCAP policy (RTMR3 replay, /// report-data binding, measurement allowlist matching, etc.). /// @@ -78,8 +78,9 @@ impl TeeVerifier { /// The timestamp quotes are verified against: block time, unless a sandbox test /// pinned one under [`tee_verifier_interface::SANDBOX_TEST_PINNED_NOW_STORAGE_KEY`]. -/// The pin exists because sandbox chain time is wall-clock and forward-only, so it -/// can never fall inside the validity window of a checked-in collateral fixture. +/// The pin exists because sandbox chain time is wall-clock and forward-only: once it +/// passes the fixed validity window of a checked-in collateral fixture it never +/// returns, so unpinned runs would start failing on that date. fn now_seconds() -> u64 { #[cfg(feature = "sandbox-test-hooks")] if let Some(bytes) = env::storage_read(SANDBOX_TEST_PINNED_NOW_STORAGE_KEY) { diff --git a/docs/deploy-tee-verifier.md b/docs/deploy-tee-verifier.md index 57fecb91a4..41b2f356fd 100644 --- a/docs/deploy-tee-verifier.md +++ b/docs/deploy-tee-verifier.md @@ -66,7 +66,7 @@ near account create-account sponsor-by-faucet-service "$VERIFIER_ACCOUNT" autoge On `mainnet` there is no faucet; create and fund the account from an existing one. The balance only needs to cover storage staking for the deployed WASM (about 1 NEAR per -100 KB); 5 NEAR comfortably covers the ~360 KB verifier: +100 KB); 5 NEAR covers the ~430 KB verifier: ```shell near account create-account fund-myself "$VERIFIER_ACCOUNT" '5 NEAR' autogenerate-new-keypair save-to-keychain sign-as network-config "$NETWORK" sign-with-keychain send diff --git a/docs/design/attestation-verifier-contract.md b/docs/design/attestation-verifier-contract.md index 3fce98bba0..a314ba710b 100644 --- a/docs/design/attestation-verifier-contract.md +++ b/docs/design/attestation-verifier-contract.md @@ -613,7 +613,7 @@ The verifier-rotation design changes the test surface in three ways. First, the Status: the stub verifier this section originally proposed was dropped during implementation, because a second contract mirroring the real one duplicated it for little gain. What shipped: -Sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` deploy the real `tee-verifier` WASM and drive each verdict through `vote_tee_verifier_change` + `submit_participant_info`: `Rejected` with a malformed quote, no-verdict with an undeployed verifier account, and `Verified` with the fixture quote. `Verified` needs the verifier built with `sandbox-test-hooks`, which lets the test pin the timestamp `verify_quote` verifies against (the fixture collateral is valid only inside a fixed window, while sandbox time is wall-clock and forward-only), and the contract built with `sandbox-test-attestation`, which whitelists the fixture's launcher compose hash. +Sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` deploy the real `tee-verifier` WASM and drive each verdict through `vote_tee_verifier_change` + `submit_participant_info`: `Rejected` with a malformed quote, no-verdict with an undeployed verifier account, and `Verified` with the fixture quote. `Verified` needs the verifier built with `sandbox-test-hooks`, which lets the test pin the timestamp `verify_quote` verifies against (the fixture collateral is valid only inside a fixed window, while sandbox time is wall-clock and forward-only), and the contract built with `sandbox-test-attestation`, which lets the test whitelist the fixture's launcher compose hash. Tests that assert the *store* additionally sign as the fixture account, because the quote's report_data binds that account key; the committed fixture secret key (`crates/test-utils/assets/near_account_secret_key`) makes that signature possible. From 5334692c9eec8a8504d0f4b67bfe9f7e504e03ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 17 Aug 2026 14:30:32 +0200 Subject: [PATCH 29/32] refactor: keep the sandbox test switches out of released artifacts The verifier's sandbox-test-hooks feature now takes effect only together with --cfg mpc_sandbox_wasm, which only the test harness sets on the wasm it builds; a wasm carrying the feature without the marker fails to compile. The contract-side sandbox-test-attestation feature and its whitelisting method are gone: sandbox tests patch the fixture's compose hash straight into contract state through a host-only test-utils helper, so the deployed contract is the production-shape build. Two new tests pin the released behavior: the production verifier ignores the pinned timestamp, and a verified quote whose compose hash was never whitelisted stores nothing. --- Cargo.toml | 10 +- crates/contract/Cargo.toml | 3 - crates/contract/src/lib.rs | 14 +- .../contract/src/sandbox_test_attestation.rs | 23 --- crates/contract/src/tee/proposal.rs | 5 +- crates/contract/src/test_utils_state.rs | 26 +++ crates/contract/tests/sandbox/common.rs | 36 +--- crates/contract/tests/sandbox/tee_verifier.rs | 179 ++++++++++++++---- .../tests/sandbox/utils/contract_build.rs | 14 -- .../tests/sandbox/utils/mpc_contract.rs | 25 +-- crates/tee-verifier-interface/src/lib.rs | 5 +- crates/tee-verifier/Cargo.toml | 4 +- crates/tee-verifier/src/lib.rs | 15 +- crates/test-utils/src/contract_build.rs | 9 + docs/design/attestation-verifier-contract.md | 2 +- 15 files changed, 205 insertions(+), 165 deletions(-) delete mode 100644 crates/contract/src/sandbox_test_attestation.rs create mode 100644 crates/contract/src/test_utils_state.rs diff --git a/Cargo.toml b/Cargo.toml index 316d45e8be..4aa0f90701 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -191,10 +191,7 @@ near-jsonrpc-primitives = "0.37.1" near-kit = { version = "0.14.0", default-features = false, features = ["rpc"] } near-primitives = "0.37.1" near-sandbox = "0.3.11" -near-sdk = { version = "5.29.0", features = [ - "legacy", - "unstable", -] } +near-sdk = { version = "5.29.0", features = ["legacy", "unstable"] } near-token = "0.3.4" near-workspaces = { version = "0.23.0" } num_enum = { version = "0.7.6", features = ["complex-expressions"] } @@ -211,9 +208,7 @@ proc-macro2 = "1.0" quote = "1.0" # TODO(#2051): updating this brings considerable breaking changes rcgen = "0.13.2" -reddsa = { version = "0.5.2", default-features = false, features = [ - "frost", -] } +reddsa = { version = "0.5.2", default-features = false, features = ["frost"] } regex = "1.12.3" reqwest = { version = "0.13.3", features = ["multipart", "json"] } rmp-serde = "1.3.1" @@ -308,6 +303,7 @@ time = "0.3.45" [workspace.lints.rust] unexpected_cfgs = { level = "allow", check-cfg = [ 'cfg(feature, values("abi"))', + 'cfg(mpc_sandbox_wasm)', ] } [workspace.lints.clippy] diff --git a/crates/contract/Cargo.toml b/crates/contract/Cargo.toml index fecfffc15d..cb355a1410 100644 --- a/crates/contract/Cargo.toml +++ b/crates/contract/Cargo.toml @@ -59,9 +59,6 @@ bench-contract-methods = [] # length of a fan-out queue). Distinct from `bench-contract-methods` because these are # behavioral hooks, not gas-measurement hooks. sandbox-test-methods = [] -# Sandbox-only method that whitelists one launcher compose hash directly, for the attestation -# fixture, whose compose hash is not derivable from the compiled-in template. -sandbox-test-attestation = [] dev-utils = ["rand", "threshold-signatures", "near-mpc-contract-interface/blstrs"] abi = [ "borsh/unstable__schema", diff --git a/crates/contract/src/lib.rs b/crates/contract/src/lib.rs index 8f700f6620..623f7687f0 100644 --- a/crates/contract/src/lib.rs +++ b/crates/contract/src/lib.rs @@ -13,6 +13,8 @@ pub mod primitives; pub mod state; pub mod storage_keys; pub mod tee; +#[cfg(feature = "test-utils")] +pub mod test_utils_state; pub mod update; #[cfg(feature = "dev-utils")] pub mod utils; @@ -23,21 +25,9 @@ pub mod v3_14_0_state; mod bench; mod dto_mapping; mod pending_requests; -#[cfg(feature = "sandbox-test-attestation")] -mod sandbox_test_attestation; #[cfg(feature = "sandbox-test-methods")] mod sandbox_test_methods; -// The released wasm is the only build that passes `abi` (the reproducible build -// command); sandbox test builds are wasm32 without it, and `--all-features` -// checks run on the host. -#[cfg(all( - target_arch = "wasm32", - feature = "abi", - feature = "sandbox-test-attestation" -))] -compile_error!("sandbox-test-attestation must never be enabled in a released wasm build"); - /// Re-export of the fan-out cap so sandbox tests can lock against the same source of /// truth as the contract rather than duplicating the literal. #[cfg(feature = "sandbox-test-methods")] diff --git a/crates/contract/src/sandbox_test_attestation.rs b/crates/contract/src/sandbox_test_attestation.rs deleted file mode 100644 index 60ba40b041..0000000000 --- a/crates/contract/src/sandbox_test_attestation.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Sandbox-only whitelisting of the attestation fixture's launcher compose hash. -//! -//! Compose hashes otherwise enter the allowlist only by derivation from the compiled-in template, -//! and the fixture's compose carries the service that exported its signer key, so no vote can -//! allow it. Gated so no released artifact carries this. - -use crate::{MpcContract, MpcContractExt}; -use mpc_primitives::hash::{LauncherDockerComposeHash, LauncherImageHash}; -use near_sdk::near; - -#[near] -impl MpcContract { - /// Panics if `launcher_hash` is not allowed yet, so callers vote it in first. - pub fn sandbox_allow_launcher_compose_hash( - &mut self, - launcher_hash: LauncherImageHash, - compose_hash: LauncherDockerComposeHash, - ) { - self.tee_state - .allowed_launcher_images - .allow_compose_hash(&launcher_hash, compose_hash); - } -} diff --git a/crates/contract/src/tee/proposal.rs b/crates/contract/src/tee/proposal.rs index a33b766145..9253cacf11 100644 --- a/crates/contract/src/tee/proposal.rs +++ b/crates/contract/src/tee/proposal.rs @@ -488,11 +488,10 @@ impl AllowedLauncherImages { .map(|e| e.expires_at.as_secs()) } - /// Test-only, also compiled into the `sandbox-test-attestation` wasm: allows one more - /// compose hash for an already-allowed launcher. The attestation + /// Test-only: allows one more compose hash for an already-allowed launcher. The attestation /// fixture is captured from a CVM whose launcher compose carries a key-export service, so /// [`get_docker_compose_hash`] cannot derive its hash. - #[cfg(any(test, feature = "sandbox-test-attestation"))] + #[cfg(any(test, feature = "test-utils"))] pub(crate) fn allow_compose_hash( &mut self, launcher_hash: &LauncherImageHash, diff --git a/crates/contract/src/test_utils_state.rs b/crates/contract/src/test_utils_state.rs new file mode 100644 index 0000000000..1d25834496 --- /dev/null +++ b/crates/contract/src/test_utils_state.rs @@ -0,0 +1,26 @@ +//! Host-side editing of raw contract state for sandbox tests. + +use crate::MpcContract; +use mpc_primitives::hash::{LauncherDockerComposeHash, LauncherImageHash}; +use near_sdk::borsh::{self, BorshDeserialize}; + +/// Adds `compose_hash` to `launcher_hash`'s allowlist entry in a raw `STATE` blob, for +/// sandbox tests to patch back in. The attestation fixture's compose hash is not +/// derivable from the compiled-in template, so no vote can allow it. +pub fn allow_launcher_compose_hash_in_state( + state: &[u8], + launcher_hash: &LauncherImageHash, + compose_hash: LauncherDockerComposeHash, +) -> Vec { + let mut contract = MpcContract::try_from_slice(state).expect("STATE deserializes"); + let roundtrip = borsh::to_vec(&contract).expect("STATE serializes"); + assert!( + roundtrip == state, + "STATE must round-trip byte-identically; the host-side layout has drifted" + ); + contract + .tee_state + .allowed_launcher_images + .allow_compose_hash(launcher_hash, compose_hash); + borsh::to_vec(&contract).expect("STATE serializes") +} diff --git a/crates/contract/tests/sandbox/common.rs b/crates/contract/tests/sandbox/common.rs index 6cb96ec8a6..582d76386c 100644 --- a/crates/contract/tests/sandbox/common.rs +++ b/crates/contract/tests/sandbox/common.rs @@ -184,7 +184,7 @@ impl SandboxTestSetup { foreign_tx: false, number_of_participants: PARTICIPANT_LEN, init_config: None, - wasm: TestWasm::Production, + with_sandbox_test_methods: false, } } @@ -197,21 +197,12 @@ impl SandboxTestSetup { } } -/// Which contract wasm the setup deploys. Exactly one wasm is deployed, so this -/// is one choice, not independent flags. -#[derive(Clone, Copy)] -enum TestWasm { - Production, - SandboxTestMethods, - SandboxTestAttestation, -} - pub struct SandboxTestSetupBuilder { protocols: Vec, foreign_tx: bool, number_of_participants: usize, init_config: Option, - wasm: TestWasm, + with_sandbox_test_methods: bool, } impl SandboxTestSetupBuilder { @@ -239,28 +230,15 @@ impl SandboxTestSetupBuilder { /// introspection view methods in [`crate::sandbox_test_methods`] (e.g. fan-out queue /// length). pub fn with_sandbox_test_methods(mut self) -> Self { - self.wasm = TestWasm::SandboxTestMethods; - self - } - - /// Deploys the wasm built with `--features sandbox-test-attestation`, which can whitelist - /// the attestation fixture's launcher compose hash. Required by tests that submit the - /// Dstack fixture and expect it to verify. - pub fn with_sandbox_test_attestation(mut self) -> Self { - self.wasm = TestWasm::SandboxTestAttestation; + self.with_sandbox_test_methods = true; self } pub async fn build(self) -> SandboxTestSetup { - let (worker, contract) = match self.wasm { - TestWasm::SandboxTestMethods => { - init_with_wasm(contract_build::current_contract_with_sandbox_test_methods()).await - } - TestWasm::SandboxTestAttestation => { - init_with_wasm(contract_build::current_contract_with_sandbox_test_attestation()) - .await - } - TestWasm::Production => init().await, + let (worker, contract) = if self.with_sandbox_test_methods { + init_with_wasm(contract_build::current_contract_with_sandbox_test_methods()).await + } else { + init().await }; let (accounts, participants) = gen_accounts(&worker, self.number_of_participants).await; let threshold_parameters = make_threshold_params(&participants); diff --git a/crates/contract/tests/sandbox/tee_verifier.rs b/crates/contract/tests/sandbox/tee_verifier.rs index 6834beb482..2773b6e397 100644 --- a/crates/contract/tests/sandbox/tee_verifier.rs +++ b/crates/contract/tests/sandbox/tee_verifier.rs @@ -6,9 +6,9 @@ //! time pinned to the fixture's validity window. The pin is needed because //! real `verify_quote` checks the quote against block time: the fixture //! collateral is valid only inside a fixed window, while sandbox time is -//! wall-clock and forward-only. These tests also deploy the contract built -//! with `sandbox-test-attestation`, since the compose that exported the -//! fixture key hashes outside the derivable set. +//! wall-clock and forward-only. The fixture's compose hash is patched straight +//! into contract state, since the compose that exported the fixture key hashes +//! outside the derivable set. //! //! Verified-path tests that store an attestation sign as the fixture account: //! the quote's report_data binds the fixture account key, and the contract @@ -22,10 +22,9 @@ use crate::sandbox::{ contract_build::{tee_verifier_contract, tee_verifier_contract_with_sandbox_test_hooks}, mpc_contract::{ get_config, get_participant_attestation, get_tee_accounts, - prepay_and_submit_participant_info, prepay_attestation_grants, - sandbox_allow_launcher_compose_hash, submit_participant_info, tee_verifier_account_id, - total_gas_fee, vote_add_launcher_hash, vote_add_os_measurement, vote_for_hash, - vote_tee_verifier_change, + prepay_and_submit_participant_info, prepay_attestation_grants, submit_participant_info, + tee_verifier_account_id, total_gas_fee, vote_add_launcher_hash, + vote_add_os_measurement, vote_for_hash, vote_tee_verifier_change, }, }, }; @@ -35,8 +34,9 @@ use mpc_attestation::attestation::{DEFAULT_EXPIRATION_DURATION_SECONDS, default_ use mpc_contract::{ errors::TeeError, tee::{measurements::ContractExpectedMeasurements, tee_state::AttestationSubmissionError}, + test_utils_state::allow_launcher_compose_hash_in_state, }; -use near_mpc_contract_interface::types as dtos; +use near_mpc_contract_interface::{method_names, types as dtos}; use near_workspaces::{ Account, AccountId, Contract, Worker, network::Sandbox, @@ -57,16 +57,6 @@ async fn setup() -> SandboxTestSetup { .await } -/// Setup for tests that expect the fixture to pass the post-DCAP checks, which needs the -/// wasm that can whitelist its launcher compose hash. -async fn setup_accepting_fixture_attestation() -> SandboxTestSetup { - SandboxTestSetup::builder() - .with_protocols(ALL_PROTOCOLS) - .with_sandbox_test_attestation() - .build() - .await -} - /// Votes `verifier` in as `mpc-contract`'s trusted verifier (all participants vote /// so the change crosses threshold). async fn trust_verifier(contract: &Contract, participants: &[Account], verifier: &AccountId) { @@ -112,12 +102,9 @@ async fn deploy_and_trust_pinned_verifier( verifier } -/// Votes the fixture's image and launcher hashes into the on-chain allowlists, then -/// whitelists the fixture's compose hash, which derivation cannot produce. Within a +/// Votes the fixture's image and launcher hashes into the on-chain allowlists. Within a /// round the voters are distinct accounts, so the votes run concurrently. -/// -/// Requires the `sandbox-test-attestation` wasm. -async fn whitelist_fixture_dstack_hashes(contract: &Contract, participants: &[Account]) { +async fn vote_fixture_image_and_launcher(contract: &Contract, participants: &[Account]) { let image = image_digest(); for result in join_all( participants @@ -138,20 +125,43 @@ async fn whitelist_fixture_dstack_hashes(contract: &Contract, participants: &[Ac { result.unwrap(); } - sandbox_allow_launcher_compose_hash( - &participants[0], - contract, - &launcher, - &launcher_compose_digest(), - ) - .await - .unwrap(); +} + +/// Votes the fixture's hashes in, then patches its compose hash into the allowlist, +/// which derivation cannot produce. +async fn whitelist_fixture_dstack_hashes( + worker: &Worker, + contract: &Contract, + participants: &[Account], +) { + vote_fixture_image_and_launcher(contract, participants).await; + let mut entries = worker + .view_state(contract.id()) + .prefix(b"STATE") + .await + .unwrap(); + let state = entries + .remove(b"STATE".as_slice()) + .expect("the contract must have a STATE entry"); + let patched = allow_launcher_compose_hash_in_state( + &state, + &launcher_image_hash(), + launcher_compose_digest(), + ); + worker + .patch_state(contract.id(), b"STATE", &patched) + .await + .unwrap(); } /// Adds the OS measurements on top of the hash allowlists, the sandbox /// analogue of the in-process `whitelist_dstack_measurements` helper. -async fn whitelist_fixture_dstack_measurements(contract: &Contract, participants: &[Account]) { - whitelist_fixture_dstack_hashes(contract, participants).await; +async fn whitelist_fixture_dstack_measurements( + worker: &Worker, + contract: &Contract, + participants: &[Account], +) { + whitelist_fixture_dstack_hashes(worker, contract, participants).await; for &measurements in default_measurements() { let measurements = ContractExpectedMeasurements::from(measurements); for result in join_all( @@ -207,10 +217,15 @@ async fn prepay_grant_from_separate_payer( /// measurements whitelisted, plus a prepaid fixture account whose submissions /// pass the report_data binding. async fn setup_verified_fixture() -> (SandboxTestSetup, Account) { - let setup = setup_accepting_fixture_attestation().await; + let setup = setup().await; deploy_and_trust_pinned_verifier(&setup.worker, &setup.contract, &setup.mpc_signer_accounts) .await; - whitelist_fixture_dstack_measurements(&setup.contract, &setup.mpc_signer_accounts).await; + whitelist_fixture_dstack_measurements( + &setup.worker, + &setup.contract, + &setup.mpc_signer_accounts, + ) + .await; let submitter = create_fixture_account(&setup.worker, "fixture-node-a").await; prepay_grant_from_separate_payer(&setup.worker, &setup.contract, submitter.id()).await; (setup, submitter) @@ -259,6 +274,20 @@ async fn assert_submission_failed_cleanly( assert_only_gas_spent(submitter, balance_before, result).await; } +/// Calls `verify_quote` with the committed borsh argument fixture and returns the raw +/// borsh return value, asserting the call itself succeeded. +async fn call_verify_quote(verifier: &Contract, args: &[u8]) -> Vec { + let result = verifier + .call(method_names::VERIFY_QUOTE) + .args(args.to_vec()) + .max_gas() + .transact() + .await + .unwrap(); + assert!(result.is_success(), "verify_quote failed: {result:#?}"); + result.raw_bytes().unwrap() +} + /// Asserts the caller spent only gas: no deposit is attached, so a failed submission costs nothing /// beyond gas. The unspent-gas refund lands a block or two after the transaction, so poll until /// the balance settles instead of reading it once. @@ -417,11 +446,11 @@ async fn submit_participant_info__should_run_dcap_within_verifier_gas_budget() { mpc_signer_accounts, contract, .. - } = setup_accepting_fixture_attestation().await; + } = setup().await; let verifier = deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await; // Only the hash allowlists gate this test's outcome: the plain dev-account // submitter fails at report_data, which runs before the measurements check. - whitelist_fixture_dstack_hashes(&contract, &mpc_signer_accounts).await; + whitelist_fixture_dstack_hashes(&worker, &contract, &mpc_signer_accounts).await; let submitter = mpc_signer_accounts[0].clone(); prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; let balance_before = submitter.view_account().await.unwrap().balance; @@ -612,3 +641,79 @@ async fn submit_participant_info__should_reject_verified_quote_when_tls_key_owne ); assert_only_gas_spent(&attacker, balance_before, &result).await; } + +#[tokio::test] +async fn submit_participant_info__should_reject_verified_quote_when_compose_hash_not_allowed() { + // Given: hashes voted in but the fixture's compose hash never patched, so the + // allowlist holds only the derived compose hash. + let SandboxTestSetup { + worker, + mpc_signer_accounts, + contract, + .. + } = setup().await; + deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await; + vote_fixture_image_and_launcher(&contract, &mpc_signer_accounts).await; + let submitter = create_fixture_account(&worker, "fixture-node-a").await; + prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; + let balance_before = submitter.view_account().await.unwrap().balance; + + // When + let result = submit_dstack(&submitter, &contract).await; + + // Then + assert_submission_failed_cleanly( + &result, + &contract, + &submitter, + balance_before, + &[ + "failed verification", + "launcher compose hash", + "is not in the allowed hashes list", + ], + ) + .await; + let remaining: u32 = contract + .view(method_names::AVAILABLE_ATTESTATION_GRANTS) + .args_json(serde_json::json!({ "account_id": submitter.id() })) + .await + .unwrap() + .json() + .unwrap(); + assert_eq!( + remaining, 1, + "a failed submission must not consume the grant" + ); +} + +#[tokio::test] +async fn verify_quote__should_ignore_pinned_timestamp_on_production_build() { + // Given + let worker = near_workspaces::sandbox().await.unwrap(); + let verifier = worker.dev_deploy(tee_verifier_contract()).await.unwrap(); + let args = include_bytes!("../../../tee-verifier/tests/fixtures/verify_quote_args.borsh"); + let unpinned = call_verify_quote(&verifier, args).await; + + // When: pin timestamps whose verdicts differ from block time in either direction, + // so honoring the pin would flip the outcome whichever side of the collateral + // window the wall clock is on. + let far_future = wall_clock_seconds() + 100 * 365 * 24 * 3600; + let mut pinned = Vec::new(); + for pin in [VALID_ATTESTATION_TIMESTAMP, far_future] { + worker + .patch_state( + verifier.id(), + SANDBOX_TEST_PINNED_NOW_STORAGE_KEY, + &pin.to_le_bytes(), + ) + .await + .unwrap(); + pinned.push(call_verify_quote(&verifier, args).await); + } + + // Then + for result in pinned { + assert_eq!(result, unpinned, "the production build must ignore the pin"); + } +} diff --git a/crates/contract/tests/sandbox/utils/contract_build.rs b/crates/contract/tests/sandbox/utils/contract_build.rs index 6e48b26655..a76d694055 100644 --- a/crates/contract/tests/sandbox/utils/contract_build.rs +++ b/crates/contract/tests/sandbox/utils/contract_build.rs @@ -8,13 +8,11 @@ const TEE_VERIFIER_MANIFEST: &str = "crates/tee-verifier/Cargo.toml"; const MPC_CONTRACT_OUT_DIR: &str = "target/near/contract-noabi"; const MPC_CONTRACT_BENCH_OUT_DIR: &str = "target/near/contract-noabi-bench"; const MPC_CONTRACT_SANDBOX_OUT_DIR: &str = "target/near/contract-noabi-sandbox"; -const MPC_CONTRACT_ATTESTATION_OUT_DIR: &str = "target/near/contract-noabi-attestation"; const TEE_VERIFIER_SANDBOX_OUT_DIR: &str = "target/near/tee-verifier-sandbox"; static CONTRACT: OnceLock> = OnceLock::new(); static CONTRACT_WITH_BENCH_METHODS: OnceLock> = OnceLock::new(); static CONTRACT_WITH_SANDBOX_TEST_METHODS: OnceLock> = OnceLock::new(); -static CONTRACT_WITH_SANDBOX_TEST_ATTESTATION: OnceLock> = OnceLock::new(); static MIGRATION_CONTRACT: OnceLock> = OnceLock::new(); static PARALLEL_CONTRACT: OnceLock> = OnceLock::new(); static TEE_VERIFIER_CONTRACT: OnceLock> = OnceLock::new(); @@ -53,18 +51,6 @@ pub fn current_contract_with_sandbox_test_methods() -> &'static [u8] { }) } -/// Returns the current contract WASM that can whitelist the fixture's launcher compose hash. -/// Use this only for tests that submit the Dstack fixture and need it to verify: that compose -/// hash is not derivable from the compiled-in template, so no vote can allow it. -pub fn current_contract_with_sandbox_test_attestation() -> &'static [u8] { - CONTRACT_WITH_SANDBOX_TEST_ATTESTATION.get_or_init(|| { - ContractBuilder::new(MPC_CONTRACT_MANIFEST) - .out_dir(MPC_CONTRACT_ATTESTATION_OUT_DIR) - .features(&["sandbox-test-attestation"]) - .build() - }) -} - pub fn migration_contract() -> &'static [u8] { MIGRATION_CONTRACT.get_or_init(|| ContractBuilder::new(MIGRATION_CONTRACT_MANIFEST).build()) } diff --git a/crates/contract/tests/sandbox/utils/mpc_contract.rs b/crates/contract/tests/sandbox/utils/mpc_contract.rs index 40576ff598..f93c291191 100644 --- a/crates/contract/tests/sandbox/utils/mpc_contract.rs +++ b/crates/contract/tests/sandbox/utils/mpc_contract.rs @@ -4,9 +4,7 @@ use crate::sandbox::utils::transactions::CallMpcContract; use super::transactions::all_receipts_successful; use mpc_contract::tee::{measurements::ContractExpectedMeasurements, tee_state::NodeId}; -use mpc_primitives::hash::{ - LauncherDockerComposeHash, LauncherImageHash, NodeImageHash, TeeVerifierCodeHash, -}; +use mpc_primitives::hash::{LauncherImageHash, NodeImageHash, TeeVerifierCodeHash}; use near_mpc_contract_interface::{ method_names, types::{ @@ -212,27 +210,6 @@ pub async fn vote_add_launcher_hash( Ok(()) } -/// Whitelists `compose_hash` for `launcher_hash` through the contract method of the same -/// name, which the `sandbox-test-attestation` feature gates out of the production wasm. -/// Vote the launcher hash in first. -pub async fn sandbox_allow_launcher_compose_hash( - account: &Account, - contract: &Contract, - launcher_hash: &LauncherImageHash, - compose_hash: &LauncherDockerComposeHash, -) -> anyhow::Result<()> { - let result = account - .call(contract.id(), "sandbox_allow_launcher_compose_hash") - .args_json(serde_json::json!({ - "launcher_hash": launcher_hash, - "compose_hash": compose_hash, - })) - .transact() - .await?; - all_receipts_successful(result)?; - Ok(()) -} - pub async fn vote_add_os_measurement( account: &Account, contract: &Contract, diff --git a/crates/tee-verifier-interface/src/lib.rs b/crates/tee-verifier-interface/src/lib.rs index 48321cddaf..7ba25d16f7 100644 --- a/crates/tee-verifier-interface/src/lib.rs +++ b/crates/tee-verifier-interface/src/lib.rs @@ -193,8 +193,9 @@ pub enum VerificationResult { /// Storage key under which a sandbox test can pin the timestamp `verify_quote` /// verifies against, as u64 little-endian seconds since the Unix epoch. /// -/// Honored only by verifier builds with the `sandbox-test-hooks` feature; -/// production builds never read it. Tests write it from outside the contract +/// Honored only by verifier builds with the `sandbox-test-hooks` feature and +/// the `mpc_sandbox_wasm` cfg marker set by the test harness; production +/// builds never read it. Tests write it from outside the contract /// (state patching), which is why the key must be shared between the verifier /// and its callers' test suites rather than staying private. pub const SANDBOX_TEST_PINNED_NOW_STORAGE_KEY: &[u8] = b"sandbox_test_pinned_now_seconds"; diff --git a/crates/tee-verifier/Cargo.toml b/crates/tee-verifier/Cargo.toml index 5cf0dcbc8a..00018b9836 100644 --- a/crates/tee-verifier/Cargo.toml +++ b/crates/tee-verifier/Cargo.toml @@ -35,8 +35,8 @@ abi = ["borsh/unstable__schema", "tee-verifier-interface/borsh-schema"] # dependency no longer turns on `unit-testing` by default. test-utils = ["near-sdk/unit-testing"] # Lets sandbox tests pin the timestamp quotes are verified against, so the -# time-expired fixture collateral can still verify. Never enabled in the -# reproducible production build (which passes only `--features abi`). +# fixture collateral verifies regardless of the wall clock. Takes effect only +# together with `--cfg mpc_sandbox_wasm`, which only the test harness sets. sandbox-test-hooks = [] [dependencies] diff --git a/crates/tee-verifier/src/lib.rs b/crates/tee-verifier/src/lib.rs index 01a9a825ca..0d24da153a 100644 --- a/crates/tee-verifier/src/lib.rs +++ b/crates/tee-verifier/src/lib.rs @@ -9,21 +9,20 @@ //! See `docs/design/attestation-verifier-contract.md` for the design. use near_sdk::{env, near}; -#[cfg(feature = "sandbox-test-hooks")] +#[cfg(all(feature = "sandbox-test-hooks", mpc_sandbox_wasm))] use tee_verifier_interface::SANDBOX_TEST_PINNED_NOW_STORAGE_KEY; use tee_verifier_interface::{Collateral, QuoteBytes, VerificationResult, VerifierError}; use tee_verifier_conversions::{IntoDcapType as _, IntoInterfaceType as _}; -// The released wasm is the only build that passes `abi` (the reproducible build -// command); sandbox test builds are wasm32 without it, and `--all-features` -// checks run on the host. +// Only the test-built wasm (marked with `--cfg mpc_sandbox_wasm` by +// `test_utils::contract_build::ContractBuilder`) may carry the pinned clock. #[cfg(all( target_arch = "wasm32", - feature = "abi", - feature = "sandbox-test-hooks" + feature = "sandbox-test-hooks", + not(mpc_sandbox_wasm) ))] -compile_error!("sandbox-test-hooks must never be enabled in a released wasm build"); +compile_error!("sandbox-test-hooks must not be enabled in a shipped wasm build"); // `dcap-qvl`'s `contract` feature pulls in `getrandom` but doesn't enable // any backend. On `wasm32-unknown-unknown` we register a custom impl that @@ -82,7 +81,7 @@ impl TeeVerifier { /// passes the fixed validity window of a checked-in collateral fixture it never /// returns, so unpinned runs would start failing on that date. fn now_seconds() -> u64 { - #[cfg(feature = "sandbox-test-hooks")] + #[cfg(all(feature = "sandbox-test-hooks", mpc_sandbox_wasm))] if let Some(bytes) = env::storage_read(SANDBOX_TEST_PINNED_NOW_STORAGE_KEY) { let bytes: [u8; 8] = bytes .try_into() diff --git a/crates/test-utils/src/contract_build.rs b/crates/test-utils/src/contract_build.rs index abd1c0f6db..b382904ad3 100644 --- a/crates/test-utils/src/contract_build.rs +++ b/crates/test-utils/src/contract_build.rs @@ -75,12 +75,21 @@ impl ContractBuilder { .expect("path must be valid UTF-8") }; + // Marks the artifact as test-built; sandbox-only code compiles in only under this cfg. + let rustflags = match std::env::var("RUSTFLAGS") { + Ok(inherited) if !inherited.is_empty() => { + format!("{inherited} --cfg mpc_sandbox_wasm") + } + _ => "--cfg mpc_sandbox_wasm".to_string(), + }; + let opts = cargo_near_build::BuildOpts { manifest_path: Some(to_utf8(abs_manifest)), out_dir: Some(to_utf8(workspace_root().join(out_dir))), profile: Some("release-contract".to_string()), no_abi: true, no_embed_abi: true, + env: vec![("RUSTFLAGS".to_string(), rustflags)], features: if self.features.is_empty() { None } else { diff --git a/docs/design/attestation-verifier-contract.md b/docs/design/attestation-verifier-contract.md index a314ba710b..18e5c13317 100644 --- a/docs/design/attestation-verifier-contract.md +++ b/docs/design/attestation-verifier-contract.md @@ -613,7 +613,7 @@ The verifier-rotation design changes the test surface in three ways. First, the Status: the stub verifier this section originally proposed was dropped during implementation, because a second contract mirroring the real one duplicated it for little gain. What shipped: -Sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` deploy the real `tee-verifier` WASM and drive each verdict through `vote_tee_verifier_change` + `submit_participant_info`: `Rejected` with a malformed quote, no-verdict with an undeployed verifier account, and `Verified` with the fixture quote. `Verified` needs the verifier built with `sandbox-test-hooks`, which lets the test pin the timestamp `verify_quote` verifies against (the fixture collateral is valid only inside a fixed window, while sandbox time is wall-clock and forward-only), and the contract built with `sandbox-test-attestation`, which lets the test whitelist the fixture's launcher compose hash. +Sandbox tests in `crates/contract/tests/sandbox/tee_verifier.rs` deploy the real `tee-verifier` WASM and drive each verdict through `vote_tee_verifier_change` + `submit_participant_info`: `Rejected` with a malformed quote, no-verdict with an undeployed verifier account, and `Verified` with the fixture quote. `Verified` needs the verifier built with `sandbox-test-hooks`, which lets the test pin the timestamp `verify_quote` verifies against (the fixture collateral is valid only inside a fixed window, while sandbox time is wall-clock and forward-only); the feature takes effect only together with the `mpc_sandbox_wasm` cfg the test harness sets on the wasm it builds, so no released artifact can carry the pin. The fixture's launcher compose hash is patched straight into the contract's state, since no vote can derive it. Tests that assert the *store* additionally sign as the fixture account, because the quote's report_data binds that account key; the committed fixture secret key (`crates/test-utils/assets/near_account_secret_key`) makes that signature possible. From a50819eb3f7a6cee0ff0e13ea69901fa487c0faa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 17 Aug 2026 17:43:18 +0200 Subject: [PATCH 30/32] refactor(contract): move the state-patching helper into tee::test_utils The crate convention is a test_utils submodule per domain module, and the helper edits the launcher allowlist, which lives under tee. Also drops the round-trip assert: borsh encoding is canonical, so deserializing and reserializing the same type is byte-identical by construction. --- crates/contract/src/lib.rs | 2 -- crates/contract/src/tee/test_utils.rs | 20 +++++++++++++- crates/contract/src/test_utils_state.rs | 26 ------------------- crates/contract/tests/sandbox/tee_verifier.rs | 6 +++-- 4 files changed, 23 insertions(+), 31 deletions(-) delete mode 100644 crates/contract/src/test_utils_state.rs diff --git a/crates/contract/src/lib.rs b/crates/contract/src/lib.rs index a8ae8b86f6..a9f446d807 100644 --- a/crates/contract/src/lib.rs +++ b/crates/contract/src/lib.rs @@ -13,8 +13,6 @@ pub mod primitives; pub mod state; pub mod storage_keys; pub mod tee; -#[cfg(feature = "test-utils")] -pub mod test_utils_state; pub mod update; #[cfg(feature = "dev-utils")] pub mod utils; diff --git a/crates/contract/src/tee/test_utils.rs b/crates/contract/src/tee/test_utils.rs index 23e2d28908..df668c6666 100644 --- a/crates/contract/src/tee/test_utils.rs +++ b/crates/contract/src/tee/test_utils.rs @@ -3,11 +3,13 @@ //! This module provides helper functions and types for testing TEE state, //! attestation behavior, and general contract state management. +use crate::MpcContract; use crate::primitives::test_utils::{gen_account_id, gen_seed}; use crate::tee::{measurements::ContractExpectedMeasurements, tee_state::TeeState}; use mpc_attestation::attestation::default_measurements; -use mpc_primitives::hash::{LauncherImageHash, NodeImageHash}; +use mpc_primitives::hash::{LauncherDockerComposeHash, LauncherImageHash, NodeImageHash}; use near_account_id::AccountId; +use near_sdk::borsh::{self, BorshDeserialize}; use near_sdk::{BlockHeight, NearToken, PublicKey, test_utils::VMContextBuilder, testing_env}; use rand::Rng; use std::time::Duration; @@ -115,3 +117,19 @@ pub fn whitelist_dstack_measurements( tee_state.add_measurement(ContractExpectedMeasurements::from(measurements)); } } + +/// Adds `compose_hash` to `launcher_hash`'s allowlist entry in a raw `STATE` blob, for +/// sandbox tests to patch back in. The attestation fixture's compose hash is not +/// derivable from the compiled-in template, so no vote can allow it. +pub fn allow_launcher_compose_hash_in_state( + state: &[u8], + launcher_hash: &LauncherImageHash, + compose_hash: LauncherDockerComposeHash, +) -> Vec { + let mut contract = MpcContract::try_from_slice(state).expect("STATE deserializes"); + contract + .tee_state + .allowed_launcher_images + .allow_compose_hash(launcher_hash, compose_hash); + borsh::to_vec(&contract).expect("STATE serializes") +} diff --git a/crates/contract/src/test_utils_state.rs b/crates/contract/src/test_utils_state.rs deleted file mode 100644 index 1d25834496..0000000000 --- a/crates/contract/src/test_utils_state.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Host-side editing of raw contract state for sandbox tests. - -use crate::MpcContract; -use mpc_primitives::hash::{LauncherDockerComposeHash, LauncherImageHash}; -use near_sdk::borsh::{self, BorshDeserialize}; - -/// Adds `compose_hash` to `launcher_hash`'s allowlist entry in a raw `STATE` blob, for -/// sandbox tests to patch back in. The attestation fixture's compose hash is not -/// derivable from the compiled-in template, so no vote can allow it. -pub fn allow_launcher_compose_hash_in_state( - state: &[u8], - launcher_hash: &LauncherImageHash, - compose_hash: LauncherDockerComposeHash, -) -> Vec { - let mut contract = MpcContract::try_from_slice(state).expect("STATE deserializes"); - let roundtrip = borsh::to_vec(&contract).expect("STATE serializes"); - assert!( - roundtrip == state, - "STATE must round-trip byte-identically; the host-side layout has drifted" - ); - contract - .tee_state - .allowed_launcher_images - .allow_compose_hash(launcher_hash, compose_hash); - borsh::to_vec(&contract).expect("STATE serializes") -} diff --git a/crates/contract/tests/sandbox/tee_verifier.rs b/crates/contract/tests/sandbox/tee_verifier.rs index 2773b6e397..8c8db9cfef 100644 --- a/crates/contract/tests/sandbox/tee_verifier.rs +++ b/crates/contract/tests/sandbox/tee_verifier.rs @@ -33,8 +33,10 @@ use futures::future::join_all; use mpc_attestation::attestation::{DEFAULT_EXPIRATION_DURATION_SECONDS, default_measurements}; use mpc_contract::{ errors::TeeError, - tee::{measurements::ContractExpectedMeasurements, tee_state::AttestationSubmissionError}, - test_utils_state::allow_launcher_compose_hash_in_state, + tee::{ + measurements::ContractExpectedMeasurements, tee_state::AttestationSubmissionError, + test_utils::allow_launcher_compose_hash_in_state, + }, }; use near_mpc_contract_interface::{method_names, types as dtos}; use near_workspaces::{ From 51fd510caec6d5d2dcc5be5bf15afeb657650821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 17 Aug 2026 22:55:16 +0200 Subject: [PATCH 31/32] refactor(test): shorten the verifier sandbox tests and their setup Collapses the repeated setup and voting scaffolding: setup() and setup_verified_fixture() return the handles the tests bind anyway, all_vote() takes the vote to cast, prepay_grant_from_separate_payer() returns the balance its callers read next, and pin_verifier_clock() replaces the patch_state blocks. Reuses submit_dstack, get_config and cluster_poll_retry where the code hand-rolled them, and drops the sha2 dependency for the near-kit hash already used a few lines away. --- Cargo.lock | 1 - Cargo.toml | 9 +- crates/contract/src/tee/test_utils.rs | 6 +- crates/contract/tests/sandbox/tee.rs | 10 +- crates/contract/tests/sandbox/tee_verifier.rs | 261 ++++++------------ crates/e2e-tests/Cargo.toml | 1 - crates/e2e-tests/src/cluster.rs | 70 ++--- crates/test-utils/src/contract_build.rs | 8 +- 8 files changed, 129 insertions(+), 237 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 491ce1781d..2f6d74a879 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3287,7 +3287,6 @@ dependencies = [ "rstest", "serde", "serde_json", - "sha2 0.10.9", "tempfile", "test-port-allocator", "test-utils", diff --git a/Cargo.toml b/Cargo.toml index 4aa0f90701..8e0d067d3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -191,7 +191,10 @@ near-jsonrpc-primitives = "0.37.1" near-kit = { version = "0.14.0", default-features = false, features = ["rpc"] } near-primitives = "0.37.1" near-sandbox = "0.3.11" -near-sdk = { version = "5.29.0", features = ["legacy", "unstable"] } +near-sdk = { version = "5.29.0", features = [ + "legacy", + "unstable", +] } near-token = "0.3.4" near-workspaces = { version = "0.23.0" } num_enum = { version = "0.7.6", features = ["complex-expressions"] } @@ -208,7 +211,9 @@ proc-macro2 = "1.0" quote = "1.0" # TODO(#2051): updating this brings considerable breaking changes rcgen = "0.13.2" -reddsa = { version = "0.5.2", default-features = false, features = ["frost"] } +reddsa = { version = "0.5.2", default-features = false, features = [ + "frost", +] } regex = "1.12.3" reqwest = { version = "0.13.3", features = ["multipart", "json"] } rmp-serde = "1.3.1" diff --git a/crates/contract/src/tee/test_utils.rs b/crates/contract/src/tee/test_utils.rs index df668c6666..aa23e7ea5e 100644 --- a/crates/contract/src/tee/test_utils.rs +++ b/crates/contract/src/tee/test_utils.rs @@ -118,9 +118,9 @@ pub fn whitelist_dstack_measurements( } } -/// Adds `compose_hash` to `launcher_hash`'s allowlist entry in a raw `STATE` blob, for -/// sandbox tests to patch back in. The attestation fixture's compose hash is not -/// derivable from the compiled-in template, so no vote can allow it. +/// Adds a [`LauncherDockerComposeHash`] to a [`LauncherImageHash`]'s allowlist entry in a +/// raw `STATE` blob, for sandbox tests to patch back in. The attestation fixture's compose +/// hash is not derivable from the compiled-in template, so no vote can allow it. pub fn allow_launcher_compose_hash_in_state( state: &[u8], launcher_hash: &LauncherImageHash, diff --git a/crates/contract/tests/sandbox/tee.rs b/crates/contract/tests/sandbox/tee.rs index d9fb0d4304..e346323435 100644 --- a/crates/contract/tests/sandbox/tee.rs +++ b/crates/contract/tests/sandbox/tee.rs @@ -9,7 +9,7 @@ use crate::sandbox::{ consts::ALL_PROTOCOLS, interface::IntoContractType, mpc_contract::{ - assert_running_return_participants, assert_running_return_threshold, + assert_running_return_participants, assert_running_return_threshold, get_config, get_participant_attestation, get_state, get_tee_accounts, prepay_and_submit_participant_info, prepay_attestation_grants, submit_participant_info, vote_add_launcher_hash, vote_for_hash, @@ -25,7 +25,7 @@ use mpc_primitives::hash::{LauncherDockerComposeHash, LauncherImageHash, NodeIma use near_mpc_contract_interface::deposits::STORAGE_BYTE_COST_YOCTONEAR; use near_mpc_contract_interface::method_names; use near_mpc_contract_interface::types::{ - self as dtos, Attestation, Config, MockAttestation, Protocol, VerifiedAttestation, + self as dtos, Attestation, MockAttestation, Protocol, VerifiedAttestation, }; use near_workspaces::types::{KeyType, NearToken, SecretKey}; use near_workspaces::{AccessKey, Account, Contract}; @@ -1090,11 +1090,7 @@ async fn prepay_and_submit_a_constrained_mock__should_use_at_most_half_a_grant_f }); let node = worker.dev_create_account().await?; let tls_key = bogus_ed25519_public_key(); - let config: Config = contract - .view(method_names::CONFIG) - .args_json(serde_json::json!({})) - .await? - .json()?; + let config = get_config(&contract).await?; let before = contract.as_account().view_account().await?; // When diff --git a/crates/contract/tests/sandbox/tee_verifier.rs b/crates/contract/tests/sandbox/tee_verifier.rs index 8c8db9cfef..320f9710ef 100644 --- a/crates/contract/tests/sandbox/tee_verifier.rs +++ b/crates/contract/tests/sandbox/tee_verifier.rs @@ -1,18 +1,9 @@ -//! Sandbox tests for the async [`submit_participant_info`] flow, driving the real -//! `tee-verifier` (or no verifier): -//! - Rejected: real verifier with a malformed quote. -//! - Unavailable: a verifier account that was never deployed. -//! - Verified: real verifier built with `sandbox-test-hooks`, its verification -//! time pinned to the fixture's validity window. The pin is needed because -//! real `verify_quote` checks the quote against block time: the fixture -//! collateral is valid only inside a fixed window, while sandbox time is -//! wall-clock and forward-only. The fixture's compose hash is patched straight -//! into contract state, since the compose that exported the fixture key hashes -//! outside the derivable set. -//! -//! Verified-path tests that store an attestation sign as the fixture account: -//! the quote's report_data binds the fixture account key, and the contract -//! reads that key from the transaction signer. +//! Sandbox tests for the async [`submit_participant_info`] flow against a real +//! deployed `tee-verifier`, covering the Rejected, Unavailable, and Verified +//! verdicts. Verified needs the `sandbox-test-hooks` verifier with its clock +//! pinned inside the fixture collateral's validity window, the fixture's +//! compose hash patched into contract state (no vote can derive it), and +//! signing as the fixture account, whose key the quote's report_data binds. #![allow(non_snake_case)] use crate::sandbox::{ @@ -21,10 +12,10 @@ use crate::sandbox::{ consts::ALL_PROTOCOLS, contract_build::{tee_verifier_contract, tee_verifier_contract_with_sandbox_test_hooks}, mpc_contract::{ - get_config, get_participant_attestation, get_tee_accounts, - prepay_and_submit_participant_info, prepay_attestation_grants, submit_participant_info, - tee_verifier_account_id, total_gas_fee, vote_add_launcher_hash, - vote_add_os_measurement, vote_for_hash, vote_tee_verifier_change, + get_config, get_participant_attestation, get_tee_accounts, prepay_attestation_grants, + submit_participant_info, tee_verifier_account_id, total_gas_fee, + vote_add_launcher_hash, vote_add_os_measurement, vote_for_hash, + vote_tee_verifier_change, }, }, }; @@ -52,22 +43,26 @@ use test_utils::attestation::{ launcher_image_hash, mock_dto_dstack_attestation, p2p_tls_key, verified_report, }; -async fn setup() -> SandboxTestSetup { - SandboxTestSetup::builder() +async fn setup() -> (Worker, Contract, Vec) { + let setup = SandboxTestSetup::builder() .with_protocols(ALL_PROTOCOLS) .build() - .await + .await; + (setup.worker, setup.contract, setup.mpc_signer_accounts) +} + +async fn all_vote(participants: &[Account], vote: impl AsyncFn(&Account) -> anyhow::Result<()>) { + for result in join_all(participants.iter().map(|p| vote(p))).await { + result.unwrap(); + } } -/// Votes `verifier` in as `mpc-contract`'s trusted verifier (all participants vote -/// so the change crosses threshold). async fn trust_verifier(contract: &Contract, participants: &[Account], verifier: &AccountId) { let expected_code_hash = [7u8; 32]; - for account in participants { - vote_tee_verifier_change(account, contract, verifier, expected_code_hash) - .await - .unwrap(); - } + all_vote(participants, async |account| { + vote_tee_verifier_change(account, contract, verifier, expected_code_hash).await + }) + .await; } async fn deploy_and_trust_verifier( @@ -79,10 +74,17 @@ async fn deploy_and_trust_verifier( trust_verifier(contract, participants, verifier.id()).await; } -/// Deploys the verifier build with the pinnable verification clock, pins it to -/// [`VALID_ATTESTATION_TIMESTAMP`] (the only time window in which the fixture -/// collateral verifies), and votes it in. Returns the verifier so tests can -/// match its receipt by executor. +async fn pin_verifier_clock(worker: &Worker, verifier: &AccountId, pin: u64) { + worker + .patch_state( + verifier, + SANDBOX_TEST_PINNED_NOW_STORAGE_KEY, + &pin.to_le_bytes(), + ) + .await + .unwrap(); +} + async fn deploy_and_trust_pinned_verifier( worker: &Worker, contract: &Contract, @@ -92,45 +94,28 @@ async fn deploy_and_trust_pinned_verifier( .dev_deploy(tee_verifier_contract_with_sandbox_test_hooks()) .await .unwrap(); - worker - .patch_state( - verifier.id(), - SANDBOX_TEST_PINNED_NOW_STORAGE_KEY, - &VALID_ATTESTATION_TIMESTAMP.to_le_bytes(), - ) - .await - .unwrap(); + pin_verifier_clock(worker, verifier.id(), VALID_ATTESTATION_TIMESTAMP).await; trust_verifier(contract, participants, verifier.id()).await; verifier } -/// Votes the fixture's image and launcher hashes into the on-chain allowlists. Within a -/// round the voters are distinct accounts, so the votes run concurrently. async fn vote_fixture_image_and_launcher(contract: &Contract, participants: &[Account]) { let image = image_digest(); - for result in join_all( - participants - .iter() - .map(|account| vote_for_hash(account, contract, &image)), - ) - .await - { - result.unwrap(); - } + all_vote(participants, async |account| { + vote_for_hash(account, contract, &image).await + }) + .await; let launcher = launcher_image_hash(); - for result in join_all( - participants - .iter() - .map(|account| vote_add_launcher_hash(account, contract, &launcher)), - ) - .await - { - result.unwrap(); - } + all_vote(participants, async |account| { + vote_add_launcher_hash(account, contract, &launcher).await + }) + .await; } -/// Votes the fixture's hashes in, then patches its compose hash into the allowlist, -/// which derivation cannot produce. +/// Votes the fixture's image and launcher hashes in, then patches its compose hash into +/// contract state. The contract only allows compose hashes computed from its compiled-in +/// template; the fixture CVM's compose carried an extra key-export service, so no vote +/// can ever allow its hash. async fn whitelist_fixture_dstack_hashes( worker: &Worker, contract: &Contract, @@ -156,30 +141,6 @@ async fn whitelist_fixture_dstack_hashes( .unwrap(); } -/// Adds the OS measurements on top of the hash allowlists, the sandbox -/// analogue of the in-process `whitelist_dstack_measurements` helper. -async fn whitelist_fixture_dstack_measurements( - worker: &Worker, - contract: &Contract, - participants: &[Account], -) { - whitelist_fixture_dstack_hashes(worker, contract, participants).await; - for &measurements in default_measurements() { - let measurements = ContractExpectedMeasurements::from(measurements); - for result in join_all( - participants - .iter() - .map(|account| vote_add_os_measurement(account, contract, &measurements)), - ) - .await - { - result.unwrap(); - } - } -} - -/// Creates an account holding the fixture secret key, so its submissions pass -/// the report_data binding baked into the fixture quote. async fn create_fixture_account(worker: &Worker, account_id: &str) -> Account { let secret_key: SecretKey = account_secret_key() .parse() @@ -199,38 +160,35 @@ fn wall_clock_seconds() -> u64 { .as_secs() } -/// Funds one attestation-storage grant for `beneficiary` from a throwaway account, the -/// way an operator does for a node. Storing a first attestation for a TLS key needs a -/// grant, and keeping the payer separate leaves the beneficiary's balance untouched so -/// tests can still assert it spent only gas. +/// A separate payer leaves the beneficiary's balance untouched, so tests can assert it +/// spent only gas. Returns the beneficiary's balance after the prepayment. async fn prepay_grant_from_separate_payer( worker: &Worker, contract: &Contract, - beneficiary: &AccountId, -) { + beneficiary: &Account, +) -> NearToken { let payer = worker.dev_create_account().await.unwrap(); - let prepayment = prepay_attestation_grants(&payer, contract, beneficiary, 1) + let prepayment = prepay_attestation_grants(&payer, contract, beneficiary.id(), 1) .await .unwrap(); assert!(prepayment.is_success(), "prepayment failed: {prepayment:?}"); + beneficiary.view_account().await.unwrap().balance } -/// Full Verified-path environment: pinned verifier voted in, fixture hashes and -/// measurements whitelisted, plus a prepaid fixture account whose submissions -/// pass the report_data binding. -async fn setup_verified_fixture() -> (SandboxTestSetup, Account) { - let setup = setup().await; - deploy_and_trust_pinned_verifier(&setup.worker, &setup.contract, &setup.mpc_signer_accounts) +async fn setup_verified_fixture() -> (Worker, Contract, Account) { + let (worker, contract, mpc_signer_accounts) = setup().await; + deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await; + whitelist_fixture_dstack_hashes(&worker, &contract, &mpc_signer_accounts).await; + for &measurements in default_measurements() { + let measurements = ContractExpectedMeasurements::from(measurements); + all_vote(&mpc_signer_accounts, async |account| { + vote_add_os_measurement(account, &contract, &measurements).await + }) .await; - whitelist_fixture_dstack_measurements( - &setup.worker, - &setup.contract, - &setup.mpc_signer_accounts, - ) - .await; - let submitter = create_fixture_account(&setup.worker, "fixture-node-a").await; - prepay_grant_from_separate_payer(&setup.worker, &setup.contract, submitter.id()).await; - (setup, submitter) + } + let submitter = create_fixture_account(&worker, "fixture-node-a").await; + prepay_grant_from_separate_payer(&worker, &contract, &submitter).await; + (worker, contract, submitter) } async fn submit_dstack(submitter: &Account, contract: &Contract) -> ExecutionFinalResult { @@ -314,21 +272,12 @@ async fn assert_only_gas_spent( #[tokio::test] async fn submit_participant_info__should_reject_dstack_when_verifier_not_configured() { // Given - let SandboxTestSetup { - mpc_signer_accounts, - contract, - .. - } = setup().await; + let (worker, contract, mpc_signer_accounts) = setup().await; + let submitter = &mpc_signer_accounts[0]; + prepay_grant_from_separate_payer(&worker, &contract, submitter).await; // When - let result = prepay_and_submit_participant_info( - &mpc_signer_accounts[0], - &contract, - &mock_dto_dstack_attestation(), - &p2p_tls_key().into(), - ) - .await - .unwrap(); + let result = submit_dstack(submitter, &contract).await; // Then: it fails synchronously (before any cross-contract call), so the error // is on the top-level tx result, not a later receipt. @@ -353,11 +302,7 @@ async fn submit_participant_info__should_reject_dstack_when_verifier_not_configu #[tokio::test] async fn tee_verifier_account_id__should_return_none_until_a_verifier_is_voted_in() { // Given - let SandboxTestSetup { - mpc_signer_accounts, - contract, - .. - } = setup().await; + let (_worker, contract, mpc_signer_accounts) = setup().await; assert_eq!(tee_verifier_account_id(&contract).await, None); // When @@ -371,16 +316,10 @@ async fn tee_verifier_account_id__should_return_none_until_a_verifier_is_voted_i #[tokio::test] async fn submit_participant_info__should_store_nothing_on_verifier_rejection() { // Given - let SandboxTestSetup { - worker, - mpc_signer_accounts, - contract, - .. - } = setup().await; + let (worker, contract, mpc_signer_accounts) = setup().await; deploy_and_trust_verifier(&worker, &contract, &mpc_signer_accounts).await; let submitter = mpc_signer_accounts[0].clone(); - prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; - let balance_before = submitter.view_account().await.unwrap().balance; + let balance_before = prepay_grant_from_separate_payer(&worker, &contract, &submitter).await; let mut attestation = mock_dto_dstack_attestation(); let dtos::Attestation::Dstack(dstack) = &mut attestation else { panic!("fixture must be a Dstack attestation"); @@ -410,17 +349,11 @@ async fn submit_participant_info__should_store_nothing_on_verifier_rejection() { #[tokio::test] async fn submit_participant_info__should_fail_and_store_nothing_when_verifier_unreachable() { // Given: a verifier account that was never deployed, so the verify_quote promise fails. - let SandboxTestSetup { - worker, - mpc_signer_accounts, - contract, - .. - } = setup().await; + let (worker, contract, mpc_signer_accounts) = setup().await; let missing_verifier: AccountId = "nonexistent-verifier.near".parse().unwrap(); trust_verifier(&contract, &mpc_signer_accounts, &missing_verifier).await; let submitter = mpc_signer_accounts[0].clone(); - prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; - let balance_before = submitter.view_account().await.unwrap().balance; + let balance_before = prepay_grant_from_separate_payer(&worker, &contract, &submitter).await; // When let result = submit_dstack(&submitter, &contract).await; @@ -443,19 +376,13 @@ const EXPIRY_SLACK_SECONDS: u64 = 600; #[tokio::test] async fn submit_participant_info__should_run_dcap_within_verifier_gas_budget() { // Given - let SandboxTestSetup { - worker, - mpc_signer_accounts, - contract, - .. - } = setup().await; + let (worker, contract, mpc_signer_accounts) = setup().await; let verifier = deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await; // Only the hash allowlists gate this test's outcome: the plain dev-account // submitter fails at report_data, which runs before the measurements check. whitelist_fixture_dstack_hashes(&worker, &contract, &mpc_signer_accounts).await; let submitter = mpc_signer_accounts[0].clone(); - prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; - let balance_before = submitter.view_account().await.unwrap().balance; + let balance_before = prepay_grant_from_separate_payer(&worker, &contract, &submitter).await; // When let result = submit_dstack(&submitter, &contract).await; @@ -519,8 +446,7 @@ async fn submit_participant_info__should_fail_cleanly_when_verifier_gas_budget_t .await; deploy_and_trust_verifier(&worker, &contract, &mpc_signer_accounts).await; let submitter = mpc_signer_accounts[0].clone(); - prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; - let balance_before = submitter.view_account().await.unwrap().balance; + let balance_before = prepay_grant_from_separate_payer(&worker, &contract, &submitter).await; // When let result = submit_dstack(&submitter, &contract).await; @@ -539,8 +465,8 @@ async fn submit_participant_info__should_fail_cleanly_when_verifier_gas_budget_t #[tokio::test] async fn submit_participant_info__should_store_attestation_on_verified_quote() { // Given - let (setup, submitter) = setup_verified_fixture().await; - let contract = &setup.contract; + let (_worker, contract, submitter) = setup_verified_fixture().await; + let contract = &contract; let balance_before = submitter.view_account().await.unwrap().balance; let submitted_at = wall_clock_seconds(); @@ -600,14 +526,14 @@ async fn submit_participant_info__should_reject_verified_quote_when_tls_key_owne // itself distinguishes the second submitter; only the ownership guard does. // That guard runs before verification, so the rejection is synchronous and // never reaches the verifier. - let (setup, owner) = setup_verified_fixture().await; - let contract = &setup.contract; + let (worker, contract, owner) = setup_verified_fixture().await; + let contract = &contract; submit_dstack(&owner, contract).await.into_result().unwrap(); let stored_before = get_participant_attestation(contract, &p2p_tls_key().into()) .await .unwrap() .expect("the owner's submission must store an attestation"); - let attacker = create_fixture_account(&setup.worker, "fixture-node-b").await; + let attacker = create_fixture_account(&worker, "fixture-node-b").await; let balance_before = attacker.view_account().await.unwrap().balance; // When @@ -648,17 +574,11 @@ async fn submit_participant_info__should_reject_verified_quote_when_tls_key_owne async fn submit_participant_info__should_reject_verified_quote_when_compose_hash_not_allowed() { // Given: hashes voted in but the fixture's compose hash never patched, so the // allowlist holds only the derived compose hash. - let SandboxTestSetup { - worker, - mpc_signer_accounts, - contract, - .. - } = setup().await; + let (worker, contract, mpc_signer_accounts) = setup().await; deploy_and_trust_pinned_verifier(&worker, &contract, &mpc_signer_accounts).await; vote_fixture_image_and_launcher(&contract, &mpc_signer_accounts).await; let submitter = create_fixture_account(&worker, "fixture-node-a").await; - prepay_grant_from_separate_payer(&worker, &contract, submitter.id()).await; - let balance_before = submitter.view_account().await.unwrap().balance; + let balance_before = prepay_grant_from_separate_payer(&worker, &contract, &submitter).await; // When let result = submit_dstack(&submitter, &contract).await; @@ -703,14 +623,7 @@ async fn verify_quote__should_ignore_pinned_timestamp_on_production_build() { let far_future = wall_clock_seconds() + 100 * 365 * 24 * 3600; let mut pinned = Vec::new(); for pin in [VALID_ATTESTATION_TIMESTAMP, far_future] { - worker - .patch_state( - verifier.id(), - SANDBOX_TEST_PINNED_NOW_STORAGE_KEY, - &pin.to_le_bytes(), - ) - .await - .unwrap(); + pin_verifier_clock(&worker, verifier.id(), pin).await; pinned.push(call_verify_quote(&verifier, args).await); } diff --git a/crates/e2e-tests/Cargo.toml b/crates/e2e-tests/Cargo.toml index 85b3cb45a3..76313cef71 100644 --- a/crates/e2e-tests/Cargo.toml +++ b/crates/e2e-tests/Cargo.toml @@ -29,7 +29,6 @@ rand = { workspace = true } reqwest = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } -sha2 = { workspace = true } tempfile = { workspace = true } test-port-allocator = { workspace = true } test-utils = { workspace = true } diff --git a/crates/e2e-tests/src/cluster.rs b/crates/e2e-tests/src/cluster.rs index 614285d704..28e9839aa4 100644 --- a/crates/e2e-tests/src/cluster.rs +++ b/crates/e2e-tests/src/cluster.rs @@ -24,7 +24,6 @@ use near_mpc_contract_interface::{ use rand::SeedableRng; use rand::rngs::StdRng; use serde_json::json; -use sha2::{Digest, Sha256}; use crate::blockchain::{DeployedContract, NearBlockchain, NearKitCaller}; use crate::mpc_node::{MpcNode, MpcNodeSetup, MpcNodeSetupArgs, NodePorts}; @@ -256,37 +255,33 @@ fn default_mpc_binary_path() -> PathBuf { /// Plumbing helper: failures here are setup bugs, not test failures, so we panic. pub fn must_load_tee_verifier_wasm() -> Vec { - if let Ok(path) = std::env::var("MPC_TEE_VERIFIER_WASM") { - let wasm_path = PathBuf::from(&path); - return std::fs::read(&wasm_path).unwrap_or_else(|e| { - panic!( - "failed to read tee-verifier WASM at {}: {e}. Build it with \ - `cargo make build-tee-verifier-optimized` (skipped when E2E_SKIP_BUILD is set)", - wasm_path.display() - ) - }); - } - let default_path = Path::new(env!("CARGO_MANIFEST_DIR")) .join("../../target/near/tee_verifier/tee_verifier.wasm"); - if default_path.exists() { - return std::fs::read(&default_path).unwrap_or_else(|e| { - panic!( - "failed to read tee-verifier WASM at {}: {e}", - default_path.display() + let wasm_path = match std::env::var("MPC_TEE_VERIFIER_WASM") { + Ok(path) => PathBuf::from(path), + Err(_) if default_path.exists() => default_path, + Err(_) => { + tracing::info!( + "MPC_TEE_VERIFIER_WASM not set and pre-built WASM not found; building \ + tee-verifier. Build it up front with `cargo make build-tee-verifier-optimized` \ + to skip this." + ); + // Same out dir the probe above checks, so this build is found and reused + // by later test processes instead of rebuilding each time. + return test_utils::contract_build::ContractBuilder::new( + "crates/tee-verifier/Cargo.toml", ) - }); - } - - tracing::info!( - "MPC_TEE_VERIFIER_WASM not set and pre-built WASM not found; building tee-verifier. \ - Build it up front with `cargo make build-tee-verifier-optimized` to skip this." - ); - // Same out dir the probe above checks, so this build is found and reused - // by later test processes instead of rebuilding each time. - test_utils::contract_build::ContractBuilder::new("crates/tee-verifier/Cargo.toml") - .out_dir("target/near/tee_verifier") - .build() + .out_dir("target/near/tee_verifier") + .build(); + } + }; + std::fs::read(&wasm_path).unwrap_or_else(|e| { + panic!( + "failed to read tee-verifier WASM at {}: {e}. Build it with \ + `cargo make build-tee-verifier-optimized` (skipped when E2E_SKIP_BUILD is set)", + wasm_path.display() + ) + }) } /// A running MPC test cluster with a deployed contract and N mpc-node processes. @@ -1440,7 +1435,7 @@ async fn deploy_and_trust_tee_verifier( // expected_code_hash commits every voter to the same audited WASM; the // contract only compares voters' hashes against each other, not against // the deployed bytes. - let expected_code_hash = hex::encode(Sha256::digest(verifier_wasm)); + let expected_code_hash = hex::encode(near_kit::CryptoHash::hash(verifier_wasm).as_bytes()); let args = json!({ "candidate_account_id": verifier_account, "expected_code_hash": expected_code_hash, @@ -1467,8 +1462,6 @@ async fn deploy_and_trust_tee_verifier( // The votes are not awaited to finality, so views can lag them; poll like // the post-init state waits do. - let timeout = Duration::from_secs(30); - let max_times = (timeout.as_millis() / POLL_INTERVAL.as_millis()) as usize; (|| async { let resolved: Option = contract.view(method_names::TEE_VERIFIER_ACCOUNT_ID).await?; anyhow::ensure!( @@ -1477,18 +1470,9 @@ async fn deploy_and_trust_tee_verifier( ); Ok(()) }) - .retry( - ConstantBuilder::default() - .with_delay(POLL_INTERVAL) - .with_max_times(max_times), - ) + .retry(cluster_poll_retry()) .await - .with_context(|| { - format!( - "tee-verifier not resolved as the trusted verifier within {}s", - timeout.as_secs() - ) - }) + .context("tee-verifier not resolved as the trusted verifier") } async fn add_initial_domains( diff --git a/crates/test-utils/src/contract_build.rs b/crates/test-utils/src/contract_build.rs index b382904ad3..83ca9afbcb 100644 --- a/crates/test-utils/src/contract_build.rs +++ b/crates/test-utils/src/contract_build.rs @@ -76,12 +76,8 @@ impl ContractBuilder { }; // Marks the artifact as test-built; sandbox-only code compiles in only under this cfg. - let rustflags = match std::env::var("RUSTFLAGS") { - Ok(inherited) if !inherited.is_empty() => { - format!("{inherited} --cfg mpc_sandbox_wasm") - } - _ => "--cfg mpc_sandbox_wasm".to_string(), - }; + let inherited = std::env::var("RUSTFLAGS").unwrap_or_default(); + let rustflags = format!("{inherited} --cfg mpc_sandbox_wasm"); let opts = cargo_near_build::BuildOpts { manifest_path: Some(to_utf8(abs_manifest)), From 4c764ec7fba9b44ef3c8368a4fe7510f09547d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20B=C4=99za?= Date: Mon, 17 Aug 2026 23:01:18 +0200 Subject: [PATCH 32/32] refactor(test): look up the fixture's stored attestation through one helper Every lookup in the file asks for the same TLS key, so keep the key in one place instead of restating it at each call site. --- crates/contract/tests/sandbox/tee_verifier.rs | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/crates/contract/tests/sandbox/tee_verifier.rs b/crates/contract/tests/sandbox/tee_verifier.rs index 320f9710ef..895d82bd86 100644 --- a/crates/contract/tests/sandbox/tee_verifier.rs +++ b/crates/contract/tests/sandbox/tee_verifier.rs @@ -202,6 +202,12 @@ async fn submit_dstack(submitter: &Account, contract: &Contract) -> ExecutionFin .unwrap() } +async fn stored_fixture_attestation(contract: &Contract) -> Option { + get_participant_attestation(contract, &p2p_tls_key().into()) + .await + .unwrap() +} + /// Asserts a Dstack submission failed cleanly: a receipt failed mentioning every /// string in `expected_error` (`fail_attestation_submission` panics in its own /// receipt), no attestation was stored, and the caller spent only gas. @@ -227,9 +233,7 @@ async fn assert_submission_failed_cleanly( ); } - let stored = get_participant_attestation(contract, &p2p_tls_key().into()) - .await - .unwrap(); + let stored = stored_fixture_attestation(contract).await; assert!(stored.is_none(), "nothing should be stored on failure"); assert_only_gas_spent(submitter, balance_before, result).await; } @@ -293,9 +297,7 @@ async fn submit_participant_info__should_reject_dstack_when_verifier_not_configu err.contains(&expected_panic), "expected {expected_panic:?}, got: {err}" ); - let stored = get_participant_attestation(&contract, &p2p_tls_key().into()) - .await - .unwrap(); + let stored = stored_fixture_attestation(&contract).await; assert!(stored.is_none(), "no attestation should be stored"); } @@ -478,9 +480,8 @@ async fn submit_participant_info__should_store_attestation_on_verified_quote() { result.failures().is_empty(), "expected every receipt to succeed, got: {result:#?}" ); - let stored = get_participant_attestation(contract, &p2p_tls_key().into()) + let stored = stored_fixture_attestation(contract) .await - .unwrap() .expect("a Verified submission must store an attestation"); let dtos::VerifiedAttestation::Dstack(stored) = stored else { panic!("expected a stored Dstack attestation, got: {stored:?}"); @@ -529,9 +530,8 @@ async fn submit_participant_info__should_reject_verified_quote_when_tls_key_owne let (worker, contract, owner) = setup_verified_fixture().await; let contract = &contract; submit_dstack(&owner, contract).await.into_result().unwrap(); - let stored_before = get_participant_attestation(contract, &p2p_tls_key().into()) + let stored_before = stored_fixture_attestation(contract) .await - .unwrap() .expect("the owner's submission must store an attestation"); let attacker = create_fixture_account(&worker, "fixture-node-b").await; let balance_before = attacker.view_account().await.unwrap().balance; @@ -551,9 +551,8 @@ async fn submit_participant_info__should_reject_verified_quote_when_tls_key_owne rendered.contains(&expected), "expected a failure containing {expected:?}, got: {rendered}" ); - let stored_after = get_participant_attestation(contract, &p2p_tls_key().into()) + let stored_after = stored_fixture_attestation(contract) .await - .unwrap() .expect("the owner's attestation must survive the attack"); assert_eq!( stored_after, stored_before,