diff --git a/.github/workflows/benchmark-runtime-weights.yml b/.github/workflows/benchmark-runtime-weights.yml index 77543590ac..2037670b31 100644 --- a/.github/workflows/benchmark-runtime-weights.yml +++ b/.github/workflows/benchmark-runtime-weights.yml @@ -30,7 +30,7 @@ on: required: true env: - INSTANCE_ID: ${{ secrets.BENCHMARK_INSTANCE_ID }} # remote AWS host to run benchmarking + INSTANCE_ID: ${{ secrets.BENCHMARK_INSTANCE_ID }} # remote AWS host to run benchmarking BENCHMARK_SSH_USER: ${{ secrets.BENCHMARK_SSH_USER }} BENCHMARK_SSH_KEYPATH: ${{ secrets.BENCHMARK_SSH_KEYPATH }} DOCKER_BUILDKIT: 1 @@ -66,7 +66,7 @@ jobs: ./scripts/build-docker.sh production runtime-benchmarks --features=runtime-benchmarks - name: Dockerhub login - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} diff --git a/.github/workflows/build-docker-with-args.yml b/.github/workflows/build-docker-with-args.yml index ffe1ca1bca..296009c25e 100644 --- a/.github/workflows/build-docker-with-args.yml +++ b/.github/workflows/build-docker-with-args.yml @@ -42,7 +42,7 @@ jobs: docker images - name: Dockerhub login - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7785e11e78..ebb86df115 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,7 +153,7 @@ jobs: - name: Install pre-built taplo run: | mkdir -p $HOME/.local/bin - wget -q https://github.com/tamasfe/taplo/releases/latest/download/taplo-linux-x86_64.gz + wget -q https://github.com/tamasfe/taplo/releases/download/0.8.1/taplo-linux-x86_64.gz gzip -d taplo-linux-x86_64.gz cp taplo-linux-x86_64 $HOME/.local/bin/taplo chmod a+x $HOME/.local/bin/taplo @@ -184,7 +184,7 @@ jobs: - name: bitacross-worker enclave-runtime fmt check working-directory: ./bitacross-worker/enclave-runtime run: | - cargo fmt --all -- --check + cargo fmt --all -- --check - name: Enable corepack and pnpm run: corepack enable && corepack enable pnpm @@ -311,7 +311,7 @@ jobs: - set-condition - sequentialise if: needs.set-condition.outputs.rebuild_bitacross == 'true' -# todo: we might want to change this image in the future + # todo: we might want to change this image in the future container: "litentry/litentry-tee-dev:latest" steps: - uses: actions/checkout@v4 @@ -327,9 +327,6 @@ jobs: echo "::group::cargo clippy all" cargo clippy --release -- -D warnings echo "::endgroup::" - echo "::group::cargo clippy sidechain" - cargo clippy --release --features sidechain -- -D warnings - echo "::endgroup::" echo "::group::cargo clippy offchain-worker" cargo clean --profile release cargo clippy --release --features offchain-worker -- -D warnings @@ -352,9 +349,6 @@ jobs: echo "::group::cargo clippy all" cargo clippy --release -- -D warnings echo "::endgroup::" - echo "::group::cargo clippy sidechain" - cargo clippy --release --features sidechain -- -D warnings - echo "::endgroup::" echo "::group::cargo clippy offchain-worker" cargo clean --profile release cargo clippy --release --features offchain-worker -- -D warnings @@ -692,20 +686,16 @@ jobs: fail-fast: false matrix: include: - - test_name: demo-shielding-unshielding-multiworker - - test_name: demo-direct-call # Litentry - - test_name: lit-set-heartbeat-timeout - test_name: lit-ii-vc-test - test_name: lit-ii-identity-test - test_name: lit-di-substrate-identity-test - test_name: lit-di-evm-identity-test - test_name: lit-di-bitcoin-identity-test - test_name: lit-di-vc-test + - test_name: lit-dr-vc-test - test_name: lit-parentchain-nonce - test_name: lit-ii-batch-test - - test_name: lit-test-stress-script - - test_name: lit-data-providers-test steps: - uses: actions/checkout@v4 @@ -785,6 +775,7 @@ jobs: - test_name: lit-di-evm-identity-multiworker-test - test_name: lit-di-substrate-identity-multiworker-test - test_name: lit-di-vc-multiworker-test + - test_name: lit-dr-vc-multiworker-test - test_name: lit-ii-batch-test-multiworker - test_name: lit-ii-identity-multiworker-test - test_name: lit-ii-vc-multiworker-test @@ -890,7 +881,7 @@ jobs: docker load < litentry-tee.tar.gz - name: Dockerhub login - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} diff --git a/.github/workflows/verify-correctness-of-vc-content-.yml b/.github/workflows/verify-correctness-of-vc-content-.yml new file mode 100644 index 0000000000..201b5f32a4 --- /dev/null +++ b/.github/workflows/verify-correctness-of-vc-content-.yml @@ -0,0 +1,73 @@ +name: Verify the correctness of VC content + +on: + workflow_dispatch: + inputs: + docker-tag: + description: "client tag(e.g. p1.2.0-9701-w0.0.1-101)" + required: true + default: "latest" +jobs: + test-data-provider: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set ENV + run: | + # extracting parachain version and worker version from release tag + echo "PARACHAIN_TAG=$(echo ${{inputs.docker-tag}} | sed 's/p/v/;s/\(.*\)-w.*/\1/')" >> $GITHUB_ENV + echo "WORKER_TAG=$(echo ${{inputs.docker-tag}} | sed 's/.*\(w.*\)/\1/;s/w/v/')" >> $GITHUB_ENV + + - name: Pull litentry image optionally + run: | + docker pull parity/polkadot + docker pull litentry/litentry-worker:$WORKER_TAG + docker pull litentry/litentry-cli:$WORKER_TAG + docker pull litentry/litentry-parachain:$PARACHAIN_TAG + + - name: Re-tag docker image + run: | + docker tag litentry/litentry-worker:$WORKER_TAG litentry/litentry-worker:latest + docker tag litentry/litentry-cli:$WORKER_TAG litentry/litentry-cli:latest + docker tag litentry/litentry-parachain:$PARACHAIN_TAG litentry/litentry-parachain:latest + + - run: docker images --all + + - name: Enable corepack and pnpm + run: corepack enable && corepack enable pnpm + + - name: Generate parachain artefacts + run: | + ./tee-worker/scripts/litentry/generate_parachain_artefacts.sh + + - name: Build litentry parachain docker images + run: | + cd tee-worker/docker + docker compose -f litentry-parachain.build.yml build + + - name: Run data-provider-test + run: | + cd tee-worker/docker + docker compose -f docker-compose.yml -f lit-data-provider-test.yml up --no-build --exit-code-from lit-data-provider-test lit-data-provider-test + + - name: Stop docker containers + run: | + cd tee-worker/docker + docker compose -f docker-compose.yml -f lit-data-provider-test.yml stop + + - name: Collect Docker Logs + continue-on-error: true + if: always() + uses: jwalton/gh-docker-logs@v2 + with: + tail: all + dest: logs + + - name: Upload logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: logs-lit-data-provider-test + path: logs + if-no-files-found: ignore diff --git a/Cargo.lock b/Cargo.lock index 4e9e5bcfdd..c546ea9364 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,7 +445,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -456,7 +456,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -961,9 +961,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1068,7 +1068,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -1116,13 +1116,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "common-primitives" -version = "0.1.0" -dependencies = [ - "sp-std", -] - [[package]] name = "concurrent-queue" version = "2.2.0" @@ -1747,7 +1740,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2046,7 +2039,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2073,7 +2066,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2090,7 +2083,7 @@ checksum = "b8fcfa71f66c8563c4fa9dd2bb68368d50267856f831ac5d85367e0805f9606c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2368,7 +2361,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2561,7 +2554,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2572,7 +2565,7 @@ checksum = "b893c4eb2dc092c811165f84dc7447fae16fb66521717968c34c509b39b1a5c5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2872,7 +2865,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3389,7 +3382,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3504,7 +3497,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3516,7 +3509,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3526,7 +3519,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3693,7 +3686,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -5538,7 +5531,7 @@ dependencies = [ "cargo_toml", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -5590,7 +5583,6 @@ dependencies = [ "pallet-scheduler", "pallet-session", "pallet-sidechain", - "pallet-teeracle", "pallet-teerex", "pallet-timestamp", "pallet-transaction-payment", @@ -6525,7 +6517,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -6536,7 +6528,7 @@ checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -6936,6 +6928,24 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-bitacross" +version = "0.1.0" +dependencies = [ + "core-primitives", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-bounties" version = "4.0.0-dev" @@ -7439,7 +7449,7 @@ dependencies = [ "frame-system", "pallet-balances", "pallet-group", - "pallet-teerex", + "pallet-teebag", "pallet-timestamp", "parity-scale-codec", "scale-info", @@ -7447,7 +7457,6 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", - "teerex-primitives", "test-utils", ] @@ -7664,7 +7673,7 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-std", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed)", + "substrate-fixed", ] [[package]] @@ -7892,7 +7901,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -7945,28 +7954,35 @@ dependencies = [ ] [[package]] -name = "pallet-teeracle" +name = "pallet-teebag" version = "0.1.0" dependencies = [ + "base64 0.13.1", + "chrono", + "der 0.6.1", + "env_logger 0.9.3", "frame-benchmarking", "frame-support", "frame-system", + "hex", "hex-literal 0.4.1", "log", "pallet-balances", - "pallet-teerex", "pallet-timestamp", "parity-scale-codec", + "ring 0.16.20", + "rustls-webpki", "scale-info", + "serde", + "serde_json", "sp-core", "sp-externalities", "sp-io", "sp-keyring", "sp-runtime", "sp-std", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed.git?tag=v0.5.9)", - "teeracle-primitives", "test-utils", + "x509-cert", ] [[package]] @@ -8119,7 +8135,7 @@ dependencies = [ "frame-system", "pallet-balances", "pallet-group", - "pallet-teerex", + "pallet-teebag", "pallet-timestamp", "parity-scale-codec", "scale-info", @@ -8127,7 +8143,6 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", - "teerex-primitives", "test-utils", ] @@ -8410,7 +8425,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -8451,7 +8466,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -9775,7 +9790,7 @@ dependencies = [ "proc-macro2", "quote", "sha3", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -9890,7 +9905,7 @@ checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -10286,7 +10301,7 @@ checksum = "2dfaf0c85b766276c797f3791f5bc6d5bd116b41d53049af2789666b0c0bc9fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -10520,6 +10535,7 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-bitacross", "pallet-bounties", "pallet-bridge", "pallet-bridge-transfer", @@ -10550,7 +10566,7 @@ dependencies = [ "pallet-session", "pallet-sidechain", "pallet-sudo", - "pallet-teeracle", + "pallet-teebag", "pallet-teerex", "pallet-timestamp", "pallet-tips", @@ -10771,6 +10787,7 @@ dependencies = [ "pallet-group", "pallet-membership", "pallet-multisig", + "pallet-teebag", "pallet-teerex", "pallet-transaction-payment", "pallet-treasury", @@ -11079,7 +11096,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -12055,7 +12072,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -12341,7 +12358,7 @@ checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -12682,7 +12699,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -12924,7 +12941,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -12943,7 +12960,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -13154,7 +13171,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -13322,7 +13339,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -13521,7 +13538,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -13577,17 +13594,6 @@ dependencies = [ "platforms 2.0.0", ] -[[package]] -name = "substrate-fixed" -version = "0.5.9" -source = "git+https://github.com/encointer/substrate-fixed.git?tag=v0.5.9#a4fb461aae6205ffc55bed51254a40c52be04e5d" -dependencies = [ - "parity-scale-codec", - "scale-info", - "serde", - "typenum 1.16.0 (git+https://github.com/encointer/typenum?tag=v1.16.0)", -] - [[package]] name = "substrate-fixed" version = "0.5.9" @@ -13706,9 +13712,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" dependencies = [ "proc-macro2", "quote", @@ -13760,14 +13766,6 @@ version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d2faeef5759ab89935255b1a4cd98e0baf99d1085e37d36599c625dac49ae8e" -[[package]] -name = "teeracle-primitives" -version = "0.1.0" -dependencies = [ - "common-primitives", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed.git?tag=v0.5.9)", -] - [[package]] name = "teerex-primitives" version = "0.1.0" @@ -13832,7 +13830,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -13976,9 +13974,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -14001,7 +13999,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -14172,7 +14170,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -14215,7 +14213,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -14435,15 +14433,6 @@ dependencies = [ "scale-info", ] -[[package]] -name = "typenum" -version = "1.16.0" -source = "git+https://github.com/encointer/typenum?tag=v1.16.0#4c8dddaa8bdd13130149e43b4085ad14e960617f" -dependencies = [ - "parity-scale-codec", - "scale-info", -] - [[package]] name = "ucd-trie" version = "0.1.6" @@ -14662,7 +14651,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", "wasm-bindgen-shared", ] @@ -14696,7 +14685,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -15827,7 +15816,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -15935,7 +15924,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ba77c155ad..f45978d303 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ 'node', 'pallets/account-fix', + 'pallets/bitacross', 'pallets/bridge', 'pallets/bridge-transfer', 'pallets/drop3', @@ -10,20 +11,19 @@ members = [ 'pallets/identity-management', 'pallets/vc-management', 'pallets/sidechain', - 'pallets/teeracle', + 'pallets/teebag', 'pallets/teerex', 'pallets/teerex/sgx-verify', 'pallets/parentchain', 'pallets/test-utils', 'pallets/group', + 'pallets/bitacross', 'precompiles/*', - 'primitives/common', 'primitives/core', 'primitives/core/proc-macros', 'primitives/core/macros', 'primitives/hex', 'primitives/sidechain', - 'primitives/teeracle', 'primitives/teerex', 'runtime/litentry', 'runtime/litmus', diff --git a/bitacross-worker/.github/workflows/build_and_test.yml b/bitacross-worker/.github/workflows/build_and_test.yml deleted file mode 100644 index d007fe1eb4..0000000000 --- a/bitacross-worker/.github/workflows/build_and_test.yml +++ /dev/null @@ -1,599 +0,0 @@ -name: Build, Test, Clippy - -on: - workflow_dispatch: - push: - branches: - - master - - 'sdk-v[0-9]+.[0-9]+.[0-9]+-*' - tags: - - 'v[0-9]+.[0-9]+.[0-9]+*' - pull_request: - branches: - - master - - 'sdk-v[0-9]+.[0-9]+.[0-9]+-*' - -env: - CARGO_TERM_COLOR: always - LOG_DIR: logs - BUILD_CONTAINER_NAME: integritee_worker_enclave_test - -jobs: - cancel_previous_runs: - name: Cancel Previous Runs - runs-on: ubuntu-latest - steps: - - uses: styfle/cancel-workflow-action@0.11.0 - with: - access_token: ${{ secrets.GITHUB_TOKEN }} - - build-test: - runs-on: ${{ matrix.host }} - strategy: - fail-fast: false - matrix: - include: - - flavor_id: sidechain - mode: sidechain - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: offchain-worker - mode: offchain-worker - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: teeracle - mode: teeracle - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: sidechain-evm - mode: sidechain - additional_features: evm,dcap - host: integritee-builder-sgx - sgx_mode: HW - - steps: - - uses: actions/checkout@v3 - - - name: Set env - run: | - fingerprint=$RANDOM - echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV - SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") - echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV - if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then - echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV - else - echo "DOCKER_DEVICES=" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=" >> $GITHUB_ENV - fi - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - buildkitd-flags: --debug - driver: docker-container - - - name: Build Worker - env: - DOCKER_BUILDKIT: 1 - run: > - docker build -t integritee-worker-${{ env.IMAGE_SUFFIX }} - --target deployed-worker - --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg FINGERPRINT=${FINGERPRINT} --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} --build-arg SGX_MODE=${{ matrix.sgx_mode }} - -f build.Dockerfile . - - - run: docker images --all - - - name: Test Enclave # cargo test is not supported in the enclave, see: https://github.com/apache/incubator-teaclave-sgx-sdk/issues/232 - run: docker run --rm ${{ env.DOCKER_DEVICES }} ${{ env.DOCKER_VOLUMES }} integritee-worker-${{ env.IMAGE_SUFFIX }} test --all - - - name: Export worker image - run: | - docker image save integritee-worker-${{ env.IMAGE_SUFFIX }} | gzip > integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - - - name: Upload worker image - uses: actions/upload-artifact@v3 - with: - name: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - path: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - - - name: Create Enclave Digest File - run: | - mrenclave_hex=$(docker run integritee-worker-${{ env.IMAGE_SUFFIX }} mrenclave | grep -oP ':\s*\K[a-fA-F0-9]+') - echo "$mrenclave_hex" > mrenclave-${{ env.IMAGE_SUFFIX }}.hex - - - name: Upload Enclave Digest File - uses: actions/upload-artifact@v3 - with: - name: mrenclave-${{ env.IMAGE_SUFFIX }}.hex - path: mrenclave-${{ env.IMAGE_SUFFIX }}.hex - - - name: Delete images - run: | - if [[ "$(docker images -q integritee-worker-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee-worker-${{ env.IMAGE_SUFFIX }} 2>/dev/null - fi - docker images --all - - build-client: - runs-on: ${{ matrix.host }} - strategy: - fail-fast: false - matrix: - include: - - flavor_id: sidechain - mode: sidechain - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: offchain-worker - mode: offchain-worker - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: teeracle - mode: teeracle - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: sidechain-evm - mode: sidechain - additional_features: evm,dcap - host: integritee-builder-sgx - sgx_mode: HW - - steps: - - uses: actions/checkout@v3 - - - name: Set env - run: | - fingerprint=$RANDOM - echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV - SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") - echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV - if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then - echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV - else - echo "DOCKER_DEVICES=" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=" >> $GITHUB_ENV - fi - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - buildkitd-flags: --debug - driver: docker-container - - - name: Build CLI client - env: - DOCKER_BUILDKIT: 1 - run: > - docker build -t integritee-cli-client-${{ env.IMAGE_SUFFIX }} - --target deployed-client - --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} - -f build.Dockerfile . - - - run: docker images --all - - - name: Export client image - run: | - docker image save integritee-cli-client-${{ env.IMAGE_SUFFIX }} | gzip > integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - - - name: Upload CLI client image - uses: actions/upload-artifact@v3 - with: - name: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - path: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - - - name: Delete images - run: | - if [[ "$(docker images -q integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2>/dev/null - fi - docker images --all - - code-quality: - runs-on: ubuntu-latest - container: "integritee/integritee-dev:0.2.2" - strategy: - fail-fast: false - matrix: - check: [ - # Workspace - cargo test --release, - # Worker - # Use release mode as the CI runs out of disk space otherwise. - cargo clippy --release -- -D warnings, - cargo clippy --release --features evm -- -D warnings, - cargo clippy --release --features sidechain -- -D warnings, - cargo clippy --release --features teeracle -- -D warnings, - cargo clippy --release --features offchain-worker -- -D warnings, - - # Enclave - cd enclave-runtime && cargo clippy -- -D warnings, - cd enclave-runtime && cargo clippy --features evm -- -D warnings, - cd enclave-runtime && cargo clippy --features sidechain -- -D warnings, - cd enclave-runtime && cargo clippy --features teeracle -- -D warnings, - cd enclave-runtime && cargo clippy --features offchain-worker -- -D warnings, - - # Fmt - cargo fmt --all -- --check, - cd enclave-runtime && cargo fmt --all -- --check, - ] - steps: - - uses: actions/checkout@v3 - - name: init-rust-target - # Enclave is not in the same workspace - run: rustup show && cd enclave-runtime && rustup show - - - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.check }} - - - name: ${{ matrix.check }} - run: ${{ matrix.check }} - - toml-fmt: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: init rust - run: rustup show - - - name: Install taplo - run: cargo install taplo-cli --locked - - name: Cargo.toml fmt - run: taplo fmt --check - - - name: Fail-fast; cancel other jobs - if: failure() - uses: andymckay/cancel-action@0.3 - - integration-tests: - runs-on: ${{ matrix.host }} - if: ${{ always() }} - needs: [build-test, build-client] - env: - WORKER_IMAGE_TAG: integritee-worker:dev - CLIENT_IMAGE_TAG: integritee-cli:dev - COINMARKETCAP_KEY: ${{ secrets.COINMARKETCAP_KEY }} - # IAS_EPID_SPID: ${{ secrets.IAS_SPID }} - # IAS_EPID_KEY: ${{ secrets.IAS_PRIMARY_KEY }} - TEERACLE_INTERVAL_SECONDS: 10 - - strategy: - fail-fast: false - matrix: - include: - - test: M6 - flavor_id: sidechain - demo_name: demo-shielding-unshielding-multiworker - host: test-runner-sgx - sgx_mode: HW - - test: M8 - flavor_id: sidechain - demo_name: demo-direct-call - host: test-runner-sgx - sgx_mode: HW - - test: Sidechain - flavor_id: sidechain - demo_name: demo-sidechain - host: test-runner-sgx - sgx_mode: HW - - test: M6 - flavor_id: offchain-worker - demo_name: demo-shielding-unshielding-multiworker - host: test-runner-sgx - sgx_mode: HW - - test: Teeracle - flavor_id: teeracle - demo_name: demo-teeracle - host: test-runner-sgx - sgx_mode: HW - - test: Teeracle - flavor_id: teeracle - demo_name: demo-teeracle-generic - host: test-runner-sgx - sgx_mode: HW - - test: Benchmark - flavor_id: sidechain - demo_name: sidechain-benchmark - host: test-runner-sgx - sgx_mode: HW - - test: EVM - flavor_id: sidechain-evm - demo_name: demo-smart-contract - host: test-runner-sgx - sgx_mode: HW - - steps: - - uses: actions/checkout@v3 - - - name: Set env - run: | - version=$RANDOM - SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") - echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV - echo "FLAVOR_ID=${{ matrix.flavor_id }}" >> $GITHUB_ENV - echo "PROJECT=${{ matrix.flavor_id }}-${{ matrix.demo_name }}" >> $GITHUB_ENV - echo "VERSION=dev.$version" >> $GITHUB_ENV - echo "WORKER_IMAGE_TAG=integritee-worker:dev.$version" >> $GITHUB_ENV - echo "INTEGRITEE_NODE=integritee-node:1.1.3.$version" >> $GITHUB_ENV - echo "CLIENT_IMAGE_TAG=integritee-cli:dev.$version" >> $GITHUB_ENV - if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then - echo "SGX_PROVISION=/dev/sgx/provision" >> $GITHUB_ENV - echo "SGX_ENCLAVE=/dev/sgx/enclave" >> $GITHUB_ENV - echo "AESMD=/var/run/aesmd" >> $GITHUB_ENV - echo "SGX_QCNL=/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV - fi - - echo "LOG_DIR=./logs-$version" >> $GITHUB_ENV - - - name: Download Worker Image - uses: actions/download-artifact@v3 - with: - name: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - path: . - - - name: Download CLI client Image - uses: actions/download-artifact@v3 - with: - name: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - path: . - - - name: Load Worker & Client Images - env: - DOCKER_BUILDKIT: 1 - run: | - docker image load --input integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - docker image load --input integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - docker images --all - - ## - # Before tagging, delete the old "stuck" ones to be sure that the newly created ones are the latest - # Without if the docker image rmi throws an error if the image doesn't exist. - ## - - name: Re-name Image Tags - run: | - if [[ "$(docker images -q ${{ env.WORKER_IMAGE_TAG }} 2> /dev/null)" == "" ]]; then - docker image rmi --force ${{ env.WORKER_IMAGE_TAG }} 2>/dev/null - fi - if [[ "$(docker images -q ${{ env.CLIENT_IMAGE_TAG }} 2> /dev/null)" == "" ]]; then - docker image rmi --force ${{ env.CLIENT_IMAGE_TAG }} 2>/dev/null - fi - docker tag integritee-worker-${{ env.IMAGE_SUFFIX }} ${{ env.WORKER_IMAGE_TAG }} - docker tag integritee-cli-client-${{ env.IMAGE_SUFFIX }} ${{ env.CLIENT_IMAGE_TAG }} - docker pull integritee/integritee-node:1.1.3 - docker tag integritee/integritee-node:1.1.3 ${{ env.INTEGRITEE_NODE }} - docker images --all - - ## - # Stop any stucked/running compose projects - ## - - name: Stop docker containers - if: always() - continue-on-error: true - run: | - cd docker - docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} stop - - - name: Integration Test ${{ matrix.test }}-${{ matrix.flavor_id }} - run: | - cd docker - docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} up ${{ matrix.demo_name }} --no-build --exit-code-from ${{ matrix.demo_name }} --remove-orphans - - - - name: Collect Docker Logs - continue-on-error: true - if: always() - uses: jwalton/gh-docker-logs@v2 - with: - images: '${{ env.WORKER_IMAGE_TAG }},${{ env.CLIENT_IMAGE_TAG }},${{ env.INTEGRITEE_NODE }}' - tail: all - dest: ${{ env.LOG_DIR }} - - - name: Upload logs - if: always() - uses: actions/upload-artifact@v3 - with: - name: logs-${{ matrix.test }}-${{ matrix.flavor_id }} - path: ${{ env.LOG_DIR }} - - - name: Stop docker containers - if: always() - continue-on-error: true - run: | - cd docker - docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} stop - - - name: Delete images - run: | - if [[ "$(docker images -q integritee-worker-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee-worker-${{ env.IMAGE_SUFFIX }} 2>/dev/null - fi - if [[ "$(docker images -q integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2>/dev/null - fi - if [[ "$(docker images -q ${{ env.WORKER_IMAGE_TAG }} 2> /dev/null)" != "" ]]; then - docker image rmi --force ${{ env.WORKER_IMAGE_TAG }} 2>/dev/null - fi - if [[ "$(docker images -q ${{ env.CLIENT_IMAGE_TAG }} 2> /dev/null)" != "" ]]; then - docker image rmi --force ${{ env.CLIENT_IMAGE_TAG }} 2>/dev/null - fi - if [[ "$(docker images -q ${{ env.INTEGRITEE_NODE }} 2> /dev/null)" != "" ]]; then - docker image rmi --force ${{ env.INTEGRITEE_NODE }} 2>/dev/null - fi - docker images --all - - release-build: - runs-on: integritee-builder-sgx - name: Release Build of teeracle - if: startsWith(github.ref, 'refs/tags/') - needs: [ build-test, integration-tests ] - - strategy: - fail-fast: false - matrix: - include: - - flavor_id: teeracle - mode: teeracle - sgx_mode: HW - additional_features: dcap - - flavor_id: sidechain - mode: sidechain - sgx_mode: HW - additional_features: dcap - - steps: - - uses: actions/checkout@v3 - - - name: Add masks - run: | - echo "::add-mask::$VAULT_TOKEN" - echo "::add-mask::$PRIVKEY_B64" - echo "::add-mask::$PRIVKEY_PASS" - - - name: Set env - run: | - fingerprint=$RANDOM - echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV - SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") - echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV - if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then - echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV - else - echo "DOCKER_DEVICES=" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=" >> $GITHUB_ENV - fi - echo "VAULT_TOKEN=$VAULT_TOKEN" >> "$GITHUB_ENV" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - buildkitd-flags: --debug - driver: docker-container - - - name: Import secrets - uses: hashicorp/vault-action@v2 - id: import-secrets - with: - url: ${{ secrets.VAULT_URL }} - tlsSkipVerify: false - token: ${{ env.VAULT_TOKEN }} - exportEnv: false - secrets: | - ${{ secrets.VAULT_PATH }} intel_sgx_pem_base64 | PRIVKEY_B64 ; - ${{ secrets.VAULT_PATH }} password | PRIVKEY_PASS - - - name: Get secrets - env: - PRIVKEY_B64: ${{ steps.import-secrets.outputs.PRIVKEY_B64 }} - PRIVKEY_PASS: ${{ steps.import-secrets.outputs.PRIVKEY_PASS }} - run: | - echo $PRIVKEY_B64 | base64 --ignore-garbage --decode > enclave-runtime/intel_sgx.pem - echo $PRIVKEY_PASS > enclave-runtime/passfile.txt - - - name: Build Worker & Run Cargo Test - env: - DOCKER_BUILDKIT: 1 - run: > - docker build -t integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} - --target deployed-worker - --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg SGX_COMMERCIAL_KEY=enclave-runtime/intel_sgx.pem --build-arg SGX_PASSFILE=enclave-runtime/passfile.txt --build-arg SGX_PRODUCTION=1 --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} --build-arg SGX_MODE=${{ matrix.sgx_mode }} - -f build.Dockerfile . - - - name: Save released teeracle - run: | - docker image save integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} | gzip > integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz - docker images --all - - - name: Upload teeracle image - uses: actions/upload-artifact@v3 - with: - name: integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz - path: integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz - - - name: Delete images - run: | - if [[ "$(docker images -q integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} 2>/dev/null - fi - docker images --all - - release: - runs-on: ubuntu-latest - name: Draft Release - if: startsWith(github.ref, 'refs/tags/') - needs: [ build-test, integration-tests, release-build ] - outputs: - release_url: ${{ steps.create-release.outputs.html_url }} - asset_upload_url: ${{ steps.create-release.outputs.upload_url }} - steps: - - uses: actions/checkout@v3 - - - name: Download Worker Image - uses: actions/download-artifact@v3 - with: - name: integritee-worker-teeracle-${{ github.ref_name }}.tar.gz - path: . - - - name: Download Worker Image - uses: actions/download-artifact@v3 - with: - name: integritee-worker-sidechain-${{ github.ref_name }}.tar.gz - path: . - - # - # Temporary comment out until we decide what to release - # - # - name: Download Integritee Client - # uses: actions/download-artifact@v3 - # with: - # name: integritee-client-sidechain-${{ github.sha }} - # path: integritee-client-tmp - - # - name: Download Enclave Signed - # uses: actions/download-artifact@v3 - # with: - # name: enclave-signed-sidechain-${{ github.sha }} - # path: enclave-signed-tmp - - # - name: Move service binaries - # run: mv integritee-worker-tmp/integritee-service ./integritee-demo-validateer - - # - name: Move service client binaries - # run: mv integritee-client-tmp/integritee-cli ./integritee-client - - # - name: Move service client binaries - # run: mv enclave-signed-tmp/enclave.signed.so ./enclave.signed.so - - - name: Changelog - uses: scottbrenner/generate-changelog-action@master - id: Changelog - - - name: Display structure of downloaded files - run: ls -R - working-directory: . - - - name: Release - id: create-release - uses: softprops/action-gh-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - body: | - ${{ steps.Changelog.outputs.changelog }} - draft: true - name: Docker ${{ github.ref_name }} - files: | - integritee-worker-teeracle-${{ github.ref_name }}.tar.gz - integritee-worker-sidechain-${{ github.ref_name }}.tar.gz - integritee-client - integritee-demo-validateer - enclave.signed.so diff --git a/bitacross-worker/.github/workflows/check_labels.yml b/bitacross-worker/.github/workflows/check_labels.yml deleted file mode 100644 index 9511ed0b93..0000000000 --- a/bitacross-worker/.github/workflows/check_labels.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Labels Check -on: - pull_request: - types: [opened, labeled, unlabeled, synchronize, ready_for_review] -jobs: - A-label-check: - uses: ./.github/workflows/label-checker.yml - with: - predefined_labels: "A0-core,A1-cli,A2-applibs,A3-sidechain,A4-offchain,A5-teeracle,A6-evm,A7-somethingelse" - - B-label-check: - uses: ./.github/workflows/label-checker.yml - with: - predefined_labels: "B0-silent,B1-releasenotes" - - C-label-check: - uses: ./.github/workflows/label-checker.yml - with: - predefined_labels: "C1-low 📌,C3-medium 📣,C7-high ❗️,C9-critical ‼️" - - E-label-check: - uses: ./.github/workflows/label-checker.yml - with: - predefined_labels: "E0-breaksnothing,E3-hardmerge,E5-publicapi,E6-parentchain,E8-breakseverything" diff --git a/bitacross-worker/.github/workflows/delete-release.yml b/bitacross-worker/.github/workflows/delete-release.yml deleted file mode 100644 index 53fbdbb0f3..0000000000 --- a/bitacross-worker/.github/workflows/delete-release.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Delete-Release - -on: - release: - types: [deleted] # should be deleted - -jobs: - purge-image: - name: Delete image from ghcr.io - runs-on: ubuntu-latest - strategy: - matrix: - #binary: ["integritee-client", "integritee-demo-validateer"] - binary: ["teeracle"] - steps: - - uses: actions/checkout@v2 - - - name: Set output - id: vars - run: echo "{tag}={$GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT - - - name: Get Tag - id: get_tag - run: echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//} - - - name: Check output - env: - RELEASE_VERSION: ${{ steps.get_tag.outputs.TAG }} - run: | - echo $RELEASE_VERSION - echo ${{ steps.vars.outputs.tag }} - echo ${{github.event.pull_request.number}} - - - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - # Unfortunately accessing the repo with personal access token is not possible - # Workaround: disable 2FA and user password instead of TOKEN - - name: Delete docker tag - run: | - ORGANIZATION="integritee" - IMAGE="${{ matrix.binary }}" - TAG="${{ steps.get_tag.outputs.TAG }}" - - login_data() { - cat < /dev/null)" != "" ]]; then - docker image rmi --force integritee/sidechain:${{ github.event.release.tag_name }} 2>/dev/null - fi - docker images --all diff --git a/bitacross-worker/.github/workflows/publish-docker-teeracle.yml b/bitacross-worker/.github/workflows/publish-docker-teeracle.yml deleted file mode 100644 index 01a9a6f8b0..0000000000 --- a/bitacross-worker/.github/workflows/publish-docker-teeracle.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Publish Docker image for new teeracle release - -on: - release: - types: - - published - -jobs: - main: - name: Push Integritee Teeracle to Dockerhub - runs-on: [ self-hosted ] - steps: - - uses: actions/checkout@v3 - - - name: Download teeracle from release - uses: dsaltares/fetch-gh-release-asset@master - with: - version: "tags/${{ github.event.release.tag_name }}" - file: integritee-worker-teeracle-${{ github.event.release.tag_name }}.tar.gz - target: "integritee-worker-teeracle.tar.gz" - token: ${{ secrets.GITHUB_TOKEN }} - - - - name: Login to Dockerhub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - - name: Load Worker & Push - env: - DOCKER_BUILDKIT: 1 - run: | - docker image load --input integritee-worker-teeracle.tar.gz - docker images --all - docker push integritee/teeracle:${{ github.event.release.tag_name }} - - - name: Delete images - run: | - if [[ "$(docker images -q integritee/teeracle:${{ github.event.release.tag_name }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee/teeracle:${{ github.event.release.tag_name }} 2>/dev/null - fi - docker images --all diff --git a/bitacross-worker/.github/workflows/publish-draft-release.yml b/bitacross-worker/.github/workflows/publish-draft-release.yml deleted file mode 100644 index 0e8c72dd6c..0000000000 --- a/bitacross-worker/.github/workflows/publish-draft-release.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Release - Publish draft - -on: - push: - tags: - # Catches only v1.2.3 (-dev,-rc1 etc won't be released as SDK) - - v[0-9]+.[0-9]+.[0-9]+ - -jobs: - publish-draft-release: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v3 - with: - fetch-depth: 0 - path: worker - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 3.0.0 - - - name: Download srtool json output - uses: actions/download-artifact@v3 - - - name: Prepare tooling - run: | - cd worker/scripts/changelog - gem install bundler changelogerator:0.9.1 - bundle install - changelogerator --help - URL=https://github.com/chevdor/tera-cli/releases/download/v0.2.1/tera-cli_linux_amd64.deb - wget $URL -O tera.deb - sudo dpkg -i tera.deb - tera --version - - - name: Generate release notes - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DEBUG: 1 - PRE_RELEASE: ${{ github.event.inputs.pre_release }} - run: | - find ${{env.GITHUB_WORKSPACE}} -type f -name "*_srtool_output.json" - - cd worker/scripts/changelog - - ./bin/changelog ${GITHUB_REF} - ls -al release-notes.md - ls -al context.json - - - name: Archive artifact context.json - uses: actions/upload-artifact@v3 - with: - name: release-notes-context - path: | - worker/scripts/changelog/context.json - **/*_srtool_output.json - - - name: Create draft release - id: create-release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: SDK ${{ github.ref }} - body_path: ./worker/scripts/changelog/release-notes.md - draft: true diff --git a/bitacross-worker/Cargo.lock b/bitacross-worker/Cargo.lock index 9e85f8180c..c4ca057004 100644 --- a/bitacross-worker/Cargo.lock +++ b/bitacross-worker/Cargo.lock @@ -32,11 +32,11 @@ dependencies = [ "derive_more", "either", "frame-metadata", - "hex", + "hex 0.4.3", "log 0.4.20", "parity-scale-codec", - "scale-bits 0.4.0", - "scale-decode 0.8.0", + "scale-bits", + "scale-decode", "scale-encode", "scale-info", "serde 1.0.193", @@ -63,7 +63,7 @@ dependencies = [ "serde_json 1.0.103", "sp-application-crypto", "sp-core", - "sp-core-hashing 5.0.0", + "sp-core-hashing", "sp-runtime", "sp-runtime-interface", "sp-staking", @@ -213,7 +213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom 0.2.10", - "once_cell 1.18.0", + "once_cell 1.19.0", "version_check", ] @@ -225,7 +225,7 @@ checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if 1.0.0", "getrandom 0.2.10", - "once_cell 1.18.0", + "once_cell 1.19.0", "version_check", ] @@ -590,6 +590,61 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bc-relayer-registry" +version = "0.1.0" +dependencies = [ + "base64 0.13.1", + "itp-settings", + "itp-sgx-io", + "lazy_static", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sp-std", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "bc-task-receiver" +version = "0.1.0" +dependencies = [ + "bc-relayer-registry", + "bc-task-sender", + "frame-support", + "futures 0.3.8", + "hex 0.4.0", + "ita-stf", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-executor", + "itp-stf-state-handler", + "lc-direct-call", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "thiserror 1.0.44", + "thiserror 1.0.9", + "threadpool 1.8.0", + "threadpool 1.8.1", +] + +[[package]] +name = "bc-task-sender" +version = "0.1.0" +dependencies = [ + "futures 0.3.28", + "futures 0.3.8", + "lazy_static", + "litentry-primitives", + "parity-scale-codec", + "sgx_tstd", +] + [[package]] name = "bech32" version = "0.10.0-beta" @@ -658,23 +713,20 @@ dependencies = [ "chrono 0.4.26", "clap 4.1.0", "env_logger 0.9.3", - "frame-metadata", "hdrhistogram", - "hex", - "ita-sgx-runtime", + "hex 0.4.3", "ita-stf", "itc-rpc-client", "itp-node-api", "itp-rpc", "itp-sgx-crypto", "itp-stf-primitives", - "itp-time-utils", "itp-types", "itp-utils", + "lc-direct-call", "litentry-primitives", "log 0.4.20", "pallet-balances", - "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", "pallet-teerex", "parity-scale-codec", "rand 0.8.5", @@ -682,13 +734,11 @@ dependencies = [ "regex 1.9.5", "reqwest", "rococo-parachain-runtime", - "scale-value", "serde 1.0.193", "serde_json 1.0.103", "sgx_crypto_helper", "sp-application-crypto", "sp-core", - "sp-core-hashing 6.0.0", "sp-keyring", "sp-keystore", "sp-runtime", @@ -711,38 +761,30 @@ dependencies = [ "env_logger 0.9.3", "frame-support", "futures 0.3.28", - "hex", + "hex 0.4.3", "ipfs-api", - "ita-stf", "itc-parentchain", "itc-parentchain-test", "itc-rest-client", "itc-rpc-client", - "itc-rpc-server", "itp-api-client-types", "itp-enclave-api", "itp-enclave-metrics", "itp-node-api", "itp-settings", + "itp-sgx-crypto", "itp-storage", "itp-types", "itp-utils", - "its-consensus-slots", - "its-peer-fetch", - "its-primitives", - "its-rpc-handler", - "its-storage", - "its-test", "jsonrpsee 0.2.0", "lazy_static", + "litentry-macros", "litentry-primitives", "log 0.4.20", "mockall", - "pallet-balances", "parity-scale-codec", "parking_lot 0.12.1", "parse_duration", - "primitive-types", "prometheus", "regex 1.9.5", "rococo-parachain-runtime", @@ -750,7 +792,6 @@ dependencies = [ "serde 1.0.193", "serde_derive 1.0.193", "serde_json 1.0.103", - "sgx-verify", "sgx_crypto_helper", "sgx_types", "sp-consensus-grandpa", @@ -758,7 +799,6 @@ dependencies = [ "sp-keyring", "sp-runtime", "substrate-api-client", - "teerex-primitives", "thiserror 1.0.44", "tokio", "warp", @@ -1083,9 +1123,9 @@ dependencies = [ [[package]] name = "cargo_toml" -version = "0.16.3" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3f9629bc6c4388ea699781dc988c2b99766d7679b151c81990b4fa1208fafd3" +checksum = "3dc9f7a067415ab5058020f04c60ec7b557084dbec0e021217bbabc7a8d38d14" dependencies = [ "serde 1.0.193", "toml 0.8.2", @@ -1276,7 +1316,7 @@ dependencies = [ "clap_derive", "clap_lex", "is-terminal", - "once_cell 1.18.0", + "once_cell 1.19.0", "strsim 0.10.0", "termcolor", ] @@ -1310,7 +1350,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a90d114103adbc625300f346d4d09dfb4ab1c4a8df6868435dd903392ecf4354" dependencies = [ "libc", - "once_cell 1.18.0", + "once_cell 1.19.0", "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -1340,13 +1380,6 @@ dependencies = [ "thiserror 1.0.44", ] -[[package]] -name = "common-primitives" -version = "0.1.0" -dependencies = [ - "sp-std 5.0.0", -] - [[package]] name = "concurrent-queue" version = "2.2.0" @@ -1421,9 +1454,9 @@ version = "0.9.12" dependencies = [ "frame-support", "litentry-hex-utils", - "litentry-macros 0.9.12", + "litentry-macros", "litentry-proc-macros", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm", "parity-scale-codec", "ring 0.16.20", "scale-info", @@ -1431,9 +1464,9 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", - "strum 0.25.0", - "strum_macros 0.25.3", + "sp-std", + "strum 0.26.1", + "strum_macros 0.26.1", ] [[package]] @@ -1749,7 +1782,7 @@ dependencies = [ "sp-application-crypto", "sp-consensus-aura", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -1765,7 +1798,7 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", ] @@ -1792,7 +1825,7 @@ dependencies = [ "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", "sp-trie", "sp-version", "xcm", @@ -1821,7 +1854,7 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", ] @@ -1840,7 +1873,7 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", "xcm-executor", ] @@ -1857,7 +1890,7 @@ dependencies = [ "scale-info", "sp-api", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-trie", "xcm", ] @@ -1879,7 +1912,7 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", "sp-storage", "sp-trie", "tracing", @@ -1894,7 +1927,7 @@ dependencies = [ "futures 0.3.28", "parity-scale-codec", "sp-inherents", - "sp-std 5.0.0", + "sp-std", "sp-timestamp", ] @@ -1910,7 +1943,7 @@ dependencies = [ "polkadot-runtime-common", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", "xcm-builder", "xcm-executor", @@ -1944,7 +1977,7 @@ dependencies = [ "polkadot-primitives", "sp-runtime", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -2007,7 +2040,7 @@ checksum = "5c0c11acd0e63bae27dcd2afced407063312771212b7a823b4fd72d633be30fb" dependencies = [ "cc", "codespan-reporting", - "once_cell 1.18.0", + "once_cell 1.19.0", "proc-macro2", "quote", "scratch", @@ -2389,7 +2422,7 @@ checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ "der 0.7.8", "digest 0.10.7", - "elliptic-curve 0.13.5", + "elliptic-curve 0.13.8", "rfc6979 0.4.0", "signature 2.1.0", "spki 0.7.2", @@ -2426,7 +2459,7 @@ checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ "curve25519-dalek 3.2.0", "hashbrown 0.12.3", - "hex", + "hex 0.4.3", "rand_core 0.6.4", "sha2 0.9.9", "zeroize", @@ -2462,9 +2495,9 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct 0.2.0", "crypto-bigint 0.5.3", @@ -2673,27 +2706,6 @@ dependencies = [ "sha3", ] -[[package]] -name = "evm" -version = "0.39.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49a4e11987c51220aa89dbe1a5cc877f5079fa6864c0a5b4533331db44e9365" -dependencies = [ - "auto_impl", - "environmental 1.1.4", - "ethereum", - "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "evm-gasometer 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.20", - "parity-scale-codec", - "primitive-types", - "rlp", - "scale-info", - "serde 1.0.193", - "sha3", -] - [[package]] name = "evm" version = "0.39.1" @@ -2702,9 +2714,9 @@ dependencies = [ "auto_impl", "environmental 1.1.4", "ethereum", - "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "evm-gasometer 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-core 0.39.0", + "evm-gasometer 0.39.0", + "evm-runtime 0.39.0", "log 0.4.20", "parity-scale-codec", "primitive-types", @@ -2726,18 +2738,6 @@ dependencies = [ "serde 1.0.193", ] -[[package]] -name = "evm-core" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1f13264b044cb66f0602180f0bc781c29accb41ff560669a3ec15858d5b606" -dependencies = [ - "parity-scale-codec", - "primitive-types", - "scale-info", - "serde 1.0.193", -] - [[package]] name = "evm-core" version = "0.39.0" @@ -2761,26 +2761,14 @@ dependencies = [ "primitive-types", ] -[[package]] -name = "evm-gasometer" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d43eadc395bd1a52990787ca1495c26b0248165444912be075c28909a853b8c" -dependencies = [ - "environmental 1.1.4", - "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types", -] - [[package]] name = "evm-gasometer" version = "0.39.0" source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" dependencies = [ "environmental 1.1.4", - "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-core 0.39.0", + "evm-runtime 0.39.0", "primitive-types", ] @@ -2797,19 +2785,6 @@ dependencies = [ "sha3", ] -[[package]] -name = "evm-runtime" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aa5b32f59ec582a5651978004e5c784920291263b7dcb6de418047438e37f4f" -dependencies = [ - "auto_impl", - "environmental 1.1.4", - "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types", - "sha3", -] - [[package]] name = "evm-runtime" version = "0.39.0" @@ -2817,7 +2792,7 @@ source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa dependencies = [ "auto_impl", "environmental 1.1.4", - "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-core 0.39.0", "primitive-types", "sha3", ] @@ -3116,14 +3091,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -[[package]] -name = "fork-tree" -version = "3.0.0" -dependencies = [ - "parity-scale-codec", - "sgx_tstd", -] - [[package]] name = "fork-tree" version = "3.0.0" @@ -3141,30 +3108,12 @@ dependencies = [ "percent-encoding 2.3.0", ] -[[package]] -name = "fp-account" -version = "1.0.0-dev" -source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" -dependencies = [ - "hex", - "impl-serde", - "libsecp256k1", - "log 0.4.20", - "parity-scale-codec", - "scale-info", - "serde 1.0.193", - "sp-core", - "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", - "sp-runtime", - "sp-std 5.0.0", -] - [[package]] name = "fp-account" version = "1.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "hex", + "hex 0.4.3", "impl-serde", "libsecp256k1", "log 0.4.20", @@ -3175,7 +3124,7 @@ dependencies = [ "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", "sp-runtime-interface", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -3187,7 +3136,7 @@ dependencies = [ "parity-scale-codec", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -3197,26 +3146,11 @@ source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#249 dependencies = [ "ethereum", "ethereum-types", - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "frame-support", "num_enum 0.6.1", "parity-scale-codec", - "sp-std 5.0.0", -] - -[[package]] -name = "fp-evm" -version = "3.0.0-dev" -source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" -dependencies = [ - "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", - "frame-support", - "parity-scale-codec", - "scale-info", - "serde 1.0.193", - "sp-core", - "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -3224,14 +3158,14 @@ name = "fp-evm" version = "3.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm 0.39.1", "frame-support", "parity-scale-codec", "scale-info", "serde 1.0.193", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -3241,14 +3175,14 @@ source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#249 dependencies = [ "ethereum", "ethereum-types", - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "parity-scale-codec", "scale-info", "sp-api", "sp-core", "sp-runtime", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -3298,7 +3232,7 @@ dependencies = [ "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", "sp-runtime-interface", - "sp-std 5.0.0", + "sp-std", "sp-storage", "static_assertions", ] @@ -3328,7 +3262,7 @@ dependencies = [ "sp-core", "sp-npos-elections", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -3343,7 +3277,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-tracing", ] @@ -3371,7 +3305,7 @@ dependencies = [ "impl-trait-for-tuples", "k256", "log 0.4.20", - "once_cell 1.18.0", + "once_cell 1.19.0", "parity-scale-codec", "paste", "scale-info", @@ -3386,7 +3320,7 @@ dependencies = [ "sp-runtime", "sp-staking", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", "sp-tracing", "sp-weights", "tt-call", @@ -3443,7 +3377,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-version", "sp-weights", ] @@ -3460,7 +3394,7 @@ dependencies = [ "scale-info", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -3481,7 +3415,7 @@ dependencies = [ "parity-scale-codec", "sp-api", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -4032,6 +3966,14 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +[[package]] +name = "hex" +version = "0.4.0" +source = "git+https://github.com/mesalock-linux/rust-hex-sgx?tag=sgx_1.1.3#ee3266cd29b9f9c2eb69af9487f55c4f09c38f2b" +dependencies = [ + "sgx_tstd", +] + [[package]] name = "hex" version = "0.4.3" @@ -4593,29 +4535,11 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ita-oracle" -version = "0.9.0" -dependencies = [ - "itc-rest-client", - "itp-enclave-metrics", - "itp-ocall-api", - "lazy_static", - "log 0.4.20", - "parity-scale-codec", - "serde 1.0.193", - "sgx_tstd", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", - "thiserror 1.0.44", - "thiserror 1.0.9", - "url 2.1.1", - "url 2.4.0", -] - [[package]] name = "ita-parentchain-interface" version = "0.9.0" dependencies = [ + "bc-relayer-registry", "bs58", "env_logger 0.9.3", "ita-sgx-runtime", @@ -4630,15 +4554,14 @@ dependencies = [ "itp-test", "itp-top-pool-author", "itp-types", - "itp-utils", "lc-scheduled-enclave", + "litentry-hex-utils", "litentry-primitives", "log 0.4.20", "parity-scale-codec", "sgx_tstd", "sp-core", "sp-runtime", - "sp-std 5.0.0", ] [[package]] @@ -4650,7 +4573,6 @@ dependencies = [ "frame-system", "itp-sgx-runtime-primitives", "pallet-balances", - "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", "pallet-parentchain", "pallet-sudo", "pallet-timestamp", @@ -4660,7 +4582,7 @@ dependencies = [ "sp-api", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-version", ] @@ -4670,19 +4592,18 @@ version = "0.9.0" dependencies = [ "frame-support", "frame-system", - "hex", "hex-literal", "ita-sgx-runtime", "itp-hashing", "itp-node-api", "itp-node-api-metadata", - "itp-node-api-metadata-provider", "itp-sgx-externalities", "itp-stf-interface", "itp-stf-primitives", "itp-storage", "itp-types", "itp-utils", + "litentry-macros", "litentry-primitives", "log 0.4.20", "pallet-balances", @@ -4696,7 +4617,7 @@ dependencies = [ "sp-io 7.0.0", "sp-keyring", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -4706,7 +4627,6 @@ dependencies = [ "itp-rpc", "itp-types", "itp-utils", - "litentry-primitives", "log 0.4.20", "parity-scale-codec", "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?tag=sgx_1.1.3)", @@ -4816,7 +4736,6 @@ version = "0.9.0" dependencies = [ "binary-merkle-tree", "bs58", - "core-primitives", "env_logger 0.9.3", "futures 0.3.28", "futures 0.3.8", @@ -4830,7 +4749,6 @@ dependencies = [ "itp-test", "itp-top-pool-author", "itp-types", - "itp-utils", "lc-scheduled-enclave", "litentry-primitives", "log 0.4.20", @@ -4839,7 +4757,6 @@ dependencies = [ "sgx_types", "sp-core", "sp-runtime", - "sp-std 5.0.0", "thiserror 1.0.44", "thiserror 1.0.9", ] @@ -4923,7 +4840,6 @@ dependencies = [ "itp-stf-primitives", "itp-types", "itp-utils", - "litentry-primitives", "log 0.4.20", "openssl", "parity-scale-codec", @@ -4931,34 +4847,11 @@ dependencies = [ "rustls 0.19.1", "serde_json 1.0.103", "sgx_crypto_helper", - "sp-core", - "teerex-primitives", "thiserror 1.0.44", "url 2.4.0", "ws", ] -[[package]] -name = "itc-rpc-server" -version = "0.9.0" -dependencies = [ - "anyhow", - "env_logger 0.10.0", - "itp-enclave-api", - "itp-rpc", - "itp-utils", - "its-peer-fetch", - "its-primitives", - "its-rpc-handler", - "its-storage", - "its-test", - "jsonrpsee 0.2.0", - "log 0.4.20", - "parity-scale-codec", - "sp-core", - "tokio", -] - [[package]] name = "itc-tls-websocket-server" version = "0.9.0" @@ -5022,7 +4915,7 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" name = "itp-api-client-extensions" version = "0.9.0" dependencies = [ - "hex", + "hex 0.4.3", "itp-api-client-types", "itp-types", "sp-consensus-grandpa", @@ -5051,7 +4944,7 @@ dependencies = [ "bit-vec", "chrono 0.4.11", "chrono 0.4.26", - "hex", + "hex 0.4.3", "httparse 1.4.1", "itertools 0.10.5", "itp-ocall-api", @@ -5094,13 +4987,15 @@ name = "itp-enclave-api" version = "0.9.0" dependencies = [ "frame-support", - "hex", + "hex 0.4.3", "itc-parentchain", "itp-enclave-api-ffi", "itp-settings", + "itp-sgx-crypto", "itp-storage", "itp-types", "log 0.4.20", + "pallet-teebag", "parity-scale-codec", "serde_json 1.0.103", "sgx_crypto_helper", @@ -5108,7 +5003,6 @@ dependencies = [ "sgx_urts", "sp-core", "sp-runtime", - "teerex-primitives", "thiserror 1.0.44", ] @@ -5125,7 +5019,6 @@ version = "0.9.0" dependencies = [ "parity-scale-codec", "sgx_tstd", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", ] [[package]] @@ -5232,7 +5125,7 @@ dependencies = [ "sgx_types", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -5268,6 +5161,7 @@ dependencies = [ "derive_more", "itp-sgx-io", "itp-sgx-temp-dir", + "k256", "log 0.4.20", "ofb", "parity-scale-codec", @@ -5308,7 +5202,6 @@ name = "itp-sgx-runtime-primitives" version = "0.9.0" dependencies = [ "frame-system", - "litentry-primitives", "pallet-balances", "sp-core", "sp-runtime", @@ -5327,9 +5220,8 @@ dependencies = [ name = "itp-stf-executor" version = "0.9.0" dependencies = [ - "hex", + "hex 0.4.3", "itc-parentchain-test", - "itp-enclave-metrics", "itp-node-api", "itp-ocall-api", "itp-sgx-crypto", @@ -5343,7 +5235,6 @@ dependencies = [ "itp-top-pool", "itp-top-pool-author", "itp-types", - "litentry-primitives", "log 0.4.20", "parity-scale-codec", "sgx_tstd", @@ -5375,7 +5266,7 @@ dependencies = [ "parity-scale-codec", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -5428,25 +5319,17 @@ dependencies = [ "sp-core", "sp-runtime", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", "sp-trie", "thiserror 1.0.44", "thiserror 1.0.9", ] -[[package]] -name = "itp-teerex-storage" -version = "0.9.0" -dependencies = [ - "itp-storage", - "sp-std 5.0.0", -] - [[package]] name = "itp-test" version = "0.9.0" dependencies = [ - "hex", + "hex 0.4.3", "itp-node-api", "itp-node-api-metadata-provider", "itp-ocall-api", @@ -5456,10 +5339,9 @@ dependencies = [ "itp-stf-primitives", "itp-stf-state-handler", "itp-storage", - "itp-teerex-storage", - "itp-time-utils", "itp-types", "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", + "lc-teebag-storage", "litentry-primitives", "log 0.4.20", "parity-scale-codec", @@ -5469,7 +5351,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -5491,358 +5373,74 @@ dependencies = [ "itp-stf-primitives", "itp-test", "itp-types", - "its-primitives", - "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", - "linked-hash-map 0.5.2", - "linked-hash-map 0.5.6", - "litentry-primitives", - "log 0.4.20", - "parity-scale-codec", - "parity-util-mem", - "serde 1.0.193", - "sgx_tstd", - "sp-application-crypto", - "sp-core", - "sp-runtime", -] - -[[package]] -name = "itp-top-pool-author" -version = "0.9.0" -dependencies = [ - "derive_more", - "futures 0.3.28", - "itp-enclave-metrics", - "itp-ocall-api", - "itp-sgx-crypto", - "itp-stf-primitives", - "itp-stf-state-handler", - "itp-test", - "itp-top-pool", - "itp-types", - "itp-utils", - "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", - "lazy_static", - "litentry-primitives", - "log 0.4.20", - "parity-scale-codec", - "sgx_crypto_helper", - "sgx_tstd", - "sp-core", - "sp-keyring", - "sp-runtime", -] - -[[package]] -name = "itp-types" -version = "0.9.0" -dependencies = [ - "frame-system", - "itp-sgx-crypto", - "itp-sgx-runtime-primitives", - "itp-stf-primitives", - "itp-utils", - "litentry-primitives", - "pallet-balances", - "parity-scale-codec", - "sp-core", - "sp-runtime", - "sp-std 5.0.0", - "substrate-api-client", -] - -[[package]] -name = "itp-utils" -version = "0.9.0" -dependencies = [ - "hex", - "parity-scale-codec", -] - -[[package]] -name = "its-block-composer" -version = "0.9.0" -dependencies = [ - "itp-node-api", - "itp-settings", - "itp-sgx-crypto", - "itp-sgx-externalities", - "itp-stf-executor", - "itp-stf-primitives", - "itp-time-utils", - "itp-top-pool-author", - "itp-types", - "its-primitives", - "its-state", - "log 0.4.20", - "parity-scale-codec", - "sgx_tstd", - "sgx_types", - "sp-core", - "sp-runtime", - "thiserror 1.0.44", - "thiserror 1.0.9", -] - -[[package]] -name = "its-block-verification" -version = "0.9.0" -dependencies = [ - "frame-support", - "itc-parentchain-test", - "itp-types", - "itp-utils", - "its-primitives", - "its-test", - "log 0.4.20", - "sgx_tstd", - "sp-consensus-slots", - "sp-core", - "sp-keyring", - "sp-runtime", - "thiserror 1.0.44", - "thiserror 1.0.9", -] - -[[package]] -name = "its-consensus-aura" -version = "0.9.0" -dependencies = [ - "env_logger 0.9.3", - "finality-grandpa", - "ita-stf", - "itc-parentchain-block-import-dispatcher", - "itc-parentchain-test", - "itc-peer-top-broadcaster", - "itp-enclave-metrics", - "itp-ocall-api", - "itp-settings", - "itp-sgx-crypto", - "itp-sgx-externalities", - "itp-stf-executor", - "itp-stf-primitives", - "itp-stf-state-handler", - "itp-storage", - "itp-test", - "itp-time-utils", - "itp-top-pool-author", - "itp-types", - "itp-utils", - "its-block-composer", - "its-block-verification", - "its-consensus-common", - "its-consensus-slots", - "its-primitives", - "its-state", - "its-test", - "its-validateer-fetch", - "lc-scheduled-enclave", - "log 0.4.20", - "parity-scale-codec", - "sgx_tstd", - "sp-core", - "sp-keyring", - "sp-runtime", -] - -[[package]] -name = "its-consensus-common" -version = "0.9.0" -dependencies = [ - "fork-tree 3.0.0", - "itc-parentchain-light-client", - "itc-parentchain-test", - "itp-enclave-metrics", - "itp-extrinsics-factory", - "itp-import-queue", - "itp-node-api-metadata", - "itp-node-api-metadata-provider", - "itp-ocall-api", - "itp-settings", - "itp-sgx-crypto", - "itp-sgx-externalities", - "itp-test", - "itp-types", - "its-block-verification", - "its-primitives", - "its-state", - "its-test", - "log 0.4.20", - "parity-scale-codec", - "sgx_tstd", - "sgx_types", - "sp-core", - "sp-runtime", - "thiserror 1.0.44", - "thiserror 1.0.9", -] - -[[package]] -name = "its-consensus-slots" -version = "0.9.0" -dependencies = [ - "derive_more", - "futures-timer", - "hex", - "itc-parentchain-test", - "itp-settings", - "itp-sgx-externalities", - "itp-stf-state-handler", - "itp-test", - "itp-time-utils", - "itp-types", - "its-block-verification", - "its-consensus-common", - "its-primitives", - "its-state", - "its-test", - "lazy_static", - "lc-scheduled-enclave", - "log 0.4.20", - "parity-scale-codec", - "sgx_tstd", - "sp-consensus-slots", - "sp-keyring", - "sp-runtime", - "tokio", -] - -[[package]] -name = "its-peer-fetch" -version = "0.9.0" -dependencies = [ - "anyhow", - "async-trait", - "itc-rpc-client", - "itp-node-api", - "itp-test", - "its-primitives", - "its-rpc-handler", - "its-storage", - "its-test", - "jsonrpsee 0.2.0", - "log 0.4.20", - "serde 1.0.193", - "serde_json 1.0.103", - "thiserror 1.0.44", - "tokio", -] - -[[package]] -name = "its-primitives" -version = "0.1.0" -dependencies = [ - "itp-types", - "parity-scale-codec", - "scale-info", - "serde 1.0.193", - "sp-core", - "sp-runtime", - "sp-std 5.0.0", -] - -[[package]] -name = "its-rpc-handler" -version = "0.9.0" -dependencies = [ - "futures 0.3.28", - "futures 0.3.8", - "itp-rpc", - "itp-stf-primitives", - "itp-top-pool-author", - "itp-types", - "itp-utils", - "its-primitives", "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", - "litentry-primitives", - "log 0.4.20", - "parity-scale-codec", - "rust-base58 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-base58 0.0.4 (git+https://github.com/mesalock-linux/rust-base58-sgx?rev=sgx_1.1.3)", - "sgx_tstd", - "sp-core", -] - -[[package]] -name = "its-sidechain" -version = "0.9.0" -dependencies = [ - "its-block-composer", - "its-consensus-aura", - "its-consensus-common", - "its-consensus-slots", - "its-primitives", - "its-rpc-handler", - "its-state", - "its-validateer-fetch", -] - -[[package]] -name = "its-state" -version = "0.9.0" -dependencies = [ - "frame-support", - "itp-sgx-externalities", - "itp-storage", - "its-primitives", + "linked-hash-map 0.5.2", + "linked-hash-map 0.5.6", + "litentry-primitives", "log 0.4.20", "parity-scale-codec", + "parity-util-mem", + "serde 1.0.193", "sgx_tstd", + "sp-application-crypto", "sp-core", - "sp-io 7.0.0", "sp-runtime", - "thiserror 1.0.44", - "thiserror 1.0.9", ] [[package]] -name = "its-storage" +name = "itp-top-pool-author" version = "0.9.0" dependencies = [ - "itp-settings", - "itp-time-utils", + "derive_more", + "futures 0.3.28", + "itp-enclave-metrics", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-test", + "itp-top-pool", "itp-types", - "its-primitives", - "its-test", + "itp-utils", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", + "lazy_static", + "litentry-primitives", "log 0.4.20", - "mockall", "parity-scale-codec", - "parking_lot 0.12.1", - "rocksdb", - "serde 1.0.193", + "sgx_crypto_helper", + "sgx_tstd", "sp-core", - "temp-dir", - "thiserror 1.0.44", + "sp-keyring", + "sp-runtime", ] [[package]] -name = "its-test" +name = "itp-types" version = "0.9.0" dependencies = [ - "itp-types", - "its-primitives", - "sgx_tstd", + "frame-system", + "itp-sgx-crypto", + "itp-sgx-runtime-primitives", + "itp-stf-primitives", + "itp-utils", + "litentry-primitives", + "pallet-balances", + "parity-scale-codec", "sp-core", + "sp-runtime", + "sp-std", + "substrate-api-client", ] [[package]] -name = "its-validateer-fetch" +name = "itp-utils" version = "0.9.0" dependencies = [ - "derive_more", - "frame-support", - "itc-parentchain-test", - "itp-ocall-api", - "itp-teerex-storage", - "itp-test", - "itp-types", + "hex 0.4.3", + "litentry-hex-utils", "parity-scale-codec", - "sp-core", - "sp-runtime", - "sp-std 5.0.0", ] [[package]] @@ -5908,10 +5506,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "316a89048d2ea5530ab5502aa31e1128f6429b524a37e4c0bc54903bcdf3d342" dependencies = [ "jsonrpsee-http-client", - "jsonrpsee-http-server", "jsonrpsee-proc-macros 0.2.0", "jsonrpsee-types 0.2.0", - "jsonrpsee-utils", "jsonrpsee-ws-client", "jsonrpsee-ws-server", ] @@ -5974,28 +5570,6 @@ dependencies = [ "url 2.4.0", ] -[[package]] -name = "jsonrpsee-http-server" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22372378f63f7d16de453e786afc740fca5ee80bd260be024a616b6ac2cefe5" -dependencies = [ - "futures-channel 0.3.28", - "futures-util 0.3.28", - "globset", - "hyper", - "jsonrpsee-types 0.2.0", - "jsonrpsee-utils", - "lazy_static", - "log 0.4.20", - "serde 1.0.193", - "serde_json 1.0.103", - "socket2 0.4.9", - "thiserror 1.0.44", - "tokio", - "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "jsonrpsee-proc-macros" version = "0.2.0" @@ -6142,15 +5716,16 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if 1.0.0", "ecdsa 0.16.8", - "elliptic-curve 0.13.5", - "once_cell 1.18.0", + "elliptic-curve 0.13.8", + "once_cell 1.19.0", "sha2 0.10.7", + "signature 2.1.0", ] [[package]] @@ -6220,6 +5795,24 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lc-direct-call" +version = "0.1.0" +dependencies = [ + "bc-relayer-registry", + "core-primitives", + "hex 0.4.3", + "itp-sgx-crypto", + "itp-stf-primitives", + "k256", + "litentry-primitives", + "parity-scale-codec", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sgx_tstd", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", +] + [[package]] name = "lc-scheduled-enclave" version = "0.8.0" @@ -6231,11 +5824,20 @@ dependencies = [ "log 0.4.20", "parity-scale-codec", "sgx_tstd", - "sp-std 5.0.0", + "sp-std", "thiserror 1.0.44", "thiserror 1.0.9", ] +[[package]] +name = "lc-teebag-storage" +version = "0.1.0" +dependencies = [ + "itp-storage", + "itp-types", + "sp-std", +] + [[package]] name = "libc" version = "0.2.147" @@ -6316,7 +5918,7 @@ dependencies = [ "multiaddr 0.16.0", "multihash 0.16.3", "multistream-select", - "once_cell 1.18.0", + "once_cell 1.19.0", "parking_lot 0.12.1", "pin-project", "prost", @@ -6348,7 +5950,7 @@ dependencies = [ "multiaddr 0.17.1", "multihash 0.17.0", "multistream-select", - "once_cell 1.18.0", + "once_cell 1.19.0", "parking_lot 0.12.1", "pin-project", "quick-protobuf", @@ -6504,7 +6106,7 @@ dependencies = [ "futures 0.3.28", "libp2p-core 0.38.0", "log 0.4.20", - "once_cell 1.18.0", + "once_cell 1.19.0", "prost", "prost-build", "rand 0.8.5", @@ -6664,7 +6266,7 @@ dependencies = [ "bytes 1.4.0", "futures 0.3.28", "futures-timer", - "hex", + "hex 0.4.3", "if-watch", "libp2p-core 0.38.0", "libp2p-noise", @@ -6854,15 +6456,7 @@ checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" name = "litentry-hex-utils" version = "0.9.12" dependencies = [ - "hex", -] - -[[package]] -name = "litentry-macros" -version = "0.1.0" -dependencies = [ - "cargo_toml", - "quote", + "hex 0.4.3", ] [[package]] @@ -6873,15 +6467,14 @@ version = "0.9.12" name = "litentry-primitives" version = "0.1.0" dependencies = [ - "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx?rev=sgx_1.1.3)", "base64 0.13.1", "bitcoin", "core-primitives", - "hex", + "hex 0.4.3", "itp-sgx-crypto", - "itp-utils", + "litentry-hex-utils", "log 0.4.20", - "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "pallet-teebag", "parity-scale-codec", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", @@ -6893,10 +6486,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", - "strum 0.25.0", - "strum_macros 0.25.3", - "teerex-primitives", + "sp-std", ] [[package]] @@ -7295,14 +6885,14 @@ dependencies = [ "evm-gasometer 0.37.0", "evm-runtime 0.37.0", "evm-tracing-events", - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "moonbeam-primitives-ext", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm", "parity-scale-codec", "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -7315,7 +6905,7 @@ dependencies = [ "parity-scale-codec", "sp-externalities", "sp-runtime-interface", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -7326,7 +6916,7 @@ dependencies = [ "environmental 1.1.4", "ethereum", "ethereum-types", - "hex", + "hex 0.4.3", "parity-scale-codec", "serde 1.0.193", "serde_json 1.0.103", @@ -7334,7 +6924,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -7348,7 +6938,7 @@ dependencies = [ "sp-api", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8019,9 +7609,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -8045,7 +7635,7 @@ dependencies = [ "cfg-if 1.0.0", "foreign-types", "libc", - "once_cell 1.18.0", + "once_cell 1.19.0", "openssl-macros", "openssl-sys", ] @@ -8143,7 +7733,7 @@ dependencies = [ "serde 1.0.193", "sp-arithmetic", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8161,7 +7751,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", ] @@ -8176,7 +7766,7 @@ dependencies = [ "serde 1.0.193", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8188,7 +7778,7 @@ dependencies = [ "orml-traits", "parity-scale-codec", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", "xcm-executor", ] @@ -8209,7 +7799,7 @@ dependencies = [ "serde 1.0.193", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", "xcm-executor", ] @@ -8252,6 +7842,21 @@ dependencies = [ "libm 0.1.4", ] +[[package]] +name = "pallet-account-fix" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-asset-manager" version = "0.1.0" @@ -8264,7 +7869,7 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", ] @@ -8280,7 +7885,7 @@ dependencies = [ "scale-info", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8296,7 +7901,7 @@ dependencies = [ "sp-application-crypto", "sp-consensus-aura", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8312,7 +7917,7 @@ dependencies = [ "sp-application-crypto", "sp-authority-discovery", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8326,7 +7931,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8350,7 +7955,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-staking", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8365,7 +7970,22 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std 5.0.0", + "sp-std", +] + +[[package]] +name = "pallet-bitacross" +version = "0.1.0" +dependencies = [ + "core-primitives", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", ] [[package]] @@ -8383,7 +8003,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8400,7 +8020,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8418,7 +8038,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8435,7 +8055,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8453,7 +8073,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8467,7 +8087,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8489,7 +8109,7 @@ dependencies = [ "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-npos-elections", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "strum 0.24.1", ] @@ -8513,44 +8133,20 @@ source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#249 dependencies = [ "ethereum", "ethereum-types", - "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm 0.39.1", "fp-consensus", "fp-ethereum", - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "fp-rpc", "fp-storage", "frame-support", "frame-system", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", - "parity-scale-codec", - "scale-info", - "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", - "sp-runtime", - "sp-std 5.0.0", -] - -[[package]] -name = "pallet-evm" -version = "6.0.0-dev" -source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" -dependencies = [ - "environmental 1.1.4", - "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fp-account 1.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", - "fp-evm 3.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", - "frame-benchmarking", - "frame-support", - "frame-system", - "hex", - "impl-trait-for-tuples", - "log 0.4.20", + "pallet-evm", "parity-scale-codec", - "rlp", "scale-info", - "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8559,13 +8155,13 @@ version = "6.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ "environmental 1.1.4", - "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "fp-account 1.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "evm 0.39.1", + "fp-account", + "fp-evm", "frame-benchmarking", "frame-support", "frame-system", - "hex", + "hex 0.4.3", "hex-literal", "impl-trait-for-tuples", "log 0.4.20", @@ -8575,7 +8171,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8583,7 +8179,7 @@ name = "pallet-evm-precompile-blake2" version = "2.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", ] [[package]] @@ -8591,7 +8187,7 @@ name = "pallet-evm-precompile-bn128" version = "2.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "sp-core", "substrate-bn", ] @@ -8600,21 +8196,21 @@ dependencies = [ name = "pallet-evm-precompile-bridge-transfer" version = "0.9.17" dependencies = [ - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "frame-support", "frame-system", "log 0.4.20", "num_enum 0.7.2", "pallet-bridge", "pallet-bridge-transfer", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm", "parity-scale-codec", "precompile-utils", "rustc-hex", "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8622,9 +8218,9 @@ name = "pallet-evm-precompile-dispatch" version = "2.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "frame-support", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm", ] [[package]] @@ -8633,7 +8229,7 @@ version = "2.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ "ed25519-dalek", - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", ] [[package]] @@ -8641,7 +8237,7 @@ name = "pallet-evm-precompile-modexp" version = "2.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "num 0.4.1", ] @@ -8649,12 +8245,12 @@ dependencies = [ name = "pallet-evm-precompile-parachain-staking" version = "0.9.17" dependencies = [ - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "frame-support", "frame-system", "log 0.4.20", "num_enum 0.7.2", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm", "pallet-parachain-staking", "parity-scale-codec", "precompile-utils", @@ -8662,7 +8258,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8670,7 +8266,7 @@ name = "pallet-evm-precompile-sha3fips" version = "2.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "tiny-keccak", ] @@ -8679,7 +8275,7 @@ name = "pallet-evm-precompile-simple" version = "2.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm", "ripemd", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", ] @@ -8694,7 +8290,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8712,7 +8308,7 @@ dependencies = [ "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", "sp-staking", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8728,7 +8324,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8744,7 +8340,7 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8755,13 +8351,12 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "pallet-teerex", + "pallet-teebag", "parity-scale-codec", "scale-info", "sp-core", "sp-runtime", - "sp-std 5.0.0", - "teerex-primitives", + "sp-std", ] [[package]] @@ -8778,7 +8373,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8794,7 +8389,7 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8814,8 +8409,8 @@ dependencies = [ "serde 1.0.193", "sp-runtime", "sp-staking", - "sp-std 5.0.0", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed)", + "sp-std", + "substrate-fixed", ] [[package]] @@ -8845,7 +8440,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8860,7 +8455,7 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8876,7 +8471,7 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-weights", ] @@ -8897,7 +8492,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-staking", - "sp-std 5.0.0", + "sp-std", "sp-trie", ] @@ -8917,7 +8512,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "teerex-primitives", ] @@ -8940,7 +8535,7 @@ dependencies = [ "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", "sp-staking", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -8963,25 +8558,33 @@ dependencies = [ "scale-info", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] -name = "pallet-teeracle" +name = "pallet-teebag" version = "0.1.0" dependencies = [ + "base64 0.13.1", + "chrono 0.4.26", + "der 0.6.1", "frame-support", "frame-system", + "hex 0.4.3", "log 0.4.20", - "pallet-teerex", + "pallet-balances", + "pallet-timestamp", "parity-scale-codec", + "ring 0.16.20", + "rustls-webpki", "scale-info", + "serde 1.0.193", + "serde_json 1.0.103", "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", - "teeracle-primitives", + "sp-std", + "x509-cert", ] [[package]] @@ -8999,7 +8602,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "teerex-primitives", ] @@ -9017,7 +8620,7 @@ dependencies = [ "sp-inherents", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-timestamp", ] @@ -9037,7 +8640,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -9053,7 +8656,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -9082,7 +8685,7 @@ dependencies = [ "scale-info", "serde 1.0.193", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -9098,7 +8701,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -9109,12 +8712,12 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "pallet-teebag", "parity-scale-codec", "scale-info", "sp-core", "sp-runtime", - "sp-std 5.0.0", - "teerex-primitives", + "sp-std", ] [[package]] @@ -9129,7 +8732,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -9148,7 +8751,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", "xcm-executor", ] @@ -9174,7 +8777,7 @@ dependencies = [ "blake2", "crc32fast", "fs2", - "hex", + "hex 0.4.3", "libc", "log 0.4.20", "lz4", @@ -9446,7 +9049,7 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2674c66ebb4b4d9036012091b537aae5878970d6999f81a265034d85b136b341" dependencies = [ - "once_cell 1.18.0", + "once_cell 1.19.0", "pest", "sha2 0.10.7", ] @@ -9540,7 +9143,7 @@ dependencies = [ "scale-info", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -9589,7 +9192,7 @@ dependencies = [ "derive_more", "fatality", "futures 0.3.28", - "hex", + "hex 0.4.3", "parity-scale-codec", "polkadot-node-jaeger", "polkadot-node-primitives", @@ -9684,7 +9287,7 @@ dependencies = [ "serde 1.0.193", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -9710,7 +9313,7 @@ dependencies = [ "sp-keystore", "sp-runtime", "sp-staking", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -9752,7 +9355,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-staking", - "sp-std 5.0.0", + "sp-std", "static_assertions", "xcm", ] @@ -9765,7 +9368,7 @@ dependencies = [ "bs58", "parity-scale-codec", "polkadot-primitives", - "sp-std 5.0.0", + "sp-std", "sp-tracing", ] @@ -9805,7 +9408,7 @@ dependencies = [ "sp-runtime", "sp-session", "sp-staking", - "sp-std 5.0.0", + "sp-std", "xcm", "xcm-executor", ] @@ -9903,21 +9506,21 @@ name = "precompile-utils" version = "0.9.17" dependencies = [ "assert_matches", - "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "evm 0.39.1", + "fp-evm", "frame-support", "frame-system", "impl-trait-for-tuples", "log 0.4.20", "num_enum 0.7.2", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm", "parity-scale-codec", "precompile-utils-macro", "sha3", "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", ] @@ -10008,7 +9611,7 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ - "once_cell 1.18.0", + "once_cell 1.19.0", "toml_edit 0.19.15", ] @@ -10076,7 +9679,7 @@ checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69" dependencies = [ "bitflags 1.3.2", "byteorder 1.4.3", - "hex", + "hex 0.4.3", "lazy_static", "rustix 0.36.15", ] @@ -10633,7 +10236,7 @@ dependencies = [ "log 0.4.20", "mime", "native-tls", - "once_cell 1.18.0", + "once_cell 1.19.0", "percent-encoding 2.3.0", "pin-project-lite 0.2.10", "serde 1.0.193", @@ -10699,7 +10302,7 @@ dependencies = [ "cc", "libc", "log 0.4.20", - "once_cell 1.18.0", + "once_cell 1.19.0", "rkyv", "spin 0.5.2", "untrusted 0.7.1", @@ -10802,10 +10405,12 @@ dependencies = [ "orml-tokens", "orml-traits", "orml-xtokens", + "pallet-account-fix", "pallet-asset-manager", "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-bitacross", "pallet-bounties", "pallet-bridge", "pallet-bridge-transfer", @@ -10813,7 +10418,7 @@ dependencies = [ "pallet-democracy", "pallet-drop3", "pallet-ethereum", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm", "pallet-evm-precompile-blake2", "pallet-evm-precompile-bn128", "pallet-evm-precompile-bridge-transfer", @@ -10836,7 +10441,7 @@ dependencies = [ "pallet-session", "pallet-sidechain", "pallet-sudo", - "pallet-teeracle", + "pallet-teebag", "pallet-teerex", "pallet-timestamp", "pallet-tips", @@ -10861,7 +10466,7 @@ dependencies = [ "sp-offchain", "sp-runtime", "sp-session", - "sp-std 5.0.0", + "sp-std", "sp-transaction-pool", "sp-version", "substrate-wasm-builder", @@ -10964,6 +10569,7 @@ dependencies = [ "pallet-group", "pallet-membership", "pallet-multisig", + "pallet-teebag", "pallet-teerex", "pallet-transaction-payment", "pallet-treasury", @@ -10979,7 +10585,7 @@ dependencies = [ "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", "teerex-primitives", "xcm", "xcm-builder", @@ -11511,7 +11117,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "log 0.4.20", - "once_cell 1.18.0", + "once_cell 1.19.0", "rustix 0.36.15", "sc-allocator", "sc-executor-common", @@ -11673,7 +11279,7 @@ source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.4 dependencies = [ "array-bytes 4.2.0", "async-trait", - "fork-tree 3.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "fork-tree", "futures 0.3.28", "futures-timer", "libp2p", @@ -11734,7 +11340,7 @@ dependencies = [ "hyper-rustls 0.23.2", "libp2p", "num_cpus", - "once_cell 1.18.0", + "once_cell 1.19.0", "parity-scale-codec", "parking_lot 0.12.1", "rand 0.8.5", @@ -11747,7 +11353,7 @@ dependencies = [ "sp-core", "sp-offchain", "sp-runtime", - "threadpool", + "threadpool 1.8.1", "tracing", ] @@ -11836,7 +11442,7 @@ dependencies = [ "array-bytes 4.2.0", "futures 0.3.28", "futures-util 0.3.28", - "hex", + "hex 0.4.3", "jsonrpsee 0.16.2", "log 0.4.20", "parity-scale-codec", @@ -11963,7 +11569,7 @@ dependencies = [ "serde_json 1.0.103", "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -11996,7 +11602,7 @@ dependencies = [ "lazy_static", "libc", "log 0.4.20", - "once_cell 1.18.0", + "once_cell 1.19.0", "parking_lot 0.12.1", "regex 1.9.5", "rustc-hash", @@ -12083,17 +11689,6 @@ dependencies = [ "sp-arithmetic", ] -[[package]] -name = "scale-bits" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd7aca73785181cc41f0bbe017263e682b585ca660540ba569133901d013ecf" -dependencies = [ - "parity-scale-codec", - "scale-info", - "serde 1.0.193", -] - [[package]] name = "scale-bits" version = "0.4.0" @@ -12105,18 +11700,6 @@ dependencies = [ "serde 1.0.193", ] -[[package]] -name = "scale-decode" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d823d4be477fc33321f93d08fb6c2698273d044f01362dc27573a750deb7c233" -dependencies = [ - "parity-scale-codec", - "scale-bits 0.3.0", - "scale-info", - "thiserror 1.0.44", -] - [[package]] name = "scale-decode" version = "0.8.0" @@ -12125,7 +11708,7 @@ checksum = "ea509715113edab351e1f4d51fba6b186653259049a1155b52e2e994dd2f0e6d" dependencies = [ "parity-scale-codec", "primitive-types", - "scale-bits 0.4.0", + "scale-bits", "scale-decode-derive", "scale-info", "smallvec 1.11.0", @@ -12152,7 +11735,7 @@ checksum = "3f6f51bc8cd927dab2f4567b1a8a8e9d7fd5d0866f2dbc7c84fc97cfa9383a26" dependencies = [ "parity-scale-codec", "primitive-types", - "scale-bits 0.4.0", + "scale-bits", "scale-encode-derive", "scale-info", "smallvec 1.11.0", @@ -12197,23 +11780,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "scale-value" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a5e7810815bd295da73e4216d1dfbced3c7c7c7054d70fa5f6e4c58123fff4" -dependencies = [ - "either", - "frame-metadata", - "parity-scale-codec", - "scale-bits 0.3.0", - "scale-decode 0.4.0", - "scale-info", - "serde 1.0.193", - "thiserror 1.0.44", - "yap", -] - [[package]] name = "schannel" version = "0.1.22" @@ -12555,7 +12121,7 @@ dependencies = [ "chrono 0.4.26", "der 0.6.1", "frame-support", - "hex", + "hex 0.4.3", "parity-scale-codec", "ring 0.16.20", "rustls-webpki", @@ -12563,7 +12129,7 @@ dependencies = [ "serde 1.0.193", "serde_json 1.0.103", "sp-core", - "sp-std 5.0.0", + "sp-std", "teerex-primitives", "x509-cert", ] @@ -12908,7 +12474,7 @@ dependencies = [ "parity-scale-codec", "paste", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13014,7 +12580,7 @@ dependencies = [ "sp-metadata-ir", "sp-runtime", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", "sp-trie", "sp-version", "thiserror 1.0.44", @@ -13044,7 +12610,7 @@ dependencies = [ "serde 1.0.193", "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13057,7 +12623,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde 1.0.193", - "sp-std 5.0.0", + "sp-std", "static_assertions", ] @@ -13071,7 +12637,7 @@ dependencies = [ "sp-api", "sp-application-crypto", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13083,7 +12649,7 @@ dependencies = [ "sp-api", "sp-inherents", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13133,7 +12699,7 @@ dependencies = [ "sp-consensus-slots", "sp-inherents", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-timestamp", ] @@ -13154,7 +12720,7 @@ dependencies = [ "sp-inherents", "sp-keystore", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-timestamp", ] @@ -13173,7 +12739,7 @@ dependencies = [ "sp-core", "sp-keystore", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13184,7 +12750,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde 1.0.193", - "sp-std 5.0.0", + "sp-std", "sp-timestamp", ] @@ -13219,11 +12785,11 @@ dependencies = [ "secp256k1 0.24.3", "secrecy", "serde 1.0.193", - "sp-core-hashing 5.0.0", + "sp-core-hashing", "sp-debug-derive", "sp-externalities", "sp-runtime-interface", - "sp-std 5.0.0", + "sp-std", "sp-storage", "ss58-registry", "substrate-bip39", @@ -13242,22 +12808,7 @@ dependencies = [ "digest 0.10.7", "sha2 0.10.7", "sha3", - "sp-std 5.0.0", - "twox-hash", -] - -[[package]] -name = "sp-core-hashing" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc2d1947252b7a4e403b0a260f596920443742791765ec111daa2bbf98eff25" -dependencies = [ - "blake2", - "byteorder 1.4.3", - "digest 0.10.7", - "sha2 0.10.7", - "sha3", - "sp-std 6.0.0", + "sp-std", "twox-hash", ] @@ -13268,7 +12819,7 @@ source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.4 dependencies = [ "proc-macro2", "quote", - "sp-core-hashing 5.0.0", + "sp-core-hashing", "syn 2.0.32", ] @@ -13298,7 +12849,7 @@ source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.4 dependencies = [ "environmental 1.1.4", "parity-scale-codec", - "sp-std 5.0.0", + "sp-std", "sp-storage", ] @@ -13313,7 +12864,7 @@ dependencies = [ "scale-info", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "thiserror 1.0.44", ] @@ -13348,7 +12899,7 @@ dependencies = [ "sp-keystore", "sp-runtime-interface", "sp-state-machine", - "sp-std 5.0.0", + "sp-std", "sp-tracing", "sp-trie", "tracing", @@ -13397,7 +12948,7 @@ dependencies = [ "frame-metadata", "parity-scale-codec", "scale-info", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13411,7 +12962,7 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13462,7 +13013,7 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", - "sp-std 5.0.0", + "sp-std", "sp-weights", ] @@ -13477,7 +13028,7 @@ dependencies = [ "primitive-types", "sp-externalities", "sp-runtime-interface-proc-macro", - "sp-std 5.0.0", + "sp-std", "sp-storage", "sp-tracing", "sp-wasm-interface", @@ -13507,7 +13058,7 @@ dependencies = [ "sp-core", "sp-runtime", "sp-staking", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13520,7 +13071,7 @@ dependencies = [ "serde 1.0.193", "sp-core", "sp-runtime", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13537,7 +13088,7 @@ dependencies = [ "sp-core", "sp-externalities", "sp-panic-handler", - "sp-std 5.0.0", + "sp-std", "sp-trie", "thiserror 1.0.44", "tracing", @@ -13548,12 +13099,6 @@ name = "sp-std" version = "5.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" -[[package]] -name = "sp-std" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af0ee286f98455272f64ac5bb1384ff21ac029fbb669afbaf48477faff12760e" - [[package]] name = "sp-storage" version = "7.0.0" @@ -13564,7 +13109,7 @@ dependencies = [ "ref-cast", "serde 1.0.193", "sp-debug-derive", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13578,7 +13123,7 @@ dependencies = [ "parity-scale-codec", "sp-inherents", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "thiserror 1.0.44", ] @@ -13588,7 +13133,7 @@ version = "6.0.0" source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", - "sp-std 5.0.0", + "sp-std", "tracing", "tracing-core", "tracing-subscriber", @@ -13615,7 +13160,7 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-trie", ] @@ -13635,7 +13180,7 @@ dependencies = [ "scale-info", "schnellru", "sp-core", - "sp-std 5.0.0", + "sp-std", "thiserror 1.0.44", "tracing", "trie-db", @@ -13654,7 +13199,7 @@ dependencies = [ "serde 1.0.193", "sp-core-hashing-proc-macro", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-version-proc-macro", "thiserror 1.0.44", ] @@ -13679,7 +13224,7 @@ dependencies = [ "impl-trait-for-tuples", "log 0.4.20", "parity-scale-codec", - "sp-std 5.0.0", + "sp-std", "wasmi", "wasmtime", ] @@ -13696,7 +13241,7 @@ dependencies = [ "sp-arithmetic", "sp-core", "sp-debug-derive", - "sp-std 5.0.0", + "sp-std", ] [[package]] @@ -13809,9 +13354,9 @@ dependencies = [ [[package]] name = "strum" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" [[package]] name = "strum_macros" @@ -13828,9 +13373,9 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" dependencies = [ "heck", "proc-macro2", @@ -13870,7 +13415,7 @@ dependencies = [ "derive_more", "frame-metadata", "frame-support", - "hex", + "hex 0.4.3", "log 0.4.20", "maybe-async", "parity-scale-codec", @@ -13925,17 +13470,6 @@ dependencies = [ "sp-keystore", ] -[[package]] -name = "substrate-fixed" -version = "0.5.9" -source = "git+https://github.com/encointer/substrate-fixed?tag=v0.5.9#a4fb461aae6205ffc55bed51254a40c52be04e5d" -dependencies = [ - "parity-scale-codec", - "scale-info", - "serde 1.0.193", - "typenum 1.16.0 (git+https://github.com/encointer/typenum?tag=v1.16.0)", -] - [[package]] name = "substrate-fixed" version = "0.5.9" @@ -14057,14 +13591,6 @@ version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d2faeef5759ab89935255b1a4cd98e0baf99d1085e37d36599c625dac49ae8e" -[[package]] -name = "teeracle-primitives" -version = "0.1.0" -dependencies = [ - "common-primitives", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", -] - [[package]] name = "teerex-primitives" version = "0.1.0" @@ -14072,15 +13598,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-core", - "sp-std 5.0.0", + "sp-std", ] -[[package]] -name = "temp-dir" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af547b166dd1ea4b472165569fc456cfb6818116f854690b0ff205e636523dab" - [[package]] name = "tempfile" version = "3.7.0" @@ -14164,7 +13684,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ "cfg-if 1.0.0", - "once_cell 1.18.0", + "once_cell 1.19.0", +] + +[[package]] +name = "threadpool" +version = "1.8.0" +source = "git+https://github.com/mesalock-linux/rust-threadpool-sgx?tag=sgx_1.1.3#098d98a85b7e2b02e2bb451a3dec0b027017ff4c" +dependencies = [ + "sgx_tstd", ] [[package]] @@ -14186,7 +13714,7 @@ dependencies = [ "integer-encoding", "log 0.4.20", "ordered-float", - "threadpool", + "threadpool 1.8.1", ] [[package]] @@ -14256,7 +13784,7 @@ checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" dependencies = [ "anyhow", "hmac 0.12.1", - "once_cell 1.18.0", + "once_cell 1.19.0", "pbkdf2 0.11.0", "rand 0.8.5", "rustc-hash", @@ -14557,7 +14085,7 @@ version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ - "once_cell 1.18.0", + "once_cell 1.19.0", "valuable", ] @@ -14863,7 +14391,7 @@ checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder 1.4.3", "crunchy", - "hex", + "hex 0.4.3", "static_assertions", ] @@ -15167,7 +14695,7 @@ checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log 0.4.20", - "once_cell 1.18.0", + "once_cell 1.19.0", "proc-macro2", "quote", "syn 2.0.32", @@ -15337,7 +14865,7 @@ dependencies = [ "libc", "log 0.4.20", "object 0.29.0", - "once_cell 1.18.0", + "once_cell 1.19.0", "paste", "psm", "rayon", @@ -15452,7 +14980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eed41cbcbf74ce3ff6f1d07d1b707888166dc408d1a880f651268f4f7c9194b2" dependencies = [ "object 0.29.0", - "once_cell 1.18.0", + "once_cell 1.19.0", "rustix 0.36.15", ] @@ -15588,7 +15116,7 @@ dependencies = [ "arc-swap", "async-trait", "bytes 1.4.0", - "hex", + "hex 0.4.3", "interceptor", "lazy_static", "log 0.4.20", @@ -15796,7 +15324,7 @@ checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" dependencies = [ "either", "libc", - "once_cell 1.18.0", + "once_cell 1.19.0", ] [[package]] @@ -16217,7 +15745,7 @@ dependencies = [ "sp-arithmetic", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "xcm", "xcm-executor", ] @@ -16236,7 +15764,7 @@ dependencies = [ "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", - "sp-std 5.0.0", + "sp-std", "sp-weights", "xcm", ] @@ -16329,12 +15857,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "yap" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc77f52dc9e9b10d55d3f4462c3b7fc393c4f17975d641542833ab2d3bc26ef" - [[package]] name = "yasna" version = "0.3.1" @@ -16368,9 +15890,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] diff --git a/bitacross-worker/Cargo.toml b/bitacross-worker/Cargo.toml index 2ad3682233..0bf7d05941 100644 --- a/bitacross-worker/Cargo.toml +++ b/bitacross-worker/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ - "app-libs/oracle", "app-libs/parentchain-interface", "app-libs/sgx-runtime", "app-libs/stf", @@ -17,7 +16,6 @@ members = [ "core/parentchain/parentchain-crate", "core/rest-client", "core/rpc-client", - "core/rpc-server", "core/tls-websocket-server", "core-primitives/attestation-handler", "core-primitives/import-queue", @@ -51,7 +49,6 @@ members = [ "core-primitives/substrate-sgx/environmental", "core-primitives/substrate-sgx/externalities", "core-primitives/substrate-sgx/sp-io", - "core-primitives/teerex-storage", "core-primitives/test", "core-primitives/time-utils", "core-primitives/top-pool", @@ -59,20 +56,11 @@ members = [ "core-primitives/types", "core-primitives/utils", "service", - "sidechain/block-composer", - "sidechain/block-verification", - "sidechain/consensus/aura", - "sidechain/consensus/common", - "sidechain/consensus/slots", - "sidechain/fork-tree", - "sidechain/peer-fetch", - "sidechain/primitives", - "sidechain/rpc-handler", - "sidechain/sidechain-crate", - "sidechain/state", - "sidechain/validateer-fetch", "litentry/primitives", - "litentry/macros", + "litentry/core/direct-call", + "bitacross/core/bc-task-receiver", + "bitacross/core/bc-task-sender", + "bitacross/core/bc-relayer-registry", ] [patch."https://github.com/apache/teaclave-sgx-sdk.git"] @@ -89,24 +77,3 @@ sgx_urts = { version = "1.1.6", git = "https://github.com/apache/incubator-teacl [patch.crates-io] ring = { git = "https://github.com/betrusted-io/ring-xous", branch = "0.16.20-cleanup" } - -#[patch."https://github.com/integritee-network/integritee-node"] -#my-node-runtime = { package = "integritee-node-runtime", git = "https://github.com/integritee-network//integritee-node", branch = "ab/integrate-pallet-teerex-refactoring" } - -#[patch."https://github.com/scs/substrate-api-client"] -#substrate-api-client = { path = "../../scs/substrate-api-client" } -#substrate-client-keystore = { path = "../../scs/substrate-api-client/client-keystore" } - -#[patch."https://github.com/integritee-network/pallets.git"] -#pallet-claims = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#pallet-enclave-bridge = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#pallet-teerex = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#pallet-sidechain = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#sgx-verify = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#pallet-teeracle = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#test-utils = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#claims-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#enclave-bridge-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#teerex-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#teeracle-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#common-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } diff --git a/bitacross-worker/README.md b/bitacross-worker/README.md index e2be743ff3..90b9f0d9c4 100755 --- a/bitacross-worker/README.md +++ b/bitacross-worker/README.md @@ -1 +1,200 @@ -# bitacross worker \ No newline at end of file +# BitAcross worker + +This repository contains code for BitAcross offchain worker. The main responsibility of the worker is to +store custodian wallets and sign transactions submitted by relayers. + +## Wallets + +Supported wallets: +* ethereum (ecdsa based on secp256k1) +* bitcoin (schnorr based on secp256k1) + +Wallets (private keys) are generated during the initialization (on first startup) and sealed to encrypted file using Intel Protected File System while public keys are published on parachain's bitacross pallet in compressed SEC1-encoded format. + + +## Transaction signing + +Signing requests are processed by a dedicated JSON-RPC `bitacross_submitRequest` method and results in raw signature bytes. Only requests signed by registered relayers are permitted. + +Typescript code related to the RPC integration and can be found in [tee-worker's ts-tests](https://github.com/litentry/litentry-parachain/blob/a6b78ed68396280655271f9cd30e17535d54da81/tee-worker/ts-tests/integration-tests/common/di-utils.ts). + +Rust code used in CLI module can also be used as a reference and can be found [here](https://github.com/litentry/litentry-parachain/blob/a6b78ed68396280655271f9cd30e17535d54da81/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/utils.rs). + + +### Step by step guide for request preparing/sending and response handling. + +1. Prepare `DirectCall`, for example `SignBitcoin` variant which will reflect bitcoin's transaction signing request. Generate 256-bit AES-GCM as request enc/dec key. The first parameter is relayer identity, second generated aes key and third is transaction payload to sign. + +```rust +pub enum DirectCall { + SignBitcoin(Identity, RequestAesKey, Vec), + SignEthereum(Identity, RequestAesKey, Vec), +} +``` + +2. Prepare `DirectCallSigned`. Scale encode created direct call from step 1, append scale encoded mrenclave and shard identifier (use mrenclave) to it, do a Blake2 256-bit hash of it and sign it using relayer's private key, then prepare struct containing direct call and signature. Mrenclave can be obtained from parachain's teebag pallet enclave registry storage. + +```Rust +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct DirectCallSigned { + pub call: DirectCall, + pub signature: LitentryMultiSignature, +} +``` + +3. Prepare `AesRequest`. Fill payload property with aes encrypted scale encoded `DirectCallSigned` prepared in previous step. Get worker's shielding key and use it to encrypt aes key from step 1 and fill `key` property with it. Fill shard identifier (use mrenclave again). Shielding key can be obtained from parachain's teebag pallet enclave registry storage. + +```rust +pub struct AesRequest { + pub shard: ShardIdentifier, + pub key: Vec, + pub payload: AesOutput, +} +``` + +4. Prepare `RpcRequest`. Scale encode `AesRequest` prepared in previous step, turn the bytes into hex representation and put in `params` vec. Generate locally unique `id`. Use following consts for `jsonrpc` and `method`: `"2.0"`, `bitacross_submitRequest` + +```rust +pub struct RpcRequest { + pub jsonrpc: String, + pub method: String, + pub params: Vec, + pub id: Id, +} +``` + +5. Send prepared request to worker's jsonrpc endpoint, in the following example `websocat` is used to send request to locally run bitacross worker. + +```bash +echo '{"jsonrpc":"2.0","method":"bitacross_submitRequest","params":["0x6565c4529cd2af40f89e5d526c6e890019a2fd33cfdc9ee3cd14a0bf1427a61601065c22cde40abe4ad0550a4beba5d05a55380117a57824a57c5949a472fb0639d1ebb1baff0f5453e222418844044ed75352f9a76b4f3fd57f8db4deabf4074eb552784b32c1a881ac27d143148e06a3607455ebafb7dd3ab1669013502bfd7b840d6698363015f55fede5275dfe7d05827315301772e4b75bf745f74b71c443b97b7d22010d54b89fcc1105cbfc72a58dfbd4c10e34ef6019dad859abafdb4f82118f5f339255cb5d2400243bc2e982b4c60341572b6253e0815ed90de74b64145aef8d8304a576ba11c73421b9c86a053619908c475be5d223acc942460afb7e248836f58d2e639d3e32365bbc7ba9fe838b3329db6432fce3427569523f513e7cc82098db4ccaf024a286ad94e6be775ba1f9e918f0867e20a8dbb409232ba297878eff52740e705f59dab2a1c5827d1f8bf7adfa7cdf9e345c16fda757016337f398201af14c820782dac82bc9c5f8df93c917cba29f89e5a1e323dafcf2465e258f1d6dcf9808e5202e6fa3766433981f619c580b831c0d49eed759a0ca1555021c688b72490ffd3f4391c60c04ba904d83aa9497cce62eb6d0e55124692c5124fabfabd70ab366ba81d152f2299ba99021a3705754d64d2b9455229d6ecd730a120a1003abe432a060e40931ad9eb3199cbb09a6b2c84af35735b51628d80210369c0f902905f7e7902d6787673691f2e923b6bc001cfa56f3568e95a95f1f084cd69e658e42c96e317cebc17d54de13f08a0fb007008777e7510d0aa8d124271afe"],"id":1}' | websocat -n1 -k -B 99999999 wss://localhost:2000 +{"jsonrpc":"2.0","result":"0x7d014101d9197274039df1280452819ede02d0867aa57185251d19c9e2c74bd22d1f3b8e1db031b068e3ee7229631a804c1d03e2d9af7055851ac9609dae5e8c7c8dccf4961b31a5cc98bfa356fa262a7376525300a2c03d6f2b59e28578fdcee00000","id":1} +``` + +6. Get result from response `result` field. It's a hex representation of scale encoded `RpcReturnValue`. In case of success, the signature can be obtained from `value` property (it's aes encrypted). + +Types definitions: + +```rust +pub type RequestAesKey = [u8; 32]; + +#[derive( +Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen, EnumIter, Ord, PartialOrd, +)] +pub enum Identity { + // web2 + #[codec(index = 0)] + Twitter(IdentityString), + #[codec(index = 1)] + Discord(IdentityString), + #[codec(index = 2)] + Github(IdentityString), + + // web3 + #[codec(index = 3)] + Substrate(Address32), + #[codec(index = 4)] + Evm(Address20), + // bitcoin addresses are derived (one-way hash) from the pubkey + // by using `Address33` as the Identity handle, it requires that pubkey + // is retrievable by the wallet API when verifying the bitcoin account. + // e.g. unisat-wallet: https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet#getpublickey + #[codec(index = 5)] + Bitcoin(Address33), +} + +pub enum LitentryMultiSignature { + /// An Ed25519 signature. + #[codec(index = 0)] + Ed25519(ed25519::Signature), + /// An Sr25519 signature. + #[codec(index = 1)] + Sr25519(sr25519::Signature), + /// An ECDSA/SECP256k1 signature. + #[codec(index = 2)] + Ecdsa(ecdsa::Signature), + /// An ECDSA/keccak256 signature. An Ethereum signature. hash message with keccak256 + #[codec(index = 3)] + Ethereum(EthereumSignature), + /// Same as above, but the payload bytes are prepended with a readable prefix and `0x` + #[codec(index = 4)] + EthereumPrettified(EthereumSignature), + /// Bitcoin signed message, a hex-encoded string of original &[u8] message, without `0x` prefix + #[codec(index = 5)] + Bitcoin(BitcoinSignature), + /// Same as above, but the payload bytes are prepended with a readable prefix and `0x` + #[codec(index = 6)] + BitcoinPrettified(BitcoinSignature), +} + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct EthereumSignature(pub [u8; 65]); + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct BitcoinSignature(pub [u8; 65]); + +#[derive( +Encode, Decode, Copy, Clone, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen, Ord, PartialOrd, +)] +pub struct Address20([u8; 20]); + +#[derive( +Encode, Decode, Copy, Clone, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen, Ord, PartialOrd, +)] +pub struct Address32([u8; 32]); + +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen, PartialOrd, Ord)] +pub struct Address33([u8; 33]); + +#[derive(Debug, Default, Clone, Eq, PartialEq, Encode, Decode)] +pub struct AesOutput { + pub ciphertext: Vec, + pub aad: Vec, + pub nonce: RequestAesKeyNonce, // IV +} + +#[derive(Encode, Decode, Debug, Eq, PartialEq)] +pub struct RpcReturnValue { + pub value: Vec, + pub do_watch: bool, + pub status: DirectRequestStatus, +} + +#[derive(Debug, Clone, PartialEq, Encode, Decode, Eq)] +pub enum DirectRequestStatus { + /// Direct request was successfully executed + #[codec(index = 0)] + Ok, + /// Trusted Call Status + /// Litentry: embed the top hash here - TODO - use generic type? + #[codec(index = 1)] + TrustedOperationStatus(TrustedOperationStatus, H256), + /// Direct request could not be executed + #[codec(index = 2)] + Error, +} +``` + +### Using CLI + +There are two commands related to transaction signing: + +* request-direct-call-sign-bitcoin +* request-direct-call-sign-ethereum + +They take single argument representing raw payload bytes to sign. + +#### Example usage + +```bash +./bitacross-cli trusted -m 7ppBUcnjGir4szRHCG59p2dTnbtRwKRbLZPpR32ACjbK request-direct-call-sign-bitcoin 00 +``` + +### Obtaining data from parachain's teebag pallet + +Mrencalve, worker's url and public shielding key can be obtained during the runtime from parachain's teebag pallet registry. + +The following gif ilustrates how it can be done manually: + +![demo](./assets/teebag_registry.gif) + +These values can also be obtained programmatically using substrate's `state_getStorage` RPC method. See [this](https://docs.substrate.io/build/remote-procedure-calls/) documentation for more information. \ No newline at end of file diff --git a/bitacross-worker/app-libs/oracle/Cargo.toml b/bitacross-worker/app-libs/oracle/Cargo.toml deleted file mode 100644 index eb8fa135e2..0000000000 --- a/bitacross-worker/app-libs/oracle/Cargo.toml +++ /dev/null @@ -1,48 +0,0 @@ -[package] -name = "ita-oracle" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] - -# std dependencies -thiserror = { version = "1.0.26", optional = true } -url = { version = "2.0.0", optional = true } - -# sgx dependencies -sgx_tstd = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } -thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } -url_sgx = { package = "url", git = "https://github.com/mesalock-linux/rust-url-sgx", tag = "sgx_1.1.3", optional = true } - -# no_std dependencies -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -lazy_static = { version = "1.1.0", features = ["spin_no_std"] } -log = { version = "0.4", default-features = false } -serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } -substrate-fixed = { default-features = false, git = "https://github.com/encointer/substrate-fixed", tag = "v0.5.9" } - -# internal dependencies -itc-rest-client = { path = "../../core/rest-client", default-features = false } -itp-enclave-metrics = { path = "../../core-primitives/enclave-metrics", default-features = false } -itp-ocall-api = { path = "../../core-primitives/ocall-api", default-features = false } - -[features] -default = ["std"] -std = [ - "itc-rest-client/std", - "itp-enclave-metrics/std", - "itp-ocall-api/std", - "log/std", - "serde/std", - "substrate-fixed/std", - "thiserror", - "url", -] -sgx = [ - "itc-rest-client/sgx", - "itp-enclave-metrics/sgx", - "sgx_tstd", - "thiserror_sgx", - "url_sgx", -] diff --git a/bitacross-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem b/bitacross-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem deleted file mode 100644 index a6f3e92af5..0000000000 --- a/bitacross-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/bitacross-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem b/bitacross-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem deleted file mode 100644 index 519028c63b..0000000000 --- a/bitacross-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- diff --git a/bitacross-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem b/bitacross-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem deleted file mode 100644 index 57d4a3766c..0000000000 --- a/bitacross-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- \ No newline at end of file diff --git a/bitacross-worker/app-libs/oracle/src/certificates/open_meteo_root.pem b/bitacross-worker/app-libs/oracle/src/certificates/open_meteo_root.pem deleted file mode 100644 index b85c8037f6..0000000000 --- a/bitacross-worker/app-libs/oracle/src/certificates/open_meteo_root.pem +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- diff --git a/bitacross-worker/app-libs/oracle/src/error.rs b/bitacross-worker/app-libs/oracle/src/error.rs deleted file mode 100644 index df72280f34..0000000000 --- a/bitacross-worker/app-libs/oracle/src/error.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::types::TradingPair; -use std::{boxed::Box, string::String}; - -/// Exchange rate error -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Rest client error")] - RestClient(#[from] itc_rest_client::error::Error), - #[error("Could not retrieve any data from {0} for {1}")] - NoValidData(String, String), - #[error("Value for exchange rate is null")] - EmptyExchangeRate(TradingPair), - #[error("Invalid id for crypto currency")] - InvalidCryptoCurrencyId, - #[error("Invalid id for fiat currency")] - InvalidFiatCurrencyId, - #[error(transparent)] - Other(#[from] Box), -} diff --git a/bitacross-worker/app-libs/oracle/src/lib.rs b/bitacross-worker/app-libs/oracle/src/lib.rs deleted file mode 100644 index 6faee79a63..0000000000 --- a/bitacross-worker/app-libs/oracle/src/lib.rs +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(test, feature(assert_matches))] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -// re-export module to properly feature gate sgx and regular std environment -#[cfg(all(not(feature = "std"), feature = "sgx"))] -pub mod sgx_reexport_prelude { - pub use thiserror_sgx as thiserror; - pub use url_sgx as url; -} - -use crate::{error::Error, metrics_exporter::MetricsExporter}; -use itp_ocall_api::EnclaveMetricsOCallApi; -use std::sync::Arc; - -pub mod error; -pub mod metrics_exporter; -pub mod traits; -pub mod types; - -pub mod oracles; -pub use oracles::{exchange_rate_oracle::ExchangeRateOracle, weather_oracle::WeatherOracle}; - -pub mod oracle_sources; -pub use oracle_sources::{ - coin_gecko::CoinGeckoSource, coin_market_cap::CoinMarketCapSource, - weather_oracle_source::WeatherOracleSource, -}; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod test; - -pub type CoinGeckoExchangeRateOracle = - ExchangeRateOracle>; - -pub type CoinMarketCapExchangeRateOracle = - ExchangeRateOracle>; - -pub type OpenMeteoWeatherOracle = - WeatherOracle>; - -pub fn create_coin_gecko_oracle( - ocall_api: Arc, -) -> CoinGeckoExchangeRateOracle { - ExchangeRateOracle::new(CoinGeckoSource {}, Arc::new(MetricsExporter::new(ocall_api))) -} - -pub fn create_coin_market_cap_oracle( - ocall_api: Arc, -) -> CoinMarketCapExchangeRateOracle { - ExchangeRateOracle::new(CoinMarketCapSource {}, Arc::new(MetricsExporter::new(ocall_api))) -} - -pub fn create_open_meteo_weather_oracle( - ocall_api: Arc, -) -> OpenMeteoWeatherOracle { - WeatherOracle::new(WeatherOracleSource {}, Arc::new(MetricsExporter::new(ocall_api))) -} diff --git a/bitacross-worker/app-libs/oracle/src/metrics_exporter.rs b/bitacross-worker/app-libs/oracle/src/metrics_exporter.rs deleted file mode 100644 index aa10516fd1..0000000000 --- a/bitacross-worker/app-libs/oracle/src/metrics_exporter.rs +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::types::{ExchangeRate, TradingPair}; -use itp_enclave_metrics::{EnclaveMetric, ExchangeRateOracleMetric, OracleMetric}; -use itp_ocall_api::EnclaveMetricsOCallApi; -use log::error; -use std::{string::String, sync::Arc, time::Instant}; - -/// Trait to export metrics for any Teeracle. -pub trait ExportMetrics { - fn increment_number_requests(&self, source: String); - - fn record_response_time(&self, source: String, timer: Instant); - - fn update_exchange_rate( - &self, - source: String, - exchange_rate: ExchangeRate, - trading_pair: TradingPair, - ); - - fn update_weather(&self, source: String, metrics_info: MetricsInfo); -} - -pub trait UpdateMetric { - fn update_metric(&self, metric: OracleMetric); -} - -/// Metrics exporter implementation. -pub struct MetricsExporter { - ocall_api: Arc, -} - -impl UpdateMetric for MetricsExporter -where - OCallApi: EnclaveMetricsOCallApi, -{ - fn update_metric(&self, _metric: OracleMetric) { - // TODO: Implement me - } -} - -impl MetricsExporter -where - OCallApi: EnclaveMetricsOCallApi, -{ - pub fn new(ocall_api: Arc) -> Self { - MetricsExporter { ocall_api } - } - - fn update_metric(&self, metric: ExchangeRateOracleMetric) { - if let Err(e) = self.ocall_api.update_metric(EnclaveMetric::ExchangeRateOracle(metric)) { - error!("Failed to update enclave metric, sgx_status_t: {}", e) - } - } -} - -impl ExportMetrics for MetricsExporter -where - OCallApi: EnclaveMetricsOCallApi, -{ - fn increment_number_requests(&self, source: String) { - self.update_metric(ExchangeRateOracleMetric::NumberRequestsIncrement(source)); - } - - fn record_response_time(&self, source: String, timer: Instant) { - self.update_metric(ExchangeRateOracleMetric::ResponseTime( - source, - timer.elapsed().as_millis(), - )); - } - - fn update_exchange_rate( - &self, - source: String, - exchange_rate: ExchangeRate, - trading_pair: TradingPair, - ) { - self.update_metric(ExchangeRateOracleMetric::ExchangeRate( - source, - trading_pair.key(), - exchange_rate, - )); - } - - fn update_weather(&self, _source: String, _metrics_info: MetricsInfo) { - // TODO: Implement me - } -} diff --git a/bitacross-worker/app-libs/oracle/src/mock.rs b/bitacross-worker/app-libs/oracle/src/mock.rs deleted file mode 100644 index f12224b0ea..0000000000 --- a/bitacross-worker/app-libs/oracle/src/mock.rs +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(feature = "sgx")] -use std::sync::SgxRwLock as RwLock; - -#[cfg(feature = "std")] -use std::sync::RwLock; - -use crate::{ - error::Error, - metrics_exporter::ExportMetrics, - traits::OracleSource, - types::{ExchangeRate, TradingPair}, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, -}; -use std::{ - time::{Duration, Instant}, - vec, - vec::Vec, -}; -use url::Url; - -/// Mock metrics exporter. -#[derive(Default)] -pub(crate) struct MetricsExporterMock { - number_requests: RwLock, - response_times: RwLock>, - exchange_rates: RwLock>, -} - -impl MetricsExporterMock { - pub fn get_number_request(&self) -> u64 { - *self.number_requests.read().unwrap() - } - - pub fn get_response_times(&self) -> Vec { - self.response_times.read().unwrap().clone() - } - - pub fn get_exchange_rates(&self) -> Vec<(TradingPair, ExchangeRate)> { - self.exchange_rates.read().unwrap().clone() - } -} - -impl ExportMetrics for MetricsExporterMock { - fn increment_number_requests(&self, _source: String) { - (*self.number_requests.write().unwrap()) += 1; - } - - fn record_response_time(&self, _source: String, timer: Instant) { - self.response_times.write().unwrap().push(timer.elapsed().as_millis()); - } - - fn update_exchange_rate( - &self, - _source: String, - exchange_rate: ExchangeRate, - trading_pair: TradingPair, - ) { - self.exchange_rates.write().unwrap().push((trading_pair, exchange_rate)); - } - - fn update_weather(&self, _source: String, _metrics_info: MetricsInfo) {} -} - -/// Mock oracle source. -#[derive(Default)] -pub(crate) struct OracleSourceMock; - -impl OracleSource for OracleSourceMock { - type OracleRequestResult = Result; - - fn metrics_id(&self) -> String { - "source_mock".to_string() - } - - fn request_timeout(&self) -> Option { - None - } - - fn base_url(&self) -> Result { - Url::parse("https://mock.base.url").map_err(|e| Error::Other(format!("{:?}", e).into())) - } - - fn root_certificates_content(&self) -> Vec { - vec!["MOCK_CERTIFICATE".to_string()] - } - fn execute_exchange_rate_request( - &self, - _rest_client: &mut RestClient>, - _trading_pair: TradingPair, - ) -> Result { - Ok(ExchangeRate::from_num(42.3f32)) - } - - fn execute_request( - _rest_client: &mut RestClient>, - _source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult { - Ok(42.3f32) - } -} diff --git a/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs b/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs deleted file mode 100644 index d9b8ad91ee..0000000000 --- a/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs +++ /dev/null @@ -1,220 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - error::Error, - traits::OracleSource, - types::{ExchangeRate, TradingInfo, TradingPair}, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, - RestGet, RestPath, -}; -use lazy_static::lazy_static; -use log::{debug, error}; -use serde::{Deserialize, Serialize}; -use std::{ - collections::HashMap, - string::{String, ToString}, - time::Duration, - vec::Vec, -}; -use url::Url; - -const COINGECKO_URL: &str = "https://api.coingecko.com"; -const COINGECKO_PARAM_CURRENCY: &str = "vs_currency"; -const COINGECKO_PARAM_COIN: &str = "ids"; -const COINGECKO_PATH: &str = "api/v3/coins/markets"; -const COINGECKO_TIMEOUT: Duration = Duration::from_secs(20u64); -const COINGECKO_ROOT_CERTIFICATE_BALTIMORE: &str = - include_str!("../certificates/baltimore_cyber_trust_root_v3.pem"); -const COINGECKO_ROOT_CERTIFICATE_LETSENCRYPT: &str = - include_str!("../certificates/lets_encrypt_root_cert.pem"); - -lazy_static! { - static ref SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = HashMap::from([ - ("DOT", "polkadot"), - ("TEER", "integritee"), - ("KSM", "kusama"), - ("BTC", "bitcoin"), - ]); -} - -/// CoinGecko oracle source. -#[derive(Default)] -pub struct CoinGeckoSource; - -impl CoinGeckoSource { - fn map_crypto_currency_id(trading_pair: &TradingPair) -> Result { - let key = &trading_pair.crypto_currency; - match SYMBOL_ID_MAP.get(key.as_str()) { - Some(v) => Ok(v.to_string()), - None => Err(Error::InvalidCryptoCurrencyId), - } - } -} - -impl> OracleSource for CoinGeckoSource { - type OracleRequestResult = Result<(), Error>; - - fn metrics_id(&self) -> String { - "coin_gecko".to_string() - } - - fn request_timeout(&self) -> Option { - Some(COINGECKO_TIMEOUT) - } - - fn base_url(&self) -> Result { - Url::parse(COINGECKO_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) - } - - fn root_certificates_content(&self) -> Vec { - vec![ - COINGECKO_ROOT_CERTIFICATE_LETSENCRYPT.to_string(), - COINGECKO_ROOT_CERTIFICATE_BALTIMORE.to_string(), - ] - } - - fn execute_request( - _rest_client: &mut RestClient>, - source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult { - let _trading_info: TradingInfo = source_info.into(); - // TODO Implement me - Ok(()) - } - - fn execute_exchange_rate_request( - &self, - rest_client: &mut RestClient>, - trading_pair: TradingPair, - ) -> Result { - let fiat_id = trading_pair.fiat_currency.clone(); - let crypto_id = Self::map_crypto_currency_id(&trading_pair)?; - - let response = rest_client.get_with::( - COINGECKO_PATH.to_string(), - &[(COINGECKO_PARAM_CURRENCY, &fiat_id), (COINGECKO_PARAM_COIN, &crypto_id)], - ); - - let response = match response { - Ok(response) => response, - Err(e) => { - error!("coingecko execute_exchange_rate_request() failed with: {:?}", &e); - return Err(Error::RestClient(e)) - }, - }; - - debug!("coingecko received response: {:?}", &response); - let list = response.0; - if list.is_empty() { - return Err(Error::NoValidData(COINGECKO_URL.to_string(), trading_pair.key())) - } - - match list[0].current_price { - Some(r) => Ok(ExchangeRate::from_num(r)), - None => Err(Error::EmptyExchangeRate(trading_pair)), - } - } -} - -#[derive(Serialize, Deserialize, Debug)] -struct CoinGeckoMarketStruct { - id: String, - symbol: String, - name: String, - current_price: Option, - last_updated: Option, -} - -#[derive(Serialize, Deserialize, Debug)] -struct CoinGeckoMarket(pub Vec); - -impl RestPath for CoinGeckoMarket { - fn get_path(path: String) -> Result { - Ok(path) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - mock::MetricsExporterMock, - oracles::exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, - }; - use core::assert_matches::assert_matches; - use std::sync::Arc; - - type TestCoinGeckoClient = ExchangeRateOracle; - - fn get_coin_gecko_crypto_currency_id(crypto_currency: &str) -> Result { - let trading_pair = TradingPair { - crypto_currency: crypto_currency.to_string(), - fiat_currency: "USD".to_string(), - }; - CoinGeckoSource::map_crypto_currency_id(&trading_pair) - } - - #[test] - fn crypto_currency_id_works_for_dot() { - let coin_id = get_coin_gecko_crypto_currency_id("DOT").unwrap(); - assert_eq!(&coin_id, "polkadot"); - } - - #[test] - fn crypto_currency_id_works_for_teer() { - let coin_id = get_coin_gecko_crypto_currency_id("TEER").unwrap(); - assert_eq!(&coin_id, "integritee"); - } - - #[test] - fn crypto_currency_id_works_for_ksm() { - let coin_id = get_coin_gecko_crypto_currency_id("KSM").unwrap(); - assert_eq!(&coin_id, "kusama"); - } - - #[test] - fn crypto_currency_id_works_for_btc() { - let coin_id = get_coin_gecko_crypto_currency_id("BTC").unwrap(); - assert_eq!(&coin_id, "bitcoin"); - } - - #[test] - fn crypto_currency_id_fails_for_undefined_crypto_currency() { - let result = get_coin_gecko_crypto_currency_id("Undefined"); - assert_matches!(result, Err(Error::InvalidCryptoCurrencyId)); - } - - #[test] - fn get_exchange_rate_for_undefined_fiat_currency_fails() { - let coin_gecko_client = create_coin_gecko_client(); - let trading_pair = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CH".to_string() }; - let result = coin_gecko_client.get_exchange_rate(trading_pair); - assert_matches!(result, Err(Error::RestClient(_))); - } - - fn create_coin_gecko_client() -> TestCoinGeckoClient { - TestCoinGeckoClient::new(CoinGeckoSource {}, Arc::new(MetricsExporterMock::default())) - } -} diff --git a/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs b/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs deleted file mode 100644 index a0e053b8e6..0000000000 --- a/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs +++ /dev/null @@ -1,242 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - error::Error, - traits::OracleSource, - types::{ExchangeRate, TradingInfo, TradingPair}, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, - RestGet, RestPath, -}; -use lazy_static::lazy_static; -use serde::{Deserialize, Serialize}; -use std::{ - collections::{BTreeMap, HashMap}, - env, - string::{String, ToString}, - time::Duration, - vec::Vec, -}; -use url::Url; - -const COINMARKETCAP_URL: &str = "https://pro-api.coinmarketcap.com"; -const COINMARKETCAP_KEY_PARAM: &str = "CMC_PRO_API_KEY"; -const FIAT_CURRENCY_PARAM: &str = "convert_id"; -const CRYPTO_CURRENCY_PARAM: &str = "id"; -const COINMARKETCAP_PATH: &str = "v2/cryptocurrency/quotes/latest"; // API endpoint to get the exchange rate with a basic API plan (free) -const COINMARKETCAP_TIMEOUT: Duration = Duration::from_secs(3u64); -const COINMARKETCAP_ROOT_CERTIFICATE: &str = include_str!("../certificates/amazon_root_ca_a.pem"); - -lazy_static! { - static ref CRYPTO_SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = - HashMap::from([("DOT", "6636"), ("TEER", "13323"), ("KSM", "5034"), ("BTC", "1"),]); - static ref COINMARKETCAP_KEY: String = env::var("COINMARKETCAP_KEY").unwrap_or_default(); -} - -lazy_static! { - static ref FIAT_SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = - HashMap::from([("USD", "2781"), ("EUR", "2790"), ("CHF", "2785"), ("JPY", "2797"),]); -} - -#[derive(Default)] -pub struct CoinMarketCapSource; - -impl CoinMarketCapSource { - fn map_crypto_currency_id(trading_pair: &TradingPair) -> Result { - CRYPTO_SYMBOL_ID_MAP - .get(trading_pair.crypto_currency.as_str()) - .map(|v| v.to_string()) - .ok_or(Error::InvalidCryptoCurrencyId) - } - - fn map_fiat_currency_id(trading_pair: &TradingPair) -> Result { - FIAT_SYMBOL_ID_MAP - .get(trading_pair.fiat_currency.as_str()) - .map(|v| v.to_string()) - .ok_or(Error::InvalidFiatCurrencyId) - } -} - -impl> OracleSource for CoinMarketCapSource { - // TODO Change this to return something useful? - type OracleRequestResult = Result<(), Error>; - - fn metrics_id(&self) -> String { - "coin_market_cap".to_string() - } - - fn request_timeout(&self) -> Option { - Some(COINMARKETCAP_TIMEOUT) - } - - fn base_url(&self) -> Result { - Url::parse(COINMARKETCAP_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) - } - - fn root_certificates_content(&self) -> Vec { - vec![COINMARKETCAP_ROOT_CERTIFICATE.to_string()] - } - - fn execute_request( - _rest_client: &mut RestClient>, - source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult { - let trading_info: TradingInfo = source_info.into(); - let _fiat_currency = trading_info.trading_pair.fiat_currency; - let _crypto_currency = trading_info.trading_pair.crypto_currency; - // TODO Implement me - Ok(()) - } - - fn execute_exchange_rate_request( - &self, - rest_client: &mut RestClient>, - trading_pair: TradingPair, - ) -> Result { - let fiat_id = Self::map_fiat_currency_id(&trading_pair)?; - let crypto_id = Self::map_crypto_currency_id(&trading_pair)?; - - let response = rest_client - .get_with::( - COINMARKETCAP_PATH.to_string(), - &[ - (FIAT_CURRENCY_PARAM, &fiat_id), - (CRYPTO_CURRENCY_PARAM, &crypto_id), - (COINMARKETCAP_KEY_PARAM, &COINMARKETCAP_KEY), - ], - ) - .map_err(Error::RestClient)?; - - let data_struct = response.0; - - let data = match data_struct.data.get(&crypto_id) { - Some(d) => d, - None => - return Err(Error::NoValidData( - COINMARKETCAP_URL.to_string(), - trading_pair.crypto_currency, - )), - }; - - let quote = match data.quote.get(&fiat_id) { - Some(q) => q, - None => - return Err(Error::NoValidData(COINMARKETCAP_URL.to_string(), trading_pair.key())), - }; - match quote.price { - Some(r) => Ok(ExchangeRate::from_num(r)), - None => Err(Error::EmptyExchangeRate(trading_pair)), - } - } -} - -#[derive(Serialize, Deserialize, Debug)] -struct DataStruct { - id: Option, - name: String, - symbol: String, - quote: BTreeMap, -} - -#[derive(Serialize, Deserialize, Debug)] -struct QuoteStruct { - price: Option, - last_updated: Option, -} - -#[derive(Serialize, Deserialize, Debug)] -struct CoinMarketCapMarketStruct { - data: BTreeMap, -} - -#[derive(Serialize, Deserialize, Debug)] -struct CoinMarketCapMarket(pub CoinMarketCapMarketStruct); - -impl RestPath for CoinMarketCapMarket { - fn get_path(path: String) -> Result { - Ok(path) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - mock::MetricsExporterMock, - oracles::exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, - }; - use core::assert_matches::assert_matches; - use std::sync::Arc; - - type TestClient = ExchangeRateOracle; - - fn get_coin_market_cap_crypto_currency_id(crypto_currency: &str) -> Result { - let trading_pair = TradingPair { - crypto_currency: crypto_currency.to_string(), - fiat_currency: "USD".to_string(), - }; - CoinMarketCapSource::map_crypto_currency_id(&trading_pair) - } - - #[test] - fn crypto_currency_id_works_for_dot() { - let coin_id = get_coin_market_cap_crypto_currency_id("DOT").unwrap(); - assert_eq!(&coin_id, "6636"); - } - - #[test] - fn crypto_currency_id_works_for_teer() { - let coin_id = get_coin_market_cap_crypto_currency_id("TEER").unwrap(); - assert_eq!(&coin_id, "13323"); - } - - #[test] - fn crypto_currency_id_works_for_ksm() { - let coin_id = get_coin_market_cap_crypto_currency_id("KSM").unwrap(); - assert_eq!(&coin_id, "5034"); - } - - #[test] - fn crypto_currency_id_works_for_btc() { - let coin_id = get_coin_market_cap_crypto_currency_id("BTC").unwrap(); - assert_eq!(&coin_id, "1"); - } - - #[test] - fn crypto_currency_id_fails_for_undefined_crypto_currency() { - let coin_id = get_coin_market_cap_crypto_currency_id("Undefined"); - assert_matches!(coin_id, Err(Error::InvalidCryptoCurrencyId)); - } - - #[test] - fn get_exchange_rate_for_undefined_fiat_currency_fails() { - let coin_market_cap_client = create_client(); - let trading_pair = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CH".to_string() }; - let result = coin_market_cap_client.get_exchange_rate(trading_pair); - assert_matches!(result, Err(Error::InvalidFiatCurrencyId)); - } - - fn create_client() -> TestClient { - TestClient::new(CoinMarketCapSource {}, Arc::new(MetricsExporterMock::default())) - } -} diff --git a/bitacross-worker/app-libs/oracle/src/oracle_sources/mod.rs b/bitacross-worker/app-libs/oracle/src/oracle_sources/mod.rs deleted file mode 100644 index d2d88153c3..0000000000 --- a/bitacross-worker/app-libs/oracle/src/oracle_sources/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -pub mod coin_gecko; -pub mod coin_market_cap; -pub mod weather_oracle_source; diff --git a/bitacross-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs b/bitacross-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs deleted file mode 100644 index 9f199be5dc..0000000000 --- a/bitacross-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - error::Error, - traits::OracleSource, - types::{ExchangeRate, TradingPair, WeatherInfo}, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, - RestGet, RestPath, -}; -use serde::{Deserialize, Serialize}; -use std::{ - string::{String, ToString}, - time::Duration, - vec::Vec, -}; -use url::Url; - -const WEATHER_URL: &str = "https://api.open-meteo.com"; -const WEATHER_PARAM_LONGITUDE: &str = "longitude"; -const WEATHER_PARAM_LATITUDE: &str = "latitude"; -// const WEATHER_PARAM_HOURLY: &str = "hourly"; // TODO: Add to Query -const WEATHER_PATH: &str = "v1/forecast"; -const WEATHER_TIMEOUT: Duration = Duration::from_secs(3u64); -const WEATHER_ROOT_CERTIFICATE: &str = include_str!("../certificates/open_meteo_root.pem"); - -// TODO: Change f32 types to appropriate Substrate Fixed Type -#[derive(Default)] -pub struct WeatherOracleSource; - -impl> OracleSource for WeatherOracleSource { - type OracleRequestResult = Result; // TODO: Change from f32 type - - fn metrics_id(&self) -> String { - "weather".to_string() - } - - fn request_timeout(&self) -> Option { - Some(WEATHER_TIMEOUT) - } - - fn base_url(&self) -> Result { - Url::parse(WEATHER_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) - } - - /// The server's root certificate. A valid certificate is required to open a tls connection - fn root_certificates_content(&self) -> Vec { - vec![WEATHER_ROOT_CERTIFICATE.to_string()] - } - - fn execute_exchange_rate_request( - &self, - _rest_client: &mut RestClient>, - _trading_pair: TradingPair, - ) -> Result { - Err(Error::NoValidData("None".into(), "None".into())) - } - - // TODO: Make this take a variant perhaps or a Closure so that it is more generic - fn execute_request( - rest_client: &mut RestClient>, - source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult { - let weather_info: WeatherInfo = source_info.into(); - let query = weather_info.weather_query; - - // TODO: - // This part is opinionated towards a hard coded query need to make more generic - let response = rest_client - .get_with::( - WEATHER_PATH.into(), - &[ - (WEATHER_PARAM_LATITUDE, &query.latitude), - (WEATHER_PARAM_LONGITUDE, &query.longitude), - //(WEATHER_PARAM_HOURLY), &query.hourly), - ], - ) - .map_err(Error::RestClient)?; - - let open_meteo_weather_struct = response.0; - - Ok(open_meteo_weather_struct.longitude) - } -} - -#[derive(Serialize, Deserialize, Debug)] -struct OpenMeteoWeatherStruct { - latitude: f32, - longitude: f32, - //hourly: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct OpenMeteo(pub OpenMeteoWeatherStruct); - -impl RestPath for OpenMeteo { - fn get_path(path: String) -> Result { - Ok(path) - } -} diff --git a/bitacross-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs b/bitacross-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs deleted file mode 100644 index 0198a5fe1b..0000000000 --- a/bitacross-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs +++ /dev/null @@ -1,154 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - metrics_exporter::ExportMetrics, - traits::OracleSource, - types::{ExchangeRate, TradingInfo, TradingPair}, - Error, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, -}; -use log::*; -use std::{ - sync::Arc, - thread, - time::{Duration, Instant}, -}; -use url::Url; - -#[allow(unused)] -pub struct ExchangeRateOracle { - oracle_source: OracleSourceType, - metrics_exporter: Arc, -} - -impl ExchangeRateOracle { - pub fn new(oracle_source: OracleSourceType, metrics_exporter: Arc) -> Self { - ExchangeRateOracle { oracle_source, metrics_exporter } - } -} - -pub trait GetExchangeRate { - /// Get the cryptocurrency/fiat_currency exchange rate - fn get_exchange_rate(&self, trading_pair: TradingPair) -> Result<(ExchangeRate, Url), Error>; -} - -impl GetExchangeRate - for ExchangeRateOracle -where - OracleSourceType: OracleSource, - MetricsExporter: ExportMetrics, -{ - fn get_exchange_rate(&self, trading_pair: TradingPair) -> Result<(ExchangeRate, Url), Error> { - let source_id = self.oracle_source.metrics_id(); - self.metrics_exporter.increment_number_requests(source_id.clone()); - - let base_url = self.oracle_source.base_url()?; - let root_certificates = self.oracle_source.root_certificates_content(); - let request_timeout = self.oracle_source.request_timeout(); - - debug!("Get exchange rate from URI: {}, trading pair: {:?}", base_url, trading_pair); - - let http_client = HttpClient::new( - SendWithCertificateVerification::new(root_certificates), - true, - request_timeout, - None, - None, - ); - let mut rest_client = RestClient::new(http_client, base_url.clone()); - - // Due to possible failures that may be temporarily this function tries to fetch the exchange rates `number_of_tries` times. - // If it still fails for the last attempt, then only in that case will it be considered a non-recoverable error. - let number_of_tries = 3; - let timer_start = Instant::now(); - - let mut tries = 0; - let result = loop { - tries += 1; - let exchange_result = self - .oracle_source - .execute_exchange_rate_request(&mut rest_client, trading_pair.clone()); - - match exchange_result { - Ok(exchange_rate) => { - self.metrics_exporter.record_response_time(source_id.clone(), timer_start); - self.metrics_exporter.update_exchange_rate( - source_id, - exchange_rate, - trading_pair, - ); - - debug!("Successfully executed exchange rate request"); - break Ok((exchange_rate, base_url)) - }, - Err(e) => - if tries < number_of_tries { - error!( - "Getting exchange rate from {} failed with {}, trying again in {:?}.", - &base_url, e, request_timeout - ); - debug!("Check that the API endpoint is available, for coingecko: https://status.coingecko.com/"); - thread::sleep( - request_timeout.unwrap_or_else(|| Duration::from_secs(number_of_tries)), - ); - } else { - error!( - "Getting exchange rate from {} failed {} times, latest error is: {}.", - &base_url, number_of_tries, &e - ); - break Err(e) - }, - } - }; - result - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::{MetricsExporterMock, OracleSourceMock}; - - type TestOracle = ExchangeRateOracle; - - #[test] - fn get_exchange_rate_updates_metrics() { - let metrics_exporter = Arc::new(MetricsExporterMock::default()); - let test_client = TestOracle::new(OracleSourceMock {}, metrics_exporter.clone()); - - let trading_pair = - TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "USD".to_string() }; - let _bit_usd = test_client.get_exchange_rate(trading_pair.clone()).unwrap(); - - assert_eq!(1, metrics_exporter.get_number_request()); - assert_eq!(1, metrics_exporter.get_response_times().len()); - assert_eq!(1, metrics_exporter.get_exchange_rates().len()); - - let (metric_trading_pair, exchange_rate) = - metrics_exporter.get_exchange_rates().first().unwrap().clone(); - - assert_eq!(trading_pair, metric_trading_pair); - assert_eq!(ExchangeRate::from_num(42.3f32), exchange_rate); - } -} diff --git a/bitacross-worker/app-libs/oracle/src/oracles/mod.rs b/bitacross-worker/app-libs/oracle/src/oracles/mod.rs deleted file mode 100644 index d6100d2469..0000000000 --- a/bitacross-worker/app-libs/oracle/src/oracles/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -pub mod exchange_rate_oracle; -pub mod weather_oracle; diff --git a/bitacross-worker/app-libs/oracle/src/oracles/weather_oracle.rs b/bitacross-worker/app-libs/oracle/src/oracles/weather_oracle.rs deleted file mode 100644 index 66809f7f3a..0000000000 --- a/bitacross-worker/app-libs/oracle/src/oracles/weather_oracle.rs +++ /dev/null @@ -1,83 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{metrics_exporter::ExportMetrics, traits::OracleSource, types::WeatherInfo, Error}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, -}; -use log::*; -use std::sync::Arc; -use url::Url; - -#[allow(unused)] -pub struct WeatherOracle { - oracle_source: OracleSourceType, - metrics_exporter: Arc, -} - -impl WeatherOracle -where - OracleSourceType: OracleSource, -{ - pub fn new(oracle_source: OracleSourceType, metrics_exporter: Arc) -> Self { - WeatherOracle { oracle_source, metrics_exporter } - } - - pub fn get_base_url(&self) -> Result { - self.oracle_source.base_url() - } -} - -pub trait GetLongitude { - type LongitudeResult; - fn get_longitude(&self, weather_info: WeatherInfo) -> Self::LongitudeResult; -} - -impl GetLongitude - for WeatherOracle -where - OracleSourceType: OracleSource>, - MetricsExporter: ExportMetrics, -{ - type LongitudeResult = Result; - - fn get_longitude(&self, weather_info: WeatherInfo) -> Self::LongitudeResult { - let query = weather_info.weather_query.clone(); - - let base_url = self.oracle_source.base_url()?; - let root_certificates = self.oracle_source.root_certificates_content(); - - debug!("Get longitude from URI: {}, query: {:?}", base_url, query); - - let http_client = HttpClient::new( - SendWithCertificateVerification::new(root_certificates), - true, - self.oracle_source.request_timeout(), - None, - None, - ); - let mut rest_client = RestClient::new(http_client, base_url); - >::execute_request( - &mut rest_client, - weather_info, - ) - } -} diff --git a/bitacross-worker/app-libs/oracle/src/test.rs b/bitacross-worker/app-libs/oracle/src/test.rs deleted file mode 100644 index 8d083a18a0..0000000000 --- a/bitacross-worker/app-libs/oracle/src/test.rs +++ /dev/null @@ -1,125 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Integration tests for concrete exchange rate oracle implementations. -//! Uses real HTTP requests, so the sites must be available for these tests. - -use crate::{ - error::Error, - mock::MetricsExporterMock, - oracle_sources::{ - coin_gecko::CoinGeckoSource, coin_market_cap::CoinMarketCapSource, - weather_oracle_source::WeatherOracleSource, - }, - oracles::{ - exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, - weather_oracle::{GetLongitude, WeatherOracle}, - }, - traits::OracleSource, - types::{TradingInfo, TradingPair, WeatherInfo, WeatherQuery}, -}; -use core::assert_matches::assert_matches; -use std::sync::Arc; -use substrate_fixed::transcendental::ZERO; - -type TestOracle = ExchangeRateOracle; -type TestWeatherOracle = WeatherOracle; - -#[test] -#[ignore = "requires API key for CoinMarketCap"] -fn get_exchange_rate_from_coin_market_cap_works() { - test_suite_exchange_rates::(); -} - -#[test] -#[ignore = "requires external coin gecko service, disabled temporarily"] -fn get_exchange_rate_from_coin_gecko_works() { - test_suite_exchange_rates::(); -} - -#[test] -fn get_longitude_from_open_meteo_works() { - let oracle = create_weather_oracle::(); - let weather_query = - WeatherQuery { latitude: "52.52".into(), longitude: "13.41".into(), hourly: "none".into() }; - // Todo: hourly param is temperature_2m to get temp or relativehumidity_2m to get humidity - let weather_info = WeatherInfo { weather_query }; - let expected_longitude = 13.41f32; - let response_longitude = - oracle.get_longitude(weather_info).expect("Can grab longitude from oracle"); - assert!((response_longitude - expected_longitude) < 0.5); -} - -#[test] -fn get_exchange_rate_for_undefined_coin_market_cap_crypto_currency_fails() { - get_exchange_rate_for_undefined_crypto_currency_fails::(); -} - -#[test] -fn get_exchange_rate_for_undefined_coin_gecko_crypto_currency_fails() { - get_exchange_rate_for_undefined_crypto_currency_fails::(); -} - -fn create_weather_oracle>( -) -> TestWeatherOracle { - let oracle_source = OracleSourceType::default(); - WeatherOracle::new(oracle_source, Arc::new(MetricsExporterMock::default())) -} - -fn create_exchange_rate_oracle>( -) -> TestOracle { - let oracle_source = OracleSourceType::default(); - ExchangeRateOracle::new(oracle_source, Arc::new(MetricsExporterMock::default())) -} - -fn get_exchange_rate_for_undefined_crypto_currency_fails< - OracleSourceType: OracleSource, ->() { - let oracle = create_exchange_rate_oracle::(); - let trading_pair = TradingPair { - crypto_currency: "invalid_coin".to_string(), - fiat_currency: "USD".to_string(), - }; - let result = oracle.get_exchange_rate(trading_pair); - assert_matches!(result, Err(Error::InvalidCryptoCurrencyId)); -} - -fn test_suite_exchange_rates>() { - let oracle = create_exchange_rate_oracle::(); - let dot_to_usd = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; - let dot_usd = oracle.get_exchange_rate(dot_to_usd).unwrap().0; - assert!(dot_usd > 0f32); - let btc_to_usd = - TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "USD".to_string() }; - let bit_usd = oracle.get_exchange_rate(btc_to_usd).unwrap().0; - assert!(bit_usd > 0f32); - let dot_to_chf = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CHF".to_string() }; - let dot_chf = oracle.get_exchange_rate(dot_to_chf).unwrap().0; - assert!(dot_chf > 0f32); - let bit_to_chf = - TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "CHF".to_string() }; - let bit_chf = oracle.get_exchange_rate(bit_to_chf).unwrap().0; - - // Ensure that get_exchange_rate returns a positive rate - assert!(dot_usd > ZERO); - - // Ensure that get_exchange_rate returns a valid value by checking - // that the values obtained for DOT/BIT from different exchange rates are the same - assert_eq!((dot_usd / bit_usd).round(), (dot_chf / bit_chf).round()); -} diff --git a/bitacross-worker/app-libs/oracle/src/traits.rs b/bitacross-worker/app-libs/oracle/src/traits.rs deleted file mode 100644 index 1ca1d21428..0000000000 --- a/bitacross-worker/app-libs/oracle/src/traits.rs +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - types::{ExchangeRate, TradingPair}, - Error, -}; -use core::time::Duration; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, -}; -use std::{string::String, vec::Vec}; -use url::Url; - -pub trait OracleSource: Default { - type OracleRequestResult; - - fn metrics_id(&self) -> String; - - fn request_timeout(&self) -> Option; - - fn base_url(&self) -> Result; - - /// The server's root certificate(s). A valid certificate is required to open a tls connection - fn root_certificates_content(&self) -> Vec; - - fn execute_exchange_rate_request( - &self, - rest_client: &mut RestClient>, - trading_pair: TradingPair, - ) -> Result; - - fn execute_request( - rest_client: &mut RestClient>, - source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult; -} diff --git a/bitacross-worker/app-libs/oracle/src/types.rs b/bitacross-worker/app-libs/oracle/src/types.rs deleted file mode 100644 index ef969ccb90..0000000000 --- a/bitacross-worker/app-libs/oracle/src/types.rs +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use codec::{Decode, Encode}; -use std::string::String; -use substrate_fixed::types::U32F32; - -#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct WeatherInfo { - pub weather_query: WeatherQuery, -} - -#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct WeatherQuery { - pub longitude: String, - pub latitude: String, - pub hourly: String, -} - -impl WeatherQuery { - pub fn key(self) -> String { - format!("{}/{}", self.latitude, self.longitude) - } -} - -#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct TradingInfo { - pub trading_pair: TradingPair, - pub exchange_rate: ExchangeRate, -} -/// Market identifier for order -#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct TradingPair { - pub crypto_currency: String, - pub fiat_currency: String, -} - -impl TradingPair { - pub fn key(self) -> String { - format!("{}/{}", self.crypto_currency, self.fiat_currency) - } -} - -/// TODO Fix https://github.com/integritee-network/pallets/issues/71 and get it from https://github.com/integritee-network/pallets.git -/// Teeracle types -pub type ExchangeRate = U32F32; -// pub type Coordinate = U32F32; diff --git a/bitacross-worker/app-libs/parentchain-interface/Cargo.toml b/bitacross-worker/app-libs/parentchain-interface/Cargo.toml index 39e4827588..9e21fe26c8 100644 --- a/bitacross-worker/app-libs/parentchain-interface/Cargo.toml +++ b/bitacross-worker/app-libs/parentchain-interface/Cargo.toml @@ -16,7 +16,6 @@ itp-api-client-types = { path = "../../core-primitives/node-api/api-client-types itp-node-api = { path = "../../core-primitives/node-api", default-features = false } itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } itp-types = { path = "../../core-primitives/types", default-features = false } -itp-utils = { path = "../../core-primitives/utils", default-features = false } # no-std compatible libraries bs58 = { version = "0.4.0", default-features = false, features = ["alloc"] } @@ -28,9 +27,11 @@ sp-core = { default-features = false, features = ["full_crypto"], git = "https:/ sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } # litentry +bc-relayer-registry = { path = "../../bitacross/core/bc-relayer-registry", default-features = false } lc-scheduled-enclave = { path = "../../litentry/core/scheduled-enclave", default-features = false, optional = true } +litentry-hex-utils = { path = "../../../primitives/hex", default-features = false } litentry-primitives = { path = "../../litentry/primitives", default-features = false } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + [dev-dependencies] env_logger = "0.9.0" @@ -57,14 +58,13 @@ std = [ "itp-stf-primitives/std", "itp-top-pool-author/std", "itp-types/std", - "itp-utils/std", "log/std", #substrate "sp-core/std", "sp-runtime/std", "litentry-primitives/std", "lc-scheduled-enclave/std", - "sp-std/std", + "bc-relayer-registry/std", ] sgx = [ "sgx_tstd", @@ -76,4 +76,5 @@ sgx = [ "itp-top-pool-author/sgx", "litentry-primitives/sgx", "lc-scheduled-enclave/sgx", + "bc-relayer-registry/sgx", ] diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/args_executor.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/args_executor.rs index 05084bfee0..3b9c018b7c 100644 --- a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/args_executor.rs +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/args_executor.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/mod.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/mod.rs index 830f452476..763319b821 100644 --- a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/mod.rs +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs index a0d1ff65bc..289e016e02 100644 --- a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify @@ -21,29 +21,35 @@ use itc_parentchain_indirect_calls_executor::{ IndirectDispatch, }; use itp_stf_primitives::traits::IndirectExecutor; -use itp_types::{MrEnclave, SidechainBlockNumber}; +use itp_types::{MrEnclave, SidechainBlockNumber, WorkerType}; use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; -use log::debug; +use log::*; #[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct UpdateScheduledEnclaveArgs { +pub struct SetScheduledEnclaveArgs { + worker_type: WorkerType, sbn: codec::Compact, mrenclave: MrEnclave, } impl> - IndirectDispatch for UpdateScheduledEnclaveArgs + IndirectDispatch for SetScheduledEnclaveArgs { type Args = (); fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { - debug!("execute indirect call: UpdateScheduledEnclave, sidechain_block_number: {:?}, mrenclave: {:?}", self.sbn, self.mrenclave); - GLOBAL_SCHEDULED_ENCLAVE.update(self.sbn.into(), self.mrenclave)?; + debug!("execute indirect call: SetScheduledEnclave, worker_type: {:?}, sidechain_block_number: {:?}, mrenclave: {:?}", self.worker_type, self.sbn, self.mrenclave); + if self.worker_type == WorkerType::BitAcross { + GLOBAL_SCHEDULED_ENCLAVE.update(self.sbn.into(), self.mrenclave)?; + } else { + warn!("Ignore SetScheduledEnclave due to wrong worker_type"); + } Ok(()) } } #[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] pub struct RemoveScheduledEnclaveArgs { + worker_type: WorkerType, sbn: codec::Compact, } @@ -53,10 +59,15 @@ impl> type Args = (); fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { debug!( - "execute indirect call: RemoveScheduledEnclave, sidechain_block_number: {:?}", + "execute indirect call: RemoveScheduledEnclave, worker_type: {:?}, sidechain_block_number: {:?}", + self.worker_type, self.sbn ); - GLOBAL_SCHEDULED_ENCLAVE.remove(self.sbn.into())?; + if self.worker_type == WorkerType::BitAcross { + GLOBAL_SCHEDULED_ENCLAVE.remove(self.sbn.into())?; + } else { + warn!("Ignore RemoveScheduledEnclave due to wrong worker_type"); + } Ok(()) } } diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs index 88fe8aab4d..826c551410 100644 --- a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs @@ -21,6 +21,6 @@ pub mod shield_funds; pub mod transfer_to_alice_shields_funds; pub use invoke::InvokeArgs; -pub use litentry::scheduled_enclave::{RemoveScheduledEnclaveArgs, UpdateScheduledEnclaveArgs}; +pub use litentry::scheduled_enclave::{RemoveScheduledEnclaveArgs, SetScheduledEnclaveArgs}; pub use shield_funds::ShieldFundsArgs; pub use transfer_to_alice_shields_funds::{TransferToAliceShieldsFundsArgs, ALICE_ACCOUNT_ID}; diff --git a/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_handler.rs b/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_handler.rs index 1cc6cd3d0e..c8111afae0 100644 --- a/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_handler.rs +++ b/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_handler.rs @@ -22,7 +22,7 @@ use ita_stf::{Getter, TrustedCall, TrustedCallSigned}; use itc_parentchain_indirect_calls_executor::error::Error; use itp_stf_primitives::{traits::IndirectExecutor, types::TrustedOperation}; use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents, ParentchainError}; -use itp_utils::hex::hex_encode; +use litentry_hex_utils::hex_encode; use log::*; pub struct ParentchainEventHandler {} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/integritee/mod.rs b/bitacross-worker/app-libs/parentchain-interface/src/integritee/mod.rs index f27609698c..fd3614c14b 100644 --- a/bitacross-worker/app-libs/parentchain-interface/src/integritee/mod.rs +++ b/bitacross-worker/app-libs/parentchain-interface/src/integritee/mod.rs @@ -21,11 +21,10 @@ mod extrinsic_parser; use crate::{ decode_and_log_error, - indirect_calls::{ - InvokeArgs, RemoveScheduledEnclaveArgs, ShieldFundsArgs, UpdateScheduledEnclaveArgs, - }, + indirect_calls::{RemoveScheduledEnclaveArgs, SetScheduledEnclaveArgs}, integritee::extrinsic_parser::ParseExtrinsic, }; +use bc_relayer_registry::{RelayerRegistryUpdater, GLOBAL_RELAYER_REGISTRY}; use codec::{Decode, Encode}; use core::marker::PhantomData; pub use event_filter::FilterableEvents; @@ -39,24 +38,20 @@ use itc_parentchain_indirect_calls_executor::{ }; use itp_node_api::metadata::NodeMetadataTrait; use itp_stf_primitives::traits::IndirectExecutor; -use itp_types::CallIndex; +use litentry_primitives::Identity; use log::trace; -use sp_std::vec::Vec; /// The default indirect call (extrinsic-triggered) of the Integritee-Parachain. #[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] pub enum IndirectCall { #[codec(index = 0)] - ShieldFunds(ShieldFundsArgs), + SetScheduledEnclave(SetScheduledEnclaveArgs), #[codec(index = 1)] - Invoke(InvokeArgs), - // Litentry - #[codec(index = 6)] - UpdateScheduledEnclave(UpdateScheduledEnclaveArgs), - #[codec(index = 7)] RemoveScheduledEnclave(RemoveScheduledEnclaveArgs), - #[codec(index = 8)] - BatchAll(Vec), + #[codec(index = 2)] + AddRelayer(AddRelayerArgs), + #[codec(index = 3)] + RemoveRelayer(RemoveRelayerArgs), } impl> @@ -66,33 +61,56 @@ impl> fn dispatch(&self, executor: &Executor, _args: Self::Args) -> Result<()> { trace!("dispatching indirect call {:?}", self); match self { - IndirectCall::ShieldFunds(shieldfunds_args) => shieldfunds_args.dispatch(executor, ()), - IndirectCall::Invoke(invoke_args) => invoke_args.dispatch(executor, ()), - // Litentry - IndirectCall::UpdateScheduledEnclave(update_enclave_args) => - update_enclave_args.dispatch(executor, ()), - IndirectCall::RemoveScheduledEnclave(remove_enclave_args) => - remove_enclave_args.dispatch(executor, ()), - IndirectCall::BatchAll(calls) => { - for x in calls.clone() { - if let Err(e) = x.dispatch(executor, ()) { - log::warn!("Failed to execute indirect call in batch all due to: {:?}", e); - continue - } - } - Ok(()) - }, + IndirectCall::SetScheduledEnclave(set_scheduled_enclave_args) => + set_scheduled_enclave_args.dispatch(executor, ()), + IndirectCall::RemoveScheduledEnclave(remove_scheduled_enclave_args) => + remove_scheduled_enclave_args.dispatch(executor, ()), + IndirectCall::AddRelayer(add_relayer_args) => add_relayer_args.dispatch(executor, ()), + IndirectCall::RemoveRelayer(remove_relayer_args) => + remove_relayer_args.dispatch(executor, ()), } } } +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct AddRelayerArgs { + account_id: Identity, +} + +impl> + IndirectDispatch for AddRelayerArgs +{ + type Args = (); + fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { + log::info!("Adding Relayer Account to Registry: {:?}", self.account_id); + GLOBAL_RELAYER_REGISTRY.update(self.account_id.clone()).unwrap(); + Ok(()) + } +} + +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct RemoveRelayerArgs { + account_id: Identity, +} + +impl> + IndirectDispatch for RemoveRelayerArgs +{ + type Args = (); + fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { + log::info!("Remove Relayer Account from Registry: {:?}", self.account_id); + GLOBAL_RELAYER_REGISTRY.remove(self.account_id.clone()).unwrap(); + Ok(()) + } +} + /// Default filter we use for the Integritee-Parachain. -pub struct ShieldFundsAndInvokeFilter { +pub struct BitAcrossIndirectCallsFilter { _phantom: PhantomData, } impl FilterIntoDataFrom - for ShieldFundsAndInvokeFilter + for BitAcrossIndirectCallsFilter where ExtrinsicParser: ParseExtrinsic, { @@ -111,7 +129,7 @@ where Ok(xt) => xt, Err(e) => { log::error!( - "[ShieldFundsAndInvokeFilter] Could not parse parentchain extrinsic: {:?}", + "[BitAcrossIndirectCallsFilter] Could not parse parentchain extrinsic: {:?}", e ); return None @@ -119,55 +137,23 @@ where }; let index = xt.call_index; let call_args = &mut &xt.call_args[..]; - log::trace!( - "[ShieldFundsAndInvokeFilter] attempting to execute indirect call with index {:?}", - index - ); - if index == metadata.shield_funds_call_indexes().ok()? { - log::debug!("executing shield funds call"); - let args = decode_and_log_error::(call_args)?; - Some(IndirectCall::ShieldFunds(args)) - } else if index == metadata.invoke_call_indexes().ok()? { - log::debug!("executing invoke call"); - let args = decode_and_log_error::(call_args)?; - Some(IndirectCall::Invoke(args)) - // Litentry - } else if index == metadata.update_scheduled_enclave().ok()? { - let args = decode_and_log_error::(call_args)?; - Some(IndirectCall::UpdateScheduledEnclave(args)) - } else if index == metadata.remove_scheduled_enclave().ok()? { + + if index == metadata.set_scheduled_enclave_call_indexes().ok()? { + let args = decode_and_log_error::(call_args)?; + Some(IndirectCall::SetScheduledEnclave(args)) + } else if index == metadata.remove_scheduled_enclave_call_indexes().ok()? { let args = decode_and_log_error::(call_args)?; Some(IndirectCall::RemoveScheduledEnclave(args)) - } else if index == metadata.batch_all_call_indexes().ok()? { - parse_batch_all(call_args, metadata) + } else if index == metadata.add_relayer_call_indexes().ok()? { + log::error!("Received Add Relayer indirect call"); + let args = decode_and_log_error::(call_args)?; + Some(IndirectCall::AddRelayer(args)) + } else if index == metadata.remove_relayer_call_indexes().ok()? { + log::error!("Processing Remove Relayer Call"); + let args = decode_and_log_error::(call_args)?; + Some(IndirectCall::RemoveRelayer(args)) } else { None } } } - -fn parse_batch_all( - call_args: &mut &[u8], - metadata: &NodeMetadata, -) -> Option { - let call_count: sp_std::vec::Vec<()> = Decode::decode(call_args).ok()?; - let mut calls: Vec = Vec::new(); - log::debug!("Received BatchAll including {} calls", call_count.len()); - for _i in 0..call_count.len() { - let index: CallIndex = Decode::decode(call_args).ok()?; - if index == metadata.shield_funds_call_indexes().ok()? { - let args = decode_and_log_error::(call_args)?; - calls.push(IndirectCall::ShieldFunds(args)) - } else if index == metadata.invoke_call_indexes().ok()? { - let args = decode_and_log_error::(call_args)?; - calls.push(IndirectCall::Invoke(args)) - } else if index == metadata.update_scheduled_enclave().ok()? { - let args = decode_and_log_error::(call_args)?; - calls.push(IndirectCall::UpdateScheduledEnclave(args)) - } else if index == metadata.remove_scheduled_enclave().ok()? { - let args = decode_and_log_error::(call_args)?; - calls.push(IndirectCall::RemoveScheduledEnclave(args)) - } - } - Some(IndirectCall::BatchAll(calls)) -} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_handler.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_handler.rs index 7ea752aa55..cb02df3e2a 100644 --- a/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_handler.rs +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_handler.rs @@ -22,7 +22,7 @@ use ita_stf::{Getter, TrustedCall, TrustedCallSigned}; use itc_parentchain_indirect_calls_executor::error::Error; use itp_stf_primitives::{traits::IndirectExecutor, types::TrustedOperation}; use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents, ParentchainError}; -use itp_utils::hex::hex_encode; +use litentry_hex_utils::hex_encode; use log::*; pub struct ParentchainEventHandler {} diff --git a/bitacross-worker/app-libs/sgx-runtime/Cargo.toml b/bitacross-worker/app-libs/sgx-runtime/Cargo.toml index 7b94576e4c..5b7f0b1038 100644 --- a/bitacross-worker/app-libs/sgx-runtime/Cargo.toml +++ b/bitacross-worker/app-libs/sgx-runtime/Cargo.toml @@ -28,21 +28,11 @@ sp-runtime = { default-features = false, git = "https://github.com/paritytech/su sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-version = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -# Integritee dependencies -pallet-evm = { default-features = false, optional = true, git = "https://github.com/integritee-network/frontier.git", branch = "bar/polkadot-v0.9.42" } pallet-parentchain = { path = "../../../pallets/parentchain", default-features = false } [features] default = ["std"] -# Compile the sgx-runtime with evm-pallet support in `no_std`. -evm = ["pallet-evm"] -# Compile the sgx-runtime with evm-pallet support in `std`. -evm_std = [ - "evm", # Activate the `feature = evm` for the compiler flags. - "std", - "pallet-evm/std", -] runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", diff --git a/bitacross-worker/app-libs/sgx-runtime/src/evm.rs b/bitacross-worker/app-libs/sgx-runtime/src/evm.rs deleted file mode 100644 index 990fdd1492..0000000000 --- a/bitacross-worker/app-libs/sgx-runtime/src/evm.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! Adds the `pallet-evm` support for the `sgx-runtime. - -// Import types from the crate root including the ones generated by the `construct_runtime!` macro. -use crate::{Balances, Runtime, RuntimeEvent, Timestamp, NORMAL_DISPATCH_RATIO}; -use frame_support::{ - pallet_prelude::Weight, parameter_types, weights::constants::WEIGHT_REF_TIME_PER_SECOND, -}; -use sp_core::{H160, U256}; -use sp_runtime::traits::BlakeTwo256; - -pub use pallet_evm::{ - AddressMapping, Call as EvmCall, EnsureAddressTruncated, FeeCalculator, GasWeightMapping, - HashedAddressMapping as GenericHashedAddressMapping, SubstrateBlockHashMapping, -}; - -pub type HashedAddressMapping = GenericHashedAddressMapping; - -/// Maximum weight per block -pub const MAXIMUM_BLOCK_WEIGHT: Weight = - Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), u64::MAX); - -// FIXME: For now just a random value. -pub struct FixedGasPrice; -impl FeeCalculator for FixedGasPrice { - fn min_gas_price() -> (U256, Weight) { - (1.into(), Weight::from_parts(1, 0u64)) - } -} - -/// Current approximation of the gas/s consumption considering -/// EVM execution over compiled WASM (on 4.4Ghz CPU). -/// Given the 500ms Weight, from which 75% only are used for transactions, -/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000. -pub const GAS_PER_SECOND: u64 = 40_000_000; - -/// Approximate ratio of the amount of Weight per Gas. -/// u64 works for approximations because Weight is a very small unit compared to gas. -pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND; - -pub struct FixedGasWeightMapping; - -impl GasWeightMapping for FixedGasWeightMapping { - fn gas_to_weight(gas: u64, _without_base_weight: bool) -> Weight { - Weight::from_parts(gas.saturating_mul(WEIGHT_PER_GAS), 0u64) - } - fn weight_to_gas(weight: Weight) -> u64 { - weight.ref_time().wrapping_div(WEIGHT_PER_GAS) - } -} - -/// An ipmlementation of Frontier's AddressMapping trait for Sgx Accounts. -/// This is basically identical to Frontier's own IdentityAddressMapping, but it works for any type -/// that is Into like AccountId20 for example. -pub struct IntoAddressMapping; - -impl> AddressMapping for IntoAddressMapping { - fn into_account_id(address: H160) -> T { - address.into() - } -} - -parameter_types! { - pub const ChainId: u64 = 42; - pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS); - pub const GasLimitPovSizeRatio: u64 = 150_000_000 / (5 * 1024 * 1024); - //pub PrecompilesValue: FrontierPrecompiles = FrontierPrecompiles::<_>::new(); -} - -impl pallet_evm::Config for Runtime { - type FeeCalculator = FixedGasPrice; - type GasWeightMapping = FixedGasWeightMapping; - type BlockHashMapping = SubstrateBlockHashMapping; - type CallOrigin = EnsureAddressTruncated; - type WithdrawOrigin = EnsureAddressTruncated; - type AddressMapping = HashedAddressMapping; - type Currency = Balances; - type RuntimeEvent = RuntimeEvent; - type Runner = pallet_evm::runner::stack::Runner; - type PrecompilesType = (); - type PrecompilesValue = (); - type ChainId = ChainId; - type OnChargeTransaction = (); - type BlockGasLimit = BlockGasLimit; - type FindAuthor = (); // Currently not available. Would need some more thoughts how prioritisation fees could be handled. - // BlockGasLimit / MAX_POV_SIZE - // type GasLimitPovSizeRatio = GasLimitPovSizeRatio; - type WeightPerGas = (); - type OnCreate = (); - type Timestamp = Timestamp; - type WeightInfo = (); -} diff --git a/bitacross-worker/app-libs/sgx-runtime/src/lib.rs b/bitacross-worker/app-libs/sgx-runtime/src/lib.rs index 0a653c3ab1..ba21f75ffb 100644 --- a/bitacross-worker/app-libs/sgx-runtime/src/lib.rs +++ b/bitacross-worker/app-libs/sgx-runtime/src/lib.rs @@ -28,15 +28,6 @@ // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] -#[cfg(feature = "evm")] -mod evm; -#[cfg(feature = "evm")] -pub use evm::{ - AddressMapping, EnsureAddressTruncated, EvmCall, FeeCalculator, FixedGasPrice, - FixedGasWeightMapping, GasWeightMapping, HashedAddressMapping, IntoAddressMapping, - SubstrateBlockHashMapping, GAS_PER_SECOND, MAXIMUM_BLOCK_WEIGHT, WEIGHT_PER_GAS, -}; - use core::convert::{TryFrom, TryInto}; use frame_support::{traits::ConstU32, weights::ConstantMultiplier}; use pallet_transaction_payment::CurrencyAdapter; @@ -53,8 +44,7 @@ use sp_version::RuntimeVersion; pub use itp_sgx_runtime_primitives::{ constants::SLOT_DURATION, types::{ - AccountData, AccountId, Address, Balance, BlockNumber, ConvertAccountId, Hash, Header, - Index, SgxParentchainTypeConverter, Signature, + AccountData, AccountId, Address, Balance, BlockNumber, Hash, Header, Index, Signature, }, }; @@ -131,7 +121,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node-template"), impl_name: create_runtime_str!("node-template"), authoring_version: 1, - spec_version: 102, + spec_version: 104, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -264,28 +254,6 @@ impl pallet_parentchain::Config for Runtime { type WeightInfo = (); } -// The plain sgx-runtime without the `evm-pallet` -#[cfg(not(feature = "evm"))] -construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = opaque::Block, - UncheckedExtrinsic = UncheckedExtrinsic - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, - Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, - Parentchain: pallet_parentchain::{Pallet, Call, Storage}, - } -); - -// Runtime constructed with the evm pallet. -// -// We need add the compiler-flag for the whole macro because it does not support -// compiler flags withing the macro. -#[cfg(feature = "evm")] construct_runtime!( pub enum Runtime where Block = Block, @@ -298,8 +266,6 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, Parentchain: pallet_parentchain::{Pallet, Call, Storage}, - - Evm: pallet_evm::{Pallet, Call, Storage, Config, Event}, } ); diff --git a/bitacross-worker/app-libs/stf/Cargo.toml b/bitacross-worker/app-libs/stf/Cargo.toml index ddec15630a..0f6156a68e 100644 --- a/bitacross-worker/app-libs/stf/Cargo.toml +++ b/bitacross-worker/app-libs/stf/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" [dependencies] # crates.io codec = { version = "3.0.0", default-features = false, features = ["derive"], package = "parity-scale-codec" } -hex = { version = "0.4", default-features = false } hex-literal = { version = "0.4" } log = { version = "0.4", default-features = false } rlp = { version = "0.5", default-features = false } @@ -39,7 +38,7 @@ sp-runtime = { default-features = false, git = "https://github.com/paritytech/su sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } # litentry -itp-node-api-metadata-provider = { path = "../../core-primitives/node-api/metadata-provider", default-features = false } +litentry-macros = { path = "../../../primitives/core/macros", default-features = false } litentry-primitives = { path = "../../litentry/primitives", default-features = false } pallet-parentchain = { path = "../../../pallets/parentchain", default-features = false } @@ -48,8 +47,6 @@ sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "po [features] default = ["std"] -evm = ["ita-sgx-runtime/evm"] -evm_std = ["evm", "ita-sgx-runtime/evm_std"] sgx = [ "sgx_tstd", "itp-sgx-externalities/sgx", @@ -57,7 +54,6 @@ sgx = [ "itp-node-api/sgx", # litentry "litentry-primitives/sgx", - "itp-node-api-metadata-provider/sgx", ] std = [ # crates.io @@ -84,6 +80,8 @@ std = [ "sp-io/std", # litentry "litentry-primitives/std", - "itp-node-api-metadata-provider/std", ] test = [] +production = [ + "litentry-macros/production", +] diff --git a/bitacross-worker/app-libs/stf/src/evm_helpers.rs b/bitacross-worker/app-libs/stf/src/evm_helpers.rs deleted file mode 100644 index f0e96d1f87..0000000000 --- a/bitacross-worker/app-libs/stf/src/evm_helpers.rs +++ /dev/null @@ -1,66 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -use crate::helpers::{get_storage_double_map, get_storage_map}; -use itp_stf_primitives::types::Nonce; -use itp_storage::StorageHasher; -use itp_types::AccountId; -use sha3::{Digest, Keccak256}; -use sp_core::{H160, H256}; -use std::prelude::v1::*; - -pub fn get_evm_account_codes(evm_account: &H160) -> Option> { - get_storage_map("Evm", "AccountCodes", evm_account, &StorageHasher::Blake2_128Concat) -} - -pub fn get_evm_account_storages(evm_account: &H160, index: &H256) -> Option { - get_storage_double_map( - "Evm", - "AccountStorages", - evm_account, - &StorageHasher::Blake2_128Concat, - index, - &StorageHasher::Blake2_128Concat, - ) -} - -// FIXME: Once events are available, these addresses should be read from events. -pub fn evm_create_address(caller: H160, nonce: Nonce) -> H160 { - let mut stream = rlp::RlpStream::new_list(2); - stream.append(&caller); - stream.append(&nonce); - H256::from_slice(Keccak256::digest(&stream.out()).as_slice()).into() -} - -// FIXME: Once events are available, these addresses should be read from events. -pub fn evm_create2_address(caller: H160, salt: H256, code_hash: H256) -> H160 { - let mut hasher = Keccak256::new(); - hasher.update([0xff]); - hasher.update(&caller[..]); - hasher.update(&salt[..]); - hasher.update(&code_hash[..]); - H256::from_slice(hasher.finalize().as_slice()).into() -} - -pub fn create_code_hash(code: &[u8]) -> H256 { - H256::from_slice(Keccak256::digest(code).as_slice()) -} - -pub fn get_evm_account(account: &AccountId) -> H160 { - let mut evm_acc_slice: [u8; 20] = [0; 20]; - evm_acc_slice.copy_from_slice((<[u8; 32]>::from(account.clone())).get(0..20).unwrap()); - evm_acc_slice.into() -} diff --git a/bitacross-worker/app-libs/stf/src/getter.rs b/bitacross-worker/app-libs/stf/src/getter.rs index de8d466189..ba4c9ec363 100644 --- a/bitacross-worker/app-libs/stf/src/getter.rs +++ b/bitacross-worker/app-libs/stf/src/getter.rs @@ -19,21 +19,14 @@ use codec::{Decode, Encode}; use ita_sgx_runtime::System; use itp_stf_interface::ExecuteGetter; use itp_stf_primitives::{traits::GetterAuthorization, types::KeyPair}; -use itp_utils::{if_production_or, stringify::account_id_to_string}; +use itp_utils::stringify::account_id_to_string; +use litentry_macros::if_production_or; use litentry_primitives::{Identity, LitentryMultiSignature}; use log::*; use sp_std::vec; use std::prelude::v1::*; -#[cfg(feature = "evm")] -use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; - -#[cfg(feature = "evm")] -use crate::evm_helpers::{get_evm_account, get_evm_account_codes, get_evm_account_storages}; - use itp_stf_primitives::traits::PoolTransactionValidation; -#[cfg(feature = "evm")] -use sp_core::{H160, H256}; use sp_runtime::transaction_validity::{ TransactionValidityError, UnknownTransaction, ValidTransaction, }; @@ -108,15 +101,6 @@ pub enum TrustedGetter { free_balance(Identity), #[codec(index = 1)] reserved_balance(Identity), - #[cfg(feature = "evm")] - #[codec(index = 2)] - evm_nonce(Identity), - #[cfg(feature = "evm")] - #[codec(index = 3)] - evm_account_codes(Identity, H160), - #[cfg(feature = "evm")] - #[codec(index = 4)] - evm_account_storages(Identity, H160, H256), } impl TrustedGetter { @@ -124,12 +108,6 @@ impl TrustedGetter { match self { TrustedGetter::free_balance(sender_identity) => sender_identity, TrustedGetter::reserved_balance(sender_identity) => sender_identity, - #[cfg(feature = "evm")] - TrustedGetter::evm_nonce(sender_identity) => sender_identity, - #[cfg(feature = "evm")] - TrustedGetter::evm_account_codes(sender_identity, _) => sender_identity, - #[cfg(feature = "evm")] - TrustedGetter::evm_account_storages(sender_identity, ..) => sender_identity, } } @@ -207,38 +185,6 @@ impl ExecuteGetter for TrustedGetterSigned { } else { None }, - #[cfg(feature = "evm")] - TrustedGetter::evm_nonce(who) => - if let Some(account_id) = who.to_account_id() { - let evm_account = get_evm_account(&account_id); - let evm_account = HashedAddressMapping::into_account_id(evm_account); - let nonce = System::account_nonce(&evm_account); - debug!("TrustedGetter evm_nonce"); - debug!("Account nonce is {}", nonce); - Some(nonce.encode()) - } else { - None - }, - #[cfg(feature = "evm")] - TrustedGetter::evm_account_codes(_who, evm_account) => - // TODO: This probably needs some security check if who == evm_account (or assosciated) - if let Some(info) = get_evm_account_codes(&evm_account) { - debug!("TrustedGetter Evm Account Codes"); - debug!("AccountCodes for {} is {:?}", evm_account, info); - Some(info) // TOOD: encoded? - } else { - None - }, - #[cfg(feature = "evm")] - TrustedGetter::evm_account_storages(_who, evm_account, index) => - // TODO: This probably needs some security check if who == evm_account (or assosciated) - if let Some(value) = get_evm_account_storages(&evm_account, &index) { - debug!("TrustedGetter Evm Account Storages"); - debug!("AccountStorages for {} is {:?}", evm_account, value); - Some(value.encode()) - } else { - None - }, } } diff --git a/bitacross-worker/app-libs/stf/src/helpers.rs b/bitacross-worker/app-libs/stf/src/helpers.rs index 0c6fd39896..639133470b 100644 --- a/bitacross-worker/app-libs/stf/src/helpers.rs +++ b/bitacross-worker/app-libs/stf/src/helpers.rs @@ -16,20 +16,14 @@ */ use crate::ENCLAVE_ACCOUNT_KEY; use codec::{Decode, Encode}; -use frame_support::ensure; -use hex_literal::hex; use itp_stf_primitives::error::{StfError, StfResult}; use itp_storage::{storage_double_map_key, storage_map_key, storage_value_key, StorageHasher}; -use itp_types::Index; use itp_utils::stringify::account_id_to_string; -use litentry_primitives::{ErrorDetail, Identity, Web3ValidationData}; use log::*; -use sp_core::blake2_256; -use sp_runtime::AccountId32; use std::prelude::v1::*; -pub const ALICE_ACCOUNTID32: AccountId32 = - AccountId32::new(hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"]); +#[cfg(not(feature = "production"))] +pub use non_prod::*; pub fn get_storage_value( storage_prefix: &'static str, @@ -129,47 +123,19 @@ pub fn ensure_enclave_signer_or_self( } #[cfg(not(feature = "production"))] -pub fn ensure_alice(signer: &AccountId32) -> bool { - signer == &ALICE_ACCOUNTID32 -} - -#[cfg(not(feature = "production"))] -pub fn ensure_enclave_signer_or_alice(signer: &AccountId32) -> bool { - signer == &enclave_signer_account::() || ensure_alice(signer) -} - -// verification message format: -// ``` -// blake2_256( + + ) -// ``` -// where <> means SCALE-encoded -// see https://github.com/litentry/litentry-parachain/issues/1739 and P-174 -pub fn get_expected_raw_message( - who: &Identity, - identity: &Identity, - sidechain_nonce: Index, -) -> Vec { - let mut payload = Vec::new(); - payload.append(&mut sidechain_nonce.encode()); - payload.append(&mut who.encode()); - payload.append(&mut identity.encode()); - blake2_256(payload.as_slice()).to_vec() -} +mod non_prod { + use super::*; + use hex_literal::hex; + use sp_runtime::AccountId32; -pub fn verify_web3_identity( - identity: &Identity, - raw_msg: &[u8], - data: &Web3ValidationData, -) -> StfResult<()> { - ensure!( - raw_msg == data.message().as_slice(), - StfError::LinkIdentityFailed(ErrorDetail::UnexpectedMessage) - ); + pub const ALICE_ACCOUNTID32: AccountId32 = + AccountId32::new(hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"]); - ensure!( - data.signature().verify(raw_msg, identity), - StfError::LinkIdentityFailed(ErrorDetail::VerifyWeb3SignatureFailed) - ); + pub fn ensure_alice(signer: &AccountId32) -> bool { + signer == &ALICE_ACCOUNTID32 + } - Ok(()) + pub fn ensure_enclave_signer_or_alice(signer: &AccountId32) -> bool { + signer == &enclave_signer_account::() || ensure_alice(signer) + } } diff --git a/bitacross-worker/app-libs/stf/src/lib.rs b/bitacross-worker/app-libs/stf/src/lib.rs index 894633b49f..4aa3ff1db4 100644 --- a/bitacross-worker/app-libs/stf/src/lib.rs +++ b/bitacross-worker/app-libs/stf/src/lib.rs @@ -33,8 +33,6 @@ pub use getter::*; pub use stf_sgx_primitives::{types::*, Stf}; pub use trusted_call::*; -#[cfg(feature = "evm")] -pub mod evm_helpers; pub mod getter; pub mod hash; pub mod helpers; diff --git a/bitacross-worker/app-libs/stf/src/test_genesis.rs b/bitacross-worker/app-libs/stf/src/test_genesis.rs index 161dec8e5e..fd70e4cc72 100644 --- a/bitacross-worker/app-libs/stf/src/test_genesis.rs +++ b/bitacross-worker/app-libs/stf/src/test_genesis.rs @@ -25,12 +25,6 @@ use sp_core::{crypto::AccountId32, ed25519, Pair}; use sp_runtime::MultiAddress; use std::{format, vec, vec::Vec}; -#[cfg(feature = "evm")] -use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; - -#[cfg(feature = "evm")] -use crate::evm_helpers::get_evm_account; - type Seed = [u8; 32]; const ALICE_ENCODED: Seed = [ @@ -62,28 +56,15 @@ pub fn test_genesis_setup(state: &mut impl SgxExternalitiesTrait) { set_sudo_account(state, &ALICE_ENCODED); trace!("Set new sudo account: {:?}", &ALICE_ENCODED); - let mut endowees: Vec<(AccountId32, Balance)> = vec![ + let endowees: Vec<(AccountId32, Balance)> = vec![ (endowed_account().public().into(), ENDOWED_ACC_FUNDS), (second_endowed_account().public().into(), SECOND_ENDOWED_ACC_FUNDS), (ALICE_ENCODED.into(), ALICE_FUNDS), ]; - append_funded_alice_evm_account(&mut endowees); - endow(state, endowees); } -#[cfg(feature = "evm")] -fn append_funded_alice_evm_account(endowees: &mut Vec<(AccountId32, Balance)>) { - let alice_evm = get_evm_account(&ALICE_ENCODED.into()); - let alice_evm_substrate_version = HashedAddressMapping::into_account_id(alice_evm); - let mut other: Vec<(AccountId32, Balance)> = vec![(alice_evm_substrate_version, ALICE_FUNDS)]; - endowees.append(other.as_mut()); -} - -#[cfg(not(feature = "evm"))] -fn append_funded_alice_evm_account(_: &mut Vec<(AccountId32, Balance)>) {} - fn set_sudo_account(state: &mut impl SgxExternalitiesTrait, account_encoded: &[u8]) { state.execute_with(|| { sp_io::storage::set(&storage_value_key("Sudo", "Key"), account_encoded); diff --git a/bitacross-worker/app-libs/stf/src/trusted_call.rs b/bitacross-worker/app-libs/stf/src/trusted_call.rs index 2ebeb97741..de6c01d03a 100644 --- a/bitacross-worker/app-libs/stf/src/trusted_call.rs +++ b/bitacross-worker/app-libs/stf/src/trusted_call.rs @@ -15,14 +15,6 @@ */ -#[cfg(feature = "evm")] -use sp_core::{H160, U256}; - -#[cfg(feature = "evm")] -use std::vec::Vec; - -#[cfg(feature = "evm")] -use crate::evm_helpers::{create_code_hash, evm_create2_address, evm_create_address}; use crate::{ helpers::{enclave_signer_account, ensure_enclave_signer_account, get_storage_by_key_hash}, trusted_call_result::TrustedCallResult, @@ -30,14 +22,9 @@ use crate::{ }; use codec::{Compact, Decode, Encode}; use frame_support::{ensure, traits::UnfilteredDispatchable}; -#[cfg(feature = "evm")] -use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; pub use ita_sgx_runtime::{Balance, Index, Runtime, System}; use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; -use itp_node_api_metadata::{ - pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, - pallet_proxy::ProxyCallIndexes, pallet_teerex::TeerexCallIndexes, pallet_vcmp::VCMPCallIndexes, -}; +use itp_node_api_metadata::{pallet_balances::BalancesCallIndexes, pallet_proxy::ProxyCallIndexes}; use itp_stf_interface::{ExecuteCall, SHARD_VAULT_KEY}; pub use itp_stf_primitives::{ error::{StfError, StfResult}, @@ -51,9 +38,8 @@ use itp_types::{ pub use itp_types::{OpaqueCall, H256}; use itp_utils::stringify::account_id_to_string; pub use litentry_primitives::{ - aes_encrypt_default, all_evm_web3networks, all_substrate_web3networks, AesOutput, Assertion, - ErrorDetail, IMPError, Identity, LitentryMultiSignature, ParentchainBlockNumber, RequestAesKey, - RequestAesKeyNonce, VCMPError, ValidationData, Web3Network, + aes_encrypt_default, AesOutput, Identity, LitentryMultiSignature, ParentchainBlockNumber, + RequestAesKey, RequestAesKeyNonce, ValidationData, }; use log::*; use sp_core::{ @@ -78,53 +64,6 @@ pub enum TrustedCall { balance_unshield(Identity, AccountId, Balance, ShardIdentifier), // (AccountIncognito, BeneficiaryPublicAccount, Amount, Shard) #[codec(index = 54)] balance_shield(Identity, AccountId, Balance), // (Root, AccountIncognito, Amount) - #[cfg(feature = "evm")] - #[codec(index = 55)] - evm_withdraw(Identity, H160, Balance), // (Origin, Address EVM Account, Value) - // (Origin, Source, Target, Input, Value, Gas limit, Max fee per gas, Max priority fee per gas, Nonce, Access list) - #[cfg(feature = "evm")] - #[codec(index = 56)] - evm_call( - Identity, - H160, - H160, - Vec, - U256, - u64, - U256, - Option, - Option, - Vec<(H160, Vec)>, - ), - // (Origin, Source, Init, Value, Gas limit, Max fee per gas, Max priority fee per gas, Nonce, Access list) - #[cfg(feature = "evm")] - #[codec(index = 57)] - evm_create( - Identity, - H160, - Vec, - U256, - u64, - U256, - Option, - Option, - Vec<(H160, Vec)>, - ), - // (Origin, Source, Init, Salt, Value, Gas limit, Max fee per gas, Max priority fee per gas, Nonce, Access list) - #[cfg(feature = "evm")] - #[codec(index = 58)] - evm_create2( - Identity, - H160, - Vec, - H256, - U256, - u64, - U256, - Option, - Option, - Vec<(H160, Vec)>, - ), } impl TrustedCall { @@ -135,14 +74,6 @@ impl TrustedCall { Self::balance_transfer(sender_identity, ..) => sender_identity, Self::balance_unshield(sender_identity, ..) => sender_identity, Self::balance_shield(sender_identity, ..) => sender_identity, - #[cfg(feature = "evm")] - Self::evm_withdraw(sender_identity, ..) => sender_identity, - #[cfg(feature = "evm")] - Self::evm_call(sender_identity, ..) => sender_identity, - #[cfg(feature = "evm")] - Self::evm_create(sender_identity, ..) => sender_identity, - #[cfg(feature = "evm")] - Self::evm_create2(sender_identity, ..) => sender_identity, } } } @@ -160,7 +91,8 @@ impl TrustedCallSigning for TrustedCall { payload.append(&mut mrenclave.encode()); payload.append(&mut shard.encode()); - TrustedCallSigned { call: self.clone(), nonce, signature: pair.sign(payload.as_slice()) } + // use blake2_256 hash to shorten the payload - see `verify_signature` below + TrustedCallSigned { call: self.clone(), nonce, signature: pair.sign(&blake2_256(&payload)) } } } @@ -213,7 +145,8 @@ impl TrustedCallVerification for TrustedCallSigned { payload.append(&mut mrenclave.encode()); payload.append(&mut shard.encode()); - self.signature.verify(payload.as_slice(), self.call.sender_identity()) + self.signature.verify(&blake2_256(&payload), self.call.sender_identity()) + || self.signature.verify(&payload, self.call.sender_identity()) } } @@ -266,7 +199,6 @@ where node_metadata_repo: Arc, ) -> Result { let sender = self.call.sender_identity().clone(); - let call_hash = blake2_256(&self.call.encode()); let account_id: AccountId = sender.to_account_id().ok_or(Self::Error::InvalidAccount)?; let system_nonce = System::account_nonce(&account_id); ensure!(self.nonce == system_nonce, Self::Error::InvalidNonce(self.nonce, system_nonce)); @@ -413,141 +345,7 @@ where debug!("balance_shield({}, {})", account_id_to_string(&who), value); shield_funds(who, value)?; - // Send proof of execution on chain. - calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( - node_metadata_repo - .get_from_metadata(|m| m.publish_hash_call_indexes()) - .map_err(|_| StfError::InvalidMetadata)? - .map_err(|_| StfError::InvalidMetadata)?, - call_hash, - Vec::::new(), - b"shielded some funds!".to_vec(), - )))); - Ok(TrustedCallResult::Empty) - }, - #[cfg(feature = "evm")] - TrustedCall::evm_withdraw(from, address, value) => { - debug!("evm_withdraw({}, {}, {})", account_id_to_string(&from), address, value); - ita_sgx_runtime::EvmCall::::withdraw { address, value } - .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::signed( - from.to_account_id().ok_or(Self::Error::InvalidAccount)?, - )) - .map_err(|e| { - Self::Error::Dispatch(format!("Evm Withdraw error: {:?}", e.error)) - })?; - Ok(TrustedCallResult::Empty) - }, - #[cfg(feature = "evm")] - TrustedCall::evm_call( - from, - source, - target, - input, - value, - gas_limit, - max_fee_per_gas, - max_priority_fee_per_gas, - nonce, - access_list, - ) => { - debug!( - "evm_call(from: {}, source: {}, target: {})", - account_id_to_string(&from), - source, - target - ); - ita_sgx_runtime::EvmCall::::call { - source, - target, - input, - value, - gas_limit, - max_fee_per_gas, - max_priority_fee_per_gas, - nonce, - access_list, - } - .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::signed( - from.to_account_id().ok_or(Self::Error::InvalidAccount)?, - )) - .map_err(|e| Self::Error::Dispatch(format!("Evm Call error: {:?}", e.error)))?; - Ok(TrustedCallResult::Empty) - }, - #[cfg(feature = "evm")] - TrustedCall::evm_create( - from, - source, - init, - value, - gas_limit, - max_fee_per_gas, - max_priority_fee_per_gas, - nonce, - access_list, - ) => { - debug!( - "evm_create(from: {}, source: {}, value: {})", - account_id_to_string(&from), - source, - value - ); - let nonce_evm_account = - System::account_nonce(&HashedAddressMapping::into_account_id(source)); - ita_sgx_runtime::EvmCall::::create { - source, - init, - value, - gas_limit, - max_fee_per_gas, - max_priority_fee_per_gas, - nonce, - access_list, - } - .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::signed( - from.to_account_id().ok_or(Self::Error::InvalidAccount)?, - )) - .map_err(|e| Self::Error::Dispatch(format!("Evm Create error: {:?}", e.error)))?; - let contract_address = evm_create_address(source, nonce_evm_account); - info!("Trying to create evm contract with address {:?}", contract_address); - Ok(TrustedCallResult::Empty) - }, - #[cfg(feature = "evm")] - TrustedCall::evm_create2( - from, - source, - init, - salt, - value, - gas_limit, - max_fee_per_gas, - max_priority_fee_per_gas, - nonce, - access_list, - ) => { - debug!( - "evm_create2(from: {}, source: {}, value: {})", - account_id_to_string(&from), - source, - value - ); - let code_hash = create_code_hash(&init); - ita_sgx_runtime::EvmCall::::create2 { - source, - init, - salt, - value, - gas_limit, - max_fee_per_gas, - max_priority_fee_per_gas, - nonce, - access_list, - } - .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::signed( - from.to_account_id().ok_or(Self::Error::InvalidAccount)?, - )) - .map_err(|e| Self::Error::Dispatch(format!("Evm Create2 error: {:?}", e.error)))?; - let contract_address = evm_create2_address(source, salt, code_hash); - info!("Trying to create evm contract with address {:?}", contract_address); + // Litentry: we don't have publish_hash call in teebag Ok(TrustedCallResult::Empty) }, } @@ -609,53 +407,6 @@ where pallet_sudo::Pallet::::key().map_or(false, |k| account == &k) } -pub fn push_call_imp_some_error( - calls: &mut Vec, - node_metadata_repo: Arc, - identity: Option, - e: IMPError, - req_ext_hash: H256, -) where - NodeMetadataRepository: AccessNodeMetadata, - NodeMetadataRepository::MetadataType: NodeMetadataTrait, -{ - debug!("pushing IMP::some_error call ..."); - // TODO: anyway to simplify this? `and_then` won't be applicable here - match node_metadata_repo.get_from_metadata(|m| m.imp_some_error_call_indexes()) { - Ok(Ok(call_index)) => calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( - call_index, - identity, - e, - req_ext_hash, - )))), - Ok(e) => warn!("error getting IMP::some_error call indexes: {:?}", e), - Err(e) => warn!("error getting IMP::some_error call indexes: {:?}", e), - } -} - -pub fn push_call_vcmp_some_error( - calls: &mut Vec, - node_metadata_repo: Arc, - identity: Option, - e: VCMPError, - req_ext_hash: H256, -) where - NodeMetadataRepository: AccessNodeMetadata, - NodeMetadataRepository::MetadataType: NodeMetadataTrait, -{ - debug!("pushing VCMP::some_error call ..."); - match node_metadata_repo.get_from_metadata(|m| m.vcmp_some_error_call_indexes()) { - Ok(Ok(call_index)) => calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( - call_index, - identity, - e, - req_ext_hash, - )))), - Ok(e) => warn!("error getting VCMP::some_error call indexes: {:?}", e), - Err(e) => warn!("error getting VCMP::some_error call indexes: {:?}", e), - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/bitacross-worker/app-libs/stf/src/trusted_call_result.rs b/bitacross-worker/app-libs/stf/src/trusted_call_result.rs index f9cbbeff95..60e303ce3b 100644 --- a/bitacross-worker/app-libs/stf/src/trusted_call_result.rs +++ b/bitacross-worker/app-libs/stf/src/trusted_call_result.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify @@ -16,7 +16,6 @@ // This file contain the RPC response struct which will be encoded and // passed back to the requester of trustedCall direct invocation (DI). -// They are mostly translated from the callback extrinsics in IMP. use codec::{Decode, Encode}; use itp_stf_interface::StfExecutionResult; diff --git a/bitacross-worker/assets/teebag_registry.gif b/bitacross-worker/assets/teebag_registry.gif new file mode 100644 index 0000000000..b337fb6c3a Binary files /dev/null and b/bitacross-worker/assets/teebag_registry.gif differ diff --git a/bitacross-worker/bitacross/core/bc-relayer-registry/Cargo.toml b/bitacross-worker/bitacross/core/bc-relayer-registry/Cargo.toml new file mode 100644 index 0000000000..c9fa935eb7 --- /dev/null +++ b/bitacross-worker/bitacross/core/bc-relayer-registry/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "bc-relayer-registry" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +lazy_static = { version = "1.1.0", features = ["spin_no_std"] } +log = { version = "0.4", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +thiserror = { version = "1.0.26", optional = true } + + +# sgx dependencies +sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master", optional = true, features = ["net", "thread"] } +thiserror-sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + + +# internal dependencies +itp-settings = { path = "../../../core-primitives/settings", default-features = false } +itp-sgx-io = { path = "../../../core-primitives/sgx/io", default-features = false } +# litentry primities +litentry-primitives = { path = "../../../litentry/primitives", default-features = false } + +[dev-dependencies] +base64 = { version = "0.13", features = ["alloc"] } + +[features] +default = ["std"] +production = [ +] +sgx = [ + "sgx_tstd", + "thiserror-sgx", + "itp-sgx-io/sgx", + "litentry-primitives/sgx", +] +std = [ + "sp-std/std", + "log/std", + "thiserror", + "itp-sgx-io/std", + "litentry-primitives/std", +] diff --git a/bitacross-worker/bitacross/core/bc-relayer-registry/src/lib.rs b/bitacross-worker/bitacross/core/bc-relayer-registry/src/lib.rs new file mode 100644 index 0000000000..4768c29b3d --- /dev/null +++ b/bitacross-worker/bitacross/core/bc-relayer-registry/src/lib.rs @@ -0,0 +1,202 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate core; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +use sp_std::{boxed::Box, fmt::Debug}; + +use lazy_static::lazy_static; +use litentry_primitives::Identity; +use log::error; +use std::{collections::BTreeMap, path::PathBuf, sync::Arc}; + +#[cfg(feature = "std")] +use std::sync::RwLock; +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +lazy_static! { + /// Global instance of a RelayerRegistry + pub static ref GLOBAL_RELAYER_REGISTRY: Arc = Default::default(); +} + +pub type RelayerRegistryMap = BTreeMap; + +#[derive(Default)] +pub struct RelayerRegistry { + pub registry: RwLock, + pub seal_path: PathBuf, +} + +pub type RegistryResult = core::result::Result; + +#[cfg(feature = "sgx")] +use thiserror_sgx as thiserror; + +#[derive(Debug, thiserror::Error)] +pub enum RegistryError { + #[error("poison lock")] + PoisonLock, + #[error("empty Relayer registry")] + EmptyRegistry, + #[error(transparent)] + Other(#[from] Box), +} + +impl From for RegistryError { + fn from(e: std::io::Error) -> Self { + Self::Other(e.into()) + } +} + +impl From for RegistryError { + #[cfg(feature = "std")] + fn from(e: codec::Error) -> Self { + Self::Other(e.into()) + } + + #[cfg(feature = "sgx")] + fn from(e: codec::Error) -> Self { + Self::Other(std::format!("{:?}", e).into()) + } +} + +#[cfg(feature = "sgx")] +mod sgx { + use crate::{RegistryError as Error, RegistryResult as Result, RelayerRegistryMap}; + pub use codec::{Decode, Encode}; + pub use itp_settings::files::RELAYER_REGISTRY_FILE; + pub use itp_sgx_io::{seal, unseal, SealedIO}; + pub use log::*; + pub use std::{boxed::Box, fs, path::PathBuf, sgxfs::SgxFile, sync::Arc}; + + #[derive(Clone, Debug)] + pub struct RelayerRegistrySeal { + base_path: PathBuf, + } + + impl RelayerRegistrySeal { + pub fn new(base_path: PathBuf) -> Self { + Self { base_path } + } + + pub fn path(&self) -> PathBuf { + self.base_path.join(RELAYER_REGISTRY_FILE) + } + } + + impl SealedIO for RelayerRegistrySeal { + type Error = Error; + type Unsealed = RelayerRegistryMap; + + fn unseal(&self) -> Result { + Ok(unseal(self.path()).map(|b| Decode::decode(&mut b.as_slice()))??) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + info!("Seal relayer registry to file: {:?}", unsealed); + Ok(unsealed.using_encoded(|bytes| seal(bytes, self.path()))?) + } + } +} + +#[cfg(feature = "sgx")] +use sgx::*; + +pub trait RelayerRegistryUpdater { + fn init(&self) -> RegistryResult<()>; + fn update(&self, account: Identity) -> RegistryResult<()>; + fn remove(&self, account: Identity) -> RegistryResult<()>; +} + +pub trait RelayerRegistryLookup { + fn contains_key(&self, account: Identity) -> bool; +} + +impl RelayerRegistryUpdater for RelayerRegistry { + #[cfg(feature = "std")] + fn init(&self) -> RegistryResult<()> { + Ok(()) + } + + #[cfg(feature = "std")] + fn update(&self, account: Identity) -> RegistryResult<()> { + let mut registry = self.registry.write().unwrap(); + registry.insert(account, ()); + Ok(()) + } + + #[cfg(feature = "std")] + fn remove(&self, _account: Identity) -> RegistryResult<()> { + Ok(()) + } + + // if `RELAYER_REGISTRY_FILE` exists, unseal and init from it + // otherwise create a new instance and seal to static file + #[cfg(feature = "sgx")] + fn init(&self) -> RegistryResult<()> { + let enclave_seal = RelayerRegistrySeal::new(self.seal_path.clone()); + if SgxFile::open(RELAYER_REGISTRY_FILE).is_err() { + info!( + "[Enclave] RelayerRegistry file not found, creating new! {}", + RELAYER_REGISTRY_FILE + ); + let registry = GLOBAL_RELAYER_REGISTRY + .registry + .write() + .map_err(|_| RegistryError::PoisonLock)?; + enclave_seal.seal(&*registry) + } else { + let m = enclave_seal.unseal()?; + info!("[Enclave] RelayerRegistry unsealed from file: {:?}", m); + let mut registry = GLOBAL_RELAYER_REGISTRY + .registry + .write() + .map_err(|_| RegistryError::PoisonLock)?; + *registry = m; + Ok(()) + } + } + + #[cfg(feature = "sgx")] + fn update(&self, account: Identity) -> RegistryResult<()> { + let mut registry = GLOBAL_RELAYER_REGISTRY + .registry + .write() + .map_err(|_| RegistryError::PoisonLock)?; + registry.insert(account, ()); + RelayerRegistrySeal::new(self.seal_path.clone()).seal(&*registry) + } + + #[cfg(feature = "sgx")] + fn remove(&self, account: Identity) -> RegistryResult<()> { + let mut registry = GLOBAL_RELAYER_REGISTRY + .registry + .write() + .map_err(|_| RegistryError::PoisonLock)?; + let old_value = registry.remove(&account); + if old_value.is_some() { + return RelayerRegistrySeal::new(self.seal_path.clone()).seal(&*registry) + } + Ok(()) + } +} + +impl RelayerRegistryLookup for RelayerRegistry { + #[cfg(feature = "std")] + fn contains_key(&self, account: Identity) -> bool { + let registry = self.registry.read().unwrap(); + registry.contains_key(&account) + } + + #[cfg(feature = "sgx")] + fn contains_key(&self, account: Identity) -> bool { + // Using unwrap becaused poisoned locks are unrecoverable errors + let registry = GLOBAL_RELAYER_REGISTRY.registry.read().unwrap(); + registry.contains_key(&account) + } +} diff --git a/bitacross-worker/bitacross/core/bc-task-receiver/Cargo.toml b/bitacross-worker/bitacross/core/bc-task-receiver/Cargo.toml new file mode 100644 index 0000000000..d386a1a6d0 --- /dev/null +++ b/bitacross-worker/bitacross/core/bc-task-receiver/Cargo.toml @@ -0,0 +1,77 @@ +[package] +name = "bc-task-receiver" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# std dependencies +thiserror = { version = "1.0.26", optional = true } +threadpool = { version = "1.8.0", optional = true } + +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +futures_sgx = { package = "futures", git = "https://github.com/mesalock-linux/futures-rs-sgx", optional = true } + +# sgx dependencies +hex-sgx = { package = "hex", git = "https://github.com/mesalock-linux/rust-hex-sgx", tag = "sgx_1.1.3", features = ["sgx_tstd"], optional = true } +sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master", features = ["net", "thread"], optional = true } +threadpool_sgx = { git = "https://github.com/mesalock-linux/rust-threadpool-sgx", package = "threadpool", tag = "sgx_1.1.3", optional = true } + +# no_std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } + +# internal dependencies +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +ita-stf = { path = "../../../app-libs/stf", default-features = false } +itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } +itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } +itp-sgx-externalities = { path = "../../../core-primitives/substrate-sgx/externalities", default-features = false } +itp-stf-executor = { path = "../../../core-primitives/stf-executor", default-features = false } +itp-stf-state-handler = { path = "../../../core-primitives/stf-state-handler", default-features = false } + +# litentry primities +bc-relayer-registry = { path = "../bc-relayer-registry", default-features = false } +lc-direct-call = { path = "../../../litentry/core/direct-call", default-features = false } +litentry-primitives = { path = "../../../litentry/primitives", default-features = false } + +bc-task-sender = { path = "../bc-task-sender", default-features = false } + +[features] +default = ["std"] +sgx = [ + "threadpool_sgx", + "hex-sgx", + "sgx_tstd", + "bc-task-sender/sgx", + "bc-relayer-registry/sgx", + "lc-direct-call/sgx", + "litentry-primitives/sgx", + "ita-stf/sgx", + "itp-sgx-crypto/sgx", + "itp-sgx-externalities/sgx", + "itp-stf-executor/sgx", + "itp-stf-state-handler/sgx", + "thiserror_sgx", + "futures_sgx", +] +std = [ + "threadpool", + "log/std", + "bc-task-sender/std", + "bc-relayer-registry/std", + "lc-direct-call/std", + "litentry-primitives/std", + "ita-stf/std", + "itp-ocall-api/std", + "itp-sgx-crypto/std", + "itp-sgx-externalities/std", + "itp-stf-executor/std", + "itp-stf-state-handler/std", + "thiserror", +] +production = [ +] diff --git a/bitacross-worker/bitacross/core/bc-task-receiver/src/lib.rs b/bitacross-worker/bitacross/core/bc-task-receiver/src/lib.rs new file mode 100644 index 0000000000..55cfdcb211 --- /dev/null +++ b/bitacross-worker/bitacross/core/bc-task-receiver/src/lib.rs @@ -0,0 +1,194 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate core; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use futures_sgx as futures; + pub use hex_sgx as hex; + pub use thiserror_sgx as thiserror; + pub use threadpool_sgx as threadpool; +} + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub use crate::sgx_reexport_prelude::*; +use core::ops::Deref; + +use bc_task_sender::init_bit_across_task_sender_storage; +use codec::{Decode, Encode}; +use frame_support::ensure; +use lc_direct_call::{DirectCall, DirectCallSigned}; +use litentry_primitives::{aes_encrypt_default, AesRequest}; +use log::*; +use std::{ + boxed::Box, + format, + string::{String, ToString}, + sync::Arc, + vec::Vec, +}; +use threadpool::ThreadPool; + +use itp_ocall_api::{EnclaveAttestationOCallApi, EnclaveMetricsOCallApi, EnclaveOnChainOCallApi}; +use itp_sgx_crypto::{key_repository::AccessKey, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_executor::traits::StfEnclaveSigning; +use itp_stf_state_handler::handle_state::HandleState; + +use bc_relayer_registry::RelayerRegistryLookup; +use ita_stf::TrustedCallSigned; +use itp_sgx_crypto::{ecdsa::Pair as EcdsaPair, schnorr::Pair as SchnorrPair}; +use lc_direct_call::handler::{sign_bitcoin, sign_ethereum}; +use litentry_primitives::DecryptableRequest; + +#[derive(Debug, thiserror::Error, Clone)] +pub enum Error { + #[error("Request error: {0}")] + RequestError(String), + + #[error("Other error: {0}")] + OtherError(String), +} + +pub struct BitAcrossTaskContext< + SKR, + EKR, + BKR, + S: StfEnclaveSigning, + H: HandleState, + O: EnclaveOnChainOCallApi, + RRL: RelayerRegistryLookup, +> where + SKR: AccessKey, + EKR: AccessKey, + BKR: AccessKey, + ::KeyType: ShieldingCryptoEncrypt + 'static, +{ + pub shielding_key: Arc, + pub ethereum_key_repository: Arc, + pub bitcoin_key_repository: Arc, + pub enclave_signer: Arc, + pub state_handler: Arc, + pub ocall_api: Arc, + pub relayer_registry_lookup: Arc, +} + +impl< + SKR, + EKR, + BKR, + S: StfEnclaveSigning, + H: HandleState, + O: EnclaveOnChainOCallApi, + RRL: RelayerRegistryLookup, + > BitAcrossTaskContext +where + SKR: AccessKey, + EKR: AccessKey, + BKR: AccessKey, + ::KeyType: ShieldingCryptoEncrypt + 'static, + H::StateT: SgxExternalitiesTrait, +{ + pub fn new( + shielding_key: Arc, + ethereum_key_repository: Arc, + bitcoin_key_repository: Arc, + enclave_signer: Arc, + state_handler: Arc, + ocall_api: Arc, + relayer_registry_lookup: Arc, + ) -> Self { + Self { + shielding_key, + ethereum_key_repository, + bitcoin_key_repository, + enclave_signer, + state_handler, + ocall_api, + relayer_registry_lookup, + } + } +} + +pub fn run_bit_across_handler_runner( + context: Arc>, +) where + SKR: AccessKey + Send + Sync + 'static, + EKR: AccessKey + Send + Sync + 'static, + BKR: AccessKey + Send + Sync + 'static, + ::KeyType: ShieldingCryptoEncrypt + ShieldingCryptoDecrypt + 'static, + S: StfEnclaveSigning + Send + Sync + 'static, + H: HandleState + Send + Sync + 'static, + H::StateT: SgxExternalitiesTrait, + O: EnclaveOnChainOCallApi + EnclaveMetricsOCallApi + EnclaveAttestationOCallApi + 'static, + RRL: RelayerRegistryLookup + Send + Sync + 'static, +{ + let bit_across_task_receiver = init_bit_across_task_sender_storage(); + let n_workers = 2; + let pool = ThreadPool::new(n_workers); + + while let Ok(mut req) = bit_across_task_receiver.recv() { + let context_pool = context.clone(); + pool.execute(move || { + if let Err(e) = req.sender.send(handle_request(&mut req.request, context_pool)) { + warn!("Unable to submit response back to the handler: {:?}", e); + } + }); + } + + pool.join(); + warn!("bit_across_task_receiver loop terminated"); +} + +pub fn handle_request( + request: &mut AesRequest, + context: Arc>, +) -> Result, String> +where + SKR: AccessKey, + EKR: AccessKey, + BKR: AccessKey, + ::KeyType: ShieldingCryptoEncrypt + ShieldingCryptoDecrypt + 'static, + S: StfEnclaveSigning + Send + Sync + 'static, + H: HandleState + Send + Sync + 'static, + O: EnclaveOnChainOCallApi + EnclaveMetricsOCallApi + EnclaveAttestationOCallApi + 'static, + RRL: RelayerRegistryLookup + 'static, +{ + let enclave_shielding_key = context + .shielding_key + .retrieve_key() + .map_err(|e| format!("Failed to retrieve shielding key: {:?}", e))?; + let dc = request + .decrypt(Box::new(enclave_shielding_key)) + .ok() + .and_then(|v| DirectCallSigned::decode(&mut v.as_slice()).ok()) + .ok_or_else(|| "Failed to decode payload".to_string())?; + + let mrenclave = match context.ocall_api.get_mrenclave_of_self() { + Ok(m) => m.m, + Err(_) => return Err("Failed to get mrenclave".to_string()), + }; + ensure!(dc.verify_signature(&mrenclave, &request.shard), "Failed to verify sig".to_string()); + match dc.call { + DirectCall::SignBitcoin(signer, aes_key, payload) => sign_bitcoin::handle( + signer, + payload, + context.relayer_registry_lookup.deref(), + context.bitcoin_key_repository.deref(), + ) + .map(|r| aes_encrypt_default(&aes_key, &r).encode()), + DirectCall::SignEthereum(signer, aes_key, msg) => sign_ethereum::handle( + signer, + msg, + context.relayer_registry_lookup.deref(), + context.ethereum_key_repository.deref(), + ) + .map(|r| aes_encrypt_default(&aes_key, &r).encode()), + } +} diff --git a/bitacross-worker/bitacross/core/bc-task-sender/Cargo.toml b/bitacross-worker/bitacross/core/bc-task-sender/Cargo.toml new file mode 100644 index 0000000000..fd738ebe7b --- /dev/null +++ b/bitacross-worker/bitacross/core/bc-task-sender/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "bc-task-sender" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# std dependencies +futures = { version = "0.3.8", optional = true } + +# sgx dependencies +futures_sgx = { package = "futures", git = "https://github.com/mesalock-linux/futures-rs-sgx", optional = true } +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["net", "thread"], optional = true } + +# no_std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +lazy_static = { version = "1.1.0", features = ["spin_no_std"] } + +# litentry primities +litentry-primitives = { path = "../../../litentry/primitives", default-features = false } + +[features] +default = ["std"] +sgx = [ + "futures_sgx", + "sgx_tstd", + "futures_sgx", + "litentry-primitives/sgx", +] +std = [ + "futures", + "futures", + "litentry-primitives/std", +] diff --git a/bitacross-worker/bitacross/core/bc-task-sender/src/lib.rs b/bitacross-worker/bitacross/core/bc-task-sender/src/lib.rs new file mode 100644 index 0000000000..6569bba2b2 --- /dev/null +++ b/bitacross-worker/bitacross/core/bc-task-sender/src/lib.rs @@ -0,0 +1,110 @@ +#![feature(trait_alias)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use futures_sgx as futures; +} + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub use crate::sgx_reexport_prelude::*; + +use codec::{Decode, Encode}; +use futures::channel::oneshot; +use lazy_static::lazy_static; +use litentry_primitives::AesRequest; +#[cfg(feature = "std")] +use std::sync::Mutex; +#[cfg(feature = "sgx")] +use std::sync::SgxMutex as Mutex; +use std::{ + format, + string::String, + sync::{ + mpsc::{channel, Receiver, Sender as MpscSender}, + Arc, + }, + vec::Vec, +}; + +#[derive(Debug)] +pub struct BitAcrossRequest { + pub sender: oneshot::Sender, String>>, + pub request: AesRequest, +} + +#[derive(Encode, Decode, Clone)] +pub struct BitAcrossResponse { + pub payload: Vec, +} + +pub type BitAcrossSender = MpscSender; + +// Global storage of the sender. Should not be accessed directly. +lazy_static! { + static ref GLOBAL_BIT_ACROSS_TASK_SENDER: Arc>> = + Arc::new(Mutex::new(Default::default())); +} + +pub struct BitAcrossRequestSender {} +impl BitAcrossRequestSender { + pub fn new() -> Self { + Self {} + } +} + +impl Default for BitAcrossRequestSender { + fn default() -> Self { + Self::new() + } +} + +impl BitAcrossRequestSender { + pub fn send(&self, request: BitAcrossRequest) -> Result<(), String> { + // Acquire lock on extrinsic sender + let mutex_guard = GLOBAL_BIT_ACROSS_TASK_SENDER.lock().unwrap(); + let bit_across_task_sender = mutex_guard.clone().unwrap(); + // Release mutex lock, so we don't block the lock longer than necessary. + drop(mutex_guard); + + // Send the request to the receiver loop. + bit_across_task_sender.send(request)?; + + Ok(()) + } +} + +/// Initialization of the extrinsic sender. Needs to be called before any sender access. +pub fn init_bit_across_task_sender_storage() -> Receiver { + let (sender, receiver) = channel(); + // It makes no sense to handle the unwrap, as this statement fails only if the lock has been poisoned + // I believe at that point it is an unrecoverable error + let mut bit_across_task_storage = GLOBAL_BIT_ACROSS_TASK_SENDER.lock().unwrap(); + *bit_across_task_storage = Some(BitAcrossTaskSender::new(sender)); + receiver +} + +/// Wrapping struct around the actual sender. Should not be accessed directly. (unnecessary) +#[derive(Clone, Debug)] +pub struct BitAcrossTaskSender { + sender: BitAcrossSender, +} + +impl BitAcrossTaskSender { + pub fn new(sender: BitAcrossSender) -> Self { + Self { sender } + } + + fn send(&self, request: BitAcrossRequest) -> Result<(), String> { + self.sender + .send(request) + .map_err(|e| format!("Failed to send message to BitAcross Handler: {:?}", e)) + } +} diff --git a/bitacross-worker/cli/Cargo.toml b/bitacross-worker/cli/Cargo.toml index 6e42a13d52..50119e7939 100644 --- a/bitacross-worker/cli/Cargo.toml +++ b/bitacross-worker/cli/Cargo.toml @@ -25,7 +25,6 @@ thiserror = "1.0" urlencoding = "2.1.3" # scs / integritee -pallet-evm = { optional = true, git = "https://github.com/integritee-network/frontier.git", branch = "bar/polkadot-v0.9.42" } # `default-features = false` to remove the jsonrpsee dependency. substrate-api-client = { default-features = false, features = ["std", "sync-api"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } substrate-client-keystore = { git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } @@ -45,24 +44,17 @@ itp-node-api = { path = "../core-primitives/node-api" } itp-rpc = { path = "../core-primitives/rpc" } itp-sgx-crypto = { path = "../core-primitives/sgx/crypto" } itp-stf-primitives = { path = "../core-primitives/stf-primitives" } -itp-time-utils = { path = "../core-primitives/time-utils" } itp-types = { path = "../core-primitives/types" } itp-utils = { path = "../core-primitives/utils" } # litentry -frame-metadata = "15.0.0" -ita-sgx-runtime = { path = "../app-libs/sgx-runtime" } +lc-direct-call = { path = "../litentry/core/direct-call" } litentry-primitives = { path = "../litentry/primitives" } my-node-runtime = { package = "rococo-parachain-runtime", path = "../../runtime/rococo" } pallet-teerex = { path = "../../pallets/teerex", default-features = false } -scale-value = "0.6.0" -sp-core-hashing = "6.0.0" [features] default = [] -evm = ["ita-stf/evm_std", "pallet-evm"] -teeracle = [] -sidechain = [] offchain-worker = [] production = [] # dcap feature flag is not used in this crate, but for easier build purposes only it present here as well diff --git a/bitacross-worker/cli/demo_teeracle_generic.sh b/bitacross-worker/cli/demo_teeracle_generic.sh deleted file mode 100755 index 8c2de3bf87..0000000000 --- a/bitacross-worker/cli/demo_teeracle_generic.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash -set -euo pipefail - -trap "echo The demo is terminated (SIGINT); exit 1" SIGINT -trap "echo The demo is terminated (SIGTERM); exit 1" SIGTERM - -# Registers a teeracle with the parentchain, and publish some oracle data. -# -# Demo to show that an enclave can update the exchange rate only when -# 1. the enclave is registered at the pallet-teerex. -# 2. and that the code used is reliable -> the enclave has been put the teeracle whitelist via a governance or sudo -# call. -# -# The teeracle's whitelist has to be empty at the start. So the script needs to run with a clean node state. -# A registered mrenclave will be added in the whitelist by a sudo account. Here //Alice -# -# setup: -# run all on localhost: -# integritee-node purge-chain --dev -# integritee-node --dev -lpallet_teeracle=debug,parity_ws=error,aura=error,sc_basic_authorship=error -# integritee-service --clean-reset run (--skip-ra --dev) -# -# then run this script -# -# usage: -# demo_teeracle_generic.sh -p -P -d -i -u -V -C - -while getopts ":p:P:d:i:u:V:C:" opt; do - case $opt in - p) - LITENTRY_RPC_PORT=$OPTARG - ;; - P) - WORKER_1_PORT=$OPTARG - ;; - d) - DURATION=$OPTARG - ;; - i) - INTERVAL=$OPTARG - ;; - u) - LITENTRY_RPC_URL=$OPTARG - ;; - V) - WORKER_1_URL=$OPTARG - ;; - C) - CLIENT_BIN=$OPTARG - ;; - *) - echo "invalid arg ${OPTARG}" - exit 1 - esac -done - -# using default port if none given as arguments -LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} -LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} - -WORKER_1_PORT=${WORKER_1_PORT:-2000} -WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} - -CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} - -DURATION=${DURATION:-48} -INTERVAL=${INTERVAL:-86400} - -LISTEN_TO_ORACLE_EVENTS_CMD="oracle listen-to-oracle-events" -ADD_TO_WHITELIST_CMD="oracle add-to-whitelist" - -echo "Using client binary ${CLIENT_BIN}" -${CLIENT_BIN} --version -echo "Using node uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" -echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" -echo "Using worker data update interval ${INTERVAL}" -echo "Count the update events for ${DURATION}" -echo "" - -OPEN_METEO="https://api.open-meteo.com/" -let "MIN_EXPECTED_NUM_OF_EVENTS=$DURATION/$INTERVAL-3" -echo "Minimum expected number of events with a single oracle source: ${MIN_EXPECTED_NUM_OF_EVENTS}" - -# let "MIN_EXPECTED_NUM_OF_EVENTS_2 = 2*$MIN_EXPECTED_NUM_OF_EVENTS" -# echo "Minimum expected number of events with two oracle sources: ${MIN_EXPECTED_NUM_OF_EVENTS_2}" - -CLIENT="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_1_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_1_URL}" - -echo "* Query on-chain enclave registry:" -${CLIENT} list-workers -echo "" - -# this will always take the first MRENCLAVE found in the registry !! -read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') -echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" - -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } -echo "" - -echo "Listen to OracleUpdated events for ${DURATION} seconds. There should be no trusted oracle source!" - -read NO_EVENTS <<< $(${CLIENT} ${LISTEN_TO_ORACLE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') -echo "Got ${NO_EVENTS} oracle updates when no trusted oracle source is in the whitelist" -echo "" - -echo "Add ${OPEN_METEO} for ${MRENCLAVE} as trusted oracle source" -${CLIENT} ${ADD_TO_WHITELIST_CMD} //Alice ${OPEN_METEO} ${MRENCLAVE} -echo "MRENCLAVE in whitelist for ${OPEN_METEO}" -echo "" - -echo "Listen to OracleUpdated events for ${DURATION} seconds, after a trusted oracle source has been added to the whitelist." -#${CLIENT} ${LISTEN_TO_ORACLE_EVENTS_CMD} ${DURATION} -#echo "" - -read EVENTS_COUNT <<< $($CLIENT ${LISTEN_TO_ORACLE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') -echo "Got ${EVENTS_COUNT} oracle updates from the trusted oracle source in ${DURATION} second(s)" -echo "" - -echo "Results :" - -# the following test is for automated CI -# it only works if the teeracle's whitelist is empty at the start (run it from genesis) -if [ $EVENTS_COUNT -ge $MIN_EXPECTED_NUM_OF_EVENTS ]; then - if [ 0 -eq $NO_EVENTS ]; then - echo "test passed" - exit 0 - else - echo "The test ran through but we received OracleUpdated events before the enclave was added to the whitelist. Was the enclave previously whitelisted? Perhaps by another teeracle?" - exit 1 - fi -else -echo "test failed: Not enough events received for single oracle source: $EVENTS_COUNT. Should be greater than $MIN_EXPECTED_NUM_OF_EVENTS" -exit 1 -fi - -exit 1 diff --git a/bitacross-worker/cli/demo_teeracle_whitelist.sh b/bitacross-worker/cli/demo_teeracle_whitelist.sh deleted file mode 100755 index cfe48f8545..0000000000 --- a/bitacross-worker/cli/demo_teeracle_whitelist.sh +++ /dev/null @@ -1,157 +0,0 @@ -#!/bin/bash -set -euo pipefail - -trap "echo The demo is terminated (SIGINT); exit 1" SIGINT -trap "echo The demo is terminated (SIGTERM); exit 1" SIGTERM - -# Registers a teeracle with the parentchain, and publish some oracle data. -# -# Demo to show that an enclave can update the exchange rate only when -# 1. the enclave is registered at the pallet-teerex. -# 2. and that the code used is reliable -> the enclave has been put the teeracle whitelist via a governance or sudo -# call. -# -# The teeracle's whitelist has to be empty at the start. So the script needs to run with a clean node state. -# A registered mrenclave will be added in the whitelist by a sudo account. Here //Alice -# -# setup: -# run all on localhost: -# integritee-node purge-chain --dev -# integritee-node --dev -lpallet_teeracle=debug,parity_ws=error,aura=error,sc_basic_authorship=error -# integritee-service --clean-reset run (--skip-ra --dev) -# -# then run this script -# -# usage: -# demo_teeracle_whitelist.sh -p -P -d -i -u -V -C - -while getopts ":p:P:d:i:u:V:C:" opt; do - case $opt in - p) - LITENTRY_RPC_PORT=$OPTARG - ;; - P) - WORKER_1_PORT=$OPTARG - ;; - d) - DURATION=$OPTARG - ;; - i) - INTERVAL=$OPTARG - ;; - u) - LITENTRY_RPC_URL=$OPTARG - ;; - V) - WORKER_1_URL=$OPTARG - ;; - C) - CLIENT_BIN=$OPTARG - ;; - *) - echo "invalid arg ${OPTARG}" - exit 1 - esac -done - -# using default port if none given as arguments -LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} -LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} - -WORKER_1_PORT=${WORKER_1_PORT:-2000} -WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} - -CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} - -DURATION=${DURATION:-48} -INTERVAL=${INTERVAL:-86400} - -LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD="oracle listen-to-exchange-rate-events" -ADD_TO_WHITELIST_CMD="oracle add-to-whitelist" - -echo "Using client binary ${CLIENT_BIN}" -${CLIENT_BIN} --version -echo "Using node uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" -echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" -echo "Using worker market data update interval ${INTERVAL}" -echo "Count the update events for ${DURATION} blocks" -echo "" - -COIN_GECKO="https://api.coingecko.com/" -COIN_MARKET_CAP="https://pro-api.coinmarketcap.com/" -let "MIN_EXPECTED_NUM_OF_EVENTS=$DURATION*6/$INTERVAL-3" -echo "Minimum expected number of events with a single oracle source: ${MIN_EXPECTED_NUM_OF_EVENTS}" - -let "MIN_EXPECTED_NUM_OF_EVENTS_2 = 2*$MIN_EXPECTED_NUM_OF_EVENTS" -echo "Minimum expected number of events with two oracle sources: ${MIN_EXPECTED_NUM_OF_EVENTS_2}" - -CLIENT="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_1_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_1_URL}" - -echo "* Query on-chain enclave registry:" -${CLIENT} list-workers -echo "" - -# this will always take the first MRENCLAVE found in the registry !! -read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') -echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" - -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } -echo "" - -echo "Listen to ExchangeRateUpdated events for ${DURATION} blocks. There should be no trusted oracle source!" -#${CLIENT} ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} -#echo "" - -read NO_EVENTS <<< $(${CLIENT} ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') -echo "Got ${NO_EVENTS} exchange rate updates when no trusted oracle source is in the whitelist" -echo "" - -echo "Add ${COIN_GECKO} for ${MRENCLAVE} as trusted oracle source" -${CLIENT} ${ADD_TO_WHITELIST_CMD} //Alice ${COIN_GECKO} ${MRENCLAVE} -echo "MRENCLAVE in whitelist for ${COIN_GECKO}" -echo "" - -echo "Listen to ExchangeRateUpdated events for ${DURATION} blocks, after a trusted oracle source has been added to the whitelist." -#${CLIENT} ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} -#echo "" - -read EVENTS_COUNT <<< $($CLIENT ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') -echo "Got ${EVENTS_COUNT} exchange rate updates from the trusted oracle source in ${DURATION} blocks(s)" -echo "" - -echo "Add ${COIN_MARKET_CAP} for ${MRENCLAVE} as trusted oracle source" -${CLIENT} ${ADD_TO_WHITELIST_CMD} //Alice ${COIN_MARKET_CAP} ${MRENCLAVE} -echo "MRENCLAVE in whitelist for ${COIN_MARKET_CAP}" -echo "" - -echo "Listen to ExchangeRateUpdated events for ${DURATION} blocks, after a second trusted oracle source has been added to the whitelist." -#${CLIENT} ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} -#echo "" - -read EVENTS_COUNT_2 <<< $($CLIENT ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') -echo "Got ${EVENTS_COUNT_2} exchange rate updates from 2 trusted oracle sources in ${DURATION} blocks(s)" -echo "" - -echo "Results :" - -# the following test is for automated CI -# it only works if the teeracle's whitelist is empty at the start (run it from genesis) -if [ $EVENTS_COUNT_2 -ge $MIN_EXPECTED_NUM_OF_EVENTS_2 ]; then - if [ $EVENTS_COUNT -ge $MIN_EXPECTED_NUM_OF_EVENTS ]; then - if [ 0 -eq $NO_EVENTS ]; then - echo "test passed" - exit 0 - else - echo "The test ran through but we received ExchangeRateUpdated events before the enclave was added to the whitelist. Was the enclave previously whitelisted? Perhaps by another teeracle?" - exit 1 - fi - else - echo "test failed: Not enough events received for single oracle source: $EVENTS_COUNT. Should be greater than $MIN_EXPECTED_NUM_OF_EVENTS" - exit 1 - fi -else - echo "test failed: Not enough events received for 2 oracle sources: $EVENTS_COUNT_2. Should be greater than $MIN_EXPECTED_NUM_OF_EVENTS_2" - exit 1 -fi - -exit 1 diff --git a/bitacross-worker/cli/lit_parentchain_nonce.sh b/bitacross-worker/cli/lit_parentchain_nonce.sh index 505469f11b..a8b0b0d446 100755 --- a/bitacross-worker/cli/lit_parentchain_nonce.sh +++ b/bitacross-worker/cli/lit_parentchain_nonce.sh @@ -62,7 +62,7 @@ ${CLIENT} trusted --mrenclave $MRENCLAVE --direct send-erroneous-parentchain-cal echo "" sleep 20 -# wait for 10 `ProcessedParentchainBlock` events, which should take around 2 min (1 worker) +# wait for 10 `ParentchainBlockProcessed` events, which should take around 2 min (1 worker) # if the incoming parentchain extrinsic is blocked (due to the wrong nonce), there won't be # such many events. set -e diff --git a/bitacross-worker/cli/lit_set_heartbeat_timeout.sh b/bitacross-worker/cli/lit_set_heartbeat_timeout.sh deleted file mode 100755 index f062118c0a..0000000000 --- a/bitacross-worker/cli/lit_set_heartbeat_timeout.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# Copyright 2020-2023 Trust Computing GmbH. - -while getopts ":p:A:B:u:W:V:C:" opt; do - case $opt in - p) - NPORT=$OPTARG - ;; - A) - WORKER1PORT=$OPTARG - ;; - B) - WORKER2PORT=$OPTARG - ;; - u) - NODEURL=$OPTARG - ;; - V) - WORKER1URL=$OPTARG - ;; - W) - WORKER2URL=$OPTARG - ;; - C) - CLIENT_BIN=$OPTARG - ;; - esac -done - -# Using default port if none given as arguments. -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} - -WORKER1PORT=${WORKER1PORT:-2000} -WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} - -CLIENT_BIN=${CLIENT_BIN:-"../bin/bitacross-cli"} - -LOG_FOLDER="./../log" - -echo "Using client binary $CLIENT_BIN" -echo "Using node uri $NODEURL:$NPORT" -echo "Using trusted-worker uri $WORKER1URL:$WORKER1PORT" -echo "" - -TIMEOUT=5000 # 5 seconds, smaller than 12s (the block duration) - -CLIENT="$CLIENT_BIN -p $NPORT -P $WORKER1PORT -u $NODEURL -U $WORKER1URL" -echo "CLIENT is: $CLIENT" - -echo "* Query on-chain enclave registry:" -WORKERS=$($CLIENT list-workers) -echo "WORKERS: " -echo "${WORKERS}" -echo "" - -if [ "$READMRENCLAVE" = "file" ] -then - read MRENCLAVE <<< $(cat ~/mrenclave.b58) - echo "Reading MRENCLAVE from file: ${MRENCLAVE}" -else - # This will always take the first MRENCLAVE found in the registry !! - read MRENCLAVE <<< $(echo "$WORKERS" | awk '/ MRENCLAVE: / { print $2; exit }') - echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" -fi -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } - - -# indirect call that will be sent to the parachain, it will be synchronously handled -sleep 10 -echo "* Set heartbeat timeout to $TIMEOUT" -${CLIENT} set-heartbeat-timeout "$TIMEOUT" -echo "" - -sleep 120 - -read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') -if [[ -z $MRENCLAVE ]] -then - echo "All workers removed, test passed" -else - echo "Worker(s) still exist(s), test fail" - exit 1 -fi diff --git a/bitacross-worker/cli/src/base_cli/commands/listen.rs b/bitacross-worker/cli/src/base_cli/commands/listen.rs index 27a9b15811..734ffb9af8 100644 --- a/bitacross-worker/cli/src/base_cli/commands/listen.rs +++ b/bitacross-worker/cli/src/base_cli/commands/listen.rs @@ -73,70 +73,55 @@ impl ListenCommand { }, } }, - RuntimeEvent::Teerex(ee) => { - println!(">>>>>>>>>> integritee teerex event: {:?}", ee); + RuntimeEvent::Teebag(ee) => { + println!(">>>>>>>>>> litentry teebag event: {:?}", ee); count += 1; match &ee { - my_node_runtime::pallet_teerex::Event::AddedEnclave( - accountid, + my_node_runtime::pallet_teebag::Event::EnclaveAdded { + who, + worker_type, url, - ) => { + } => { println!( - "AddedEnclave: {:?} at url {}", - accountid, + "EnclaveAdded: {:?} [{:?}] at url {}", + who, + worker_type, String::from_utf8(url.to_vec()) .unwrap_or_else(|_| "error".to_string()) ); }, - my_node_runtime::pallet_teerex::Event::RemovedEnclave( - accountid, - ) => { - println!("RemovedEnclave: {:?}", accountid); + my_node_runtime::pallet_teebag::Event::EnclaveRemoved { + who, + } => { + println!("EnclaveRemoved: {:?}", who); }, - my_node_runtime::pallet_teerex::Event::Forwarded(shard) => { + my_node_runtime::pallet_teebag::Event::OpaqueTaskPosted { shard } => { println!( - "Forwarded request for shard {}", + "OpaqueTaskPosted for shard {}", shard.encode().to_base58() ); }, - my_node_runtime::pallet_teerex::Event::ProcessedParentchainBlock( - accountid, - block_hash, - merkle_root, + my_node_runtime::pallet_teebag::Event::ParentchainBlockProcessed { + who, block_number, - ) => { + block_hash, + task_merkle_root, + } => { println!( - "ProcessedParentchainBlock from {} with hash {:?}, number {} and merkle root {:?}", - accountid, block_hash, merkle_root, block_number + "ParentchainBlockProcessed from {} with hash {:?}, number {} and merkle root {:?}", + who, block_hash, block_number, task_merkle_root ); }, - my_node_runtime::pallet_teerex::Event::ShieldFunds( - incognito_account, - ) => { - println!("ShieldFunds for {:?}", incognito_account); - }, - my_node_runtime::pallet_teerex::Event::UnshieldedFunds( - public_account, - ) => { - println!("UnshieldFunds for {:?}", public_account); - }, - _ => debug!("ignoring unsupported teerex event: {:?}", ee), - } - }, - RuntimeEvent::Sidechain(ee) => { - println!(">>>>>>>>>> integritee sidechain event: {:?}", ee); - count += 1; - match &ee { - my_node_runtime::pallet_sidechain::Event::ProposedSidechainBlock( - accountid, - block_hash, - ) => { + my_node_runtime::pallet_teebag::Event::SidechainBlockFinalized { + who, + sidechain_block_number, + } => { println!( - "ProposedSidechainBlock from {} with hash {:?}", - accountid, block_hash + "SidechainBlockFinalized from {} with number {:?}", + who, sidechain_block_number ); }, - _ => debug!("ignoring unsupported sidechain event: {:?}", ee), + _ => debug!("ignoring unsupported teebag event: {:?}", ee), } }, _ => debug!("ignoring unsupported module event: {:?}", evr.event), diff --git a/bitacross-worker/cli/src/base_cli/commands/litentry/mod.rs b/bitacross-worker/cli/src/base_cli/commands/litentry/mod.rs index b5700e1258..20182fa371 100644 --- a/bitacross-worker/cli/src/base_cli/commands/litentry/mod.rs +++ b/bitacross-worker/cli/src/base_cli/commands/litentry/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify @@ -13,5 +13,3 @@ // // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . - -pub mod set_heartbeat_timeout; diff --git a/bitacross-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs b/bitacross-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs deleted file mode 100644 index f4efb49ae7..0000000000 --- a/bitacross-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020-2023 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -use crate::{command_utils::get_chain_api, Cli}; - -use crate::{CliResult, CliResultOk}; -use itp_node_api::api_client::TEEREX; -use log::*; -use sp_keyring::AccountKeyring; -use substrate_api_client::{ac_compose_macros::compose_extrinsic, SubmitAndWatch, XtStatus}; -#[derive(Parser)] -pub struct SetHeartbeatTimeoutCommand { - /// Heartbeat timeout - timeout: u64, -} - -impl SetHeartbeatTimeoutCommand { - pub(crate) fn run(&self, cli: &Cli) -> CliResult { - let mut chain_api = get_chain_api(cli); - - // has to be //Alice as this is the genesis admin for teerex pallet, - // otherwise `set_heartbeat_timeout` call won't work - chain_api.set_signer(AccountKeyring::Alice.pair().into()); - - // call set_heartbeat_timeout - let xt = compose_extrinsic!( - chain_api, - TEEREX, - "set_heartbeat_timeout", - codec::Compact(self.timeout) - ); - - let tx_hash = chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap(); - println!( - "[+] SetHeartbeatTimeoutCommand TrustedOperation got finalized. Hash: {:?}\n", - tx_hash - ); - - Ok(CliResultOk::None) - } -} diff --git a/bitacross-worker/cli/src/base_cli/commands/mod.rs b/bitacross-worker/cli/src/base_cli/commands/mod.rs index 313a32249c..033b15b253 100644 --- a/bitacross-worker/cli/src/base_cli/commands/mod.rs +++ b/bitacross-worker/cli/src/base_cli/commands/mod.rs @@ -3,5 +3,4 @@ pub mod faucet; pub mod listen; pub mod litentry; pub mod register_tcb_info; -pub mod shield_funds; pub mod transfer; diff --git a/bitacross-worker/cli/src/base_cli/commands/register_tcb_info.rs b/bitacross-worker/cli/src/base_cli/commands/register_tcb_info.rs index 7802794a09..4ab9b55a45 100644 --- a/bitacross-worker/cli/src/base_cli/commands/register_tcb_info.rs +++ b/bitacross-worker/cli/src/base_cli/commands/register_tcb_info.rs @@ -19,7 +19,7 @@ use crate::{ command_utils::{get_chain_api, *}, Cli, CliResult, CliResultOk, }; -use itp_node_api::api_client::TEEREX; +use itp_node_api::api_client::TEEBAG; use itp_types::{parentchain::Hash, OpaqueCall}; use itp_utils::ToHexPrefixed; use log::*; @@ -106,7 +106,7 @@ impl RegisterTcbInfoCommand { let call = OpaqueCall::from_tuple(&compose_call!( chain_api.metadata(), - TEEREX, + TEEBAG, "register_tcb_info", tcb_info, intel_signature, diff --git a/bitacross-worker/cli/src/base_cli/commands/shield_funds.rs b/bitacross-worker/cli/src/base_cli/commands/shield_funds.rs deleted file mode 100644 index ec45da50fb..0000000000 --- a/bitacross-worker/cli/src/base_cli/commands/shield_funds.rs +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - command_utils::{get_accountid_from_str, get_chain_api, *}, - Cli, CliError, CliResult, CliResultOk, -}; -use base58::FromBase58; -use codec::{Decode, Encode}; -use itp_node_api::api_client::TEEREX; -use itp_sgx_crypto::ShieldingCryptoEncrypt; -use itp_stf_primitives::types::ShardIdentifier; -use litentry_primitives::ParentchainBalance as Balance; -use log::*; -use sp_core::sr25519 as sr25519_core; -use substrate_api_client::{ac_compose_macros::compose_extrinsic, SubmitAndWatch, XtStatus}; - -#[derive(Parser)] -pub struct ShieldFundsCommand { - /// Sender's parentchain AccountId in ss58check format. - from: String, - /// Recipient's incognito AccountId in ss58check format. - to: String, - /// Amount to be transferred. - amount: Balance, - /// Shard identifier. - shard: String, -} - -impl ShieldFundsCommand { - pub(crate) fn run(&self, cli: &Cli) -> CliResult { - let mut chain_api = get_chain_api(cli); - - let shard_opt = match self.shard.from_base58() { - Ok(s) => ShardIdentifier::decode(&mut &s[..]), - _ => panic!("shard argument must be base58 encoded"), - }; - - let shard = match shard_opt { - Ok(shard) => shard, - Err(e) => panic!("{}", e), - }; - - // Get the sender. - let from = get_pair_from_str(&self.from); - chain_api.set_signer(sr25519_core::Pair::from(from).into()); - - // Get the recipient. - let to = get_accountid_from_str(&self.to); - - let encryption_key = get_shielding_key(cli).unwrap(); - let encrypted_recevier = encryption_key.encrypt(&to.encode()).unwrap(); - - // Compose the extrinsic. - let xt = compose_extrinsic!( - chain_api, - TEEREX, - "shield_funds", - encrypted_recevier, - self.amount, - shard - ); - - match chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized) { - Ok(xt_report) => { - println!( - "[+] shield funds success. extrinsic hash: {:?} / status: {:?} / block hash: {:?}", - xt_report.extrinsic_hash, xt_report.status, xt_report.block_hash.unwrap() - ); - Ok(CliResultOk::H256 { hash: xt_report.block_hash.unwrap() }) - }, - Err(e) => { - error!("shield_funds extrinsic failed {:?}", e); - Err(CliError::Extrinsic { msg: format!("{:?}", e) }) - }, - } - } -} diff --git a/bitacross-worker/cli/src/base_cli/mod.rs b/bitacross-worker/cli/src/base_cli/mod.rs index 9ba67f94f7..d74d538f2f 100644 --- a/bitacross-worker/cli/src/base_cli/mod.rs +++ b/bitacross-worker/cli/src/base_cli/mod.rs @@ -18,9 +18,7 @@ use crate::{ base_cli::commands::{ balance::BalanceCommand, faucet::FaucetCommand, listen::ListenCommand, - litentry::set_heartbeat_timeout::SetHeartbeatTimeoutCommand, - register_tcb_info::RegisterTcbInfoCommand, shield_funds::ShieldFundsCommand, - transfer::TransferCommand, + register_tcb_info::RegisterTcbInfoCommand, transfer::TransferCommand, }, command_utils::*, Cli, CliResult, CliResultOk, ED25519_KEY_TYPE, SR25519_KEY_TYPE, @@ -29,7 +27,8 @@ use base58::ToBase58; use chrono::{DateTime, Utc}; use clap::Subcommand; use itc_rpc_client::direct_client::DirectApi; -use itp_node_api::api_client::PalletTeerexApi; +use itp_node_api::api_client::PalletTeebagApi; +use itp_types::WorkerType; use sp_core::crypto::Ss58Codec; use sp_keystore::Keystore; use std::{ @@ -72,17 +71,11 @@ pub enum BaseCommand { /// Register TCB info for FMSPC RegisterTcbInfo(RegisterTcbInfoCommand), - /// Transfer funds from an parentchain account to an incognito account - ShieldFunds(ShieldFundsCommand), - // Litentry's commands below /// query sgx-runtime metadata and print the raw (hex-encoded) metadata to stdout /// we could have added a parameter like `--raw` to `PrintSgxMetadata`, but /// we want to keep our changes isolated PrintSgxMetadataRaw, - - /// set heartbeat timeout storage - SetHeartbeatTimeout(SetHeartbeatTimeoutCommand), } impl BaseCommand { @@ -98,10 +91,8 @@ impl BaseCommand { BaseCommand::ListWorkers => list_workers(cli), BaseCommand::Listen(cmd) => cmd.run(cli), BaseCommand::RegisterTcbInfo(cmd) => cmd.run(cli), - BaseCommand::ShieldFunds(cmd) => cmd.run(cli), // Litentry's commands below BaseCommand::PrintSgxMetadataRaw => print_sgx_metadata_raw(cli), - BaseCommand::SetHeartbeatTimeout(cmd) => cmd.run(cli), } } } @@ -164,29 +155,22 @@ fn print_sgx_metadata_raw(cli: &Cli) -> CliResult { fn list_workers(cli: &Cli) -> CliResult { let api = get_chain_api(cli); - let wcount = api.enclave_count(None).unwrap(); - println!("number of workers registered: {}", wcount); - - let mut mr_enclaves = Vec::with_capacity(wcount as usize); - - for w in 1..=wcount { - let enclave = api.enclave(w, None).unwrap(); - if enclave.is_none() { - println!("error reading enclave data"); - continue - }; - let enclave = enclave.unwrap(); - let timestamp = - DateTime::::from(UNIX_EPOCH + Duration::from_millis(enclave.timestamp)); - let mr_enclave = enclave.mr_enclave.to_base58(); - println!("Enclave {}", w); - println!(" AccountId: {}", enclave.pubkey.to_ss58check()); - println!(" MRENCLAVE: {}", mr_enclave); - println!(" RA timestamp: {}", timestamp); - println!(" URL: {}", enclave.url); - - mr_enclaves.push(mr_enclave); - } + let enclaves = api.all_enclaves(WorkerType::BitAcross, None).unwrap(); + println!("number of enclaves registered: {}", enclaves.len()); + + let mr_enclaves = enclaves + .iter() + .map(|enclave| { + println!("Enclave"); + println!(" MRENCLAVE: {}", enclave.mrenclave.to_base58()); + let timestamp = DateTime::::from( + UNIX_EPOCH + Duration::from_millis(enclave.last_seen_timestamp), + ); + println!(" Last seen: {}", timestamp); + println!(" URL: {}", String::from_utf8_lossy(enclave.url.as_slice())); + enclave.mrenclave.to_base58() + }) + .collect(); Ok(CliResultOk::MrEnclaveBase58 { mr_enclaves }) } diff --git a/bitacross-worker/cli/src/commands.rs b/bitacross-worker/cli/src/commands.rs index e01a79d930..17b5ea42c4 100644 --- a/bitacross-worker/cli/src/commands.rs +++ b/bitacross-worker/cli/src/commands.rs @@ -19,9 +19,6 @@ extern crate chrono; use crate::{base_cli::BaseCommand, trusted_cli::TrustedCli, Cli, CliResult, CliResultOk}; use clap::Subcommand; -#[cfg(feature = "teeracle")] -use crate::oracle::OracleCommand; - use crate::attesteer::AttesteerCommand; #[derive(Subcommand)] @@ -33,11 +30,6 @@ pub enum Commands { #[clap(after_help = "stf subcommands depend on the stf crate this has been built against")] Trusted(TrustedCli), - /// Subcommands for the oracle. - #[cfg(feature = "teeracle")] - #[clap(subcommand)] - Oracle(OracleCommand), - /// Subcommand for the attesteer. #[clap(subcommand)] Attesteer(AttesteerCommand), @@ -47,11 +39,6 @@ pub fn match_command(cli: &Cli) -> CliResult { match &cli.command { Commands::Base(cmd) => cmd.run(cli), Commands::Trusted(trusted_cli) => trusted_cli.run(cli), - #[cfg(feature = "teeracle")] - Commands::Oracle(cmd) => { - cmd.run(cli); - Ok(CliResultOk::None) - }, Commands::Attesteer(cmd) => { cmd.run(cli); Ok(CliResultOk::None) diff --git a/bitacross-worker/cli/src/evm/commands/evm_call.rs b/bitacross-worker/cli/src/evm/commands/evm_call.rs deleted file mode 100644 index 04a7b56879..0000000000 --- a/bitacross-worker/cli/src/evm/commands/evm_call.rs +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - get_layer_two_evm_nonce, get_layer_two_nonce, - trusted_cli::TrustedCli, - trusted_command_utils::{get_identifiers, get_pair_from_str}, - trusted_operation::perform_trusted_operation, - Cli, CliResult, CliResultOk, -}; -use ita_stf::{Index, TrustedCall, TrustedGetter}; -use itp_stf_primitives::{ - traits::TrustedCallSigning, - types::{KeyPair, TrustedOperation}, -}; -use itp_types::AccountId; -use log::*; -use sp_core::{crypto::Ss58Codec, Pair, H160, U256}; -use std::{boxed::Box, vec::Vec}; -#[derive(Parser)] -pub struct EvmCallCommands { - /// Sender's incognito AccountId in ss58check format - from: String, - - /// Execution address of the smart contract - execution_address: String, - - /// Function hash - function: String, -} - -impl EvmCallCommands { - pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { - let sender = get_pair_from_str(trusted_args, &self.from, cli); - let sender_acc: AccountId = sender.public().into(); - - info!("senders ss58 is {}", sender.public().to_ss58check()); - - let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; - sender_evm_acc_slice - .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); - let sender_evm_acc: H160 = sender_evm_acc_slice.into(); - - info!("senders evm account is {}", sender_evm_acc); - - let execution_address = - H160::from_slice(&array_bytes::hex2bytes(&self.execution_address).unwrap()); - - let function_hash = array_bytes::hex2bytes(&self.function).unwrap(); - - let (mrenclave, shard) = get_identifiers(trusted_args, cli); - let nonce = get_layer_two_nonce!(sender, cli, trusted_args); - let evm_nonce = get_layer_two_evm_nonce!(sender, cli, trusted_args); - - println!("calling smart contract function"); - let function_call = TrustedCall::evm_call( - sender_acc.into(), - sender_evm_acc, - execution_address, - function_hash, - U256::from(0), - 10_000_000, // gas limit - U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime - None, - Some(U256::from(evm_nonce)), - Vec::new(), - ) - .sign(&KeyPair::Sr25519(Box::new(sender)), nonce, &mrenclave, &shard) - .into_trusted_operation(trusted_args.direct); - Ok(perform_trusted_operation::<()>(cli, trusted_args, &function_call) - .map(|_| CliResultOk::None)?) - } -} diff --git a/bitacross-worker/cli/src/evm/commands/evm_command_utils.rs b/bitacross-worker/cli/src/evm/commands/evm_command_utils.rs deleted file mode 100644 index cc8c5fff34..0000000000 --- a/bitacross-worker/cli/src/evm/commands/evm_command_utils.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[macro_export] -macro_rules! get_layer_two_evm_nonce { - ($signer_pair:ident, $cli:ident, $trusted_args:ident ) => {{ - use ita_stf::{Getter, TrustedCallSigned}; - - let top = TrustedOperation::::get(Getter::trusted( - TrustedGetter::evm_nonce($signer_pair.public().into()) - .sign(&KeyPair::Sr25519(Box::new($signer_pair.clone()))), - )); - let res = perform_trusted_operation::($cli, $trusted_args, &top); - let nonce = res.ok().unwrap_or(0); - debug!("got evm nonce: {:?}", nonce); - nonce - }}; -} diff --git a/bitacross-worker/cli/src/evm/commands/evm_create.rs b/bitacross-worker/cli/src/evm/commands/evm_create.rs deleted file mode 100644 index acce77e3e5..0000000000 --- a/bitacross-worker/cli/src/evm/commands/evm_create.rs +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - get_layer_two_evm_nonce, get_layer_two_nonce, - trusted_cli::TrustedCli, - trusted_command_utils::{get_identifiers, get_pair_from_str}, - trusted_operation::perform_trusted_operation, - Cli, CliResult, CliResultOk, -}; -use ita_stf::{evm_helpers::evm_create_address, Index, TrustedCall, TrustedGetter}; -use itp_stf_primitives::{ - traits::TrustedCallSigning, - types::{KeyPair, TrustedOperation}, -}; -use itp_types::AccountId; -use log::*; -use pallet_evm::{AddressMapping, HashedAddressMapping}; -use sp_core::{crypto::Ss58Codec, Pair, H160, U256}; -use sp_runtime::traits::BlakeTwo256; -use std::vec::Vec; -#[derive(Parser)] -pub struct EvmCreateCommands { - /// Sender's incognito AccountId in ss58check format - from: String, - - /// Smart Contract in Hex format - smart_contract: String, -} - -impl EvmCreateCommands { - pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { - let from = get_pair_from_str(trusted_args, &self.from, cli); - let from_acc: AccountId = from.public().into(); - println!("from ss58 is {}", from.public().to_ss58check()); - - let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; - sender_evm_acc_slice - .copy_from_slice((<[u8; 32]>::from(from_acc.clone())).get(0..20).unwrap()); - let sender_evm_acc: H160 = sender_evm_acc_slice.into(); - - let (mrenclave, shard) = get_identifiers(trusted_args, cli); - - let sender_evm_substrate_addr = - HashedAddressMapping::::into_account_id(sender_evm_acc); - println!( - "Trying to get nonce of evm account {:?}", - sender_evm_substrate_addr.to_ss58check() - ); - - let nonce = get_layer_two_nonce!(from, cli, trusted_args); - let evm_account_nonce = get_layer_two_evm_nonce!(from, cli, trusted_args); - - let top = TrustedCall::evm_create( - from_acc.into(), - sender_evm_acc, - array_bytes::hex2bytes(&self.smart_contract).unwrap().to_vec(), - U256::from(0), - 967295, // gas limit - U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime - None, - None, - Vec::new(), - ) - .sign(&from.into(), nonce, &mrenclave, &shard) - .into_trusted_operation(trusted_args.direct); - - perform_trusted_operation::<()>(cli, trusted_args, &top)?; - - let execution_address = evm_create_address(sender_evm_acc, evm_account_nonce); - info!("trusted call evm_create executed"); - println!("Created the smart contract with address {:?}", execution_address); - Ok(CliResultOk::H160 { hash: execution_address }) - } -} diff --git a/bitacross-worker/cli/src/evm/commands/evm_read.rs b/bitacross-worker/cli/src/evm/commands/evm_read.rs deleted file mode 100644 index b863533860..0000000000 --- a/bitacross-worker/cli/src/evm/commands/evm_read.rs +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - trusted_cli::TrustedCli, trusted_command_utils::get_pair_from_str, - trusted_operation::perform_trusted_operation, Cli, CliError, CliResult, CliResultOk, -}; -use ita_stf::{Getter, TrustedCallSigned, TrustedGetter}; -use itp_stf_primitives::types::{KeyPair, TrustedOperation}; -use itp_types::AccountId; -use log::*; -use sp_core::{crypto::Ss58Codec, Pair, H160, H256}; - -#[derive(Parser)] -pub struct EvmReadCommands { - /// Sender's incognito AccountId in ss58check format - from: String, - - /// Execution address of the smart contract - execution_address: String, -} - -impl EvmReadCommands { - pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { - let sender = get_pair_from_str(trusted_args, &self.from, cli); - let sender_acc: AccountId = sender.public().into(); - - info!("senders ss58 is {}", sender.public().to_ss58check()); - - let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; - sender_evm_acc_slice - .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); - let sender_evm_acc: H160 = sender_evm_acc_slice.into(); - - info!("senders evm account is {}", sender_evm_acc); - - let execution_address = - H160::from_slice(&array_bytes::hex2bytes(&self.execution_address).unwrap()); - - let top = TrustedOperation::::get(Getter::trusted( - TrustedGetter::evm_account_storages(sender_acc.into(), execution_address, H256::zero()) - .sign(&KeyPair::Sr25519(Box::new(sender))), - )); - match perform_trusted_operation::(cli, trusted_args, &top) { - Ok(hash) => { - println!("{:?}", hash); - Ok(CliResultOk::H256 { hash }) - }, - Err(e) => { - error!("Nothing in state! Reason: {:?} !", e); - Err(CliError::EvmRead { msg: "Nothing in state!".to_string() }) - }, - } - } -} diff --git a/bitacross-worker/cli/src/evm/commands/mod.rs b/bitacross-worker/cli/src/evm/commands/mod.rs deleted file mode 100644 index 014b093832..0000000000 --- a/bitacross-worker/cli/src/evm/commands/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod evm_call; -pub mod evm_command_utils; -pub mod evm_create; -pub mod evm_read; - -pub use crate::get_layer_two_evm_nonce; diff --git a/bitacross-worker/cli/src/evm/mod.rs b/bitacross-worker/cli/src/evm/mod.rs deleted file mode 100644 index 0b1ff31d47..0000000000 --- a/bitacross-worker/cli/src/evm/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - evm::commands::{ - evm_call::EvmCallCommands, evm_create::EvmCreateCommands, evm_read::EvmReadCommands, - }, - trusted_cli::TrustedCli, - Cli, CliResult, -}; - -mod commands; - -#[allow(clippy::enum_variant_names)] -#[derive(Subcommand)] -pub enum EvmCommand { - /// Create smart contract - EvmCreate(EvmCreateCommands), - - /// Read smart contract storage - EvmRead(EvmReadCommands), - - /// Create smart contract - EvmCall(EvmCallCommands), -} - -impl EvmCommand { - pub fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { - match self { - EvmCommand::EvmCreate(cmd) => cmd.run(cli, trusted_args), - EvmCommand::EvmRead(cmd) => cmd.run(cli, trusted_args), - EvmCommand::EvmCall(cmd) => cmd.run(cli, trusted_args), - } - } -} diff --git a/bitacross-worker/cli/src/lib.rs b/bitacross-worker/cli/src/lib.rs index 0738cc6dd4..16fb72fd42 100644 --- a/bitacross-worker/cli/src/lib.rs +++ b/bitacross-worker/cli/src/lib.rs @@ -33,10 +33,6 @@ mod base_cli; mod benchmark; mod command_utils; mod error; -#[cfg(feature = "evm")] -mod evm; -#[cfg(feature = "teeracle")] -mod oracle; mod trusted_base_cli; mod trusted_cli; mod trusted_command_utils; @@ -48,7 +44,7 @@ use crate::commands::Commands; use clap::Parser; use itp_node_api::api_client::Metadata; use sp_application_crypto::KeyTypeId; -use sp_core::{H160, H256}; +use sp_core::H256; use thiserror::Error; const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -61,9 +57,6 @@ pub(crate) const ED25519_KEY_TYPE: KeyTypeId = KeyTypeId(*b"ed25"); #[clap(version = VERSION)] #[clap(author = "Trust Computing GmbH ")] #[clap(about = "cli tool to interact with litentry-parachain and workers", long_about = None)] -#[cfg_attr(feature = "teeracle", clap(about = "interact with litentry-parachain and teeracle", long_about = None))] -#[cfg_attr(feature = "sidechain", clap(about = "interact with litentry-parachain and sidechain", long_about = None))] -#[cfg_attr(feature = "offchain-worker", clap(about = "interact with litentry-parachain and offchain-worker", long_about = None))] #[clap(after_help = "stf subcommands depend on the stf crate this has been built against")] pub struct Cli { /// node url @@ -87,26 +80,11 @@ pub struct Cli { } pub enum CliResultOk { - PubKeysBase58 { - pubkeys_sr25519: Option>, - pubkeys_ed25519: Option>, - }, - Balance { - balance: u128, - }, - MrEnclaveBase58 { - mr_enclaves: Vec, - }, - Metadata { - metadata: Metadata, - }, - H256 { - hash: H256, - }, - /// Result of "EvmCreateCommands": execution_address - H160 { - hash: H160, - }, + PubKeysBase58 { pubkeys_sr25519: Option>, pubkeys_ed25519: Option> }, + Balance { balance: u128 }, + MrEnclaveBase58 { mr_enclaves: Vec }, + Metadata { metadata: Metadata }, + H256 { hash: H256 }, // TODO should ideally be removed; or at least drastically less used // We WANT all commands exposed by the cli to return something useful for the caller(ie instead of printing) None, @@ -118,8 +96,6 @@ pub enum CliError { Extrinsic { msg: String }, #[error("trusted operation error: {:?}", msg)] TrustedOp { msg: String }, - #[error("EvmReadCommands error: {:?}", msg)] - EvmRead { msg: String }, #[error("worker rpc api error: {:?}", msg)] WorkerRpcApi { msg: String }, } diff --git a/bitacross-worker/cli/src/oracle/commands/add_to_whitelist.rs b/bitacross-worker/cli/src/oracle/commands/add_to_whitelist.rs deleted file mode 100644 index 98afeb801d..0000000000 --- a/bitacross-worker/cli/src/oracle/commands/add_to_whitelist.rs +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - command_utils::{get_chain_api, get_pair_from_str, mrenclave_from_base58}, - Cli, -}; -use itp_node_api::api_client::{ADD_TO_WHITELIST, TEERACLE}; -use substrate_api_client::{ - ac_compose_macros::{compose_call, compose_extrinsic}, - SubmitAndWatch, XtStatus, -}; - -/// Add a trusted market data source to the on-chain whitelist. -#[derive(Debug, Clone, Parser)] -pub struct AddToWhitelistCmd { - /// Sender's on-chain AccountId in ss58check format. - /// - /// It has to be a sudo account. - from: String, - - /// Market data URL - source: String, - - /// MRENCLAVE of the oracle worker base58 encoded. - mrenclave: String, -} - -impl AddToWhitelistCmd { - pub fn run(&self, cli: &Cli) { - let mut api = get_chain_api(cli); - let mrenclave = mrenclave_from_base58(&self.mrenclave); - let from = get_pair_from_str(&self.from); - - let market_data_source = self.source.clone(); - - api.set_signer(from.into()); - - let call = compose_call!( - api.metadata(), - TEERACLE, - ADD_TO_WHITELIST, - market_data_source, - mrenclave - ); - - // compose the extrinsic - let xt = compose_extrinsic!(api, "Sudo", "sudo", call); - - let report = api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap(); - println!("[+] Add to whitelist got finalized. Hash: {:?}\n", report.extrinsic_hash); - } -} diff --git a/bitacross-worker/cli/src/oracle/commands/listen_to_exchange.rs b/bitacross-worker/cli/src/oracle/commands/listen_to_exchange.rs deleted file mode 100644 index 181be4febd..0000000000 --- a/bitacross-worker/cli/src/oracle/commands/listen_to_exchange.rs +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{command_utils::get_chain_api, Cli}; -use itp_node_api::api_client::ParentchainApi; -use itp_time_utils::{duration_now, remaining_time}; -use log::{debug, info, trace}; -use my_node_runtime::{Hash, RuntimeEvent}; -use std::time::Duration; -use substrate_api_client::SubscribeEvents; - -/// Listen to exchange rate events. -#[derive(Debug, Clone, Parser)] -pub struct ListenToExchangeRateEventsCmd { - /// Listen for `duration` in seconds. - duration: u64, -} - -impl ListenToExchangeRateEventsCmd { - pub fn run(&self, cli: &Cli) { - let api = get_chain_api(cli); - let duration = Duration::from_secs(self.duration); - - let count = count_exchange_rate_update_events(&api, duration); - - println!("Number of ExchangeRateUpdated events received : "); - println!(" EVENTS_COUNT: {}", count); - } -} - -pub fn count_exchange_rate_update_events(api: &ParentchainApi, duration: Duration) -> u32 { - let stop = duration_now() + duration; - - //subscribe to events - let mut subscription = api.subscribe_events().unwrap(); - let mut count = 0; - - while remaining_time(stop).unwrap_or_default() > Duration::ZERO { - let events_result = subscription.next_events::().unwrap(); - if let Ok(events) = events_result { - for event_record in &events { - info!("received event {:?}", event_record.event); - if let RuntimeEvent::Teeracle(event) = &event_record.event { - match &event { - my_node_runtime::pallet_teeracle::Event::ExchangeRateUpdated( - data_source, - trading_pair, - exchange_rate, - ) => { - count += 1; - debug!("Received ExchangeRateUpdated event"); - println!( - "ExchangeRateUpdated: TRADING_PAIR : {}, SRC : {}, VALUE :{:?}", - trading_pair, data_source, exchange_rate - ); - }, - _ => trace!("ignoring teeracle event: {:?}", event), - } - } - } - } - } - debug!("Received {} ExchangeRateUpdated event(s) in total", count); - count -} diff --git a/bitacross-worker/cli/src/oracle/commands/listen_to_oracle.rs b/bitacross-worker/cli/src/oracle/commands/listen_to_oracle.rs deleted file mode 100644 index 87cc334040..0000000000 --- a/bitacross-worker/cli/src/oracle/commands/listen_to_oracle.rs +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{command_utils::get_chain_api, Cli}; -use itp_node_api::api_client::ParentchainApi; -use itp_time_utils::{duration_now, remaining_time}; -use log::{debug, info}; -use my_node_runtime::{Hash, RuntimeEvent}; -use std::time::Duration; -use substrate_api_client::{ac_node_api::EventRecord, SubscribeEvents}; - -/// Listen to exchange rate events. -#[derive(Debug, Clone, Parser)] -pub struct ListenToOracleEventsCmd { - /// Listen for `duration` in seconds. - duration: u64, -} - -type EventCount = u32; -type Event = EventRecord; - -impl ListenToOracleEventsCmd { - pub fn run(&self, cli: &Cli) { - let api = get_chain_api(cli); - let duration = Duration::from_secs(self.duration); - let count = count_oracle_update_events(&api, duration); - println!("Number of Oracle events received : "); - println!(" EVENTS_COUNT: {}", count); - } -} - -fn count_oracle_update_events(api: &ParentchainApi, duration: Duration) -> EventCount { - let stop = duration_now() + duration; - - //subscribe to events - let mut subscription = api.subscribe_events().unwrap(); - let mut count = 0; - - while remaining_time(stop).unwrap_or_default() > Duration::ZERO { - let events_result = subscription.next_events::(); - let event_count = match events_result { - Some(Ok(event_records)) => { - debug!("Could not successfully decode event_bytes {:?}", event_records); - report_event_count(event_records) - }, - _ => 0, - }; - count += event_count; - } - debug!("Received {} ExchangeRateUpdated event(s) in total", count); - count -} - -fn report_event_count(event_records: Vec) -> EventCount { - let mut count = 0; - event_records.iter().for_each(|event_record| { - info!("received event {:?}", event_record.event); - if let RuntimeEvent::Teeracle(event) = &event_record.event { - match &event { - my_node_runtime::pallet_teeracle::Event::OracleUpdated( - oracle_data_name, - data_source, - ) => { - count += 1; - debug!("Received OracleUpdated event"); - println!( - "OracleUpdated: ORACLE_NAME : {}, SRC : {}", - oracle_data_name, data_source - ); - }, - // Can just remove this and ignore handling this case - _ => debug!("ignoring teeracle event: {:?}", event), - } - } - }); - count -} diff --git a/bitacross-worker/cli/src/oracle/commands/mod.rs b/bitacross-worker/cli/src/oracle/commands/mod.rs deleted file mode 100644 index 22b0a326c6..0000000000 --- a/bitacross-worker/cli/src/oracle/commands/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -mod add_to_whitelist; -mod listen_to_exchange; -mod listen_to_oracle; - -pub use self::{ - add_to_whitelist::AddToWhitelistCmd, listen_to_exchange::ListenToExchangeRateEventsCmd, - listen_to_oracle::ListenToOracleEventsCmd, -}; diff --git a/bitacross-worker/cli/src/oracle/mod.rs b/bitacross-worker/cli/src/oracle/mod.rs deleted file mode 100644 index e12f117cd4..0000000000 --- a/bitacross-worker/cli/src/oracle/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Add cli commands for the oracle -//! -//! Todo: This shall be a standalone crate in app-libs/oracle. However, this needs: -//! https://github.com/integritee-network/worker/issues/852 - -use crate::Cli; -use commands::{AddToWhitelistCmd, ListenToExchangeRateEventsCmd, ListenToOracleEventsCmd}; - -mod commands; - -/// Oracle subcommands for the cli. -#[derive(Debug, clap::Subcommand)] -pub enum OracleCommand { - /// Add a market source to the teeracle's whitelist. - AddToWhitelist(AddToWhitelistCmd), - - /// Listen to exchange rate events - ListenToExchangeRateEvents(ListenToExchangeRateEventsCmd), - - /// Listen to all oracles event updates - ListenToOracleEvents(ListenToOracleEventsCmd), -} - -impl OracleCommand { - pub fn run(&self, cli: &Cli) { - match self { - OracleCommand::AddToWhitelist(cmd) => cmd.run(cli), - OracleCommand::ListenToExchangeRateEvents(cmd) => cmd.run(cli), - OracleCommand::ListenToOracleEvents(cmd) => cmd.run(cli), - } - } -} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/direct_call_sign_bitcoin.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/direct_call_sign_bitcoin.rs new file mode 100644 index 0000000000..4cfddb4982 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/direct_call_sign_bitcoin.rs @@ -0,0 +1,57 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{ + trusted_base_cli::commands::bitacross::utils::{random_aes_key, send_direct_request}, + trusted_cli::TrustedCli, + trusted_command_utils::{get_identifiers, get_pair_from_str}, + Cli, CliResult, CliResultOk, +}; +use itp_rpc::{RpcResponse, RpcReturnValue}; +use itp_stf_primitives::types::KeyPair; +use itp_utils::FromHexPrefixed; +use lc_direct_call::DirectCall; +use sp_core::Pair; + +#[derive(Parser)] +pub struct RequestDirectCallSignBitcoinCommand { + payload: Vec, +} + +impl RequestDirectCallSignBitcoinCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_cli: &TrustedCli) -> CliResult { + let alice = get_pair_from_str(trusted_cli, "//Alice", cli); + let (mrenclave, shard) = get_identifiers(trusted_cli, cli); + let key: [u8; 32] = random_aes_key(); + + let dc = DirectCall::SignBitcoin(alice.public().into(), key, self.payload.clone()).sign( + &KeyPair::Sr25519(Box::new(alice)), + &mrenclave, + &shard, + ); + + let result: String = send_direct_request(cli, trusted_cli, dc, key).unwrap(); + let response: RpcResponse = serde_json::from_str(&result).unwrap(); + if let Ok(return_value) = RpcReturnValue::from_hex(&response.result) { + println!("Got return value: {:?}", return_value); + } else { + println!("Could not decode return value: {:?}", response.result); + } + println!("Got result: {:?}", result); + + Ok(CliResultOk::None) + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/direct_call_sign_ethereum.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/direct_call_sign_ethereum.rs new file mode 100644 index 0000000000..ebd5568e17 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/direct_call_sign_ethereum.rs @@ -0,0 +1,59 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{ + trusted_base_cli::commands::bitacross::utils::{random_aes_key, send_direct_request}, + trusted_cli::TrustedCli, + trusted_command_utils::{get_identifiers, get_pair_from_str}, + Cli, CliResult, CliResultOk, +}; +use itp_rpc::{RpcResponse, RpcReturnValue}; +use itp_stf_primitives::types::KeyPair; +use itp_utils::FromHexPrefixed; +use lc_direct_call::{DirectCall, PrehashedEthereumMessage}; +use sp_core::Pair; + +#[derive(Parser)] +pub struct RequestDirectCallSignEthereumCommand { + payload: Vec, +} + +impl RequestDirectCallSignEthereumCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_cli: &TrustedCli) -> CliResult { + let alice = get_pair_from_str(trusted_cli, "//Alice", cli); + let (mrenclave, shard) = get_identifiers(trusted_cli, cli); + let key: [u8; 32] = random_aes_key(); + let msg: PrehashedEthereumMessage = + self.payload.clone().try_into().expect("Unable to convert payload to [u8; 32]"); + + let dc = DirectCall::SignEthereum(alice.public().into(), key, msg).sign( + &KeyPair::Sr25519(Box::new(alice)), + &mrenclave, + &shard, + ); + + let result: String = send_direct_request(cli, trusted_cli, dc, key).unwrap(); + let response: RpcResponse = serde_json::from_str(&result).unwrap(); + if let Ok(return_value) = RpcReturnValue::from_hex(&response.result) { + println!("Got return value: {:?}", return_value); + } else { + println!("Could not decode return value: {:?}", response.result); + } + println!("Got result: {:?}", result); + + Ok(CliResultOk::None) + } +} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/peer_updater_mock.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/mod.rs similarity index 73% rename from bitacross-worker/enclave-runtime/src/test/mocks/peer_updater_mock.rs rename to bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/mod.rs index 63a60108df..149e066e59 100644 --- a/bitacross-worker/enclave-runtime/src/test/mocks/peer_updater_mock.rs +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify @@ -14,11 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use itc_peer_top_broadcaster::PeerUpdater; -use sgx_tstd::{string::String, vec::Vec}; +pub mod direct_call_sign_bitcoin; +pub mod direct_call_sign_ethereum; -pub struct PeerUpdaterMock {} - -impl PeerUpdater for PeerUpdaterMock { - fn update(&self, _peers: Vec) {} -} +pub mod utils; diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/utils.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/utils.rs new file mode 100644 index 0000000000..768a3b3fda --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/bitacross/utils.rs @@ -0,0 +1,68 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{ + command_utils::{get_shielding_key, get_worker_api_direct}, + trusted_cli::TrustedCli, + trusted_operation::read_shard, + Cli, +}; +use codec::Encode; +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{Id, RpcRequest}; +use itp_sgx_crypto::ShieldingCryptoEncrypt; +use itp_utils::ToHexPrefixed; +use lc_direct_call::DirectCallSigned; +use litentry_primitives::{ + aes_encrypt_default, AesRequest, RequestAesKey, ShardIdentifier, REQUEST_AES_KEY_LEN, +}; + +pub fn random_aes_key() -> RequestAesKey { + let random: Vec = (0..REQUEST_AES_KEY_LEN).map(|_| rand::random::()).collect(); + random[0..REQUEST_AES_KEY_LEN].try_into().unwrap() +} + +pub fn send_direct_request( + cli: &Cli, + trusted_args: &TrustedCli, + call: DirectCallSigned, + key: RequestAesKey, +) -> Result { + let encryption_key = get_shielding_key(cli).unwrap(); + let shard = read_shard(trusted_args, cli).unwrap(); + let jsonrpc_call: String = get_bitacross_json_request(shard, call, encryption_key, key); + let direct_api = get_worker_api_direct(cli); + direct_api.get(&jsonrpc_call).map_err(|e| e.to_string()) +} + +pub fn get_bitacross_json_request( + shard: ShardIdentifier, + call: DirectCallSigned, + shielding_pubkey: sgx_crypto_helper::rsa3072::Rsa3072PubKey, + key: RequestAesKey, +) -> String { + let encrypted_key = shielding_pubkey.encrypt(&key).unwrap(); + let encrypted_top = aes_encrypt_default(&key, &call.encode()); + + // compose jsonrpc call + let request = AesRequest { shard, key: encrypted_key, payload: encrypted_top }; + RpcRequest::compose_jsonrpc_call( + Id::Number(1), + "bitacross_submitRequest".to_string(), + vec![request.to_hex()], + ) + .unwrap() +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/mod.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/mod.rs index 0687a4fe1d..f4edfe02ef 100644 --- a/bitacross-worker/cli/src/trusted_base_cli/commands/mod.rs +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/mod.rs @@ -1,4 +1,5 @@ pub mod balance; +pub mod bitacross; pub mod get_shard; pub mod get_shard_vault; pub mod nonce; diff --git a/bitacross-worker/cli/src/trusted_base_cli/mod.rs b/bitacross-worker/cli/src/trusted_base_cli/mod.rs index e964e1f3df..0297923847 100644 --- a/bitacross-worker/cli/src/trusted_base_cli/mod.rs +++ b/bitacross-worker/cli/src/trusted_base_cli/mod.rs @@ -17,8 +17,16 @@ use crate::{ trusted_base_cli::commands::{ - balance::BalanceCommand, get_shard::GetShardCommand, get_shard_vault::GetShardVaultCommand, - nonce::NonceCommand, set_balance::SetBalanceCommand, transfer::TransferCommand, + balance::BalanceCommand, + bitacross::{ + direct_call_sign_bitcoin::RequestDirectCallSignBitcoinCommand, + direct_call_sign_ethereum::RequestDirectCallSignEthereumCommand, + }, + get_shard::GetShardCommand, + get_shard_vault::GetShardVaultCommand, + nonce::NonceCommand, + set_balance::SetBalanceCommand, + transfer::TransferCommand, unshield_funds::UnshieldFundsCommand, }, trusted_cli::TrustedCli, @@ -61,6 +69,12 @@ pub enum TrustedBaseCommand { /// get shard vault for shielding (if defined for this worker) GetShardVault(GetShardVaultCommand), + + /// sign bitcoin transaction using custodian wallet + RequestDirectCallSignBitcoin(RequestDirectCallSignBitcoinCommand), + + /// sign ethereum transaction using custodian wallet + RequestDirectCallSignEthereum(RequestDirectCallSignEthereumCommand), } impl TrustedBaseCommand { @@ -75,6 +89,8 @@ impl TrustedBaseCommand { TrustedBaseCommand::Nonce(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::GetShard(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::GetShardVault(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::RequestDirectCallSignBitcoin(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::RequestDirectCallSignEthereum(cmd) => cmd.run(cli, trusted_cli), } } } diff --git a/bitacross-worker/cli/src/trusted_cli.rs b/bitacross-worker/cli/src/trusted_cli.rs index 5c1f5d6553..f0fffe8b96 100644 --- a/bitacross-worker/cli/src/trusted_cli.rs +++ b/bitacross-worker/cli/src/trusted_cli.rs @@ -17,8 +17,6 @@ use crate::{benchmark::BenchmarkCommand, Cli, CliResult}; -#[cfg(feature = "evm")] -use crate::evm::EvmCommand; use crate::trusted_base_cli::TrustedBaseCommand; #[derive(Args)] @@ -48,10 +46,6 @@ pub enum TrustedCommand { #[clap(flatten)] BaseTrusted(TrustedBaseCommand), - #[cfg(feature = "evm")] - #[clap(flatten)] - EvmCommands(EvmCommand), - /// Run Benchmark Benchmark(BenchmarkCommand), } @@ -61,8 +55,6 @@ impl TrustedCli { match &self.command { TrustedCommand::BaseTrusted(cmd) => cmd.run(cli, self), TrustedCommand::Benchmark(cmd) => cmd.run(cli, self), - #[cfg(feature = "evm")] - TrustedCommand::EvmCommands(cmd) => cmd.run(cli, self), } } } diff --git a/bitacross-worker/cli/src/trusted_command_utils.rs b/bitacross-worker/cli/src/trusted_command_utils.rs index 57704b982c..ae61dd60cb 100644 --- a/bitacross-worker/cli/src/trusted_command_utils.rs +++ b/bitacross-worker/cli/src/trusted_command_utils.rs @@ -116,7 +116,11 @@ pub(crate) fn get_pair_from_str( ) -> sr25519_core::Pair { info!("getting pair for {}", account); match &account[..2] { - "//" => sr25519_core::Pair::from_string(account, None).unwrap(), + "//" => { + let pair = sr25519_core::Pair::from_string(account, None).unwrap(); + info!("public_key: {:?}", &pair.public().to_hex()); + pair + }, _ => { info!("fetching from keystore at {}", &TRUSTED_KEYSTORE_PATH); // open store without password protection diff --git a/bitacross-worker/cli/src/trusted_operation.rs b/bitacross-worker/cli/src/trusted_operation.rs index bfbb18c221..f3564f0e23 100644 --- a/bitacross-worker/cli/src/trusted_operation.rs +++ b/bitacross-worker/cli/src/trusted_operation.rs @@ -25,7 +25,7 @@ use base58::{FromBase58, ToBase58}; use codec::{Decode, Encode, Input}; use ita_stf::{Getter, StfError, TrustedCallSigned}; use itc_rpc_client::direct_client::{DirectApi, DirectClient}; -use itp_node_api::api_client::{ParentchainApi, TEEREX}; +use itp_node_api::api_client::{ParentchainApi, TEEBAG}; use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; use itp_sgx_crypto::ShieldingCryptoEncrypt; use itp_stf_primitives::types::{ShardIdentifier, TrustedOperation}; @@ -33,8 +33,7 @@ use itp_types::{BlockNumber, DirectRequestStatus, RsaRequest, TrustedOperationSt use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use litentry_primitives::ParentchainHash as Hash; use log::*; -use my_node_runtime::RuntimeEvent; -use pallet_teerex::Event as TeerexEvent; +use my_node_runtime::{pallet_teebag::Event as TeebagEvent, RuntimeEvent}; use sp_core::H256; use std::{ fmt::Debug, @@ -150,7 +149,7 @@ fn send_indirect_request( chain_api.set_signer(signer.into()); let request = RsaRequest::new(shard, call_encrypted); - let xt = compose_extrinsic!(&chain_api, TEEREX, "call_worker", request); + let xt = compose_extrinsic!(&chain_api, TEEBAG, "post_opaque_task", request); let block_hash = match chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) { Ok(xt_report) => { @@ -176,14 +175,14 @@ fn send_indirect_request( let event_result = subscription.next_events::(); if let Some(Ok(event_records)) = event_result { for event_record in event_records { - if let RuntimeEvent::Teerex(TeerexEvent::ProcessedParentchainBlock( - _signer, - confirmed_block_hash, - trusted_calls_merkle_root, - confirmed_block_number, - )) = event_record.event + if let RuntimeEvent::Teebag(TeebagEvent::ParentchainBlockProcessed { + who: _signer, + block_number: confirmed_block_number, + block_hash: confirmed_block_hash, + task_merkle_root: trusted_calls_merkle_root, + }) = event_record.event { - info!("Confirmation of ProcessedParentchainBlock received"); + info!("Confirmation of ParentchainBlockProcessed received"); debug!("shard: {:?}", shard); debug!("confirmed parentchain block Hash: {:?}", block_hash); debug!("trusted calls merkle root: {:?}", trusted_calls_merkle_root); @@ -194,9 +193,9 @@ fn send_indirect_request( confirmed_block_hash, confirmed_block_number, ) { - error!("ProcessedParentchainBlock event: {:?}", e); + error!("ParentchainBlockProcessed event: {:?}", e); return Err(TrustedOperationError::Default { - msg: format!("ProcessedParentchainBlock event: {:?}", e), + msg: format!("ParentchainBlockProcessed event: {:?}", e), }) }; diff --git a/bitacross-worker/core-primitives/enclave-api/Cargo.toml b/bitacross-worker/core-primitives/enclave-api/Cargo.toml index c9dfaa9dff..afc82899b8 100644 --- a/bitacross-worker/core-primitives/enclave-api/Cargo.toml +++ b/bitacross-worker/core-primitives/enclave-api/Cargo.toml @@ -22,11 +22,12 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "po itc-parentchain = { path = "../../core/parentchain/parentchain-crate" } itp-enclave-api-ffi = { path = "ffi" } itp-settings = { path = "../settings" } +itp-sgx-crypto = { path = "../sgx/crypto" } itp-storage = { path = "../storage" } itp-types = { path = "../types" } # litentry -teerex-primitives = { path = "../../../primitives/teerex", default-features = false } +pallet-teebag = { path = "../../../pallets/teebag", default-features = false } [features] default = [] diff --git a/bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs b/bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs index 2dbb8fb016..3a3ac922d8 100644 --- a/bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs +++ b/bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs @@ -33,10 +33,6 @@ extern "C" { pub fn init_enclave_sidechain_components( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, - fail_mode: *const u8, - fail_mode_size: u32, - fail_at: *const u8, - fail_at_size: u32, ) -> sgx_status_t; pub fn init_direct_invocation_server( @@ -71,8 +67,6 @@ extern "C" { parentchain_id_size: u32, ) -> sgx_status_t; - pub fn execute_trusted_calls(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; - pub fn sync_parentchain( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, @@ -127,6 +121,20 @@ extern "C" { pubkey_size: u32, ) -> sgx_status_t; + pub fn get_bitcoin_wallet_pair( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + pair: *mut u8, + pair_size: u32, + ) -> sgx_status_t; + + pub fn get_ethereum_wallet_pair( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + pair: *mut u8, + pair_size: u32, + ) -> sgx_status_t; + pub fn get_mrenclave( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, @@ -206,39 +214,6 @@ extern "C" { pub fn test_main_entrance(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; - pub fn call_rpc_methods( - eid: sgx_enclave_id_t, - retval: *mut sgx_status_t, - request: *const u8, - request_len: u32, - response: *mut u8, - response_len: u32, - ) -> sgx_status_t; - - pub fn update_market_data_xt( - eid: sgx_enclave_id_t, - retval: *mut sgx_status_t, - crypto_currency: *const u8, - crypto_currency_size: u32, - fiat_currency: *const u8, - fiat_currency_size: u32, - unchecked_extrinsic: *mut u8, - unchecked_extrinsic_max_size: u32, - unchecked_extrinsic_size: *mut u32, - ) -> sgx_status_t; - - pub fn update_weather_data_xt( - eid: sgx_enclave_id_t, - retval: *mut sgx_status_t, - weather_info_longitude: *const u8, - weather_info_longitude_size: u32, - weather_info_latitude: *const u8, - weather_info_latitude_size: u32, - unchecked_extrinsic: *mut u8, - unchecked_extrinsic_max_size: u32, - unchecked_extrinsic_size: *mut u32, - ) -> sgx_status_t; - pub fn run_state_provisioning_server( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, @@ -276,4 +251,6 @@ extern "C" { until: *const u32, ) -> sgx_status_t; + pub fn publish_wallets(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; + } diff --git a/bitacross-worker/core-primitives/enclave-api/src/direct_request.rs b/bitacross-worker/core-primitives/enclave-api/src/direct_request.rs deleted file mode 100644 index f3fff3388a..0000000000 --- a/bitacross-worker/core-primitives/enclave-api/src/direct_request.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::EnclaveResult; - -pub trait DirectRequest: Send + Sync + 'static { - // Todo: Vec shall be replaced by D: Decode, E: Encode but this is currently - // not compatible with the direct_api_server... - fn rpc(&self, request: Vec) -> EnclaveResult>; -} - -#[cfg(feature = "implement-ffi")] -mod impl_ffi { - use super::DirectRequest; - use crate::{error::Error, Enclave, EnclaveResult}; - use frame_support::ensure; - use itp_enclave_api_ffi as ffi; - use sgx_types::sgx_status_t; - - impl DirectRequest for Enclave { - fn rpc(&self, request: Vec) -> EnclaveResult> { - let mut retval = sgx_status_t::SGX_SUCCESS; - let response_len = 8192; - let mut response: Vec = vec![0u8; response_len as usize]; - - let res = unsafe { - ffi::call_rpc_methods( - self.eid, - &mut retval, - request.as_ptr(), - request.len() as u32, - response.as_mut_ptr(), - response_len, - ) - }; - - ensure!(res == sgx_status_t::SGX_SUCCESS, Error::Sgx(res)); - ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); - - Ok(response) - } - } -} diff --git a/bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs b/bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs index 4e79a6f902..870e61f01a 100644 --- a/bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs +++ b/bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs @@ -20,10 +20,11 @@ use crate::EnclaveResult; use codec::Decode; use core::fmt::Debug; use itc_parentchain::primitives::{ParentchainId, ParentchainInitParams}; +use itp_sgx_crypto::{ecdsa, schnorr}; use itp_types::ShardIdentifier; +use pallet_teebag::EnclaveFingerprint; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::ed25519; -use teerex_primitives::EnclaveFingerprint; /// Trait for base/common Enclave API functions pub trait EnclaveBase: Send + Sync + 'static { @@ -36,11 +37,7 @@ pub trait EnclaveBase: Send + Sync + 'static { ) -> EnclaveResult<()>; /// Initialize the enclave sidechain components. - fn init_enclave_sidechain_components( - &self, - fail_mode: Option, - fail_at: u64, - ) -> EnclaveResult<()>; + fn init_enclave_sidechain_components(&self) -> EnclaveResult<()>; /// Initialize the direct invocation RPC server. fn init_direct_invocation_server(&self, rpc_server_addr: String) -> EnclaveResult<()>; @@ -76,16 +73,25 @@ pub trait EnclaveBase: Send + Sync + 'static { /// retrieve vault account from shard state fn get_ecc_vault_pubkey(&self, shard: &ShardIdentifier) -> EnclaveResult; + /// retrieve the btc wallet key pair, only works in non-prod + fn get_bitcoin_wallet_pair(&self) -> EnclaveResult; + + /// retrieve the eth wallet key pair, only works in non-prod + fn get_ethereum_wallet_pair(&self) -> EnclaveResult; + fn get_fingerprint(&self) -> EnclaveResult; // litentry fn migrate_shard(&self, old_shard: Vec, new_shard: Vec) -> EnclaveResult<()>; + + /// Publish generated wallets on parachain + fn publish_wallets(&self) -> EnclaveResult<()>; } /// EnclaveApi implementation for Enclave struct #[cfg(feature = "implement-ffi")] mod impl_ffi { - use super::EnclaveBase; + use super::{ecdsa, schnorr, EnclaveBase}; use crate::{error::Error, Enclave, EnclaveResult}; use codec::{Decode, Encode}; use core::fmt::Debug; @@ -97,10 +103,10 @@ mod impl_ffi { }; use itp_types::ShardIdentifier; use log::*; + use pallet_teebag::EnclaveFingerprint; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sgx_types::*; use sp_core::ed25519; - use teerex_primitives::EnclaveFingerprint; impl EnclaveBase for Enclave { fn init( @@ -134,25 +140,10 @@ mod impl_ffi { Ok(()) } - fn init_enclave_sidechain_components( - &self, - fail_mode: Option, - fail_at: u64, - ) -> EnclaveResult<()> { + fn init_enclave_sidechain_components(&self) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; - let encoded_fail_mode = fail_mode.encode(); - let encoded_fail_at = fail_at.encode(); - let result = unsafe { - ffi::init_enclave_sidechain_components( - self.eid, - &mut retval, - encoded_fail_mode.as_ptr(), - encoded_fail_mode.len() as u32, - encoded_fail_at.as_ptr(), - encoded_fail_at.len() as u32, - ) - }; + let result = unsafe { ffi::init_enclave_sidechain_components(self.eid, &mut retval) }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); @@ -342,6 +333,46 @@ mod impl_ffi { Ok(ed25519::Public::from_raw(pubkey)) } + fn get_bitcoin_wallet_pair(&self) -> EnclaveResult { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut private_key = [0u8; 32]; + + let result = unsafe { + ffi::get_bitcoin_wallet_pair( + self.eid, + &mut retval, + private_key.as_mut_ptr(), + private_key.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + schnorr::Pair::from_bytes(&private_key) + .map_err(|e| Error::Other(format!("{:?}", e).into())) + } + + fn get_ethereum_wallet_pair(&self) -> EnclaveResult { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut private_key = [0u8; 32]; + + let result = unsafe { + ffi::get_ethereum_wallet_pair( + self.eid, + &mut retval, + private_key.as_mut_ptr(), + private_key.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + ecdsa::Pair::from_bytes(&private_key) + .map_err(|e| Error::Other(format!("{:?}", e).into())) + } + fn get_fingerprint(&self) -> EnclaveResult { let mut retval = sgx_status_t::SGX_SUCCESS; let mut mr_enclave = [0u8; MR_ENCLAVE_SIZE]; @@ -379,6 +410,17 @@ mod impl_ffi { Ok(()) } + + fn publish_wallets(&self) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { ffi::publish_wallets(self.eid, &mut retval) }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } } fn init_parentchain_components_ffi( diff --git a/bitacross-worker/core-primitives/enclave-api/src/lib.rs b/bitacross-worker/core-primitives/enclave-api/src/lib.rs index 38c810624f..131f4e9b7a 100644 --- a/bitacross-worker/core-primitives/enclave-api/src/lib.rs +++ b/bitacross-worker/core-primitives/enclave-api/src/lib.rs @@ -13,13 +13,11 @@ use crate::error::Error; -pub mod direct_request; pub mod enclave_base; pub mod enclave_test; pub mod error; pub mod remote_attestation; pub mod sidechain; -pub mod teeracle_api; pub mod utils; #[cfg(feature = "implement-ffi")] diff --git a/bitacross-worker/core-primitives/enclave-api/src/remote_attestation.rs b/bitacross-worker/core-primitives/enclave-api/src/remote_attestation.rs index 9aa32cb631..30a765da32 100644 --- a/bitacross-worker/core-primitives/enclave-api/src/remote_attestation.rs +++ b/bitacross-worker/core-primitives/enclave-api/src/remote_attestation.rs @@ -18,8 +18,8 @@ use crate::EnclaveResult; use itp_types::ShardIdentifier; +use pallet_teebag::Fmspc; use sgx_types::*; -use teerex_primitives::Fmspc; /// Struct that unites all relevant data reported by the QVE pub struct QveReport { @@ -128,8 +128,8 @@ mod impl_ffi { use itp_settings::worker::EXTRINSIC_MAX_SIZE; use itp_types::ShardIdentifier; use log::*; + use pallet_teebag::Fmspc; use sgx_types::*; - use teerex_primitives::Fmspc; const OS_SYSTEM_PATH: &str = "/usr/lib/x86_64-linux-gnu/"; const C_STRING_ENDING: &str = "\0"; diff --git a/bitacross-worker/core-primitives/enclave-api/src/sidechain.rs b/bitacross-worker/core-primitives/enclave-api/src/sidechain.rs index 877460075b..9dee8e3bb4 100644 --- a/bitacross-worker/core-primitives/enclave-api/src/sidechain.rs +++ b/bitacross-worker/core-primitives/enclave-api/src/sidechain.rs @@ -35,8 +35,6 @@ pub trait Sidechain: Send + Sync + 'static { is_syncing: bool, ) -> EnclaveResult<()>; - fn execute_trusted_calls(&self) -> EnclaveResult<()>; - // litentry /// Ignore the parentchain block import validation until the given block number /// TODO: use the generic Header::Number trait @@ -92,17 +90,6 @@ mod impl_ffi { Ok(()) } - fn execute_trusted_calls(&self) -> EnclaveResult<()> { - let mut retval = sgx_status_t::SGX_SUCCESS; - - let result = unsafe { ffi::execute_trusted_calls(self.eid, &mut retval) }; - - ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); - ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); - - Ok(()) - } - fn ignore_parentchain_block_import_validation_until( &self, until: u32, diff --git a/bitacross-worker/core-primitives/enclave-api/src/teeracle_api.rs b/bitacross-worker/core-primitives/enclave-api/src/teeracle_api.rs deleted file mode 100644 index 530e2ff127..0000000000 --- a/bitacross-worker/core-primitives/enclave-api/src/teeracle_api.rs +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::EnclaveResult; - -pub trait TeeracleApi: Send + Sync + 'static { - /// Update the currency market data for the token oracle. - fn update_market_data_xt( - &self, - crypto_currency: &str, - fiat_currency: &str, - ) -> EnclaveResult>; - - /// Update weather data for the corresponding coordinates. - fn update_weather_data_xt(&self, longitude: &str, latitude: &str) -> EnclaveResult>; -} - -#[cfg(feature = "implement-ffi")] -mod impl_ffi { - use super::TeeracleApi; - use crate::{error::Error, Enclave, EnclaveResult}; - use codec::Encode; - use frame_support::ensure; - use itp_enclave_api_ffi as ffi; - use log::*; - use sgx_types::*; - impl TeeracleApi for Enclave { - fn update_market_data_xt( - &self, - crypto_currency: &str, - fiat_currency: &str, - ) -> EnclaveResult> { - info!( - "TeeracleApi update_market_data_xt in with crypto {} and fiat {}", - crypto_currency, fiat_currency - ); - let mut retval = sgx_status_t::SGX_SUCCESS; - let response_max_len = 8192; - let mut response: Vec = vec![0u8; response_max_len as usize]; - let mut response_len: u32 = 0; - - let crypto_curr = crypto_currency.encode(); - let fiat_curr = fiat_currency.encode(); - - let res = unsafe { - ffi::update_market_data_xt( - self.eid, - &mut retval, - crypto_curr.as_ptr(), - crypto_curr.len() as u32, - fiat_curr.as_ptr(), - fiat_curr.len() as u32, - response.as_mut_ptr(), - response_max_len, - &mut response_len as *mut u32, - ) - }; - - ensure!(res == sgx_status_t::SGX_SUCCESS, Error::Sgx(res)); - ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); - - Ok(Vec::from(&response[..response_len as usize])) - } - fn update_weather_data_xt( - &self, - longitude: &str, - latitude: &str, - ) -> EnclaveResult> { - info!( - "TeeracleApi update_weather_data_xt in with latitude: {}, longitude: {}", - latitude, longitude - ); - let mut retval = sgx_status_t::SGX_SUCCESS; - let response_max_len = 8192; - let mut response: Vec = vec![0u8; response_max_len as usize]; - let mut response_len: u32 = 0; - - let longitude_encoded: Vec = longitude.encode(); - let latitude_encoded: Vec = latitude.encode(); - - let res = unsafe { - ffi::update_weather_data_xt( - self.eid, - &mut retval, - longitude_encoded.as_ptr(), - longitude_encoded.len() as u32, - latitude_encoded.as_ptr(), - latitude_encoded.len() as u32, - response.as_mut_ptr(), - response_max_len, - &mut response_len as *mut u32, - ) - }; - - ensure!(res == sgx_status_t::SGX_SUCCESS, Error::Sgx(res)); - ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); - Ok(Vec::from(&response[..response_len as usize])) - } - } -} diff --git a/bitacross-worker/core-primitives/enclave-bridge-storage/Cargo.toml b/bitacross-worker/core-primitives/enclave-bridge-storage/Cargo.toml deleted file mode 100644 index 8b191f3458..0000000000 --- a/bitacross-worker/core-primitives/enclave-bridge-storage/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "itp-enclave-bridge-storage" -version = "0.9.0" -authors = ["Integritee AG "] -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -#local deps -itp-storage = { path = "../storage", default-features = false } - -[features] -default = ["std"] -std = [ - "codec/std", - "sp-std/std", - "itp-storage/std", -] diff --git a/bitacross-worker/core-primitives/enclave-bridge-storage/src/lib.rs b/bitacross-worker/core-primitives/enclave-bridge-storage/src/lib.rs deleted file mode 100644 index 9077d756b6..0000000000 --- a/bitacross-worker/core-primitives/enclave-bridge-storage/src/lib.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::Encode; -use itp_storage::{storage_map_key, StorageHasher}; -use sp_std::prelude::Vec; - -pub struct EnclaveBridgeStorage; - -// Separate the prefix from the rest because in our case we changed the storage prefix due to -// the rebranding. With the below implementation of the `TeerexStorageKeys`, we could simply -// define another struct `OtherStorage`, implement `StoragePrefix` for it, and get the -// `TeerexStorageKeys` implementation for free. -pub trait StoragePrefix { - fn prefix() -> &'static str; -} - -impl StoragePrefix for EnclaveBridgeStorage { - fn prefix() -> &'static str { - "EnclaveBridge" - } -} - -pub trait EnclaveBridgeStorageKeys { - fn shard_status(shard: T) -> Vec; -} - -impl EnclaveBridgeStorageKeys for S { - fn shard_status(shard: T) -> Vec { - storage_map_key(Self::prefix(), "ShardStatus", &shard, &StorageHasher::Blake2_128Concat) - } -} diff --git a/bitacross-worker/core-primitives/enclave-metrics/Cargo.toml b/bitacross-worker/core-primitives/enclave-metrics/Cargo.toml index b6f3ae3e29..27504af273 100644 --- a/bitacross-worker/core-primitives/enclave-metrics/Cargo.toml +++ b/bitacross-worker/core-primitives/enclave-metrics/Cargo.toml @@ -12,12 +12,10 @@ sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sd # no-std dependencies codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } -substrate-fixed = { default-features = false, git = "https://github.com/encointer/substrate-fixed", tag = "v0.5.9" } [features] default = ["std"] std = [ - "substrate-fixed/std", "codec/std", ] sgx = [ diff --git a/bitacross-worker/core-primitives/enclave-metrics/src/lib.rs b/bitacross-worker/core-primitives/enclave-metrics/src/lib.rs index ae7f253adc..0bec4a51da 100644 --- a/bitacross-worker/core-primitives/enclave-metrics/src/lib.rs +++ b/bitacross-worker/core-primitives/enclave-metrics/src/lib.rs @@ -27,10 +27,6 @@ extern crate sgx_tstd as std; use codec::{Decode, Encode}; use core::time::Duration; use std::string::String; -use substrate_fixed::types::U32F32; - -// FIXME: Copied from ita-oracle because of cyclic deps. Should be removed after integritee-network/pallets#71 -pub type ExchangeRate = U32F32; #[derive(Encode, Decode, Debug)] pub enum EnclaveMetric { @@ -38,31 +34,7 @@ pub enum EnclaveMetric { TopPoolSizeSet(u64), TopPoolSizeIncrement, TopPoolSizeDecrement, - ExchangeRateOracle(ExchangeRateOracleMetric), SuccessfulTrustedOperationIncrement(String), FailedTrustedOperationIncrement(String), ParentchainBlockImportTime(Duration), - SidechainBlockImportTime(Duration), - SidechainSlotPrepareTime(Duration), - SidechainSlotStfExecutionTime(Duration), - SidechainSlotBlockCompositionTime(Duration), - SidechainBlockBroadcastingTime(Duration), - // OracleMetric(OracleMetric), -} - -#[derive(Encode, Decode, Debug)] -pub enum ExchangeRateOracleMetric { - /// Exchange Rate from CoinGecko - (Source, TradingPair, ExchangeRate) - ExchangeRate(String, String, ExchangeRate), - /// Response time of the request in [ms]. (Source, ResponseTime) - ResponseTime(String, u128), - /// Increment the number of requests (Source) - NumberRequestsIncrement(String), -} - -#[derive(Encode, Decode, Debug)] -pub enum OracleMetric { - OracleSpecificMetric(MetricsInfo), - ResponseTime(String, u128), - NumberRequestsIncrement(String), } diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/lib.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/lib.rs index 2829b53c1c..668cefd2ba 100644 --- a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/lib.rs +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/lib.rs @@ -21,12 +21,10 @@ pub use substrate_api_client::{api::Error as ApiClientError, rpc::TungsteniteRpc pub mod account; pub mod chain; -pub mod pallet_teeracle; -pub mod pallet_teerex; +pub mod pallet_teebag; pub use account::*; pub use chain::*; -pub use pallet_teeracle::*; -pub use pallet_teerex::*; +pub use pallet_teebag::*; pub type ApiResult = Result; diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teebag.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teebag.rs new file mode 100644 index 0000000000..e243091ca5 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teebag.rs @@ -0,0 +1,134 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::ApiResult; +use itp_api_client_types::{traits::GetStorage, Api, Config, Request}; +use itp_types::{AccountId, Enclave, ShardIdentifier, WorkerType}; + +pub const TEEBAG: &str = "Teebag"; + +/// ApiClient extension that enables communication with the `teebag` pallet. +pub trait PalletTeebagApi { + type Hash; + + fn enclave( + &self, + account: &AccountId, + at_block: Option, + ) -> ApiResult>; + fn enclave_count( + &self, + worker_type: WorkerType, + at_block: Option, + ) -> ApiResult; + fn primary_enclave_identifier_for_shard( + &self, + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult>; + fn primary_enclave_for_shard( + &self, + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult>; + fn all_enclaves( + &self, + worker_type: WorkerType, + at_block: Option, + ) -> ApiResult>; +} + +impl PalletTeebagApi for Api +where + RuntimeConfig: Config, + Client: Request, +{ + type Hash = RuntimeConfig::Hash; + + fn enclave( + &self, + account: &AccountId, + at_block: Option, + ) -> ApiResult> { + self.get_storage_map(TEEBAG, "EnclaveRegistry", account, at_block) + } + + fn enclave_count( + &self, + worker_type: WorkerType, + at_block: Option, + ) -> ApiResult { + // Vec<> and BoundedVec<> have the same encoding, thus they are used interchangeably + let identifiers: Vec = self + .get_storage_map(TEEBAG, "EnclaveIdentifier", worker_type, at_block)? + .unwrap_or_default(); + Ok(identifiers.len() as u64) + } + + // please note we don't use dedicated on-chain storage for this (like the upstream `WorkerForShard`) + // so this API will always return the "first" registered and qualified enclave. + // Wheter it meets our needs needs to be further evaluated + fn primary_enclave_identifier_for_shard( + &self, + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { + let identifiers: Vec = self + .get_storage_map(TEEBAG, "EnclaveIdentifier", worker_type, at_block)? + .unwrap_or_default(); + let mut maybe_account: Option = None; + for account in identifiers { + match self.enclave(&account, at_block)? { + Some(e) => + if e.mrenclave == shard.as_ref() { + maybe_account = Some(account.clone()); + break + }, + None => continue, + } + } + Ok(maybe_account) + } + + fn primary_enclave_for_shard( + &self, + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { + self.primary_enclave_identifier_for_shard(worker_type, shard, at_block)? + .map_or_else(|| Ok(None), |account| self.enclave(&account, at_block)) + } + + fn all_enclaves( + &self, + worker_type: WorkerType, + at_block: Option, + ) -> ApiResult> { + let identifiers: Vec = self + .get_storage_map(TEEBAG, "EnclaveIdentifier", worker_type, at_block)? + .unwrap_or_default(); + + let enclaves = identifiers + .into_iter() + .filter_map(|account| self.enclave(&account, at_block).ok()?) + .collect(); + Ok(enclaves) + } +} diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs deleted file mode 100644 index 3f1ad2d198..0000000000 --- a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub const TEERACLE: &str = "Teeracle"; -pub const ADD_TO_WHITELIST: &str = "add_to_whitelist"; diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs deleted file mode 100644 index 222e249402..0000000000 --- a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::ApiResult; -use itp_api_client_types::{storage_key, traits::GetStorage, Api, Config, Request}; -use itp_types::{Enclave, IpfsHash, MrEnclave, ShardIdentifier}; -use sp_core::storage::StorageKey; - -pub const TEEREX: &str = "Teerex"; -pub const SIDECHAIN: &str = "Sidechain"; - -/// ApiClient extension that enables communication with the `teerex` pallet. -// Todo: make generic over `Config` type instead? -pub trait PalletTeerexApi { - type Hash; - - fn enclave(&self, index: u64, at_block: Option) -> ApiResult>; - fn enclave_count(&self, at_block: Option) -> ApiResult; - fn all_enclaves(&self, at_block: Option) -> ApiResult>; - fn worker_for_shard( - &self, - shard: &ShardIdentifier, - at_block: Option, - ) -> ApiResult>; - fn latest_ipfs_hash( - &self, - shard: &ShardIdentifier, - at_block: Option, - ) -> ApiResult>; - - // litentry - fn all_scheduled_mrenclaves(&self, at_block: Option) -> ApiResult>; -} - -impl PalletTeerexApi for Api -where - RuntimeConfig: Config, - Client: Request, -{ - type Hash = RuntimeConfig::Hash; - - fn enclave(&self, index: u64, at_block: Option) -> ApiResult> { - self.get_storage_map(TEEREX, "EnclaveRegistry", index, at_block) - } - - fn enclave_count(&self, at_block: Option) -> ApiResult { - Ok(self.get_storage(TEEREX, "EnclaveCount", at_block)?.unwrap_or(0u64)) - } - - fn all_enclaves(&self, at_block: Option) -> ApiResult> { - let count = self.enclave_count(at_block)?; - let mut enclaves = Vec::with_capacity(count as usize); - for n in 1..=count { - enclaves.push(self.enclave(n, at_block)?.expect("None enclave")) - } - Ok(enclaves) - } - - fn worker_for_shard( - &self, - shard: &ShardIdentifier, - at_block: Option, - ) -> ApiResult> { - self.get_storage_map(SIDECHAIN, "WorkerForShard", shard, at_block)? - .map_or_else(|| Ok(None), |w_index| self.enclave(w_index, at_block)) - } - - fn latest_ipfs_hash( - &self, - shard: &ShardIdentifier, - at_block: Option, - ) -> ApiResult> { - self.get_storage_map(TEEREX, "LatestIPFSHash", shard, at_block) - } - - fn all_scheduled_mrenclaves(&self, at_block: Option) -> ApiResult> { - let keys: Vec<_> = self - .get_keys(storage_key(TEEREX, "ScheduledEnclave"), at_block)? - .unwrap_or_default() - .iter() - .map(|key| { - let key = key.strip_prefix("0x").unwrap_or(key); - let raw_key = hex::decode(key).unwrap(); - self.get_storage_by_key::(StorageKey(raw_key).into(), at_block) - }) - .filter(|enclave| matches!(enclave, Ok(Some(_)))) - .map(|enclave| enclave.unwrap().unwrap()) - .collect(); - Ok(keys) - } -} diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs deleted file mode 100644 index df5bf3646f..0000000000 --- a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{pallet_teerex::PalletTeerexApi, ApiResult}; -use itp_types::{parentchain::Hash, AccountId, IpfsHash, MrEnclave, MultiEnclave, ShardIdentifier}; -use std::collections::HashMap; - -#[derive(Default)] -pub struct PalletTeerexApiMock { - registered_enclaves: HashMap>>, -} - -impl PalletTeerexApiMock { - pub fn with_enclaves(mut self, enclaves: Vec>>) -> Self { - enclaves.iter().map(|enclave| self.registered_enclaves.insert(enclave)); - self - } -} - -impl PalletTeerexApi for PalletTeerexApiMock { - fn enclave( - &self, - account: AccountId, - _at_block: Option, - ) -> ApiResult>>> { - Ok(self.registered_enclaves.get(index as usize).cloned()) - } - - fn enclave_count(&self, _at_block: Option) -> ApiResult { - Ok(self.registered_enclaves.len() as u64) - } - - fn all_enclaves(&self, _at_block: Option) -> ApiResult>>> { - Ok(self.registered_enclaves.clone()) - } - - fn primary_worker_for_shard( - &self, - _shard: &ShardIdentifier, - _at_block: Option, - ) -> ApiResult>>> { - todo!() - } - - fn latest_ipfs_hash( - &self, - _shard: &ShardIdentifier, - _at_block: Option, - ) -> ApiResult> { - todo!() - } - - fn all_scheduled_mrenclaves(&self, _at_block: Option) -> ApiResult> { - Ok(self.registered_enclaves.iter().map(|k| k.mr_enclave).collect()) - } -} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/lib.rs b/bitacross-worker/core-primitives/node-api/metadata/src/lib.rs index 0a069c0277..3f8073c569 100644 --- a/bitacross-worker/core-primitives/node-api/metadata/src/lib.rs +++ b/bitacross-worker/core-primitives/node-api/metadata/src/lib.rs @@ -20,10 +20,9 @@ #![cfg_attr(not(feature = "std"), no_std)] use crate::{ - error::Result, pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, - pallet_proxy::ProxyCallIndexes, pallet_sidechain::SidechainCallIndexes, - pallet_system::SystemSs58Prefix, pallet_teerex::TeerexCallIndexes, - pallet_utility::UtilityCallIndexes, pallet_vcmp::VCMPCallIndexes, + error::Result, pallet_balances::BalancesCallIndexes, pallet_bitacross::BitAcrossCallIndexes, + pallet_proxy::ProxyCallIndexes, pallet_system::SystemSs58Prefix, + pallet_teebag::TeebagCallIndexes, pallet_utility::UtilityCallIndexes, }; use codec::{Decode, Encode}; use sp_core::storage::StorageKey; @@ -33,39 +32,32 @@ pub use itp_api_client_types::{Metadata, MetadataError}; pub mod error; pub mod pallet_balances; -pub mod pallet_imp; +pub mod pallet_bitacross; pub mod pallet_proxy; -pub mod pallet_sidechain; pub mod pallet_system; -pub mod pallet_teeracle; -pub mod pallet_teerex; +pub mod pallet_teebag; pub mod pallet_utility; -pub mod pallet_vcmp; pub mod runtime_call; #[cfg(feature = "mocks")] pub mod metadata_mocks; pub trait NodeMetadataTrait: - TeerexCallIndexes - + SidechainCallIndexes - + IMPCallIndexes - + VCMPCallIndexes + TeebagCallIndexes + SystemSs58Prefix + UtilityCallIndexes + ProxyCallIndexes + BalancesCallIndexes + + BitAcrossCallIndexes { } impl< - T: TeerexCallIndexes - + SidechainCallIndexes - + IMPCallIndexes - + VCMPCallIndexes + T: TeebagCallIndexes + SystemSs58Prefix + UtilityCallIndexes + ProxyCallIndexes - + BalancesCallIndexes, + + BalancesCallIndexes + + BitAcrossCallIndexes, > NodeMetadataTrait for T { } diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs b/bitacross-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs index cdf24e4fcc..ab4bdedcce 100644 --- a/bitacross-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs +++ b/bitacross-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -16,10 +16,10 @@ */ use crate::{ - error::Result, pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, - pallet_proxy::ProxyCallIndexes, pallet_sidechain::SidechainCallIndexes, - pallet_system::SystemSs58Prefix, pallet_teerex::TeerexCallIndexes, - pallet_utility::UtilityCallIndexes, pallet_vcmp::VCMPCallIndexes, runtime_call::RuntimeCall, + error::Result, pallet_balances::BalancesCallIndexes, pallet_bitacross::BitAcrossCallIndexes, + pallet_proxy::ProxyCallIndexes, pallet_system::SystemSs58Prefix, + pallet_teebag::TeebagCallIndexes, pallet_utility::UtilityCallIndexes, + runtime_call::RuntimeCall, }; use codec::{Decode, Encode}; @@ -35,39 +35,17 @@ impl TryFrom for Metadata { #[derive(Default, Encode, Decode, Debug, Clone)] pub struct NodeMetadataMock { - teerex_module: u8, + // teebag + teebag_module: u8, + set_scheduled_enclave: u8, + remove_scheduled_enclave: u8, register_enclave: u8, - unregister_sovereign_enclave: u8, - unregister_proxied_enclave: u8, + unregister_enclave: u8, register_quoting_enclave: u8, register_tcb_info: u8, - enclave_bridge_module: u8, - invoke: u8, - confirm_processed_parentchain_block: u8, - shield_funds: u8, - unshield_funds: u8, - publish_hash: u8, - update_shard_config: u8, - sidechain_module: u8, - // litentry - update_scheduled_enclave: u8, - remove_scheduled_enclave: u8, - // IMP - imp_module: u8, - imp_link_identity: u8, - imp_deactivate_identity: u8, - imp_activate_identity: u8, - imp_update_id_graph_hash: u8, - imp_identity_linked: u8, - imp_identity_deactivated: u8, - imp_identity_activated: u8, - imp_identity_networks_set: u8, - imp_some_error: u8, - // VCMP - vcmp_module: u8, - vcmp_request_vc: u8, - vcmp_vc_issued: u8, - vcmp_some_error: u8, + post_opaque_task: u8, + parentchain_block_processed: u8, + sidechain_block_imported: u8, utility_module: u8, utility_batch: u8, @@ -86,44 +64,27 @@ pub struct NodeMetadataMock { transfer_allow_death: u8, runtime_spec_version: u32, runtime_transaction_version: u32, + + bitacross_module: u8, + bitacross_add_relayer: u8, + bitacross_remove_relayer: u8, + btc_wallet_generated: u8, + eth_wallet_generated: u8, } impl NodeMetadataMock { pub fn new() -> Self { NodeMetadataMock { - teerex_module: 50u8, - register_enclave: 0u8, - unregister_sovereign_enclave: 1u8, - unregister_proxied_enclave: 2u8, - register_quoting_enclave: 3, - register_tcb_info: 4, - enclave_bridge_module: 54u8, - invoke: 0u8, - confirm_processed_parentchain_block: 1u8, - shield_funds: 2u8, - unshield_funds: 3u8, - publish_hash: 4u8, - update_shard_config: 5u8, - sidechain_module: 53u8, - // litentry - update_scheduled_enclave: 10u8, - remove_scheduled_enclave: 11u8, - - imp_module: 64u8, - imp_link_identity: 1u8, - imp_deactivate_identity: 2u8, - imp_activate_identity: 3u8, - imp_update_id_graph_hash: 4u8, - imp_identity_linked: 6u8, - imp_identity_deactivated: 7u8, - imp_identity_activated: 8u8, - imp_identity_networks_set: 9u8, - imp_some_error: 10u8, - - vcmp_module: 66u8, - vcmp_request_vc: 0u8, - vcmp_vc_issued: 3u8, - vcmp_some_error: 9u8, + teebag_module: 50u8, + set_scheduled_enclave: 0u8, + remove_scheduled_enclave: 1u8, + register_enclave: 2u8, + unregister_enclave: 3u8, + register_quoting_enclave: 4u8, + register_tcb_info: 5u8, + post_opaque_task: 6u8, + parentchain_block_processed: 7u8, + sidechain_block_imported: 8u8, utility_module: 80u8, utility_batch: 0u8, @@ -142,119 +103,43 @@ impl NodeMetadataMock { transfer_allow_death: 0u8, runtime_spec_version: 25, runtime_transaction_version: 4, + + bitacross_module: 69u8, + bitacross_add_relayer: 0u8, + bitacross_remove_relayer: 1u8, + btc_wallet_generated: 2u8, + eth_wallet_generated: 3u8, } } } -impl TeerexCallIndexes for NodeMetadataMock { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_enclave]) +impl TeebagCallIndexes for NodeMetadataMock { + fn set_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.set_scheduled_enclave]) } - - fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.unregister_sovereign_enclave]) + fn remove_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.remove_scheduled_enclave]) } - - fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.unregister_proxied_enclave]) + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.register_enclave]) + } + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.unregister_enclave]) } - fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_quoting_enclave]) + Ok([self.teebag_module, self.register_quoting_enclave]) } - fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_tcb_info]) - } - - fn invoke_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.invoke]) + Ok([self.teebag_module, self.register_tcb_info]) } - - fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.confirm_processed_parentchain_block]) + fn post_opaque_task_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.post_opaque_task]) } - - fn shield_funds_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.shield_funds]) + fn parentchain_block_processed_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.parentchain_block_processed]) } - - fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.unshield_funds]) - } - - fn publish_hash_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.publish_hash]) - } - - // fn update_shard_config_call_indexes(&self) -> Result<[u8; 2]> { - // Ok([self.teerex_module, self.update_shard_config]) - // } - - fn update_scheduled_enclave(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.update_scheduled_enclave]) - } - - fn remove_scheduled_enclave(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.remove_scheduled_enclave]) - } -} - -impl SidechainCallIndexes for NodeMetadataMock { - fn confirm_imported_sidechain_block_indexes(&self) -> Result<[u8; 2]> { - Ok([self.sidechain_module, self.imported_sidechain_block]) - } -} - -impl IMPCallIndexes for NodeMetadataMock { - fn link_identity_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_link_identity]) - } - - fn deactivate_identity_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_deactivate_identity]) - } - - fn activate_identity_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_activate_identity]) - } - - fn update_id_graph_hash_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_update_id_graph_hash]) - } - - fn identity_linked_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_identity_linked]) - } - - fn identity_deactivated_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_identity_deactivated]) - } - - fn identity_activated_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_identity_activated]) - } - - fn identity_networks_set_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_identity_networks_set]) - } - - fn imp_some_error_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.imp_module, self.imp_some_error]) - } -} - -impl VCMPCallIndexes for NodeMetadataMock { - fn request_vc_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.vcmp_module, self.vcmp_request_vc]) - } - - fn vc_issued_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.vcmp_module, self.vcmp_vc_issued]) - } - - fn vcmp_some_error_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.vcmp_module, self.vcmp_some_error]) + fn sidechain_block_imported_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.sidechain_block_imported]) } } @@ -315,3 +200,21 @@ impl BalancesCallIndexes for NodeMetadataMock { Ok([self.balances_module, self.transfer_allow_death]) } } + +impl BitAcrossCallIndexes for NodeMetadataMock { + fn add_relayer_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.bitacross_module, self.bitacross_add_relayer]) + } + + fn remove_relayer_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.bitacross_module, self.bitacross_remove_relayer]) + } + + fn btc_wallet_generated_indexes(&self) -> Result<[u8; 2]> { + Ok([self.bitacross_module, self.btc_wallet_generated]) + } + + fn eth_wallet_generated_indexes(&self) -> Result<[u8; 2]> { + Ok([self.bitacross_module, self.eth_wallet_generated]) + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_bitacross.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_bitacross.rs new file mode 100644 index 0000000000..914cd18704 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_bitacross.rs @@ -0,0 +1,45 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +// TODO: maybe use macros to simplify this +use crate::{error::Result, NodeMetadata}; + +const BITACROSS: &str = "Bitacross"; + +pub trait BitAcrossCallIndexes { + fn add_relayer_call_indexes(&self) -> Result<[u8; 2]>; + fn remove_relayer_call_indexes(&self) -> Result<[u8; 2]>; + fn btc_wallet_generated_indexes(&self) -> Result<[u8; 2]>; + fn eth_wallet_generated_indexes(&self) -> Result<[u8; 2]>; +} + +impl BitAcrossCallIndexes for NodeMetadata { + fn add_relayer_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(BITACROSS, "add_relayer") + } + + fn remove_relayer_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(BITACROSS, "remove_relayer") + } + + fn btc_wallet_generated_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(BITACROSS, "btc_wallet_generated") + } + + fn eth_wallet_generated_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(BITACROSS, "eth_wallet_generated") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_imp.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_imp.rs deleted file mode 100644 index 636d93cdab..0000000000 --- a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_imp.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2020-2023 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -// TODO: maybe use macros to simplify this -use crate::{error::Result, NodeMetadata}; - -/// Pallet' name: -const IMP: &str = "IdentityManagement"; - -pub trait IMPCallIndexes { - fn link_identity_call_indexes(&self) -> Result<[u8; 2]>; - fn deactivate_identity_call_indexes(&self) -> Result<[u8; 2]>; - fn activate_identity_call_indexes(&self) -> Result<[u8; 2]>; - fn update_id_graph_hash_call_indexes(&self) -> Result<[u8; 2]>; - fn identity_linked_call_indexes(&self) -> Result<[u8; 2]>; - fn identity_deactivated_call_indexes(&self) -> Result<[u8; 2]>; - fn identity_activated_call_indexes(&self) -> Result<[u8; 2]>; - fn identity_networks_set_call_indexes(&self) -> Result<[u8; 2]>; - fn imp_some_error_call_indexes(&self) -> Result<[u8; 2]>; -} - -impl IMPCallIndexes for NodeMetadata { - fn link_identity_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "link_identity") - } - - fn deactivate_identity_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "deactivate_identity") - } - - fn activate_identity_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "activate_identity") - } - - fn update_id_graph_hash_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "update_id_graph_hash") - } - - fn identity_linked_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "identity_linked") - } - - fn identity_deactivated_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "identity_deactivated") - } - - fn identity_activated_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "identity_activated") - } - - fn identity_networks_set_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "identity_networks_set") - } - - fn imp_some_error_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(IMP, "some_error") - } -} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teebag.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teebag.rs new file mode 100644 index 0000000000..b748dd632f --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teebag.rs @@ -0,0 +1,71 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{error::Result, NodeMetadata}; + +/// Pallet' name: +pub const TEEBAG: &str = "Teebag"; + +// we only list the extrinsics that we care +pub trait TeebagCallIndexes { + fn set_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn remove_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]>; + + fn post_opaque_task_call_indexes(&self) -> Result<[u8; 2]>; + + fn parentchain_block_processed_call_indexes(&self) -> Result<[u8; 2]>; + + fn sidechain_block_imported_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl TeebagCallIndexes for NodeMetadata { + fn set_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "set_scheduled_enclave") + } + fn remove_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "remove_scheduled_enclave") + } + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "register_enclave") + } + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "unregister_enclave") + } + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "register_quoting_enclave") + } + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "register_tcb_info") + } + fn post_opaque_task_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "post_opaque_task") + } + fn parentchain_block_processed_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "parentchain_block_processed") + } + fn sidechain_block_imported_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "sidechain_block_imported") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs deleted file mode 100644 index 0d10003514..0000000000 --- a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{error::Result, NodeMetadata}; - -/// Pallet' name: -pub const TEERACLE: &str = "Teeracle"; - -pub trait TeeracleCallIndexes { - fn add_to_whitelist_call_indexes(&self) -> Result<[u8; 2]>; - fn remove_from_whitelist_call_indexes(&self) -> Result<[u8; 2]>; - fn update_exchange_rate_call_indexes(&self) -> Result<[u8; 2]>; - fn update_oracle_call_indexes(&self) -> Result<[u8; 2]>; -} - -impl TeeracleCallIndexes for NodeMetadata { - fn add_to_whitelist_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEERACLE, "add_to_whitelist") - } - - fn remove_from_whitelist_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEERACLE, "remove_from_whitelist") - } - - fn update_exchange_rate_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEERACLE, "update_exchange_rate") - } - - fn update_oracle_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEERACLE, "update_oracle") - } -} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs deleted file mode 100644 index d2cd618e80..0000000000 --- a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -use crate::{error::Result, NodeMetadata}; -use sp_core::storage::StorageKey; - -/// Pallet' name: -pub const TEEREX: &str = "Teerex"; - -pub trait TeerexCallIndexes { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]>; - - fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]>; - - fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]>; - - fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]>; - - fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]>; - - fn invoke_call_indexes(&self) -> Result<[u8; 2]>; - - fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]>; - - fn shield_funds_call_indexes(&self) -> Result<[u8; 2]>; - - fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]>; - - fn publish_hash_call_indexes(&self) -> Result<[u8; 2]>; - - // litentry - fn update_scheduled_enclave(&self) -> Result<[u8; 2]>; - - fn remove_scheduled_enclave(&self) -> Result<[u8; 2]>; -} - -pub trait TeerexStorageKey { - fn sovereign_enclaves_storage_map_key(&self, index: u64) -> Result; - - fn proxied_enclaves_storage_map_key(&self, index: u64) -> Result; -} - -impl TeerexCallIndexes for NodeMetadata { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "register_enclave") - } - - fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "unregister_sovereign_enclave") - } - - fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "unregister_proxied_enclave") - } - - fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "register_quoting_enclave") - } - - fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "register_tcb_info") - } - - /* Keep parachain extrinsic name untouched. Keep alignment with upstream worker */ - fn invoke_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "call_worker") - } - - fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "confirm_processed_parentchain_block") - } - - fn shield_funds_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "shield_funds") - } - - fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "unshield_funds") - } - - fn publish_hash_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "publish_hash") - } - - fn update_scheduled_enclave(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "update_scheduled_enclave") - } - - fn remove_scheduled_enclave(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "remove_scheduled_enclave") - } -} - -impl TeerexStorageKey for NodeMetadata { - fn sovereign_enclaves_storage_map_key(&self, index: u64) -> Result { - self.storage_map_key(TEEREX, "SovereignEnclaves", index) - } - fn proxied_enclaves_storage_map_key(&self, index: u64) -> Result { - self.storage_map_key(TEEREX, "ProxiedEnclaves", index) - } -} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_utility.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_utility.rs index 909e4a7d30..0eeef1339a 100644 --- a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_utility.rs +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_utility.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_vcmp.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_vcmp.rs deleted file mode 100644 index 210d55e74f..0000000000 --- a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_vcmp.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020-2023 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -// TODO: maybe use macros to simplify this -use crate::{error::Result, NodeMetadata}; - -const VCMP: &str = "VCManagement"; - -pub trait VCMPCallIndexes { - fn request_vc_call_indexes(&self) -> Result<[u8; 2]>; - - fn vc_issued_call_indexes(&self) -> Result<[u8; 2]>; - - fn vcmp_some_error_call_indexes(&self) -> Result<[u8; 2]>; -} - -impl VCMPCallIndexes for NodeMetadata { - fn request_vc_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(VCMP, "request_vc") - } - - fn vc_issued_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(VCMP, "vc_issued") - } - - fn vcmp_some_error_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(VCMP, "some_error") - } -} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/runtime_call.rs b/bitacross-worker/core-primitives/node-api/metadata/src/runtime_call.rs index a484e6f779..8fa69cc9ad 100644 --- a/bitacross-worker/core-primitives/node-api/metadata/src/runtime_call.rs +++ b/bitacross-worker/core-primitives/node-api/metadata/src/runtime_call.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/core-primitives/ocall-api/src/lib.rs b/bitacross-worker/core-primitives/ocall-api/src/lib.rs index d4a0a9b944..2366dd00f1 100644 --- a/bitacross-worker/core-primitives/ocall-api/src/lib.rs +++ b/bitacross-worker/core-primitives/ocall-api/src/lib.rs @@ -19,14 +19,14 @@ pub extern crate alloc; -use alloc::{string::String, vec::Vec}; +use alloc::vec::Vec; use codec::{Decode, Encode}; use core::result::Result as StdResult; use derive_more::{Display, From}; use itp_storage::Error as StorageError; use itp_types::{ - parentchain::ParentchainId, storage::StorageEntryVerified, BlockHash, ShardIdentifier, - TrustedOperationStatus, WorkerRequest, WorkerResponse, + parentchain::ParentchainId, storage::StorageEntryVerified, TrustedOperationStatus, + WorkerRequest, WorkerResponse, }; use sgx_types::*; use sp_core::H256; @@ -126,27 +126,6 @@ pub trait EnclaveMetricsOCallApi: Clone + Send + Sync { fn update_metric(&self, metric: Metric) -> SgxResult<()>; } -pub trait EnclaveSidechainOCallApi: Clone + Send + Sync { - fn propose_sidechain_blocks( - &self, - signed_blocks: Vec, - ) -> SgxResult<()>; - - fn store_sidechain_blocks( - &self, - signed_blocks: Vec, - ) -> SgxResult<()>; - - fn fetch_sidechain_blocks_from_peer( - &self, - last_imported_block_hash: BlockHash, - maybe_until_block_hash: Option, - shard_identifier: ShardIdentifier, - ) -> SgxResult>; - - fn get_trusted_peers_urls(&self) -> SgxResult>; -} - /// Newtype for IPFS CID pub struct IpfsCid(pub [u8; 46]); diff --git a/bitacross-worker/core-primitives/settings/Cargo.toml b/bitacross-worker/core-primitives/settings/Cargo.toml index bf48cd4ec2..5248c07308 100644 --- a/bitacross-worker/core-primitives/settings/Cargo.toml +++ b/bitacross-worker/core-primitives/settings/Cargo.toml @@ -6,9 +6,7 @@ edition = "2021" [dependencies] - [features] -production = [] -sidechain = [] +production = [ +] offchain-worker = [] -teeracle = [] diff --git a/bitacross-worker/core-primitives/settings/src/lib.rs b/bitacross-worker/core-primitives/settings/src/lib.rs index bc3ca98dcf..74e9838a75 100644 --- a/bitacross-worker/core-primitives/settings/src/lib.rs +++ b/bitacross-worker/core-primitives/settings/src/lib.rs @@ -19,31 +19,16 @@ #![no_std] -#[cfg(any( - all(feature = "sidechain", feature = "offchain-worker"), - all(feature = "sidechain", feature = "teeracle"), - all(feature = "teeracle", feature = "offchain-worker") -))] -compile_error!( - "feature \"sidechain\" , \"offchain-worker\" or \"teeracle\" cannot be enabled at the same time" -); - -pub mod worker_mode; - pub mod files { // used by worker pub static ENCLAVE_TOKEN: &str = "enclave.token"; pub static ENCLAVE_FILE: &str = "enclave.signed.so"; pub static SHIELDING_KEY_FILE: &str = "enclave-shielding-pubkey.json"; pub static SIGNING_KEY_FILE: &str = "enclave-signing-pubkey.bin"; - /// sidechain database path - pub static SIDECHAIN_STORAGE_PATH: &str = "sidechain_db"; - pub static SIDECHAIN_PURGE_INTERVAL: u64 = 7200; // purge sidechain every .. s - pub static SIDECHAIN_PURGE_LIMIT: u64 = 100; // keep the last.. sidechainblocks when purging // used by enclave /// Path to the light-client db for the Integritee parentchain. - pub const LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "integritee_lcdb"; + pub const LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "litentry_lcdb"; /// Path to the light-client db for the Target A parentchain. pub const TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "target_a_lcdb"; @@ -54,6 +39,9 @@ pub mod files { // litentry pub const SCHEDULED_ENCLAVE_FILE: &str = "scheduled_enclave_sealed.bin"; + // bitacross + pub const RELAYER_REGISTRY_FILE: &str = "relayer_registry_sealed.bin"; + pub const RA_DUMP_CERT_DER_FILE: &str = "ra_dump_cert.der"; // used by worker and enclave @@ -104,17 +92,3 @@ pub mod sidechain { pub static SLOT_DURATION: Duration = Duration::from_millis(6000); } - -/// Settings concerning the enclave -pub mod enclave {} - -/// Settings for the Teeracle -pub mod teeracle { - use core::time::Duration; - // Send extrinsic to update market exchange rate on the parentchain once per day - pub static DEFAULT_MARKET_DATA_UPDATE_INTERVAL: Duration = ONE_DAY; - - pub static ONE_DAY: Duration = Duration::from_secs(86400); - - pub static THIRTY_MINUTES: Duration = Duration::from_secs(1800); -} diff --git a/bitacross-worker/core-primitives/settings/src/worker_mode.rs b/bitacross-worker/core-primitives/settings/src/worker_mode.rs deleted file mode 100644 index 7eef1144fa..0000000000 --- a/bitacross-worker/core-primitives/settings/src/worker_mode.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[derive(Eq, PartialEq, Debug, Clone)] -pub enum WorkerMode { - OffChainWorker, - Sidechain, - Teeracle, -} - -pub trait ProvideWorkerMode { - fn worker_mode() -> WorkerMode; -} - -#[derive(Default, Copy, Clone)] -pub struct WorkerModeProvider; - -#[cfg(feature = "offchain-worker")] -impl ProvideWorkerMode for WorkerModeProvider { - fn worker_mode() -> WorkerMode { - WorkerMode::OffChainWorker - } -} - -#[cfg(feature = "teeracle")] -impl ProvideWorkerMode for WorkerModeProvider { - fn worker_mode() -> WorkerMode { - WorkerMode::Teeracle - } -} - -#[cfg(feature = "sidechain")] -impl ProvideWorkerMode for WorkerModeProvider { - fn worker_mode() -> WorkerMode { - WorkerMode::Sidechain - } -} - -// Default to `Sidechain` worker mode when no cargo features are set. -#[cfg(not(any(feature = "sidechain", feature = "teeracle", feature = "offchain-worker")))] -impl ProvideWorkerMode for WorkerModeProvider { - fn worker_mode() -> WorkerMode { - WorkerMode::Sidechain - } -} diff --git a/bitacross-worker/core-primitives/sgx-runtime-primitives/Cargo.toml b/bitacross-worker/core-primitives/sgx-runtime-primitives/Cargo.toml index 8ec87045fa..5290e8da32 100644 --- a/bitacross-worker/core-primitives/sgx-runtime-primitives/Cargo.toml +++ b/bitacross-worker/core-primitives/sgx-runtime-primitives/Cargo.toml @@ -12,9 +12,6 @@ pallet-balances = { default-features = false, git = "https://github.com/parityte sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -# litentry -litentry-primitives = { path = "../../litentry/primitives", default-features = false } - [features] default = ["std"] std = [ @@ -22,6 +19,4 @@ std = [ "pallet-balances/std", "sp-core/std", "sp-runtime/std", - # litentry - "litentry-primitives/std", ] diff --git a/bitacross-worker/core-primitives/sgx-runtime-primitives/src/types.rs b/bitacross-worker/core-primitives/sgx-runtime-primitives/src/types.rs index bad667791e..035ae982b8 100644 --- a/bitacross-worker/core-primitives/sgx-runtime-primitives/src/types.rs +++ b/bitacross-worker/core-primitives/sgx-runtime-primitives/src/types.rs @@ -21,8 +21,6 @@ use sp_runtime::{ MultiSignature, OpaqueExtrinsic, }; -use litentry_primitives::ParentchainAccountId; - /// The address format for describing accounts. pub type Address = sp_runtime::MultiAddress; /// Block header type as expected by this sgx-runtime. @@ -66,21 +64,3 @@ pub type Block = BlockG; pub type SignedBlock = SignedBlockG; pub type BlockHash = sp_core::H256; pub type ShardIdentifier = sp_core::H256; - -// litentry -pub trait ConvertAccountId { - type Input; - type Output; - fn convert(input: Self::Input) -> Self::Output; -} - -pub struct SgxParentchainTypeConverter; - -impl ConvertAccountId for SgxParentchainTypeConverter { - type Input = AccountId; - type Output = ParentchainAccountId; - fn convert(a: AccountId) -> ParentchainAccountId { - // it's an identity converter - a as ParentchainAccountId - } -} diff --git a/bitacross-worker/core-primitives/sgx/crypto/Cargo.toml b/bitacross-worker/core-primitives/sgx/crypto/Cargo.toml index fd8a971e49..1663c6c5f9 100644 --- a/bitacross-worker/core-primitives/sgx/crypto/Cargo.toml +++ b/bitacross-worker/core-primitives/sgx/crypto/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" aes = { version = "0.6.0" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } derive_more = { version = "0.99.5" } +k256 = { version = "0.13.3", default-features = false, features = ["ecdsa-core", "schnorr", "alloc"] } log = { version = "0.4", default-features = false } ofb = { version = "0.4.0" } serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true } diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/ecdsa.rs b/bitacross-worker/core-primitives/sgx/crypto/src/ecdsa.rs new file mode 100644 index 0000000000..7bb8ce0cb7 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/ecdsa.rs @@ -0,0 +1,219 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . +#[cfg(feature = "sgx")] +pub use sgx::*; + +use crate::error::{Error, Result}; +use k256::{ + ecdsa::{SigningKey, VerifyingKey}, + elliptic_curve::group::GroupEncoding, + PublicKey, +}; +use std::string::ToString; + +/// File name of the sealed seed file. +pub const SEALED_SIGNER_SEED_FILE: &str = "ecdsa_key_sealed.bin"; + +#[derive(Clone, PartialEq, Eq)] +pub struct Pair { + pub public: PublicKey, + private: SigningKey, +} + +impl Pair { + pub fn new(private: SigningKey) -> Self { + let public = PublicKey::from(VerifyingKey::from(&private)); + Self { private, public } + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + let private_key = SigningKey::from_bytes(bytes.into()) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(Self::new(private_key)) + } + + pub fn public_bytes(&self) -> [u8; 33] { + self.public.as_affine().to_bytes().as_slice().try_into().unwrap() + } + + pub fn private_bytes(&self) -> [u8; 32] { + self.private.to_bytes().as_slice().try_into().unwrap() + } + + // sign the prehashed message + pub fn sign_prehash_recoverable(&self, payload: &[u8]) -> Result<[u8; 65]> { + let (signature, rid) = self + .private + .sign_prehash_recoverable(payload) + .map_err(|e| Error::Other(e.to_string().into()))?; + let mut bytes = [0u8; 65]; + bytes[..64].copy_from_slice(signature.to_vec().as_slice()); + bytes[64] = rid.to_byte(); + Ok(bytes) + } +} + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::SEALED_SIGNER_SEED_FILE; + use crate::{ + ecdsa::Pair, + error::{Error, Result}, + key_repository::KeyRepository, + std::string::ToString, + }; + use itp_sgx_io::{seal, unseal, SealedIO}; + use k256::ecdsa::SigningKey; + use log::*; + use sgx_rand::{Rng, StdRng}; + use std::{path::PathBuf, string::String}; + + /// Creates a repository for ecdsa keypair and initializes + /// a fresh private key if it doesn't exist at `path`. + pub fn create_ecdsa_repository( + path: PathBuf, + key_file_prefix: &str, + ) -> Result> { + let seal = Seal::new(path, key_file_prefix.to_string()); + Ok(KeyRepository::new(seal.init()?, seal.into())) + } + + #[derive(Clone, Debug)] + pub struct Seal { + base_path: PathBuf, + key_file_prefix: String, + } + + impl Seal { + pub fn new(base_path: PathBuf, key_file_prefix: String) -> Self { + Self { base_path, key_file_prefix } + } + + pub fn path(&self) -> PathBuf { + self.base_path + .join(self.key_file_prefix.clone() + "_" + SEALED_SIGNER_SEED_FILE) + } + + fn unseal_pair(&self) -> Result { + self.unseal() + } + + pub fn exists(&self) -> bool { + self.path().exists() + } + + pub fn init(&self) -> Result { + if !self.exists() { + info!("Keyfile not found, creating new! {}", self.path().display()); + let mut seed = [0u8; 32]; + let mut rand = StdRng::new()?; + rand.fill_bytes(&mut seed); + seal(&seed, self.path())?; + } + self.unseal_pair() + } + } + + impl SealedIO for Seal { + type Error = Error; + type Unsealed = Pair; + + fn unseal(&self) -> Result { + let raw = unseal(self.path())?; + let secret = SigningKey::from_slice(&raw) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(Pair::new(secret)) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + let raw = unsealed.private.to_bytes(); + seal(&raw, self.path()).map_err(|e| e.into()) + } + } +} + +#[cfg(feature = "test")] +pub mod sgx_tests { + use crate::{ + create_ecdsa_repository, key_repository::AccessKey, std::string::ToString, Pair, Seal, + }; + use itp_sgx_temp_dir::TempDir; + use k256::ecdsa::VerifyingKey; + use sgx_tstd::path::PathBuf; + + pub fn ecdsa_creating_repository_with_same_path_and_prefix_results_in_same_key() { + //given + let key_file_prefix = "test"; + fn get_key_from_repo(path: PathBuf, prefix: &str) -> Pair { + create_ecdsa_repository(path, prefix).unwrap().retrieve_key().unwrap() + } + let temp_dir = TempDir::with_prefix( + "creating_repository_with_same_path_and_prefix_results_in_same_key", + ) + .unwrap(); + let temp_path = temp_dir.path().to_path_buf(); + + //when + let first_key = get_key_from_repo(temp_path.clone(), key_file_prefix); + let second_key = get_key_from_repo(temp_path.clone(), key_file_prefix); + + //then + assert_eq!(first_key.public, second_key.public); + } + + pub fn ecdsa_seal_init_should_create_new_key_if_not_present() { + //given + let temp_dir = + TempDir::with_prefix("ecdsa_seal_init_should_create_new_key_if_not_present").unwrap(); + let seal = Seal::new(temp_dir.path().to_path_buf(), "test".to_string()); + assert!(!seal.exists()); + + //when + seal.init().unwrap(); + + //then + assert!(seal.exists()); + } + + pub fn ecdsa_seal_init_should_not_change_key_if_exists() { + //given + let temp_dir = + TempDir::with_prefix("ecdsa_seal_init_should_not_change_key_if_exists").unwrap(); + let seal = Seal::new(temp_dir.path().to_path_buf(), "test".to_string()); + let pair = seal.init().unwrap(); + + //when + let new_pair = seal.init().unwrap(); + + //then + assert_eq!(pair.public, new_pair.public); + } + + pub fn ecdsa_sign_should_produce_valid_signature() { + //given + let temp_dir = TempDir::with_prefix("ecdsa_sign_should_produce_valid_signature").unwrap(); + let seal = Seal::new(temp_dir.path().to_path_buf(), "test".to_string()); + let pair = seal.init().unwrap(); + let message = [1u8; 32]; + + //when + let (signature, rid) = &pair.private.sign_prehash_recoverable(&message).unwrap(); + + //then + let verifying_key = VerifyingKey::recover_from_prehash(&message, signature, *rid).unwrap(); + assert_eq!(verifying_key, VerifyingKey::from(&pair.private)); + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/lib.rs b/bitacross-worker/core-primitives/sgx/crypto/src/lib.rs index 832239c027..27b6b99028 100644 --- a/bitacross-worker/core-primitives/sgx/crypto/src/lib.rs +++ b/bitacross-worker/core-primitives/sgx/crypto/src/lib.rs @@ -33,14 +33,16 @@ pub mod sgx_reexport_prelude { } pub mod aes; +pub mod ecdsa; pub mod ed25519; pub mod ed25519_derivation; pub mod error; pub mod key_repository; pub mod rsa3072; +pub mod schnorr; pub mod traits; -pub use self::{aes::*, ed25519::*, rsa3072::*}; +pub use self::{aes::*, ecdsa::*, ed25519::*, rsa3072::*}; pub use error::*; pub use traits::*; @@ -60,4 +62,17 @@ pub mod tests { pub use super::aes::sgx_tests::{ aes_sealing_works, using_get_aes_repository_twice_initializes_key_only_once, }; + + pub use super::ecdsa::sgx_tests::{ + ecdsa_creating_repository_with_same_path_and_prefix_results_in_same_key, + ecdsa_seal_init_should_create_new_key_if_not_present, + ecdsa_seal_init_should_not_change_key_if_exists, ecdsa_sign_should_produce_valid_signature, + }; + + pub use super::schnorr::sgx_tests::{ + schnorr_creating_repository_with_same_path_and_prefix_results_in_same_key, + schnorr_seal_init_should_create_new_key_if_not_present, + schnorr_seal_init_should_not_change_key_if_exists, + schnorr_sign_should_produce_valid_signature, + }; } diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/mocks.rs b/bitacross-worker/core-primitives/sgx/crypto/src/mocks.rs index 0e199378fd..a871943806 100644 --- a/bitacross-worker/core-primitives/sgx/crypto/src/mocks.rs +++ b/bitacross-worker/core-primitives/sgx/crypto/src/mocks.rs @@ -32,14 +32,14 @@ use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; #[derive(Default)] pub struct KeyRepositoryMock where - KeyType: Clone + Default, + KeyType: Clone, { key: RwLock, } impl KeyRepositoryMock where - KeyType: Clone + Default, + KeyType: Clone, { pub fn new(key: KeyType) -> Self { KeyRepositoryMock { key: RwLock::new(key) } @@ -48,7 +48,7 @@ where impl AccessKey for KeyRepositoryMock where - KeyType: Clone + Default, + KeyType: Clone, { type KeyType = KeyType; @@ -59,7 +59,7 @@ where impl MutateKey for KeyRepositoryMock where - KeyType: Clone + Default, + KeyType: Clone, { fn update_key(&self, key: KeyType) -> Result<()> { let mut lock = self.key.write().unwrap(); diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/schnorr.rs b/bitacross-worker/core-primitives/sgx/crypto/src/schnorr.rs new file mode 100644 index 0000000000..ca32644ad7 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/schnorr.rs @@ -0,0 +1,219 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . +#[cfg(feature = "sgx")] +pub use sgx::*; + +use crate::error::{Error, Result}; +use k256::{ + elliptic_curve::group::GroupEncoding, + schnorr::{signature::Signer, Signature, SigningKey}, + PublicKey, +}; +use std::string::ToString; + +/// File name of the sealed seed file. +pub const SEALED_SIGNER_SEED_FILE: &str = "schnorr_key_sealed.bin"; + +#[derive(Clone)] +pub struct Pair { + pub public: PublicKey, + private: SigningKey, +} + +impl Pair { + pub fn new(private: SigningKey) -> Self { + let public = PublicKey::from(private.verifying_key()); + Self { private, public } + } + + pub fn from_bytes(bytes: &[u8]) -> Result { + let private_key = + SigningKey::from_bytes(bytes).map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(Self::new(private_key)) + } + + pub fn public_bytes(&self) -> [u8; 33] { + // safe to unwrap here + self.public.as_affine().to_bytes().as_slice().try_into().unwrap() + } + + pub fn private_bytes(&self) -> [u8; 32] { + // safe to unwrap here + self.private.to_bytes().as_slice().try_into().unwrap() + } + + pub fn sign(&self, payload: &[u8]) -> Result<[u8; 64]> { + let signature: Signature = + self.private.try_sign(payload).map_err(|e| Error::Other(e.to_string().into()))?; + Ok(signature.to_bytes()) + } +} + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::SEALED_SIGNER_SEED_FILE; + use crate::{ + error::{Error, Result}, + key_repository::KeyRepository, + schnorr::Pair, + std::string::ToString, + }; + use itp_sgx_io::{seal, unseal, SealedIO}; + use k256::schnorr::SigningKey; + use log::*; + use sgx_rand::{Rng, StdRng}; + use std::{path::PathBuf, string::String}; + + /// Creates a repository for schnorr keypair and initializes + /// a fresh private key if it doesn't exist at `path`. + pub fn create_schnorr_repository( + path: PathBuf, + key_file_prefix: &str, + ) -> Result> { + let seal = Seal::new(path, key_file_prefix.to_string()); + Ok(KeyRepository::new(seal.init()?, seal.into())) + } + + #[derive(Clone, Debug)] + pub struct Seal { + base_path: PathBuf, + key_file_prefix: String, + } + + impl Seal { + pub fn new(base_path: PathBuf, key_file_prefix: String) -> Self { + Self { base_path, key_file_prefix } + } + + pub fn path(&self) -> PathBuf { + self.base_path + .join(self.key_file_prefix.clone() + "_" + SEALED_SIGNER_SEED_FILE) + } + } + + impl Seal { + fn unseal_pair(&self) -> Result { + self.unseal() + } + + pub fn exists(&self) -> bool { + self.path().exists() + } + + pub fn init(&self) -> Result { + if !self.exists() { + info!("Keyfile not found, creating new! {}", self.path().display()); + let mut seed = [0u8; 32]; + let mut rand = StdRng::new()?; + rand.fill_bytes(&mut seed); + seal(&seed, self.path())?; + } + self.unseal_pair() + } + } + + impl SealedIO for Seal { + type Error = Error; + type Unsealed = Pair; + + fn unseal(&self) -> Result { + let raw = unseal(self.path())?; + let secret = SigningKey::from_bytes(&raw) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(Pair::new(secret)) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + let raw = unsealed.private.to_bytes(); + seal(&raw, self.path()).map_err(|e| e.into()) + } + } +} + +#[cfg(feature = "test")] +pub mod sgx_tests { + use crate::{ + key_repository::AccessKey, + schnorr::{create_schnorr_repository, Pair, Seal}, + std::string::ToString, + }; + use itp_sgx_temp_dir::TempDir; + use k256::schnorr::{signature::Verifier, Signature, VerifyingKey}; + use std::path::PathBuf; + + pub fn schnorr_creating_repository_with_same_path_and_prefix_results_in_same_key() { + //given + let key_file_prefix = "test"; + fn get_key_from_repo(path: PathBuf, prefix: &str) -> Pair { + create_schnorr_repository(path, prefix).unwrap().retrieve_key().unwrap() + } + let temp_dir = TempDir::with_prefix( + "schnorr_creating_repository_with_same_path_and_prefix_results_in_same_key", + ) + .unwrap(); + let temp_path = temp_dir.path().to_path_buf(); + + //when + let first_key = get_key_from_repo(temp_path.clone(), key_file_prefix); + let second_key = get_key_from_repo(temp_path.clone(), key_file_prefix); + + //then + assert_eq!(first_key.public, second_key.public); + } + + pub fn schnorr_seal_init_should_create_new_key_if_not_present() { + //given + let temp_dir = + TempDir::with_prefix("schnorr_seal_init_should_create_new_key_if_not_present").unwrap(); + let seal = Seal::new(temp_dir.path().to_path_buf(), "test".to_string()); + assert!(!seal.exists()); + + //when + seal.init().unwrap(); + + //then + assert!(seal.exists()); + } + + pub fn schnorr_seal_init_should_not_change_key_if_exists() { + //given + let temp_dir = + TempDir::with_prefix("schnorr_seal_init_should_not_change_key_if_exists").unwrap(); + let seal = Seal::new(temp_dir.path().to_path_buf(), "test".to_string()); + let pair = seal.init().unwrap(); + + //when + let new_pair = seal.init().unwrap(); + + //then + assert_eq!(pair.public, new_pair.public); + } + + pub fn schnorr_sign_should_produce_valid_signature() { + //given + let temp_dir = TempDir::with_prefix("ecdsa_sign_should_produce_valid_signature").unwrap(); + let seal = Seal::new(temp_dir.path().to_path_buf(), "test".to_string()); + let pair = seal.init().unwrap(); + let message = [1; 32]; + + //when + let signature = Signature::try_from(pair.sign(&message).unwrap().as_slice()).unwrap(); + + //then + let verifying_key = VerifyingKey::try_from(&pair.public).unwrap(); + assert!(verifying_key.verify(&message, &signature).is_ok()); + } +} diff --git a/bitacross-worker/core-primitives/stf-executor/Cargo.toml b/bitacross-worker/core-primitives/stf-executor/Cargo.toml index 0b34106bc4..3a2b6d5e9b 100644 --- a/bitacross-worker/core-primitives/stf-executor/Cargo.toml +++ b/bitacross-worker/core-primitives/stf-executor/Cargo.toml @@ -12,7 +12,6 @@ sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sd sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } # local dependencies -itp-enclave-metrics = { path = "../enclave-metrics", default-features = false } itp-node-api = { path = "../node-api", default-features = false } itp-ocall-api = { path = "../ocall-api", default-features = false } itp-sgx-crypto = { path = "../sgx/crypto", default-features = false } @@ -43,9 +42,6 @@ sp-runtime = { default-features = false, git = "https://github.com/paritytech/su itc-parentchain-test = { path = "../../core/parentchain/test", optional = true, default-features = false } itp-test = { path = "../test", default-features = false, optional = true } -# litentry -litentry-primitives = { path = "../../litentry/primitives", default-features = false } - [dev-dependencies] itp-stf-state-observer = { path = "../stf-state-observer", features = ["mocks"] } itp-stf-interface = { path = "../stf-interface", features = ["mocks"] } @@ -73,8 +69,6 @@ std = [ "sp-core/std", "sp-runtime/std", "thiserror", - # litentry - "litentry-primitives/std", ] sgx = [ "sgx_tstd", @@ -86,8 +80,6 @@ sgx = [ "itp-top-pool-author/sgx", "itp-time-utils/sgx", "thiserror_sgx", - # litentry - "litentry-primitives/sgx", ] test = [ "itc-parentchain-test", diff --git a/bitacross-worker/core-primitives/stf-executor/src/executor.rs b/bitacross-worker/core-primitives/stf-executor/src/executor.rs index a980563774..42a2f9b6e9 100644 --- a/bitacross-worker/core-primitives/stf-executor/src/executor.rs +++ b/bitacross-worker/core-primitives/stf-executor/src/executor.rs @@ -21,7 +21,6 @@ use crate::{ BatchExecutionResult, ExecutedOperation, }; use codec::{Decode, Encode}; -use itp_enclave_metrics::EnclaveMetric; use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; use itp_ocall_api::{EnclaveAttestationOCallApi, EnclaveMetricsOCallApi, EnclaveOnChainOCallApi}; use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; @@ -43,8 +42,8 @@ use itp_types::{ use log::*; use sp_runtime::traits::Header as HeaderTrait; use std::{ - collections::BTreeMap, fmt::Debug, marker::PhantomData, string::ToString, sync::Arc, - time::Duration, vec, vec::Vec, + collections::BTreeMap, fmt::Debug, marker::PhantomData, sync::Arc, time::Duration, vec, + vec::Vec, }; pub struct StfExecutor diff --git a/bitacross-worker/core-primitives/stf-interface/src/runtime_upgrade.rs b/bitacross-worker/core-primitives/stf-interface/src/runtime_upgrade.rs index 30ee22140e..649ba34ca5 100644 --- a/bitacross-worker/core-primitives/stf-interface/src/runtime_upgrade.rs +++ b/bitacross-worker/core-primitives/stf-interface/src/runtime_upgrade.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/core-primitives/stf-primitives/src/error.rs b/bitacross-worker/core-primitives/stf-primitives/src/error.rs index c69514f109..a4fa844a88 100644 --- a/bitacross-worker/core-primitives/stf-primitives/src/error.rs +++ b/bitacross-worker/core-primitives/stf-primitives/src/error.rs @@ -15,10 +15,9 @@ */ use crate::types::{AccountId, Nonce}; -use alloc::{format, string::String}; +use alloc::string::String; use codec::{Decode, Encode}; use derive_more::Display; -use litentry_primitives::{Assertion, ErrorDetail, ErrorString, IMPError, VCMPError}; pub type StfResult = Result; @@ -45,74 +44,6 @@ pub enum StfError { InvalidStorageDiff, #[codec(index = 7)] InvalidMetadata, - // litentry #[codec(index = 8)] - #[display(fmt = "LinkIdentityFailed: {:?}", _0)] - LinkIdentityFailed(ErrorDetail), - #[codec(index = 9)] - #[display(fmt = "DeactivateIdentityFailed: {:?}", _0)] - DeactivateIdentityFailed(ErrorDetail), - #[codec(index = 10)] - #[display(fmt = "ActivateIdentityFailed: {:?}", _0)] - ActivateIdentityFailed(ErrorDetail), - #[codec(index = 11)] - #[display(fmt = "RequestVCFailed: {:?} {:?}", _0, _1)] - RequestVCFailed(Assertion, ErrorDetail), - #[codec(index = 12)] - SetScheduledMrEnclaveFailed, - #[codec(index = 13)] - #[display(fmt = "SetIdentityNetworksFailed: {:?}", _0)] - SetIdentityNetworksFailed(ErrorDetail), - #[codec(index = 14)] InvalidAccount, - #[codec(index = 15)] - UnclassifiedError, - #[codec(index = 16)] - #[display(fmt = "RemovingIdentityFailed: {:?}", _0)] - RemoveIdentityFailed(ErrorDetail), - #[codec(index = 17)] - EmptyIDGraph, -} - -impl From for StfError { - fn from(e: IMPError) -> Self { - match e { - IMPError::LinkIdentityFailed(d) => StfError::LinkIdentityFailed(d), - IMPError::DeactivateIdentityFailed(d) => StfError::DeactivateIdentityFailed(d), - IMPError::ActivateIdentityFailed(d) => StfError::ActivateIdentityFailed(d), - _ => StfError::UnclassifiedError, - } - } -} - -impl From for StfError { - fn from(e: VCMPError) -> Self { - match e { - VCMPError::RequestVCFailed(a, d) => StfError::RequestVCFailed(a, d), - _ => StfError::UnclassifiedError, - } - } -} - -impl StfError { - // Convert StfError to IMPError that would be sent to parentchain - pub fn to_imp_error(&self) -> IMPError { - match self { - StfError::LinkIdentityFailed(d) => IMPError::LinkIdentityFailed(d.clone()), - StfError::DeactivateIdentityFailed(d) => IMPError::DeactivateIdentityFailed(d.clone()), - StfError::ActivateIdentityFailed(d) => IMPError::ActivateIdentityFailed(d.clone()), - _ => IMPError::UnclassifiedError(ErrorDetail::StfError(ErrorString::truncate_from( - format!("{:?}", self).as_bytes().to_vec(), - ))), - } - } - // Convert StfError to VCMPError that would be sent to parentchain - pub fn to_vcmp_error(&self) -> VCMPError { - match self { - StfError::RequestVCFailed(a, d) => VCMPError::RequestVCFailed(a.clone(), d.clone()), - _ => VCMPError::UnclassifiedError(ErrorDetail::StfError(ErrorString::truncate_from( - format!("{:?}", self).as_bytes().to_vec(), - ))), - } - } } diff --git a/bitacross-worker/core-primitives/teerex-storage/Cargo.toml b/bitacross-worker/core-primitives/teerex-storage/Cargo.toml deleted file mode 100644 index ca9bafb791..0000000000 --- a/bitacross-worker/core-primitives/teerex-storage/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "itp-teerex-storage" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -#local deps -itp-storage = { path = "../storage", default-features = false } - -[features] -default = ["std"] -std = [ - "sp-std/std", - "itp-storage/std", -] diff --git a/bitacross-worker/core-primitives/teerex-storage/src/lib.rs b/bitacross-worker/core-primitives/teerex-storage/src/lib.rs deleted file mode 100644 index 706d92fcb1..0000000000 --- a/bitacross-worker/core-primitives/teerex-storage/src/lib.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -use itp_storage::{storage_map_key, storage_value_key, StorageHasher}; -use sp_std::prelude::Vec; - -pub struct TeeRexStorage; - -// Separate the prefix from the rest because in our case we changed the storage prefix due to -// the rebranding. With the below implementation of the `TeerexStorageKeys`, we could simply -// define another struct `OtherStorage`, implement `StoragePrefix` for it, and get the -// `TeerexStorageKeys` implementation for free. -pub trait StoragePrefix { - fn prefix() -> &'static str; -} - -impl StoragePrefix for TeeRexStorage { - fn prefix() -> &'static str { - "Teerex" - } -} - -pub trait TeerexStorageKeys { - fn enclave_count() -> Vec; - fn enclave(index: u64) -> Vec; -} - -impl TeerexStorageKeys for S { - fn enclave_count() -> Vec { - storage_value_key(Self::prefix(), "EnclaveCount") - } - - fn enclave(index: u64) -> Vec { - storage_map_key(Self::prefix(), "EnclaveRegistry", &index, &StorageHasher::Blake2_128Concat) - } -} diff --git a/bitacross-worker/core-primitives/test/Cargo.toml b/bitacross-worker/core-primitives/test/Cargo.toml index ff82183e77..eff1d893b5 100644 --- a/bitacross-worker/core-primitives/test/Cargo.toml +++ b/bitacross-worker/core-primitives/test/Cargo.toml @@ -29,12 +29,11 @@ itp-stf-interface = { path = "../stf-interface", default-features = false } itp-stf-primitives = { path = "../stf-primitives", default-features = false } itp-stf-state-handler = { path = "../stf-state-handler", default-features = false } itp-storage = { path = "../storage", default-features = false } -itp-teerex-storage = { path = "../teerex-storage", default-features = false } -itp-time-utils = { path = "../time-utils", default-features = false } itp-types = { path = "../types", default-features = false, features = ["test"] } # litentry hex = { version = "0.4.3", default-features = false } +lc-teebag-storage = { path = "../../litentry/core/teebag-storage", default-features = false } litentry-primitives = { path = "../../litentry/primitives", default-features = false } [features] @@ -50,8 +49,6 @@ std = [ "itp-stf-primitives/std", "itp-stf-state-handler/std", "itp-storage/std", - "itp-teerex-storage/std", - "itp-time-utils/std", "itp-types/std", "log/std", "sp-core/std", @@ -59,6 +56,7 @@ std = [ "sp-runtime/std", "sp-std/std", "litentry-primitives/std", + "lc-teebag-storage/std", ] sgx = [ "itp-node-api/sgx", @@ -66,7 +64,6 @@ sgx = [ "itp-sgx-crypto/sgx", "itp-sgx-externalities/sgx", "itp-stf-state-handler/sgx", - "itp-time-utils/sgx", "jsonrpc-core_sgx", "sgx_tstd", "litentry-primitives/sgx", diff --git a/bitacross-worker/core-primitives/test/src/builders/enclave_gen_builder.rs b/bitacross-worker/core-primitives/test/src/builders/enclave_gen_builder.rs deleted file mode 100644 index 85e807c628..0000000000 --- a/bitacross-worker/core-primitives/test/src/builders/enclave_gen_builder.rs +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use itp_time_utils::now_as_millis; -use itp_types::{Enclave, PalletString}; - -/// Builder for a generic enclave (`EnclaveGen`) struct. -pub struct EnclaveGenBuilder { - pubkey: AccountId, - mr_enclave: [u8; 32], - timestamp: u64, - url: PalletString, // utf8 encoded url -} - -impl Default for EnclaveGenBuilder -where - AccountId: Default, -{ - fn default() -> Self { - EnclaveGenBuilder { - pubkey: AccountId::default(), - mr_enclave: [0u8; 32], - timestamp: now_as_millis(), - url: PalletString::default(), - } - } -} - -impl EnclaveGenBuilder { - pub fn with_account(mut self, account: AccountId) -> Self { - self.pubkey = account; - self - } - - pub fn with_url(mut self, url: PalletString) -> Self { - self.url = url; - self - } - - pub fn build(self) -> EnclaveGen { - EnclaveGen { - pubkey: self.pubkey, - mr_enclave: self.mr_enclave, - timestamp: self.timestamp, - url: self.url, - } - } -} diff --git a/bitacross-worker/core-primitives/test/src/builders/mod.rs b/bitacross-worker/core-primitives/test/src/builders/mod.rs deleted file mode 100644 index 610066f015..0000000000 --- a/bitacross-worker/core-primitives/test/src/builders/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Builder patterns for common structs used in tests. - -pub mod enclave_gen_builder; diff --git a/bitacross-worker/core-primitives/test/src/mock/onchain_mock.rs b/bitacross-worker/core-primitives/test/src/mock/onchain_mock.rs index 22744289b5..5871396aee 100644 --- a/bitacross-worker/core-primitives/test/src/mock/onchain_mock.rs +++ b/bitacross-worker/core-primitives/test/src/mock/onchain_mock.rs @@ -18,21 +18,18 @@ use codec::{Decode, Encode}; use core::fmt::Debug; -use itp_ocall_api::{ - EnclaveAttestationOCallApi, EnclaveMetricsOCallApi, EnclaveOnChainOCallApi, - EnclaveSidechainOCallApi, -}; +use itp_ocall_api::{EnclaveAttestationOCallApi, EnclaveMetricsOCallApi, EnclaveOnChainOCallApi}; use itp_storage::Error::StorageValueUnavailable; -use itp_teerex_storage::{TeeRexStorage, TeerexStorageKeys}; use itp_types::{ - parentchain::ParentchainId, storage::StorageEntryVerified, BlockHash, Enclave, ShardIdentifier, - WorkerRequest, WorkerResponse, + parentchain::ParentchainId, storage::StorageEntryVerified, AccountId, WorkerRequest, + WorkerResponse, WorkerType, }; +use lc_teebag_storage::{TeebagStorage, TeebagStorageKeys}; use sgx_types::*; use sp_core::H256; -use sp_runtime::{traits::Header as HeaderTrait, AccountId32, OpaqueExtrinsic}; +use sp_runtime::{traits::Header as HeaderTrait, OpaqueExtrinsic}; use sp_std::prelude::*; -use std::{collections::HashMap, string::String}; +use std::collections::HashMap; #[derive(Default, Clone, Debug)] pub struct OnchainMock { @@ -55,11 +52,15 @@ impl OnchainMock { pub fn add_validateer_set>( mut self, header: &Header, - set: Option>, + set: Option>, ) -> Self { - let set = set.unwrap_or_else(validateer_set); - self.insert_at_header(header, TeeRexStorage::enclave_count(), (set.len() as u64).encode()); - self.with_storage_entries_at_header(header, into_key_value_storage(set)) + let set: Vec = set.unwrap_or_else(validateer_set); + self.insert_at_header( + header, + TeebagStorage::enclave_identifier(WorkerType::BitAcross), + set.encode(), + ); + self } pub fn with_mr_enclave(mut self, mr_enclave: [u8; SGX_HASH_SIZE]) -> Self { @@ -135,35 +136,6 @@ impl EnclaveAttestationOCallApi for OnchainMock { } } -impl EnclaveSidechainOCallApi for OnchainMock { - fn propose_sidechain_blocks( - &self, - _signed_blocks: Vec, - ) -> SgxResult<()> { - Ok(()) - } - - fn store_sidechain_blocks( - &self, - _signed_blocks: Vec, - ) -> SgxResult<()> { - Ok(()) - } - - fn fetch_sidechain_blocks_from_peer( - &self, - _last_imported_block_hash: BlockHash, - _maybe_until_block_hash: Option, - _shard_identifier: ShardIdentifier, - ) -> SgxResult> { - Ok(Vec::new()) - } - - fn get_trusted_peers_urls(&self) -> SgxResult> { - Ok(Vec::default()) - } -} - impl EnclaveMetricsOCallApi for OnchainMock { fn update_metric(&self, _metric: Metric) -> SgxResult<()> { Ok(()) @@ -224,20 +196,11 @@ impl EnclaveOnChainOCallApi for OnchainMock { } } -pub fn validateer_set() -> Vec { - let default_enclave = Enclave::new( - AccountId32::from([0; 32]), - Default::default(), - Default::default(), - Default::default(), - ); - vec![default_enclave.clone(), default_enclave.clone(), default_enclave.clone(), default_enclave] -} - -fn into_key_value_storage(validateers: Vec) -> Vec<(Vec, Enclave)> { - validateers - .into_iter() - .enumerate() - .map(|(i, e)| (TeeRexStorage::enclave(i as u64 + 1), e)) - .collect() +pub fn validateer_set() -> Vec { + vec![ + AccountId::from([0; 32]), + AccountId::from([1; 32]), + AccountId::from([2; 32]), + AccountId::from([3; 32]), + ] } diff --git a/bitacross-worker/core-primitives/test/src/mock/sidechain_ocall_api_mock.rs b/bitacross-worker/core-primitives/test/src/mock/sidechain_ocall_api_mock.rs index 0210e3bd85..640a6aa73f 100644 --- a/bitacross-worker/core-primitives/test/src/mock/sidechain_ocall_api_mock.rs +++ b/bitacross-worker/core-primitives/test/src/mock/sidechain_ocall_api_mock.rs @@ -23,10 +23,9 @@ use std::sync::RwLock; use codec::{Decode, Encode}; use core::marker::PhantomData; -use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; -use itp_types::{BlockHash, ShardIdentifier}; -use sgx_types::{sgx_status_t, SgxResult}; -use std::{string::String, vec::Vec}; +use itp_ocall_api::EnclaveMetricsOCallApi; +use sgx_types::SgxResult; +use std::vec::Vec; pub struct SidechainOCallApiMock { fetch_from_peer_blocks: Option>, @@ -80,45 +79,3 @@ where Ok(()) } } - -impl EnclaveSidechainOCallApi - for SidechainOCallApiMock -where - SignedSidechainBlockType: Clone + Encode + Decode + Send + Sync, -{ - fn propose_sidechain_blocks( - &self, - _signed_blocks: Vec, - ) -> SgxResult<()> { - Ok(()) - } - - fn store_sidechain_blocks( - &self, - _signed_blocks: Vec, - ) -> SgxResult<()> { - Ok(()) - } - - fn fetch_sidechain_blocks_from_peer( - &self, - _last_imported_block_hash: BlockHash, - _maybe_until_block_hash: Option, - _shard_identifier: ShardIdentifier, - ) -> SgxResult> { - let mut number_of_fetch_calls_lock = self.number_of_fetch_calls.write().unwrap(); - *number_of_fetch_calls_lock += 1; - - match &self.fetch_from_peer_blocks { - Some(blocks) => Ok(blocks - .iter() - .map(|b| SignedSidechainBlock::decode(&mut b.encode().as_slice()).unwrap()) - .collect()), - None => Err(sgx_status_t::SGX_ERROR_UNEXPECTED), - } - } - - fn get_trusted_peers_urls(&self) -> SgxResult> { - Ok(Vec::default()) - } -} diff --git a/bitacross-worker/core-primitives/top-pool-author/Cargo.toml b/bitacross-worker/core-primitives/top-pool-author/Cargo.toml index 191ae19ea0..6bafe2e32c 100644 --- a/bitacross-worker/core-primitives/top-pool-author/Cargo.toml +++ b/bitacross-worker/core-primitives/top-pool-author/Cargo.toml @@ -73,6 +73,4 @@ sgx = [ ] test = ["itp-test/sgx", "itp-top-pool/mocks"] mocks = ["lazy_static"] -sidechain = [] offchain-worker = [] -teeracle = [] diff --git a/bitacross-worker/core-primitives/top-pool-author/src/api.rs b/bitacross-worker/core-primitives/top-pool-author/src/api.rs index 7214e184e3..7a133dca40 100644 --- a/bitacross-worker/core-primitives/top-pool-author/src/api.rs +++ b/bitacross-worker/core-primitives/top-pool-author/src/api.rs @@ -134,9 +134,6 @@ mod tests { type TestChainApi = SidechainApi; - type Seed = [u8; 32]; - const TEST_SEED: Seed = *b"12345678901234567890123456789012"; - pub fn endowed_account() -> ed25519::Pair { ed25519::Pair::from_seed(&[42u8; 32].into()) } diff --git a/bitacross-worker/core-primitives/top-pool-author/src/author.rs b/bitacross-worker/core-primitives/top-pool-author/src/author.rs index 08cbd61ff7..49d015198f 100644 --- a/bitacross-worker/core-primitives/top-pool-author/src/author.rs +++ b/bitacross-worker/core-primitives/top-pool-author/src/author.rs @@ -58,25 +58,7 @@ use std::{ }; /// Define type of TOP filter that is used in the Author -#[cfg(feature = "sidechain")] -pub type AuthorTopFilter = crate::top_filter::CallsOnlyFilter; -#[cfg(feature = "sidechain")] -pub type BroadcastedTopFilter = crate::top_filter::DirectCallsOnlyFilter; - -#[cfg(feature = "offchain-worker")] pub type AuthorTopFilter = crate::top_filter::IndirectCallsOnlyFilter; -#[cfg(feature = "offchain-worker")] -pub type BroadcastedTopFilter = crate::top_filter::DenyAllFilter; - -#[cfg(feature = "teeracle")] // Teeracle currently does not process any trusted operations -pub type AuthorTopFilter = crate::top_filter::DenyAllFilter; -#[cfg(feature = "teeracle")] -pub type BroadcastedTopFilter = crate::top_filter::DenyAllFilter; - -#[cfg(not(any(feature = "sidechain", feature = "offchain-worker", feature = "teeracle")))] -pub type AuthorTopFilter = crate::top_filter::CallsOnlyFilter; - -#[cfg(not(any(feature = "sidechain", feature = "offchain-worker", feature = "teeracle")))] pub type BroadcastedTopFilter = crate::top_filter::DenyAllFilter; /// Currently we treat all RPC operations as externals. @@ -576,7 +558,5 @@ impl< { type Hash = TxHash; - fn on_block_imported(&self, hashes: &[Self::Hash], block_hash: SidechainBlockHash) { - self.top_pool.on_block_imported(hashes, block_hash) - } + fn on_block_imported(&self, _hashes: &[Self::Hash], _block_hash: SidechainBlockHash) {} } diff --git a/bitacross-worker/core-primitives/top-pool-author/src/author_tests.rs b/bitacross-worker/core-primitives/top-pool-author/src/author_tests.rs index 3fb0370970..9a2db01035 100644 --- a/bitacross-worker/core-primitives/top-pool-author/src/author_tests.rs +++ b/bitacross-worker/core-primitives/top-pool-author/src/author_tests.rs @@ -39,7 +39,6 @@ use itp_top_pool::mocks::trusted_operation_pool_mock::TrustedOperationPoolMock; use itp_utils::ToHexPrefixed; use litentry_primitives::BroadcastedRequest; use sgx_crypto_helper::{rsa3072::Rsa3072KeyPair, RsaKeyPair}; -use sp_core::H256; use std::sync::Arc; type TestAuthor = Author< diff --git a/bitacross-worker/core-primitives/top-pool-author/src/test_fixtures.rs b/bitacross-worker/core-primitives/top-pool-author/src/test_fixtures.rs index b46f1d3e7c..d5c83341d5 100644 --- a/bitacross-worker/core-primitives/top-pool-author/src/test_fixtures.rs +++ b/bitacross-worker/core-primitives/top-pool-author/src/test_fixtures.rs @@ -18,25 +18,9 @@ use codec::Encode; use itp_stf_primitives::types::ShardIdentifier; -use sp_core::{ed25519, Pair}; use sp_runtime::traits::{BlakeTwo256, Hash}; use std::vec; -type Seed = [u8; 32]; -const TEST_SEED: Seed = *b"12345678901234567890123456789012"; - -pub(crate) fn mr_enclave() -> [u8; 32] { - [1u8; 32] -} - pub(crate) fn shard_id() -> ShardIdentifier { BlakeTwo256::hash(vec![1u8, 2u8, 3u8].as_slice().encode().as_slice()) } - -fn alice_pair() -> ed25519::Pair { - ed25519::Pair::from_seed(b"22222678901234567890123456789012") -} - -fn bob_pair() -> ed25519::Pair { - ed25519::Pair::from_seed(b"33333378901234567890123456789012") -} diff --git a/bitacross-worker/core-primitives/top-pool/Cargo.toml b/bitacross-worker/core-primitives/top-pool/Cargo.toml index 21f6f89ea7..a7407db3a7 100644 --- a/bitacross-worker/core-primitives/top-pool/Cargo.toml +++ b/bitacross-worker/core-primitives/top-pool/Cargo.toml @@ -12,7 +12,6 @@ sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sd itc-direct-rpc-server = { path = "../../core/direct-rpc-server", default-features = false } itp-stf-primitives = { path = "../stf-primitives", default-features = false } itp-types = { path = "../types", default-features = false } -its-primitives = { path = "../../sidechain/primitives", default-features = false } # sgx enabled external libraries jsonrpc-core_sgx = { package = "jsonrpc-core", git = "https://github.com/scs/jsonrpc", branch = "no_std_v18", default-features = false, optional = true } @@ -52,7 +51,6 @@ sgx = [ std = [ "itc-direct-rpc-server/std", "itp-types/std", - "its-primitives/std", "jsonrpc-core", "linked-hash-map", "log/std", diff --git a/bitacross-worker/core-primitives/top-pool/src/basic_pool.rs b/bitacross-worker/core-primitives/top-pool/src/basic_pool.rs index 577898f4f0..d046fa72b6 100644 --- a/bitacross-worker/core-primitives/top-pool/src/basic_pool.rs +++ b/bitacross-worker/core-primitives/top-pool/src/basic_pool.rs @@ -40,7 +40,6 @@ use codec::Encode; use core::{marker::PhantomData, pin::Pin}; use itc_direct_rpc_server::SendRpcResponse; use itp_stf_primitives::{traits::PoolTransactionValidation, types::ShardIdentifier}; -use its_primitives::types::BlockHash as SidechainBlockHash; use jsonrpc_core::futures::{ channel::oneshot, future::{ready, Future, FutureExt}, @@ -244,10 +243,6 @@ where self.pool.validated_pool().ready_by_hash(hash, shard) } - fn on_block_imported(&self, hashes: &[TxHash], block_hash: SidechainBlockHash) { - self.pool.validated_pool().on_block_imported(hashes, block_hash); - } - fn update_connection_state(&self, updates: Vec<(TxHash, (Vec, bool))>) { self.pool.validated_pool().update_connection_state(updates); } diff --git a/bitacross-worker/core-primitives/top-pool/src/mocks/trusted_operation_pool_mock.rs b/bitacross-worker/core-primitives/top-pool/src/mocks/trusted_operation_pool_mock.rs index 72f5514da6..1e515d612d 100644 --- a/bitacross-worker/core-primitives/top-pool/src/mocks/trusted_operation_pool_mock.rs +++ b/bitacross-worker/core-primitives/top-pool/src/mocks/trusted_operation_pool_mock.rs @@ -36,7 +36,7 @@ use crate::{ use codec::Encode; use core::{future::Future, pin::Pin}; -use itp_types::{Block, BlockHash as SidechainBlockHash, ShardIdentifier, H256}; +use itp_types::{Block, ShardIdentifier, H256}; use jsonrpc_core::futures::future::ready; use sp_runtime::{ generic::BlockId, @@ -211,8 +211,6 @@ where unimplemented!() } - fn on_block_imported(&self, _hashes: &[TxHash], _block_hash: SidechainBlockHash) {} - fn update_connection_state(&self, _updates: Vec<(TxHash, (Vec, bool))>) {} fn swap_rpc_connection_hash(&self, _old_hash: TxHash, _new_hash: TxHash) {} diff --git a/bitacross-worker/core-primitives/top-pool/src/pool.rs b/bitacross-worker/core-primitives/top-pool/src/pool.rs index 17a8fcbd5b..42f43c645b 100644 --- a/bitacross-worker/core-primitives/top-pool/src/pool.rs +++ b/bitacross-worker/core-primitives/top-pool/src/pool.rs @@ -478,7 +478,6 @@ pub mod tests { primitives::from_low_u64_to_be_h256, }; use codec::{Decode, Encode}; - use itp_stf_primitives::types::Nonce; use itp_test::mock::stf_mock::{ mock_top_direct_trusted_call_signed, mock_trusted_call_signed, TrustedOperationMock, }; @@ -492,7 +491,6 @@ pub mod tests { use sp_application_crypto::ed25519; use sp_core::hash::H256; use sp_runtime::traits::{BlakeTwo256, Extrinsic as ExtrinsicT, Hash, Verify}; - use std::{collections::HashSet, sync::Mutex}; #[derive(Clone, PartialEq, Eq, Encode, Decode, core::fmt::Debug, Serialize, MallocSizeOf)] pub enum Extrinsic { @@ -541,16 +539,10 @@ pub mod tests { /// Test RPC responder pub type TestRpcResponder = RpcResponderMock; - const INVALID_NONCE: Nonce = 254; const SOURCE: TrustedOperationSource = TrustedOperationSource::External; #[derive(Clone, Debug, Default)] - struct TestApi { - delay: Arc>>>, - invalidate: Arc>>, - clear_requirements: Arc>>, - add_requirements: Arc>>, - } + struct TestApi {} impl ChainApi for TestApi { type Block = tests::Block; diff --git a/bitacross-worker/core-primitives/top-pool/src/primitives.rs b/bitacross-worker/core-primitives/top-pool/src/primitives.rs index d40fbabd93..acd24bb317 100644 --- a/bitacross-worker/core-primitives/top-pool/src/primitives.rs +++ b/bitacross-worker/core-primitives/top-pool/src/primitives.rs @@ -10,7 +10,6 @@ use byteorder::{BigEndian, ByteOrder}; use codec::{Decode, Encode}; use core::pin::Pin; use itp_stf_primitives::types::ShardIdentifier; -use itp_types::BlockHash as SidechainBlockHash; use jsonrpc_core::futures::{channel::mpsc::Receiver, Future, Stream}; use sp_core::H256; use sp_runtime::{ @@ -250,9 +249,6 @@ pub trait TrustedOperationPool: Send + Sync { shard: ShardIdentifier, ) -> Option>; - /// Notify the listener of top inclusion in sidechain block - fn on_block_imported(&self, hashes: &[TxHash], block_hash: SidechainBlockHash); - /// Litentry: set the rpc response value #[allow(clippy::type_complexity)] fn update_connection_state(&self, updates: Vec<(TxHash, (Vec, bool))>); diff --git a/bitacross-worker/core-primitives/types/src/lib.rs b/bitacross-worker/core-primitives/types/src/lib.rs index 911282e427..a4e378786c 100644 --- a/bitacross-worker/core-primitives/types/src/lib.rs +++ b/bitacross-worker/core-primitives/types/src/lib.rs @@ -21,53 +21,22 @@ use crate::storage::StorageEntry; use codec::{Decode, Encode}; use itp_sgx_crypto::ShieldingCryptoDecrypt; -use litentry_primitives::{decl_rsa_request, RequestAesKeyNonce}; +use litentry_primitives::decl_rsa_request; use sp_std::{boxed::Box, fmt::Debug, vec::Vec}; pub mod parentchain; pub mod storage; -/// Substrate runtimes provide no string type. Hence, for arbitrary data of varying length the -/// `Vec` is used. In the polkadot-js the typedef `Text` is used to automatically -/// utf8 decode bytes into a string. -#[cfg(not(feature = "std"))] -pub type PalletString = Vec; - -#[cfg(feature = "std")] -pub type PalletString = String; - pub use itp_sgx_runtime_primitives::types::*; -pub use litentry_primitives::{Assertion, DecryptableRequest}; +pub use litentry_primitives::{ + AttestationType, DecryptableRequest, Enclave, EnclaveFingerprint, MrEnclave, WorkerType, +}; pub use sp_core::{crypto::AccountId32 as AccountId, H256}; pub type IpfsHash = [u8; 46]; -pub type MrEnclave = [u8; 32]; - pub type CallIndex = [u8; 2]; -// pallet teerex -pub type ConfirmCallFn = (CallIndex, ShardIdentifier, H256, Vec); -pub type ShieldFundsFn = (CallIndex, Vec, Balance, ShardIdentifier); -pub type CallWorkerFn = (CallIndex, RsaRequest); - -pub type UpdateScheduledEnclaveFn = (CallIndex, SidechainBlockNumber, MrEnclave); -pub type RemoveScheduledEnclaveFn = (CallIndex, SidechainBlockNumber); - -// pallet IMP -pub type LinkIdentityParams = (ShardIdentifier, AccountId, Vec, Vec, RequestAesKeyNonce); -pub type LinkIdentityFn = (CallIndex, LinkIdentityParams); - -pub type DeactivateIdentityParams = (ShardIdentifier, Vec); -pub type DeactivateIdentityFn = (CallIndex, DeactivateIdentityParams); - -pub type ActivateIdentityParams = (ShardIdentifier, Vec); -pub type ActivateIdentityFn = (CallIndex, DeactivateIdentityParams); - -// pallet VCMP -pub type RequestVCParams = (ShardIdentifier, Assertion); -pub type RequestVCFn = (CallIndex, RequestVCParams); - -pub type Enclave = EnclaveGen; +pub type PostOpaqueTaskFn = (CallIndex, RsaRequest); /// Simple blob to hold an encoded call #[derive(Debug, PartialEq, Eq, Clone, Default)] @@ -108,23 +77,6 @@ impl DecryptableRequest for RsaRequest { } } -// Todo: move this improved enclave definition into a primitives crate in the pallet_teerex repo. -#[derive(Encode, Decode, Clone, PartialEq, sp_core::RuntimeDebug)] -pub struct EnclaveGen { - pub pubkey: AccountId, - // FIXME: this is redundant information - pub mr_enclave: [u8; 32], - pub timestamp: u64, - // unix epoch in milliseconds - pub url: PalletString, // utf8 encoded url -} - -impl EnclaveGen { - pub fn new(pubkey: AccountId, mr_enclave: [u8; 32], timestamp: u64, url: PalletString) -> Self { - Self { pubkey, mr_enclave, timestamp, url } - } -} - #[derive(Debug, Clone, PartialEq, Encode, Decode, Eq)] pub enum DirectRequestStatus { /// Direct request was successfully executed diff --git a/bitacross-worker/core-primitives/utils/Cargo.toml b/bitacross-worker/core-primitives/utils/Cargo.toml index 7c293aa011..1e8bd059ae 100644 --- a/bitacross-worker/core-primitives/utils/Cargo.toml +++ b/bitacross-worker/core-primitives/utils/Cargo.toml @@ -10,6 +10,7 @@ edition = "2021" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } +litentry-hex-utils = { path = "../../../primitives/hex", default-features = false } [features] default = ["std"] diff --git a/bitacross-worker/core-primitives/utils/src/hex.rs b/bitacross-worker/core-primitives/utils/src/hex.rs index 4c167af6f3..3b6ff8a8a8 100644 --- a/bitacross-worker/core-primitives/utils/src/hex.rs +++ b/bitacross-worker/core-primitives/utils/src/hex.rs @@ -20,8 +20,9 @@ // Todo: merge with hex_display use crate::error::{Error, Result}; -use alloc::{string::String, vec::Vec}; +use alloc::string::String; use codec::{Decode, Encode}; +use litentry_hex_utils::{decode_hex, hex_encode}; /// Trait to encode a given value to a hex string, prefixed with "0x". pub trait ToHexPrefixed { @@ -45,57 +46,16 @@ impl FromHexPrefixed for T { type Output = T; fn from_hex(msg: &str) -> Result { - let byte_array = decode_hex(msg)?; + let byte_array = decode_hex(msg).map_err(Error::Hex)?; Decode::decode(&mut byte_array.as_slice()).map_err(Error::Codec) } } -/// Hex encodes given data and preappends a "0x". -pub fn hex_encode(data: &[u8]) -> String { - let mut hex_str = hex::encode(data); - hex_str.insert_str(0, "0x"); - hex_str -} - -/// Helper method for decoding hex. -pub fn decode_hex>(message: T) -> Result> { - let message = message.as_ref(); - let message = match message { - [b'0', b'x', hex_value @ ..] => hex_value, - _ => message, - }; - - let decoded_message = hex::decode(message).map_err(Error::Hex)?; - Ok(decoded_message) -} - #[cfg(test)] mod tests { use super::*; use alloc::string::ToString; - #[test] - fn hex_encode_decode_works() { - let data = "Hello World!".to_string(); - - let hex_encoded_data = hex_encode(&data.encode()); - let decoded_data = - String::decode(&mut decode_hex(hex_encoded_data).unwrap().as_slice()).unwrap(); - - assert_eq!(data, decoded_data); - } - - #[test] - fn hex_encode_decode_works_empty_input() { - let data = String::new(); - - let hex_encoded_data = hex_encode(&data.encode()); - let decoded_data = - String::decode(&mut decode_hex(hex_encoded_data).unwrap().as_slice()).unwrap(); - - assert_eq!(data, decoded_data); - } - #[test] fn hex_encode_decode_works_empty_input_for_decode() { let data = String::new(); diff --git a/bitacross-worker/core-primitives/utils/src/lib.rs b/bitacross-worker/core-primitives/utils/src/lib.rs index d03767e6c6..297ff5090e 100644 --- a/bitacross-worker/core-primitives/utils/src/lib.rs +++ b/bitacross-worker/core-primitives/utils/src/lib.rs @@ -25,7 +25,6 @@ pub mod buffer; pub mod error; pub mod hex; pub mod hex_display; -pub mod macros; pub mod stringify; // Public re-exports. diff --git a/bitacross-worker/core/direct-rpc-client/Cargo.toml b/bitacross-worker/core/direct-rpc-client/Cargo.toml index 69631b5e40..18e30ea6a3 100644 --- a/bitacross-worker/core/direct-rpc-client/Cargo.toml +++ b/bitacross-worker/core/direct-rpc-client/Cargo.toml @@ -27,7 +27,6 @@ webpki = { version = "0.21", optional = true } itp-rpc = { path = "../../core-primitives/rpc", default-features = false } itp-types = { path = "../../core-primitives/types", default-features = false } itp-utils = { path = "../../core-primitives/utils", default-features = false } -litentry-primitives = { path = "../../litentry/primitives", default-features = false } [features] default = ["std"] @@ -38,7 +37,6 @@ sgx = [ "rustls_sgx", "sgx_tstd", "itp-rpc/sgx", - "litentry-primitives/sgx", ] std = [ "rustls", @@ -49,5 +47,4 @@ std = [ "itp-types/std", "itp-utils/std", "log/std", - "litentry-primitives/std", ] diff --git a/bitacross-worker/core/direct-rpc-client/src/lib.rs b/bitacross-worker/core/direct-rpc-client/src/lib.rs index 6de127f7df..ba5253fdf7 100644 --- a/bitacross-worker/core/direct-rpc-client/src/lib.rs +++ b/bitacross-worker/core/direct-rpc-client/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs b/bitacross-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs index 141ff21b54..461142f97c 100644 --- a/bitacross-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs +++ b/bitacross-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs @@ -78,7 +78,6 @@ pub mod tests { use crate::builders::{ rpc_response_builder::RpcResponseBuilder, rpc_return_value_builder::RpcReturnValueBuilder, }; - use codec::Encode; use itp_rpc::Id; use itp_types::{TrustedOperationStatus, H256}; diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/Cargo.toml b/bitacross-worker/core/parentchain/indirect-calls-executor/Cargo.toml index e8e018d334..b006457b3a 100644 --- a/bitacross-worker/core/parentchain/indirect-calls-executor/Cargo.toml +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/Cargo.toml @@ -39,11 +39,8 @@ sp-core = { default-features = false, features = ["full_crypto"], git = "https:/ sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } # litentry -itp-utils = { path = "../../../core-primitives/utils", default-features = false } lc-scheduled-enclave = { path = "../../../litentry/core/scheduled-enclave", default-features = false, optional = true } litentry-primitives = { path = "../../../litentry/primitives", default-features = false } -parachain-core-primitives = { package = "core-primitives", path = "../../../../primitives/core", default-features = false } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } [dev-dependencies] env_logger = "0.9.0" @@ -76,7 +73,6 @@ std = [ "thiserror", # litentry "litentry-primitives/std", - "itp-utils/std", "lc-scheduled-enclave/std", ] sgx = [ diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/error.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/error.rs index 2973f984f8..cbb80d384e 100644 --- a/bitacross-worker/core/parentchain/indirect-calls-executor/src/error.rs +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/error.rs @@ -17,7 +17,6 @@ #[cfg(all(not(feature = "std"), feature = "sgx"))] use crate::sgx_reexport_prelude::*; -pub use litentry_primitives::{ErrorDetail, IMPError, VCMPError}; use itp_types::parentchain::ParentchainError; use lc_scheduled_enclave::error::Error as ScheduledEnclaveError; @@ -44,14 +43,6 @@ pub enum Error { Other(#[from] Box), #[error("AccountId lookup error")] AccountIdLookup, - #[error("convert parent chain block number error")] - ConvertParentchainBlockNumber, - #[error("IMP handling error: {0:?}")] - IMPHandlingError(IMPError), - #[error("VCMP handling error: {0:?}")] - VCMPHandlingError(VCMPError), - #[error("BatchAll handling error")] - BatchAllHandlingError, #[error("ScheduledEnclave Error: {0:?}")] ImportScheduledEnclave(ScheduledEnclaveError), } @@ -92,18 +83,6 @@ impl From for Error { } } -impl From for Error { - fn from(e: IMPError) -> Self { - Self::IMPHandlingError(e) - } -} - -impl From for Error { - fn from(e: VCMPError) -> Self { - Self::VCMPHandlingError(e) - } -} - impl From for Error { fn from(e: ScheduledEnclaveError) -> Self { Self::ImportScheduledEnclave(e) diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/executor.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/executor.rs index 0c2dbcf74c..7ab712aa71 100644 --- a/bitacross-worker/core/parentchain/indirect-calls-executor/src/executor.rs +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/executor.rs @@ -29,7 +29,7 @@ use binary_merkle_tree::merkle_root; use codec::{Decode, Encode}; use core::marker::PhantomData; use itp_node_api::metadata::{ - pallet_teerex::TeerexCallIndexes, provider::AccessNodeMetadata, NodeMetadataTrait, + pallet_teebag::TeebagCallIndexes, provider::AccessNodeMetadata, NodeMetadataTrait, }; use itp_sgx_crypto::{key_repository::AccessKey, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}; use itp_stf_executor::traits::{StfEnclaveSigning, StfShardVaultQuery}; @@ -217,10 +217,10 @@ impl< ParentchainBlock: ParentchainBlockTrait, { let call = self.node_meta_data_provider.get_from_metadata(|meta_data| { - meta_data.confirm_processed_parentchain_block_call_indexes() + meta_data.parentchain_block_processed_call_indexes() })??; let root: H256 = merkle_root::(extrinsics); - trace!("prepared confirm_processed_parentchain_block() call for block {:?} with index {:?} and merkle root {}", block_number, call, root); + trace!("prepared parentchain_block_processed() call for block {:?} with index {:?} and merkle root {}", block_number, call, root); // Litentry: we don't include `shard` in the extrinsic parameter to be backwards compatible, // however, we should not forget it in case we need it later Ok(OpaqueCall::from_tuple(&(call, block_hash, block_number, root))) @@ -300,7 +300,7 @@ pub fn hash_of(xt: &T) -> H256 { mod test { use super::*; use crate::mock::*; - use codec::{Decode, Encode}; + use codec::Encode; use itc_parentchain_test::ParentchainBlockBuilder; use itp_node_api::{ api_client::{ @@ -311,16 +311,12 @@ mod test { }; use itp_sgx_crypto::mocks::KeyRepositoryMock; use itp_stf_executor::mocks::StfEnclaveSignerMock; - use itp_stf_primitives::{ - traits::TrustedCallVerification, - types::{AccountId, TrustedOperation}, - }; use itp_test::mock::{ shielding_crypto_mock::ShieldingCryptoMock, stf_mock::{GetterMock, TrustedCallSignedMock}, }; use itp_top_pool_author::mocks::AuthorApiMock; - use itp_types::{Block, CallWorkerFn, RsaRequest, ShardIdentifier, ShieldFundsFn}; + use itp_types::{Block, PostOpaqueTaskFn, RsaRequest, ShardIdentifier}; use sp_core::{ed25519, Pair}; use sp_runtime::{MultiAddress, MultiSignature, OpaqueExtrinsic}; use std::assert_matches::assert_matches; @@ -366,41 +362,6 @@ mod test { assert_eq!(1, top_pool_author.pending_tops(shard_id()).unwrap().len()); } - #[test] - fn shielding_call_can_be_added_to_pool_successfully() { - let _ = env_logger::builder().is_test(true).try_init(); - - let mr_enclave = [33u8; 32]; - let (indirect_calls_executor, top_pool_author, shielding_key_repo) = - test_fixtures(mr_enclave.clone(), NodeMetadataMock::new()); - let shielding_key = shielding_key_repo.retrieve_key().unwrap(); - - let opaque_extrinsic = OpaqueExtrinsic::from_bytes( - shield_funds_unchecked_extrinsic(&shielding_key).encode().as_slice(), - ) - .unwrap(); - - let parentchain_block = ParentchainBlockBuilder::default() - .with_extrinsics(vec![opaque_extrinsic]) - .build(); - - indirect_calls_executor - .execute_indirect_calls_in_extrinsics(&parentchain_block, &Vec::new()) - .unwrap(); - - assert_eq!(1, top_pool_author.pending_tops(shard_id()).unwrap().len()); - let submitted_extrinsic = - top_pool_author.pending_tops(shard_id()).unwrap().first().cloned().unwrap(); - let decrypted_extrinsic = shielding_key.decrypt(&submitted_extrinsic).unwrap(); - let decoded_operation = TrustedOperation::::decode( - &mut decrypted_extrinsic.as_slice(), - ) - .unwrap(); - assert_matches!(decoded_operation, TrustedOperation::indirect_call(_)); - let trusted_call_signed = decoded_operation.to_call().unwrap(); - assert!(trusted_call_signed.verify_signature(&mr_enclave, &shard_id())); - } - #[test] fn ensure_empty_extrinsic_vec_triggers_zero_filled_merkle_root() { // given @@ -409,11 +370,10 @@ mod test { let block_hash = H256::from([1; 32]); let extrinsics = Vec::new(); - let confirm_processed_parentchain_block_indexes = - dummy_metadata.confirm_processed_parentchain_block_call_indexes().unwrap(); + let parentchain_block_processed_call_indexes = + dummy_metadata.parentchain_block_processed_call_indexes().unwrap(); let expected_call = - (confirm_processed_parentchain_block_indexes, block_hash, 1u32, H256::default()) - .encode(); + (parentchain_block_processed_call_indexes, block_hash, 1u32, H256::default()).encode(); // when let call = indirect_calls_executor @@ -432,12 +392,11 @@ mod test { let block_hash = H256::from([1; 32]); let extrinsics = vec![H256::from([4; 32]), H256::from([9; 32])]; - let confirm_processed_parentchain_block_indexes = - dummy_metadata.confirm_processed_parentchain_block_call_indexes().unwrap(); + let parentchain_block_processed_call_indexes = + dummy_metadata.parentchain_block_processed_call_indexes().unwrap(); let zero_root_call = - (confirm_processed_parentchain_block_indexes, block_hash, 1u32, H256::default()) - .encode(); + (parentchain_block_processed_call_indexes, block_hash, 1u32, H256::default()).encode(); // when let call = indirect_calls_executor @@ -448,27 +407,12 @@ mod test { assert_ne!(call.0, zero_root_call); } - fn shield_funds_unchecked_extrinsic( - shielding_key: &ShieldingCryptoMock, - ) -> ParentchainUncheckedExtrinsic { - let target_account = shielding_key.encrypt(&AccountId::new([2u8; 32]).encode()).unwrap(); - let dummy_metadata = NodeMetadataMock::new(); - - let shield_funds_indexes = dummy_metadata.shield_funds_call_indexes().unwrap(); - ParentchainUncheckedExtrinsic::::new_signed( - (shield_funds_indexes, target_account, 1000u128, shard_id()), - MultiAddress::Address32([1u8; 32]), - MultiSignature::Ed25519(default_signature()), - default_extrinsic_params().signed_extra(), - ) - } - - fn invoke_unchecked_extrinsic() -> ParentchainUncheckedExtrinsic { + fn invoke_unchecked_extrinsic() -> ParentchainUncheckedExtrinsic { let request = RsaRequest::new(shard_id(), vec![1u8, 2u8]); let dummy_metadata = NodeMetadataMock::new(); - let call_worker_indexes = dummy_metadata.invoke_call_indexes().unwrap(); + let call_worker_indexes = dummy_metadata.post_opaque_task_call_indexes().unwrap(); - ParentchainUncheckedExtrinsic::::new_signed( + ParentchainUncheckedExtrinsic::::new_signed( (call_worker_indexes, request), MultiAddress::Address32([1u8; 32]), MultiSignature::Ed25519(default_signature()), diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/mock.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/mock.rs index 38189f44d8..57c1645cc2 100644 --- a/bitacross-worker/core/parentchain/indirect-calls-executor/src/mock.rs +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/mock.rs @@ -58,11 +58,7 @@ where "[ShieldFundsAndInvokeFilter] attempting to execute indirect call with index {:?}", index ); - if index == metadata.shield_funds_call_indexes().ok()? { - log::debug!("executing shield funds call"); - let args = ShieldFundsArgs::decode(call_args).unwrap(); - Some(IndirectCall::ShieldFunds(args)) - } else if index == metadata.invoke_call_indexes().ok()? { + if index == metadata.post_opaque_task_call_indexes().ok()? { log::debug!("executing invoke call"); let args = InvokeArgs::decode(call_args).unwrap(); Some(IndirectCall::Invoke(args)) diff --git a/bitacross-worker/core/peer-top-broadcaster/src/lib.rs b/bitacross-worker/core/peer-top-broadcaster/src/lib.rs index eef091de21..9e34033741 100644 --- a/bitacross-worker/core/peer-top-broadcaster/src/lib.rs +++ b/bitacross-worker/core/peer-top-broadcaster/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/core/rpc-client/Cargo.toml b/bitacross-worker/core/rpc-client/Cargo.toml index fc06593ed3..ebbba96ba7 100644 --- a/bitacross-worker/core/rpc-client/Cargo.toml +++ b/bitacross-worker/core/rpc-client/Cargo.toml @@ -19,7 +19,6 @@ ws = { version = "0.9.1", features = ["ssl"] } # parity frame-metadata = { version = "15.1.0", features = ["v14"] } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", default-features = false } # local itp-api-client-types = { path = "../../core-primitives/node-api/api-client-types" } @@ -30,8 +29,6 @@ itp-utils = { path = "../../core-primitives/utils" } # litentry ita-stf = { path = "../../app-libs/stf" } itp-stf-primitives = { path = "../../core-primitives/stf-primitives" } -litentry-primitives = { path = "../../litentry/primitives", default-features = false } -teerex-primitives = { path = "../../../primitives/teerex", default-features = false } [dev-dependencies] env_logger = "0.9.0" diff --git a/bitacross-worker/core/rpc-client/src/direct_client.rs b/bitacross-worker/core/rpc-client/src/direct_client.rs index 5f7acab959..142ecdb897 100644 --- a/bitacross-worker/core/rpc-client/src/direct_client.rs +++ b/bitacross-worker/core/rpc-client/src/direct_client.rs @@ -17,6 +17,7 @@ //! Interface for direct access to a workers rpc. +pub use crate::error::{Error, Result}; use crate::ws_client::{WsClient, WsClientControl}; use base58::ToBase58; use codec::{Decode, Encode}; @@ -25,7 +26,7 @@ use ita_stf::Getter; use itp_api_client_types::Metadata; use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; use itp_stf_primitives::types::{AccountId, ShardIdentifier}; -use itp_types::{DirectRequestStatus, RsaRequest}; +use itp_types::{DirectRequestStatus, MrEnclave, RsaRequest}; use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use log::*; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; @@ -37,9 +38,6 @@ use std::{ thread, thread::JoinHandle, }; -use teerex_primitives::MrEnclave; - -pub use crate::error::{Error, Result}; #[derive(Clone)] pub struct DirectClient { diff --git a/bitacross-worker/core/rpc-client/src/mock.rs b/bitacross-worker/core/rpc-client/src/mock.rs index d61290c035..401c9496d2 100644 --- a/bitacross-worker/core/rpc-client/src/mock.rs +++ b/bitacross-worker/core/rpc-client/src/mock.rs @@ -20,13 +20,11 @@ use crate::{direct_client::DirectApi, error::Result}; use codec::Decode; use frame_metadata::RuntimeMetadataPrefixed; -use ita_stf::H256; use itp_api_client_types::Metadata; use itp_stf_primitives::types::{AccountId, ShardIdentifier}; -use litentry_primitives::Identity; +use itp_types::MrEnclave; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use std::{sync::mpsc::Sender as MpscSender, thread::JoinHandle}; -use teerex_primitives::MrEnclave; #[derive(Clone, Default)] pub struct DirectClientMock { diff --git a/bitacross-worker/core/rpc-server/Cargo.toml b/bitacross-worker/core/rpc-server/Cargo.toml deleted file mode 100644 index d7f22c184e..0000000000 --- a/bitacross-worker/core/rpc-server/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "itc-rpc-server" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -anyhow = "1.0.40" -jsonrpsee = { version = "0.2.0-alpha.7", features = ["full"] } -log = "0.4" -tokio = { version = "1.6.1", features = ["full"] } - -# local -itp-enclave-api = { path = "../../core-primitives/enclave-api" } -itp-rpc = { path = "../../core-primitives/rpc" } -itp-utils = { path = "../../core-primitives/utils" } -its-peer-fetch = { path = "../../sidechain/peer-fetch" } -its-primitives = { path = "../../sidechain/primitives" } -its-rpc-handler = { path = "../../sidechain/rpc-handler" } -its-storage = { path = "../../sidechain/storage" } - -[features] -default = ["std"] -std = [] - -[dev-dependencies] -env_logger = { version = "*" } -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -its-test = { path = "../../sidechain/test" } -parity-scale-codec = "3.0.0" diff --git a/bitacross-worker/core/rpc-server/src/lib.rs b/bitacross-worker/core/rpc-server/src/lib.rs deleted file mode 100644 index 1386f0de4d..0000000000 --- a/bitacross-worker/core/rpc-server/src/lib.rs +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use itp_enclave_api::direct_request::DirectRequest; -use itp_rpc::{Id, RpcRequest}; -use itp_utils::ToHexPrefixed; -use its_peer_fetch::block_fetch_server::BlockFetchServerModuleBuilder; -use its_primitives::types::block::SignedBlock; -use its_rpc_handler::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; -use its_storage::interface::FetchBlocks; -use jsonrpsee::{ - types::error::CallError, - ws_server::{RpcModule, WsServerBuilder}, -}; -use log::debug; -use std::{net::SocketAddr, sync::Arc}; -use tokio::net::ToSocketAddrs; - -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -pub async fn run_server( - addr: impl ToSocketAddrs, - enclave: Arc, - sidechain_block_fetcher: Arc, -) -> anyhow::Result -where - Enclave: DirectRequest, - FetchSidechainBlocks: FetchBlocks + Send + Sync + 'static, -{ - let mut server = WsServerBuilder::default().build(addr).await?; - - // FIXME: import block should be moved to trusted side. - let mut import_sidechain_block_module = RpcModule::new(enclave); - import_sidechain_block_module.register_method( - RPC_METHOD_NAME_IMPORT_BLOCKS, - |params, enclave| { - debug!("{} params: {:?}", RPC_METHOD_NAME_IMPORT_BLOCKS, params); - - let enclave_req = RpcRequest::compose_jsonrpc_call( - Id::Text("1".to_string()), - RPC_METHOD_NAME_IMPORT_BLOCKS.into(), - vec![params.one::>()?.to_hex()], - ) - .unwrap(); - - enclave - .rpc(enclave_req.as_bytes().to_vec()) - .map_err(|e| CallError::Failed(e.into())) - }, - )?; - server.register_module(import_sidechain_block_module).unwrap(); - - let fetch_sidechain_blocks_module = BlockFetchServerModuleBuilder::new(sidechain_block_fetcher) - .build() - .map_err(|e| CallError::Failed(e.to_string().into()))?; // `to_string` necessary due to no all errors implementing Send + Sync. - server.register_module(fetch_sidechain_blocks_module).unwrap(); - - let socket_addr = server.local_addr()?; - tokio::spawn(async move { server.start().await }); - - println!("[+] Untrusted RPC server is spawned on: {}", socket_addr); - - Ok(socket_addr) -} diff --git a/bitacross-worker/core/rpc-server/src/mock.rs b/bitacross-worker/core/rpc-server/src/mock.rs deleted file mode 100644 index 172c1a7528..0000000000 --- a/bitacross-worker/core/rpc-server/src/mock.rs +++ /dev/null @@ -1,75 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use itp_enclave_api::{direct_request::DirectRequest, EnclaveResult}; -use itp_rpc::{Id, RpcResponse}; -use itp_utils::ToHexPrefixed; -use its_primitives::{ - traits::ShardIdentifierFor, - types::{BlockHash, BlockNumber, SignedBlock, SignedBlock as SignedSidechainBlock}, -}; -use its_storage::{interface::FetchBlocks, LastSidechainBlock}; -use parity_scale_codec::Encode; - -pub struct TestEnclave; - -impl DirectRequest for TestEnclave { - fn rpc(&self, _request: Vec) -> EnclaveResult> { - Ok(RpcResponse { - jsonrpc: "mock_response".into(), - result: "null".to_hex(), - id: Id::Number(1), - } - .encode()) - } -} - -pub struct MockSidechainBlockFetcher; - -impl FetchBlocks for MockSidechainBlockFetcher { - fn fetch_all_blocks_after( - &self, - _block_hash: &BlockHash, - _shard_identifier: &ShardIdentifierFor, - ) -> its_storage::Result> { - Ok(Vec::new()) - } - - fn fetch_blocks_in_range( - &self, - _block_hash_from: &BlockHash, - _block_hash_until: &BlockHash, - _shard_identifier: &ShardIdentifierFor, - ) -> its_storage::Result> { - Ok(Vec::new()) - } - - fn latest_block( - &self, - _shard_identifier: &ShardIdentifierFor, - ) -> Option { - Some(LastSidechainBlock::default()) - } - - fn block_hash( - &self, - _block_number: BlockNumber, - _shard_identifier: &ShardIdentifierFor, - ) -> Option { - Some(LastSidechainBlock::default()) - } -} diff --git a/bitacross-worker/core/rpc-server/src/tests.rs b/bitacross-worker/core/rpc-server/src/tests.rs deleted file mode 100644 index 4c99081804..0000000000 --- a/bitacross-worker/core/rpc-server/src/tests.rs +++ /dev/null @@ -1,56 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use super::*; -use crate::mock::MockSidechainBlockFetcher; -use itp_rpc::RpcResponse; -use its_rpc_handler::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; -use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; -use jsonrpsee::{ - types::{to_json_value, traits::Client}, - ws_client::WsClientBuilder, -}; -use log::info; -use mock::TestEnclave; -use parity_scale_codec::Decode; - -fn init() { - let _ = env_logger::builder().is_test(true).try_init(); -} - -#[tokio::test] -async fn test_client_calls() { - init(); - let addr = - run_server("127.0.0.1:0", Arc::new(TestEnclave), Arc::new(MockSidechainBlockFetcher)) - .await - .unwrap(); - info!("ServerAddress: {:?}", addr); - - let url = format!("ws://{}", addr); - let client = WsClientBuilder::default().build(&url).await.unwrap(); - let response: Vec = client - .request( - RPC_METHOD_NAME_IMPORT_BLOCKS, - vec![to_json_value(vec![SidechainBlockBuilder::default().build_signed()]).unwrap()] - .into(), - ) - .await - .unwrap(); - - assert!(RpcResponse::decode(&mut response.as_slice()).is_ok()); -} diff --git a/bitacross-worker/docker/README.md b/bitacross-worker/docker/README.md index 7f9ddb7a86..09ee9bb415 100644 --- a/bitacross-worker/docker/README.md +++ b/bitacross-worker/docker/README.md @@ -55,16 +55,6 @@ Run docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-sidechain.yml) up demo-sidechain --exit-code-from demo-sidechain ``` -### Demo Teeracle -Build -``` -COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-teeracle.yml) build --build-arg WORKER_MODE_ARG=teeracle -``` -Run -``` -docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-teeracle.yml) up demo-teeracle --exit-code-from demo-teeracle -``` - ## Run the benchmarks Build with diff --git a/bitacross-worker/docker/demo-teeracle-generic.yml b/bitacross-worker/docker/demo-teeracle-generic.yml deleted file mode 100644 index 4ff30dafdf..0000000000 --- a/bitacross-worker/docker/demo-teeracle-generic.yml +++ /dev/null @@ -1,68 +0,0 @@ -# Teeracle Demo Setup -# -# The demo is parameterized with the interval that the teeracle uses to query its sources. -# Set the `TEERACLE_INTERVAL_SECONDS` variable when invoking, e.g. `TEERACLE_INTERVAL_SECONDS=4 docker compose -f docker-compose.yml -f demo-teeracle-generic.yml up --exit-code-from demo-teeracle-generic` -# Set the `ADDITIONAL_RUNTIME_FLAGS` variable to for additional flags. -# To skip remote attestation: `export ADDITIONAL_RUNTIME_FLAG="--skip-ra"` -services: - integritee-teeracle-worker-${VERSION}: - image: integritee-worker:${VERSION:-dev} - hostname: integritee-teeracle-worker - devices: - - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" - - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" - volumes: - - "${AESMD:-/dev/null}:/var/run/aesmd" - - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" - build: - context: ${PWD}/.. - dockerfile: build.Dockerfile - target: deployed-worker - depends_on: - integritee-node-${VERSION}: - condition: service_healthy - environment: - - RUST_LOG=warn,ws=warn,sp_io=warn,substrate_api_client=warn,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=warn,integritee_service=info,integritee_service::teeracle=debug,ita_stf=warn,ita_oracle=debug - networks: - - integritee-test-network - healthcheck: - test: curl -s -f http://integritee-teeracle-worker:4645/is_initialized || exit 1 - interval: 10s - timeout: 10s - retries: 25 - command: - "--clean-reset --ws-external -M integritee-teeracle-worker -T wss://integritee-teeracle-worker - -u ws://integritee-node -U ws://integritee-teeracle-worker -P 2011 -w 2101 -p 9912 -h 4645 - run --dev ${ADDITIONAL_RUNTIME_FLAGS} --teeracle-interval ${TEERACLE_INTERVAL_SECONDS}s" - restart: always - demo-teeracle-generic: - image: bitacross-cli:${VERSION:-dev} - devices: - - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" - - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" - volumes: - - "${AESMD:-/dev/null}:/var/run/aesmd" - - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" - build: - context: ${PWD}/.. - dockerfile: build.Dockerfile - target: deployed-client - depends_on: - integritee-node-${VERSION}: - condition: service_healthy - integritee-teeracle-worker-${VERSION}: - condition: service_healthy - environment: - - RUST_LOG=warn,sp_io=warn,integritee_cli::exchange_oracle=debug - networks: - - integritee-test-network - entrypoint: - "/usr/local/worker-cli/demo_teeracle_generic.sh - -u ws://integritee-node -p 9912 - -V wss://integritee-teeracle-worker -P 2011 - -d 21 -i ${TEERACLE_INTERVAL_SECONDS} - -C /usr/local/bin/bitacross-cli 2>&1" - restart: "no" -networks: - integritee-test-network: - driver: bridge diff --git a/bitacross-worker/docker/demo-teeracle.yml b/bitacross-worker/docker/demo-teeracle.yml deleted file mode 100644 index d71b36df6b..0000000000 --- a/bitacross-worker/docker/demo-teeracle.yml +++ /dev/null @@ -1,71 +0,0 @@ -# Teeracle Demo Setup -# -# The demo is parameterized with the interval that the teeracle uses to query its sources. -# Set the `TEERACLE_INTERVAL_SECONDS` variable when invoking, e.g. `TEERACLE_INTERVAL_SECONDS=4 docker compose -f docker-compose.yml -f demo-teeracle.yml up --exit-code-from demo-teeracle` -# This setup requires an API key for CoinMarketCap -# Add the API key to the environment variable `COINMARKETCAP_KEY`, with `export COINMARKETCAP_KEY=` -# Set the `ADDITIONAL_RUNTIME_FLAGS` variable to for additional flags. -# To skip remote attestation: `export ADDITIONAL_RUNTIME_FLAG="--skip-ra"` -services: - integritee-teeracle-worker-${VERSION}: - image: integritee-worker:${VERSION:-dev} - hostname: integritee-teeracle-worker - devices: - - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" - - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" - volumes: - - "${AESMD:-/dev/null}:/var/run/aesmd" - - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" - build: - context: ${PWD}/.. - dockerfile: build.Dockerfile - target: deployed-worker - depends_on: - integritee-node-${VERSION}: - condition: service_healthy - environment: - - RUST_LOG=warn,ws=warn,sp_io=warn,substrate_api_client=warn,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=warn,integritee_service=info,integritee_service::teeracle=debug,ita_stf=warn,ita_exchange_oracle=debug - - COINMARKETCAP_KEY - networks: - - integritee-test-network - healthcheck: - test: curl -s -f http://integritee-teeracle-worker:4645/is_initialized || exit 1 - interval: 10s - timeout: 10s - retries: 25 - command: - "--clean-reset --ws-external -M integritee-teeracle-worker -T wss://integritee-teeracle-worker - -u ws://integritee-node -U ws://integritee-teeracle-worker -P 2011 -w 2101 -p 9912 -h 4645 - run --dev ${ADDITIONAL_RUNTIME_FLAGS} --teeracle-interval ${TEERACLE_INTERVAL_SECONDS}s" - restart: always - demo-teeracle: - image: bitacross-cli:${VERSION:-dev} - devices: - - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" - - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" - volumes: - - "${AESMD:-/dev/null}:/var/run/aesmd" - - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" - build: - context: ${PWD}/.. - dockerfile: build.Dockerfile - target: deployed-client - depends_on: - integritee-node-${VERSION}: - condition: service_healthy - integritee-teeracle-worker-${VERSION}: - condition: service_healthy - environment: - - RUST_LOG=warn,sp_io=warn,integritee_cli::exchange_oracle=debug - networks: - - integritee-test-network - entrypoint: - "/usr/local/worker-cli/demo_teeracle_whitelist.sh - -u ws://integritee-node -p 9912 - -V wss://integritee-teeracle-worker -P 2011 - -d 7 -i ${TEERACLE_INTERVAL_SECONDS} - -C /usr/local/bin/bitacross-cli 2>&1" - restart: "no" -networks: - integritee-test-network: - driver: bridge diff --git a/bitacross-worker/docker/docker-compose.yml b/bitacross-worker/docker/docker-compose.yml index fedb1e549f..95116de23b 100644 --- a/bitacross-worker/docker/docker-compose.yml +++ b/bitacross-worker/docker/docker-compose.yml @@ -118,10 +118,9 @@ services: environment: - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, - TWITTER_OFFICIAL_URL=http://localhost:19527 - - TWITTER_LITENTRY_URL=http://localhost:19527 - TWITTER_AUTH_TOKEN_V2= - DISCORD_OFFICIAL_URL=http://localhost:19527 - - DISCORD_LITENTRY_URL=http://localhost:19527 + - LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 - DISCORD_AUTH_TOKEN= - ACHAINABLE_URL=http://localhost:19527 - ACHAINABLE_AUTH_KEY= diff --git a/bitacross-worker/docker/lit-set-heartbeat-timeout.yml b/bitacross-worker/docker/lit-set-heartbeat-timeout.yml deleted file mode 100644 index b4e271ce4c..0000000000 --- a/bitacross-worker/docker/lit-set-heartbeat-timeout.yml +++ /dev/null @@ -1,24 +0,0 @@ -services: - lit-set-heartbeat-timeout: - image: litentry/bitacross-cli:latest - container_name: litentry-set-heartbeat-timeout - volumes: - - ../cli:/usr/local/worker-cli - build: - context: .. - dockerfile: build.Dockerfile - target: deployed-client - depends_on: - litentry-node: - condition: service_healthy - bitacross-worker-1: - condition: service_healthy - networks: - - litentry-test-network - entrypoint: - "/usr/local/worker-cli/lit_set_heartbeat_timeout.sh -p 9912 -u ws://litentry-node - -V wss://bitacross-worker-1 -A 2011 -W wss://bitacross-worker-2 -B 2012 -C /usr/local/bin/bitacross-cli 2>&1" - restart: "no" -networks: - litentry-test-network: - driver: bridge \ No newline at end of file diff --git a/bitacross-worker/docker/multiworker-docker-compose.yml b/bitacross-worker/docker/multiworker-docker-compose.yml index 081077de84..a3b2c2aa90 100644 --- a/bitacross-worker/docker/multiworker-docker-compose.yml +++ b/bitacross-worker/docker/multiworker-docker-compose.yml @@ -119,10 +119,9 @@ services: environment: - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, - TWITTER_OFFICIAL_URL=http://localhost:19527 - - TWITTER_LITENTRY_URL=http://localhost:19527 - TWITTER_AUTH_TOKEN_V2= - DISCORD_OFFICIAL_URL=http://localhost:19527 - - DISCORD_LITENTRY_URL=http://localhost:19527 + - LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 - DISCORD_AUTH_TOKEN= - ACHAINABLE_URL=http://localhost:19527 - ACHAINABLE_AUTH_KEY= @@ -169,10 +168,9 @@ services: environment: - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, - TWITTER_OFFICIAL_URL=http://localhost:19527 - - TWITTER_LITENTRY_URL=http://localhost:19527 - TWITTER_AUTH_TOKEN_V2= - DISCORD_OFFICIAL_URL=http://localhost:19527 - - DISCORD_LITENTRY_URL=http://localhost:19527 + - LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 - DISCORD_AUTH_TOKEN= - ACHAINABLE_URL=http://localhost:19527 - ACHAINABLE_AUTH_KEY= @@ -219,10 +217,9 @@ services: environment: - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, - TWITTER_OFFICIAL_URL=http://localhost:19527 - - TWITTER_LITENTRY_URL=http://localhost:19527 - TWITTER_AUTH_TOKEN_V2= - DISCORD_OFFICIAL_URL=http://localhost:19527 - - DISCORD_LITENTRY_URL=http://localhost:19527 + - LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 - DISCORD_AUTH_TOKEN= - ACHAINABLE_URL=http://localhost:19527 - ACHAINABLE_AUTH_KEY= diff --git a/bitacross-worker/enclave-runtime/Cargo.lock b/bitacross-worker/enclave-runtime/Cargo.lock index ce53c8dc84..95451674f4 100644 --- a/bitacross-worker/enclave-runtime/Cargo.lock +++ b/bitacross-worker/enclave-runtime/Cargo.lock @@ -32,7 +32,7 @@ dependencies = [ "derive_more", "either", "frame-metadata", - "hex", + "hex 0.4.3", "log", "parity-scale-codec", "scale-bits", @@ -248,6 +248,62 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bc-relayer-registry" +version = "0.1.0" +dependencies = [ + "itp-settings", + "itp-sgx-io", + "lazy_static", + "litentry-primitives", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-std", + "thiserror", +] + +[[package]] +name = "bc-task-receiver" +version = "0.1.0" +dependencies = [ + "bc-relayer-registry", + "bc-task-sender", + "frame-support", + "futures 0.3.8", + "hex 0.4.0", + "ita-stf", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-executor", + "itp-stf-state-handler", + "lc-direct-call", + "litentry-primitives", + "log", + "parity-scale-codec", + "sgx_tstd", + "thiserror", + "threadpool", +] + +[[package]] +name = "bc-task-sender" +version = "0.1.0" +dependencies = [ + "futures 0.3.8", + "lazy_static", + "litentry-primitives", + "parity-scale-codec", + "sgx_tstd", +] + [[package]] name = "bech32" version = "0.10.0-beta" @@ -471,9 +527,9 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cargo_toml" -version = "0.16.3" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3f9629bc6c4388ea699781dc988c2b99766d7679b151c81990b4fa1208fafd3" +checksum = "3dc9f7a067415ab5058020f04c60ec7b557084dbec0e021217bbabc7a8d38d14" dependencies = [ "serde 1.0.193", "toml", @@ -526,6 +582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "num-traits 0.2.16", + "serde 1.0.193", ] [[package]] @@ -547,19 +604,6 @@ dependencies = [ "generic-array 0.14.7", ] -[[package]] -name = "common-primitives" -version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" -dependencies = [ - "derive_more", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "const-oid" version = "0.9.5" @@ -590,9 +634,9 @@ version = "0.9.12" dependencies = [ "frame-support", "litentry-hex-utils", - "litentry-macros 0.9.12", + "litentry-macros", "litentry-proc-macros", - "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm", "parity-scale-codec", "ring 0.16.20", "scale-info", @@ -648,7 +692,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.7", - "typenum 1.17.0", + "typenum", ] [[package]] @@ -718,6 +762,17 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "der_derive", + "flagset", +] + [[package]] name = "der" version = "0.7.8" @@ -728,6 +783,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef71ddb5b3a1f53dee24817c8f70dfa1cb29e804c18d88c228d4bc9c86ee3b9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "derive-syn-parse" version = "0.1.5" @@ -788,11 +855,12 @@ version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ - "der", + "der 0.7.8", "digest 0.10.7", "elliptic-curve", "rfc6979", "signature", + "spki 0.7.3", ] [[package]] @@ -803,7 +871,7 @@ checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" dependencies = [ "curve25519-dalek 3.2.0", "hashbrown 0.12.3", - "hex", + "hex 0.4.3", "rand_core 0.6.4", "sha2 0.9.9", "zeroize", @@ -817,9 +885,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" -version = "0.13.5" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", @@ -827,6 +895,7 @@ dependencies = [ "ff", "generic-array 0.14.7", "group", + "pkcs8", "rand_core 0.6.4", "sec1", "subtle", @@ -838,14 +907,16 @@ name = "enclave-runtime" version = "0.0.1" dependencies = [ "array-bytes 6.1.0", + "bc-relayer-registry", + "bc-task-receiver", + "bc-task-sender", "cid", "derive_more", "env_logger", "frame-support", - "frame-system", - "hex", + "futures 0.3.8", + "hex 0.4.3", "ipfs-unixfs", - "ita-oracle", "ita-parentchain-interface", "ita-sgx-runtime", "ita-stf", @@ -854,16 +925,17 @@ dependencies = [ "itc-offchain-worker-executor", "itc-parentchain", "itc-parentchain-block-import-dispatcher", + "itc-parentchain-light-client", "itc-parentchain-test", "itc-peer-top-broadcaster", "itc-tls-websocket-server", "itp-attestation-handler", "itp-component-container", - "itp-enclave-metrics", "itp-extrinsics-factory", "itp-import-queue", "itp-node-api", "itp-node-api-metadata", + "itp-node-api-metadata-provider", "itp-nonce-cache", "itp-ocall-api", "itp-primitives-cache", @@ -879,19 +951,17 @@ dependencies = [ "itp-stf-state-observer", "itp-storage", "itp-test", - "itp-time-utils", "itp-top-pool", "itp-top-pool-author", "itp-types", "itp-utils", - "its-block-verification", - "its-primitives", - "its-sidechain", "jsonrpc-core", "lazy_static", "lc-scheduled-enclave", - "litentry-macros 0.1.0", + "litentry-hex-utils", + "litentry-macros", "litentry-primitives", + "litentry-proc-macros", "log", "multibase", "once_cell 1.4.0", @@ -913,7 +983,6 @@ dependencies = [ "sgx_types", "sp-core", "sp-runtime", - "teerex-primitives 0.1.0 (git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42)", "webpki", ] @@ -994,25 +1063,6 @@ dependencies = [ "uint", ] -[[package]] -name = "evm" -version = "0.39.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49a4e11987c51220aa89dbe1a5cc877f5079fa6864c0a5b4533331db44e9365" -dependencies = [ - "auto_impl", - "ethereum", - "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "evm-gasometer 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log", - "parity-scale-codec", - "primitive-types", - "rlp", - "scale-info", - "sha3 0.10.8", -] - [[package]] name = "evm" version = "0.39.1" @@ -1020,9 +1070,9 @@ source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa dependencies = [ "auto_impl", "ethereum", - "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "evm-gasometer 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-core", + "evm-gasometer", + "evm-runtime", "log", "parity-scale-codec", "primitive-types", @@ -1031,17 +1081,6 @@ dependencies = [ "sha3 0.10.8", ] -[[package]] -name = "evm-core" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1f13264b044cb66f0602180f0bc781c29accb41ff560669a3ec15858d5b606" -dependencies = [ - "parity-scale-codec", - "primitive-types", - "scale-info", -] - [[package]] name = "evm-core" version = "0.39.0" @@ -1052,37 +1091,14 @@ dependencies = [ "scale-info", ] -[[package]] -name = "evm-gasometer" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d43eadc395bd1a52990787ca1495c26b0248165444912be075c28909a853b8c" -dependencies = [ - "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types", -] - [[package]] name = "evm-gasometer" version = "0.39.0" source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" dependencies = [ - "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "primitive-types", -] - -[[package]] -name = "evm-runtime" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aa5b32f59ec582a5651978004e5c784920291263b7dcb6de418047438e37f4f" -dependencies = [ - "auto_impl", - "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-core", + "evm-runtime", "primitive-types", - "sha3 0.10.8", ] [[package]] @@ -1091,7 +1107,7 @@ version = "0.39.0" source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" dependencies = [ "auto_impl", - "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-core", "primitive-types", "sha3 0.10.8", ] @@ -1149,6 +1165,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flagset" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a7e408202050813e6f1d9addadcaafef3dca7530c7ddfb005d4081cce6779" + [[package]] name = "fnv" version = "1.0.6" @@ -1163,28 +1185,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "fp-account" -version = "1.0.0-dev" -source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" -dependencies = [ - "hex", - "libsecp256k1", - "log", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "fp-account" version = "1.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "hex", + "hex 0.4.3", "libsecp256k1", "log", "parity-scale-codec", @@ -1196,26 +1202,12 @@ dependencies = [ "sp-std", ] -[[package]] -name = "fp-evm" -version = "3.0.0-dev" -source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" -dependencies = [ - "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", - "frame-support", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "fp-evm" version = "3.0.0-dev" source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm", "frame-support", "parity-scale-codec", "scale-info", @@ -1513,7 +1505,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ - "typenum 1.17.0", + "typenum", ] [[package]] @@ -1522,7 +1514,7 @@ version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "typenum 1.17.0", + "typenum", "version_check", "zeroize", ] @@ -1628,6 +1620,14 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hex" +version = "0.4.0" +source = "git+https://github.com/mesalock-linux/rust-hex-sgx?tag=sgx_1.1.3#ee3266cd29b9f9c2eb69af9487f55c4f09c38f2b" +dependencies = [ + "sgx_tstd", +] + [[package]] name = "hex" version = "0.4.3" @@ -1675,19 +1675,6 @@ dependencies = [ "sgx_tstd", ] -[[package]] -name = "http_req" -version = "0.8.1" -source = "git+https://github.com/integritee-network/http_req#3723e88235f2b29bc1a31835853b072ffd0455fd" -dependencies = [ - "log", - "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?branch=mesalock_sgx)", - "sgx_tstd", - "unicase", - "webpki", - "webpki-roots 0.21.0 (git+https://github.com/mesalock-linux/webpki-roots?branch=mesalock_sgx)", -] - [[package]] name = "httparse" version = "1.4.1" @@ -1809,27 +1796,11 @@ dependencies = [ "sha2 0.9.9", ] -[[package]] -name = "ita-oracle" -version = "0.9.0" -dependencies = [ - "itc-rest-client", - "itp-enclave-metrics", - "itp-ocall-api", - "lazy_static", - "log", - "parity-scale-codec", - "serde 1.0.193", - "sgx_tstd", - "substrate-fixed", - "thiserror", - "url", -] - [[package]] name = "ita-parentchain-interface" version = "0.9.0" dependencies = [ + "bc-relayer-registry", "bs58", "ita-sgx-runtime", "ita-stf", @@ -1838,15 +1809,14 @@ dependencies = [ "itp-node-api", "itp-stf-primitives", "itp-types", - "itp-utils", "lc-scheduled-enclave", + "litentry-hex-utils", "litentry-primitives", "log", "parity-scale-codec", "sgx_tstd", "sp-core", "sp-runtime", - "sp-std", ] [[package]] @@ -1858,7 +1828,6 @@ dependencies = [ "frame-system", "itp-sgx-runtime-primitives", "pallet-balances", - "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", "pallet-parentchain", "pallet-sudo", "pallet-timestamp", @@ -1878,19 +1847,18 @@ version = "0.9.0" dependencies = [ "frame-support", "frame-system", - "hex", "hex-literal", "ita-sgx-runtime", "itp-hashing", "itp-node-api", "itp-node-api-metadata", - "itp-node-api-metadata-provider", "itp-sgx-externalities", "itp-stf-interface", "itp-stf-primitives", "itp-storage", "itp-types", "itp-utils", + "litentry-macros", "litentry-primitives", "log", "pallet-balances", @@ -1913,7 +1881,6 @@ dependencies = [ "itp-rpc", "itp-types", "itp-utils", - "litentry-primitives", "log", "parity-scale-codec", "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?tag=sgx_1.1.3)", @@ -2011,7 +1978,6 @@ version = "0.9.0" dependencies = [ "binary-merkle-tree", "bs58", - "core-primitives", "futures 0.3.8", "itp-api-client-types", "itp-node-api", @@ -2022,7 +1988,6 @@ dependencies = [ "itp-test", "itp-top-pool-author", "itp-types", - "itp-utils", "lc-scheduled-enclave", "litentry-primitives", "log", @@ -2031,7 +1996,6 @@ dependencies = [ "sgx_types", "sp-core", "sp-runtime", - "sp-std", "thiserror", ] @@ -2079,21 +2043,6 @@ dependencies = [ "sgx_tstd", ] -[[package]] -name = "itc-rest-client" -version = "0.9.0" -dependencies = [ - "base64 0.13.1", - "http", - "http_req", - "log", - "serde 1.0.193", - "serde_json 1.0.107", - "sgx_tstd", - "thiserror", - "url", -] - [[package]] name = "itc-tls-websocket-server" version = "0.9.0" @@ -2162,7 +2111,7 @@ dependencies = [ "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx?rev=sgx_1.1.3)", "bit-vec", "chrono 0.4.11", - "hex", + "hex 0.4.3", "httparse", "itertools 0.10.5", "itp-ocall-api", @@ -2201,7 +2150,6 @@ version = "0.9.0" dependencies = [ "parity-scale-codec", "sgx_tstd", - "substrate-fixed", ] [[package]] @@ -2321,6 +2269,7 @@ dependencies = [ "derive_more", "itp-sgx-io", "itp-sgx-temp-dir", + "k256", "log", "ofb", "parity-scale-codec", @@ -2359,7 +2308,6 @@ name = "itp-sgx-runtime-primitives" version = "0.9.0" dependencies = [ "frame-system", - "litentry-primitives", "pallet-balances", "sp-core", "sp-runtime", @@ -2377,9 +2325,8 @@ dependencies = [ name = "itp-stf-executor" version = "0.9.0" dependencies = [ - "hex", + "hex 0.4.3", "itc-parentchain-test", - "itp-enclave-metrics", "itp-node-api", "itp-ocall-api", "itp-sgx-crypto", @@ -2392,7 +2339,6 @@ dependencies = [ "itp-time-utils", "itp-top-pool-author", "itp-types", - "litentry-primitives", "log", "parity-scale-codec", "sgx_tstd", @@ -2474,325 +2420,113 @@ dependencies = [ "sp-runtime", "sp-std", "sp-trie", - "thiserror", -] - -[[package]] -name = "itp-teerex-storage" -version = "0.9.0" -dependencies = [ - "itp-storage", - "sp-std", -] - -[[package]] -name = "itp-test" -version = "0.9.0" -dependencies = [ - "hex", - "itp-node-api", - "itp-node-api-metadata-provider", - "itp-ocall-api", - "itp-sgx-crypto", - "itp-sgx-externalities", - "itp-stf-interface", - "itp-stf-primitives", - "itp-stf-state-handler", - "itp-storage", - "itp-teerex-storage", - "itp-time-utils", - "itp-types", - "jsonrpc-core", - "litentry-primitives", - "log", - "parity-scale-codec", - "sgx_crypto_helper", - "sgx_tstd", - "sgx_types", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "itp-time-utils" -version = "0.9.0" -dependencies = [ - "chrono 0.4.11", - "sgx_tstd", -] - -[[package]] -name = "itp-top-pool" -version = "0.9.0" -dependencies = [ - "byteorder 1.4.3", - "derive_more", - "itc-direct-rpc-server", - "itp-stf-primitives", - "itp-types", - "its-primitives", - "jsonrpc-core", - "linked-hash-map", - "log", - "parity-scale-codec", - "sgx_tstd", - "sp-core", - "sp-runtime", -] - -[[package]] -name = "itp-top-pool-author" -version = "0.9.0" -dependencies = [ - "derive_more", - "itp-enclave-metrics", - "itp-ocall-api", - "itp-sgx-crypto", - "itp-stf-primitives", - "itp-stf-state-handler", - "itp-test", - "itp-top-pool", - "itp-types", - "itp-utils", - "jsonrpc-core", - "lazy_static", - "litentry-primitives", - "log", - "parity-scale-codec", - "sgx_tstd", - "sp-core", - "sp-runtime", -] - -[[package]] -name = "itp-types" -version = "0.9.0" -dependencies = [ - "frame-system", - "itp-sgx-crypto", - "itp-sgx-runtime-primitives", - "itp-stf-primitives", - "itp-utils", - "litentry-primitives", - "pallet-balances", - "parity-scale-codec", - "sp-core", - "sp-runtime", - "sp-std", - "substrate-api-client", -] - -[[package]] -name = "itp-utils" -version = "0.9.0" -dependencies = [ - "hex", - "parity-scale-codec", -] - -[[package]] -name = "its-block-composer" -version = "0.9.0" -dependencies = [ - "itp-node-api", - "itp-settings", - "itp-sgx-crypto", - "itp-sgx-externalities", - "itp-stf-executor", - "itp-stf-primitives", - "itp-time-utils", - "itp-top-pool-author", - "itp-types", - "its-primitives", - "its-state", - "log", - "parity-scale-codec", - "sgx_tstd", - "sgx_types", - "sp-core", - "sp-runtime", - "thiserror", -] - -[[package]] -name = "its-block-verification" -version = "0.9.0" -dependencies = [ - "frame-support", - "itp-types", - "itp-utils", - "its-primitives", - "log", - "sgx_tstd", - "sp-consensus-slots", - "sp-core", - "sp-runtime", - "thiserror", -] - -[[package]] -name = "its-consensus-aura" -version = "0.9.0" -dependencies = [ - "finality-grandpa", - "ita-stf", - "itc-parentchain-block-import-dispatcher", - "itc-peer-top-broadcaster", - "itp-enclave-metrics", - "itp-ocall-api", - "itp-settings", - "itp-sgx-crypto", - "itp-sgx-externalities", - "itp-stf-executor", - "itp-stf-primitives", - "itp-stf-state-handler", - "itp-time-utils", - "itp-top-pool-author", - "itp-types", - "itp-utils", - "its-block-composer", - "its-block-verification", - "its-consensus-common", - "its-consensus-slots", - "its-primitives", - "its-state", - "its-validateer-fetch", - "lc-scheduled-enclave", - "log", - "parity-scale-codec", - "sgx_tstd", - "sp-core", - "sp-runtime", + "thiserror", ] [[package]] -name = "its-consensus-common" +name = "itp-test" version = "0.9.0" dependencies = [ - "itc-parentchain-light-client", - "itp-enclave-metrics", - "itp-extrinsics-factory", - "itp-import-queue", - "itp-node-api-metadata", + "hex 0.4.3", + "itp-node-api", "itp-node-api-metadata-provider", "itp-ocall-api", - "itp-settings", "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-interface", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-storage", "itp-types", - "its-block-verification", - "its-primitives", - "its-state", + "jsonrpc-core", + "lc-teebag-storage", + "litentry-primitives", "log", "parity-scale-codec", + "sgx_crypto_helper", "sgx_tstd", "sgx_types", + "sp-core", + "sp-io", "sp-runtime", - "thiserror", + "sp-std", ] [[package]] -name = "its-consensus-slots" +name = "itp-time-utils" version = "0.9.0" dependencies = [ - "derive_more", - "hex", - "itp-settings", - "itp-sgx-externalities", - "itp-stf-state-handler", - "itp-time-utils", - "itp-types", - "its-block-verification", - "its-consensus-common", - "its-primitives", - "its-state", - "lazy_static", - "lc-scheduled-enclave", - "log", - "parity-scale-codec", + "chrono 0.4.11", "sgx_tstd", - "sp-consensus-slots", - "sp-runtime", ] [[package]] -name = "its-primitives" -version = "0.1.0" +name = "itp-top-pool" +version = "0.9.0" dependencies = [ + "byteorder 1.4.3", + "derive_more", + "itc-direct-rpc-server", + "itp-stf-primitives", "itp-types", + "jsonrpc-core", + "linked-hash-map", + "log", "parity-scale-codec", - "scale-info", - "serde 1.0.193", + "sgx_tstd", "sp-core", "sp-runtime", - "sp-std", ] [[package]] -name = "its-rpc-handler" +name = "itp-top-pool-author" version = "0.9.0" dependencies = [ - "futures 0.3.8", - "itp-rpc", + "derive_more", + "itp-enclave-metrics", + "itp-ocall-api", + "itp-sgx-crypto", "itp-stf-primitives", - "itp-top-pool-author", + "itp-stf-state-handler", + "itp-test", + "itp-top-pool", "itp-types", "itp-utils", - "its-primitives", "jsonrpc-core", + "lazy_static", "litentry-primitives", "log", "parity-scale-codec", - "rust-base58", "sgx_tstd", "sp-core", + "sp-runtime", ] [[package]] -name = "its-sidechain" -version = "0.9.0" -dependencies = [ - "its-block-composer", - "its-consensus-aura", - "its-consensus-common", - "its-consensus-slots", - "its-primitives", - "its-rpc-handler", - "its-state", - "its-validateer-fetch", -] - -[[package]] -name = "its-state" +name = "itp-types" version = "0.9.0" dependencies = [ - "frame-support", - "itp-sgx-externalities", - "itp-storage", - "its-primitives", - "log", + "frame-system", + "itp-sgx-crypto", + "itp-sgx-runtime-primitives", + "itp-stf-primitives", + "itp-utils", + "litentry-primitives", + "pallet-balances", "parity-scale-codec", - "sgx_tstd", "sp-core", - "sp-io", "sp-runtime", - "thiserror", + "sp-std", + "substrate-api-client", ] [[package]] -name = "its-validateer-fetch" +name = "itp-utils" version = "0.9.0" dependencies = [ - "derive_more", - "frame-support", - "itp-ocall-api", - "itp-teerex-storage", - "itp-types", + "hex 0.4.3", + "litentry-hex-utils", "parity-scale-codec", - "sp-core", - "sp-runtime", - "sp-std", ] [[package]] @@ -2818,14 +2552,15 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" dependencies = [ "cfg-if 1.0.0", "ecdsa", "elliptic-curve", "sha2 0.10.7", + "signature", ] [[package]] @@ -2852,6 +2587,21 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lc-direct-call" +version = "0.1.0" +dependencies = [ + "bc-relayer-registry", + "core-primitives", + "itp-sgx-crypto", + "itp-stf-primitives", + "litentry-primitives", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-io", +] + [[package]] name = "lc-scheduled-enclave" version = "0.8.0" @@ -2867,6 +2617,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "lc-teebag-storage" +version = "0.1.0" +dependencies = [ + "itp-storage", + "itp-types", + "sp-std", +] + [[package]] name = "libc" version = "0.2.152" @@ -2930,15 +2689,7 @@ dependencies = [ name = "litentry-hex-utils" version = "0.9.12" dependencies = [ - "hex", -] - -[[package]] -name = "litentry-macros" -version = "0.1.0" -dependencies = [ - "cargo_toml", - "quote 1.0.33", + "hex 0.4.3", ] [[package]] @@ -2951,11 +2702,11 @@ version = "0.1.0" dependencies = [ "bitcoin", "core-primitives", - "hex", + "hex 0.4.3", "itp-sgx-crypto", - "itp-utils", + "litentry-hex-utils", "log", - "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "pallet-teebag", "parity-scale-codec", "rand 0.7.3", "ring 0.16.20", @@ -2967,9 +2718,6 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std", - "strum", - "strum_macros", - "teerex-primitives 0.1.0", ] [[package]] @@ -3241,14 +2989,15 @@ dependencies = [ [[package]] name = "pallet-evm" version = "6.0.0-dev" -source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" dependencies = [ - "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fp-account 1.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", - "fp-evm 3.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "evm", + "fp-account", + "fp-evm", "frame-support", "frame-system", - "hex", + "hex 0.4.3", + "hex-literal", "impl-trait-for-tuples", "log", "parity-scale-codec", @@ -3261,53 +3010,55 @@ dependencies = [ ] [[package]] -name = "pallet-evm" -version = "6.0.0-dev" -source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +name = "pallet-parentchain" +version = "0.9.0" dependencies = [ - "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", - "fp-account 1.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", - "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", "frame-support", "frame-system", - "hex", - "hex-literal", - "impl-trait-for-tuples", - "log", "parity-scale-codec", - "rlp", "scale-info", "sp-core", "sp-io", "sp-runtime", - "sp-std", ] [[package]] -name = "pallet-parentchain" -version = "0.9.0" +name = "pallet-sudo" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", "parity-scale-codec", "scale-info", - "sp-core", "sp-io", "sp-runtime", + "sp-std", ] [[package]] -name = "pallet-sudo" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +name = "pallet-teebag" +version = "0.1.0" dependencies = [ + "base64 0.13.1", + "chrono 0.4.31", + "der 0.6.1", "frame-support", "frame-system", + "hex 0.4.3", + "log", + "pallet-timestamp", "parity-scale-codec", + "ring 0.16.20", + "rustls-webpki", "scale-info", + "serde 1.0.193", + "serde_json 1.0.107", + "sp-core", "sp-io", "sp-runtime", "sp-std", + "x509-cert", ] [[package]] @@ -3402,6 +3153,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.8", + "spki 0.7.3", +] + [[package]] name = "postcard" version = "0.7.3" @@ -3688,7 +3449,7 @@ dependencies = [ "cc", "sgx_tstd", "spin", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -3701,7 +3462,7 @@ dependencies = [ "libc", "once_cell 1.18.0", "spin", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] @@ -3791,6 +3552,22 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-pki-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47003264dea418db67060fa420ad16d0d2f8f0a0360d825c00e177ac52cb5d8" + +[[package]] +name = "rustls-webpki" +version = "0.102.0-alpha.3" +source = "git+https://github.com/rustls/webpki?rev=da923ed#da923edaab56f599971e58773617fb574cd019dc" +dependencies = [ + "ring 0.16.20", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -3917,7 +3694,7 @@ source = "git+https://github.com/mesalock-linux/sct.rs?branch=mesalock_sgx#c4d85 dependencies = [ "ring 0.16.19", "sgx_tstd", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -3927,8 +3704,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", - "der", + "der 0.7.8", "generic-array 0.14.7", + "pkcs8", "subtle", "zeroize", ] @@ -4440,17 +4218,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "sp-consensus-slots" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" -dependencies = [ - "parity-scale-codec", - "scale-info", - "sp-std", - "sp-timestamp", -] - [[package]] name = "sp-core" version = "7.0.0" @@ -4732,6 +4499,25 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.8", +] + [[package]] name = "ss58-registry" version = "1.43.0" @@ -4760,15 +4546,15 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" dependencies = [ "heck", "proc-macro2", @@ -4788,7 +4574,7 @@ dependencies = [ "async-trait", "derive_more", "frame-metadata", - "hex", + "hex 0.4.3", "log", "maybe-async", "parity-scale-codec", @@ -4799,16 +4585,6 @@ dependencies = [ "sp-runtime-interface", ] -[[package]] -name = "substrate-fixed" -version = "0.5.9" -source = "git+https://github.com/encointer/substrate-fixed?tag=v0.5.9#a4fb461aae6205ffc55bed51254a40c52be04e5d" -dependencies = [ - "parity-scale-codec", - "scale-info", - "typenum 1.16.0", -] - [[package]] name = "subtle" version = "2.4.1" @@ -4863,32 +4639,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "teerex-primitives" -version = "0.1.0" -dependencies = [ - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-std", -] - -[[package]] -name = "teerex-primitives" -version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" -dependencies = [ - "common-primitives", - "derive_more", - "log", - "parity-scale-codec", - "scale-info", - "serde 1.0.193", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "termcolor" version = "1.0.5" @@ -4925,6 +4675,14 @@ dependencies = [ "sgx_tstd", ] +[[package]] +name = "threadpool" +version = "1.8.0" +source = "git+https://github.com/mesalock-linux/rust-threadpool-sgx?tag=sgx_1.1.3#098d98a85b7e2b02e2bb451a3dec0b027017ff4c" +dependencies = [ + "sgx_tstd", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -5066,15 +4824,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "typenum" -version = "1.16.0" -source = "git+https://github.com/encointer/typenum?tag=v1.16.0#4c8dddaa8bdd13130149e43b4085ad14e960617f" -dependencies = [ - "parity-scale-codec", - "scale-info", -] - [[package]] name = "typenum" version = "1.17.0" @@ -5089,19 +4838,10 @@ checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder 1.4.3", "crunchy", - "hex", + "hex 0.4.3", "static_assertions", ] -[[package]] -name = "unicase" -version = "2.6.0" -source = "git+https://github.com/mesalock-linux/unicase-sgx#0b0519348572927118af47af3da4da9ffdca8ec6" -dependencies = [ - "sgx_tstd", - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.4" @@ -5149,6 +4889,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.1.1" @@ -5251,7 +4997,7 @@ source = "git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx#8dbe6 dependencies = [ "ring 0.16.19", "sgx_tstd", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -5312,6 +5058,18 @@ dependencies = [ "tap", ] +[[package]] +name = "x509-cert" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d224a125dec5adda27d0346b9cae9794830279c4f9c27e4ab0b6c408d54012" +dependencies = [ + "const-oid", + "der 0.6.1", + "flagset", + "spki 0.6.0", +] + [[package]] name = "yasna" version = "0.3.1" @@ -5325,9 +5083,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] @@ -5342,8 +5100,3 @@ dependencies = [ "quote 1.0.33", "syn 2.0.37", ] - -[[patch.unused]] -name = "getrandom" -version = "0.2.3" -source = "git+https://github.com/integritee-network/getrandom-sgx?branch=update-v2.3#0a4af01fe1df0e6200192e7a709fd18da413466e" diff --git a/bitacross-worker/enclave-runtime/Cargo.toml b/bitacross-worker/enclave-runtime/Cargo.toml index c6eae4b549..79127983eb 100644 --- a/bitacross-worker/enclave-runtime/Cargo.toml +++ b/bitacross-worker/enclave-runtime/Cargo.toml @@ -13,21 +13,18 @@ crate-type = ["staticlib"] [features] default = [] -evm = [ - "ita-sgx-runtime/evm", - "ita-stf/evm", +production = [ + "ita-stf/production", + "itp-settings/production", + "itp-attestation-handler/production", + "litentry-primitives/production", + "litentry-macros/production", + "bc-task-receiver/production", ] -production = ["itp-settings/production", "itp-attestation-handler/production"] -sidechain = ["itp-settings/sidechain", "itp-top-pool-author/sidechain"] offchain-worker = [ "itp-settings/offchain-worker", "itp-top-pool-author/offchain-worker", ] -teeracle = [ - "ita-oracle", - "itp-settings/teeracle", - "itp-top-pool-author/teeracle", -] test = [ "ita-stf/test", "itc-parentchain/test", @@ -43,8 +40,6 @@ test = [ "itp-test/sgx", "itp-top-pool-author/test", "itp-top-pool-author/mocks", - # substrate - "frame-system", ] dcap = [] @@ -65,11 +60,13 @@ sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-s array-bytes = { version = "6.0.0" } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } derive_more = { version = "0.99.5" } +futures_sgx = { package = "futures", git = "https://github.com/mesalock-linux/futures-rs-sgx" } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } ipfs-unixfs = { default-features = false, git = "https://github.com/whalelephant/rust-ipfs", branch = "w-nstd" } lazy_static = { version = "1.1.0", features = ["spin_no_std"] } primitive-types = { version = "0.12.1", default-features = false, features = ["codec", "serde_no_std"] } + # scs / integritee jsonrpc-core = { default-features = false, git = "https://github.com/scs/jsonrpc", branch = "no_std_v18" } @@ -87,10 +84,8 @@ base58 = { rev = "sgx_1.1.3", package = "rust-base58", default-features = false, cid = { default-features = false, git = "https://github.com/whalelephant/rust-cid", branch = "nstd" } multibase = { default-features = false, git = "https://github.com/whalelephant/rust-multibase", branch = "nstd" } -teerex-primitives = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } # local deps -ita-oracle = { path = "../app-libs/oracle", default-features = false, optional = true, features = ["sgx"] } ita-parentchain-interface = { path = "../app-libs/parentchain-interface", default-features = false, features = ["sgx"] } ita-sgx-runtime = { path = "../app-libs/sgx-runtime", default-features = false } ita-stf = { path = "../app-libs/stf", default-features = false, features = ["sgx"] } @@ -99,16 +94,17 @@ itc-direct-rpc-server = { path = "../core/direct-rpc-server", default-features = itc-offchain-worker-executor = { path = "../core/offchain-worker-executor", default-features = false, features = ["sgx"] } itc-parentchain = { path = "../core/parentchain/parentchain-crate", default-features = false, features = ["sgx"] } itc-parentchain-block-import-dispatcher = { path = "../core/parentchain/block-import-dispatcher", default-features = false, features = ["sgx"] } +itc-parentchain-light-client = { path = "../core/parentchain/light-client", default-features = false } itc-parentchain-test = { path = "../core/parentchain/test", default-features = false } itc-peer-top-broadcaster = { path = "../core/peer-top-broadcaster", default-features = false, features = ["sgx"] } itc-tls-websocket-server = { path = "../core/tls-websocket-server", default-features = false, features = ["sgx"] } itp-attestation-handler = { path = "../core-primitives/attestation-handler", default-features = false, features = ["sgx"] } itp-component-container = { path = "../core-primitives/component-container", default-features = false, features = ["sgx"] } -itp-enclave-metrics = { path = "../core-primitives/enclave-metrics", default-features = false, features = ["sgx"] } itp-extrinsics-factory = { path = "../core-primitives/extrinsics-factory", default-features = false, features = ["sgx"] } itp-import-queue = { path = "../core-primitives/import-queue", default-features = false, features = ["sgx"] } itp-node-api = { path = "../core-primitives/node-api", default-features = false, features = ["sgx"] } itp-node-api-metadata = { path = "../core-primitives/node-api/metadata", default-features = false } +itp-node-api-metadata-provider = { path = "../core-primitives/node-api/metadata-provider", default-features = false } itp-nonce-cache = { path = "../core-primitives/nonce-cache", default-features = false, features = ["sgx"] } itp-ocall-api = { path = "../core-primitives/ocall-api", default-features = false } itp-primitives-cache = { path = "../core-primitives/primitives-cache", default-features = false, features = ["sgx"] } @@ -123,23 +119,25 @@ itp-stf-state-handler = { path = "../core-primitives/stf-state-handler", default itp-stf-state-observer = { path = "../core-primitives/stf-state-observer", default-features = false, features = ["sgx"] } itp-storage = { path = "../core-primitives/storage", default-features = false, features = ["sgx"] } itp-test = { path = "../core-primitives/test", default-features = false, optional = true } -itp-time-utils = { path = "../core-primitives/time-utils", default-features = false, features = ["sgx"] } itp-top-pool = { path = "../core-primitives/top-pool", default-features = false, features = ["sgx"] } itp-top-pool-author = { path = "../core-primitives/top-pool-author", default-features = false, features = ["sgx"] } itp-types = { path = "../core-primitives/types", default-features = false } itp-utils = { path = "../core-primitives/utils", default-features = false } -its-block-verification = { path = "../sidechain/block-verification", default-features = false } -its-primitives = { path = "../sidechain/primitives", default-features = false } -its-sidechain = { path = "../sidechain/sidechain-crate", default-features = false, features = ["sgx"] } # litentry +bc-relayer-registry = { path = "../bitacross/core/bc-relayer-registry", default-features = false, features = ["sgx"] } +bc-task-sender = { path = "../bitacross/core/bc-task-sender", default-features = false, features = ["sgx"] } lc-scheduled-enclave = { path = "../litentry/core/scheduled-enclave", default-features = false, features = ["sgx"] } -litentry-macros = { path = "../litentry/macros" } +litentry-hex-utils = { path = "../../primitives/hex", default-features = false } +litentry-macros = { path = "../../primitives/core/macros", default-features = false } litentry-primitives = { path = "../litentry/primitives", default-features = false, features = ["sgx"] } +litentry-proc-macros = { path = "../../primitives/core/proc-macros", default-features = false } + +# bitacross +bc-task-receiver = { path = "../bitacross/core/bc-task-receiver", default-features = false, features = ["sgx"] } # substrate deps frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -frame-system = { optional = true, default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } @@ -148,7 +146,6 @@ itp-sgx-temp-dir = { version = "0.1", default-features = false, optional = true, [patch.crates-io] env_logger = { git = "https://github.com/integritee-network/env_logger-sgx" } -getrandom = { git = "https://github.com/integritee-network/getrandom-sgx", branch = "update-v2.3" } log = { git = "https://github.com/integritee-network/log-sgx" } [patch."https://github.com/mesalock-linux/log-sgx"] diff --git a/bitacross-worker/enclave-runtime/Enclave.edl b/bitacross-worker/enclave-runtime/Enclave.edl index 04c02fea61..7ebae232ac 100644 --- a/bitacross-worker/enclave-runtime/Enclave.edl +++ b/bitacross-worker/enclave-runtime/Enclave.edl @@ -43,10 +43,9 @@ enclave { [in, size=encoded_base_dir_size] uint8_t* encoded_base_dir_str, uint32_t encoded_base_dir_size ); - public sgx_status_t init_enclave_sidechain_components( - [in, size=fail_mode_size] uint8_t* fail_mode, uint32_t fail_mode_size, - [in, size=fail_at_size] uint8_t* fail_at, uint32_t fail_at_size - ); + public sgx_status_t publish_wallets(); + + public sgx_status_t init_enclave_sidechain_components(); public sgx_status_t init_direct_invocation_server( [in, size=server_addr_size] uint8_t* server_addr, uint32_t server_addr_size @@ -66,8 +65,6 @@ enclave { [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size ); - public sgx_status_t execute_trusted_calls(); - public sgx_status_t sync_parentchain( [in, size=blocks_size] uint8_t* blocks, size_t blocks_size, [in, size=events_size] uint8_t* events, size_t events_size, @@ -92,6 +89,12 @@ enclave { public sgx_status_t get_ecc_signing_pubkey( [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); + public sgx_status_t get_bitcoin_wallet_pair( + [out, size=pair_size] uint8_t* pair, uint32_t pair_size); + + public sgx_status_t get_ethereum_wallet_pair( + [out, size=pair_size] uint8_t* pair, uint32_t pair_size); + public sgx_status_t get_ecc_vault_pubkey( [in, size=shard_size] uint8_t* shard, uint32_t shard_size, [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); @@ -140,20 +143,6 @@ enclave { [out] uint32_t* unchecked_extrinsic_size ); - public sgx_status_t update_market_data_xt( - [in, size=crypto_currency_size] uint8_t* crypto_currency, uint32_t crypto_currency_size, - [in, size=fiat_currency_size] uint8_t* fiat_currency, uint32_t fiat_currency_size, - [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, - [out] uint32_t* unchecked_extrinsic_size - ); - - public sgx_status_t update_weather_data_xt( - [in, size=weather_info_logitude_size] uint8_t* weather_info_logitude, uint32_t weather_info_logitude_size, - [in, size=weather_info_latitude_size] uint8_t* weather_info_latitude, uint32_t weather_info_latitude_size, - [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, - [out] uint32_t* unchecked_extrinsic_size - ); - public sgx_status_t dump_ias_ra_cert_to_disk(); public sgx_status_t dump_dcap_ra_cert_to_disk([in] const sgx_target_info_t* quoting_enclave_target_info, uint32_t quote_size); @@ -176,11 +165,6 @@ enclave { int skip_ra ); - public sgx_status_t call_rpc_methods( - [in, size=request_len] uint8_t* request, uint32_t request_len, - [out, size=response_len] uint8_t* response, uint32_t response_len - ); - public size_t test_main_entrance(); public sgx_status_t migrate_shard( @@ -251,23 +235,6 @@ enclave { [in, size = metric_size] uint8_t * metric, uint32_t metric_size ); - sgx_status_t ocall_propose_sidechain_blocks( - [in, size = signed_blocks_size] uint8_t * signed_blocks, uint32_t signed_blocks_size - ); - - sgx_status_t ocall_store_sidechain_blocks( - [in, size = signed_blocks_size] uint8_t * signed_blocks, uint32_t signed_blocks_size - ); - - sgx_status_t ocall_fetch_sidechain_blocks_from_peer( - [in, size = last_imported_block_hash_size] uint8_t * last_imported_block_hash, uint32_t last_imported_block_hash_size, - [in, size = maybe_until_block_hash_size] uint8_t * maybe_until_block_hash, uint32_t maybe_until_block_hash_size, - [in, size = shard_identifier_size] uint8_t * shard_identifier, uint32_t shard_identifier_size, - [out, size = sidechain_blocks_size] uint8_t * sidechain_blocks, uint32_t sidechain_blocks_size - ); - - sgx_status_t ocall_get_trusted_peers_urls([out, size = peers_size] uint8_t * peers, uint32_t peers_size); - sgx_status_t ocall_send_to_parentchain( [in, size = extrinsics_size] uint8_t * extrinsics, uint32_t extrinsics_size, [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size, diff --git a/bitacross-worker/enclave-runtime/Makefile b/bitacross-worker/enclave-runtime/Makefile index b4dc322eed..bf3aa55dee 100644 --- a/bitacross-worker/enclave-runtime/Makefile +++ b/bitacross-worker/enclave-runtime/Makefile @@ -27,8 +27,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ######## Worker Feature Settings ######## -# Set sidechain as default feature mode -WORKER_MODE ?= sidechain +# Set offchain-worker as default feature mode +WORKER_MODE ?= offchain-worker Rust_Enclave_Name := libenclave.a Rust_Enclave_Files := $(wildcard src/*.rs) $(wildcard ../stf/src/*.rs) diff --git a/bitacross-worker/enclave-runtime/src/attestation.rs b/bitacross-worker/enclave-runtime/src/attestation.rs index 5b7f7ded3a..08348de70f 100644 --- a/bitacross-worker/enclave-runtime/src/attestation.rs +++ b/bitacross-worker/enclave-runtime/src/attestation.rs @@ -42,7 +42,7 @@ use itp_attestation_handler::{AttestationHandler, RemoteAttestationType, SgxQlQv use itp_component_container::ComponentGetter; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::metadata::{ - pallet_teerex::TeerexCallIndexes, + pallet_teebag::TeebagCallIndexes, provider::{AccessNodeMetadata, Error as MetadataProviderError}, Error as MetadataError, }; @@ -51,11 +51,12 @@ use itp_settings::worker::MR_ENCLAVE_SIZE; use itp_sgx_crypto::{ ed25519_derivation::DeriveEd25519, key_repository::AccessKey, Error as SgxCryptoError, }; -use itp_types::OpaqueCall; +use itp_types::{AttestationType, OpaqueCall, WorkerType}; use itp_utils::write_slice_and_whitespace_pad; +use litentry_primitives::WorkerMode; use log::*; use sgx_types::*; -use sp_core::Pair; +use sp_core::{ed25519::Public as Ed25519Public, Pair}; use sp_runtime::OpaqueExtrinsic; use std::{prelude::v1::*, slice, vec::Vec}; @@ -142,7 +143,8 @@ pub unsafe extern "C" fn generate_ias_ra_extrinsic( } let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); let url = match String::decode(&mut url_slice) { - Ok(url) => url, + // Litentry: the teebag extrinsic expects an URL with plain utf8 encoded Vec, not string scale-encoded + Ok(url) => url.as_bytes().to_vec(), Err(_) => return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), }; @@ -178,7 +180,8 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( } let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); let url = match String::decode(&mut url_slice) { - Ok(url) => url, + // Litentry: the teebag extrinsic expects an URL with plain utf8 encoded Vec, not string scale-encoded + Ok(url) => url.as_bytes().to_vec(), Err(_) => return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), }; @@ -204,7 +207,7 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( } pub fn generate_dcap_ra_extrinsic_internal( - url: String, + url: Vec, skip_ra: bool, quoting_enclave_target_info: Option<&sgx_target_info_t>, quote_size: Option<&u32>, @@ -287,7 +290,8 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic_from_quote( } let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); let url = match String::decode(&mut url_slice) { - Ok(url) => url, + // Litentry: the teebag extrinsic expects an URL with plain utf8 encoded Vec, not string scale-encoded + Ok(url) => url.as_bytes().to_vec(), Err(_) => return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), }; @@ -311,7 +315,7 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic_from_quote( } pub fn generate_dcap_ra_extrinsic_from_quote_internal( - url: String, + url: Vec, quote: &[u8], ) -> EnclaveResult { let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; @@ -324,15 +328,24 @@ pub fn generate_dcap_ra_extrinsic_from_quote_internal( let shielding_pubkey = get_shielding_pubkey()?; let vc_pubkey = get_vc_pubkey()?; + let attestation_type = AttestationType::Dcap(Default::default()); // skip_ra should be false here already - let call = OpaqueCall::from_tuple(&(call_ids, quote, url, shielding_pubkey, vc_pubkey)); - + let call = OpaqueCall::from_tuple(&( + call_ids, + WorkerType::BitAcross, + WorkerMode::OffChainWorker, + quote, + url, + shielding_pubkey, + vc_pubkey, + attestation_type, + )); info!(" [Enclave] Compose register enclave got extrinsic, returning"); create_extrinsics(call) } pub fn generate_dcap_skip_ra_extrinsic_from_mr_enclave( - url: String, + url: Vec, quote: &[u8], ) -> EnclaveResult { let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; @@ -346,25 +359,34 @@ pub fn generate_dcap_skip_ra_extrinsic_from_mr_enclave( let shielding_pubkey = get_shielding_pubkey()?; let vc_pubkey = get_vc_pubkey()?; - let call = OpaqueCall::from_tuple(&(call_ids, quote, url, shielding_pubkey, vc_pubkey)); - + let call = OpaqueCall::from_tuple(&( + call_ids, + WorkerType::BitAcross, + WorkerMode::OffChainWorker, + quote, + url, + shielding_pubkey, + vc_pubkey, + AttestationType::Ignore, + )); info!(" [Enclave] Compose register enclave (skip-ra) got extrinsic, returning"); create_extrinsics(call) } fn generate_ias_ra_extrinsic_internal( - url: String, + url: Vec, skip_ra: bool, ) -> EnclaveResult { let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; let cert_der = attestation_handler.generate_ias_ra_cert(skip_ra)?; - generate_ias_ra_extrinsic_from_der_cert_internal(url, &cert_der) + generate_ias_ra_extrinsic_from_der_cert_internal(url, &cert_der, skip_ra) } pub fn generate_ias_ra_extrinsic_from_der_cert_internal( - url: String, + url: Vec, cert_der: &[u8], + skip_ra: bool, ) -> EnclaveResult { let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; @@ -375,9 +397,18 @@ pub fn generate_ias_ra_extrinsic_from_der_cert_internal( let shielding_pubkey = get_shielding_pubkey()?; let vc_pubkey = get_vc_pubkey()?; + let attestation_type = if skip_ra { AttestationType::Ignore } else { AttestationType::Ias }; - let call = OpaqueCall::from_tuple(&(call_ids, cert_der, url, shielding_pubkey, vc_pubkey)); - + let call = OpaqueCall::from_tuple(&( + call_ids, + WorkerType::BitAcross, + WorkerMode::OffChainWorker, + cert_der, + url, + shielding_pubkey, + vc_pubkey, + attestation_type, + )); create_extrinsics(call) } @@ -533,18 +564,16 @@ fn get_shielding_pubkey() -> EnclaveResult>> { }) .ok(); - debug!("[Enclave] shielding_pubkey size: {:?}", shielding_pubkey.clone().map(|key| key.len())); - Ok(shielding_pubkey) } -fn get_vc_pubkey() -> EnclaveResult>> { +fn get_vc_pubkey() -> EnclaveResult> { let vc_pubkey = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT .get()? .retrieve_key() .and_then(|keypair| { // vc signing pubkey - keypair.derive_ed25519().map(|keypair| keypair.public().to_vec()) + keypair.derive_ed25519().map(|keypair| keypair.public()) }) .ok(); diff --git a/bitacross-worker/enclave-runtime/src/empty_impls.rs b/bitacross-worker/enclave-runtime/src/empty_impls.rs index e401fa8d05..e011e4d19c 100644 --- a/bitacross-worker/enclave-runtime/src/empty_impls.rs +++ b/bitacross-worker/enclave-runtime/src/empty_impls.rs @@ -22,35 +22,3 @@ pub extern "C" fn test_main_entrance() -> sgx_types::size_t { unreachable!("Tests are not available when compiled in production mode.") } - -/// Empty Teeracle market data implementation. -#[cfg(not(feature = "teeracle"))] -#[no_mangle] -#[allow(clippy::unreachable)] -pub unsafe extern "C" fn update_market_data_xt( - _crypto_currency_ptr: *const u8, - _crypto_currency_size: u32, - _fiat_currency_ptr: *const u8, - _fiat_currency_size: u32, - _unchecked_extrinsic: *mut u8, - _unchecked_extrinsic_max_size: u32, - _unchecked_extrinsic_size: *mut u32, -) -> sgx_types::sgx_status_t { - unreachable!("Cannot update market data, teeracle feature is not enabled.") -} - -/// Empty Teeracle Weather data implementation. -#[cfg(not(feature = "teeracle"))] -#[no_mangle] -#[allow(clippy::unreachable)] -pub unsafe extern "C" fn update_weather_data_xt( - _weather_info_longitude: *const u8, - _weather_info_longitude_size: u32, - _weather_info_latitude: *const u8, - _weather_info_latitude_size: u32, - _unchecked_extrinsic: *mut u8, - _unchecked_extrinsic_max_size: u32, - _unchecked_extrinsic_size: *mut u32, -) -> sgx_types::sgx_status_t { - unreachable!("Cannot update weather data, teeracle feature is not enabled.") -} diff --git a/bitacross-worker/enclave-runtime/src/error.rs b/bitacross-worker/enclave-runtime/src/error.rs index da657f87de..04ff2b796d 100644 --- a/bitacross-worker/enclave-runtime/src/error.rs +++ b/bitacross-worker/enclave-runtime/src/error.rs @@ -34,7 +34,6 @@ pub enum Error { NodeMetadataProvider(itp_node_api::metadata::provider::Error), Sgx(sgx_status_t), SgxQuote(sgx_quote3_error_t), - Consensus(its_sidechain::consensus_common::Error), Stf(String), StfStateHandler(itp_stf_state_handler::error::Error), StfExecution(itp_stf_executor::error::Error), diff --git a/bitacross-worker/enclave-runtime/src/initialization/global_components.rs b/bitacross-worker/enclave-runtime/src/initialization/global_components.rs index 8f45ddcc7f..261c7fdfd0 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/global_components.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/global_components.rs @@ -63,7 +63,12 @@ use itp_node_api::{ metadata::{provider::NodeMetadataRepository, NodeMetadata}, }; use itp_nonce_cache::NonceCache; -use itp_sgx_crypto::{key_repository::KeyRepository, Aes, AesSeal, Ed25519Seal, Rsa3072Seal}; +use itp_sgx_crypto::{ + ecdsa::{Pair as EcdsaPair, Seal as EcdsaSeal}, + key_repository::KeyRepository, + schnorr::{Pair as SchnorrPair, Seal as SchnorrSeal}, + Aes, AesSeal, Ed25519Seal, Rsa3072Seal, +}; use itp_stf_executor::{ enclave_signer::StfEnclaveSigner, executor::StfExecutor, getter_executor::GetterExecutor, state_getter::StfStateGetter, @@ -80,16 +85,6 @@ use itp_top_pool_author::{ author::{Author, AuthorTopFilter, BroadcastedTopFilter}, }; use itp_types::{Block as ParentchainBlock, SignedBlock as SignedParentchainBlock}; -use its_primitives::{ - traits::{Block as SidechainBlockTrait, SignedBlock as SignedSidechainBlockTrait}, - types::block::SignedBlock as SignedSidechainBlock, -}; -use its_sidechain::{ - aura::block_importer::BlockImporter as SidechainBlockImporter, - block_composer::BlockComposer, - consensus_common::{BlockImportConfirmationHandler, BlockImportQueueWorker, PeerBlockSync}, - slots::FailSlotOnDemand, -}; use lazy_static::lazy_static; use litentry_primitives::BroadcastedRequest; use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; @@ -106,6 +101,8 @@ pub type EnclaveStf = Stf; pub type EnclaveShieldingKeyRepository = KeyRepository; pub type EnclaveSigningKeyRepository = KeyRepository; +pub type EnclaveBitcoinKeyRepository = KeyRepository; +pub type EnclaveEthereumKeyRepository = KeyRepository; pub type EnclaveStateFileIo = SgxStateFileIo; pub type EnclaveStateSnapshotRepository = StateSnapshotRepository; pub type EnclaveStateObserver = StateObserver; @@ -174,7 +171,7 @@ pub type IntegriteeParentchainIndirectCallsExecutor = IndirectCallsExecutor< EnclaveStfEnclaveSigner, EnclaveTopPoolAuthor, EnclaveNodeMetadataRepository, - integritee::ShieldFundsAndInvokeFilter, + integritee::BitAcrossIndirectCallsFilter, EventCreator, integritee::ParentchainEventHandler, EnclaveTrustedCallSigned, @@ -309,43 +306,6 @@ pub type EnclaveTopPoolAuthor = Author< EnclaveGetter, >; pub type EnclaveDirectRpcBroadcaster = DirectRpcBroadcaster; -pub type EnclaveSidechainBlockComposer = - BlockComposer; -pub type EnclaveSidechainBlockImporter = SidechainBlockImporter< - Pair, - ParentchainBlock, - SignedSidechainBlock, - EnclaveOCallApi, - EnclaveStateHandler, - EnclaveStateKeyRepository, - EnclaveTopPoolAuthor, - // For now the sidechain does only support one parentchain. - IntegriteeParentchainTriggeredBlockImportDispatcher, - EnclaveDirectRpcBroadcaster, - EnclaveTrustedCallSigned, - EnclaveGetter, ->; -pub type EnclaveSidechainBlockImportQueue = ImportQueue; -pub type EnclaveBlockImportConfirmationHandler = BlockImportConfirmationHandler< - ParentchainBlock, - <::Block as SidechainBlockTrait>::HeaderType, - EnclaveNodeMetadataRepository, - EnclaveExtrinsicsFactory, - EnclaveValidatorAccessor, ->; -pub type EnclaveSidechainBlockSyncer = PeerBlockSync< - ParentchainBlock, - SignedSidechainBlock, - EnclaveSidechainBlockImporter, - EnclaveOCallApi, - EnclaveBlockImportConfirmationHandler, ->; -pub type EnclaveSidechainBlockImportQueueWorker = BlockImportQueueWorker< - ParentchainBlock, - SignedSidechainBlock, - EnclaveSidechainBlockImportQueue, - EnclaveSidechainBlockSyncer, ->; pub type EnclaveSealHandler = SealHandler< EnclaveShieldingKeyRepository, EnclaveStateKeyRepository, @@ -381,6 +341,16 @@ pub static GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT: ComponentContainer< EnclaveSigningKeyRepository, > = ComponentContainer::new("Signing key repository"); +/// Bitcoin key repository +pub static GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT: ComponentContainer< + EnclaveBitcoinKeyRepository, +> = ComponentContainer::new("Bitcoin key repository"); + +/// Ethereum key repository +pub static GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT: ComponentContainer< + EnclaveEthereumKeyRepository, +> = ComponentContainer::new("Ethereum key repository"); + /// Light client db seal for the Integritee parentchain pub static GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer< EnclaveLightClientSeal, @@ -474,28 +444,3 @@ pub static GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT: ComponentContainer< /// Enclave RPC WS handler. pub static GLOBAL_RPC_WS_HANDLER_COMPONENT: ComponentContainer = ComponentContainer::new("rpc_ws_handler"); - -/// Sidechain import queue. -pub static GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT: ComponentContainer< - EnclaveSidechainBlockImportQueue, -> = ComponentContainer::new("sidechain_import_queue"); - -/// Sidechain import queue worker - processes the import queue. -pub static GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT: ComponentContainer< - EnclaveSidechainBlockImportQueueWorker, -> = ComponentContainer::new("sidechain_import_queue_worker"); - -/// Sidechain block composer. -pub static GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT: ComponentContainer< - EnclaveSidechainBlockComposer, -> = ComponentContainer::new("sidechain_block_composer"); - -/// Sidechain block syncer. -pub static GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT: ComponentContainer< - EnclaveSidechainBlockSyncer, -> = ComponentContainer::new("sidechain_block_syncer"); - -/// Sidechain fail slot on demand. -pub static GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT: ComponentContainer< - Option, -> = ComponentContainer::new("sidechain_fail_slot_on_demand"); diff --git a/bitacross-worker/enclave-runtime/src/initialization/mod.rs b/bitacross-worker/enclave-runtime/src/initialization/mod.rs index 1510341a61..56415e0921 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/mod.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/mod.rs @@ -15,47 +15,45 @@ */ +#![allow(clippy::unwrap_used)] + pub mod global_components; pub mod parentchain; use crate::{ error::{Error, Result as EnclaveResult}, + get_node_metadata_repository_from_integritee_solo_or_parachain, + get_validator_accessor_from_integritee_solo_or_parachain, initialization::global_components::{ - EnclaveBlockImportConfirmationHandler, EnclaveGetterExecutor, EnclaveLightClientSeal, - EnclaveOCallApi, EnclaveRpcResponder, EnclaveShieldingKeyRepository, EnclaveSidechainApi, - EnclaveSidechainBlockImportQueue, EnclaveSidechainBlockImportQueueWorker, - EnclaveSidechainBlockImporter, EnclaveSidechainBlockSyncer, EnclaveStateFileIo, + EnclaveGetterExecutor, EnclaveLightClientSeal, EnclaveOCallApi, EnclaveRpcResponder, + EnclaveShieldingKeyRepository, EnclaveSidechainApi, EnclaveStateFileIo, EnclaveStateHandler, EnclaveStateInitializer, EnclaveStateObserver, EnclaveStateSnapshotRepository, EnclaveStfEnclaveSigner, EnclaveTopPool, EnclaveTopPoolAuthor, DIRECT_RPC_REQUEST_SINK_COMPONENT, - GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT, + GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT, + GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT, GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT, GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_OCALL_API_COMPONENT, GLOBAL_RPC_WS_HANDLER_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, - GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT, - GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT, GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT, - GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, - GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, - GLOBAL_STATE_OBSERVER_COMPONENT, GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_OBSERVER_COMPONENT, + GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TOP_POOL_AUTHOR_COMPONENT, GLOBAL_WEB_SOCKET_SERVER_COMPONENT, }, ocall::OcallApi, rpc::{rpc_response_channel::RpcResponseChannel, worker_api_direct::public_api_rpc_handler}, - utils::{ - get_extrinsic_factory_from_integritee_solo_or_parachain, - get_node_metadata_repository_from_integritee_solo_or_parachain, - get_triggered_dispatcher_from_integritee_solo_or_parachain, - get_validator_accessor_from_integritee_solo_or_parachain, - }, + utils::get_extrinsic_factory_from_integritee_solo_or_parachain, Hash, }; use base58::ToBase58; +use bc_relayer_registry::{RelayerRegistryUpdater, GLOBAL_RELAYER_REGISTRY}; +use bc_task_receiver::{run_bit_across_handler_runner, BitAcrossTaskContext}; use codec::Encode; -use core::str::FromStr; use ita_stf::{Getter, TrustedCallSigned}; use itc_direct_rpc_server::{ create_determine_watch, rpc_connection_registry::ConnectionRegistry, rpc_ws_handler::RpcWsHandler, }; +use itc_parentchain_light_client::{concurrent_access::ValidatorAccess, ExtrinsicSender}; use itc_peer_top_broadcaster::init; use itc_tls_websocket_server::{ certificate_generation::ed25519_self_signed_certificate, create_ws_server, ConnectionToken, @@ -63,13 +61,17 @@ use itc_tls_websocket_server::{ }; use itp_attestation_handler::{AttestationHandler, IntelAttestationHandler}; use itp_component_container::{ComponentGetter, ComponentInitializer}; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_node_api_metadata::pallet_bitacross::BitAcrossCallIndexes; +use itp_node_api_metadata_provider::AccessNodeMetadata; use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; use itp_settings::files::{ LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, }; use itp_sgx_crypto::{ - get_aes_repository, get_ed25519_repository, get_rsa3072_repository, key_repository::AccessKey, + ecdsa::create_ecdsa_repository, get_aes_repository, get_ed25519_repository, + get_rsa3072_repository, key_repository::AccessKey, schnorr::create_schnorr_repository, }; use itp_stf_state_handler::{ file_io::StateDir, handle_state::HandleState, query_shard_state::QueryShardState, @@ -78,27 +80,34 @@ use itp_stf_state_handler::{ }; use itp_top_pool::pool::Options as PoolOptions; use itp_top_pool_author::author::{AuthorTopFilter, BroadcastedTopFilter}; -use itp_types::{parentchain::ParentchainId, ShardIdentifier}; -use its_sidechain::{ - block_composer::BlockComposer, - slots::{FailSlotMode, FailSlotOnDemand}, -}; +use itp_types::{parentchain::ParentchainId, OpaqueCall, ShardIdentifier}; use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; use litentry_primitives::BroadcastedRequest; use log::*; -use sgx_types::sgx_status_t; use sp_core::crypto::Pair; use std::{collections::HashMap, path::PathBuf, string::String, sync::Arc}; + pub(crate) fn init_enclave( mu_ra_url: String, untrusted_worker_url: String, base_dir: PathBuf, ) -> EnclaveResult<()> { let signing_key_repository = Arc::new(get_ed25519_repository(base_dir.clone())?); + GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.initialize(signing_key_repository.clone()); let signer = signing_key_repository.retrieve_key()?; info!("[Enclave initialized] Ed25519 prim raw : {:?}", signer.public().0); + let bitcoin_key_repository = Arc::new(create_schnorr_repository(base_dir.clone(), "bitcoin")?); + GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT.initialize(bitcoin_key_repository.clone()); + let bitcoin_key = bitcoin_key_repository.retrieve_key()?; + info!("[Enclave initialized] Bitcoin public key raw : {:?}", bitcoin_key.public_bytes()); + + let ethereum_key_repository = Arc::new(create_ecdsa_repository(base_dir.clone(), "ethereum")?); + GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT.initialize(ethereum_key_repository.clone()); + let ethereum_key = ethereum_key_repository.retrieve_key()?; + info!("[Enclave initialized] Ethereum public key raw : {:?}", ethereum_key.public_bytes()); + let shielding_key_repository = Arc::new(get_rsa3072_repository(base_dir.clone())?); GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.initialize(shielding_key_repository.clone()); @@ -185,7 +194,7 @@ pub(crate) fn init_enclave( let top_pool_author = create_top_pool_author( rpc_responder, - state_handler.clone(), + state_handler, ocall_api.clone(), shielding_key_repository.clone(), request_sink_cloned, @@ -200,18 +209,55 @@ pub(crate) fn init_enclave( top_pool_author, getter_executor, shielding_key_repository, - Some(state_handler), + ocall_api.clone(), ); let rpc_handler = Arc::new(RpcWsHandler::new(io_handler, watch_extractor, connection_registry)); GLOBAL_RPC_WS_HANDLER_COMPONENT.initialize(rpc_handler); - let sidechain_block_import_queue = Arc::new(EnclaveSidechainBlockImportQueue::default()); - GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT.initialize(sidechain_block_import_queue); - let attestation_handler = Arc::new(IntelAttestationHandler::new(ocall_api, signing_key_repository)); GLOBAL_ATTESTATION_HANDLER_COMPONENT.initialize(attestation_handler); + GLOBAL_RELAYER_REGISTRY.init().map_err(|e| Error::Other(e.into()))?; + + std::thread::spawn(move || run_bit_across_handler().unwrap()); + + Ok(()) +} + +pub(crate) fn publish_wallets() -> EnclaveResult<()> { + let metadata_repository = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let validator_accessor = get_validator_accessor_from_integritee_solo_or_parachain()?; + + let bitcoin_key_repository = GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT.get()?; + let bitcoin_key = bitcoin_key_repository.retrieve_key()?; + + let bitcoin_call = metadata_repository + .get_from_metadata(|m| m.btc_wallet_generated_indexes()) + .map_err(|e| Error::Other(e.into()))? + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + + let bitcoin_opaque_call = OpaqueCall::from_tuple(&(bitcoin_call, bitcoin_key.public_bytes())); + + let ethereum_key_repository = GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT.get()?; + let ethereum_key = ethereum_key_repository.retrieve_key()?; + + let ethereum_call = metadata_repository + .get_from_metadata(|m| m.eth_wallet_generated_indexes()) + .map_err(|e| Error::Other(e.into()))? + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + + let ethereum_opaque_call = + OpaqueCall::from_tuple(&(ethereum_call, ethereum_key.public_bytes())); + + let xts = extrinsics_factory + .create_extrinsics(&[bitcoin_opaque_call, ethereum_opaque_call], None) + .map_err(|e| Error::Other(e.into()))?; + validator_accessor + .execute_mut_on_validator(|v| v.send_extrinsics(xts)) + .map_err(|e| Error::Other(e.into()))?; + Ok(()) } @@ -230,73 +276,43 @@ fn initialize_state_observer( Ok(Arc::new(EnclaveStateObserver::from_map(states_map))) } -pub(crate) fn init_enclave_sidechain_components( - fail_mode: Option, - fail_at: u64, -) -> EnclaveResult<()> { +fn run_bit_across_handler() -> Result<(), Error> { + let author_api = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; - let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; - let direct_rpc_broadcaster = GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT.get()?; + let state_observer = GLOBAL_STATE_OBSERVER_COMPONENT.get()?; + let relayer_registry_lookup = GLOBAL_RELAYER_REGISTRY.clone(); - let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; - let state_key_repository = GLOBAL_STATE_KEY_REPOSITORY_COMPONENT.get()?; + let shielding_key_repository = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get()?; + let ethereum_key_repository = GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT.get()?; + let bitcoin_key_repository = GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT.get()?; - // GLOBAL_SCHEDULED_ENCLAVE must be initialized after attestation_handler and enclave - let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; - let mrenclave = attestation_handler.get_mrenclave()?; - GLOBAL_SCHEDULED_ENCLAVE.init(mrenclave).map_err(|e| Error::Other(e.into()))?; - - let parentchain_block_import_dispatcher = - get_triggered_dispatcher_from_integritee_solo_or_parachain()?; - - let signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; - - let sidechain_block_importer = Arc::new(EnclaveSidechainBlockImporter::new( - state_handler, - state_key_repository.clone(), - top_pool_author, - parentchain_block_import_dispatcher, + #[allow(clippy::unwrap_used)] + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let stf_enclave_signer = Arc::new(EnclaveStfEnclaveSigner::new( + state_observer, ocall_api.clone(), - direct_rpc_broadcaster, + shielding_key_repository.clone(), + author_api, )); - let sidechain_block_import_queue = GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT.get()?; - let metadata_repository = get_node_metadata_repository_from_integritee_solo_or_parachain()?; - let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; - let validator_accessor = get_validator_accessor_from_integritee_solo_or_parachain()?; - - let sidechain_block_import_confirmation_handler = - Arc::new(EnclaveBlockImportConfirmationHandler::new( - metadata_repository, - extrinsics_factory, - validator_accessor, - )); - - let sidechain_block_syncer = Arc::new(EnclaveSidechainBlockSyncer::new( - sidechain_block_importer, + let stf_task_context = BitAcrossTaskContext::new( + shielding_key_repository, + ethereum_key_repository, + bitcoin_key_repository, + stf_enclave_signer, + state_handler, ocall_api, - sidechain_block_import_confirmation_handler, - )); - GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT.initialize(sidechain_block_syncer.clone()); - - let sidechain_block_import_queue_worker = - Arc::new(EnclaveSidechainBlockImportQueueWorker::new( - sidechain_block_import_queue, - sidechain_block_syncer, - )); - GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT.initialize(sidechain_block_import_queue_worker); - - let block_composer = Arc::new(BlockComposer::new(signer, state_key_repository)); - GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT.initialize(block_composer); - if let Some(fail_mode) = fail_mode { - let fail_mode = FailSlotMode::from_str(&fail_mode) - .map_err(|_| Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED))?; - let fail_on_demand = Arc::new(Some(FailSlotOnDemand::new(fail_at, fail_mode))); - GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT.initialize(fail_on_demand); - } else { - GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT.initialize(Arc::new(None)); - } + relayer_registry_lookup, + ); + run_bit_across_handler_runner(Arc::new(stf_task_context)); + Ok(()) +} +pub(crate) fn init_enclave_sidechain_components() -> EnclaveResult<()> { + // GLOBAL_SCHEDULED_ENCLAVE must be initialized after attestation_handler and enclave + let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; + let mrenclave = attestation_handler.get_mrenclave()?; + GLOBAL_SCHEDULED_ENCLAVE.init(mrenclave).map_err(|e| Error::Other(e.into()))?; Ok(()) } diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/common.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/common.rs index 7db3228214..dac07b9c9c 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/parentchain/common.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/common.rs @@ -21,21 +21,13 @@ use crate::{ global_components::{ EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOffchainWorkerExecutor, EnclaveParentchainSigner, EnclaveStfExecutor, EnclaveValidatorAccessor, - IntegriteeParentchainBlockImportDispatcher, IntegriteeParentchainBlockImportQueue, - IntegriteeParentchainBlockImporter, IntegriteeParentchainEventImportQueue, + IntegriteeParentchainBlockImportDispatcher, IntegriteeParentchainBlockImporter, IntegriteeParentchainImmediateBlockImportDispatcher, - IntegriteeParentchainIndirectCallsExecutor, - IntegriteeParentchainTriggeredBlockImportDispatcher, - TargetAParentchainBlockImportDispatcher, TargetAParentchainBlockImportQueue, - TargetAParentchainBlockImporter, TargetAParentchainEventImportQueue, - TargetAParentchainImmediateBlockImportDispatcher, - TargetAParentchainIndirectCallsExecutor, - TargetAParentchainTriggeredBlockImportDispatcher, - TargetBParentchainBlockImportDispatcher, TargetBParentchainBlockImportQueue, - TargetBParentchainBlockImporter, TargetBParentchainEventImportQueue, - TargetBParentchainImmediateBlockImportDispatcher, - TargetBParentchainIndirectCallsExecutor, - TargetBParentchainTriggeredBlockImportDispatcher, GLOBAL_OCALL_API_COMPONENT, + IntegriteeParentchainIndirectCallsExecutor, TargetAParentchainBlockImportDispatcher, + TargetAParentchainBlockImporter, TargetAParentchainImmediateBlockImportDispatcher, + TargetAParentchainIndirectCallsExecutor, TargetBParentchainBlockImportDispatcher, + TargetBParentchainBlockImporter, TargetBParentchainImmediateBlockImportDispatcher, + TargetBParentchainIndirectCallsExecutor, GLOBAL_OCALL_API_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_STATE_OBSERVER_COMPONENT, GLOBAL_TOP_POOL_AUTHOR_COMPONENT, @@ -250,48 +242,3 @@ pub(crate) fn create_target_b_offchain_immediate_import_dispatcher( immediate_dispatcher, )))) } - -pub(crate) fn create_sidechain_triggered_import_dispatcher( - block_importer: IntegriteeParentchainBlockImporter, -) -> Arc { - let parentchain_block_import_queue = IntegriteeParentchainBlockImportQueue::default(); - let parentchain_event_import_queue = IntegriteeParentchainEventImportQueue::default(); - let triggered_dispatcher = IntegriteeParentchainTriggeredBlockImportDispatcher::new( - block_importer, - parentchain_block_import_queue, - parentchain_event_import_queue, - ); - Arc::new(IntegriteeParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( - triggered_dispatcher, - ))) -} - -pub(crate) fn create_sidechain_triggered_import_dispatcher_for_target_a( - block_importer: TargetAParentchainBlockImporter, -) -> Arc { - let parentchain_block_import_queue = TargetAParentchainBlockImportQueue::default(); - let parentchain_event_import_queue = TargetAParentchainEventImportQueue::default(); - let triggered_dispatcher = TargetAParentchainTriggeredBlockImportDispatcher::new( - block_importer, - parentchain_block_import_queue, - parentchain_event_import_queue, - ); - Arc::new(TargetAParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( - triggered_dispatcher, - ))) -} - -pub(crate) fn create_sidechain_triggered_import_dispatcher_for_target_b( - block_importer: TargetBParentchainBlockImporter, -) -> Arc { - let parentchain_block_import_queue = TargetBParentchainBlockImportQueue::default(); - let parentchain_event_import_queue = TargetBParentchainEventImportQueue::default(); - let triggered_dispatcher = TargetBParentchainTriggeredBlockImportDispatcher::new( - block_importer, - parentchain_block_import_queue, - parentchain_event_import_queue, - ); - Arc::new(TargetBParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( - triggered_dispatcher, - ))) -} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs index f297c4960e..a15b8a6025 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs @@ -29,13 +29,11 @@ use crate::{ parentchain::common::{ create_extrinsics_factory, create_integritee_offchain_immediate_import_dispatcher, create_integritee_parentchain_block_importer, - create_sidechain_triggered_import_dispatcher, }, }, }; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; use itp_component_container::ComponentGetter; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; use itp_types::parentchain::ParentchainId; use std::{path::PathBuf, sync::Arc}; @@ -52,10 +50,7 @@ pub struct IntegriteeParachainHandler { } impl IntegriteeParachainHandler { - pub fn init( - _base_path: PathBuf, - params: ParachainParams, - ) -> Result { + pub fn init(_base_path: PathBuf, params: ParachainParams) -> Result { let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); @@ -92,17 +87,12 @@ impl IntegriteeParachainHandler { node_metadata_repository.clone(), )?; - let import_dispatcher = match WorkerModeProvider::worker_mode() { - WorkerMode::OffChainWorker => create_integritee_offchain_immediate_import_dispatcher( - stf_executor.clone(), - block_importer, - validator_accessor.clone(), - extrinsics_factory.clone(), - )?, - WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher(block_importer), - WorkerMode::Teeracle => - Arc::new(IntegriteeParentchainBlockImportDispatcher::new_empty_dispatcher()), - }; + let import_dispatcher = create_integritee_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?; let parachain_handler = Self { genesis_header, diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs index b5ae349479..ee08abf4c9 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs @@ -29,13 +29,11 @@ use crate::{ parentchain::common::{ create_extrinsics_factory, create_integritee_offchain_immediate_import_dispatcher, create_integritee_parentchain_block_importer, - create_sidechain_triggered_import_dispatcher, }, }, }; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; use itp_component_container::ComponentGetter; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; use itp_types::parentchain::ParentchainId; use std::{path::PathBuf, sync::Arc}; @@ -51,10 +49,7 @@ pub struct IntegriteeSolochainHandler { } impl IntegriteeSolochainHandler { - pub fn init( - _base_path: PathBuf, - params: SolochainParams, - ) -> Result { + pub fn init(_base_path: PathBuf, params: SolochainParams) -> Result { let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; let light_client_seal = GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; @@ -91,17 +86,12 @@ impl IntegriteeSolochainHandler { node_metadata_repository.clone(), )?; - let import_dispatcher = match WorkerModeProvider::worker_mode() { - WorkerMode::OffChainWorker => create_integritee_offchain_immediate_import_dispatcher( - stf_executor.clone(), - block_importer, - validator_accessor.clone(), - extrinsics_factory.clone(), - )?, - WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher(block_importer), - WorkerMode::Teeracle => - Arc::new(IntegriteeParentchainBlockImportDispatcher::new_empty_dispatcher()), - }; + let import_dispatcher = create_integritee_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?; let solochain_handler = Self { genesis_header, diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/mod.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/mod.rs index b0045d6ca5..8e15dfcd80 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/parentchain/mod.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/mod.rs @@ -42,7 +42,6 @@ use itc_parentchain::{ primitives::{ParentchainId, ParentchainInitParams}, }; use itp_component_container::ComponentInitializer; -use itp_settings::worker_mode::ProvideWorkerMode; use std::{path::PathBuf, vec::Vec}; mod common; @@ -53,15 +52,14 @@ pub mod target_a_solochain; pub mod target_b_parachain; pub mod target_b_solochain; -pub(crate) fn init_parentchain_components( +pub(crate) fn init_parentchain_components( base_path: PathBuf, encoded_params: Vec, ) -> Result> { match ParentchainInitParams::decode(&mut encoded_params.as_slice())? { ParentchainInitParams::Parachain { id, params } => match id { ParentchainId::Litentry => { - let handler = - IntegriteeParachainHandler::init::(base_path, params)?; + let handler = IntegriteeParachainHandler::init(base_path, params)?; let header = handler .validator_accessor .execute_on_validator(|v| v.latest_finalized_header())?; @@ -69,8 +67,7 @@ pub(crate) fn init_parentchain_components Ok(header.encode()) }, ParentchainId::TargetA => { - let handler = - TargetAParachainHandler::init::(base_path, params)?; + let handler = TargetAParachainHandler::init(base_path, params)?; let header = handler .validator_accessor .execute_on_validator(|v| v.latest_finalized_header())?; @@ -78,8 +75,7 @@ pub(crate) fn init_parentchain_components Ok(header.encode()) }, ParentchainId::TargetB => { - let handler = - TargetBParachainHandler::init::(base_path, params)?; + let handler = TargetBParachainHandler::init(base_path, params)?; let header = handler .validator_accessor .execute_on_validator(|v| v.latest_finalized_header())?; @@ -89,8 +85,7 @@ pub(crate) fn init_parentchain_components }, ParentchainInitParams::Solochain { id, params } => match id { ParentchainId::Litentry => { - let handler = - IntegriteeSolochainHandler::init::(base_path, params)?; + let handler = IntegriteeSolochainHandler::init(base_path, params)?; let header = handler .validator_accessor .execute_on_validator(|v| v.latest_finalized_header())?; @@ -98,8 +93,7 @@ pub(crate) fn init_parentchain_components Ok(header.encode()) }, ParentchainId::TargetA => { - let handler = - TargetASolochainHandler::init::(base_path, params)?; + let handler = TargetASolochainHandler::init(base_path, params)?; let header = handler .validator_accessor .execute_on_validator(|v| v.latest_finalized_header())?; @@ -107,8 +101,7 @@ pub(crate) fn init_parentchain_components Ok(header.encode()) }, ParentchainId::TargetB => { - let handler = - TargetBSolochainHandler::init::(base_path, params)?; + let handler = TargetBSolochainHandler::init(base_path, params)?; let header = handler .validator_accessor .execute_on_validator(|v| v.latest_finalized_header())?; diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs index bf24f6fdd4..209ab9f70d 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs @@ -31,8 +31,7 @@ use crate::{ GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, }, parentchain::common::{ - create_extrinsics_factory, create_sidechain_triggered_import_dispatcher_for_target_a, - create_target_a_offchain_immediate_import_dispatcher, + create_extrinsics_factory, create_target_a_offchain_immediate_import_dispatcher, create_target_a_parentchain_block_importer, }, }, @@ -40,7 +39,6 @@ use crate::{ use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; pub use itc_parentchain::primitives::{ParachainBlock, ParachainHeader, ParachainParams}; use itp_component_container::ComponentGetter; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; use itp_types::parentchain::ParentchainId; use std::{path::PathBuf, sync::Arc}; @@ -55,10 +53,7 @@ pub struct TargetAParachainHandler { } impl TargetAParachainHandler { - pub fn init( - _base_path: PathBuf, - params: ParachainParams, - ) -> Result { + pub fn init(_base_path: PathBuf, params: ParachainParams) -> Result { let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); @@ -95,18 +90,12 @@ impl TargetAParachainHandler { node_metadata_repository.clone(), )?; - let import_dispatcher = match WorkerModeProvider::worker_mode() { - WorkerMode::OffChainWorker => create_target_a_offchain_immediate_import_dispatcher( - stf_executor.clone(), - block_importer, - validator_accessor.clone(), - extrinsics_factory.clone(), - )?, - WorkerMode::Sidechain => - create_sidechain_triggered_import_dispatcher_for_target_a(block_importer), - WorkerMode::Teeracle => - Arc::new(TargetAParentchainBlockImportDispatcher::new_empty_dispatcher()), - }; + let import_dispatcher = create_target_a_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?; let parachain_handler = Self { genesis_header, diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs index f5cf2ae8ff..5ce352bece 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs @@ -25,8 +25,7 @@ use crate::{ GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, }, parentchain::common::{ - create_extrinsics_factory, create_sidechain_triggered_import_dispatcher_for_target_a, - create_target_a_offchain_immediate_import_dispatcher, + create_extrinsics_factory, create_target_a_offchain_immediate_import_dispatcher, create_target_a_parentchain_block_importer, }, }, @@ -34,7 +33,6 @@ use crate::{ use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; pub use itc_parentchain::primitives::{SolochainBlock, SolochainHeader, SolochainParams}; use itp_component_container::ComponentGetter; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; use itp_types::parentchain::ParentchainId; use std::{path::PathBuf, sync::Arc}; @@ -48,10 +46,7 @@ pub struct TargetASolochainHandler { } impl TargetASolochainHandler { - pub fn init( - _base_path: PathBuf, - params: SolochainParams, - ) -> Result { + pub fn init(_base_path: PathBuf, params: SolochainParams) -> Result { let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; let light_client_seal = GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; @@ -88,18 +83,12 @@ impl TargetASolochainHandler { node_metadata_repository.clone(), )?; - let import_dispatcher = match WorkerModeProvider::worker_mode() { - WorkerMode::OffChainWorker => create_target_a_offchain_immediate_import_dispatcher( - stf_executor.clone(), - block_importer, - validator_accessor.clone(), - extrinsics_factory.clone(), - )?, - WorkerMode::Sidechain => - create_sidechain_triggered_import_dispatcher_for_target_a(block_importer), - WorkerMode::Teeracle => - Arc::new(TargetAParentchainBlockImportDispatcher::new_empty_dispatcher()), - }; + let import_dispatcher = create_target_a_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?; let solochain_handler = Self { genesis_header, diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs index be44224c65..4bb1f2638e 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs @@ -31,8 +31,7 @@ use crate::{ GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, }, parentchain::common::{ - create_extrinsics_factory, create_sidechain_triggered_import_dispatcher_for_target_b, - create_target_b_offchain_immediate_import_dispatcher, + create_extrinsics_factory, create_target_b_offchain_immediate_import_dispatcher, create_target_b_parentchain_block_importer, }, }, @@ -40,7 +39,6 @@ use crate::{ use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; pub use itc_parentchain::primitives::{ParachainBlock, ParachainHeader, ParachainParams}; use itp_component_container::ComponentGetter; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; use itp_types::parentchain::ParentchainId; use std::{path::PathBuf, sync::Arc}; @@ -55,10 +53,7 @@ pub struct TargetBParachainHandler { } impl TargetBParachainHandler { - pub fn init( - _base_path: PathBuf, - params: ParachainParams, - ) -> Result { + pub fn init(_base_path: PathBuf, params: ParachainParams) -> Result { let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); @@ -95,18 +90,12 @@ impl TargetBParachainHandler { node_metadata_repository.clone(), )?; - let import_dispatcher = match WorkerModeProvider::worker_mode() { - WorkerMode::OffChainWorker => create_target_b_offchain_immediate_import_dispatcher( - stf_executor.clone(), - block_importer, - validator_accessor.clone(), - extrinsics_factory.clone(), - )?, - WorkerMode::Sidechain => - create_sidechain_triggered_import_dispatcher_for_target_b(block_importer), - WorkerMode::Teeracle => - Arc::new(TargetBParentchainBlockImportDispatcher::new_empty_dispatcher()), - }; + let import_dispatcher = create_target_b_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?; let parachain_handler = Self { genesis_header, diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs index 842baa8129..40b51d76de 100644 --- a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs @@ -25,8 +25,7 @@ use crate::{ GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, }, parentchain::common::{ - create_extrinsics_factory, create_sidechain_triggered_import_dispatcher_for_target_b, - create_target_b_offchain_immediate_import_dispatcher, + create_extrinsics_factory, create_target_b_offchain_immediate_import_dispatcher, create_target_b_parentchain_block_importer, }, }, @@ -34,7 +33,6 @@ use crate::{ use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; pub use itc_parentchain::primitives::{SolochainBlock, SolochainHeader, SolochainParams}; use itp_component_container::ComponentGetter; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; use itp_types::parentchain::ParentchainId; use std::{path::PathBuf, sync::Arc}; @@ -48,10 +46,7 @@ pub struct TargetBSolochainHandler { } impl TargetBSolochainHandler { - pub fn init( - _base_path: PathBuf, - params: SolochainParams, - ) -> Result { + pub fn init(_base_path: PathBuf, params: SolochainParams) -> Result { let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; let light_client_seal = GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; @@ -88,18 +83,12 @@ impl TargetBSolochainHandler { node_metadata_repository.clone(), )?; - let import_dispatcher = match WorkerModeProvider::worker_mode() { - WorkerMode::OffChainWorker => create_target_b_offchain_immediate_import_dispatcher( - stf_executor.clone(), - block_importer, - validator_accessor.clone(), - extrinsics_factory.clone(), - )?, - WorkerMode::Sidechain => - create_sidechain_triggered_import_dispatcher_for_target_b(block_importer), - WorkerMode::Teeracle => - Arc::new(TargetBParentchainBlockImportDispatcher::new_empty_dispatcher()), - }; + let import_dispatcher = create_target_b_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?; let solochain_handler = Self { genesis_header, diff --git a/bitacross-worker/enclave-runtime/src/lib.rs b/bitacross-worker/enclave-runtime/src/lib.rs index 9c3b078558..0ef69b9a96 100644 --- a/bitacross-worker/enclave-runtime/src/lib.rs +++ b/bitacross-worker/enclave-runtime/src/lib.rs @@ -24,9 +24,9 @@ #![cfg_attr(not(target_env = "sgx"), no_std)] #![cfg_attr(target_env = "sgx", feature(rustc_private))] #![allow(clippy::missing_safety_doc)] +#![allow(clippy::unreachable)] #![warn( clippy::unwrap_used, - clippy::unreachable, /* comment out for the moment. There are some upstream code `unimplemented` */ // clippy::unimplemented, // clippy::panic_in_result_fn, @@ -46,36 +46,36 @@ use crate::{ initialization::global_components::{ GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE, GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, - GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, - GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, - GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, - GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, - GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, + GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, + GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, }, - rpc::worker_api_direct::sidechain_io_handler, utils::{ get_node_metadata_repository_from_integritee_solo_or_parachain, get_node_metadata_repository_from_target_a_solo_or_parachain, get_node_metadata_repository_from_target_b_solo_or_parachain, - get_validator_accessor_from_integritee_solo_or_parachain, utf8_str_from_raw, DecodeRaw, + get_validator_accessor_from_integritee_solo_or_parachain, DecodeRaw, }, }; use codec::Decode; use core::ffi::c_int; +use initialization::global_components::{ + GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT, GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT, +}; use itc_parentchain::{ block_import_dispatcher::DispatchBlockImport, light_client::{concurrent_access::ValidatorAccess, Validator}, primitives::ParentchainId, }; use itp_component_container::ComponentGetter; -use itp_import_queue::PushToQueue; use itp_node_api::metadata::NodeMetadata; use itp_nonce_cache::{MutateNonce, Nonce}; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; -use itp_sgx_crypto::key_repository::AccessPubkey; +use itp_sgx_crypto::key_repository::{AccessKey, AccessPubkey}; use itp_storage::{StorageProof, StorageProofChecker}; use itp_types::{ShardIdentifier, SignedBlock}; -use itp_utils::{if_production_or, write_slice_and_whitespace_pad}; +use itp_utils::write_slice_and_whitespace_pad; +use litentry_macros::if_production_or; use log::*; use once_cell::sync::OnceCell; use sgx_types::sgx_status_t; @@ -98,14 +98,9 @@ mod utils; pub mod error; pub mod rpc; mod sync; -mod tls_ra; -pub mod top_pool_execution; - -#[cfg(feature = "teeracle")] -pub mod teeracle; - #[cfg(feature = "test")] pub mod test; +mod tls_ra; pub type Hash = sp_core::H256; pub type AuthorityPair = sp_core::ed25519::Pair; @@ -133,7 +128,7 @@ pub unsafe extern "C" fn init( // Initialize the logging environment in the enclave. if_production_or!( { - let module_names = litentry_macros::local_modules!(); + let module_names = litentry_proc_macros::local_modules!(); println!( "Initializing logger to filter only following local modules: {:?}", module_names @@ -247,6 +242,64 @@ pub unsafe extern "C" fn get_ecc_signing_pubkey(pubkey: *mut u8, pubkey_size: u3 sgx_status_t::SGX_SUCCESS } +#[no_mangle] +pub unsafe extern "C" fn get_bitcoin_wallet_pair(pair: *mut u8, pair_size: u32) -> sgx_status_t { + if_production_or!( + { + error!("Bitcoin wallet can only be retrieved in non-prod"); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + { + let bitcoin_key_repository = match GLOBAL_BITCOIN_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let keypair = match bitcoin_key_repository.retrieve_key() { + Ok(p) => p, + Err(e) => return e.into(), + }; + + let privkey_slice = slice::from_raw_parts_mut(pair, pair_size as usize); + privkey_slice.clone_from_slice(&keypair.private_bytes()); + + sgx_status_t::SGX_SUCCESS + } + ) +} + +#[no_mangle] +pub unsafe extern "C" fn get_ethereum_wallet_pair(pair: *mut u8, pair_size: u32) -> sgx_status_t { + if_production_or!( + { + error!("Ethereum wallet can only be retrieved in non-prod"); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + { + let ethereum_key_repository = match GLOBAL_ETHEREUM_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let keypair = match ethereum_key_repository.retrieve_key() { + Ok(p) => p, + Err(e) => return e.into(), + }; + + let privkey_slice = slice::from_raw_parts_mut(pair, pair_size as usize); + privkey_slice.clone_from_slice(&keypair.private_bytes()); + + sgx_status_t::SGX_SUCCESS + } + ) +} + #[no_mangle] pub unsafe extern "C" fn set_nonce( nonce: *const u32, @@ -324,79 +377,24 @@ pub unsafe extern "C" fn set_node_metadata( sgx_status_t::SGX_SUCCESS } -/// This is reduced to the sidechain block import RPC interface (i.e. worker-worker communication). -/// The entire rest of the RPC server is run inside the enclave and does not use this e-call function anymore. #[no_mangle] -pub unsafe extern "C" fn call_rpc_methods( - request: *const u8, - request_len: u32, - response: *mut u8, - response_len: u32, -) -> sgx_status_t { - let request = match utf8_str_from_raw(request, request_len as usize) { - Ok(req) => req, - Err(e) => { - error!("[SidechainRpc] FFI: Invalid utf8 request: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let res = match sidechain_rpc_int(request) { - Ok(res) => res, - Err(e) => { - error!("RPC request failed: {:?}", e); - return e.into() - }, - }; - - let response_slice = slice::from_raw_parts_mut(response, response_len as usize); - if let Err(e) = write_slice_and_whitespace_pad(response_slice, res.into_bytes()) { - return Error::BufferError(e).into() - }; +pub unsafe extern "C" fn publish_wallets() -> sgx_status_t { + if let Err(e) = initialization::publish_wallets() { + error!("Failed to publish generated wallets: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } sgx_status_t::SGX_SUCCESS } -fn sidechain_rpc_int(request: &str) -> Result { - let sidechain_block_import_queue = GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT.get()?; - - let io = sidechain_io_handler(move |signed_block| { - sidechain_block_import_queue.push_single(signed_block) - }); - - // note: errors are still returned as Option - Ok(io - .handle_request_sync(request) - .unwrap_or_else(|| format!("Empty rpc response for request: {}", request))) -} - /// Initialize sidechain enclave components. /// /// Call this once at startup. Has to be called AFTER the light-client /// (parentchain components) have been initialized (because we need the parentchain /// block import dispatcher). #[no_mangle] -pub unsafe extern "C" fn init_enclave_sidechain_components( - fail_mode: *const u8, - fail_mode_size: u32, - fail_at: *const u8, - fail_at_size: u32, -) -> sgx_status_t { - let fail_mode = match Option::::decode_raw(fail_mode, fail_mode_size as usize) { - Ok(s) => s, - Err(e) => { - error!("failed to decode fail mode {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - let fail_at = match u64::decode_raw(fail_at, fail_at_size as usize) { - Ok(v) => v, - Err(e) => { - error!("failed to decode fail at {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - if let Err(e) = initialization::init_enclave_sidechain_components(fail_mode, fail_at) { +pub unsafe extern "C" fn init_enclave_sidechain_components() -> sgx_status_t { + if let Err(e) = initialization::init_enclave_sidechain_components() { error!("Failed to initialize sidechain components: {:?}", e); return sgx_status_t::SGX_ERROR_UNEXPECTED } @@ -454,8 +452,7 @@ pub unsafe extern "C" fn init_parentchain_components( fn init_parentchain_params_internal(params: Vec, latest_header: &mut [u8]) -> Result<()> { use initialization::parentchain::init_parentchain_components; - let encoded_latest_header = - init_parentchain_components::(get_base_path()?, params)?; + let encoded_latest_header = init_parentchain_components(get_base_path()?, params)?; write_slice_and_whitespace_pad(latest_header, encoded_latest_header)?; @@ -550,7 +547,7 @@ unsafe fn sync_parentchain_internal( let events_to_sync = Vec::>::decode_raw(events_to_sync, events_to_sync_size)?; - dispatch_parentchain_blocks_for_import::( + dispatch_parentchain_blocks_for_import( blocks_to_sync, events_to_sync, &parentchain_id, @@ -583,16 +580,12 @@ pub unsafe extern "C" fn ignore_parentchain_block_import_validation_until( /// * The sidechain uses a triggered dispatcher, where the import of a parentchain block is /// synchronized and triggered by the sidechain block production cycle. /// -fn dispatch_parentchain_blocks_for_import( +fn dispatch_parentchain_blocks_for_import( blocks_to_sync: Vec, events_to_sync: Vec>, id: &ParentchainId, is_syncing: bool, ) -> Result<()> { - if WorkerModeProvider::worker_mode() == WorkerMode::Teeracle { - trace!("Not importing any parentchain blocks"); - return Ok(()) - } trace!( "[{:?}] Dispatching Import of {} blocks and {} events", id, diff --git a/bitacross-worker/enclave-runtime/src/ocall/ffi.rs b/bitacross-worker/enclave-runtime/src/ocall/ffi.rs index 388cc0c54a..1b3b1adec2 100644 --- a/bitacross-worker/enclave-runtime/src/ocall/ffi.rs +++ b/bitacross-worker/enclave-runtime/src/ocall/ffi.rs @@ -83,36 +83,6 @@ extern "C" { metric_size: u32, ) -> sgx_status_t; - pub fn ocall_propose_sidechain_blocks( - ret_val: *mut sgx_status_t, - signed_blocks: *const u8, - signed_blocks_size: u32, - ) -> sgx_status_t; - - pub fn ocall_store_sidechain_blocks( - ret_val: *mut sgx_status_t, - signed_blocks: *const u8, - signed_blocks_size: u32, - ) -> sgx_status_t; - - pub fn ocall_fetch_sidechain_blocks_from_peer( - ret_val: *mut sgx_status_t, - last_imported_block_hash: *const u8, - last_imported_block_hash_size: u32, - maybe_until_block_hash: *const u8, - maybe_until_block_hash_encoded_size: u32, - shard_identifier: *const u8, - shard_identifier_size: u32, - sidechain_blocks: *mut u8, - sidechain_blocks_size: u32, - ) -> sgx_status_t; - - pub fn ocall_get_trusted_peers_urls( - ret_val: *mut sgx_status_t, - peers: *mut u8, - peers_size: u32, - ) -> sgx_status_t; - pub fn ocall_send_to_parentchain( ret_val: *mut sgx_status_t, extrinsics: *const u8, diff --git a/bitacross-worker/enclave-runtime/src/ocall/mod.rs b/bitacross-worker/enclave-runtime/src/ocall/mod.rs index 7374b63fde..f85d82d8b3 100644 --- a/bitacross-worker/enclave-runtime/src/ocall/mod.rs +++ b/bitacross-worker/enclave-runtime/src/ocall/mod.rs @@ -20,7 +20,6 @@ mod ffi; mod ipfs_ocall; mod metrics_ocall; mod on_chain_ocall; -mod sidechain_ocall; #[derive(Clone, Debug, Default)] pub struct OcallApi; diff --git a/bitacross-worker/enclave-runtime/src/ocall/sidechain_ocall.rs b/bitacross-worker/enclave-runtime/src/ocall/sidechain_ocall.rs deleted file mode 100644 index b961e93752..0000000000 --- a/bitacross-worker/enclave-runtime/src/ocall/sidechain_ocall.rs +++ /dev/null @@ -1,139 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::ocall::{ffi, OcallApi}; -use codec::{Decode, Encode}; -use frame_support::ensure; -use itp_ocall_api::EnclaveSidechainOCallApi; -use itp_types::{BlockHash, ShardIdentifier}; -use log::*; -use sgx_types::{sgx_status_t, SgxResult}; -use std::{string::String, vec::Vec}; - -impl EnclaveSidechainOCallApi for OcallApi { - fn propose_sidechain_blocks( - &self, - signed_blocks: Vec, - ) -> SgxResult<()> { - let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; - let signed_blocks_encoded = signed_blocks.encode(); - - let res = unsafe { - ffi::ocall_propose_sidechain_blocks( - &mut rt as *mut sgx_status_t, - signed_blocks_encoded.as_ptr(), - signed_blocks_encoded.len() as u32, - ) - }; - - ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); - ensure!(res == sgx_status_t::SGX_SUCCESS, res); - - Ok(()) - } - - fn store_sidechain_blocks( - &self, - signed_blocks: Vec, - ) -> SgxResult<()> { - let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; - let signed_blocks_encoded = signed_blocks.encode(); - - let res = unsafe { - ffi::ocall_store_sidechain_blocks( - &mut rt as *mut sgx_status_t, - signed_blocks_encoded.as_ptr(), - signed_blocks_encoded.len() as u32, - ) - }; - - ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); - ensure!(res == sgx_status_t::SGX_SUCCESS, res); - - Ok(()) - } - - fn fetch_sidechain_blocks_from_peer( - &self, - last_imported_block_hash: BlockHash, - maybe_until_block_hash: Option, - shard_identifier: ShardIdentifier, - ) -> SgxResult> { - const BLOCK_BUFFER_SIZE: usize = 262144; // Buffer size for sidechain blocks in bytes (256KB). - - let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; - let last_imported_block_hash_encoded = last_imported_block_hash.encode(); - let maybe_until_block_hash_encoded = maybe_until_block_hash.encode(); - let shard_identifier_encoded = shard_identifier.encode(); - - // We have to pre-allocate the vector and hope it's large enough (see GitHub issue #621). - let mut signed_blocks_encoded: Vec = vec![0; BLOCK_BUFFER_SIZE]; - - let res = unsafe { - ffi::ocall_fetch_sidechain_blocks_from_peer( - &mut rt as *mut sgx_status_t, - last_imported_block_hash_encoded.as_ptr(), - last_imported_block_hash_encoded.len() as u32, - maybe_until_block_hash_encoded.as_ptr(), - maybe_until_block_hash_encoded.len() as u32, - shard_identifier_encoded.as_ptr(), - shard_identifier_encoded.len() as u32, - signed_blocks_encoded.as_mut_ptr(), - signed_blocks_encoded.len() as u32, - ) - }; - - ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); - ensure!(res == sgx_status_t::SGX_SUCCESS, res); - - let decoded_signed_blocks: Vec = - Decode::decode(&mut signed_blocks_encoded.as_slice()).map_err(|e| { - error!("Failed to decode WorkerResponse: {}", e); - sgx_status_t::SGX_ERROR_UNEXPECTED - })?; - - Ok(decoded_signed_blocks) - } - - fn get_trusted_peers_urls(&self) -> SgxResult> { - let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; - const BLOCK_BUFFER_SIZE: usize = 262144; // Buffer size for sidechain blocks in bytes (256KB). - - // We have to pre-allocate the vector and hope it's large enough (see GitHub issue #621). - let mut peers_encoded: Vec = vec![0; BLOCK_BUFFER_SIZE]; - - let res = unsafe { - ffi::ocall_get_trusted_peers_urls( - &mut rt as *mut sgx_status_t, - peers_encoded.as_mut_ptr(), - peers_encoded.len() as u32, - ) - }; - - ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); - ensure!(res == sgx_status_t::SGX_SUCCESS, res); - - let decoded_peers: Vec = - Decode::decode(&mut peers_encoded.as_slice()).map_err(|e| { - error!("Failed to decode peers list: {}", e); - sgx_status_t::SGX_ERROR_UNEXPECTED - })?; - - Ok(decoded_peers) - } -} diff --git a/bitacross-worker/enclave-runtime/src/rpc/worker_api_direct.rs b/bitacross-worker/enclave-runtime/src/rpc/worker_api_direct.rs index 4133bccca6..61b5ed443c 100644 --- a/bitacross-worker/enclave-runtime/src/rpc/worker_api_direct.rs +++ b/bitacross-worker/enclave-runtime/src/rpc/worker_api_direct.rs @@ -20,16 +20,20 @@ use crate::{ generate_dcap_ra_extrinsic_from_quote_internal, generate_ias_ra_extrinsic_from_der_cert_internal, }, + std::string::ToString, utils::{ get_stf_enclave_signer_from_solo_or_parachain, get_validator_accessor_from_integritee_solo_or_parachain, }, }; +use bc_task_sender::{BitAcrossRequest, BitAcrossRequestSender}; use codec::Encode; use core::result::Result; -use ita_sgx_runtime::{Runtime, System}; +use futures_sgx::channel::oneshot; +use ita_sgx_runtime::Runtime; use ita_stf::{Getter, TrustedCallSigned}; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, ExtrinsicSender}; +use itp_ocall_api::EnclaveAttestationOCallApi; use itp_primitives_cache::{GetPrimitives, GLOBAL_PRIMITIVES_CACHE}; use itp_rpc::RpcReturnValue; use itp_sgx_crypto::{ @@ -37,22 +41,14 @@ use itp_sgx_crypto::{ key_repository::{AccessKey, AccessPubkey}, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt, }; -use itp_sgx_externalities::SgxExternalitiesTrait; use itp_stf_executor::{getter_executor::ExecuteGetter, traits::StfShardVaultQuery}; -use itp_stf_primitives::types::AccountId; -use itp_stf_state_handler::handle_state::HandleState; use itp_top_pool_author::traits::AuthorApi; -use itp_types::{ - DirectRequestStatus, Index, MrEnclave, RsaRequest, ShardIdentifier, SidechainBlockNumber, H256, -}; -use itp_utils::{if_not_production, FromHexPrefixed, ToHexPrefixed}; -use its_primitives::types::block::SignedBlock; -use its_sidechain::rpc_handler::{ - direct_top_pool_api, direct_top_pool_api::decode_shard_from_base58, import_block_api, -}; +use itp_types::{DirectRequestStatus, RsaRequest, ShardIdentifier, H256}; +use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use jsonrpc_core::{serde_json::json, IoHandler, Params, Value}; use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; -use litentry_primitives::DecryptableRequest; +use litentry_macros::if_not_production; +use litentry_primitives::{AesRequest, DecryptableRequest}; use log::debug; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::Pair; @@ -73,11 +69,11 @@ fn get_all_rpc_methods_string(io_handler: &IoHandler) -> String { format!("methods: [{}]", method_string) } -pub fn public_api_rpc_handler( +pub fn public_api_rpc_handler( top_pool_author: Arc, getter_executor: Arc, shielding_key: Arc, - state: Option>, + ocall_api: Arc, ) -> IoHandler where Author: AuthorApi + Send + Sync + 'static, @@ -85,13 +81,9 @@ where AccessShieldingKey: AccessPubkey + AccessKey + Send + Sync + 'static, ::KeyType: ShieldingCryptoDecrypt + ShieldingCryptoEncrypt + DeriveEd25519 + Send + Sync + 'static, - State: HandleState + Send + Sync + 'static, - State::StateT: SgxExternalitiesTrait, + OcallApi: EnclaveAttestationOCallApi + Send + Sync + 'static, { - let mut io = direct_top_pool_api::add_top_pool_direct_rpc_methods( - top_pool_author.clone(), - IoHandler::new(), - ); + let mut io = IoHandler::new(); let shielding_key_cloned = shielding_key.clone(); io.add_sync_method("author_getShieldingKey", move |_: Params| { @@ -141,64 +133,15 @@ where Ok(json!(json_value.to_hex())) }); - let local_top_pool_author = top_pool_author.clone(); - let local_state = state.clone(); - io.add_sync_method("author_getNextNonce", move |params: Params| { - let local_state = match local_state.clone() { - Some(s) => s, - None => - return Ok(json!(compute_hex_encoded_return_error( - "author_getNextNonce is not avaiable" - ))), - }; - - match params.parse::<(String, String)>() { - Ok((shard_base58, account_hex)) => { - let shard = match decode_shard_from_base58(shard_base58.as_str()) { - Ok(id) => id, - Err(msg) => { - let error_msg: String = - format!("Could not retrieve author_getNextNonce calls due to: {}", msg); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; - let account = match AccountId::from_hex(account_hex.as_str()) { - Ok(acc) => acc, - Err(msg) => { - let error_msg: String = format!( - "Could not retrieve author_getNextNonce calls due to: {:?}", - msg - ); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; - - match local_state.load_cloned(&shard) { - Ok((mut state, _hash)) => { - let trusted_calls = - local_top_pool_author.get_pending_trusted_calls_for(shard, &account); - let pending_tx_count = trusted_calls.len(); - #[allow(clippy::unwrap_used)] - let pending_tx_count = Index::try_from(pending_tx_count).unwrap(); - let nonce = state.execute_with(|| System::account_nonce(&account)); - let json_value = RpcReturnValue { - do_watch: false, - value: (nonce.saturating_add(pending_tx_count)).encode(), - status: DirectRequestStatus::Ok, - }; - Ok(json!(json_value.to_hex())) - }, - Err(e) => { - let error_msg = format!("load shard failure due to: {:?}", e); - Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - } - }, - Err(e) => { - let error_msg: String = - format!("Could not retrieve author_getNextNonce calls due to: {}", e); - Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, + // Submit BitAcross Request + io.add_method("bitacross_submitRequest", move |params: Params| { + debug!("worker_api_direct rpc was called: bitacross_submitRequest"); + async move { + let json_value = match request_bit_across_inner(params).await { + Ok(value) => value.to_hex(), + Err(error) => compute_hex_encoded_return_error(&error), + }; + Ok(json!(json_value)) } }); @@ -321,17 +264,16 @@ where }); // state_getMrenclave - io.add_sync_method("state_getMrenclave", |_: Params| { - let json_value = match GLOBAL_SCHEDULED_ENCLAVE.get_current_mrenclave() { - Ok(mrenclave) => RpcReturnValue { + io.add_sync_method("state_getMrenclave", move |_: Params| { + let json_value = match ocall_api.get_mrenclave_of_self() { + Ok(m) => RpcReturnValue { do_watch: false, - value: mrenclave.encode(), + value: m.m.encode(), status: DirectRequestStatus::Ok, } .to_hex(), - Err(error) => { - let error_msg: String = - format!("Could not get current mrenclave due to: {}", error); + Err(e) => { + let error_msg: String = format!("Could not get current mrenclave due to: {}", e); compute_hex_encoded_return_error(error_msg.as_str()) }, }; @@ -339,8 +281,9 @@ where }); if_not_production!({ - // state_updateScheduledEnclave, params: sidechainBlockNumber, hex encoded mrenclave - io.add_sync_method("state_updateScheduledEnclave", move |params: Params| { + use itp_types::{MrEnclave, SidechainBlockNumber}; + // state_setScheduledEnclave, params: sidechainBlockNumber, hex encoded mrenclave + io.add_sync_method("state_setScheduledEnclave", move |params: Params| { match params.parse::<(SidechainBlockNumber, String)>() { Ok((bn, mrenclave)) => return match hex::decode(&mrenclave) { @@ -375,56 +318,6 @@ where Err(_) => Ok(json!(compute_hex_encoded_return_error("parse error"))), } }); - - // state_getStorage - io.add_sync_method("state_getStorage", move |params: Params| { - let local_state = match state.clone() { - Some(s) => s, - None => - return Ok(json!(compute_hex_encoded_return_error( - "state_getStorage is not avaiable" - ))), - }; - match params.parse::<(String, String)>() { - Ok((shard_str, key_hash)) => { - let key_hash = if key_hash.starts_with("0x") { - #[allow(clippy::unwrap_used)] - key_hash.strip_prefix("0x").unwrap() - } else { - key_hash.as_str() - }; - let key_hash = match hex::decode(key_hash) { - Ok(key_hash) => key_hash, - Err(_) => - return Ok(json!(compute_hex_encoded_return_error("docode key error"))), - }; - - let shard: ShardIdentifier = match decode_shard_from_base58(shard_str.as_str()) - { - Ok(id) => id, - Err(msg) => { - let error_msg = format!("decode shard failure due to: {}", msg); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; - match local_state.load_cloned(&shard) { - Ok((state, _)) => { - // Get storage by key hash - let value = state.get(key_hash.as_slice()).cloned().unwrap_or_default(); - debug!("query storage value:{:?}", &value); - let json_value = - RpcReturnValue::new(value, false, DirectRequestStatus::Ok); - Ok(json!(json_value.to_hex())) - }, - Err(e) => { - let error_msg = format!("load shard failure due to: {:?}", e); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - } - }, - Err(_err) => Ok(json!(compute_hex_encoded_return_error("parse error"))), - } - }); }); // system_health @@ -489,11 +382,14 @@ fn forward_dcap_quote_inner(params: Params) -> Result { let param = &hex_encoded_params.get(0).ok_or("Could not get first param")?; let encoded_quote_to_forward: Vec = - itp_utils::hex::decode_hex(param).map_err(|e| format!("{:?}", e))?; + litentry_hex_utils::decode_hex(param).map_err(|e| format!("{:?}", e))?; let url = String::new(); - let ext = generate_dcap_ra_extrinsic_from_quote_internal(url, &encoded_quote_to_forward) - .map_err(|e| format!("{:?}", e))?; + let ext = generate_dcap_ra_extrinsic_from_quote_internal( + url.as_bytes().to_vec(), + &encoded_quote_to_forward, + ) + .map_err(|e| format!("{:?}", e))?; let validator_access = get_validator_accessor_from_integritee_solo_or_parachain() .map_err(|e| format!("{:?}", e))?; @@ -519,11 +415,15 @@ fn attesteer_forward_ias_attestation_report_inner( let param = &hex_encoded_params.get(0).ok_or("Could not get first param")?; let ias_attestation_report = - itp_utils::hex::decode_hex(param).map_err(|e| format!("{:?}", e))?; + litentry_hex_utils::decode_hex(param).map_err(|e| format!("{:?}", e))?; let url = String::new(); - let ext = generate_ias_ra_extrinsic_from_der_cert_internal(url, &ias_attestation_report) - .map_err(|e| format!("{:?}", e))?; + let ext = generate_ias_ra_extrinsic_from_der_cert_internal( + url.as_bytes().to_vec(), + &ias_attestation_report, + false, + ) + .map_err(|e| format!("{:?}", e))?; let validator_access = get_validator_accessor_from_integritee_solo_or_parachain() .map_err(|e| format!("{:?}", e))?; @@ -534,13 +434,39 @@ fn attesteer_forward_ias_attestation_report_inner( Ok(ext) } -pub fn sidechain_io_handler(import_fn: ImportFn) -> IoHandler -where - ImportFn: Fn(SignedBlock) -> Result<(), Error> + Sync + Send + 'static, - Error: std::fmt::Debug, -{ - let io = IoHandler::new(); - import_block_api::add_import_block_rpc_method(import_fn, io) +async fn request_bit_across_inner(params: Params) -> Result { + let payload = get_request_payload(params)?; + let request = AesRequest::from_hex(&payload) + .map_err(|e| format!("AesRequest construction error: {:?}", e))?; + + let bit_across_request_sender = BitAcrossRequestSender::new(); + let (sender, receiver) = oneshot::channel::, String>>(); + + bit_across_request_sender.send(BitAcrossRequest { sender, request })?; + + // we only expect one response, hence no loop + match receiver.await { + Ok(Ok(response)) => + Ok(RpcReturnValue { do_watch: false, value: response, status: DirectRequestStatus::Ok }), + Ok(Err(e)) => { + log::error!("Received error in jsonresponse: {:?} ", e); + Err(compute_hex_encoded_return_error(&e)) + }, + Err(_) => { + // This case will only happen if the sender has been dropped + Err(compute_hex_encoded_return_error("The sender has been dropped")) + }, + } +} + +// we expect our `params` to be "by-position array" +// see https://www.jsonrpc.org/specification#parameter_structures +fn get_request_payload(params: Params) -> Result { + let s_vec = params.parse::>().map_err(|e| format!("{}", e))?; + + let s = s_vec.get(0).ok_or_else(|| "Empty params".to_string())?; + debug!("Request payload: {}", s); + Ok(s.to_owned()) } #[cfg(feature = "test")] diff --git a/bitacross-worker/enclave-runtime/src/teeracle/mod.rs b/bitacross-worker/enclave-runtime/src/teeracle/mod.rs deleted file mode 100644 index c38dd27c2e..0000000000 --- a/bitacross-worker/enclave-runtime/src/teeracle/mod.rs +++ /dev/null @@ -1,279 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - error::{Error, Result}, - initialization::global_components::GLOBAL_OCALL_API_COMPONENT, - utils::{ - get_extrinsic_factory_from_integritee_solo_or_parachain, - get_node_metadata_repository_from_integritee_solo_or_parachain, - }, -}; -use codec::{Decode, Encode}; -use core::slice; -use ita_oracle::{ - create_coin_gecko_oracle, create_coin_market_cap_oracle, create_open_meteo_weather_oracle, - metrics_exporter::ExportMetrics, - oracles::{ - exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, - weather_oracle::{GetLongitude, WeatherOracle}, - }, - traits::OracleSource, - types::{TradingInfo, TradingPair, WeatherInfo, WeatherQuery}, -}; -use itp_component_container::ComponentGetter; -use itp_extrinsics_factory::CreateExtrinsics; -use itp_node_api::metadata::{pallet_teeracle::TeeracleCallIndexes, provider::AccessNodeMetadata}; -use itp_types::OpaqueCall; -use itp_utils::write_slice_and_whitespace_pad; -use log::*; -use sgx_types::sgx_status_t; -use sp_runtime::OpaqueExtrinsic; -use std::{string::String, vec::Vec}; - -fn update_weather_data_internal(weather_info: WeatherInfo) -> Result> { - let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; - let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; - - let mut extrinsic_calls: Vec = Vec::new(); - - let open_meteo_weather_oracle = create_open_meteo_weather_oracle(ocall_api); - - match get_longitude(weather_info, open_meteo_weather_oracle) { - Ok(opaque_call) => extrinsic_calls.push(opaque_call), - Err(e) => { - error!("[-] Failed to get the newest longitude from OpenMeteo. {:?}", e); - }, - }; - let extrinsics = extrinsics_factory.create_extrinsics(extrinsic_calls.as_slice(), None)?; - Ok(extrinsics) -} - -fn get_longitude( - weather_info: WeatherInfo, - oracle: WeatherOracle, -) -> Result -where - OracleSourceType: OracleSource< - WeatherInfo, - OracleRequestResult = std::result::Result, - >, - MetricsExporter: ExportMetrics, -{ - let longitude = - oracle.get_longitude(weather_info.clone()).map_err(|e| Error::Other(e.into()))?; - - let base_url = oracle.get_base_url().map_err(|e| Error::Other(e.into()))?; - let source_base_url = base_url.as_str(); - - println!("Update the longitude: {}, for source {}", longitude, source_base_url); - - let node_metadata_repository = - get_node_metadata_repository_from_integritee_solo_or_parachain()?; - - let call_ids = node_metadata_repository - .get_from_metadata(|m| m.update_oracle_call_indexes()) - .map_err(Error::NodeMetadataProvider)? - .map_err(|e| Error::Other(format!("{:?}", e).into()))?; - - let call = OpaqueCall::from_tuple(&( - call_ids, - weather_info.weather_query.key().as_bytes().to_vec(), - source_base_url.as_bytes().to_vec(), - longitude.encode(), - )); - - Ok(call) -} - -#[no_mangle] -pub unsafe extern "C" fn update_weather_data_xt( - weather_info_longitude: *const u8, - weather_info_longitude_size: u32, - weather_info_latitude: *const u8, - weather_info_latitude_size: u32, - unchecked_extrinsic: *mut u8, - unchecked_extrinsic_max_size: u32, - unchecked_extrinsic_size: *mut u32, -) -> sgx_status_t { - let mut weather_info_longitude_slice = - slice::from_raw_parts(weather_info_longitude, weather_info_longitude_size as usize); - let longitude = match String::decode(&mut weather_info_longitude_slice) { - Ok(val) => val, - Err(e) => { - error!("Could not decode longitude: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let mut weather_info_latitude_slice = - slice::from_raw_parts(weather_info_latitude, weather_info_latitude_size as usize); - let latitude = match String::decode(&mut weather_info_latitude_slice) { - Ok(val) => val, - Err(e) => { - error!("Could not decode latitude: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let weather_query = WeatherQuery { longitude, latitude, hourly: " ".into() }; - let weather_info = WeatherInfo { weather_query }; - - let extrinsics = match update_weather_data_internal(weather_info) { - Ok(xts) => xts, - Err(e) => { - error!("Updating weather info failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let extrinsic_slice = - slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); - - // Save created extrinsic as slice in the return value unchecked_extrinsic. - *unchecked_extrinsic_size = - match write_slice_and_whitespace_pad(extrinsic_slice, extrinsics.encode()) { - Ok(l) => l as u32, - Err(e) => { - error!("Copying encoded extrinsics into return slice failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - sgx_status_t::SGX_SUCCESS -} - -/// For now get the crypto/fiat currency exchange rate from coingecko and CoinMarketCap. -#[no_mangle] -pub unsafe extern "C" fn update_market_data_xt( - crypto_currency_ptr: *const u8, - crypto_currency_size: u32, - fiat_currency_ptr: *const u8, - fiat_currency_size: u32, - unchecked_extrinsic: *mut u8, - unchecked_extrinsic_max_size: u32, - unchecked_extrinsic_size: *mut u32, -) -> sgx_status_t { - let mut crypto_currency_slice = - slice::from_raw_parts(crypto_currency_ptr, crypto_currency_size as usize); - #[allow(clippy::unwrap_used)] - let crypto_currency: String = Decode::decode(&mut crypto_currency_slice).unwrap(); - - let mut fiat_currency_slice = - slice::from_raw_parts(fiat_currency_ptr, fiat_currency_size as usize); - #[allow(clippy::unwrap_used)] - let fiat_currency: String = Decode::decode(&mut fiat_currency_slice).unwrap(); - - let extrinsics = match update_market_data_internal(crypto_currency, fiat_currency) { - Ok(xts) => xts, - Err(e) => { - error!("Update market data failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - if extrinsics.is_empty() { - error!("Updating market data yielded no extrinsics"); - return sgx_status_t::SGX_ERROR_UNEXPECTED - } - let extrinsic_slice = - slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); - - // Save created extrinsic as slice in the return value unchecked_extrinsic. - *unchecked_extrinsic_size = - match write_slice_and_whitespace_pad(extrinsic_slice, extrinsics.encode()) { - Ok(l) => l as u32, - Err(e) => { - error!("Copying encoded extrinsics into return slice failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - sgx_status_t::SGX_SUCCESS -} - -fn update_market_data_internal( - crypto_currency: String, - fiat_currency: String, -) -> Result> { - let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; - let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; - - let mut extrinsic_calls: Vec = Vec::new(); - - // Get the exchange rate - let trading_pair = TradingPair { crypto_currency, fiat_currency }; - - let coin_gecko_oracle = create_coin_gecko_oracle(ocall_api.clone()); - - match get_exchange_rate(trading_pair.clone(), coin_gecko_oracle) { - Ok(opaque_call) => extrinsic_calls.push(opaque_call), - Err(e) => { - error!("[-] Failed to get the newest exchange rate from CoinGecko. {:?}", e); - }, - }; - - let coin_market_cap_oracle = create_coin_market_cap_oracle(ocall_api); - match get_exchange_rate(trading_pair, coin_market_cap_oracle) { - Ok(oc) => extrinsic_calls.push(oc), - Err(e) => { - error!("[-] Failed to get the newest exchange rate from CoinMarketCap. {:?}", e); - }, - }; - - let extrinsics = extrinsics_factory.create_extrinsics(extrinsic_calls.as_slice(), None)?; - Ok(extrinsics) -} - -fn get_exchange_rate( - trading_pair: TradingPair, - oracle: ExchangeRateOracle, -) -> Result -where - OracleSourceType: OracleSource, - MetricsExporter: ExportMetrics, -{ - let (rate, base_url) = oracle - .get_exchange_rate(trading_pair.clone()) - .map_err(|e| Error::Other(e.into()))?; - - let source_base_url = base_url.as_str(); - - println!( - "Update the exchange rate: {} = {:?} for source {}", - trading_pair.clone().key(), - rate, - source_base_url, - ); - - let node_metadata_repository = - get_node_metadata_repository_from_integritee_solo_or_parachain()?; - - let call_ids = node_metadata_repository - .get_from_metadata(|m| m.update_exchange_rate_call_indexes()) - .map_err(Error::NodeMetadataProvider)? - .map_err(|e| Error::Other(format!("{:?}", e).into()))?; - - let call = OpaqueCall::from_tuple(&( - call_ids, - source_base_url.as_bytes().to_vec(), - trading_pair.key().as_bytes().to_vec(), - Some(rate), - )); - - Ok(call) -} diff --git a/bitacross-worker/enclave-runtime/src/test/direct_rpc_tests.rs b/bitacross-worker/enclave-runtime/src/test/direct_rpc_tests.rs index bcb7ba5d45..9d9ac24ff5 100644 --- a/bitacross-worker/enclave-runtime/src/test/direct_rpc_tests.rs +++ b/bitacross-worker/enclave-runtime/src/test/direct_rpc_tests.rs @@ -16,26 +16,82 @@ */ -use crate::{rpc::worker_api_direct::public_api_rpc_handler, Hash}; +use crate::{ + rpc::worker_api_direct::public_api_rpc_handler, + test::{ + fixtures::components::create_ocall_api, + mocks::types::{TestOCallApi, TestSigner}, + }, + Hash, +}; use codec::{Decode, Encode}; use ita_stf::{Getter, PublicGetter}; use itc_direct_rpc_server::{ create_determine_watch, rpc_connection_registry::ConnectionRegistry, rpc_ws_handler::RpcWsHandler, }; +use itc_parentchain_test::ParentchainHeaderBuilder; use itc_tls_websocket_server::{ConnectionToken, WebSocketMessageHandler}; use itp_rpc::{Id, RpcRequest, RpcReturnValue}; use itp_sgx_crypto::get_rsa3072_repository; use itp_sgx_temp_dir::TempDir; use itp_stf_executor::{getter_executor::GetterExecutor, mocks::GetStateMock}; use itp_stf_state_observer::mock::ObserveStateMock; -use itp_test::mock::handle_state_mock::HandleStateMock; use itp_top_pool_author::mocks::AuthorApiMock; use itp_types::{DirectRequestStatus, RsaRequest, ShardIdentifier}; use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use litentry_primitives::{Address32, Identity}; +use sp_core::Pair; use std::{string::ToString, sync::Arc, vec::Vec}; +pub fn state_get_mrenclave_works() { + type TestState = u64; + + let temp_dir = TempDir::with_prefix("get_state_request_works").unwrap(); + + let connection_registry = Arc::new(ConnectionRegistry::::new()); + let watch_extractor = Arc::new(create_determine_watch::()); + let rsa_repository = get_rsa3072_repository(temp_dir.path().to_path_buf()).unwrap(); + + let mr_enclave = [1; 32]; + + let ocall_api = TestOCallApi::default().with_mr_enclave(mr_enclave.clone()); + + let state: TestState = 78234u64; + let state_observer = Arc::new(ObserveStateMock::::new(state)); + let getter_executor = + Arc::new(GetterExecutor::<_, GetStateMock, Getter>::new(state_observer)); + let top_pool_author = Arc::new(AuthorApiMock::default()); + + let io_handler = public_api_rpc_handler( + top_pool_author, + getter_executor, + Arc::new(rsa_repository), + ocall_api.into(), + ); + let rpc_handler = Arc::new(RpcWsHandler::new(io_handler, watch_extractor, connection_registry)); + + let request_string = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "state_getMrenclave".to_string(), + vec![], + ) + .unwrap(); + + let response_string = + rpc_handler.handle_message(ConnectionToken(1), request_string).unwrap().unwrap(); + + assert!(!response_string.is_empty()); + + const EXPECTED_HEX_RETURN_VALUE: &str = + "0x8001010101010101010101010101010101010101010101010101010101010101010000"; + assert!(response_string.contains(EXPECTED_HEX_RETURN_VALUE)); + let rpc_return_value = RpcReturnValue::from_hex(EXPECTED_HEX_RETURN_VALUE).unwrap(); + assert_eq!(rpc_return_value.status, DirectRequestStatus::Ok); + let decoded_value: [u8; 32] = Decode::decode(&mut rpc_return_value.value.as_slice()).unwrap(); + assert_eq!(decoded_value, mr_enclave); +} + pub fn get_state_request_works() { type TestState = u64; @@ -45,6 +101,11 @@ pub fn get_state_request_works() { let watch_extractor = Arc::new(create_determine_watch::()); let rsa_repository = get_rsa3072_repository(temp_dir.path().to_path_buf()).unwrap(); + let signer = TestSigner::from_seed(b"42315678901234567890123456789012"); + let header = ParentchainHeaderBuilder::default().build(); + + let ocall_api = create_ocall_api(&header, &signer); + let state: TestState = 78234u64; let state_observer = Arc::new(ObserveStateMock::::new(state)); let getter_executor = @@ -55,7 +116,7 @@ pub fn get_state_request_works() { top_pool_author, getter_executor, Arc::new(rsa_repository), - None::>, + ocall_api, ); let rpc_handler = Arc::new(RpcWsHandler::new(io_handler, watch_extractor, connection_registry)); @@ -76,11 +137,6 @@ pub fn get_state_request_works() { assert!(!response_string.is_empty()); - // Because we cannot de-serialize the RpcResponse here (unresolved serde_json and std/sgx feature issue), - // we hard-code the expected response. - //error!("{}", response_string); - //let response: RpcResponse = serde_json::from_str(&response_string).unwrap(); - const EXPECTED_HEX_RETURN_VALUE: &str = "0x2801209a310100000000000000"; assert!(response_string.contains(EXPECTED_HEX_RETURN_VALUE)); let rpc_return_value = RpcReturnValue::from_hex(EXPECTED_HEX_RETURN_VALUE).unwrap(); diff --git a/bitacross-worker/enclave-runtime/src/test/evm_pallet_tests.rs b/bitacross-worker/enclave-runtime/src/test/evm_pallet_tests.rs deleted file mode 100644 index 61a8912e2e..0000000000 --- a/bitacross-worker/enclave-runtime/src/test/evm_pallet_tests.rs +++ /dev/null @@ -1,401 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -use crate::test::fixtures::test_setup::{test_setup, TestStf}; -use core::str::FromStr; -use ita_sgx_runtime::{AddressMapping, HashedAddressMapping, Index, System}; -use ita_stf::{ - evm_helpers::{ - create_code_hash, evm_create2_address, evm_create_address, get_evm_account_codes, - get_evm_account_storages, - }, - test_genesis::{endow, endowed_account as funded_pair}, - State, TrustedCall, -}; -use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; -use itp_sgx_externalities::SgxExternalitiesTrait; -use itp_stf_interface::StateCallInterface; -use itp_stf_primitives::{traits::TrustedCallSigning, types::KeyPair}; -use itp_types::{parentchain::ParentchainCall, AccountId, ShardIdentifier}; -use primitive_types::H256; -use sp_core::{crypto::Pair, H160, U256}; -use std::{sync::Arc, vec::Vec}; - -pub fn test_evm_call() { - // given - let (_, mut state, shard, mrenclave, ..) = test_setup(); - let mut parentchain_calls = Vec::new(); - - // Create the sender account. - let sender = funded_pair(); - let sender_acc: AccountId = sender.public().into(); - let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; - sender_evm_acc_slice - .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); - let sender_evm_acc: H160 = sender_evm_acc_slice.into(); - // Ensure the substrate version of the evm account has some money. - let sender_evm_substrate_addr = - ita_sgx_runtime::HashedAddressMapping::into_account_id(sender_evm_acc); - endow(&mut state, vec![(sender_evm_substrate_addr, 51_777_000_000_000)]); - - // Create the receiver account. - let destination_evm_acc = H160::from_str("1000000000000000000000000000000000000001").unwrap(); - let destination_evm_substrate_addr = - ita_sgx_runtime::HashedAddressMapping::into_account_id(destination_evm_acc); - assert_eq!( - state.execute_with(|| System::account(&destination_evm_substrate_addr).data.free), - 0 - ); - - let transfer_value: u128 = 1_000_000_000; - - let trusted_call = TrustedCall::evm_call( - sender_acc, - sender_evm_acc, - destination_evm_acc, - Vec::new(), - U256::from(transfer_value), - 21776, // gas limit - U256::from(1_000_000_000), - None, - Some(U256::from(0)), - Vec::new(), - ) - .sign(&sender.into(), 0, &mrenclave, &shard); - - // when - let repo = Arc::new(NodeMetadataRepository::::default()); - let shard = ShardIdentifier::default(); - TestStf::execute_call( - &mut state, - &shard, - trusted_call, - Default::default(), - &mut parentchain_calls, - repo, - ) - .unwrap(); - - // then - assert_eq!( - transfer_value, - state.execute_with(|| System::account(&destination_evm_substrate_addr).data.free) - ); -} - -pub fn test_evm_counter() { - // given - let (_, mut state, shard, mrenclave, ..) = test_setup(); - let mut parentchain_calls = Vec::new(); - - // Create the sender account. - let sender = funded_pair(); - let sender_acc: AccountId = sender.public().into(); - let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; - sender_evm_acc_slice - .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); - let sender_evm_acc: H160 = sender_evm_acc_slice.into(); - // Ensure the substrate version of the evm account has some money. - let sender_evm_substrate_addr = - ita_sgx_runtime::HashedAddressMapping::into_account_id(sender_evm_acc); - endow(&mut state, vec![(sender_evm_substrate_addr, 51_777_000_000_000)]); - - // Smart Contract from Counter.sol. - let smart_contract = "608060405234801561001057600080fd5b50600160008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610377806100696000396000f3fe6080604052600436106100435760003560e01c80631003e2d21461004d57806333cf508014610076578063371303c0146100a157806358992216146100b857610044565b5b60056000819055005b34801561005957600080fd5b50610074600480360381019061006f9190610209565b6100e3565b005b34801561008257600080fd5b5061008b61013f565b6040516100989190610245565b60405180910390f35b3480156100ad57600080fd5b506100b6610148565b005b3480156100c457600080fd5b506100cd6101a4565b6040516100da91906102a1565b60405180910390f35b806000808282546100f491906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054905090565b600160008082825461015a91906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b6000819050919050565b6101e6816101d3565b81146101f157600080fd5b50565b600081359050610203816101dd565b92915050565b60006020828403121561021f5761021e6101ce565b5b600061022d848285016101f4565b91505092915050565b61023f816101d3565b82525050565b600060208201905061025a6000830184610236565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028b82610260565b9050919050565b61029b81610280565b82525050565b60006020820190506102b66000830184610292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102f6826101d3565b9150610301836101d3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610336576103356102bc565b5b82820190509291505056fea2646970667358221220b37e993e133ed19c840809cc8acbbba8116dee3744ba01c81044d75146805c9364736f6c634300080f0033"; - - let trusted_call = TrustedCall::evm_create( - sender_acc.clone(), - sender_evm_acc, - array_bytes::hex2bytes(smart_contract).unwrap().to_vec(), - U256::from(0), - 10_000_000, // gas limit - U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime - None, - Some(U256::from(0)), - Vec::new(), - ) - .sign(&sender.into(), 0, &mrenclave, &shard); - - // when - let execution_address = evm_create_address(sender_evm_acc, 0); - let repo = Arc::new(NodeMetadataRepository::::default()); - let shard = ShardIdentifier::default(); - TestStf::execute_call( - &mut state, - &shard, - trusted_call, - Default::default(), - &mut parentchain_calls, - repo, - ) - .unwrap(); - - // then - assert_eq!( - execution_address, - H160::from_slice( - &array_bytes::hex2bytes("0xce2c9e7f9c10049996173b2ca2d9a6815a70e890").unwrap(), - ) - ); - - assert!(state.execute_with(|| get_evm_account_codes(&execution_address).is_some())); - - let counter_value = state - .execute_with(|| get_evm_account_storages(&execution_address, &H256::zero())) - .unwrap(); - assert_eq!(H256::from_low_u64_be(1), counter_value); - let last_caller = state - .execute_with(|| get_evm_account_storages(&execution_address, &H256::from_low_u64_be(1))) - .unwrap(); - assert_eq!(H256::from(sender_evm_acc), last_caller); - - // Call to inc() function - // in solidity compile information you get the hash of the call - let inc_function_input = array_bytes::hex2bytes("371303c0").unwrap(); - - execute_and_verify_evm_call( - sender_acc.clone(), - sender_evm_acc, - execution_address, - inc_function_input.to_vec(), - 1, - 1, - sender.into(), - &mrenclave, - &shard, - &mut state, - &mut parentchain_calls, - 2, - ); - - // Call the fallback function - execute_and_verify_evm_call( - sender_acc.clone(), - sender_evm_acc, - execution_address, - Vec::new(), // Empty input calls the fallback function. - 2, - 2, - sender.into(), - &mrenclave, - &shard, - &mut state, - &mut parentchain_calls, - 5, - ); - - // Call to inc() function - // in solidity compile information you get the hash of the call - execute_and_verify_evm_call( - sender_acc.clone(), - sender_evm_acc, - execution_address, - inc_function_input, - 3, - 3, - sender.into(), - &mrenclave, - &shard, - &mut state, - &mut parentchain_calls, - 6, - ); - - // Call to add() function - // in solidity compile information you get the hash of the call - let function_hash = "1003e2d2"; - // 32 byte string of the value to add in hex - let add_value = "0000000000000000000000000000000000000000000000000000000000000002"; - let add_function_input = - array_bytes::hex2bytes(&format!("{}{}", function_hash, add_value)).unwrap(); - - execute_and_verify_evm_call( - sender_acc, - sender_evm_acc, - execution_address, - add_function_input, - 4, - 4, - sender.into(), - &mrenclave, - &shard, - &mut state, - &mut parentchain_calls, - 8, - ); -} - -#[allow(clippy::too_many_arguments)] -fn execute_and_verify_evm_call( - sender_acc: AccountId, - sender_evm_acc: H160, - execution_address: H160, - function_input: Vec, - evm_nonce: i8, - nonce: Index, - pair: KeyPair, - mrenclave: &[u8; 32], - shard: &ShardIdentifier, - state: &mut State, - calls: &mut Vec, - counter_expected: u64, -) { - let inc_call = TrustedCall::evm_call( - sender_acc, - sender_evm_acc, - execution_address, - function_input, - U256::from(0), - 10_000_000, // gas limit - U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime - None, - Some(U256::from(evm_nonce)), - Vec::new(), - ) - .sign(&pair, nonce, mrenclave, shard); - let repo = Arc::new(NodeMetadataRepository::::default()); - let shard = ShardIdentifier::default(); - TestStf::execute_call(state, &shard, inc_call, Default::default(), calls, repo).unwrap(); - - let counter_value = state - .execute_with(|| get_evm_account_storages(&execution_address, &H256::zero())) - .unwrap(); - assert_eq!(counter_value, H256::from_low_u64_be(counter_expected)); -} - -pub fn test_evm_create() { - // given - let (_, mut state, shard, mrenclave, ..) = test_setup(); - let mut parentchain_calls = Vec::new(); - - // Create the sender account. - let sender = funded_pair(); - let sender_acc: AccountId = sender.public().into(); - let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; - sender_evm_acc_slice - .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); - let sender_evm_acc: H160 = sender_evm_acc_slice.into(); - // Ensure the substrate version of the evm account has some money. - let sender_evm_substrate_addr = HashedAddressMapping::into_account_id(sender_evm_acc); - endow(&mut state, vec![(sender_evm_substrate_addr.clone(), 51_777_000_000_000)]); - - // Bytecode from Counter.sol - let smart_contract = "608060405234801561001057600080fd5b50600160008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610377806100696000396000f3fe6080604052600436106100435760003560e01c80631003e2d21461004d57806333cf508014610076578063371303c0146100a157806358992216146100b857610044565b5b60056000819055005b34801561005957600080fd5b50610074600480360381019061006f9190610209565b6100e3565b005b34801561008257600080fd5b5061008b61013f565b6040516100989190610245565b60405180910390f35b3480156100ad57600080fd5b506100b6610148565b005b3480156100c457600080fd5b506100cd6101a4565b6040516100da91906102a1565b60405180910390f35b806000808282546100f491906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054905090565b600160008082825461015a91906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b6000819050919050565b6101e6816101d3565b81146101f157600080fd5b50565b600081359050610203816101dd565b92915050565b60006020828403121561021f5761021e6101ce565b5b600061022d848285016101f4565b91505092915050565b61023f816101d3565b82525050565b600060208201905061025a6000830184610236565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028b82610260565b9050919050565b61029b81610280565b82525050565b60006020820190506102b66000830184610292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102f6826101d3565b9150610301836101d3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610336576103356102bc565b5b82820190509291505056fea2646970667358221220b37e993e133ed19c840809cc8acbbba8116dee3744ba01c81044d75146805c9364736f6c634300080f0033"; - let smart_contract = array_bytes::hex2bytes(smart_contract).unwrap(); - - let trusted_call = TrustedCall::evm_create( - sender_acc, - sender_evm_acc, - smart_contract, - U256::from(0), // value - 10_000_000, // gas limit - U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime - None, - Some(U256::from(0)), - Vec::new(), - ) - .sign(&sender.into(), 0, &mrenclave, &shard); - - // Should be the first call of the evm account - let nonce = state.execute_with(|| System::account_nonce(&sender_evm_substrate_addr)); - assert_eq!(nonce, 0); - let execution_address = evm_create_address(sender_evm_acc, nonce); - let repo = Arc::new(NodeMetadataRepository::::default()); - let shard = ShardIdentifier::default(); - TestStf::execute_call( - &mut state, - &shard, - trusted_call, - Default::default(), - &mut parentchain_calls, - repo, - ) - .unwrap(); - - assert_eq!( - execution_address, - H160::from_slice( - &array_bytes::hex2bytes("0xce2c9e7f9c10049996173b2ca2d9a6815a70e890").unwrap(), - ) - ); - assert!(state.execute_with(|| get_evm_account_codes(&execution_address).is_some())); - - // Ensure the nonce of the evm account has been increased by one - // Should be the first call of the evm account - let nonce = state.execute_with(|| System::account_nonce(&sender_evm_substrate_addr)); - assert_eq!(nonce, 1); -} - -pub fn test_evm_create2() { - // given - let (_, mut state, shard, mrenclave, ..) = test_setup(); - let mut parentchain_calls = Vec::new(); - - // Create the sender account. - let sender = funded_pair(); - let sender_acc: AccountId = sender.public().into(); - let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; - sender_evm_acc_slice - .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); - let sender_evm_acc: H160 = sender_evm_acc_slice.into(); - // Ensure the substrate version of the evm account has some money. - let sender_evm_substrate_addr = HashedAddressMapping::into_account_id(sender_evm_acc); - endow(&mut state, vec![(sender_evm_substrate_addr, 51_777_000_000_000)]); - - let salt = H256::from_low_u64_be(20); - // Bytecode from Counter.sol - let smart_contract = "608060405234801561001057600080fd5b50600160008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610377806100696000396000f3fe6080604052600436106100435760003560e01c80631003e2d21461004d57806333cf508014610076578063371303c0146100a157806358992216146100b857610044565b5b60056000819055005b34801561005957600080fd5b50610074600480360381019061006f9190610209565b6100e3565b005b34801561008257600080fd5b5061008b61013f565b6040516100989190610245565b60405180910390f35b3480156100ad57600080fd5b506100b6610148565b005b3480156100c457600080fd5b506100cd6101a4565b6040516100da91906102a1565b60405180910390f35b806000808282546100f491906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054905090565b600160008082825461015a91906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b6000819050919050565b6101e6816101d3565b81146101f157600080fd5b50565b600081359050610203816101dd565b92915050565b60006020828403121561021f5761021e6101ce565b5b600061022d848285016101f4565b91505092915050565b61023f816101d3565b82525050565b600060208201905061025a6000830184610236565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028b82610260565b9050919050565b61029b81610280565b82525050565b60006020820190506102b66000830184610292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102f6826101d3565b9150610301836101d3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610336576103356102bc565b5b82820190509291505056fea2646970667358221220b37e993e133ed19c840809cc8acbbba8116dee3744ba01c81044d75146805c9364736f6c634300080f0033"; - let smart_contract = array_bytes::hex2bytes(smart_contract).unwrap(); - - let trusted_call = TrustedCall::evm_create2( - sender_acc, - sender_evm_acc, - smart_contract.clone(), - salt, - U256::from(0), // value - 10_000_000, // gas limit - U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime - None, - Some(U256::from(0)), - Vec::new(), - ) - .sign(&sender.into(), 0, &mrenclave, &shard); - - // when - let code_hash = create_code_hash(&smart_contract); - let execution_address = evm_create2_address(sender_evm_acc, salt, code_hash); - let repo = Arc::new(NodeMetadataRepository::::default()); - let shard = ShardIdentifier::default(); - TestStf::execute_call( - &mut state, - &shard, - trusted_call, - Default::default(), - &mut parentchain_calls, - repo, - ) - .unwrap(); - - // then - assert_eq!( - execution_address, - H160::from_slice( - &array_bytes::hex2bytes("0xe07ad7925f6b2b10c5a7653fb16db7a984059d11").unwrap(), - ) - ); - - assert!(state.execute_with(|| get_evm_account_codes(&execution_address).is_some())); -} diff --git a/bitacross-worker/enclave-runtime/src/test/fixtures/components.rs b/bitacross-worker/enclave-runtime/src/test/fixtures/components.rs index dd1237672d..34f3606010 100644 --- a/bitacross-worker/enclave-runtime/src/test/fixtures/components.rs +++ b/bitacross-worker/enclave-runtime/src/test/fixtures/components.rs @@ -27,7 +27,7 @@ use itp_stf_primitives::{ }; use itp_top_pool::pool::Options as PoolOptions; use itp_top_pool_author::api::SidechainApi; -use itp_types::{Block as ParentchainBlock, Enclave, ShardIdentifier}; +use itp_types::{Block as ParentchainBlock, ShardIdentifier}; use sp_core::{ed25519, Pair, H256}; use sp_runtime::traits::Header as HeaderTrait; use std::{boxed::Box, sync::Arc, vec::Vec}; @@ -41,13 +41,7 @@ pub(crate) fn create_ocall_api>( header: &Header, signer: &TestSigner, ) -> Arc { - let enclave_validateer = Enclave::new( - signer.public().into(), - Default::default(), - Default::default(), - Default::default(), - ); - Arc::new(TestOCallApi::default().add_validateer_set(header, Some(vec![enclave_validateer]))) + Arc::new(TestOCallApi::default().add_validateer_set(header, Some(vec![signer.public().into()]))) } pub(crate) fn encrypt_trusted_operation( diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/enclave_rpc_ocall_mock.rs b/bitacross-worker/enclave-runtime/src/test/mocks/enclave_rpc_ocall_mock.rs deleted file mode 100644 index 23003989e8..0000000000 --- a/bitacross-worker/enclave-runtime/src/test/mocks/enclave_rpc_ocall_mock.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use codec::Encode; -use itp_ocall_api::EnclaveRpcOCallApi; -use itp_types::TrustedOperationStatus; -use sgx_types::SgxResult; -use std::vec::Vec; - -#[derive(Clone, Debug, Default)] -pub struct EnclaveRpcOCallMock; - -impl EnclaveRpcOCallApi for EnclaveRpcOCallMock { - fn update_status_event( - &self, - _hash: H, - _status_update: TrustedOperationStatus, - ) -> SgxResult<()> { - Ok(()) - } - - fn send_state(&self, _hash: H, _value_opt: Option>) -> SgxResult<()> { - Ok(()) - } -} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/mod.rs b/bitacross-worker/enclave-runtime/src/test/mocks/mod.rs index 26551844d6..a6079c29eb 100644 --- a/bitacross-worker/enclave-runtime/src/test/mocks/mod.rs +++ b/bitacross-worker/enclave-runtime/src/test/mocks/mod.rs @@ -17,8 +17,5 @@ */ pub mod attestation_ocall_mock; -pub mod enclave_rpc_ocall_mock; -pub mod peer_updater_mock; -pub mod propose_to_import_call_mock; pub mod rpc_responder_mock; pub mod types; diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs b/bitacross-worker/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs deleted file mode 100644 index fa47ae9539..0000000000 --- a/bitacross-worker/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs +++ /dev/null @@ -1,137 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::test::mocks::types::TestBlockImporter; -use codec::{Decode, Encode}; -use itc_parentchain::primitives::ParentchainId; -use itp_ocall_api::{ - EnclaveMetricsOCallApi, EnclaveOnChainOCallApi, EnclaveSidechainOCallApi, Result, -}; -use itp_types::{ - storage::StorageEntryVerified, BlockHash, Header as ParentchainHeader, ShardIdentifier, - WorkerRequest, WorkerResponse, H256, -}; -use its_primitives::types::block::SignedBlock as SignedSidechainBlockType; -use its_sidechain::consensus_common::BlockImport; -use sgx_types::SgxResult; -use sp_runtime::{traits::Header as ParentchainHeaderTrait, OpaqueExtrinsic}; -use std::{string::String, sync::Arc, vec::Vec}; - -/// OCallApi mock that routes the proposed sidechain blocks directly to the importer, -/// short circuiting all the RPC calls. -#[derive(Clone)] -pub struct ProposeToImportOCallApi { - parentchain_header: ParentchainHeader, - block_importer: Arc, -} - -impl ProposeToImportOCallApi { - pub fn new( - parentchain_header: ParentchainHeader, - block_importer: Arc, - ) -> Self { - ProposeToImportOCallApi { parentchain_header, block_importer } - } -} - -impl EnclaveOnChainOCallApi for ProposeToImportOCallApi { - fn send_to_parentchain( - &self, - _extrinsics: Vec, - _: &ParentchainId, - _: bool, - ) -> SgxResult<()> { - Ok(()) - } - - fn worker_request( - &self, - _req: Vec, - _: &ParentchainId, - ) -> SgxResult>> { - todo!() - } - - fn get_storage_verified, V: Decode>( - &self, - _storage_hash: Vec, - _header: &H, - _: &ParentchainId, - ) -> Result> { - todo!() - } - - fn get_multiple_storages_verified, V: Decode>( - &self, - _storage_hashes: Vec>, - _header: &H, - _: &ParentchainId, - ) -> Result>> { - todo!() - } - - fn get_storage_keys(&self, _key_prefix: Vec) -> Result>> { - todo!() - } -} - -impl EnclaveSidechainOCallApi for ProposeToImportOCallApi { - fn propose_sidechain_blocks( - &self, - signed_blocks: Vec, - ) -> SgxResult<()> { - let decoded_signed_blocks: Vec = signed_blocks - .iter() - .map(|sb| sb.encode()) - .map(|e| SignedSidechainBlockType::decode(&mut e.as_slice()).unwrap()) - .collect(); - - for signed_block in decoded_signed_blocks { - self.block_importer - .import_block(signed_block, &self.parentchain_header) - .unwrap(); - } - Ok(()) - } - - fn store_sidechain_blocks( - &self, - _signed_blocks: Vec, - ) -> SgxResult<()> { - Ok(()) - } - - fn fetch_sidechain_blocks_from_peer( - &self, - _last_imported_block_hash: BlockHash, - _maybe_until_block_hash: Option, - _shard_identifier: ShardIdentifier, - ) -> SgxResult> { - Ok(Vec::new()) - } - - fn get_trusted_peers_urls(&self) -> SgxResult> { - Ok(vec![]) - } -} - -impl EnclaveMetricsOCallApi for ProposeToImportOCallApi { - fn update_metric(&self, _metric: Metric) -> SgxResult<()> { - Ok(()) - } -} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/types.rs b/bitacross-worker/enclave-runtime/src/test/mocks/types.rs index ae939c53e4..4c9500eb5a 100644 --- a/bitacross-worker/enclave-runtime/src/test/mocks/types.rs +++ b/bitacross-worker/enclave-runtime/src/test/mocks/types.rs @@ -18,9 +18,7 @@ //! Type definitions for testing. Includes various mocks. -use crate::test::mocks::{ - peer_updater_mock::PeerUpdaterMock, rpc_responder_mock::RpcResponderMock, -}; +use crate::test::mocks::rpc_responder_mock::RpcResponderMock; use ita_sgx_runtime::Runtime; use ita_stf::{Getter, Stf, TrustedCallSigned}; use itc_parentchain::block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; @@ -40,8 +38,6 @@ use itp_top_pool_author::{ top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}, }; use itp_types::{Block as ParentchainBlock, SignedBlock as SignedParentchainBlock}; -use its_primitives::types::SignedBlock as SignedSidechainBlock; -use its_sidechain::{aura::block_importer::BlockImporter, block_composer::BlockComposer}; use primitive_types::H256; use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; use sp_core::ed25519 as spEd25519; @@ -95,20 +91,3 @@ pub type TestTopPoolAuthor = Author< TrustedCallSigned, Getter, >; - -pub type TestBlockComposer = - BlockComposer; - -pub type TestBlockImporter = BlockImporter< - TestSigner, - ParentchainBlock, - SignedSidechainBlock, - TestOCallApi, - HandleStateMock, - TestStateKeyRepo, - TestTopPoolAuthor, - TestParentchainBlockImportTrigger, - PeerUpdaterMock, - TrustedCallSigned, - Getter, ->; diff --git a/bitacross-worker/enclave-runtime/src/test/mod.rs b/bitacross-worker/enclave-runtime/src/test/mod.rs index 6f3d7a252e..8bdbe375c9 100644 --- a/bitacross-worker/enclave-runtime/src/test/mod.rs +++ b/bitacross-worker/enclave-runtime/src/test/mod.rs @@ -19,16 +19,9 @@ pub mod cert_tests; pub mod direct_rpc_tests; pub mod enclave_signer_tests; -#[cfg(feature = "evm")] -pub mod evm_pallet_tests; pub mod fixtures; pub mod ipfs_tests; pub mod mocks; -pub mod sidechain_aura_tests; -pub mod sidechain_event_tests; mod state_getter_tests; pub mod tests_main; pub mod top_pool_tests; - -#[cfg(feature = "teeracle")] -pub mod teeracle_tests; diff --git a/bitacross-worker/enclave-runtime/src/test/sidechain_aura_tests.rs b/bitacross-worker/enclave-runtime/src/test/sidechain_aura_tests.rs deleted file mode 100644 index 36ad0f69b9..0000000000 --- a/bitacross-worker/enclave-runtime/src/test/sidechain_aura_tests.rs +++ /dev/null @@ -1,287 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - test::{ - fixtures::{ - components::{ - create_ocall_api, create_top_pool, encrypt_trusted_operation, sign_trusted_call, - }, - initialize_test_state::init_state, - test_setup::{enclave_call_signer, TestStf}, - }, - mocks::{ - peer_updater_mock::PeerUpdaterMock, - propose_to_import_call_mock::ProposeToImportOCallApi, types::*, - }, - }, - top_pool_execution::{exec_aura_on_slot, send_blocks_and_extrinsics}, -}; -use codec::Decode; -use ita_stf::{ - test_genesis::{endowed_account, second_endowed_account, unendowed_account}, - Balance, Getter, TrustedCall, TrustedCallSigned, -}; -use itc_parentchain_test::ParentchainHeaderBuilder; -use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; -use itp_ocall_api::EnclaveAttestationOCallApi; -use itp_settings::{ - sidechain::SLOT_DURATION, - worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}, -}; -use itp_sgx_crypto::{Aes, ShieldingCryptoEncrypt, StateCrypto}; -use itp_sgx_externalities::SgxExternalitiesDiffType; -use itp_stf_interface::system_pallet::{SystemPalletAccountInterface, SystemPalletEventInterface}; -use itp_stf_primitives::types::{StatePayload, TrustedOperation}; -use itp_stf_state_handler::handle_state::HandleState; -use itp_test::mock::{handle_state_mock::HandleStateMock, metrics_ocall_mock::MetricsOCallMock}; -use itp_time_utils::duration_now; -use itp_top_pool_author::{ - top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}, - traits::AuthorApi, -}; -use itp_types::{AccountId, Block as ParentchainBlock, RsaRequest, ShardIdentifier}; -use its_block_verification::slot::slot_from_timestamp_and_duration; -use its_primitives::{traits::Block, types::SignedBlock as SignedSidechainBlock}; -use its_sidechain::{aura::proposer_factory::ProposerFactory, slots::SlotInfo}; -use jsonrpc_core::futures::executor; -use lc_scheduled_enclave::ScheduledEnclaveMock; -use litentry_primitives::Identity; -use log::*; -use primitive_types::H256; -use sgx_crypto_helper::RsaKeyPair; -use sp_core::{ed25519, Pair}; -use std::{sync::Arc, vec, vec::Vec}; - -/// Integration test for sidechain block production and block import. -/// (requires Sidechain mode) -/// -/// - Create trusted calls and add them to the TOP pool. -/// - Run AURA on a valid and claimed slot, which executes the trusted operations and produces a new block. -/// - Import the new sidechain block, which updates the state. -pub fn produce_sidechain_block_and_import_it() { - // Test can only be run in Sidechain mode - if WorkerModeProvider::worker_mode() != WorkerMode::Sidechain { - info!("Ignoring sidechain block production test: Not in sidechain mode"); - return - } - - let _ = env_logger::builder().is_test(true).try_init(); - info!("Setting up test."); - - let signer = TestSigner::from_seed(b"42315678901234567890123456789012"); - let shielding_key = TestShieldingKey::new().unwrap(); - let state_key = TestStateKey::new([3u8; 16], [1u8; 16]); - let shielding_key_repo = Arc::new(TestShieldingKeyRepo::new(shielding_key)); - let state_key_repo = Arc::new(TestStateKeyRepo::new(state_key)); - let parentchain_header = ParentchainHeaderBuilder::default().build(); - - let ocall_api = create_ocall_api(&parentchain_header, &signer); - - info!("Initializing state and shard.."); - let state_handler = Arc::new(TestStateHandler::default()); - let enclave_call_signer = enclave_call_signer(&shielding_key); - let (_, shard_id) = init_state(state_handler.as_ref(), enclave_call_signer.public().into()); - let shards = vec![shard_id]; - - let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadataMock::new())); - let stf_executor = Arc::new(TestStfExecutor::new( - ocall_api.clone(), - state_handler.clone(), - node_metadata_repo, - )); - let top_pool = create_top_pool(); - - let (sender, _receiver) = std::sync::mpsc::sync_channel(1000); - - let metrics_ocall_mock = Arc::new(MetricsOCallMock::default()); - - let top_pool_author = Arc::new(TestTopPoolAuthor::new( - top_pool, - AllowAllTopsFilter::::new(), - DirectCallsOnlyFilter::::new(), - state_handler.clone(), - shielding_key_repo, - metrics_ocall_mock.clone(), - Arc::new(sender), - )); - let parentchain_block_import_trigger = Arc::new(TestParentchainBlockImportTrigger::default()); - let peer_updater_mock = Arc::new(PeerUpdaterMock {}); - let block_importer = Arc::new(TestBlockImporter::new( - state_handler.clone(), - state_key_repo.clone(), - top_pool_author.clone(), - parentchain_block_import_trigger.clone(), - ocall_api.clone(), - peer_updater_mock, - )); - let block_composer = Arc::new(TestBlockComposer::new(signer, state_key_repo)); - let proposer_environment = ProposerFactory::new( - top_pool_author.clone(), - stf_executor, - block_composer, - metrics_ocall_mock, - ); - - info!("Create trusted operations.."); - let sender = endowed_account(); - let sender_with_low_balance = second_endowed_account(); - let receiver = unendowed_account(); - let transfered_amount: Balance = 1000; - let trusted_operation = encrypted_trusted_operation_transfer_balance( - ocall_api.as_ref(), - &shard_id, - &shielding_key, - sender, - receiver.public().into(), - transfered_amount, - ); - let invalid_trusted_operation = encrypted_trusted_operation_transfer_balance( - ocall_api.as_ref(), - &shard_id, - &shielding_key, - sender_with_low_balance, - receiver.public().into(), - ita_stf::test_genesis::SECOND_ENDOWED_ACC_FUNDS + 1, - ); - info!("Add trusted operations to TOP pool.."); - executor::block_on(top_pool_author.submit_top(RsaRequest::new(shard_id, trusted_operation))) - .unwrap(); - executor::block_on( - top_pool_author.submit_top(RsaRequest::new(shard_id, invalid_trusted_operation)), - ) - .unwrap(); - - // Ensure we have exactly two trusted calls in our TOP pool, and no getters. - assert_eq!(2, top_pool_author.get_pending_trusted_calls(shard_id).len()); - assert!(top_pool_author.get_pending_getters(shard_id).is_empty()); - - info!("Setup AURA SlotInfo"); - let timestamp = duration_now(); - let slot = slot_from_timestamp_and_duration(duration_now(), SLOT_DURATION); - let ends_at = timestamp + SLOT_DURATION; - let slot_info = SlotInfo::new( - slot, - timestamp, - SLOT_DURATION, - ends_at, - parentchain_header.clone(), - None, - None, - ); - - info!("Test setup is done."); - - let state_hash_before_block_production = get_state_hash(state_handler.as_ref(), &shard_id); - let scheduled_enclave = Arc::new(ScheduledEnclaveMock::default()); - - info!("Executing AURA on slot.."); - let (blocks, opaque_calls) = - exec_aura_on_slot::<_, ParentchainBlock, SignedSidechainBlock, _, _, _, _, _, _, _>( - slot_info, - signer, - ocall_api, - parentchain_block_import_trigger.clone(), - None::>, - None::>, - proposer_environment, - shards, - scheduled_enclave, - state_handler.clone(), - ) - .unwrap(); - - assert_eq!(1, blocks.len()); - assert_eq!( - state_hash_before_block_production, - get_state_hash(state_handler.as_ref(), &shard_id) - ); - - let (apriori_state_hash_in_block, aposteriori_state_hash_in_block) = - get_state_hashes_from_block(blocks.first().unwrap(), &state_key); - assert_ne!(state_hash_before_block_production, aposteriori_state_hash_in_block); - assert_eq!(state_hash_before_block_production, apriori_state_hash_in_block); - - // Ensure we have triggered the parentchain block import, because we claimed the slot. - assert!(parentchain_block_import_trigger.has_import_been_called()); - - // Ensure that invalid calls are removed from pool. Valid calls should only be removed upon block import. - assert_eq!(1, top_pool_author.get_pending_trusted_calls(shard_id).len()); - - info!("Executed AURA successfully. Sending blocks and extrinsics.."); - let propose_to_block_import_ocall_api = - Arc::new(ProposeToImportOCallApi::new(parentchain_header, block_importer)); - - send_blocks_and_extrinsics::( - blocks, - opaque_calls, - propose_to_block_import_ocall_api, - ) - .unwrap(); - - // After importing the sidechain block, the trusted operation should be removed. - assert!(top_pool_author.get_pending_trusted_calls(shard_id).is_empty()); - - // After importing the block, the state hash must be changed. - // We don't have a way to directly compare state hashes, because calculating the state hash - // would also involve applying set_last_block action, which updates the state upon import. - assert_ne!( - state_hash_before_block_production, - get_state_hash(state_handler.as_ref(), &shard_id) - ); - - let (mut state, _) = state_handler.load_cloned(&shard_id).unwrap(); - let free_balance = TestStf::get_account_data(&mut state, &receiver.public().into()).free; - assert_eq!(free_balance, transfered_amount); - assert!(TestStf::get_event_count(&mut state) > 0); - assert!(!TestStf::get_events(&mut state).is_empty()); -} - -fn encrypted_trusted_operation_transfer_balance< - AttestationApi: EnclaveAttestationOCallApi, - ShieldingKey: ShieldingCryptoEncrypt, ->( - attestation_api: &AttestationApi, - shard_id: &ShardIdentifier, - shielding_key: &ShieldingKey, - from: ed25519::Pair, - to: AccountId, - amount: Balance, -) -> Vec { - let call = TrustedCall::balance_transfer(Identity::Substrate(from.public().into()), to, amount); - let call_signed = sign_trusted_call(&call, attestation_api, shard_id, from); - let trusted_operation = TrustedOperation::::direct_call(call_signed); - encrypt_trusted_operation(shielding_key, &trusted_operation) -} - -fn get_state_hashes_from_block( - signed_block: &SignedSidechainBlock, - state_key: &Aes, -) -> (H256, H256) { - let mut encrypted_state_diff = signed_block.block.block_data().encrypted_state_diff.clone(); - state_key.decrypt(&mut encrypted_state_diff).unwrap(); - let decoded_state = - StatePayload::::decode(&mut encrypted_state_diff.as_slice()) - .unwrap(); - (decoded_state.state_hash_apriori(), decoded_state.state_hash_aposteriori()) -} - -fn get_state_hash(state_handler: &HandleStateMock, shard_id: &ShardIdentifier) -> H256 { - let (_, state_hash) = state_handler.load_cloned(shard_id).unwrap(); - state_hash -} diff --git a/bitacross-worker/enclave-runtime/src/test/sidechain_event_tests.rs b/bitacross-worker/enclave-runtime/src/test/sidechain_event_tests.rs deleted file mode 100644 index 64294f0121..0000000000 --- a/bitacross-worker/enclave-runtime/src/test/sidechain_event_tests.rs +++ /dev/null @@ -1,190 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - test::{ - fixtures::{ - components::{create_ocall_api, create_top_pool}, - initialize_test_state::init_state, - test_setup::{enclave_call_signer, TestStf}, - }, - mocks::{ - peer_updater_mock::PeerUpdaterMock, - propose_to_import_call_mock::ProposeToImportOCallApi, types::*, - }, - }, - top_pool_execution::{exec_aura_on_slot, send_blocks_and_extrinsics}, -}; -use ita_sgx_runtime::Runtime; -use ita_stf::{helpers::set_block_number, Getter, TrustedCallSigned}; -use itc_parentchain_test::ParentchainHeaderBuilder; -use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; -use itp_settings::{ - sidechain::SLOT_DURATION, - worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}, -}; -use itp_sgx_externalities::SgxExternalitiesTrait; -use itp_stf_interface::system_pallet::SystemPalletEventInterface; -use itp_stf_state_handler::handle_state::HandleState; -use itp_test::mock::metrics_ocall_mock::MetricsOCallMock; -use itp_time_utils::duration_now; -use itp_top_pool_author::top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}; -use itp_types::Block as ParentchainBlock; -use its_block_verification::slot::slot_from_timestamp_and_duration; -use its_primitives::types::SignedBlock as SignedSidechainBlock; -use its_sidechain::{aura::proposer_factory::ProposerFactory, slots::SlotInfo}; -use lc_scheduled_enclave::ScheduledEnclaveMock; -use log::*; -use primitive_types::H256; -use sgx_crypto_helper::RsaKeyPair; -use sp_core::Pair; -use std::{sync::Arc, vec}; - -/// Integration test to ensure the events are reset upon block import. -/// Otherwise we will have an ever growing state. -/// (requires Sidechain mode) -pub fn ensure_events_get_reset_upon_block_proposal() { - // Test can only be run in Sidechain mode - if WorkerModeProvider::worker_mode() != WorkerMode::Sidechain { - info!("Ignoring sidechain block production test: Not in sidechain mode"); - return - } - - let _ = env_logger::builder().is_test(true).try_init(); - info!("Setting up test."); - - let signer = TestSigner::from_seed(b"42315678901234567890123456789012"); - let shielding_key = TestShieldingKey::new().unwrap(); - let state_key = TestStateKey::new([3u8; 16], [1u8; 16]); - let shielding_key_repo = Arc::new(TestShieldingKeyRepo::new(shielding_key)); - let state_key_repo = Arc::new(TestStateKeyRepo::new(state_key)); - let parentchain_header = ParentchainHeaderBuilder::default().build(); - - let ocall_api = create_ocall_api(&parentchain_header, &signer); - - info!("Initializing state and shard.."); - let state_handler = Arc::new(TestStateHandler::default()); - let enclave_call_signer = enclave_call_signer(&shielding_key); - let (_, shard_id) = init_state(state_handler.as_ref(), enclave_call_signer.public().into()); - let shards = vec![shard_id]; - - let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadataMock::new())); - let stf_executor = Arc::new(TestStfExecutor::new( - ocall_api.clone(), - state_handler.clone(), - node_metadata_repo, - )); - let top_pool = create_top_pool(); - let (sender, _receiver) = std::sync::mpsc::sync_channel(1000); - - let enclave_metrics_ocall_mock = Arc::new(MetricsOCallMock::default()); - - let top_pool_author = Arc::new(TestTopPoolAuthor::new( - top_pool, - AllowAllTopsFilter::::new(), - DirectCallsOnlyFilter::::new(), - state_handler.clone(), - shielding_key_repo, - enclave_metrics_ocall_mock.clone(), - Arc::new(sender), - )); - let parentchain_block_import_trigger = Arc::new(TestParentchainBlockImportTrigger::default()); - let peer_updater_mock = Arc::new(PeerUpdaterMock {}); - let block_importer = Arc::new(TestBlockImporter::new( - state_handler.clone(), - state_key_repo.clone(), - top_pool_author.clone(), - parentchain_block_import_trigger.clone(), - ocall_api.clone(), - peer_updater_mock, - )); - let block_composer = Arc::new(TestBlockComposer::new(signer, state_key_repo)); - let proposer_environment = ProposerFactory::new( - top_pool_author, - stf_executor, - block_composer, - enclave_metrics_ocall_mock, - ); - - // Add some events to the state. - let topic_hash = H256::from([7; 32]); - let event = frame_system::Event::::CodeUpdated; - let (lock, mut state) = state_handler.load_for_mutation(&shard_id).unwrap(); - state.execute_with(|| { - set_block_number(10); - frame_system::Pallet::::deposit_event_indexed( - &[topic_hash], - ita_sgx_runtime::RuntimeEvent::System(event), - ) - }); - state_handler.write_after_mutation(state.clone(), lock, &shard_id).unwrap(); - - // Check if state now really contains events and topics. - let (mut state, _) = state_handler.load_cloned(&shard_id).unwrap(); - assert_eq!(TestStf::get_event_count(&mut state), 1); - assert_eq!(TestStf::get_events(&mut state).len(), 1); - assert_eq!(TestStf::get_event_topics(&mut state, &topic_hash).len(), 1); - - info!("Setup AURA SlotInfo"); - let timestamp = duration_now(); - let slot = slot_from_timestamp_and_duration(duration_now(), SLOT_DURATION); - let ends_at = timestamp + SLOT_DURATION; - let slot_info = SlotInfo::new( - slot, - timestamp, - SLOT_DURATION, - ends_at, - parentchain_header.clone(), - None, - None, - ); - - let scheduled_enclave = Arc::new(ScheduledEnclaveMock::default()); - info!("Executing AURA on slot.."); - let (blocks, opaque_calls) = - exec_aura_on_slot::<_, ParentchainBlock, SignedSidechainBlock, _, _, _, _, _, _, _>( - slot_info, - signer, - ocall_api, - parentchain_block_import_trigger, - None::>, - None::>, - proposer_environment, - shards, - scheduled_enclave, - state_handler.clone(), - ) - .unwrap(); - - info!("Executed AURA successfully. Sending blocks and extrinsics.."); - let propose_to_block_import_ocall_api = - Arc::new(ProposeToImportOCallApi::new(parentchain_header, block_importer)); - - send_blocks_and_extrinsics::( - blocks, - opaque_calls, - propose_to_block_import_ocall_api, - ) - .unwrap(); - - // Ensure events have been reset. - let (mut state, _) = state_handler.load_cloned(&shard_id).unwrap(); - assert_eq!(TestStf::get_event_count(&mut state), 0); - assert_eq!(TestStf::get_event_topics(&mut state, &topic_hash).len(), 0); - assert_eq!(TestStf::get_events(&mut state).len(), 0); -} diff --git a/bitacross-worker/enclave-runtime/src/test/teeracle_tests.rs b/bitacross-worker/enclave-runtime/src/test/teeracle_tests.rs deleted file mode 100644 index bd9a4c8391..0000000000 --- a/bitacross-worker/enclave-runtime/src/test/teeracle_tests.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use codec::alloc::string::ToString; -use ita_oracle::{ - create_coin_gecko_oracle, create_coin_market_cap_oracle, - oracles::exchange_rate_oracle::GetExchangeRate, types::TradingPair, -}; -use itp_test::mock::metrics_ocall_mock::MetricsOCallMock; -use std::sync::Arc; - -pub(super) fn test_verify_get_exchange_rate_from_coin_gecko_works() { - // Get the exchange rate - let trading_pair = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; - - let coin_gecko_oracle = create_coin_gecko_oracle(Arc::new(MetricsOCallMock::default())); - - let result = coin_gecko_oracle.get_exchange_rate(trading_pair.clone()); - assert!(result.is_ok()); -} - -/// Get exchange rate from coin market cap. Requires API key (therefore not suited for unit testing). -#[allow(unused)] -pub(super) fn test_verify_get_exchange_rate_from_coin_market_cap_works() { - // Get the exchange rate - let trading_pair = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; - - let coin_market_cap_oracle = - create_coin_market_cap_oracle(Arc::new(MetricsOCallMock::default())); - - let result = coin_market_cap_oracle.get_exchange_rate(trading_pair.clone()); - assert!(result.is_ok()); -} diff --git a/bitacross-worker/enclave-runtime/src/test/tests_main.rs b/bitacross-worker/enclave-runtime/src/test/tests_main.rs index 8632bfbeea..f677b9ec76 100644 --- a/bitacross-worker/enclave-runtime/src/test/tests_main.rs +++ b/bitacross-worker/enclave-runtime/src/test/tests_main.rs @@ -14,9 +14,6 @@ limitations under the License. */ -#[cfg(feature = "evm")] -use crate::test::evm_pallet_tests; - use crate::{ rpc, sync::tests::{enclave_rw_lock_works, sidechain_rw_lock_works}, @@ -26,22 +23,21 @@ use crate::{ fixtures::test_setup::{ enclave_call_signer, test_setup, TestStf, TestStfExecutor, TestTopPoolAuthor, }, - mocks::types::TestStateKeyRepo, - sidechain_aura_tests, sidechain_event_tests, state_getter_tests, top_pool_tests, + state_getter_tests, top_pool_tests, }, tls_ra, }; use codec::Decode; use ita_sgx_runtime::Parentchain; use ita_stf::{ - helpers::{account_key_hash, set_block_number}, + helpers::set_block_number, stf_sgx_tests, test_genesis::{endowed_account as funded_pair, unendowed_account}, - AccountInfo, Getter, State, TrustedCall, TrustedCallSigned, TrustedGetter, + Getter, State, TrustedCall, TrustedCallSigned, TrustedGetter, }; use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; use itp_sgx_crypto::{Aes, StateCrypto}; -use itp_sgx_externalities::{SgxExternalitiesDiffType, SgxExternalitiesTrait, StateHash}; +use itp_sgx_externalities::{SgxExternalitiesDiffType, SgxExternalitiesTrait}; use itp_stf_executor::{ executor_tests as stf_executor_tests, traits::StateUpdateProposer, BatchExecutionResult, }; @@ -57,18 +53,7 @@ use itp_stf_primitives::{ use itp_stf_state_handler::handle_state::HandleState; use itp_test::mock::handle_state_mock; use itp_top_pool_author::{test_utils::submit_operation_to_top_pool, traits::AuthorApi}; -use itp_types::{AccountId, Balance, Block, Header}; -use its_primitives::{ - traits::{ - Block as BlockTrait, BlockData, Header as SidechainHeaderTrait, - SignedBlock as SignedBlockTrait, - }, - types::block::SignedBlock, -}; -use its_sidechain::{ - block_composer::{BlockComposer, ComposeBlock}, - state::SidechainSystemExt, -}; +use itp_types::{AccountId, Header}; use litentry_primitives::Identity; use sgx_tunittest::*; use sgx_types::size_t; @@ -99,12 +84,17 @@ pub extern "C" fn test_main_entrance() -> size_t { itp_sgx_crypto::tests::using_get_ed25519_repository_twice_initializes_key_only_once, itp_sgx_crypto::tests::rsa3072_sealing_works, itp_sgx_crypto::tests::using_get_rsa3072_repository_twice_initializes_key_only_once, - test_compose_block, + itp_sgx_crypto::tests::ecdsa_creating_repository_with_same_path_and_prefix_results_in_same_key, + itp_sgx_crypto::tests::ecdsa_seal_init_should_create_new_key_if_not_present, + itp_sgx_crypto::tests::ecdsa_seal_init_should_not_change_key_if_exists, + itp_sgx_crypto::tests::ecdsa_sign_should_produce_valid_signature, + itp_sgx_crypto::tests::schnorr_creating_repository_with_same_path_and_prefix_results_in_same_key, + itp_sgx_crypto::tests::schnorr_seal_init_should_create_new_key_if_not_present, + itp_sgx_crypto::tests::schnorr_seal_init_should_not_change_key_if_exists, + itp_sgx_crypto::tests::schnorr_sign_should_produce_valid_signature, test_submit_trusted_call_to_top_pool, test_submit_trusted_getter_to_top_pool, test_differentiate_getter_and_call_works, - test_create_block_and_confirmation_works, - test_create_state_diff, test_executing_call_updates_account_nonce, test_call_set_update_parentchain_block, test_invalid_nonce_call_is_not_executed, @@ -140,10 +130,9 @@ pub extern "C" fn test_main_entrance() -> size_t { enclave_signer_tests::nonce_is_computed_correctly, state_getter_tests::state_getter_works, // sidechain integration tests - sidechain_aura_tests::produce_sidechain_block_and_import_it, - sidechain_event_tests::ensure_events_get_reset_upon_block_proposal, top_pool_tests::process_indirect_call_in_top_pool, - top_pool_tests::submit_shielding_call_to_top_pool, + // TODO: Litentry disables it for now (P-494) + // top_pool_tests::submit_shielding_call_to_top_pool, // tls_ra unit tests tls_ra::seal_handler::test::seal_shielding_key_works, tls_ra::seal_handler::test::seal_shielding_key_fails_for_invalid_key, @@ -158,9 +147,7 @@ pub extern "C" fn test_main_entrance() -> size_t { tls_ra::tests::test_tls_ra_server_client_networking, // RPC tests direct_rpc_tests::get_state_request_works, - - // EVM tests - run_evm_tests, + direct_rpc_tests::state_get_mrenclave_works, // light-client-test itc_parentchain::light_client::io::sgx_tests::init_parachain_light_client_works, @@ -171,63 +158,9 @@ pub extern "C" fn test_main_entrance() -> size_t { // ipfs::test_verification_ok_for_correct_content, // ipfs::test_verification_fails_for_incorrect_content, // test_ocall_read_write_ipfs, - - // Teeracle tests - run_teeracle_tests, ) } -#[cfg(feature = "teeracle")] -fn run_teeracle_tests() { - use super::teeracle_tests::*; - test_verify_get_exchange_rate_from_coin_gecko_works(); - // Disabled - requires API key, cannot run locally - //test_verify_get_exchange_rate_from_coin_market_cap_works(); -} - -#[cfg(not(feature = "teeracle"))] -fn run_teeracle_tests() {} - -#[cfg(feature = "evm")] -fn run_evm_tests() { - evm_pallet_tests::test_evm_call(); - evm_pallet_tests::test_evm_counter(); - evm_pallet_tests::test_evm_create(); - evm_pallet_tests::test_evm_create2(); -} -#[cfg(not(feature = "evm"))] -fn run_evm_tests() {} - -fn test_compose_block() { - // given - let (_, _, shard, _, _, state_handler, _) = test_setup(); - let block_composer = BlockComposer::::new( - test_account(), - Arc::new(TestStateKeyRepo::new(state_key())), - ); - - let signed_top_hashes: Vec = vec![[94; 32].into(), [1; 32].into()].to_vec(); - - let (mut state, _) = state_handler.load_cloned(&shard).unwrap(); - state.set_block_number(&1); - let state_hash_before_execution = state.hash(); - - // when - let signed_block = block_composer - .compose_block( - &latest_parentchain_header(), - signed_top_hashes, - shard, - state_hash_before_execution, - &state, - ) - .unwrap(); - - // then - assert!(signed_block.verify_signature()); - assert_eq!(signed_block.block().header().block_number(), 1); -} - fn test_submit_trusted_call_to_top_pool() { // given let (top_pool_author, _, shard, mrenclave, shielding_key, ..) = test_setup(); @@ -340,122 +273,6 @@ fn test_differentiate_getter_and_call_works() { ); } -fn test_create_block_and_confirmation_works() { - // given - let (top_pool_author, _, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); - - let block_composer = BlockComposer::::new( - test_account(), - Arc::new(TestStateKeyRepo::new(state_key())), - ); - - let sender = funded_pair(); - let receiver = unfunded_public(); - - let signed_call = TrustedCall::balance_transfer( - Identity::Substrate(sender.public().into()), - receiver.into(), - 1000, - ) - .sign(&sender.into(), 0, &mrenclave, &shard); - let trusted_operation = direct_top(signed_call); - - let (top_hash, _) = submit_operation_to_top_pool( - top_pool_author.as_ref(), - &trusted_operation, - &shielding_key, - shard, - false, - ) - .unwrap(); - - // when - let execution_result = execute_trusted_calls(&shard, stf_executor.as_ref(), &top_pool_author); - - let executed_operation_hashes = execution_result.get_executed_operation_hashes().to_vec(); - - let signed_block = block_composer - .compose_block( - &latest_parentchain_header(), - executed_operation_hashes, - shard, - execution_result.state_hash_before_execution, - &execution_result.state_after_execution, - ) - .unwrap(); - - // then - assert!(signed_block.verify_signature()); - assert_eq!(signed_block.block().header().block_number(), 1); - assert_eq!(signed_block.block().block_data().signed_top_hashes()[0], top_hash); -} - -fn test_create_state_diff() { - // given - let (top_pool_author, _, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); - - let block_composer = BlockComposer::::new( - test_account(), - Arc::new(TestStateKeyRepo::new(state_key())), - ); - - let sender = funded_pair(); - let receiver = unfunded_public(); - const TX_AMOUNT: Balance = 1_000_000_000_000; - let signed_call = TrustedCall::balance_transfer( - Identity::Substrate(sender.public().into()), - receiver.into(), - TX_AMOUNT, - ) - .sign(&sender.into(), 0, &mrenclave, &shard); - let trusted_operation = direct_top(signed_call); - - submit_operation_to_top_pool( - top_pool_author.as_ref(), - &trusted_operation, - &shielding_key, - shard, - false, - ) - .unwrap(); - - // when - let execution_result = execute_trusted_calls(&shard, stf_executor.as_ref(), &top_pool_author); - - let executed_operation_hashes = execution_result.get_executed_operation_hashes().to_vec(); - - let signed_block = block_composer - .compose_block( - &latest_parentchain_header(), - executed_operation_hashes, - shard, - execution_result.state_hash_before_execution, - &execution_result.state_after_execution, - ) - .unwrap(); - - let encrypted_state_diff = encrypted_state_diff_from_encrypted( - signed_block.block().block_data().encrypted_state_diff(), - ); - let state_diff = encrypted_state_diff.state_update(); - - // then - let sender_acc_info: AccountInfo = - get_from_state_diff(state_diff, &account_key_hash::(&sender.public().into())); - - let receiver_acc_info: AccountInfo = - get_from_state_diff(state_diff, &account_key_hash::(&receiver.into())); - - // state diff should consist of the following updates: - // (last_hash, sidechain block_number, sender_funds, receiver_funds, fee_recipient account [no clear, after polkadot_v0.9.26 update], events, frame_system::LastRuntimeUpgradeInfo,) - assert_eq!(state_diff.len(), 8); - assert_eq!(receiver_acc_info.data.free, TX_AMOUNT); - assert_eq!( - sender_acc_info.data.free, - ita_stf::test_genesis::ENDOWED_ACC_FUNDS - TX_AMOUNT - ita_stf::STF_TX_FEE - ); -} - fn test_executing_call_updates_account_nonce() { // given let (top_pool_author, _, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); @@ -755,10 +572,7 @@ fn execute_trusted_calls( &latest_parentchain_header(), shard, Duration::from_millis(600), - |mut s| { - s.set_block_number(&s.get_block_number().map_or(1, |n| n + 1)); - s - }, + |s| s, ) .unwrap() } diff --git a/bitacross-worker/enclave-runtime/src/test/top_pool_tests.rs b/bitacross-worker/enclave-runtime/src/test/top_pool_tests.rs index 22776fbd39..03362680d7 100644 --- a/bitacross-worker/enclave-runtime/src/test/top_pool_tests.rs +++ b/bitacross-worker/enclave-runtime/src/test/top_pool_tests.rs @@ -22,53 +22,32 @@ use crate::test::{ create_ocall_api, create_top_pool, encrypt_trusted_operation, sign_trusted_call, }, initialize_test_state::init_state, - test_setup::TestStf, }, mocks::types::{ TestShieldingKey, TestShieldingKeyRepo, TestSigner, TestStateHandler, TestTopPoolAuthor, }, }; -use codec::Encode; -use ita_parentchain_interface::integritee; use ita_stf::{ test_genesis::{endowed_account, unendowed_account}, Getter, TrustedCall, TrustedCallSigned, }; -use itc_parentchain::indirect_calls_executor::{ - mock::TestEventCreator, ExecuteIndirectCalls, IndirectCallsExecutor, -}; -use itc_parentchain_test::{ - parentchain_block_builder::ParentchainBlockBuilder, - parentchain_header_builder::ParentchainHeaderBuilder, -}; -use itp_node_api::{ - api_client::{ - ExtrinsicParams, ParentchainAdditionalParams, ParentchainExtrinsicParams, - ParentchainUncheckedExtrinsic, - }, - metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}, -}; -use itp_node_api_metadata::pallet_teerex::TeerexCallIndexes; +use itc_parentchain_test::ParentchainHeaderBuilder; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_sgx_crypto::ShieldingCryptoEncrypt; -use itp_stf_executor::enclave_signer::StfEnclaveSigner; -use itp_stf_primitives::{traits::TrustedCallVerification, types::TrustedOperation}; -use itp_stf_state_observer::mock::ObserveStateMock; +use itp_stf_primitives::types::TrustedOperation; use itp_test::mock::metrics_ocall_mock::MetricsOCallMock; use itp_top_pool_author::{ top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}, traits::AuthorApi, }; -use itp_types::{ - parentchain::Address, AccountId, Block, RsaRequest, ShardIdentifier, ShieldFundsFn, H256, -}; +use itp_types::{RsaRequest, ShardIdentifier}; use jsonrpc_core::futures::executor; use litentry_primitives::Identity; use log::*; use sgx_crypto_helper::RsaKeyPair; -use sp_core::{ed25519, Pair}; -use sp_runtime::{MultiSignature, OpaqueExtrinsic}; +use sp_core::Pair; use std::{sync::Arc, vec::Vec}; + pub fn process_indirect_call_in_top_pool() { let _ = env_logger::builder().is_test(true).try_init(); info!("Setting up test."); @@ -107,6 +86,9 @@ pub fn process_indirect_call_in_top_pool() { assert_eq!(1, top_pool_author.get_pending_trusted_calls(shard_id).len()); } +/* +// TODO: use our trusted call for testing - see P-494 + pub fn submit_shielding_call_to_top_pool() { let _ = env_logger::builder().is_test(true).try_init(); @@ -150,7 +132,7 @@ pub fn submit_shielding_call_to_top_pool() { _, _, _, - integritee::ShieldFundsAndInvokeFilter, + integritee::BitAcrossIndirectCallsFilter, TestEventCreator, integritee::ParentchainEventHandler, TrustedCallSigned, @@ -172,6 +154,8 @@ pub fn submit_shielding_call_to_top_pool() { assert!(trusted_call.verify_signature(&mr_enclave.m, &shard_id)); } +*/ + fn encrypted_indirect_call< AttestationApi: EnclaveAttestationOCallApi, ShieldingKey: ShieldingCryptoEncrypt, @@ -194,11 +178,11 @@ fn encrypted_indirect_call< encrypt_trusted_operation(shielding_key, &trusted_operation) } -fn create_shielding_call_extrinsic( - shard: ShardIdentifier, - shielding_key: &ShieldingKey, +/* +fn create_opaque_call_extrinsic( + _shard: ShardIdentifier, + _shielding_key: &ShieldingKey, ) -> Block { - let target_account = shielding_key.encrypt(&AccountId::new([2u8; 32]).encode()).unwrap(); let test_signer = ed25519::Pair::from_seed(b"33345678901234567890123456789012"); let signature = test_signer.sign(&[0u8]); @@ -212,15 +196,10 @@ fn create_shielding_call_extrinsic( let dummy_node_metadata = NodeMetadataMock::new(); - let shield_funds_indexes = dummy_node_metadata.shield_funds_call_indexes().unwrap(); + let call_index = dummy_node_metadata.post_opaque_task_call_indexes().unwrap(); let opaque_extrinsic = OpaqueExtrinsic::from_bytes( - ParentchainUncheckedExtrinsic::::new_signed( - ( - shield_funds_indexes, - target_account, - ita_stf::test_genesis::SECOND_ENDOWED_ACC_FUNDS, - shard, - ), + ParentchainUncheckedExtrinsic::::new_signed( + (call_index, RsaRequest::default()), Address::Address32([1u8; 32]), MultiSignature::Ed25519(signature), default_extra_for_test.signed_extra(), @@ -234,3 +213,4 @@ fn create_shielding_call_extrinsic( .with_extrinsics(vec![opaque_extrinsic]) .build() } +*/ diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/tests.rs b/bitacross-worker/enclave-runtime/src/tls_ra/tests.rs index 5cdbd2a184..eb83438d74 100644 --- a/bitacross-worker/enclave-runtime/src/tls_ra/tests.rs +++ b/bitacross-worker/enclave-runtime/src/tls_ra/tests.rs @@ -27,7 +27,6 @@ use crate::{ }; use ita_stf::State; use itc_parentchain::light_client::mocks::validator_mock_seal::LightValidationStateSealMock; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; use itp_sgx_crypto::{mocks::KeyRepositoryMock, Aes}; use itp_stf_interface::InitState; use itp_stf_primitives::types::AccountId; @@ -55,7 +54,7 @@ fn run_state_provisioning_server(seal_handler: impl UnsealStateAndKeys, port: u1 let (socket, _addr) = listener.accept().unwrap(); let sgx_target_info: sgx_target_info_t = sgx_target_info_t::default(); - run_state_provisioning_server_internal::<_, WorkerModeProvider>( + run_state_provisioning_server_internal::<_>( socket.as_raw_fd(), SIGN_TYPE, Some(&sgx_target_info), @@ -128,14 +127,8 @@ pub fn test_tls_ra_server_client_networking() { assert_eq!(*client_shielding_key.read().unwrap(), shielding_key_encoded); assert_eq!(*client_light_client_state.read().unwrap(), light_client_state_encoded); - // State and state-key are provisioned only in sidechain mode - if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain { - assert_eq!(*client_state.read().unwrap(), state_encoded); - assert_eq!(*client_state_key.read().unwrap(), state_key_encoded); - } else { - assert_eq!(*client_state.read().unwrap(), initial_client_state); - assert_eq!(*client_state_key.read().unwrap(), initial_client_state_key); - } + assert_eq!(*client_state.read().unwrap(), initial_client_state); + assert_eq!(*client_state_key.read().unwrap(), initial_client_state_key); } // Test state and key provisioning with 'real' data structures. diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs b/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs index 33f72e9095..b72347afb2 100644 --- a/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -34,8 +34,8 @@ use codec::Decode; use itp_attestation_handler::RemoteAttestationType; use itp_component_container::ComponentGetter; use itp_ocall_api::EnclaveAttestationOCallApi; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; use itp_types::ShardIdentifier; +use litentry_primitives::WorkerMode; use log::*; use rustls::{ServerConfig, ServerSession, StreamOwned}; use sgx_types::*; @@ -55,8 +55,7 @@ enum ProvisioningPayload { impl From for ProvisioningPayload { fn from(m: WorkerMode) -> Self { match m { - WorkerMode::OffChainWorker | WorkerMode::Teeracle => - ProvisioningPayload::ShieldingKeyAndLightClient, + WorkerMode::OffChainWorker => ProvisioningPayload::ShieldingKeyAndLightClient, WorkerMode::Sidechain => ProvisioningPayload::Everything, } } @@ -232,7 +231,7 @@ pub unsafe extern "C" fn run_state_provisioning_server( light_client_seal, ); - if let Err(e) = run_state_provisioning_server_internal::<_, WorkerModeProvider>( + if let Err(e) = run_state_provisioning_server_internal::<_>( socket_fd, sign_type, quoting_enclave_target_info, @@ -248,10 +247,7 @@ pub unsafe extern "C" fn run_state_provisioning_server( } /// Internal [`run_state_provisioning_server`] function to be able to use the handy `?` operator. -pub(crate) fn run_state_provisioning_server_internal< - StateAndKeyUnsealer: UnsealStateAndKeys, - WorkerModeProvider: ProvideWorkerMode, ->( +pub(crate) fn run_state_provisioning_server_internal( socket_fd: c_int, sign_type: sgx_quote_sign_type_t, quoting_enclave_target_info: Option<&sgx_target_info_t>, @@ -268,7 +264,7 @@ pub(crate) fn run_state_provisioning_server_internal< )?; let (server_session, tcp_stream) = tls_server_session_stream(socket_fd, server_config)?; - let provisioning = ProvisioningPayload::from(WorkerModeProvider::worker_mode()); + let provisioning = ProvisioningPayload::ShieldingKeyAndLightClient; let mut server = TlsServer::new(StreamOwned::new(server_session, tcp_stream), seal_handler, provisioning); diff --git a/bitacross-worker/enclave-runtime/src/top_pool_execution.rs b/bitacross-worker/enclave-runtime/src/top_pool_execution.rs deleted file mode 100644 index a8168864e3..0000000000 --- a/bitacross-worker/enclave-runtime/src/top_pool_execution.rs +++ /dev/null @@ -1,412 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - error::Result, - initialization::global_components::{ - GLOBAL_OCALL_API_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT, - GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT, - GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, - GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_TOP_POOL_AUTHOR_COMPONENT, - }, - sync::{EnclaveLock, EnclaveStateRWLock}, - utils::{ - get_extrinsic_factory_from_integritee_solo_or_parachain, - get_extrinsic_factory_from_target_a_solo_or_parachain, - get_extrinsic_factory_from_target_b_solo_or_parachain, - get_stf_executor_from_solo_or_parachain, - get_triggered_dispatcher_from_integritee_solo_or_parachain, - get_triggered_dispatcher_from_target_a_solo_or_parachain, - get_triggered_dispatcher_from_target_b_solo_or_parachain, - get_validator_accessor_from_integritee_solo_or_parachain, - get_validator_accessor_from_target_a_solo_or_parachain, - get_validator_accessor_from_target_b_solo_or_parachain, - }, -}; -use codec::Encode; -use itc_parentchain::{ - block_import_dispatcher::triggered_dispatcher::TriggerParentchainBlockImport, - light_client::{ - concurrent_access::ValidatorAccess, BlockNumberOps, ExtrinsicSender, LightClientState, - NumberFor, - }, -}; -use itp_component_container::ComponentGetter; -use itp_enclave_metrics::EnclaveMetric; -use itp_extrinsics_factory::CreateExtrinsics; -use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveOnChainOCallApi, EnclaveSidechainOCallApi}; -use itp_settings::sidechain::SLOT_DURATION; -use itp_sgx_crypto::key_repository::AccessKey; -use itp_sgx_externalities::SgxExternalities; -use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; -use itp_time_utils::duration_now; -use itp_types::{parentchain::ParentchainCall, Block, OpaqueCall, H256}; -use itp_utils::if_not_production; -use its_primitives::{ - traits::{ - Block as SidechainBlockTrait, Header as HeaderTrait, ShardIdentifierFor, SignedBlock, - }, - types::block::SignedBlock as SignedSidechainBlock, -}; -use its_sidechain::{ - aura::{proposer_factory::ProposerFactory, Aura, SlotClaimStrategy}, - consensus_common::{Environment, Error as ConsensusError, ProcessBlockImportQueue}, - slots::{yield_next_slot, LastSlot, PerShardSlotWorkerScheduler, SlotInfo}, - validateer_fetch::ValidateerFetch, -}; -use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; -use log::*; -use sgx_types::sgx_status_t; -use sp_core::{crypto::UncheckedFrom, Pair}; -use sp_runtime::{ - generic::SignedBlock as SignedParentchainBlock, traits::Block as BlockTrait, MultiSignature, -}; -use std::{sync::Arc, time::Instant, vec::Vec}; - -#[no_mangle] -pub unsafe extern "C" fn execute_trusted_calls() -> sgx_status_t { - if let Err(e) = execute_top_pool_trusted_calls_internal() { - return e.into() - } - - sgx_status_t::SGX_SUCCESS -} - -/// Internal [`execute_trusted_calls`] function to be able to use the `?` operator. -/// -/// Executes `Aura::on_slot() for `slot` if it is this enclave's `Slot`. -/// -/// This function makes an ocall that does the following: -/// -/// * Import all pending parentchain blocks. -/// * Sends sidechain `confirm_block` xt's with the produced sidechain blocks. -/// * Broadcast produced sidechain blocks to peer validateers. -fn execute_top_pool_trusted_calls_internal() -> Result<()> { - let start_time = Instant::now(); - - debug!("----------------------------------------"); - debug!("Start sidechain block production cycle"); - - // We acquire lock explicitly (variable binding), since '_' will drop the lock after the statement. - // See https://medium.com/codechain/rust-underscore-does-not-bind-fec6a18115a8 - let _enclave_write_lock = EnclaveLock::write_all()?; - - let slot_beginning_timestamp = duration_now(); - - let integritee_parentchain_import_dispatcher = - get_triggered_dispatcher_from_integritee_solo_or_parachain()?; - let maybe_target_a_parentchain_import_dispatcher = - get_triggered_dispatcher_from_target_a_solo_or_parachain().ok(); - let maybe_target_b_parentchain_import_dispatcher = - get_triggered_dispatcher_from_target_b_solo_or_parachain().ok(); - - let maybe_latest_target_a_parentchain_header = - if let Some(ref _triggered_dispatcher) = maybe_target_a_parentchain_import_dispatcher { - let validator_access = get_validator_accessor_from_target_a_solo_or_parachain()?; - Some(validator_access.execute_on_validator(|v| { - let latest_parentchain_header = v.latest_finalized_header()?; - Ok(latest_parentchain_header) - })?) - } else { - None - }; - - let maybe_latest_target_b_parentchain_header = - if let Some(ref _triggered_dispatcher) = maybe_target_b_parentchain_import_dispatcher { - let validator_access = get_validator_accessor_from_target_b_solo_or_parachain()?; - Some(validator_access.execute_on_validator(|v| { - let latest_parentchain_header = v.latest_finalized_header()?; - Ok(latest_parentchain_header) - })?) - } else { - None - }; - - let integritee_validator_access = get_validator_accessor_from_integritee_solo_or_parachain()?; - - // This gets the latest imported block. We accept that all of AURA, up until the block production - // itself, will operate on a parentchain block that is potentially outdated by one block - // (in case we have a block in the queue, but not imported yet). - let current_integritee_parentchain_header = - integritee_validator_access.execute_on_validator(|v| { - let latest_parentchain_header = v.latest_finalized_header()?; - Ok(latest_parentchain_header) - })?; - - // Import any sidechain blocks that are in the import queue. In case we are missing blocks, - // a peer sync will happen. If that happens, the slot time might already be used up just by this import. - let sidechain_block_import_queue_worker = - GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT.get()?; - - let latest_integritee_parentchain_header = sidechain_block_import_queue_worker - .process_queue(¤t_integritee_parentchain_header)?; - - trace!( - "Elapsed time to process sidechain block import queue: {} ms", - start_time.elapsed().as_millis() - ); - - let stf_executor = get_stf_executor_from_solo_or_parachain()?; - - let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; - - let block_composer = GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT.get()?; - - let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; - - let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; - - let authority = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; - - let fail_on_demand = GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT.get()?; - - match yield_next_slot( - slot_beginning_timestamp, - SLOT_DURATION, - latest_integritee_parentchain_header, - maybe_latest_target_a_parentchain_header, - maybe_latest_target_b_parentchain_header, - &mut LastSlot, - )? { - Some(slot) => { - if slot.duration_remaining().is_none() { - warn!("No time remaining in slot, skipping AURA execution"); - return Ok(()) - } - log_remaining_slot_duration(&slot, "Before AURA"); - - let shards = state_handler.list_shards()?; - let env = ProposerFactory::::new( - top_pool_author, - stf_executor, - block_composer, - ocall_api.clone(), - ); - - if_not_production!({ - if let Some(ref fail_on_demand) = *fail_on_demand { - fail_on_demand.next_slot(); - if fail_on_demand.check_before_on_slot() { - Result::Err(crate::error::Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED))?; - } - } - }); - - let (blocks, parentchain_calls) = - exec_aura_on_slot::<_, _, SignedSidechainBlock, _, _, _, _, _, _, _>( - slot.clone(), - authority, - ocall_api.clone(), - integritee_parentchain_import_dispatcher, - maybe_target_a_parentchain_import_dispatcher, - maybe_target_b_parentchain_import_dispatcher, - env, - shards, - GLOBAL_SCHEDULED_ENCLAVE.clone(), - state_handler, - )?; - - if_not_production!({ - if let Some(ref fail_on_demand) = *fail_on_demand { - if fail_on_demand.check_after_on_slot() { - Result::Err(crate::error::Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED))?; - } - } - }); - - debug!("Aura executed successfully"); - - // Drop lock as soon as we don't need it anymore. - drop(_enclave_write_lock); - - log_remaining_slot_duration(&slot, "After AURA"); - - send_blocks_and_extrinsics::(blocks, parentchain_calls, ocall_api)?; - - log_remaining_slot_duration(&slot, "After broadcasting and sending extrinsic"); - }, - None => { - debug!("No slot yielded. Skipping block production."); - return Ok(()) - }, - }; - - debug!("End sidechain block production cycle"); - Ok(()) -} - -/// Executes aura for the given `slot`. -#[allow(clippy::too_many_arguments)] -pub(crate) fn exec_aura_on_slot< - Authority, - ParentchainBlock, - SignedSidechainBlock, - OCallApi, - PEnvironment, - IntegriteeBlockImportTrigger, - TargetABlockImportTrigger, - TargetBBlockImportTrigger, - ScheduledEnclave, - StateHandler, ->( - slot: SlotInfo, - authority: Authority, - ocall_api: Arc, - integritee_block_import_trigger: Arc, - maybe_target_a_block_import_trigger: Option>, - maybe_target_b_block_import_trigger: Option>, - proposer_environment: PEnvironment, - shards: Vec>, - scheduled_enclave: Arc, - state_handler: Arc, -) -> Result<(Vec, Vec)> -where - ParentchainBlock: BlockTrait, - SignedSidechainBlock: - SignedBlock + 'static, // Setting the public type is necessary due to some non-generic downstream code. - SignedSidechainBlock::Block: SidechainBlockTrait, - <::Block as SidechainBlockTrait>::HeaderType: - HeaderTrait, - SignedSidechainBlock::Signature: From, - Authority: Pair, - Authority::Public: Encode + UncheckedFrom<[u8; 32]>, - OCallApi: ValidateerFetch + EnclaveOnChainOCallApi + EnclaveSidechainOCallApi + Send + 'static, - NumberFor: BlockNumberOps, - PEnvironment: - Environment + Send + Sync, - IntegriteeBlockImportTrigger: - TriggerParentchainBlockImport>, - TargetABlockImportTrigger: - TriggerParentchainBlockImport>, - TargetBBlockImportTrigger: - TriggerParentchainBlockImport>, - ScheduledEnclave: ScheduledEnclaveUpdater, - StateHandler: HandleState, -{ - debug!("[Aura] Executing aura for slot: {:?}", slot); - - let mut aura = - Aura::<_, ParentchainBlock, SignedSidechainBlock, PEnvironment, _, _, _, _, _, _>::new( - authority, - ocall_api.as_ref().clone(), - integritee_block_import_trigger, - maybe_target_a_block_import_trigger, - maybe_target_b_block_import_trigger, - proposer_environment, - scheduled_enclave, - state_handler, - ) - .with_claim_strategy(SlotClaimStrategy::RoundRobin); - - // We only check if there are more workers registered, which might not really mean they are - // online and syncing sidechain state but that should be enough for now. - let is_single_worker = match ocall_api.get_trusted_peers_urls() { - Ok(urls) => urls.is_empty(), - Err(e) => { - warn!("Could not get trusted peers urls, error: {:?}", e); - warn!("Falling back to non single worker mode"); - false - }, - }; - - let (blocks, pxts): (Vec<_>, Vec<_>) = - PerShardSlotWorkerScheduler::on_slot(&mut aura, slot, shards, is_single_worker) - .into_iter() - .map(|r| (r.block, r.parentchain_effects)) - .unzip(); - - let opaque_calls: Vec = pxts.into_iter().flatten().collect(); - Ok((blocks, opaque_calls)) -} - -/// Broadcasts sidechain blocks to fellow peers and sends opaque calls as extrinsic to the parentchain. -pub(crate) fn send_blocks_and_extrinsics( - blocks: Vec, - parentchain_calls: Vec, - ocall_api: Arc, -) -> Result<()> -where - ParentchainBlock: BlockTrait, - SignedSidechainBlock: SignedBlock + 'static, - OCallApi: EnclaveSidechainOCallApi + EnclaveMetricsOCallApi, - NumberFor: BlockNumberOps, -{ - let started = std::time::Instant::now(); - debug!("Proposing {} sidechain block(s) (broadcasting to peers)", blocks.len()); - ocall_api.propose_sidechain_blocks(blocks)?; - if let Err(e) = - ocall_api.update_metric(EnclaveMetric::SidechainBlockBroadcastingTime(started.elapsed())) - { - warn!("Failed to update metric for sidechain block broadcasting time: {:?}", e); - }; - - let calls: Vec = parentchain_calls - .iter() - .filter_map(|parentchain_call| parentchain_call.as_litentry()) - .collect(); - debug!("Enclave wants to send {} extrinsics to Integritee Parentchain", calls.len()); - if !calls.is_empty() { - let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; - let xts = extrinsics_factory.create_extrinsics(calls.as_slice(), None)?; - let validator_access = get_validator_accessor_from_integritee_solo_or_parachain()?; - validator_access.execute_mut_on_validator(|v| v.send_extrinsics(xts))?; - } - let calls: Vec = parentchain_calls - .iter() - .filter_map(|parentchain_call| parentchain_call.as_target_a()) - .collect(); - debug!("Enclave wants to send {} extrinsics to TargetA Parentchain", calls.len()); - if !calls.is_empty() { - let extrinsics_factory = get_extrinsic_factory_from_target_a_solo_or_parachain()?; - let xts = extrinsics_factory.create_extrinsics(calls.as_slice(), None)?; - let validator_access = get_validator_accessor_from_target_a_solo_or_parachain()?; - validator_access.execute_mut_on_validator(|v| v.send_extrinsics(xts))?; - } - let calls: Vec = parentchain_calls - .iter() - .filter_map(|parentchain_call| parentchain_call.as_target_b()) - .collect(); - debug!("Enclave wants to send {} extrinsics to TargetB Parentchain", calls.len()); - if !calls.is_empty() { - let extrinsics_factory = get_extrinsic_factory_from_target_b_solo_or_parachain()?; - let xts = extrinsics_factory.create_extrinsics(calls.as_slice(), None)?; - let validator_access = get_validator_accessor_from_target_b_solo_or_parachain()?; - validator_access.execute_mut_on_validator(|v| v.send_extrinsics(xts))?; - } - - Ok(()) -} - -fn log_remaining_slot_duration>( - slot_info: &SlotInfo, - stage_name: &str, -) { - match slot_info.duration_remaining() { - None => { - info!("No time remaining in slot (id: {:?}, stage: {})", slot_info.slot, stage_name); - }, - Some(remainder) => { - trace!( - "Remaining time in slot (id: {:?}, stage {}): {} ms, {}% of slot time", - slot_info.slot, - stage_name, - remainder.as_millis(), - (remainder.as_millis() as f64 / slot_info.duration.as_millis() as f64) * 100f64 - ); - }, - }; -} diff --git a/bitacross-worker/enclave-runtime/src/utils.rs b/bitacross-worker/enclave-runtime/src/utils.rs index 47ff73ce26..640ec99e88 100644 --- a/bitacross-worker/enclave-runtime/src/utils.rs +++ b/bitacross-worker/enclave-runtime/src/utils.rs @@ -18,11 +18,7 @@ use crate::{ error::{Error, Result}, initialization::global_components::{ EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveStfEnclaveSigner, - EnclaveStfExecutor, EnclaveValidatorAccessor, - IntegriteeParentchainTriggeredBlockImportDispatcher, - TargetAParentchainTriggeredBlockImportDispatcher, - TargetBParentchainTriggeredBlockImportDispatcher, - GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, + EnclaveValidatorAccessor, GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, @@ -65,65 +61,6 @@ unsafe impl DecodeRaw for D { } } -pub unsafe fn utf8_str_from_raw<'a>( - data: *const u8, - len: usize, -) -> StdResult<&'a str, std::str::Utf8Error> { - let bytes = slice::from_raw_parts(data, len); - - std::str::from_utf8(bytes) -} - -// FIXME: When solving #1080, these helper functions should be obsolete, because no dynamic allocation -// is necessary anymore. -pub(crate) fn get_triggered_dispatcher_from_integritee_solo_or_parachain( -) -> Result> { - let dispatcher = - if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { - get_triggered_dispatcher(solochain_handler.import_dispatcher.clone())? - } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { - get_triggered_dispatcher(parachain_handler.import_dispatcher.clone())? - } else { - return Err(Error::NoLitentryParentchainAssigned) - }; - Ok(dispatcher) -} - -pub(crate) fn get_triggered_dispatcher_from_target_a_solo_or_parachain( -) -> Result> { - let dispatcher = - if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { - get_triggered_dispatcher(solochain_handler.import_dispatcher.clone())? - } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { - get_triggered_dispatcher(parachain_handler.import_dispatcher.clone())? - } else { - return Err(Error::NoTargetAParentchainAssigned) - }; - Ok(dispatcher) -} - -pub(crate) fn get_triggered_dispatcher_from_target_b_solo_or_parachain( -) -> Result> { - let dispatcher = - if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { - get_triggered_dispatcher(solochain_handler.import_dispatcher.clone())? - } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { - get_triggered_dispatcher(parachain_handler.import_dispatcher.clone())? - } else { - return Err(Error::NoTargetBParentchainAssigned) - }; - Ok(dispatcher) -} - -pub(crate) fn get_triggered_dispatcher( - dispatcher: Arc>, -) -> Result> { - let triggered_dispatcher = dispatcher - .triggered_dispatcher() - .ok_or(Error::ExpectedTriggeredImportDispatcher)?; - Ok(triggered_dispatcher) -} - pub(crate) fn get_validator_accessor_from_integritee_solo_or_parachain( ) -> Result> { let validator_accessor = @@ -137,32 +74,6 @@ pub(crate) fn get_validator_accessor_from_integritee_solo_or_parachain( Ok(validator_accessor) } -pub(crate) fn get_validator_accessor_from_target_a_solo_or_parachain( -) -> Result> { - let validator_accessor = - if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { - solochain_handler.validator_accessor.clone() - } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { - parachain_handler.validator_accessor.clone() - } else { - return Err(Error::NoTargetAParentchainAssigned) - }; - Ok(validator_accessor) -} - -pub(crate) fn get_validator_accessor_from_target_b_solo_or_parachain( -) -> Result> { - let validator_accessor = - if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { - solochain_handler.validator_accessor.clone() - } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { - parachain_handler.validator_accessor.clone() - } else { - return Err(Error::NoTargetBParentchainAssigned) - }; - Ok(validator_accessor) -} - pub(crate) fn get_node_metadata_repository_from_integritee_solo_or_parachain( ) -> Result> { let metadata_repository = @@ -241,18 +152,6 @@ pub(crate) fn get_extrinsic_factory_from_target_b_solo_or_parachain( Ok(extrinsics_factory) } -pub(crate) fn get_stf_executor_from_solo_or_parachain() -> Result> { - let stf_executor = - if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { - solochain_handler.stf_executor.clone() - } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { - parachain_handler.stf_executor.clone() - } else { - return Err(Error::NoLitentryParentchainAssigned) - }; - Ok(stf_executor) -} - pub(crate) fn get_stf_enclave_signer_from_solo_or_parachain() -> Result> { let stf_enclave_signer = diff --git a/bitacross-worker/litentry/core/direct-call/Cargo.toml b/bitacross-worker/litentry/core/direct-call/Cargo.toml new file mode 100644 index 0000000000..ba8a61b8c4 --- /dev/null +++ b/bitacross-worker/litentry/core/direct-call/Cargo.toml @@ -0,0 +1,49 @@ +[package] +authors = ["Trust Computing GmbH "] +edition = "2021" +name = "lc-direct-call" +version = "0.1.0" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } + +# internal dependencies +bc-relayer-registry = { path = "../../../bitacross/core/bc-relayer-registry", default-features = false } +itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } +itp-stf-primitives = { path = "../../../core-primitives/stf-primitives", default-features = false } +litentry-primitives = { path = "../../primitives", default-features = false } +parentchain-primitives = { package = "core-primitives", path = "../../../../primitives/core", default-features = false } + +# sgx dependencies +sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master", optional = true } + +[dev-dependencies] +k256 = { version = "0.13.3", features = ["ecdsa-core", "schnorr"] } +rand = { version = "0.7" } +hex = { version = "0.4" } + +[features] +default = ["std"] +production = [ + "parentchain-primitives/production", +] +sgx = [ + "sgx_tstd", + "bc-relayer-registry/sgx", + "litentry-primitives/sgx", + "itp-sgx-crypto/sgx", +] +std = [ + "bc-relayer-registry/std", + "itp-stf-primitives/std", + "itp-sgx-crypto/std", + "litentry-primitives/std", + "sp-core/std", + "sp-io/std", + "parentchain-primitives/std", +] +test = [ + "itp-sgx-crypto/mocks", +] diff --git a/bitacross-worker/litentry/core/direct-call/src/handler/mod.rs b/bitacross-worker/litentry/core/direct-call/src/handler/mod.rs new file mode 100644 index 0000000000..95984698bb --- /dev/null +++ b/bitacross-worker/litentry/core/direct-call/src/handler/mod.rs @@ -0,0 +1,2 @@ +pub mod sign_bitcoin; +pub mod sign_ethereum; diff --git a/bitacross-worker/litentry/core/direct-call/src/handler/sign_bitcoin.rs b/bitacross-worker/litentry/core/direct-call/src/handler/sign_bitcoin.rs new file mode 100644 index 0000000000..b8065fcf03 --- /dev/null +++ b/bitacross-worker/litentry/core/direct-call/src/handler/sign_bitcoin.rs @@ -0,0 +1,70 @@ +use bc_relayer_registry::RelayerRegistryLookup; +use itp_sgx_crypto::{key_repository::AccessKey, schnorr::Pair}; +use parentchain_primitives::Identity; +use std::{ + string::{String, ToString}, + vec::Vec, +}; + +pub fn handle>( + signer: Identity, + payload: Vec, + relayer_registry: &RRL, + key_repository: &BKR, +) -> Result<[u8; 64], String> { + if relayer_registry.contains_key(signer) { + let key = key_repository.retrieve_key().unwrap(); + Ok(key.sign(&payload).unwrap()) + } else { + Err("Unauthorized: Signer is not a valid relayer".to_string()) + } +} + +#[cfg(test)] +pub mod test { + use crate::handler::sign_bitcoin::handle; + use bc_relayer_registry::{RelayerRegistry, RelayerRegistryUpdater}; + use itp_sgx_crypto::mocks::KeyRepositoryMock; + use k256::elliptic_curve::rand_core; + use parentchain_primitives::Identity; + use sp_core::{sr25519, Pair}; + + #[test] + pub fn it_should_return_ok_for_relayer_signer() { + //given + let relayer_registry = RelayerRegistry::default(); + let alice_key_pair = sr25519::Pair::from_string("//Alice", None).unwrap(); + let relayer_account = Identity::Substrate(alice_key_pair.public().into()); + relayer_registry.update(relayer_account.clone()).unwrap(); + + let private = k256::schnorr::SigningKey::random(&mut rand_core::OsRng); + let signing_key = itp_sgx_crypto::schnorr::Pair::new(private); + + let key_repository = KeyRepositoryMock::new(signing_key); + + //when + let result = handle(relayer_account, vec![], &relayer_registry, &key_repository); + + //then + assert!(result.is_ok()) + } + + #[test] + pub fn it_should_return_err_for_non_relayer_signer() { + //given + let relayer_registry = RelayerRegistry::default(); + let alice_key_pair = sr25519::Pair::from_string("//Alice", None).unwrap(); + let non_relayer_account = Identity::Substrate(alice_key_pair.public().into()); + + let private = k256::schnorr::SigningKey::random(&mut rand_core::OsRng); + let signing_key = itp_sgx_crypto::schnorr::Pair::new(private); + + let key_repository = KeyRepositoryMock::new(signing_key); + + //when + let result = handle(non_relayer_account, vec![], &relayer_registry, &key_repository); + + //then + assert!(result.is_err()) + } +} diff --git a/bitacross-worker/litentry/core/direct-call/src/handler/sign_ethereum.rs b/bitacross-worker/litentry/core/direct-call/src/handler/sign_ethereum.rs new file mode 100644 index 0000000000..254826ba3e --- /dev/null +++ b/bitacross-worker/litentry/core/direct-call/src/handler/sign_ethereum.rs @@ -0,0 +1,90 @@ +use crate::PrehashedEthereumMessage; +use bc_relayer_registry::RelayerRegistryLookup; +use itp_sgx_crypto::{ecdsa::Pair, key_repository::AccessKey}; +use parentchain_primitives::Identity; +use std::{ + format, + string::{String, ToString}, +}; + +pub fn handle>( + signer: Identity, + msg: PrehashedEthereumMessage, + relayer_registry: &RRL, + key_repository: &EKR, +) -> Result<[u8; 65], String> { + if relayer_registry.contains_key(signer) { + let key = key_repository.retrieve_key().map_err(|e| format!("{}", e))?; + let sig = key.sign_prehash_recoverable(&msg).map_err(|e| format!("{}", e))?; + Ok(sig) + } else { + Err("Unauthorized: Signer is not a valid relayer".to_string()) + } +} + +#[cfg(test)] +pub mod test { + use crate::handler::sign_ethereum::handle; + use bc_relayer_registry::{RelayerRegistry, RelayerRegistryUpdater}; + use itp_sgx_crypto::{ecdsa::Pair as EcdsaPair, mocks::KeyRepositoryMock}; + use k256::{ecdsa::SigningKey, elliptic_curve::rand_core}; + use parentchain_primitives::Identity; + use sp_core::{sr25519, Pair}; + + #[test] + pub fn it_should_return_ok_for_relayer_signer() { + //given + let relayer_registry = RelayerRegistry::default(); + let alice_key_pair = sr25519::Pair::from_string("//Alice", None).unwrap(); + let relayer_account = Identity::Substrate(alice_key_pair.public().into()); + relayer_registry.update(relayer_account.clone()).unwrap(); + + let private = SigningKey::random(&mut rand_core::OsRng); + let signing_key = EcdsaPair::new(private); + + let key_repository = KeyRepositoryMock::new(signing_key); + + //when + let result = + handle(relayer_account, Default::default(), &relayer_registry, &key_repository); + + //then + assert!(result.is_ok()) + } + + #[test] + pub fn it_should_return_err_for_non_relayer_signer() { + //given + let relayer_registry = RelayerRegistry::default(); + let alice_key_pair = sr25519::Pair::from_string("//Alice", None).unwrap(); + let non_relayer_account = Identity::Substrate(alice_key_pair.public().into()); + + let private = SigningKey::random(&mut rand_core::OsRng); + let signing_key = EcdsaPair::new(private); + + let key_repository = KeyRepositoryMock::new(signing_key); + + //when + let result = + handle(non_relayer_account, Default::default(), &relayer_registry, &key_repository); + + //then + assert!(result.is_err()) + } + + #[test] + pub fn sign_ethereum_works() { + // test vector from bc team, verified with sp_core::ecdsa::Pair::sign_prehashed + let private_key = + hex::decode("038a5c907573ea7f61a7dcce5ebb2e233a6e9376e5a6f077729bd732d6cab620") + .unwrap(); + let key_pair = EcdsaPair::from_bytes(&private_key).unwrap(); + let payload = + hex::decode("3b08e117290fdd2617ea0e457a8eeebe373c456ecd3f6dc6dc4089380f486516") + .unwrap(); + let result = key_pair.sign_prehash_recoverable(&payload).unwrap(); + let expected_result = hex::decode("e733e8e3cd4f90d8fc10c2f8eeb7183623451b8e1d55b5ab6c4724c5428264955289fac3da7ce2095e12f19b4eb157c55be5c58a09ac8ae3358af0b7ec266a7201").unwrap(); + + assert_eq!(&result, expected_result.as_slice()) + } +} diff --git a/bitacross-worker/litentry/core/direct-call/src/lib.rs b/bitacross-worker/litentry/core/direct-call/src/lib.rs new file mode 100644 index 0000000000..88583c4fdd --- /dev/null +++ b/bitacross-worker/litentry/core/direct-call/src/lib.rs @@ -0,0 +1,78 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use codec::{Decode, Encode}; +use itp_stf_primitives::types::KeyPair; +use litentry_primitives::{LitentryMultiSignature, RequestAesKey, ShardIdentifier}; +use parentchain_primitives::Identity; +use sp_io::hashing::blake2_256; +use std::vec::Vec; + +pub mod handler; + +pub type PrehashedEthereumMessage = [u8; 32]; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct DirectCallSigned { + pub call: DirectCall, + pub signature: LitentryMultiSignature, +} + +impl DirectCallSigned { + pub fn verify_signature(&self, mrenclave: &[u8; 32], shard: &ShardIdentifier) -> bool { + let mut payload = self.call.encode(); + payload.append(&mut mrenclave.encode()); + payload.append(&mut shard.encode()); + + self.signature.verify(blake2_256(&payload).as_slice(), self.call.signer()) + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub enum DirectCall { + SignBitcoin(Identity, RequestAesKey, Vec), + SignEthereum(Identity, RequestAesKey, PrehashedEthereumMessage), +} + +impl DirectCall { + pub fn signer(&self) -> &Identity { + match self { + Self::SignBitcoin(signer, ..) => signer, + Self::SignEthereum(signer, ..) => signer, + } + } + + pub fn sign( + &self, + pair: &KeyPair, + mrenclave: &[u8; 32], + shard: &ShardIdentifier, + ) -> DirectCallSigned { + let mut payload = self.encode(); + payload.append(&mut mrenclave.encode()); + payload.append(&mut shard.encode()); + + DirectCallSigned { + call: self.clone(), + signature: pair.sign(blake2_256(&payload).as_slice()), + } + } +} diff --git a/bitacross-worker/litentry/core/scheduled-enclave/src/error.rs b/bitacross-worker/litentry/core/scheduled-enclave/src/error.rs index 6353db15f5..70228b33a0 100644 --- a/bitacross-worker/litentry/core/scheduled-enclave/src/error.rs +++ b/bitacross-worker/litentry/core/scheduled-enclave/src/error.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/litentry/core/scheduled-enclave/src/io.rs b/bitacross-worker/litentry/core/scheduled-enclave/src/io.rs index 9912fe4a6f..7aad2bc57d 100644 --- a/bitacross-worker/litentry/core/scheduled-enclave/src/io.rs +++ b/bitacross-worker/litentry/core/scheduled-enclave/src/io.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/litentry/core/scheduled-enclave/src/lib.rs b/bitacross-worker/litentry/core/scheduled-enclave/src/lib.rs index e71edfb88a..ddb47e2e3d 100644 --- a/bitacross-worker/litentry/core/scheduled-enclave/src/lib.rs +++ b/bitacross-worker/litentry/core/scheduled-enclave/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/litentry/core/teebag-storage/Cargo.toml b/bitacross-worker/litentry/core/teebag-storage/Cargo.toml new file mode 100644 index 0000000000..c68b9e0d5e --- /dev/null +++ b/bitacross-worker/litentry/core/teebag-storage/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "lc-teebag-storage" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition = "2021" + +[dependencies] +itp-storage = { path = "../../../core-primitives/storage", default-features = false } +itp-types = { path = "../../../core-primitives/types", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", default-features = false } + +[features] +default = ["std"] +std = [ + "sp-std/std", + "itp-storage/std", + "itp-types/std", +] diff --git a/bitacross-worker/litentry/core/teebag-storage/src/lib.rs b/bitacross-worker/litentry/core/teebag-storage/src/lib.rs new file mode 100644 index 0000000000..3f931d9f7e --- /dev/null +++ b/bitacross-worker/litentry/core/teebag-storage/src/lib.rs @@ -0,0 +1,48 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use itp_storage::{storage_map_key, StorageHasher}; +use itp_types::WorkerType; +use sp_std::prelude::Vec; + +pub struct TeebagStorage; + +pub trait StoragePrefix { + fn prefix() -> &'static str; +} + +impl StoragePrefix for TeebagStorage { + fn prefix() -> &'static str { + "Teebag" + } +} + +pub trait TeebagStorageKeys { + fn enclave_identifier(worker_type: WorkerType) -> Vec; +} + +impl TeebagStorageKeys for S { + fn enclave_identifier(worker_type: WorkerType) -> Vec { + storage_map_key( + Self::prefix(), + "EnclaveIdentifier", + &worker_type, + &StorageHasher::Blake2_128Concat, + ) + } +} diff --git a/bitacross-worker/litentry/macros/src/lib.rs b/bitacross-worker/litentry/macros/src/lib.rs index b57ac19473..f76bbe03c0 100644 --- a/bitacross-worker/litentry/macros/src/lib.rs +++ b/bitacross-worker/litentry/macros/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/litentry/primitives/Cargo.toml b/bitacross-worker/litentry/primitives/Cargo.toml index 86242bc003..e0b645a3eb 100644 --- a/bitacross-worker/litentry/primitives/Cargo.toml +++ b/bitacross-worker/litentry/primitives/Cargo.toml @@ -9,7 +9,6 @@ bitcoin = { version = "0.31.0", default-features = false, features = ["secp-reco codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex = { version = "0.4.3", default-features = false } log = { version = "0.4", default-features = false } -pallet-evm = { default-features = false, git = "https://github.com/integritee-network/frontier.git", branch = "bar/polkadot-v0.9.42" } rand = { version = "0.7", optional = true } rand-sgx = { package = "rand", git = "https://github.com/mesalock-linux/rand-sgx", tag = "sgx_1.1.3", features = ["sgx_tstd"], optional = true } ring = { version = "0.16.20", default-features = false } @@ -20,43 +19,40 @@ sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot- sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } -strum = { version = "0.26", default-features = false } -strum_macros = { version = "0.26", default-features = false } # sgx dependencies -base64_sgx = { package = "base64", rev = "sgx_1.1.3", git = "https://github.com/mesalock-linux/rust-base64-sgx", optional = true } sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master", optional = true, features = ["net", "thread"] } # internal dependencies itp-sgx-crypto = { path = "../../core-primitives/sgx/crypto", default-features = false } -itp-utils = { path = "../../core-primitives/utils", default-features = false } +litentry-hex-utils = { path = "../../../primitives/hex", default-features = false } +pallet-teebag = { path = "../../../pallets/teebag", default-features = false } parentchain-primitives = { package = "core-primitives", path = "../../../primitives/core", default-features = false } -teerex-primitives = { path = "../../../primitives/teerex", default-features = false } [dev-dependencies] base64 = { version = "0.13", features = ["alloc"] } [features] default = ["std"] -production = [] +production = [ + "parentchain-primitives/production", +] sgx = [ "sgx_tstd", "rand-sgx", "itp-sgx-crypto/sgx", ] std = [ - "strum/std", "hex/std", "serde/std", "itp-sgx-crypto/std", - "itp-utils/std", "sp-core/std", "sp-std/std", "sp-io/std", "sp-runtime/std", "ring/std", "parentchain-primitives/std", - "teerex-primitives/std", + "pallet-teebag/std", "rand", "log/std", "bitcoin/std", diff --git a/bitacross-worker/litentry/primitives/src/aes.rs b/bitacross-worker/litentry/primitives/src/aes.rs index d63b02432a..8abbb7b149 100644 --- a/bitacross-worker/litentry/primitives/src/aes.rs +++ b/bitacross-worker/litentry/primitives/src/aes.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/litentry/primitives/src/aes_request.rs b/bitacross-worker/litentry/primitives/src/aes_request.rs index 7c133429e2..e15c88e40b 100644 --- a/bitacross-worker/litentry/primitives/src/aes_request.rs +++ b/bitacross-worker/litentry/primitives/src/aes_request.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ #[cfg(all(not(feature = "std"), feature = "sgx"))] extern crate sgx_tstd as std; -/// A morphling of itp_types::RsaRequest which stems from teerex_primitives::RsaRequest +/// A morphling of itp_types::RsaRequest which stems from teebag::RsaRequest /// /// Instead of encrypting the TrustedCallSigned with the TEE's shielding key, we encrypt /// it with a 32-byte ephemeral AES key which is generated from the client's side, and diff --git a/bitacross-worker/litentry/primitives/src/bitcoin_signature.rs b/bitacross-worker/litentry/primitives/src/bitcoin_signature.rs index cb6db71a23..689e088fbc 100644 --- a/bitacross-worker/litentry/primitives/src/bitcoin_signature.rs +++ b/bitacross-worker/litentry/primitives/src/bitcoin_signature.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/litentry/primitives/src/ethereum_signature.rs b/bitacross-worker/litentry/primitives/src/ethereum_signature.rs index 75496fa61d..e0869efd08 100644 --- a/bitacross-worker/litentry/primitives/src/ethereum_signature.rs +++ b/bitacross-worker/litentry/primitives/src/ethereum_signature.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/litentry/primitives/src/lib.rs b/bitacross-worker/litentry/primitives/src/lib.rs index b439190a30..6acab463cc 100644 --- a/bitacross-worker/litentry/primitives/src/lib.rs +++ b/bitacross-worker/litentry/primitives/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify @@ -41,20 +41,17 @@ pub use validation_data::*; use bitcoin::sign_message::{signed_msg_hash, MessageSignature}; use codec::{Decode, Encode, MaxEncodedLen}; use itp_sgx_crypto::ShieldingCryptoDecrypt; -use itp_utils::hex::hex_encode; +use litentry_hex_utils::hex_encode; use log::error; +pub use pallet_teebag::{ + decl_rsa_request, extract_tcb_info_from_raw_dcap_quote, AttestationType, Enclave, + EnclaveFingerprint, MrEnclave, ShardIdentifier, SidechainBlockNumber, WorkerMode, WorkerType, +}; pub use parentchain_primitives::{ - all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks, all_web3networks, - identity::*, AccountId as ParentchainAccountId, AchainableAmount, AchainableAmountHolding, - AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, - AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, - AchainableMirror, AchainableParams, AchainableToken, AmountHoldingTimeType, Assertion, - Balance as ParentchainBalance, BlockNumber as ParentchainBlockNumber, BnbDigitDomainType, - BoundedWeb3Network, ContestType, EVMTokenType, ErrorDetail, ErrorString, - GenericDiscordRoleType, Hash as ParentchainHash, Header as ParentchainHeader, IMPError, - Index as ParentchainIndex, IntoErrorDetail, OneBlockCourseType, ParameterString, - SchemaContentString, SchemaIdString, Signature as ParentchainSignature, SoraQuizType, - VCMPError, VIP3MembershipCardLevel, Web3Network, MINUTES, + identity::*, AccountId as ParentchainAccountId, Balance as ParentchainBalance, + BlockNumber as ParentchainBlockNumber, ErrorDetail, ErrorString, Hash as ParentchainHash, + Header as ParentchainHeader, Index as ParentchainIndex, ParameterString, + Signature as ParentchainSignature, MINUTES, }; use scale_info::TypeInfo; use sp_core::{ecdsa, ed25519, sr25519, ByteArray}; @@ -64,7 +61,6 @@ use sp_io::{ }; use sp_runtime::traits::Verify; use std::string::{String, ToString}; -pub use teerex_primitives::{decl_rsa_request, ShardIdentifier, SidechainBlockNumber}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; @@ -228,8 +224,6 @@ fn evm_eip191_wrap(msg: &[u8]) -> Vec { ["\x19Ethereum Signed Message:\n".as_bytes(), msg.len().to_string().as_bytes(), msg].concat() } -pub type IdentityNetworkTuple = (Identity, Vec); - // Represent a request that can be decrypted by the enclave // Both itp_types::RsaRequest and AesRequest should impelement this pub trait DecryptableRequest { diff --git a/bitacross-worker/litentry/primitives/src/validation_data.rs b/bitacross-worker/litentry/primitives/src/validation_data.rs index aac3427799..0b9eb19001 100644 --- a/bitacross-worker/litentry/primitives/src/validation_data.rs +++ b/bitacross-worker/litentry/primitives/src/validation_data.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify diff --git a/bitacross-worker/local-setup/launch.py b/bitacross-worker/local-setup/launch.py index ae4a6e5b24..3adfc131b5 100755 --- a/bitacross-worker/local-setup/launch.py +++ b/bitacross-worker/local-setup/launch.py @@ -102,6 +102,26 @@ def check_all_ports_and_reallocate(): reallocate_ports(x, os.environ.get(x)) print("All preliminary port checks completed") + +# Generate `config.local.json` used by parachain ts utils +def generate_config_local_json(parachain_dir): + data = { + "eth_endpoint": "http://127.0.0.1:8545", + "eth_address": "[0x4d88dc5d528a33e4b8be579e9476715f60060582]", + "private_key": "0xe82c0c4259710bb0d6cf9f9e8d0ad73419c1278a14d375e5ca691e7618103011", + "ocw_account": "5FEYX9NES9mAJt1Xg4WebmHWywxyeGQK8G3oEBXtyfZrRePX", + "genesis_state_path": parachain_dir+"/genesis-state", + "genesis_wasm_path": parachain_dir+"/genesis-wasm", + "parachain_ws": "ws://localhost:" + os.environ.get("CollatorWSPort", "9944"), + "relaychain_ws": "ws://localhost:" + os.environ.get("AliceWSPort", "9946"), + "bridge_path": "/tmp/parachain_dev/chainbridge", + } + config_file = "../ts-tests/config.local.json" + + with open(config_file, "w") as f: + json.dump(data, f, indent=4) + + print("Successfully written ", config_file) def run_node(config, i: int): @@ -122,6 +142,7 @@ def setup_environment(offset, config, parachain_dir): load_dotenv(".env.dev") offset_port(offset) check_all_ports_and_reallocate() + generate_config_local_json(parachain_dir) # TODO: only works for single worker for now for p in [ diff --git a/bitacross-worker/samples/teeracle/README.md b/bitacross-worker/samples/teeracle/README.md deleted file mode 100644 index 05758f7d09..0000000000 --- a/bitacross-worker/samples/teeracle/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# Teeracle install into Securitee's kubernetes cluster - -This example is about to install [Integritee's Teeracle](https://docs.integritee.network/3-our-technology/3.5-use-cases/3.5.3-teeracle-oracle-framework). - -*Prerequisites:* - -* Ensure you have access to a Kubernetes cluster with SGX-enabled nodes and kubectl installed and configured. The easiest way to get started is to order Kubernetes from Securitee [Securitee Kubernetes](https://securitee.tech/products/), which offers SGX-enabled nodes. -* You have [Helm](https://helm.sh/docs/intro/install/) installed - -## Kubernetes deployment walkthrough - -We are now installing Teeracle - -### Install steps - - -* Edit the configuration values in file [kubernetes/values.yaml](kubernetes/values.yaml) - ```yaml - app: - url: "wss://rococo.api.integritee.network" - interval: "2m" - ``` -* Install the Teeracle into the cluster - - ```bash - helm install -f ./kubernetes/values.yaml teeracle ./kubernetes --create-namespace -n teeracle - or run - ./install-teeracle.sh - ``` - - -## Misc. - -### SGX Plugin - -If you are running in simulation mode, or are using a different plugin please edit the [kubernetes/templates/teeracle.yaml](kubernetes/templates/teeracle.yaml) - ```yaml - limits: - sgx.intel.com/epc: "10Mi" - sgx.intel.com/enclave: 1 - sgx.intel.com/provision: 1 - ``` - -### PCCS server - -The DCAP attestation requires a running PCCS server - which is provided by Securitee by default that's why we need to mount the ```/etc/sgx_default_qcnl.conf``` config file -see [kubernetes/templates/teeracle.yaml](kubernetes/templates/teeracle.yaml) - ```yaml - volumeMounts: - - name: qcnl - mountPath: /etc/sgx_default_qcnl.conf - ... - volumes: - - name: qcnl - hostPath: - path: /etc/sgx_default_qcnl.conf - - ``` diff --git a/bitacross-worker/samples/teeracle/install-teeracle.sh b/bitacross-worker/samples/teeracle/install-teeracle.sh deleted file mode 100755 index dbc21bc2b4..0000000000 --- a/bitacross-worker/samples/teeracle/install-teeracle.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/env bash - -namespace=teeracle -helm uninstall -n $namespace teeracle - -helm install -f ./kubernetes/values.yaml teeracle ./kubernetes --create-namespace -n $namespace - diff --git a/bitacross-worker/samples/teeracle/kubernetes/Chart.yaml b/bitacross-worker/samples/teeracle/kubernetes/Chart.yaml deleted file mode 100644 index d1f3a9a7f8..0000000000 --- a/bitacross-worker/samples/teeracle/kubernetes/Chart.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v2 -name: teeracle -description: teeracle dcap - -type: application -version: 0.1.0 -appVersion: 1.0.0 \ No newline at end of file diff --git a/bitacross-worker/samples/teeracle/kubernetes/templates/teeracle.yaml b/bitacross-worker/samples/teeracle/kubernetes/templates/teeracle.yaml deleted file mode 100644 index 130ad79cb4..0000000000 --- a/bitacross-worker/samples/teeracle/kubernetes/templates/teeracle.yaml +++ /dev/null @@ -1,73 +0,0 @@ -kind: ServiceAccount -apiVersion: v1 -metadata: - name: teeracle - namespace: {{ .Release.Namespace }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: teeracle-main - namespace: {{ .Release.Namespace }} - labels: - app: teeracle - role: main - tier: backend -spec: - replicas: 1 - selector: - matchLabels: - app: teeracle - role: main - tier: backend - template: - metadata: - labels: - app: teeracle - spec: - serviceAccountName: teeracle - containers: - - image: {{ .Values.image }} - imagePullPolicy: {{ .Values.imagePullPolicy }} - - args: [ - "-p", "443", - "-u", {{ .Values.app.url }}, - "--enable-metrics", - "--data-dir", "/opt/teeracle", - "run", - "--teeracle-interval", {{ .Values.app.interval }} - ] - name: teeracle - - resources: - # Resource request to use Intel SGX Device Plugin - # If you are running in simulation mode, or are using a different plugin, - # update these values accordingly - limits: - sgx.intel.com/epc: "10Mi" - sgx.intel.com/enclave: 1 - sgx.intel.com/provision: 1 - - volumeMounts: - - name: aesmd-socket - mountPath: /var/run/aesmd - - name: data-dir - mountPath: /opt/teeracle - - name: qcnl - mountPath: /etc/sgx_default_qcnl.conf - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: aesmd-socket - hostPath: - path: /var/run/aesmd - - name: data-dir - hostPath: - path: /opt/teeracle - - name: qcnl - hostPath: - path: /etc/sgx_default_qcnl.conf - diff --git a/bitacross-worker/samples/teeracle/kubernetes/values.yaml b/bitacross-worker/samples/teeracle/kubernetes/values.yaml deleted file mode 100644 index 8a423ee3ab..0000000000 --- a/bitacross-worker/samples/teeracle/kubernetes/values.yaml +++ /dev/null @@ -1,14 +0,0 @@ -imagePullSecrets: - - name: regcred - -imagePullPolicy: IfNotPresent - -image: integritee/teeracle:v0.12.2-dev - -# -# To get more insights run: -# docker run integritee/teeracle:v0.12.2-dev --help -# -app: - url: "wss://rococo.api.integritee.network" - interval: "2m" \ No newline at end of file diff --git a/bitacross-worker/scripts/changelog/templates/changes.md.tera b/bitacross-worker/scripts/changelog/templates/changes.md.tera index 571f2f4cab..1dcb6ea978 100644 --- a/bitacross-worker/scripts/changelog/templates/changes.md.tera +++ b/bitacross-worker/scripts/changelog/templates/changes.md.tera @@ -19,6 +19,5 @@ {% include "changes_sidechain.md.tera" %} -{% include "changes_teeracle.md.tera" %} {% include "changes_misc.md.tera" %} diff --git a/bitacross-worker/scripts/changelog/templates/changes_teeracle.md.tera b/bitacross-worker/scripts/changelog/templates/changes_teeracle.md.tera deleted file mode 100644 index 6e94e88b2c..0000000000 --- a/bitacross-worker/scripts/changelog/templates/changes_teeracle.md.tera +++ /dev/null @@ -1,17 +0,0 @@ -{% import "change.md.tera" as m_c -%} -### Teeracle - -{#- The changes are sorted by merge date #} -{%- for pr in changes | sort(attribute="merged_at") %} - -{%- if pr.meta.B %} - {%- if pr.meta.B.value == 0 %} - {#- We skip silent ones -#} - {%- else -%} - - {%- if pr.meta.A.value == 5 %} -- {{ m_c::change(c=pr) }} - {%- endif -%} - {% endif -%} - {% endif -%} -{% endfor %} diff --git a/bitacross-worker/scripts/litentry/release/config.json.eg b/bitacross-worker/scripts/litentry/release/config.json.eg index acfdbc872a..c655446160 100644 --- a/bitacross-worker/scripts/litentry/release/config.json.eg +++ b/bitacross-worker/scripts/litentry/release/config.json.eg @@ -1,9 +1,8 @@ { "twitter_official_url": "https://api.twitter.com", - "twitter_litentry_url": "", "twitter_auth_token_v2": "abcdefghijklmnopqrstuvwxyz", "discord_official_url": "https://discordapp.com", - "discord_litentry_url": "", + "litentry_discord_microservice_url": "", "discord_auth_token": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "achainable_url": "https://graph.tdf-labs.io/", "achainable_auth_key": "88888888-4444-4444-4444-1234567890ab", diff --git a/bitacross-worker/scripts/teeracle.sh b/bitacross-worker/scripts/teeracle.sh deleted file mode 100644 index 829c67b2a3..0000000000 --- a/bitacross-worker/scripts/teeracle.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Runs Teeracle1 demo: Either set `CLIENT_DIR` env var directly or run script with: -# -# source ./init_env.sh && ./teeracle.sh - -echo "$CLIENT_DIR" - -cd "$CLIENT_DIR" || exit - -LOG_1="${LOG_1:-$LOG_DIR/teeracle1_demo_whitelist.log}" - -echo "[teeracle.sh] printing to logs:" -echo " $LOG_1" - -touch "$LOG_1" - -./demo_teeracle_whitelist.sh -p 9944 -P 2000 -d 120 -i 24 2>&1 | tee "$LOG_1" diff --git a/bitacross-worker/service/Cargo.toml b/bitacross-worker/service/Cargo.toml index f076e26cf5..9a9caf29d9 100644 --- a/bitacross-worker/service/Cargo.toml +++ b/bitacross-worker/service/Cargo.toml @@ -33,7 +33,6 @@ warp = "0.3" ipfs-api = "0.11.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -primitive-types = { version = "0.12.1", default-features = false, features = ["codec"] } sgx_crypto_helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } @@ -42,7 +41,6 @@ sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-s itc-parentchain = { path = "../core/parentchain/parentchain-crate" } itc-rest-client = { path = "../core/rest-client" } itc-rpc-client = { path = "../core/rpc-client" } -itc-rpc-server = { path = "../core/rpc-server" } itp-api-client-types = { path = "../core-primitives/node-api/api-client-types" } itp-enclave-api = { path = "../core-primitives/enclave-api" } itp-enclave-metrics = { path = "../core-primitives/enclave-metrics" } @@ -51,18 +49,12 @@ itp-settings = { path = "../core-primitives/settings" } itp-storage = { path = "../core-primitives/storage" } itp-types = { path = "../core-primitives/types" } itp-utils = { path = "../core-primitives/utils" } -its-consensus-slots = { path = "../sidechain/consensus/slots" } -its-peer-fetch = { path = "../sidechain/peer-fetch" } -its-primitives = { path = "../sidechain/primitives" } -its-rpc-handler = { path = "../sidechain/rpc-handler" } -its-storage = { path = "../sidechain/storage" } # `default-features = false` to remove the jsonrpsee dependency. substrate-api-client = { default-features = false, features = ["std", "sync-api"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", features = ["full_crypto"] } sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } @@ -70,19 +62,18 @@ sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "po # litentry config = "0.13.3" -ita-stf = { path = "../app-libs/stf", default-features = false } +litentry-macros = { path = "../../primitives/core/macros", default-features = false } litentry-primitives = { path = "../litentry/primitives" } my-node-runtime = { package = "rococo-parachain-runtime", path = "../../runtime/rococo" } -sgx-verify = { path = "../../pallets/teerex/sgx-verify", default-features = false } -teerex-primitives = { path = "../../primitives/teerex", default-features = false } [features] default = [] -evm = [] -sidechain = ["itp-settings/sidechain"] offchain-worker = ["itp-settings/offchain-worker"] -production = ["itp-settings/production"] -teeracle = ["itp-settings/teeracle"] +production = [ + "itp-settings/production", + "litentry-macros/production", + "litentry-primitives/production", +] dcap = [] attesteer = ["dcap"] # Must be enabled to build a binary and link it with the enclave successfully. @@ -103,5 +94,4 @@ anyhow = "1.0.40" mockall = "0.11" # local itc-parentchain-test = { path = "../core/parentchain/test" } -its-peer-fetch = { path = "../sidechain/peer-fetch", features = ["mocks"] } -its-test = { path = "../sidechain/test" } +itp-sgx-crypto = { path = "../core-primitives/sgx/crypto" } diff --git a/bitacross-worker/service/src/cli.yml b/bitacross-worker/service/src/cli.yml index e517e6b1bb..6954013454 100644 --- a/bitacross-worker/service/src/cli.yml +++ b/bitacross-worker/service/src/cli.yml @@ -114,17 +114,6 @@ args: takes_value: true required: false default_value: "0" - - fail-slot-mode: - long: fail-slot-mode - help: Set the mode of failing a slot, values [BeforeOnSlot, AfterOnSlot] - takes_value: true - required: false - - fail-at: - long: fail-at - help: Set the slot to fail on - takes_value: true - required: false - default_value: "0" subcommands: - run: @@ -145,17 +134,6 @@ subcommands: long: request-state short: r help: Run the worker and request key and state provisioning from another worker. - - teeracle-interval: - required: false - long: teeracle-interval - short: i - help: Set the teeracle exchange rate update interval. Example of accepted syntax <5 seconds 15 minutes 2 hours 1 days> or short <5s15m2h1d> - takes_value: true - - reregister-teeracle-interval: - required: false - long: reregister - help: Set the teeracle reregistration interval. Example of accepted syntax <5 seconds 15 minutes 2 hours 1 days> or short <5s15m2h1d> - takes_value: true - request-state: about: join a shard by requesting key provisioning from another worker args: @@ -172,6 +150,8 @@ subcommands: about: Get the public ed25519 key the TEE uses to sign messages and extrinsics - dump-ra: about: Perform RA and dump cert to disk + - wallet: + about: Print the bitcoin and ethereum custodian wallet key information, only works in non-prod - mrenclave: about: Dump mrenclave to stdout. base58 encoded. - init-shard: diff --git a/bitacross-worker/service/src/config.rs b/bitacross-worker/service/src/config.rs index bc9b8b7cdb..6498bf86fd 100644 --- a/bitacross-worker/service/src/config.rs +++ b/bitacross-worker/service/src/config.rs @@ -17,7 +17,6 @@ use clap::ArgMatches; use itc_rest_client::rest_client::Url; -use itp_settings::teeracle::{DEFAULT_MARKET_DATA_UPDATE_INTERVAL, ONE_DAY, THIRTY_MINUTES}; use parse_duration::parse; use serde::{Deserialize, Serialize}; use std::{ @@ -34,7 +33,6 @@ static DEFAULT_MU_RA_PORT: &str = "3443"; static DEFAULT_METRICS_PORT: &str = "8787"; static DEFAULT_UNTRUSTED_HTTP_PORT: &str = "4545"; static DEFAULT_PARENTCHAIN_START_BLOCK: &str = "0"; -static DEFAULT_FAIL_AT: &str = "0"; #[derive(Clone, Debug, PartialEq)] pub struct Config { @@ -70,10 +68,6 @@ pub struct Config { /// the parentchain block number to start syncing with pub parentchain_start_block: String, - /// mode to use for failing sidechain slot - pub fail_slot_mode: Option, - /// slot number to fail at - pub fail_at: u64, } #[allow(clippy::too_many_arguments)] @@ -98,8 +92,6 @@ impl Config { data_dir: PathBuf, run_config: Option, parentchain_start_block: String, - fail_slot_mode: Option, - fail_at: u64, ) -> Self { Self { litentry_rpc_url, @@ -121,8 +113,6 @@ impl Config { data_dir, run_config, parentchain_start_block, - fail_slot_mode, - fail_at, } } @@ -254,8 +244,6 @@ impl From<&ArgMatches<'_>> for Config { let parentchain_start_block = m.value_of("parentchain-start-block").unwrap_or(DEFAULT_PARENTCHAIN_START_BLOCK); - let fail_slot_mode = m.value_of("fail-slot-mode").map(|v| v.to_string()); - let fail_at = m.value_of("fail-at").unwrap_or(DEFAULT_FAIL_AT).parse().unwrap(); Self::new( m.value_of("node-url").unwrap_or(DEFAULT_NODE_URL).into(), m.value_of("node-port").unwrap_or(DEFAULT_NODE_PORT).into(), @@ -279,8 +267,6 @@ impl From<&ArgMatches<'_>> for Config { data_dir, run_config, parentchain_start_block.to_string(), - fail_slot_mode, - fail_at, ) } } @@ -295,10 +281,6 @@ pub struct RunConfig { request_state: bool, /// Shard identifier base58 encoded. Defines the shard that this worker operates on. Default is mrenclave. shard: Option, - /// Optional teeracle update interval - teeracle_update_interval: Option, - /// Optional teeracle reregistration interval - reregister_teeracle_interval: Option, /// Marblerun's Prometheus endpoint base URL marblerun_base_url: Option, } @@ -320,19 +302,6 @@ impl RunConfig { self.shard.as_deref() } - pub fn teeracle_update_interval(&self) -> Duration { - self.teeracle_update_interval.unwrap_or(DEFAULT_MARKET_DATA_UPDATE_INTERVAL) - } - - /// The periodic registration period of the teeracle. - /// - /// Defaults to 23h30m, as this is slightly below the currently configured automatic - /// deregistration period on the Integritee chains. - pub fn reregister_teeracle_interval(&self) -> Duration { - // Todo: Derive this from chain https://github.com/integritee-network/worker/issues/1351 - self.reregister_teeracle_interval.unwrap_or(ONE_DAY - THIRTY_MINUTES) - } - pub fn marblerun_base_url(&self) -> &str { // This conflicts with the default port of a substrate node, but it is indeed the // default port of marblerun too: @@ -347,12 +316,6 @@ impl From<&ArgMatches<'_>> for RunConfig { let dev = m.is_present("dev"); let request_state = m.is_present("request-state"); let shard = m.value_of("shard").map(|s| s.to_string()); - let teeracle_update_interval = m.value_of("teeracle-interval").map(|i| { - parse(i).unwrap_or_else(|e| panic!("teeracle-interval parsing error {:?}", e)) - }); - let reregister_teeracle_interval = m.value_of("reregister-teeracle-interval").map(|i| { - parse(i).unwrap_or_else(|e| panic!("teeracle-interval parsing error {:?}", e)) - }); let marblerun_base_url = m.value_of("marblerun-url").map(|i| { Url::parse(i) @@ -360,15 +323,7 @@ impl From<&ArgMatches<'_>> for RunConfig { .to_string() }); - Self { - skip_ra, - dev, - request_state, - shard, - teeracle_update_interval, - reregister_teeracle_interval, - marblerun_base_url, - } + Self { skip_ra, dev, request_state, shard, marblerun_base_url } } } @@ -423,8 +378,6 @@ mod test { assert_eq!(config.data_dir, pwd()); assert!(config.run_config.is_none()); assert_eq!(config.parentchain_start_block, DEFAULT_PARENTCHAIN_START_BLOCK); - assert_matches!(config.fail_slot_mode, Option::None); - assert_eq!(config.fail_at, DEFAULT_FAIL_AT.parse::().unwrap()) } #[test] @@ -504,7 +457,6 @@ mod test { assert_eq!(run_config.dev, false); assert_eq!(run_config.skip_ra, false); assert!(run_config.shard.is_none()); - assert!(run_config.teeracle_update_interval.is_none()); } #[test] @@ -517,11 +469,9 @@ mod test { ("dev", Default::default()), ("skip-ra", Default::default()), ("shard", Default::default()), - ("teeracle-interval", Default::default()), ]); // Workaround because MatchedArg is private. args.args.get_mut("shard").unwrap().vals = vec![shard_identifier.into()]; - args.args.get_mut("teeracle-interval").unwrap().vals = vec!["42s".into()]; let run_config = RunConfig::from(&args); @@ -529,7 +479,6 @@ mod test { assert_eq!(run_config.dev, true); assert_eq!(run_config.skip_ra, true); assert_eq!(run_config.shard.unwrap(), shard_identifier.to_string()); - assert_eq!(run_config.teeracle_update_interval.unwrap(), Duration::from_secs(42)); } #[test] @@ -563,17 +512,6 @@ mod test { assert_eq!(config.mu_ra_url_external(), format!("{}:{}", expected_worker_ip, mu_ra_port)); } - #[test] - fn teeracle_interval_parsing_panics_if_format_is_invalid() { - let teeracle_interval = "24s_invalid-format"; - let mut args = ArgMatches::default(); - args.args = HashMap::from([("teeracle-interval", Default::default())]); - args.args.get_mut("teeracle-interval").unwrap().vals = vec![teeracle_interval.into()]; - - let result = std::panic::catch_unwind(|| RunConfig::from(&args)); - assert!(result.is_err()); - } - #[test] fn external_addresses_are_returned_correctly_if_set() { let trusted_ext_addr = "wss://1.1.1.2:700"; diff --git a/bitacross-worker/service/src/initialized_service.rs b/bitacross-worker/service/src/initialized_service.rs index f35a17fa28..2aca3876ac 100644 --- a/bitacross-worker/service/src/initialized_service.rs +++ b/bitacross-worker/service/src/initialized_service.rs @@ -19,7 +19,6 @@ //! hosted on a http server. use crate::error::ServiceResult; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; use log::*; use parking_lot::RwLock; use std::{default::Default, marker::PhantomData, net::SocketAddr, sync::Arc}; @@ -61,62 +60,30 @@ pub trait IsInitialized { pub trait TrackInitialization { fn registered_on_parentchain(&self); - fn sidechain_block_produced(&self); - fn worker_for_shard_registered(&self); } -pub struct InitializationHandler { +#[derive(Default)] +pub struct InitializationHandler { registered_on_parentchain: RwLock, - sidechain_block_produced: RwLock, worker_for_shard_registered: RwLock, - _phantom: PhantomData, -} - -// Cannot use #[derive(Default)], because the compiler complains that WorkerModeProvider then -// also needs to implement Default. Which does not make sense, since it's only used in PhantomData. -// Explicitly implementing Default solves the problem -// (see https://stackoverflow.com/questions/59538071/the-trait-bound-t-stddefaultdefault-is-not-satisfied-when-using-phantomda). -impl Default for InitializationHandler { - fn default() -> Self { - Self { - registered_on_parentchain: Default::default(), - sidechain_block_produced: Default::default(), - worker_for_shard_registered: Default::default(), - _phantom: Default::default(), - } - } } -impl TrackInitialization for InitializationHandler { +impl TrackInitialization for InitializationHandler { fn registered_on_parentchain(&self) { let mut registered_lock = self.registered_on_parentchain.write(); *registered_lock = true; } - fn sidechain_block_produced(&self) { - let mut block_produced_lock = self.sidechain_block_produced.write(); - *block_produced_lock = true; - } - fn worker_for_shard_registered(&self) { let mut registered_lock = self.worker_for_shard_registered.write(); *registered_lock = true; } } -impl IsInitialized for InitializationHandler -where - WorkerModeProvider: ProvideWorkerMode, -{ +impl IsInitialized for InitializationHandler { fn is_initialized(&self) -> bool { - match WorkerModeProvider::worker_mode() { - WorkerMode::Sidechain => - *self.registered_on_parentchain.read() - && *self.worker_for_shard_registered.read() - && *self.sidechain_block_produced.read(), - _ => *self.registered_on_parentchain.read(), - } + *self.registered_on_parentchain.read() } } @@ -125,48 +92,18 @@ mod tests { use super::*; - struct OffchainWorkerMode; - impl ProvideWorkerMode for OffchainWorkerMode { - fn worker_mode() -> WorkerMode { - WorkerMode::OffChainWorker - } - } - - struct SidechainWorkerMode; - impl ProvideWorkerMode for SidechainWorkerMode { - fn worker_mode() -> WorkerMode { - WorkerMode::Sidechain - } - } - #[test] fn default_handler_is_initialized_returns_false() { - let offchain_worker_handler = InitializationHandler::::default(); - let sidechain_handler = InitializationHandler::::default(); + let offchain_worker_handler = InitializationHandler::default(); assert!(!offchain_worker_handler.is_initialized()); - assert!(!sidechain_handler.is_initialized()); } #[test] - fn in_offchain_worker_mode_parentchain_registration_is_enough_for_initialized() { - let initialization_handler = InitializationHandler::::default(); + fn parentchain_registration_is_enough_for_initialized() { + let initialization_handler = InitializationHandler::default(); initialization_handler.registered_on_parentchain(); assert!(initialization_handler.is_initialized()); } - - #[test] - fn in_sidechain_mode_all_condition_have_to_be_met() { - let sidechain_handler = InitializationHandler::::default(); - - sidechain_handler.registered_on_parentchain(); - assert!(!sidechain_handler.is_initialized()); - - sidechain_handler.worker_for_shard_registered(); - assert!(!sidechain_handler.is_initialized()); - - sidechain_handler.sidechain_block_produced(); - assert!(sidechain_handler.is_initialized()); - } } diff --git a/bitacross-worker/service/src/main.rs b/bitacross-worker/service/src/main.rs index 6c5a888eee..cb7f43d4c8 100644 --- a/bitacross-worker/service/src/main.rs +++ b/bitacross-worker/service/src/main.rs @@ -28,11 +28,7 @@ mod ocall_bridge; mod parentchain_handler; mod prometheus_metrics; mod setup; -mod sidechain_setup; -mod sync_block_broadcaster; mod sync_state; -#[cfg(feature = "teeracle")] -mod teeracle; mod tests; mod utils; mod worker; diff --git a/bitacross-worker/service/src/main_impl.rs b/bitacross-worker/service/src/main_impl.rs index a4f58a459b..f6099eaa52 100644 --- a/bitacross-worker/service/src/main_impl.rs +++ b/bitacross-worker/service/src/main_impl.rs @@ -1,6 +1,3 @@ -#[cfg(feature = "teeracle")] -use crate::teeracle::{schedule_periodic_reregistration_thread, start_periodic_market_update}; - #[cfg(not(feature = "dcap"))] use crate::utils::check_files; use crate::{ @@ -20,10 +17,7 @@ use crate::{ }, parentchain_handler::{HandleParentchain, ParentchainHandler}, prometheus_metrics::{start_metrics_server, EnclaveMetricsReceiver, MetricsHandler}, - setup, - sidechain_setup::{sidechain_init_block_production, sidechain_start_untrusted_rpc_server}, - sync_block_broadcaster::SyncBlockBroadcaster, - sync_state, tests, + setup, sync_state, tests, utils::extract_shard, worker::Worker, worker_peers_registry::WorkerPeersRegistry, @@ -32,24 +26,17 @@ use base58::ToBase58; use clap::{load_yaml, App, ArgMatches}; use codec::{Decode, Encode}; use itp_enclave_api::{ - direct_request::DirectRequest, enclave_base::EnclaveBase, remote_attestation::{RemoteAttestation, TlsRemoteAttestation}, sidechain::Sidechain, - teeracle_api::TeeracleApi, }; use itp_node_api::{ - api_client::{AccountApi, PalletTeerexApi, ParentchainApi}, + api_client::{AccountApi, PalletTeebagApi, ParentchainApi}, metadata::NodeMetadata, node_api_factory::{CreateNodeApi, NodeApiFactory}, }; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; -use itp_utils::if_production_or; -use its_peer_fetch::{ - block_fetch_client::BlockFetcher, untrusted_peer_fetch::UntrustedPeerFetcher, -}; -use its_primitives::types::block::SignedBlock as SignedSidechainBlock; -use its_storage::{interface::FetchBlocks, BlockPruner, SidechainStorageLock}; +use litentry_macros::if_production_or; +use litentry_primitives::{Enclave as TeebagEnclave, ShardIdentifier, WorkerType}; use log::*; use my_node_runtime::{Hash, Header, RuntimeEvent}; use regex::Regex; @@ -60,10 +47,9 @@ use substrate_api_client::{ ac_primitives::serde_impls::StorageKey, api::XtStatus, rpc::HandleSubscription, storage_key, GetChainInfo, GetStorage, SubmitAndWatch, SubscribeChain, SubscribeEvents, }; -use teerex_primitives::{Enclave as TeerexEnclave, ShardIdentifier}; #[cfg(feature = "dcap")] -use sgx_verify::extract_tcb_info_from_raw_dcap_quote; +use litentry_primitives::extract_tcb_info_from_raw_dcap_quote; use itc_parentchain::primitives::ParentchainId; use itp_enclave_api::Enclave; @@ -79,8 +65,7 @@ use substrate_api_client::ac_node_api::{EventRecord, Phase::ApplyExtrinsic}; const VERSION: &str = env!("CARGO_PKG_VERSION"); #[cfg(feature = "link-binary")] -pub type EnclaveWorker = - Worker>; +pub type EnclaveWorker = Worker; pub type Event = substrate_api_client::ac_node_api::EventRecord; pub(crate) fn main() { @@ -101,8 +86,6 @@ pub(crate) fn main() { #[cfg(not(feature = "production"))] info!("*** Starting service in SGX debug mode"); - info!("*** Running worker in mode: {:?} \n", WorkerModeProvider::worker_mode()); - let clean_reset = matches.is_present("clean-reset"); if clean_reset { crate::setup::purge_files_from_dir(config.data_dir()).unwrap(); @@ -110,12 +93,6 @@ pub(crate) fn main() { // build the entire dependency tree let tokio_handle = Arc::new(GlobalTokioHandle {}); - let sidechain_blockstorage = Arc::new( - SidechainStorageLock::::from_base_path( - config.data_dir().to_path_buf(), - ) - .unwrap(), - ); let node_api_factory = Arc::new(NodeApiFactory::new(config.litentry_rpc_endpoint(), AccountKeyring::Alice.pair())); let enclave = Arc::new(enclave_init(&config).unwrap()); @@ -127,12 +104,7 @@ pub(crate) fn main() { initialization_handler.clone(), HashSet::new(), )); - let sync_block_broadcaster = - Arc::new(SyncBlockBroadcaster::new(tokio_handle.clone(), worker.clone())); let peer_updater = Arc::new(WorkerPeersRegistry::new(worker)); - let untrusted_peer_fetcher = UntrustedPeerFetcher::new(node_api_factory.clone()); - let peer_sidechain_block_fetcher = - Arc::new(BlockFetcher::::new(untrusted_peer_fetcher)); let enclave_metrics_receiver = Arc::new(EnclaveMetricsReceiver {}); let maybe_target_a_parentchain_api_factory = config @@ -148,11 +120,8 @@ pub(crate) fn main() { node_api_factory.clone(), maybe_target_a_parentchain_api_factory, maybe_target_b_parentchain_api_factory, - sync_block_broadcaster, enclave.clone(), - sidechain_blockstorage.clone(), peer_updater, - peer_sidechain_block_fetcher, tokio_handle.clone(), enclave_metrics_receiver, ))); @@ -192,7 +161,7 @@ pub(crate) fn main() { node_api_factory.create_api().expect("Failed to create parentchain node API"); if run_config.request_state() { - sync_state::sync_state::<_, _, WorkerModeProvider>( + sync_state::sync_state::<_, _>( &node_api, &shard, enclave.as_ref(), @@ -200,11 +169,10 @@ pub(crate) fn main() { ); } - start_worker::<_, _, _, _, WorkerModeProvider>( + start_worker::<_, _, _>( config, &shard, enclave, - sidechain_blockstorage, node_api, tokio_handle, initialization_handler, @@ -215,7 +183,7 @@ pub(crate) fn main() { println!("*** Requesting state from a registered worker \n"); let node_api = node_api_factory.create_api().expect("Failed to create parentchain node API"); - sync_state::sync_state::<_, _, WorkerModeProvider>( + sync_state::sync_state::<_, _>( &node_api, &extract_shard(smatches.value_of("shard"), enclave.as_ref()), enclave.as_ref(), @@ -300,6 +268,16 @@ pub(crate) fn main() { } else { setup::migrate_shard(enclave.as_ref(), &old_shard, &new_shard); } + } else if let Some(sub_matches) = matches.subcommand_matches("wallet") { + println!("Bitcoin wallet:"); + let bitcoin_keypair = enclave.get_bitcoin_wallet_pair().unwrap(); + println!("public : 0x{}", hex::encode(bitcoin_keypair.public_bytes())); + println!("private: 0x{}", hex::encode(bitcoin_keypair.private_bytes())); + + println!("Ethereum wallet:"); + let ethereum_keypair = enclave.get_ethereum_wallet_pair().unwrap(); + println!("public : 0x{}", hex::encode(ethereum_keypair.public_bytes())); + println!("private: 0x{}", hex::encode(ethereum_keypair.private_bytes())); } else { println!("For options: use --help"); } @@ -307,11 +285,10 @@ pub(crate) fn main() { /// FIXME: needs some discussion (restructuring?) #[allow(clippy::too_many_arguments)] -fn start_worker( +fn start_worker( config: Config, shard: &ShardIdentifier, enclave: Arc, - sidechain_storage: Arc, litentry_rpc_api: ParentchainApi, tokio_handle_getter: Arc, initialization_handler: Arc, @@ -319,27 +296,12 @@ fn start_worker( quote_size: Option, ) where T: GetTokioHandle, - E: EnclaveBase - + DirectRequest - + Sidechain - + RemoteAttestation - + TlsRemoteAttestation - + TeeracleApi - + Clone, - D: BlockPruner + FetchBlocks + Sync + Send + 'static, + E: EnclaveBase + Sidechain + RemoteAttestation + TlsRemoteAttestation + Clone, InitializationHandler: TrackInitialization + IsInitialized + Sync + Send + 'static, - WorkerModeProvider: ProvideWorkerMode, { let run_config = config.run_config().clone().expect("Run config missing"); let skip_ra = run_config.skip_ra(); - #[cfg(feature = "teeracle")] - let flavor_str = "teeracle"; - #[cfg(feature = "sidechain")] - let flavor_str = "sidechain"; - #[cfg(feature = "offchain-worker")] - let flavor_str = "offchain-worker"; - #[cfg(not(any(feature = "offchain-worker", feature = "sidechain", feature = "teeracle")))] let flavor_str = "offchain-worker"; println!("Litentry Worker for {} v{}", flavor_str, VERSION); @@ -352,10 +314,6 @@ fn start_worker( println!(" Production Mode is enabled"); #[cfg(not(feature = "production"))] println!(" Production Mode is disabled"); - #[cfg(feature = "evm")] - println!(" EVM is enabled"); - #[cfg(not(feature = "evm"))] - println!(" EVM is disabled"); info!("starting worker on shard {}", shard.encode().to_base58()); // ------------------------------------------------------------------------ @@ -430,34 +388,18 @@ fn start_worker( // ------------------------------------------------------------------------ // Start trusted worker rpc server - if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain - || WorkerModeProvider::worker_mode() == WorkerMode::OffChainWorker - { - let direct_invocation_server_addr = config.trusted_worker_url_internal(); - let enclave_for_direct_invocation = enclave.clone(); - thread::spawn(move || { - println!( - "[+] Trusted RPC direct invocation server listening on {}", - direct_invocation_server_addr - ); - enclave_for_direct_invocation - .init_direct_invocation_server(direct_invocation_server_addr) - .unwrap(); - println!("[+] RPC direct invocation server shut down"); - }); - } - - // ------------------------------------------------------------------------ - // Start untrusted worker rpc server. - // i.e move sidechain block importing to trusted worker. - if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain { - sidechain_start_untrusted_rpc_server( - &config, - enclave.clone(), - sidechain_storage.clone(), - &tokio_handle, + let direct_invocation_server_addr = config.trusted_worker_url_internal(); + let enclave_for_direct_invocation = enclave.clone(); + thread::spawn(move || { + println!( + "[+] Trusted RPC direct invocation server listening on {}", + direct_invocation_server_addr ); - } + enclave_for_direct_invocation + .init_direct_invocation_server(direct_invocation_server_addr) + .unwrap(); + println!("[+] RPC direct invocation server shut down"); + }); // ------------------------------------------------------------------------ // Init parentchain specific stuff. Needed for parentchain communication. @@ -504,154 +446,64 @@ fn start_worker( #[cfg(feature = "dcap")] let register_xt = move || enclave2.generate_dcap_ra_extrinsic(&trusted_url2, skip_ra).unwrap(); - let mut register_enclave_xt_header: Option
= None; - let mut we_are_primary_validateer: bool = false; - let send_register_xt = move || { println!("[+] Send register enclave extrinsic"); send_extrinsic(register_xt(), &node_api2, &tee_accountid2, is_development_mode) }; - // litentry: check if the enclave is already registered - // TODO: revisit the registration process (P-10) - match litentry_rpc_api.get_keys(storage_key("Teerex", "EnclaveRegistry"), None) { - Ok(Some(keys)) => { - let trusted_url = trusted_url.as_bytes().to_vec(); - let mrenclave = mrenclave.0.to_vec(); - let mut found = false; - for key in keys { - let key = if key.starts_with("0x") { - let bytes = &key.as_bytes()[b"0x".len()..]; - hex::decode(bytes).unwrap() - } else { - hex::decode(key.as_bytes()).unwrap() - }; - match litentry_rpc_api.get_storage_by_key::>>( - StorageKey(key.clone()), - None, - ) { - Ok(Some(value)) => { - if value.mr_enclave.to_vec() == mrenclave && value.url == trusted_url { - // After calling the perform_ra function, the nonce will be incremented by 1, - // so enclave is already registered, we should reset the nonce_cache - let nonce = - litentry_rpc_api.get_account_next_index(&tee_accountid).unwrap(); - enclave - .set_nonce(nonce, ParentchainId::Litentry) - .expect("Could not set nonce of enclave. Returning here..."); - found = true; - info!("fond enclave: {:?}", value); - break - } - }, - Ok(None) => { - warn!("not found from key: {:?}", key); - }, - Err(_) => {}, - } - } - if !found { - // Todo: Can't unwrap here because the extrinsic is for some reason not found in the block - // even if it was successful: https://github.com/scs/substrate-api-client/issues/624. - let register_enclave_block_hash = send_register_xt(); - let api_register_enclave_xt_header = - litentry_rpc_api.get_header(register_enclave_block_hash).unwrap().unwrap(); - - // TODO: #1451: Fix api-client type hacks - // TODO(Litentry): keep an eye on it - it's a hacky way to convert `SubstrateHeader` to `Header` - let header = - Header::decode(&mut api_register_enclave_xt_header.encode().as_slice()) - .expect("Can decode previously encoded header; qed"); - - println!( - "[+] Enclave registered at block number: {:?}, hash: {:?}", - header.number(), - header.hash() - ); + // Litentry: send the registration extrinsic regardless of being registered or not, + // the reason is the mrenclave could change in between, so we rely on the + // on-chain logic to handle everything. + // this is the same behavior as upstream + let register_enclave_block_hash = + send_register_xt().expect("enclave RA registration must be successful to continue"); + + let api_register_enclave_xt_header = + litentry_rpc_api.get_header(Some(register_enclave_block_hash)).unwrap().unwrap(); + + // TODO: #1451: Fix api-client type hacks + let register_enclave_xt_header = + Header::decode(&mut api_register_enclave_xt_header.encode().as_slice()) + .expect("Can decode previously encoded header; qed"); + + println!( + "[+] Enclave registered at block number: {:?}, hash: {:?}", + register_enclave_xt_header.number(), + register_enclave_xt_header.hash() + ); - register_enclave_xt_header = Some(header); - } - }, - _ => panic!("unknown error"), - } + // double-check + let my_enclave = litentry_rpc_api + .enclave(&tee_accountid, None) + .unwrap() + .expect("our enclave should be registered at this point"); + trace!("verified that our enclave is registered: {:?}", my_enclave); - if let Some(register_enclave_xt_header) = register_enclave_xt_header.clone() { - we_are_primary_validateer = - we_are_primary_worker(&litentry_rpc_api, ®ister_enclave_xt_header).unwrap(); - } + let is_primary_enclave = match litentry_rpc_api + .primary_enclave_identifier_for_shard(WorkerType::BitAcross, shard, None) + .unwrap() + { + Some(account) => account == tee_accountid, + None => false, + }; - if we_are_primary_validateer { - println!("[+] We are the primary worker"); + if is_primary_enclave { + println!("[+] We are the primary enclave"); } else { - println!("[+] We are NOT the primary worker"); + println!("[+] We are NOT the primary enclave"); } initialization_handler.registered_on_parentchain(); - match WorkerModeProvider::worker_mode() { - WorkerMode::Teeracle => { - // ------------------------------------------------------------------------ - // initialize teeracle interval - #[cfg(feature = "teeracle")] - schedule_periodic_reregistration_thread( - send_register_xt, - run_config.reregister_teeracle_interval(), - ); - - #[cfg(feature = "teeracle")] - start_periodic_market_update( - &litentry_rpc_api, - run_config.teeracle_update_interval(), - enclave.as_ref(), - &tokio_handle, - ); - }, - WorkerMode::OffChainWorker => { - println!("*** [+] Finished initializing light client, syncing parentchain..."); - - // Syncing all parentchain blocks, this might take a while.. - let last_synced_header = - parentchain_handler.sync_parentchain(last_synced_header, 0, true).unwrap(); + println!("*** [+] Finished initializing light client, syncing parentchain..."); - start_parentchain_header_subscription_thread(parentchain_handler, last_synced_header); + // Syncing all parentchain blocks, this might take a while.. + let last_synced_header = + parentchain_handler.sync_parentchain(last_synced_header, 0, true).unwrap(); - info!("skipping shard vault check because not yet supported for offchain worker"); - }, - WorkerMode::Sidechain => { - println!("*** [+] Finished initializing light client, syncing parentchain..."); - - // Litentry: apply skipped parentchain block - let parentchain_start_block = config - .try_parse_parentchain_start_block() - .expect("parentchain start block to be a valid number"); - - println!( - "*** [+] last_synced_header: {}, config.parentchain_start_block: {}", - last_synced_header.number, parentchain_start_block - ); + start_parentchain_header_subscription_thread(parentchain_handler, last_synced_header); - // ------------------------------------------------------------------------ - // Initialize the sidechain - let last_synced_header = sidechain_init_block_production( - enclave.clone(), - register_enclave_xt_header, - we_are_primary_validateer, - parentchain_handler.clone(), - sidechain_storage, - &last_synced_header, - parentchain_start_block, - config.clone().fail_slot_mode, - config.fail_at, - ) - .unwrap(); - - start_parentchain_header_subscription_thread(parentchain_handler, last_synced_header); - - init_provided_shard_vault(shard, &enclave, we_are_primary_validateer); - - spawn_worker_for_shard_polling(shard, litentry_rpc_api.clone(), initialization_handler); - }, - } + info!("skipping shard vault check because not yet supported for offchain worker"); if let Some(url) = config.target_a_parentchain_rpc_endpoint() { init_target_parentchain( @@ -674,6 +526,8 @@ fn start_worker( is_development_mode, ) } + // Publish generated custiodian wallets + enclave.publish_wallets(); // ------------------------------------------------------------------------ // Subscribe to events and print them. @@ -690,14 +544,14 @@ fn start_worker( fn init_provided_shard_vault( shard: &ShardIdentifier, enclave: &Arc, - we_are_primary_validateer: bool, + is_primary_enclave: bool, ) { if let Ok(shard_vault) = enclave.get_ecc_vault_pubkey(shard) { println!( "[Litentry] shard vault account is already initialized in state: {}", shard_vault.to_ss58check() ); - } else if we_are_primary_validateer { + } else if is_primary_enclave { println!("[Litentry] initializing proxied shard vault account now"); enclave.init_proxied_shard_vault(shard, &ParentchainId::Litentry).unwrap(); println!( @@ -735,18 +589,17 @@ fn init_target_parentchain( let (parentchain_handler, last_synched_header) = init_parentchain(enclave, &node_api, tee_account_id, parentchain_id); - if WorkerModeProvider::worker_mode() != WorkerMode::Teeracle { - println!( - "*** [+] [{:?}] Finished initializing light client, syncing parentchain...", - parentchain_id - ); + println!( + "*** [+] [{:?}] Finished initializing light client, syncing parentchain...", + parentchain_id + ); - // Syncing all parentchain blocks, this might take a while.. - let last_synched_header = - parentchain_handler.sync_parentchain(last_synched_header, 0, true).unwrap(); + // Syncing all parentchain blocks, this might take a while.. + let last_synched_header = + parentchain_handler.sync_parentchain(last_synched_header, 0, true).unwrap(); + + start_parentchain_header_subscription_thread(parentchain_handler, last_synched_header); - start_parentchain_header_subscription_thread(parentchain_handler, last_synched_header) - } println!("[{:?}] initializing proxied shard vault account now", parentchain_id); enclave.init_proxied_shard_vault(shard, &parentchain_id).unwrap(); @@ -785,7 +638,7 @@ where let last_synced_header = parentchain_handler.init_parentchain_components().unwrap(); println!("[{:?}] last synced parentchain block: {}", parentchain_id, last_synced_header.number); - let nonce = node_api.get_nonce_of(tee_account_id).unwrap(); + let nonce = node_api.get_account_next_index(tee_account_id).unwrap(); info!("[{:?}] Enclave nonce = {:?}", parentchain_id, nonce); enclave.set_nonce(nonce, parentchain_id).unwrap_or_else(|_| { panic!("[{:?}] Could not set nonce of enclave. Returning here...", parentchain_id) @@ -807,9 +660,8 @@ where } /// Start polling loop to wait until we have a worker for a shard registered on -/// the parentchain (TEEREX WorkerForShard). This is the pre-requisite to be +/// the parentchain (TEEBAG EnclaveIdentifier). This is the pre-requisite to be /// considered initialized and ready for the next worker to start (in sidechain mode only). -/// considered initialized and ready for the next worker to start. fn spawn_worker_for_shard_polling( shard: &ShardIdentifier, node_api: ParentchainApi, @@ -823,7 +675,11 @@ fn spawn_worker_for_shard_polling( loop { info!("Polling for worker for shard ({} seconds interval)", POLL_INTERVAL_SECS); - if let Ok(Some(_enclave)) = node_api.worker_for_shard(&shard_for_initialized, None) { + if let Ok(Some(_account)) = node_api.primary_enclave_identifier_for_shard( + WorkerType::BitAcross, + &shard_for_initialized, + None, + ) { // Set that the service is initialized. initialization_handler.worker_for_shard_registered(); println!("[+] Found `WorkerForShard` on parentchain state",); @@ -1036,13 +892,3 @@ pub fn enclave_account(enclave_api: &E) -> AccountId32 { trace!("[+] Got ed25519 account of TEE = {}", tee_public.to_ss58check()); AccountId32::from(*tee_public.as_array_ref()) } - -/// Checks if we are the first validateer to register on the parentchain. -fn we_are_primary_worker( - node_api: &ParentchainApi, - register_enclave_xt_header: &Header, -) -> Result { - let enclave_count_of_previous_block = - node_api.enclave_count(Some(*register_enclave_xt_header.parent_hash()))?; - Ok(enclave_count_of_previous_block == 0) -} diff --git a/bitacross-worker/service/src/ocall_bridge/bridge_api.rs b/bitacross-worker/service/src/ocall_bridge/bridge_api.rs index 71899760c1..085b9b9fb4 100644 --- a/bitacross-worker/service/src/ocall_bridge/bridge_api.rs +++ b/bitacross-worker/service/src/ocall_bridge/bridge_api.rs @@ -52,14 +52,6 @@ impl Bridge { .get_ra_api() } - pub fn get_sidechain_api() -> Arc { - COMPONENT_FACTORY - .read() - .as_ref() - .expect("Component factory has not been set. Use `initialize()`") - .get_sidechain_api() - } - pub fn get_oc_api() -> Arc { debug!("Requesting WorkerOnChain OCall API instance"); @@ -101,9 +93,6 @@ pub trait GetOCallBridgeComponents { /// remote attestation OCall API fn get_ra_api(&self) -> Arc; - /// side chain OCall API - fn get_sidechain_api(&self) -> Arc; - /// on chain (parentchain) OCall API fn get_oc_api(&self) -> Arc; @@ -223,23 +212,6 @@ pub trait MetricsBridge { fn update_metric(&self, metric_encoded: Vec) -> OCallBridgeResult<()>; } -/// Trait for all the OCalls related to sidechain operations -#[cfg_attr(test, automock)] -pub trait SidechainBridge { - fn propose_sidechain_blocks(&self, signed_blocks_encoded: Vec) -> OCallBridgeResult<()>; - - fn store_sidechain_blocks(&self, signed_blocks_encoded: Vec) -> OCallBridgeResult<()>; - - fn fetch_sidechain_blocks_from_peer( - &self, - last_imported_block_hash_encoded: Vec, - maybe_until_block_hash_encoded: Vec, - shard_identifier_encoded: Vec, - ) -> OCallBridgeResult>; - - fn get_trusted_peers_urls(&self) -> OCallBridgeResult>; -} - /// type for IPFS pub type Cid = [u8; 46]; diff --git a/bitacross-worker/service/src/ocall_bridge/component_factory.rs b/bitacross-worker/service/src/ocall_bridge/component_factory.rs index e23c509101..506f50a0a3 100644 --- a/bitacross-worker/service/src/ocall_bridge/component_factory.rs +++ b/bitacross-worker/service/src/ocall_bridge/component_factory.rs @@ -21,23 +21,18 @@ use crate::{ ocall_bridge::{ bridge_api::{ GetOCallBridgeComponents, IpfsBridge, MetricsBridge, RemoteAttestationBridge, - SidechainBridge, WorkerOnChainBridge, + WorkerOnChainBridge, }, ipfs_ocall::IpfsOCall, metrics_ocall::MetricsOCall, remote_attestation_ocall::RemoteAttestationOCall, - sidechain_ocall::SidechainOCall, worker_on_chain_ocall::WorkerOnChainOCall, }, prometheus_metrics::ReceiveEnclaveMetrics, - sync_block_broadcaster::BroadcastBlocks, worker_peers_registry::PeersRegistry, }; use itp_enclave_api::{enclave_base::EnclaveBase, remote_attestation::RemoteAttestationCallBacks}; use itp_node_api::node_api_factory::CreateNodeApi; -use its_peer_fetch::FetchBlocksFromPeer; -use its_primitives::types::block::SignedBlock as SignedSidechainBlock; -use its_storage::BlockStorage; use std::sync::Arc; /// Concrete implementation, should be moved out of the OCall Bridge, into the worker @@ -45,57 +40,30 @@ use std::sync::Arc; /// our dependency graph is worker -> ocall bridge pub struct OCallBridgeComponentFactory< NodeApi, - Broadcaster, EnclaveApi, - Storage, WorkerPeersRegistry, - PeerBlockFetcher, TokioHandle, MetricsReceiver, > { integritee_rpc_api_factory: Arc, target_a_parentchain_rpc_api_factory: Option>, target_b_parentchain_rpc_api_factory: Option>, - block_broadcaster: Arc, enclave_api: Arc, - block_storage: Arc, peers_registry: Arc, - peer_block_fetcher: Arc, tokio_handle: Arc, metrics_receiver: Arc, } -impl< - NodeApi, - Broadcaster, - EnclaveApi, - Storage, - WorkerPeersRegistry, - PeerBlockFetcher, - TokioHandle, - MetricsReceiver, - > - OCallBridgeComponentFactory< - NodeApi, - Broadcaster, - EnclaveApi, - Storage, - WorkerPeersRegistry, - PeerBlockFetcher, - TokioHandle, - MetricsReceiver, - > +impl + OCallBridgeComponentFactory { #[allow(clippy::too_many_arguments)] pub fn new( integritee_rpc_api_factory: Arc, target_a_parentchain_rpc_api_factory: Option>, target_b_parentchain_rpc_api_factory: Option>, - block_broadcaster: Arc, enclave_api: Arc, - block_storage: Arc, peers_registry: Arc, - peer_block_fetcher: Arc, tokio_handle: Arc, metrics_receiver: Arc, ) -> Self { @@ -103,43 +71,26 @@ impl< integritee_rpc_api_factory, target_a_parentchain_rpc_api_factory, target_b_parentchain_rpc_api_factory, - block_broadcaster, enclave_api, - block_storage, peers_registry, - peer_block_fetcher, tokio_handle, metrics_receiver, } } } -impl< - NodeApi, - Broadcaster, - EnclaveApi, - Storage, - WorkerPeersRegistry, - PeerBlockFetcher, - TokioHandle, - MetricsReceiver, - > GetOCallBridgeComponents +impl + GetOCallBridgeComponents for OCallBridgeComponentFactory< NodeApi, - Broadcaster, EnclaveApi, - Storage, WorkerPeersRegistry, - PeerBlockFetcher, TokioHandle, MetricsReceiver, > where NodeApi: CreateNodeApi + 'static, - Broadcaster: BroadcastBlocks + 'static, EnclaveApi: EnclaveBase + RemoteAttestationCallBacks + 'static, - Storage: BlockStorage + 'static, WorkerPeersRegistry: PeersRegistry + 'static, - PeerBlockFetcher: FetchBlocksFromPeer + 'static, TokioHandle: GetTokioHandle + 'static, MetricsReceiver: ReceiveEnclaveMetrics + 'static, { @@ -147,16 +98,6 @@ impl< Arc::new(RemoteAttestationOCall::new(self.enclave_api.clone())) } - fn get_sidechain_api(&self) -> Arc { - Arc::new(SidechainOCall::new( - self.block_broadcaster.clone(), - self.block_storage.clone(), - self.peers_registry.clone(), - self.peer_block_fetcher.clone(), - self.tokio_handle.clone(), - )) - } - fn get_oc_api(&self) -> Arc { Arc::new(WorkerOnChainOCall::new( self.enclave_api.clone(), diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/fetch_sidechain_blocks_from_peer.rs b/bitacross-worker/service/src/ocall_bridge/ffi/fetch_sidechain_blocks_from_peer.rs deleted file mode 100644 index c6c8b9e89e..0000000000 --- a/bitacross-worker/service/src/ocall_bridge/ffi/fetch_sidechain_blocks_from_peer.rs +++ /dev/null @@ -1,193 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::ocall_bridge::bridge_api::{Bridge, SidechainBridge}; -use itp_utils::write_slice_and_whitespace_pad; -use log::*; -use sgx_types::sgx_status_t; -use std::{slice, sync::Arc}; - -/// # Safety -/// -/// FFI are always unsafe -#[no_mangle] -pub unsafe extern "C" fn ocall_fetch_sidechain_blocks_from_peer( - last_imported_block_hash_ptr: *const u8, - last_imported_block_hash_size: u32, - maybe_until_block_hash_ptr: *const u8, - maybe_until_block_hash_size: u32, - shard_identifier_ptr: *const u8, - shard_identifier_size: u32, - sidechain_blocks_ptr: *mut u8, - sidechain_blocks_size: u32, -) -> sgx_status_t { - fetch_sidechain_blocks_from_peer( - last_imported_block_hash_ptr, - last_imported_block_hash_size, - maybe_until_block_hash_ptr, - maybe_until_block_hash_size, - shard_identifier_ptr, - shard_identifier_size, - sidechain_blocks_ptr, - sidechain_blocks_size, - Bridge::get_sidechain_api(), - ) -} - -#[allow(clippy::too_many_arguments)] -fn fetch_sidechain_blocks_from_peer( - last_imported_block_hash_ptr: *const u8, - last_imported_block_hash_size: u32, - maybe_until_block_hash_ptr: *const u8, - maybe_until_block_hash_size: u32, - shard_identifier_ptr: *const u8, - shard_identifier_size: u32, - sidechain_blocks_ptr: *mut u8, - sidechain_blocks_size: u32, - sidechain_api: Arc, -) -> sgx_status_t { - let last_imported_block_hash_encoded = unsafe { - Vec::from(slice::from_raw_parts( - last_imported_block_hash_ptr, - last_imported_block_hash_size as usize, - )) - }; - let maybe_until_block_hash = unsafe { - Vec::from(slice::from_raw_parts( - maybe_until_block_hash_ptr, - maybe_until_block_hash_size as usize, - )) - }; - let shard_identifier_encoded = unsafe { - Vec::from(slice::from_raw_parts(shard_identifier_ptr, shard_identifier_size as usize)) - }; - - let sidechain_blocks_encoded = match sidechain_api.fetch_sidechain_blocks_from_peer( - last_imported_block_hash_encoded, - maybe_until_block_hash, - shard_identifier_encoded, - ) { - Ok(r) => r, - Err(e) => { - error!("fetch sidechain blocks from peer failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let sidechain_blocks_encoded_slice = - unsafe { slice::from_raw_parts_mut(sidechain_blocks_ptr, sidechain_blocks_size as usize) }; - if let Err(e) = - write_slice_and_whitespace_pad(sidechain_blocks_encoded_slice, sidechain_blocks_encoded) - { - error!("Failed to transfer encoded sidechain blocks to o-call buffer: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - } - - sgx_status_t::SGX_SUCCESS -} - -#[cfg(test)] -mod tests { - - use super::*; - use crate::ocall_bridge::test::mocks::sidechain_bridge_mock::SidechainBridgeMock; - use codec::{Decode, Encode}; - use its_primitives::types::block::SignedBlock; - use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; - use primitive_types::H256; - - #[test] - fn fetch_sidechain_blocks_from_peer_works() { - let sidechain_blocks = vec![ - SidechainBlockBuilder::random().build_signed(), - SidechainBlockBuilder::random().build_signed(), - ]; - - let sidechain_bridge_mock = - Arc::new(SidechainBridgeMock::default().with_peer_blocks(sidechain_blocks.encode())); - - let last_known_block_hash = H256::random(); - let shard_identifier = H256::random(); - let mut block_buffer = vec![0; 16 * 4096]; - - let result = call_fetch_sidechain_blocks_from_peer( - last_known_block_hash, - None, - shard_identifier, - &mut block_buffer, - sidechain_bridge_mock, - ); - - let decoded_blocks: Vec = - Decode::decode(&mut block_buffer.as_slice()).unwrap(); - - assert_eq!(result, sgx_status_t::SGX_SUCCESS); - assert_eq!(sidechain_blocks, decoded_blocks); - } - - #[test] - fn returns_error_if_buffer_is_too_small() { - let sidechain_blocks = vec![ - SidechainBlockBuilder::random().build_signed(), - SidechainBlockBuilder::random().build_signed(), - SidechainBlockBuilder::random().build_signed(), - SidechainBlockBuilder::random().build_signed(), - ]; - - let sidechain_bridge_mock = - Arc::new(SidechainBridgeMock::default().with_peer_blocks(sidechain_blocks.encode())); - - let last_known_block_hash = H256::random(); - let shard_identifier = H256::random(); - let mut block_buffer = vec![0; 16]; // way too small to hold the encoded blocks - - let result = call_fetch_sidechain_blocks_from_peer( - last_known_block_hash, - None, - shard_identifier, - &mut block_buffer, - sidechain_bridge_mock, - ); - - assert_eq!(result, sgx_status_t::SGX_ERROR_UNEXPECTED); - } - - fn call_fetch_sidechain_blocks_from_peer( - last_imported_block_hash: H256, - maybe_until_block_hash: Option, - shard_identifier: H256, - buffer: &mut Vec, - sidechain_bridge: Arc, - ) -> sgx_status_t { - let last_imported_block_hash_encoded = last_imported_block_hash.encode(); - let maybe_until_block_hash_encoded = maybe_until_block_hash.encode(); - let shard_identifier_encoded = shard_identifier.encode(); - - fetch_sidechain_blocks_from_peer( - last_imported_block_hash_encoded.as_ptr(), - last_imported_block_hash_encoded.len() as u32, - maybe_until_block_hash_encoded.as_ptr(), - maybe_until_block_hash_encoded.len() as u32, - shard_identifier_encoded.as_ptr(), - shard_identifier_encoded.len() as u32, - buffer.as_mut_ptr(), - buffer.len() as u32, - sidechain_bridge, - ) - } -} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/get_peers.rs b/bitacross-worker/service/src/ocall_bridge/ffi/get_peers.rs deleted file mode 100644 index 2cc380d6e4..0000000000 --- a/bitacross-worker/service/src/ocall_bridge/ffi/get_peers.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::ocall_bridge::bridge_api::{Bridge, SidechainBridge}; -use itp_utils::write_slice_and_whitespace_pad; -use log::*; -use sgx_types::sgx_status_t; -use std::{slice, sync::Arc}; - -#[no_mangle] -pub unsafe extern "C" fn ocall_get_trusted_peers_urls( - peers_ptr: *mut u8, - peers_size: u32, -) -> sgx_status_t { - get_trusted_peers_urls(peers_ptr, peers_size, Bridge::get_sidechain_api()) -} - -fn get_trusted_peers_urls( - peers_ptr: *mut u8, - peers_size: u32, - sidechain_api: Arc, -) -> sgx_status_t { - debug!(" Entering ocall_get_trusted_peers_urls"); - - let peers_encoded = match sidechain_api.get_trusted_peers_urls() { - Ok(r) => r, - Err(e) => { - error!("get peers failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let peers_encoded_slice = unsafe { slice::from_raw_parts_mut(peers_ptr, peers_size as usize) }; - if let Err(e) = write_slice_and_whitespace_pad(peers_encoded_slice, peers_encoded) { - error!("Failed to transfer encoded peers to o-call buffer: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - } - - sgx_status_t::SGX_SUCCESS -} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/mod.rs b/bitacross-worker/service/src/ocall_bridge/ffi/mod.rs index d146db1046..b18f24bf15 100644 --- a/bitacross-worker/service/src/ocall_bridge/ffi/mod.rs +++ b/bitacross-worker/service/src/ocall_bridge/ffi/mod.rs @@ -21,16 +21,12 @@ //! These should just be wrappers that transform the C-API structures and call the //! actual implementation of the OCalls (using the traits defined in the bridge_api). -pub mod fetch_sidechain_blocks_from_peer; pub mod get_ias_socket; -pub mod get_peers; pub mod get_quote; pub mod get_qve_report_on_quote; pub mod get_update_info; pub mod init_quote; pub mod ipfs; -pub mod propose_sidechain_blocks; pub mod send_to_parentchain; -pub mod store_sidechain_blocks; pub mod update_metric; pub mod worker_request; diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/propose_sidechain_blocks.rs b/bitacross-worker/service/src/ocall_bridge/ffi/propose_sidechain_blocks.rs deleted file mode 100644 index 21ff07d0bb..0000000000 --- a/bitacross-worker/service/src/ocall_bridge/ffi/propose_sidechain_blocks.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::ocall_bridge::bridge_api::{Bridge, SidechainBridge}; -use log::*; -use sgx_types::sgx_status_t; -use std::{slice, sync::Arc}; - -/// # Safety -/// -/// FFI are always unsafe -#[no_mangle] -pub unsafe extern "C" fn ocall_propose_sidechain_blocks( - signed_blocks_ptr: *const u8, - signed_blocks_size: u32, -) -> sgx_status_t { - propose_sidechain_blocks(signed_blocks_ptr, signed_blocks_size, Bridge::get_sidechain_api()) -} - -fn propose_sidechain_blocks( - signed_blocks_ptr: *const u8, - signed_blocks_size: u32, - sidechain_api: Arc, -) -> sgx_status_t { - let signed_blocks_vec: Vec = - unsafe { Vec::from(slice::from_raw_parts(signed_blocks_ptr, signed_blocks_size as usize)) }; - - match sidechain_api.propose_sidechain_blocks(signed_blocks_vec) { - Ok(_) => sgx_status_t::SGX_SUCCESS, - Err(e) => { - error!("send sidechain blocks failed: {:?}", e); - sgx_status_t::SGX_ERROR_UNEXPECTED - }, - } -} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/store_sidechain_blocks.rs b/bitacross-worker/service/src/ocall_bridge/ffi/store_sidechain_blocks.rs deleted file mode 100644 index 70361d8fd7..0000000000 --- a/bitacross-worker/service/src/ocall_bridge/ffi/store_sidechain_blocks.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::ocall_bridge::bridge_api::{Bridge, SidechainBridge}; -use log::*; -use sgx_types::sgx_status_t; -use std::{slice, sync::Arc}; - -/// # Safety -/// -/// FFI are always unsafe -#[no_mangle] -pub unsafe extern "C" fn ocall_store_sidechain_blocks( - signed_blocks_ptr: *const u8, - signed_blocks_size: u32, -) -> sgx_status_t { - store_sidechain_blocks(signed_blocks_ptr, signed_blocks_size, Bridge::get_sidechain_api()) -} - -fn store_sidechain_blocks( - signed_blocks_ptr: *const u8, - signed_blocks_size: u32, - sidechain_api: Arc, -) -> sgx_status_t { - let signed_blocks_vec: Vec = - unsafe { Vec::from(slice::from_raw_parts(signed_blocks_ptr, signed_blocks_size as usize)) }; - - match sidechain_api.store_sidechain_blocks(signed_blocks_vec) { - Ok(_) => sgx_status_t::SGX_SUCCESS, - Err(e) => { - error!("store sidechain blocks failed: {:?}", e); - sgx_status_t::SGX_ERROR_UNEXPECTED - }, - } -} diff --git a/bitacross-worker/service/src/ocall_bridge/mod.rs b/bitacross-worker/service/src/ocall_bridge/mod.rs index 91a5f8887f..db5775cec3 100644 --- a/bitacross-worker/service/src/ocall_bridge/mod.rs +++ b/bitacross-worker/service/src/ocall_bridge/mod.rs @@ -25,8 +25,4 @@ mod ffi; mod ipfs_ocall; mod metrics_ocall; mod remote_attestation_ocall; -mod sidechain_ocall; mod worker_on_chain_ocall; - -#[cfg(test)] -pub mod test; diff --git a/bitacross-worker/service/src/ocall_bridge/sidechain_ocall.rs b/bitacross-worker/service/src/ocall_bridge/sidechain_ocall.rs deleted file mode 100644 index 667901cced..0000000000 --- a/bitacross-worker/service/src/ocall_bridge/sidechain_ocall.rs +++ /dev/null @@ -1,282 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - globals::tokio_handle::GetTokioHandle, - ocall_bridge::bridge_api::{OCallBridgeError, OCallBridgeResult, SidechainBridge}, - sync_block_broadcaster::BroadcastBlocks, - worker_peers_registry::PeersRegistry, -}; -use codec::{Decode, Encode}; -use itp_types::{BlockHash, ShardIdentifier}; -use its_peer_fetch::FetchBlocksFromPeer; -use its_primitives::{traits::Block, types::SignedBlock as SignedSidechainBlock}; -use its_storage::BlockStorage; -use log::*; -use std::sync::Arc; - -pub struct SidechainOCall< - BlockBroadcaster, - Storage, - WorkerPeerRegistry, - PeerBlockFetcher, - TokioHandle, -> { - block_broadcaster: Arc, - block_storage: Arc, - peer_registry: Arc, - peer_block_fetcher: Arc, - tokio_handle: Arc, -} - -impl - SidechainOCall -{ - pub fn new( - block_broadcaster: Arc, - block_storage: Arc, - peer_registry: Arc, - peer_block_fetcher: Arc, - tokio_handle: Arc, - ) -> Self { - SidechainOCall { - block_broadcaster, - block_storage, - peer_registry, - peer_block_fetcher, - tokio_handle, - } - } -} - -impl SidechainBridge - for SidechainOCall -where - BlockBroadcaster: BroadcastBlocks, - Storage: BlockStorage, - WorkerPeerRegistry: PeersRegistry, - PeerBlockFetcher: FetchBlocksFromPeer, - TokioHandle: GetTokioHandle, -{ - fn propose_sidechain_blocks(&self, signed_blocks_encoded: Vec) -> OCallBridgeResult<()> { - // TODO: improve error handling, using a mut status is not good design? - let mut status: OCallBridgeResult<()> = Ok(()); - - // handle blocks - let signed_blocks: Vec = - match Decode::decode(&mut signed_blocks_encoded.as_slice()) { - Ok(blocks) => blocks, - Err(_) => { - status = Err(OCallBridgeError::ProposeSidechainBlock( - "Could not decode signed blocks".to_string(), - )); - vec![] - }, - }; - - if !signed_blocks.is_empty() { - info!( - "Enclave produced sidechain blocks: {:?}", - signed_blocks - .iter() - .map(|b| b.block.header().block_number) - .collect::>() - ); - } else { - debug!("Enclave did not produce sidechain blocks"); - } - - // FIXME: When & where should peers be updated? - debug!("Updating peers.."); - if let Err(e) = self.peer_registry.update_peers() { - error!("Error updating peers: {:?}", e); - // Fixme: returning an error here results in a `HeaderAncestryMismatch` error. - // status = sgx_status_t::SGX_ERROR_UNEXPECTED; - } else { - info!("Successfully updated peers"); - } - - debug!("Broadcasting sidechain blocks ..."); - if let Err(e) = self.block_broadcaster.broadcast_blocks(signed_blocks) { - error!("Error broadcasting blocks: {:?}", e); - // Fixme: returning an error here results in a `HeaderAncestryMismatch` error. - // status = sgx_status_t::SGX_ERROR_UNEXPECTED; - } else { - info!("Successfully broadcast blocks"); - } - - status - } - - fn store_sidechain_blocks(&self, signed_blocks_encoded: Vec) -> OCallBridgeResult<()> { - // TODO: improve error handling, using a mut status is not good design? - let mut status: OCallBridgeResult<()> = Ok(()); - - let signed_blocks: Vec = - match Decode::decode(&mut signed_blocks_encoded.as_slice()) { - Ok(blocks) => blocks, - Err(_) => { - status = Err(OCallBridgeError::ProposeSidechainBlock( - "Could not decode signed blocks".to_string(), - )); - vec![] - }, - }; - - if let Err(e) = self.block_storage.store_blocks(signed_blocks) { - error!("Error storing blocks: {:?}", e); - } - - status - } - - fn fetch_sidechain_blocks_from_peer( - &self, - last_imported_block_hash_encoded: Vec, - maybe_until_block_hash_encoded: Vec, - shard_identifier_encoded: Vec, - ) -> OCallBridgeResult> { - let last_imported_block_hash: BlockHash = - Decode::decode(&mut last_imported_block_hash_encoded.as_slice()).map_err(|_| { - OCallBridgeError::FetchSidechainBlocksFromPeer( - "Failed to decode last imported block hash".to_string(), - ) - })?; - - let maybe_until_block_hash: Option = - Decode::decode(&mut maybe_until_block_hash_encoded.as_slice()).map_err(|_| { - OCallBridgeError::FetchSidechainBlocksFromPeer( - "Failed to decode optional until block hash".to_string(), - ) - })?; - - let shard_identifier: ShardIdentifier = - Decode::decode(&mut shard_identifier_encoded.as_slice()).map_err(|_| { - OCallBridgeError::FetchSidechainBlocksFromPeer( - "Failed to decode shard identifier".to_string(), - ) - })?; - - info!("[O-call] fetching blocks from peer.."); - - let tokio_handle = self.tokio_handle.get_handle(); - - let signed_sidechain_blocks = tokio_handle - .block_on(self.peer_block_fetcher.fetch_blocks_from_peer( - last_imported_block_hash, - maybe_until_block_hash, - shard_identifier, - )) - .map_err(|e| { - OCallBridgeError::FetchSidechainBlocksFromPeer(format!( - "Failed to execute block fetching from peer: {:?}", - e - )) - })?; - - info!("[O-call] successfully fetched {} blocks from peer", signed_sidechain_blocks.len()); - - Ok(signed_sidechain_blocks.encode()) - } - - fn get_trusted_peers_urls(&self) -> OCallBridgeResult> { - let peers = self.peer_registry.read_trusted_peers().unwrap(); - Ok(peers.encode()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - globals::tokio_handle::ScopedTokioHandle, - tests::mocks::{ - broadcast_blocks_mock::BroadcastBlocksMock, - update_worker_peers_mock::WorkerPeersRegistryMock, - }, - }; - use codec::Decode; - use its_peer_fetch::mocks::fetch_blocks_from_peer_mock::FetchBlocksFromPeerMock; - use its_primitives::types::block::SignedBlock as SignedSidechainBlock; - use its_storage::{interface::BlockStorage, Result as StorageResult}; - use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; - use primitive_types::H256; - use std::{collections::HashMap, vec::Vec}; - - struct BlockStorageMock; - impl BlockStorage for BlockStorageMock { - fn store_blocks(&self, _blocks: Vec) -> StorageResult<()> { - Ok(()) - } - } - - type TestSidechainOCall = SidechainOCall< - BroadcastBlocksMock, - BlockStorageMock, - WorkerPeersRegistryMock, - FetchBlocksFromPeerMock, - ScopedTokioHandle, - >; - - #[test] - fn fetch_sidechain_blocks_from_peer_works() { - let last_imported_block_hash = H256::random(); - let until_block_hash: Option = None; - let shard_identifier = H256::random(); - let blocks = vec![ - SidechainBlockBuilder::random().build_signed(), - SidechainBlockBuilder::random().build_signed(), - ]; - let peer_blocks_map = HashMap::from([(shard_identifier, blocks.clone())]); - let sidechain_ocall = setup_sidechain_ocall_with_peer_blocks(peer_blocks_map); - - let fetched_blocks_encoded = sidechain_ocall - .fetch_sidechain_blocks_from_peer( - last_imported_block_hash.encode(), - until_block_hash.encode(), - shard_identifier.encode(), - ) - .unwrap(); - - let fetched_blocks_decoded: Vec = - Decode::decode(&mut fetched_blocks_encoded.as_slice()).unwrap(); - - assert_eq!(blocks, fetched_blocks_decoded); - } - - fn setup_sidechain_ocall_with_peer_blocks( - peer_blocks_map: HashMap>, - ) -> TestSidechainOCall { - let block_broadcaster_mock = Arc::new(BroadcastBlocksMock {}); - let block_storage_mock = Arc::new(BlockStorageMock {}); - let worker_peers_registry_mock = Arc::new(WorkerPeersRegistryMock {}); - let peer_block_fetcher_mock = Arc::new( - FetchBlocksFromPeerMock::::default() - .with_signed_blocks(peer_blocks_map), - ); - let scoped_tokio_handle = Arc::new(ScopedTokioHandle::default()); - - SidechainOCall::new( - block_broadcaster_mock, - block_storage_mock, - worker_peers_registry_mock, - peer_block_fetcher_mock, - scoped_tokio_handle, - ) - } -} diff --git a/bitacross-worker/service/src/ocall_bridge/test/mocks/mod.rs b/bitacross-worker/service/src/ocall_bridge/test/mocks/mod.rs deleted file mode 100644 index 298b05435a..0000000000 --- a/bitacross-worker/service/src/ocall_bridge/test/mocks/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub mod sidechain_bridge_mock; diff --git a/bitacross-worker/service/src/ocall_bridge/test/mocks/sidechain_bridge_mock.rs b/bitacross-worker/service/src/ocall_bridge/test/mocks/sidechain_bridge_mock.rs deleted file mode 100644 index dc1ba7d8da..0000000000 --- a/bitacross-worker/service/src/ocall_bridge/test/mocks/sidechain_bridge_mock.rs +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::ocall_bridge::bridge_api::{OCallBridgeResult, SidechainBridge}; - -#[derive(Default)] -pub struct SidechainBridgeMock { - peer_blocks_encoded: Vec, -} - -impl SidechainBridgeMock { - pub fn with_peer_blocks(mut self, blocks_encoded: Vec) -> Self { - self.peer_blocks_encoded = blocks_encoded; - self - } -} - -impl SidechainBridge for SidechainBridgeMock { - fn propose_sidechain_blocks(&self, _signed_blocks_encoded: Vec) -> OCallBridgeResult<()> { - Ok(()) - } - - fn store_sidechain_blocks(&self, _signed_blocks_encoded: Vec) -> OCallBridgeResult<()> { - Ok(()) - } - - fn fetch_sidechain_blocks_from_peer( - &self, - _last_imported_block_hash_encoded: Vec, - _maybe_until_block_hash_encoded: Vec, - _shard_identifier_encoded: Vec, - ) -> OCallBridgeResult> { - Ok(self.peer_blocks_encoded.clone()) - } - - fn get_trusted_peers_urls(&self) -> OCallBridgeResult> { - Ok(vec![]) - } -} diff --git a/bitacross-worker/service/src/ocall_bridge/test/mod.rs b/bitacross-worker/service/src/ocall_bridge/test/mod.rs deleted file mode 100644 index 0c205a3799..0000000000 --- a/bitacross-worker/service/src/ocall_bridge/test/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub mod mocks; diff --git a/bitacross-worker/service/src/prometheus_metrics.rs b/bitacross-worker/service/src/prometheus_metrics.rs index 64a3615135..84448f552a 100644 --- a/bitacross-worker/service/src/prometheus_metrics.rs +++ b/bitacross-worker/service/src/prometheus_metrics.rs @@ -17,9 +17,6 @@ //! Service for prometheus metrics, hosted on a http server. -#[cfg(feature = "teeracle")] -use crate::teeracle::teeracle_metrics::update_teeracle_metrics; - use crate::{ account_funding::EnclaveAccountInfo, error::{Error, ServiceResult}, @@ -37,7 +34,6 @@ use itc_rest_client::{ }; use itp_enclave_metrics::EnclaveMetric; use lazy_static::lazy_static; -use litentry_primitives::{Assertion, Identity}; use log::*; use prometheus::{ proto::MetricFamily, register_counter_vec, register_histogram, register_histogram_vec, @@ -215,22 +211,6 @@ impl ReceiveEnclaveMetrics for EnclaveMetricsReceiver { }, EnclaveMetric::ParentchainBlockImportTime(time) => ENCLAVE_PARENTCHAIN_BLOCK_IMPORT_TIME.observe(time.as_secs_f64()), - EnclaveMetric::SidechainBlockImportTime(time) => - ENCLAVE_SIDECHAIN_BLOCK_IMPORT_TIME.observe(time.as_secs_f64()), - EnclaveMetric::SidechainSlotPrepareTime(time) => - ENCLAVE_SIDECHAIN_SLOT_PREPARE_TIME.observe(time.as_secs_f64()), - EnclaveMetric::SidechainSlotStfExecutionTime(time) => - ENCLAVE_SIDECHAIN_SLOT_STF_EXECUTION_TIME.observe(time.as_secs_f64()), - EnclaveMetric::SidechainSlotBlockCompositionTime(time) => - ENCLAVE_SIDECHAIN_SLOT_BLOCK_COMPOSITION_TIME.observe(time.as_secs_f64()), - EnclaveMetric::SidechainBlockBroadcastingTime(time) => - ENCLAVE_SIDECHAIN_BLOCK_BROADCASTING_TIME.observe(time.as_secs_f64()), - #[cfg(feature = "teeracle")] - EnclaveMetric::ExchangeRateOracle(m) => update_teeracle_metrics(m)?, - #[cfg(not(feature = "teeracle"))] - EnclaveMetric::ExchangeRateOracle(_) => { - error!("Received Teeracle metric, but Teeracle feature is not enabled, ignoring metric item.") - }, } Ok(()) } diff --git a/bitacross-worker/service/src/setup.rs b/bitacross-worker/service/src/setup.rs index 4bd056edd8..0f44676707 100644 --- a/bitacross-worker/service/src/setup.rs +++ b/bitacross-worker/service/src/setup.rs @@ -18,8 +18,8 @@ use crate::error::{Error, ServiceResult}; use itp_settings::files::{ - LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, SCHEDULED_ENCLAVE_FILE, SHARDS_PATH, - SIDECHAIN_STORAGE_PATH, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, + LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, RELAYER_REGISTRY_FILE, SCHEDULED_ENCLAVE_FILE, + SHARDS_PATH, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, }; use std::{fs, path::Path}; @@ -37,7 +37,7 @@ mod needs_enclave { use itp_enclave_api::{enclave_base::EnclaveBase, Enclave}; use itp_settings::files::{ LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, SHARDS_PATH, SHIELDING_KEY_FILE, - SIDECHAIN_STORAGE_PATH, SIGNING_KEY_FILE, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, + SIGNING_KEY_FILE, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, }; use itp_types::ShardIdentifier; @@ -139,13 +139,13 @@ pub(crate) fn purge_files_from_dir(dir: &Path) -> ServiceResult<()> { /// Purge all worker files in a given path. fn purge_files(root_directory: &Path) -> ServiceResult<()> { remove_dir_if_it_exists(root_directory, SHARDS_PATH)?; - remove_dir_if_it_exists(root_directory, SIDECHAIN_STORAGE_PATH)?; remove_dir_if_it_exists(root_directory, LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)?; remove_dir_if_it_exists(root_directory, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)?; remove_dir_if_it_exists(root_directory, TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)?; remove_file_if_it_exists(root_directory, SCHEDULED_ENCLAVE_FILE)?; + remove_file_if_it_exists(root_directory, RELAYER_REGISTRY_FILE)?; Ok(()) } @@ -182,11 +182,8 @@ mod tests { fs::File::create(&shards_path.join("state_1.bin")).unwrap(); fs::File::create(&shards_path.join("state_2.bin")).unwrap(); - let sidechain_db_path = root_directory.join(SIDECHAIN_STORAGE_PATH); - fs::create_dir_all(&sidechain_db_path).unwrap(); - fs::File::create(&sidechain_db_path.join("sidechain_db_1.bin")).unwrap(); - fs::File::create(&sidechain_db_path.join("sidechain_db_2.bin")).unwrap(); - fs::File::create(&sidechain_db_path.join("sidechain_db_3.bin")).unwrap(); + fs::File::create(&root_directory.join(SCHEDULED_ENCLAVE_FILE)).unwrap(); + fs::File::create(&root_directory.join(RELAYER_REGISTRY_FILE)).unwrap(); fs::create_dir_all(&root_directory.join(LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)) .unwrap(); @@ -198,10 +195,11 @@ mod tests { purge_files(&root_directory).unwrap(); assert!(!shards_path.exists()); - assert!(!sidechain_db_path.exists()); assert!(!root_directory.join(LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH).exists()); assert!(!root_directory.join(TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH).exists()); assert!(!root_directory.join(TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH).exists()); + assert!(!root_directory.join(SCHEDULED_ENCLAVE_FILE).exists()); + assert!(!root_directory.join(RELAYER_REGISTRY_FILE).exists()); } #[test] diff --git a/bitacross-worker/service/src/sidechain_setup.rs b/bitacross-worker/service/src/sidechain_setup.rs deleted file mode 100644 index a499c85fed..0000000000 --- a/bitacross-worker/service/src/sidechain_setup.rs +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - config::Config, - error::{Error, ServiceResult}, - parentchain_handler::HandleParentchain, -}; -use futures::executor::block_on; -use itp_enclave_api::{ - direct_request::DirectRequest, enclave_base::EnclaveBase, sidechain::Sidechain, -}; -use itp_settings::{ - files::{SIDECHAIN_PURGE_INTERVAL, SIDECHAIN_PURGE_LIMIT}, - sidechain::SLOT_DURATION, -}; -use itp_types::Header; -use its_consensus_slots::start_slot_worker; -use its_primitives::types::block::SignedBlock as SignedSidechainBlock; -use its_storage::{interface::FetchBlocks, start_sidechain_pruning_loop, BlockPruner}; -use log::*; -use std::{sync::Arc, thread}; -use tokio::runtime::Handle; - -pub(crate) fn sidechain_start_untrusted_rpc_server( - config: &Config, - enclave: Arc, - sidechain_storage: Arc, - tokio_handle: &Handle, -) where - Enclave: DirectRequest + Clone, - SidechainStorage: BlockPruner + FetchBlocks + Sync + Send + 'static, -{ - let untrusted_url = config.untrusted_worker_url(); - println!("[+] Untrusted RPC server listening on {}", &untrusted_url); - let _untrusted_rpc_join_handle = tokio_handle.spawn(async move { - itc_rpc_server::run_server(&untrusted_url, enclave, sidechain_storage) - .await - .unwrap(); - }); -} - -#[allow(clippy::too_many_arguments)] -pub(crate) fn sidechain_init_block_production( - enclave: Arc, - register_enclave_xt_header: Option
, - we_are_primary_validateer: bool, - parentchain_handler: Arc, - sidechain_storage: Arc, - last_synced_header: &Header, - overriden_start_block: u32, - fail_mode: Option, - fail_at: u64, -) -> ServiceResult
-where - Enclave: EnclaveBase + Sidechain, - SidechainStorage: BlockPruner + FetchBlocks + Sync + Send + 'static, - ParentchainHandler: HandleParentchain, -{ - // If we're the first validateer to register, also trigger parentchain block import. - let mut updated_header: Option
= None; - - if we_are_primary_validateer { - info!( - "We're the first validateer to be registered, syncing parentchain blocks until the one we have registered ourselves on." - ); - updated_header = Some(parentchain_handler.sync_and_import_parentchain_until( - last_synced_header, - ®ister_enclave_xt_header.unwrap(), - overriden_start_block, - )?); - } - - // ------------------------------------------------------------------------ - // Initialize sidechain components (has to be AFTER init_parentchain_components() - enclave.init_enclave_sidechain_components(fail_mode, fail_at).unwrap(); - - // ------------------------------------------------------------------------ - // Start interval sidechain block production (execution of trusted calls, sidechain block production). - let sidechain_enclave_api = enclave; - println!("[+] Spawning thread for sidechain block production"); - thread::Builder::new() - .name("interval_block_production_timer".to_owned()) - .spawn(move || { - let future = start_slot_worker( - || execute_trusted_calls(sidechain_enclave_api.as_ref()), - SLOT_DURATION, - ); - block_on(future); - println!("[!] Sidechain block production loop has terminated"); - }) - .map_err(|e| Error::Custom(Box::new(e)))?; - - // ------------------------------------------------------------------------ - // start sidechain pruning loop - thread::Builder::new() - .name("sidechain_pruning_loop".to_owned()) - .spawn(move || { - start_sidechain_pruning_loop( - &sidechain_storage, - SIDECHAIN_PURGE_INTERVAL, - SIDECHAIN_PURGE_LIMIT, - ); - }) - .map_err(|e| Error::Custom(Box::new(e)))?; - - Ok(updated_header.unwrap_or_else(|| last_synced_header.clone())) -} - -/// Execute trusted operations in the enclave. -fn execute_trusted_calls(enclave_api: &E) { - if let Err(e) = enclave_api.execute_trusted_calls() { - error!("{:?}", e); - }; -} diff --git a/bitacross-worker/service/src/sync_block_broadcaster.rs b/bitacross-worker/service/src/sync_block_broadcaster.rs deleted file mode 100644 index b0752c900d..0000000000 --- a/bitacross-worker/service/src/sync_block_broadcaster.rs +++ /dev/null @@ -1,57 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(test)] -use mockall::predicate::*; -#[cfg(test)] -use mockall::*; - -use crate::{ - globals::tokio_handle::GetTokioHandle, - worker::{AsyncBlockBroadcaster, WorkerResult}, -}; -use its_primitives::types::block::SignedBlock as SignedSidechainBlock; -use std::sync::Arc; - -/// Allows to broadcast blocks, does it in a synchronous (i.e. blocking) manner -#[cfg_attr(test, automock)] -pub trait BroadcastBlocks { - fn broadcast_blocks(&self, blocks: Vec) -> WorkerResult<()>; -} - -pub struct SyncBlockBroadcaster { - tokio_handle: Arc, - worker: Arc, -} - -impl SyncBlockBroadcaster { - pub fn new(tokio_handle: Arc, worker: Arc) -> Self { - SyncBlockBroadcaster { tokio_handle, worker } - } -} - -impl BroadcastBlocks for SyncBlockBroadcaster -where - T: GetTokioHandle, - W: AsyncBlockBroadcaster, -{ - fn broadcast_blocks(&self, blocks: Vec) -> WorkerResult<()> { - let handle = self.tokio_handle.get_handle(); - handle.block_on(self.worker.broadcast_blocks(blocks)) - } -} diff --git a/bitacross-worker/service/src/sync_state.rs b/bitacross-worker/service/src/sync_state.rs index 21d2d4d7e0..287721e687 100644 --- a/bitacross-worker/service/src/sync_state.rs +++ b/bitacross-worker/service/src/sync_state.rs @@ -26,16 +26,14 @@ use itp_enclave_api::{ enclave_base::EnclaveBase, remote_attestation::{RemoteAttestation, TlsRemoteAttestation}, }; -use itp_node_api::api_client::PalletTeerexApi; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; -use itp_types::ShardIdentifier; +use itp_node_api::api_client::PalletTeebagApi; +use itp_types::{ShardIdentifier, WorkerType}; use sgx_types::sgx_quote_sign_type_t; use std::string::String; pub(crate) fn sync_state< E: TlsRemoteAttestation + EnclaveBase + RemoteAttestation, - NodeApi: PalletTeerexApi, - WorkerModeProvider: ProvideWorkerMode, + NodeApi: PalletTeebagApi, >( node_api: &NodeApi, shard: &ShardIdentifier, @@ -43,13 +41,9 @@ pub(crate) fn sync_state< skip_ra: bool, ) { // FIXME: we now assume that keys are equal for all shards. - let provider_url = match WorkerModeProvider::worker_mode() { - WorkerMode::Sidechain => - executor::block_on(get_author_url_of_last_finalized_sidechain_block(node_api, shard)) - .expect("Author of last finalized sidechain block could not be found"), - _ => executor::block_on(get_enclave_url_of_first_registered(node_api, enclave_api)) - .expect("Author of last finalized sidechain block could not be found"), - }; + let provider_url = + executor::block_on(get_enclave_url_of_first_registered(node_api, enclave_api)) + .expect("Author of last finalized sidechain block could not be found"); println!("Requesting state provisioning from worker at {}", &provider_url); @@ -64,36 +58,20 @@ pub(crate) fn sync_state< println!("[+] State provisioning successfully performed."); } -/// Returns the url of the last sidechain block author that has been stored -/// in the parentchain state as "worker for shard". -/// -/// Note: The sidechainblock author will only change whenever a new parentchain block is -/// produced. And even then, it might be the same as the last block. So if several workers -/// are started in a timely manner, they will all get the same url. -async fn get_author_url_of_last_finalized_sidechain_block( - node_api: &NodeApi, - shard: &ShardIdentifier, -) -> Result { - let enclave = node_api - .worker_for_shard(shard, None)? - .ok_or_else(|| Error::NoWorkerForShardFound(*shard))?; - let worker_api_direct = DirectWorkerApi::new(enclave.url); - Ok(worker_api_direct.get_mu_ra_url()?) -} - /// Returns the url of the first Enclave that matches our own MRENCLAVE. /// /// This should be run before we register ourselves as enclave, to ensure we don't get our own url. -async fn get_enclave_url_of_first_registered( +async fn get_enclave_url_of_first_registered( node_api: &NodeApi, enclave_api: &EnclaveApi, ) -> Result { - let self_mr_enclave = enclave_api.get_fingerprint()?; + let self_mrenclave = enclave_api.get_fingerprint()?; let first_enclave = node_api - .all_enclaves(None)? + .all_enclaves(WorkerType::BitAcross, None)? .into_iter() - .find(|e| e.mr_enclave == self_mr_enclave.to_fixed_bytes()) + .find(|e| e.mrenclave == self_mrenclave.to_fixed_bytes()) .ok_or(Error::NoPeerWorkerFound)?; - let worker_api_direct = DirectWorkerApi::new(first_enclave.url); + let worker_api_direct = + DirectWorkerApi::new(String::from_utf8_lossy(first_enclave.url.as_slice()).to_string()); Ok(worker_api_direct.get_mu_ra_url()?) } diff --git a/bitacross-worker/service/src/teeracle/mod.rs b/bitacross-worker/service/src/teeracle/mod.rs deleted file mode 100644 index 420a175b26..0000000000 --- a/bitacross-worker/service/src/teeracle/mod.rs +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{error::ServiceResult, teeracle::schedule_periodic::schedule_periodic}; -use codec::{Decode, Encode}; -use itp_enclave_api::teeracle_api::TeeracleApi; -use itp_node_api::api_client::ParentchainApi; -use itp_types::parentchain::Hash; -use itp_utils::hex::hex_encode; -use log::*; -use sp_runtime::OpaqueExtrinsic; -use std::time::Duration; -use substrate_api_client::{SubmitAndWatch, XtStatus}; -use teeracle_metrics::{increment_number_of_request_failures, set_extrinsics_inclusion_success}; -use tokio::runtime::Handle; - -pub(crate) mod schedule_periodic; -pub(crate) mod teeracle_metrics; - -/// Schedule periodic reregistration of the enclave. -/// -/// The `send_register_xt` needs to create a fresh registration extrinsic every time it is called -/// (updated nonce, fresh IAS-RA or DCAP-Quote). -/// -/// Currently, this is only used for the teeracle, but could also be used for other flavors in the -/// future. -pub(crate) fn schedule_periodic_reregistration_thread( - send_register_xt: impl Fn() -> Option + std::marker::Send + 'static, - period: Duration, -) { - println!("Schedule periodic enclave reregistration every: {:?}", period); - - std::thread::Builder::new() - .name("enclave_reregistration_thread".to_owned()) - .spawn(move || { - schedule_periodic( - || { - trace!("Reregistering the enclave."); - if let Some(block_hash) = send_register_xt() { - println!( - "✅ Successfully reregistered the enclave. Block hash: {}.", - block_hash - ) - } else { - error!("❌ Could not reregister the enclave.") - } - }, - period, - ); - }) - .unwrap(); -} - -/// Executes a periodic teeracle data update and sends the new data to the parentchain. -/// -/// Note: Puts the current thread to sleep for `period`. -pub(crate) fn start_periodic_market_update( - api: &ParentchainApi, - period: Duration, - enclave_api: &E, - tokio_handle: &Handle, -) { - let updates_to_run = || { - if let Err(e) = execute_oracle_update(api, tokio_handle, || { - // Get market data for usd (hardcoded) - enclave_api.update_market_data_xt("TEER", "USD") - }) { - error!("Error running market update {:?}", e) - } - - // TODO: Refactor and add this back according to ISSUE: https://github.com/integritee-network/worker/issues/1300 - // if let Err(e) = execute_oracle_update(api, tokio_handle, || { - // enclave_api.update_weather_data_xt("54.32", "15.37") - // }) { - // error!("Error running weather update {:?}", e) - // } - }; - info!("Teeracle will update now"); - updates_to_run(); - - info!("Schedule teeracle updates every {:?}", period); - schedule_periodic(updates_to_run, period); -} - -fn execute_oracle_update( - node_api: &ParentchainApi, - tokio_handle: &Handle, - get_oracle_xt: F, -) -> ServiceResult<()> -where - F: Fn() -> Result, itp_enclave_api::error::Error>, -{ - let oracle_xt = get_oracle_xt().map_err(|e| { - increment_number_of_request_failures(); - e - })?; - - let extrinsics = >::decode(&mut oracle_xt.as_slice())?; - - // Send the extrinsics to the parentchain and wait for InBlock confirmation. - for call in extrinsics.into_iter() { - let node_api_clone = node_api.clone(); - tokio_handle.spawn(async move { - let encoded_extrinsic = call.encode(); - debug!("Hex encoded extrinsic to be sent: {}", hex_encode(&encoded_extrinsic)); - - println!("[>] Update oracle data (send the extrinsic)"); - let extrinsic_hash = match node_api_clone.submit_and_watch_opaque_extrinsic_until( - &encoded_extrinsic.into(), - XtStatus::InBlock, - ) { - Err(e) => { - error!("Failed to send extrinsic: {:?}", e); - set_extrinsics_inclusion_success(false); - return - }, - Ok(report) => { - set_extrinsics_inclusion_success(true); - report.extrinsic_hash - }, - }; - - println!("[<] Extrinsic got included into a block. Hash: {:?}\n", extrinsic_hash); - }); - } - - Ok(()) -} diff --git a/bitacross-worker/service/src/teeracle/schedule_periodic.rs b/bitacross-worker/service/src/teeracle/schedule_periodic.rs deleted file mode 100644 index cde09af452..0000000000 --- a/bitacross-worker/service/src/teeracle/schedule_periodic.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use std::{ - thread, - time::{Duration, Instant}, -}; - -/// Schedules a periodic task in the current thread. -/// -/// In case the task takes longer than is scheduled by the interval duration, -/// the interval timing will drift. The task is responsible for -/// ensuring it does not use up more time than is scheduled. -pub(super) fn schedule_periodic(task: T, period: Duration) -where - T: Fn(), -{ - let mut interval_start = Instant::now(); - loop { - let elapsed = interval_start.elapsed(); - - if elapsed >= period { - // update interval time - interval_start = Instant::now(); - task(); - } else { - // sleep for the rest of the interval - let sleep_time = period - elapsed; - thread::sleep(sleep_time); - } - } -} diff --git a/bitacross-worker/service/src/teeracle/teeracle_metrics.rs b/bitacross-worker/service/src/teeracle/teeracle_metrics.rs deleted file mode 100644 index 8fe62c2092..0000000000 --- a/bitacross-worker/service/src/teeracle/teeracle_metrics.rs +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::error::{Error, ServiceResult}; -use itp_enclave_metrics::ExchangeRateOracleMetric; -use lazy_static::lazy_static; -use prometheus::{ - register_gauge_vec, register_int_counter, register_int_counter_vec, register_int_gauge, - register_int_gauge_vec, GaugeVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, -}; - -lazy_static! { - /// Register Teeracle specific metrics - - static ref EXCHANGE_RATE: GaugeVec = - register_gauge_vec!("integritee_teeracle_exchange_rate", "Exchange rates partitioned into source and trading pair", &["source", "trading_pair"]) - .unwrap(); - static ref RESPONSE_TIME: IntGaugeVec = - register_int_gauge_vec!("integritee_teeracle_response_times", "Response times in ms for requests that the oracle makes", &["source"]) - .unwrap(); - static ref NUMBER_OF_REQUESTS: IntCounterVec = - register_int_counter_vec!("integritee_teeracle_number_of_requests", "Number of requests made per source", &["source"]) - .unwrap(); - - static ref NUMBER_OF_REQUEST_FAILURES: IntCounter = - register_int_counter!("integritee_teeracle_request_failures", "Number of requests that failed") - .unwrap(); - - static ref EXTRINSIC_INCLUSION_SUCCESS: IntGauge = - register_int_gauge!("integritee_teeracle_extrinsic_inclusion_success", "1 if extrinsics was successfully finalized, 0 if not") - .unwrap(); -} - -pub(super) fn increment_number_of_request_failures() { - NUMBER_OF_REQUEST_FAILURES.inc(); -} - -pub(super) fn set_extrinsics_inclusion_success(is_successful: bool) { - let success_values = i64::from(is_successful); - EXTRINSIC_INCLUSION_SUCCESS.set(success_values); -} - -pub fn update_teeracle_metrics(metric: ExchangeRateOracleMetric) -> ServiceResult<()> { - match metric { - ExchangeRateOracleMetric::ExchangeRate(source, trading_pair, exchange_rate) => - EXCHANGE_RATE - .get_metric_with_label_values(&[source.as_str(), trading_pair.as_str()]) - .map(|m| m.set(exchange_rate.to_num())) - .map_err(|e| Error::Custom(e.into()))?, - - ExchangeRateOracleMetric::ResponseTime(source, t) => RESPONSE_TIME - .get_metric_with_label_values(&[source.as_str()]) - .map(|m| m.set(t as i64)) - .map_err(|e| Error::Custom(e.into()))?, - - ExchangeRateOracleMetric::NumberRequestsIncrement(source) => NUMBER_OF_REQUESTS - .get_metric_with_label_values(&[source.as_str()]) - .map(|m| m.inc()) - .map_err(|e| Error::Custom(e.into()))?, - }; - Ok(()) -} diff --git a/bitacross-worker/service/src/tests/commons.rs b/bitacross-worker/service/src/tests/commons.rs index df6b5c9172..068576e8d7 100644 --- a/bitacross-worker/service/src/tests/commons.rs +++ b/bitacross-worker/service/src/tests/commons.rs @@ -57,7 +57,5 @@ pub fn local_worker_config( crate::config::pwd(), None, "0".to_string(), - None, - 0, ) } diff --git a/bitacross-worker/service/src/tests/mock.rs b/bitacross-worker/service/src/tests/mock.rs index 0587669dc4..0f96dc3f1e 100644 --- a/bitacross-worker/service/src/tests/mock.rs +++ b/bitacross-worker/service/src/tests/mock.rs @@ -15,8 +15,8 @@ */ -use itp_node_api::api_client::{ApiResult, PalletTeerexApi}; -use itp_types::{Enclave, MrEnclave, ShardIdentifier, H256 as Hash}; +use itp_node_api::api_client::{ApiResult, PalletTeebagApi}; +use itp_types::{AccountId, Enclave, MrEnclave, ShardIdentifier, WorkerType, H256 as Hash}; use std::collections::HashSet; pub struct TestNodeApi; @@ -26,43 +26,44 @@ pub const W2_URL: &str = "127.0.0.1:33333"; pub fn enclaves() -> Vec { vec![ - Enclave::new([0; 32].into(), [1; 32], 1, format!("wss://{}", W1_URL)), - Enclave::new([2; 32].into(), [3; 32], 2, format!("wss://{}", W2_URL)), + Enclave::new(WorkerType::BitAcross).with_url(W1_URL.into()), + Enclave::new(WorkerType::BitAcross).with_url(W2_URL.into()), ] } -impl PalletTeerexApi for TestNodeApi { +impl PalletTeebagApi for TestNodeApi { type Hash = Hash; - fn enclave(&self, index: u64, _at_block: Option) -> ApiResult> { - Ok(Some(enclaves().remove(index as usize))) + fn enclave(&self, _account: &AccountId, _at_block: Option) -> ApiResult> { + unreachable!() } - fn enclave_count(&self, _at_block: Option) -> ApiResult { + fn enclave_count(&self, _worker_type: WorkerType, _at_block: Option) -> ApiResult { unreachable!() } - fn all_enclaves(&self, _at_block: Option) -> ApiResult> { + fn all_enclaves( + &self, + _worker_type: WorkerType, + _at_block: Option, + ) -> ApiResult> { Ok(enclaves()) } - fn worker_for_shard( + fn primary_enclave_identifier_for_shard( &self, - _: &ShardIdentifier, - _at_block: Option, - ) -> ApiResult> { + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { unreachable!() } - fn latest_ipfs_hash( + + fn primary_enclave_for_shard( &self, - _: &ShardIdentifier, - _at_block: Option, - ) -> ApiResult> { + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { unreachable!() } - - fn all_scheduled_mrenclaves(&self, _at_block: Option) -> ApiResult> { - let enclaves = enclaves(); - let mr_enclaves: HashSet<_> = enclaves.into_iter().map(|e| e.mr_enclave).collect(); - Ok(mr_enclaves.into_iter().collect()) - } } diff --git a/bitacross-worker/service/src/tests/mocks/broadcast_blocks_mock.rs b/bitacross-worker/service/src/tests/mocks/broadcast_blocks_mock.rs deleted file mode 100644 index 2df5f65506..0000000000 --- a/bitacross-worker/service/src/tests/mocks/broadcast_blocks_mock.rs +++ /dev/null @@ -1,28 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{sync_block_broadcaster::BroadcastBlocks, worker::WorkerResult}; -use its_primitives::types::block::SignedBlock as SignedSidechainBlock; -use std::vec::Vec; - -pub struct BroadcastBlocksMock; - -impl BroadcastBlocks for BroadcastBlocksMock { - fn broadcast_blocks(&self, _blocks: Vec) -> WorkerResult<()> { - Ok(()) - } -} diff --git a/bitacross-worker/service/src/tests/mocks/direct_request_mock.rs b/bitacross-worker/service/src/tests/mocks/direct_request_mock.rs deleted file mode 100644 index a2c572dfc6..0000000000 --- a/bitacross-worker/service/src/tests/mocks/direct_request_mock.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use itp_enclave_api::{direct_request::DirectRequest, EnclaveResult}; - -pub struct DirectRequestMock; - -impl DirectRequest for DirectRequestMock { - fn rpc(&self, request: Vec) -> EnclaveResult> { - Ok(request) - } -} diff --git a/bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs b/bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs index af27dd3fae..3048230d83 100644 --- a/bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs +++ b/bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs @@ -23,11 +23,11 @@ use itc_parentchain::primitives::{ }; use itp_enclave_api::{enclave_base::EnclaveBase, sidechain::Sidechain, EnclaveResult}; use itp_settings::worker::MR_ENCLAVE_SIZE; +use itp_sgx_crypto::{ecdsa, schnorr}; use itp_storage::StorageProof; -use itp_types::ShardIdentifier; +use itp_types::{EnclaveFingerprint, ShardIdentifier}; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::ed25519; -use teerex_primitives::EnclaveFingerprint; /// mock for EnclaveBase - use in tests pub struct EnclaveMock; @@ -37,11 +37,7 @@ impl EnclaveBase for EnclaveMock { Ok(()) } - fn init_enclave_sidechain_components( - &self, - _fail_mode: Option, - _fail_at: u64, - ) -> EnclaveResult<()> { + fn init_enclave_sidechain_components(&self) -> EnclaveResult<()> { Ok(()) } @@ -93,6 +89,14 @@ impl EnclaveBase for EnclaveMock { unreachable!() } + fn get_bitcoin_wallet_pair(&self) -> EnclaveResult { + unreachable!() + } + + fn get_ethereum_wallet_pair(&self) -> EnclaveResult { + unreachable!() + } + fn get_fingerprint(&self) -> EnclaveResult { Ok([1u8; MR_ENCLAVE_SIZE].into()) } @@ -100,6 +104,10 @@ impl EnclaveBase for EnclaveMock { fn migrate_shard(&self, _old_shard: Vec, _new_shard: Vec) -> EnclaveResult<()> { unimplemented!() } + + fn publish_wallets(&self) -> EnclaveResult<()> { + unimplemented!() + } } impl Sidechain for EnclaveMock { @@ -114,10 +122,6 @@ impl Sidechain for EnclaveMock { Ok(()) } - fn execute_trusted_calls(&self) -> EnclaveResult<()> { - todo!() - } - fn ignore_parentchain_block_import_validation_until(&self, _until: u32) -> EnclaveResult<()> { todo!() } diff --git a/bitacross-worker/service/src/tests/mocks/initialization_handler_mock.rs b/bitacross-worker/service/src/tests/mocks/initialization_handler_mock.rs index e4539afc0e..79b2797d7b 100644 --- a/bitacross-worker/service/src/tests/mocks/initialization_handler_mock.rs +++ b/bitacross-worker/service/src/tests/mocks/initialization_handler_mock.rs @@ -22,8 +22,6 @@ pub struct TrackInitializationMock; impl TrackInitialization for TrackInitializationMock { fn registered_on_parentchain(&self) {} - fn sidechain_block_produced(&self) {} - fn worker_for_shard_registered(&self) {} } diff --git a/bitacross-worker/service/src/tests/mocks/mod.rs b/bitacross-worker/service/src/tests/mocks/mod.rs index cfe0d6fc76..406392ef62 100644 --- a/bitacross-worker/service/src/tests/mocks/mod.rs +++ b/bitacross-worker/service/src/tests/mocks/mod.rs @@ -15,8 +15,6 @@ */ -pub mod broadcast_blocks_mock; -pub mod direct_request_mock; pub mod enclave_api_mock; pub mod initialization_handler_mock; pub mod parentchain_api_mock; diff --git a/bitacross-worker/service/src/worker.rs b/bitacross-worker/service/src/worker.rs index 638e4f081b..89bc4c382f 100644 --- a/bitacross-worker/service/src/worker.rs +++ b/bitacross-worker/service/src/worker.rs @@ -25,13 +25,12 @@ use async_trait::async_trait; use codec::{Decode, Encode}; use itc_rpc_client::direct_client::{DirectApi, DirectClient as DirectWorkerApi}; use itp_enclave_api::enclave_base::EnclaveBase; -use itp_node_api::{api_client::PalletTeerexApi, node_api_factory::CreateNodeApi}; -use its_primitives::types::SignedBlock as SignedSidechainBlock; -use its_rpc_handler::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; +use itp_node_api::{api_client::PalletTeebagApi, node_api_factory::CreateNodeApi}; use jsonrpsee::{ types::{to_json_value, traits::Client}, ws_client::WsClientBuilder, }; +use litentry_primitives::WorkerType; use log::*; use std::{ collections::HashSet, @@ -83,67 +82,6 @@ impl } } -#[async_trait] -/// Broadcast Sidechain blocks to peers. -pub trait AsyncBlockBroadcaster { - async fn broadcast_blocks(&self, blocks: Vec) -> WorkerResult<()>; -} - -#[async_trait] -impl AsyncBlockBroadcaster - for Worker -where - NodeApiFactory: CreateNodeApi + Send + Sync, - Enclave: Send + Sync, - InitializationHandler: TrackInitialization + Send + Sync, -{ - async fn broadcast_blocks(&self, blocks: Vec) -> WorkerResult<()> { - if blocks.is_empty() { - debug!("No blocks to broadcast, returning"); - return Ok(()) - } - - let blocks_json = vec![to_json_value(blocks)?]; - let peers = self - .peer_urls - .read() - .map_err(|e| { - Error::Custom(format!("Encountered poisoned lock for peers: {:?}", e).into()) - }) - .map(|l| l.clone())?; - - self.initialization_handler.sidechain_block_produced(); - - for url in peers { - let blocks = blocks_json.clone(); - - tokio::spawn(async move { - let untrusted_peer_url = url.untrusted; - - debug!("Broadcasting block to peer with address: {:?}", untrusted_peer_url); - // FIXME: Websocket connection to a worker should stay, once established. - let client = match WsClientBuilder::default().build(&untrusted_peer_url).await { - Ok(c) => c, - Err(e) => { - error!("Failed to create websocket client for block broadcasting (target url: {}): {:?}", untrusted_peer_url, e); - return - }, - }; - - if let Err(e) = - client.request::>(RPC_METHOD_NAME_IMPORT_BLOCKS, blocks.into()).await - { - error!( - "Broadcast block request ({}) to {} failed: {:?}", - RPC_METHOD_NAME_IMPORT_BLOCKS, untrusted_peer_url, e - ); - } - }); - } - Ok(()) - } -} - /// Looks for new peers and updates them. pub trait UpdatePeers { fn search_peers(&self) -> WorkerResult>; @@ -187,11 +125,11 @@ where .node_api_factory .create_api() .map_err(|e| Error::Custom(format!("Failed to create NodeApi: {:?}", e).into()))?; - let enclaves = node_api.all_enclaves(None)?; + let enclaves = node_api.all_enclaves(WorkerType::BitAcross, None)?; let mut peer_urls = HashSet::::new(); for enclave in enclaves { // FIXME: This is temporary only, as block broadcasting should be moved to trusted ws server. - let enclave_url = enclave.url.clone(); + let enclave_url = String::from_utf8_lossy(enclave.url.as_slice()).to_string(); let worker_api_direct = DirectWorkerApi::new(enclave_url.clone()); match worker_api_direct.get_untrusted_worker_url() { Ok(untrusted_worker_url) => { @@ -217,81 +155,3 @@ where Ok(()) } } -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - tests::{ - commons::local_worker_config, - mock::{W1_URL, W2_URL}, - mocks::initialization_handler_mock::TrackInitializationMock, - }, - worker::{AsyncBlockBroadcaster, Worker}, - }; - use frame_support::assert_ok; - use itp_node_api::node_api_factory::NodeApiFactory; - use its_primitives::types::block::SignedBlock as SignedSidechainBlock; - use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; - use jsonrpsee::{ws_server::WsServerBuilder, RpcModule}; - use log::debug; - use sp_keyring::AccountKeyring; - use std::{net::SocketAddr, sync::Arc}; - use tokio::net::ToSocketAddrs; - - fn init() { - let _ = env_logger::builder().is_test(true).try_init(); - } - - async fn run_server(addr: impl ToSocketAddrs) -> anyhow::Result { - let mut server = WsServerBuilder::default().build(addr).await?; - let mut module = RpcModule::new(()); - - module.register_method(RPC_METHOD_NAME_IMPORT_BLOCKS, |params, _| { - debug!("{} params: {:?}", RPC_METHOD_NAME_IMPORT_BLOCKS, params); - let _blocks: Vec = params.one()?; - Ok("ok".as_bytes().to_vec()) - })?; - - server.register_module(module).unwrap(); - - let socket_addr = server.local_addr()?; - tokio::spawn(async move { server.start().await }); - Ok(socket_addr) - } - - #[tokio::test] - async fn broadcast_blocks_works() { - init(); - run_server(W1_URL).await.unwrap(); - run_server(W2_URL).await.unwrap(); - let untrusted_worker_port = "4000".to_string(); - let mut peer_urls: HashSet = HashSet::new(); - - peer_urls.insert(PeerUrls { - untrusted: format!("ws://{}", W1_URL), - trusted: format!("ws://{}", W1_URL), - me: false, - }); - peer_urls.insert(PeerUrls { - untrusted: format!("ws://{}", W2_URL), - trusted: format!("ws://{}", W2_URL), - me: false, - }); - - let worker = Worker::new( - local_worker_config(W1_URL.into(), untrusted_worker_port.clone(), "30".to_string()), - Arc::new(()), - Arc::new(NodeApiFactory::new( - "ws://invalid.url".to_string(), - AccountKeyring::Alice.pair(), - )), - Arc::new(TrackInitializationMock {}), - peer_urls, - ); - - let resp = worker - .broadcast_blocks(vec![SidechainBlockBuilder::default().build_signed()]) - .await; - assert_ok!(resp); - } -} diff --git a/bitacross-worker/sidechain/block-composer/Cargo.toml b/bitacross-worker/sidechain/block-composer/Cargo.toml deleted file mode 100644 index f1be550d61..0000000000 --- a/bitacross-worker/sidechain/block-composer/Cargo.toml +++ /dev/null @@ -1,64 +0,0 @@ -[package] -name = "its-block-composer" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -# sgx dependencies -sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } -sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } - -# local dependencies -itp-node-api = { path = "../../core-primitives/node-api", default-features = false } -itp-settings = { path = "../../core-primitives/settings", default-features = false } -itp-sgx-crypto = { path = "../../core-primitives/sgx/crypto", default-features = false } -itp-sgx-externalities = { path = "../../core-primitives/substrate-sgx/externalities", default-features = false } -itp-stf-executor = { path = "../../core-primitives/stf-executor", default-features = false } -itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } -itp-time-utils = { path = "../../core-primitives/time-utils", default-features = false } -itp-top-pool-author = { path = "../../core-primitives/top-pool-author", default-features = false } -itp-types = { path = "../../core-primitives/types", default-features = false } -its-primitives = { path = "../primitives", default-features = false, features = ["full_crypto"] } -its-state = { path = "../state", default-features = false } - -# sgx enabled external libraries -thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } - -# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) -thiserror = { version = "1.0", optional = true } - -# no-std compatible libraries -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -log = { version = "0.4", default-features = false } -sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - - -[features] -default = ["std"] -std = [ - "itp-node-api/std", - "itp-sgx-crypto/std", - "itp-sgx-externalities/std", - "itp-stf-executor/std", - "itp-stf-primitives/std", - "itp-time-utils/std", - "itp-top-pool-author/std", - "itp-types/std", - "its-primitives/std", - "its-state/std", - "log/std", - "thiserror", -] -sgx = [ - "sgx_tstd", - "itp-node-api/sgx", - "itp-sgx-crypto/sgx", - "itp-sgx-externalities/sgx", - "itp-stf-executor/sgx", - "itp-time-utils/sgx", - "itp-top-pool-author/sgx", - "its-state/sgx", - "thiserror_sgx", -] diff --git a/bitacross-worker/sidechain/block-composer/src/block_composer.rs b/bitacross-worker/sidechain/block-composer/src/block_composer.rs deleted file mode 100644 index d87f7e61d3..0000000000 --- a/bitacross-worker/sidechain/block-composer/src/block_composer.rs +++ /dev/null @@ -1,185 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::error::{Error, Result}; -use codec::Encode; -use itp_settings::worker::BLOCK_NUMBER_FINALIZATION_DIFF; -use itp_sgx_crypto::{key_repository::AccessKey, StateCrypto}; -use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; -use itp_stf_primitives::types::StatePayload; -use itp_time_utils::now_as_millis; -use itp_types::{ShardIdentifier, H256}; -use its_primitives::traits::{ - Block as SidechainBlockTrait, BlockData, Header as HeaderTrait, SignBlock, - SignedBlock as SignedSidechainBlockTrait, -}; -use its_state::{LastBlockExt, SidechainState, SidechainSystemExt}; -use log::*; -use sp_core::Pair; -use sp_runtime::{ - traits::{Block as ParentchainBlockTrait, Header}, - MultiSignature, -}; -use std::{format, marker::PhantomData, sync::Arc, vec::Vec}; - -/// Compose a sidechain block and corresponding confirmation extrinsic for the parentchain -/// -pub trait ComposeBlock { - type SignedSidechainBlock: SignedSidechainBlockTrait; - - fn compose_block( - &self, - latest_parentchain_header: &::Header, - top_call_hashes: Vec, - shard: ShardIdentifier, - state_hash_apriori: H256, - aposteriori_state: &Externalities, - ) -> Result; -} - -/// Block composer implementation for the sidechain -pub struct BlockComposer { - signer: Signer, - state_key_repository: Arc, - _phantom: PhantomData<(ParentchainBlock, SignedSidechainBlock)>, -} - -impl - BlockComposer -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: - SignedSidechainBlockTrait, - SignedSidechainBlock::Block: SidechainBlockTrait, - <::Block as SidechainBlockTrait>::HeaderType: - HeaderTrait, - SignedSidechainBlock::Signature: From, - Signer: Pair, - Signer::Public: Encode, - StateKeyRepository: AccessKey, - ::KeyType: StateCrypto, -{ - pub fn new(signer: Signer, state_key_repository: Arc) -> Self { - BlockComposer { signer, state_key_repository, _phantom: Default::default() } - } -} - -type HeaderTypeOf = <::Block as SidechainBlockTrait>::HeaderType; -type BlockDataTypeOf = - <::Block as SidechainBlockTrait>::BlockDataType; - -impl - ComposeBlock - for BlockComposer -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: - SignedSidechainBlockTrait, - SignedSidechainBlock::Block: SidechainBlockTrait, - <::Block as SidechainBlockTrait>::HeaderType: - HeaderTrait, - SignedSidechainBlock::Signature: From, - Externalities: SgxExternalitiesTrait - + SidechainState - + SidechainSystemExt - + StateHash - + LastBlockExt - + Encode, - ::SgxExternalitiesType: Encode, - ::SgxExternalitiesDiffType: Encode, - Signer: Pair, - Signer::Public: Encode, - StateKeyRepository: AccessKey, - ::KeyType: StateCrypto, -{ - type SignedSidechainBlock = SignedSidechainBlock; - - fn compose_block( - &self, - latest_parentchain_header: &ParentchainBlock::Header, - top_call_hashes: Vec, - shard: ShardIdentifier, - state_hash_apriori: H256, - aposteriori_state: &Externalities, - ) -> Result { - let author_public = self.signer.public(); - - let state_hash_new = aposteriori_state.hash(); - - let (block_number, parent_hash, next_finalization_block_number) = - match aposteriori_state.get_last_block() { - Some(block) => ( - block.header().block_number() + 1, - block.hash(), - block.header().next_finalization_block_number(), - ), - None => { - info!("Seems to be first sidechain block."); - (1, Default::default(), 1) - }, - }; - - if block_number != aposteriori_state.get_block_number().unwrap_or(0) { - return Err(Error::Other("[Sidechain] BlockNumber is not LastBlock's Number + 1".into())) - } - - // create encrypted payload - let mut payload: Vec = - StatePayload::new(state_hash_apriori, state_hash_new, aposteriori_state.state_diff()) - .encode(); - - let state_key = self - .state_key_repository - .retrieve_key() - .map_err(|e| Error::Other(format!("Failed to retrieve state key: {:?}", e).into()))?; - - state_key.encrypt(&mut payload).map_err(|e| { - Error::Other(format!("Failed to encrypt state payload: {:?}", e).into()) - })?; - - let block_data = BlockDataTypeOf::::new( - author_public, - latest_parentchain_header.hash(), - top_call_hashes, - payload, - now_as_millis(), - ); - - let mut finalization_candidate = next_finalization_block_number; - if block_number == 1 { - finalization_candidate = 1; - } else if block_number > finalization_candidate { - finalization_candidate += BLOCK_NUMBER_FINALIZATION_DIFF; - } - - let header = HeaderTypeOf::::new( - block_number, - parent_hash, - shard, - block_data.hash(), - finalization_candidate, - ); - - let block = SignedSidechainBlock::Block::new(header.clone(), block_data); - - debug!("Block header hash {}", header.hash()); - - let signed_block = block.sign_block(&self.signer); - - Ok(signed_block) - } -} diff --git a/bitacross-worker/sidechain/block-composer/src/error.rs b/bitacross-worker/sidechain/block-composer/src/error.rs deleted file mode 100644 index 6baba32eb7..0000000000 --- a/bitacross-worker/sidechain/block-composer/src/error.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use sgx_types::sgx_status_t; -use std::{boxed::Box, format}; - -pub type Result = core::result::Result; - -/// Block composer error -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("SGX error, status: {0}")] - Sgx(sgx_status_t), - #[error("STF execution error: {0}")] - StfExecution(#[from] itp_stf_executor::error::Error), - #[error("TOP pool RPC author error: {0}")] - TopPoolAuthor(#[from] itp_top_pool_author::error::Error), - #[error("Node Metadata error: {0:?}")] - NodeMetadata(itp_node_api::metadata::Error), - #[error("Node metadata provider error: {0:?}")] - NodeMetadataProvider(#[from] itp_node_api::metadata::provider::Error), - #[error(transparent)] - Other(#[from] Box), -} - -impl From for Error { - fn from(sgx_status: sgx_status_t) -> Self { - Self::Sgx(sgx_status) - } -} - -impl From for Error { - fn from(e: codec::Error) -> Self { - Self::Other(format!("{:?}", e).into()) - } -} - -impl From for Error { - fn from(e: itp_node_api::metadata::Error) -> Self { - Self::NodeMetadata(e) - } -} diff --git a/bitacross-worker/sidechain/block-composer/src/lib.rs b/bitacross-worker/sidechain/block-composer/src/lib.rs deleted file mode 100644 index 038f348c1d..0000000000 --- a/bitacross-worker/sidechain/block-composer/src/lib.rs +++ /dev/null @@ -1,36 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -//! Sidechain block composing logic. -#![feature(trait_alias)] -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -extern crate sgx_tstd as std; - -// re-export module to properly feature gate sgx and regular std environment -#[cfg(all(not(feature = "std"), feature = "sgx"))] -pub mod sgx_reexport_prelude { - pub use thiserror_sgx as thiserror; -} - -pub mod block_composer; -pub mod error; - -pub use block_composer::*; diff --git a/bitacross-worker/sidechain/block-verification/Cargo.toml b/bitacross-worker/sidechain/block-verification/Cargo.toml deleted file mode 100644 index 9265b86517..0000000000 --- a/bitacross-worker/sidechain/block-verification/Cargo.toml +++ /dev/null @@ -1,52 +0,0 @@ -[package] -name = "its-block-verification" -description = "Verification logic for sidechain blocks" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -homepage = "https://litentry.com/" -repository = "https://github.com/litentry/litentry-parachain" -license = "Apache-2.0" -edition = "2021" - -[dependencies] -log = { version = "0.4.17", default-features = false } -thiserror = { version = "1.0.26", optional = true } - -# local deps -itp-types = { default-features = false, path = "../../core-primitives/types" } -itp-utils = { default-features = false, path = "../../core-primitives/utils" } -its-primitives = { default-features = false, path = "../primitives" } - -# substrate deps -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-consensus-slots = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -# sgx deps -sgx_tstd = { branch = "master", features = ["untrusted_fs", "net", "backtrace"], git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } -thiserror-sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } - -[features] -default = ["std"] -std = [ - "log/std", - "thiserror", - # local - "itp-types/std", - "its-primitives/std", - # substrate - "frame-support/std", - "sp-consensus-slots/std", - "sp-core/std", - "sp-runtime/std", -] -sgx = [ - "sgx_tstd", - "thiserror-sgx", -] - -[dev-dependencies] -itc-parentchain-test = { path = "../../core/parentchain/test" } -its-test = { path = "../../sidechain/test" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } diff --git a/bitacross-worker/sidechain/block-verification/src/error.rs b/bitacross-worker/sidechain/block-verification/src/error.rs deleted file mode 100644 index bac9b8d60b..0000000000 --- a/bitacross-worker/sidechain/block-verification/src/error.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Error types in sidechain consensus - -use itp_types::BlockHash as ParentchainBlockHash; -use its_primitives::types::{block::BlockHash as SidechainBlockHash, BlockNumber}; -use std::string::String; - -pub type Result = std::result::Result; - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -pub use thiserror_sgx as thiserror; - -#[derive(Debug, thiserror::Error)] -#[non_exhaustive] -pub enum Error { - #[error("Message sender {0} is not a valid authority")] - InvalidAuthority(String), - #[error("Could not get authorities: {0:?}.")] - CouldNotGetAuthorities(String), - #[error("Bad parentchain block (Hash={0}). Reason: {1}")] - BadParentchainBlock(ParentchainBlockHash, String), - #[error("Bad sidechain block (Hash={0}). Reason: {1}")] - BadSidechainBlock(SidechainBlockHash, String), - #[error("Could not import new block due to {2}. (Last imported by number: {0:?})")] - BlockAncestryMismatch(BlockNumber, SidechainBlockHash, String), - #[error("Could not import new block. Expected first block, but found {0}. {1:?}")] - InvalidFirstBlock(BlockNumber, String), - #[error("Could not import block (number: {0}). A block with this number is already imported (current state block number: {1})")] - BlockAlreadyImported(BlockNumber, BlockNumber), -} diff --git a/bitacross-worker/sidechain/block-verification/src/lib.rs b/bitacross-worker/sidechain/block-verification/src/lib.rs deleted file mode 100644 index b496bcc0be..0000000000 --- a/bitacross-worker/sidechain/block-verification/src/lib.rs +++ /dev/null @@ -1,492 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -#![feature(assert_matches)] -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), not(feature = "sgx")))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be disabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -use crate::slot::{slot_author, slot_from_timestamp_and_duration}; -use error::Error as ConsensusError; -use frame_support::ensure; -use itp_utils::stringify::public_to_string; -use its_primitives::{ - traits::{ - Block as SidechainBlockTrait, BlockData, Header as HeaderTrait, - SignedBlock as SignedSidechainBlockTrait, SignedBlock, - }, - types::block::BlockHash, -}; -use log::*; -pub use sp_consensus_slots::Slot; -use sp_core::ByteArray; -use sp_runtime::{ - app_crypto::Pair, - traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}, -}; -use std::{fmt::Debug, time::Duration}; - -pub mod error; -pub mod slot; - -type AuthorityId

=

::Public; - -pub fn verify_sidechain_block( - signed_block: SignedSidechainBlock, - slot_duration: Duration, - last_block: &Option<::Block>, - parentchain_header: &ParentchainBlock::Header, - authorities: &[AuthorityId], -) -> Result -where - AuthorityPair: Pair, - AuthorityPair::Public: Debug, - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: 'static + SignedSidechainBlockTrait, - SignedSidechainBlock::Block: SidechainBlockTrait, -{ - ensure!( - signed_block.verify_signature(), - ConsensusError::BadSidechainBlock(signed_block.block().hash(), "bad signature".into()) - ); - - let slot = slot_from_timestamp_and_duration( - Duration::from_millis(signed_block.block().block_data().timestamp()), - slot_duration, - ); - - // We need to check the ancestry first to ensure that an already imported block does not result - // in an author verification error, but rather a `BlockAlreadyImported` error. - match last_block { - Some(last_block) => - verify_block_ancestry::(signed_block.block(), last_block)?, - None => ensure_first_block(signed_block.block())?, - } - - if let Err(e) = verify_author::( - &slot, - signed_block.block(), - parentchain_header, - authorities, - ) { - error!( - "Author verification for block (number: {}) failed, block will be discarded", - signed_block.block().header().block_number() - ); - return Err(e) - } - - Ok(signed_block) -} - -/// Verify that the `blocks` author is the expected author when comparing with onchain data. -fn verify_author( - slot: &Slot, - block: &SignedSidechainBlock::Block, - parentchain_head: &ParentchainHeader, - authorities: &[AuthorityId], -) -> Result<(), ConsensusError> -where - AuthorityPair: Pair, - AuthorityPair::Public: Debug, - SignedSidechainBlock: SignedSidechainBlockTrait + 'static, - ParentchainHeader: ParentchainHeaderTrait, -{ - ensure!( - parentchain_head.hash() == block.block_data().layer_one_head(), - ConsensusError::BadParentchainBlock( - parentchain_head.hash(), - "Invalid parentchain head".into(), - ) - ); - - let expected_author = slot_author::(*slot, authorities) - .ok_or_else(|| ConsensusError::CouldNotGetAuthorities("No authorities found".into()))?; - - ensure!( - expected_author == block.block_data().block_author(), - ConsensusError::InvalidAuthority(format!( - "Expected author: {}, author found in block: {}", - public_to_string(&expected_author.to_raw_vec()), - public_to_string(&block.block_data().block_author().to_raw_vec()) - )) - ); - - Ok(()) -} - -fn verify_block_ancestry( - block: &SidechainBlock, - last_block: &SidechainBlock, -) -> Result<(), ConsensusError> { - // These next two checks might seem redundant at first glance. However, they are distinct (see comments). - - // We have already imported this block. - ensure!( - block.header().block_number() > last_block.header().block_number(), - ConsensusError::BlockAlreadyImported( - block.header().block_number(), - last_block.header().block_number() - ) - ); - - // We are missing some blocks between our last known block and the one we're trying to import. - ensure!( - last_block.header().block_number() + 1 == block.header().block_number(), - ConsensusError::BlockAncestryMismatch( - last_block.header().block_number(), - last_block.hash(), - format!( - "Invalid block number, {} does not succeed {}", - block.header().block_number(), - last_block.header().block_number() - ) - ) - ); - - ensure!( - last_block.hash() == block.header().parent_hash(), - ConsensusError::BlockAncestryMismatch( - last_block.header().block_number(), - last_block.hash(), - "Parent hash does not match".into(), - ) - ); - - Ok(()) -} - -fn ensure_first_block( - block: &SidechainBlock, -) -> Result<(), ConsensusError> { - ensure!( - block.header().block_number() == 1, - ConsensusError::InvalidFirstBlock( - block.header().block_number(), - "No last block found, expecting first block. But block to import has number != 1" - .into() - ) - ); - ensure!( - block.header().parent_hash() == Default::default(), - ConsensusError::InvalidFirstBlock( - block.header().block_number(), - "No last block found, excepting first block. But block to import has parent_hash != 0" - .into() - ) - ); - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use core::assert_matches::assert_matches; - use frame_support::assert_ok; - use itc_parentchain_test::ParentchainHeaderBuilder; - use itp_types::{AccountId, Block as ParentchainBlock}; - use its_primitives::types::{block::SignedBlock, header::SidechainHeader as Header}; - use its_test::{ - sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}, - sidechain_block_data_builder::SidechainBlockDataBuilder, - sidechain_header_builder::SidechainHeaderBuilder, - }; - use sp_core::{ed25519::Pair, ByteArray, H256}; - use sp_keyring::ed25519::Keyring; - - pub const SLOT_DURATION: Duration = Duration::from_millis(300); - - fn assert_ancestry_mismatch_err(result: Result) { - assert_matches!(result, Err(ConsensusError::BlockAncestryMismatch(_, _, _,))) - } - - fn block(signer: Keyring, header: Header) -> SignedBlock { - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let block_data = SidechainBlockDataBuilder::default() - .with_signer(signer.pair()) - .with_timestamp(0) - .with_layer_one_head(parentchain_header.hash()) - .build(); - - SidechainBlockBuilder::default() - .with_header(header) - .with_block_data(block_data) - .with_signer(signer.pair()) - .build_signed() - } - - fn block1(signer: Keyring) -> SignedBlock { - let header = SidechainHeaderBuilder::default().with_block_number(1).build(); - - block(signer, header) - } - - fn block2(signer: Keyring, parent_hash: H256) -> SignedBlock { - let header = SidechainHeaderBuilder::default() - .with_parent_hash(parent_hash) - .with_block_number(2) - .build(); - - block(signer, header) - } - - fn block3(signer: Keyring, parent_hash: H256, block_number: u64) -> SignedBlock { - let header = SidechainHeaderBuilder::default() - .with_parent_hash(parent_hash) - .with_block_number(block_number) - .build(); - - block(signer, header) - } - - #[test] - fn ensure_first_block_works() { - let block = SidechainBlockBuilder::default().build(); - assert_ok!(ensure_first_block(&block)); - } - - #[test] - fn ensure_first_block_errs_with_invalid_block_number() { - let header = SidechainHeaderBuilder::default().with_block_number(2).build(); - let block = SidechainBlockBuilder::default().with_header(header).build(); - assert_matches!(ensure_first_block(&block), Err(ConsensusError::InvalidFirstBlock(2, _))) - } - - #[test] - fn ensure_first_block_errs_with_invalid_parent_hash() { - let parent = H256::random(); - let header = SidechainHeaderBuilder::default().with_parent_hash(parent).build(); - let block = SidechainBlockBuilder::default().with_header(header).build(); - - assert_matches!(ensure_first_block(&block), Err(ConsensusError::InvalidFirstBlock(_, _))); - } - - #[test] - fn verify_block_ancestry_works() { - let last_block = SidechainBlockBuilder::default().build(); - let header = SidechainHeaderBuilder::default() - .with_parent_hash(last_block.hash()) - .with_block_number(2) - .build(); - let curr_block = SidechainBlockBuilder::default().with_header(header).build(); - - assert_ok!(verify_block_ancestry(&curr_block, &last_block)); - } - - #[test] - fn verify_block_ancestry_errs_with_invalid_parent_block_number() { - let last_block = SidechainBlockBuilder::default().build(); - let header = SidechainHeaderBuilder::default() - .with_parent_hash(last_block.hash()) - .with_block_number(5) - .build(); - let curr_block = SidechainBlockBuilder::default().with_header(header).build(); - - assert_ancestry_mismatch_err(verify_block_ancestry(&curr_block, &last_block)); - } - - #[test] - fn verify_block_ancestry_errs_with_invalid_parent_hash() { - let last_block = SidechainBlockBuilder::default().build(); - let header = SidechainHeaderBuilder::default().with_block_number(2).build(); - let curr_block = SidechainBlockBuilder::default().with_header(header).build(); - - assert_ancestry_mismatch_err(verify_block_ancestry(&curr_block, &last_block)); - } - - #[test] - fn verify_works() { - let signer = Keyring::Alice; - let signer_account: AccountId = signer.public().into(); - let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; - - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let last_block = SidechainBlockBuilder::default().build(); - let curr_block = block2(signer, last_block.hash()); - - assert_ok!(verify_sidechain_block::( - curr_block, - SLOT_DURATION, - &Some(last_block), - &parentchain_header, - &authorities, - )); - } - - #[test] - fn verify_works_for_first_block() { - let signer = Keyring::Alice; - let signer_account: AccountId = signer.public().into(); - let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; - - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let curr_block = block1(signer); - - assert_ok!(verify_sidechain_block::( - curr_block, - SLOT_DURATION, - &None, - &parentchain_header, - &authorities, - )); - } - - #[test] - fn verify_errs_on_wrong_authority() { - let signer = Keyring::Alice; - let signer_account: AccountId = signer.public().into(); - let bob_account: AccountId = Keyring::Bob.public().into(); - let authorities = [ - AuthorityId::::from_slice(bob_account.as_ref()).unwrap(), - AuthorityId::::from_slice(signer_account.as_ref()).unwrap(), - ]; - - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let last_block = SidechainBlockBuilder::default().build(); - let curr_block = block2(signer, last_block.hash()); - - assert_matches!( - verify_sidechain_block::( - curr_block, - SLOT_DURATION, - &Some(last_block), - &parentchain_header, - &authorities, - ) - .unwrap_err(), - ConsensusError::InvalidAuthority(_) - ); - } - - #[test] - fn verify_errs_on_invalid_ancestry() { - let signer = Keyring::Alice; - let signer_account: AccountId = signer.public().into(); - let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; - - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let last_block = SidechainBlockBuilder::default().build(); - let curr_block = block2(signer, Default::default()); - - assert_ancestry_mismatch_err(verify_sidechain_block::( - curr_block, - SLOT_DURATION, - &Some(last_block), - &parentchain_header, - &authorities, - )); - } - - #[test] - fn verify_errs_on_wrong_first_block() { - let signer = Keyring::Alice; - let signer_account: AccountId = signer.public().into(); - let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; - - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let curr_block = block2(signer, Default::default()); - - assert_matches!( - verify_sidechain_block::( - curr_block, - SLOT_DURATION, - &None, - &parentchain_header, - &authorities, - ) - .unwrap_err(), - ConsensusError::InvalidFirstBlock(2, _) - ); - } - - #[test] - fn verify_errs_on_already_imported_block() { - let signer = Keyring::Alice; - let signer_account: AccountId = signer.public().into(); - let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; - - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let last_block = SidechainBlockBuilder::default().build(); - // Current block has also number 1, same as last. So import should return an error - // that a block with this number is already imported. - let curr_block = block3(signer, last_block.hash(), 1); - - assert_matches!( - verify_sidechain_block::( - curr_block, - SLOT_DURATION, - &Some(last_block), - &parentchain_header, - &authorities, - ) - .unwrap_err(), - ConsensusError::BlockAlreadyImported(1, 1) - ); - } - - #[test] - fn verify_block_already_imported_error_even_if_parentchain_block_mismatches() { - // This test is to ensure that we get a 'AlreadyImported' error, when the sidechain block - // is already imported, and the parentchain block that is passed into the verifier is newer. - // Important because client of the verifier acts differently for an 'AlreadyImported' error than an 'AncestryErrorMismatch'. - - let signer = Keyring::Alice; - let signer_account: AccountId = signer.public().into(); - let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; - - let parentchain_header_1 = ParentchainHeaderBuilder::default().with_number(1).build(); - let parentchain_header_2 = ParentchainHeaderBuilder::default().with_number(2).build(); - - let block_data = SidechainBlockDataBuilder::default() - .with_layer_one_head(parentchain_header_1.hash()) - .with_signer(signer.pair()) - .build(); - let last_block = SidechainBlockBuilder::default() - .with_block_data(block_data) - .with_signer(signer.pair()) - .build(); - - let block_data_for_signed_block = SidechainBlockDataBuilder::default() - .with_layer_one_head(parentchain_header_1.hash()) - .with_signer(signer.pair()) - .build(); - let signed_block_to_verify = SidechainBlockBuilder::default() - .with_block_data(block_data_for_signed_block) - .with_signer(signer.pair()) - .build_signed(); - - assert_matches!( - verify_sidechain_block::( - signed_block_to_verify, - SLOT_DURATION, - &Some(last_block), - &parentchain_header_2, - &authorities, - ) - .unwrap_err(), - ConsensusError::BlockAlreadyImported(1, 1) - ); - } -} diff --git a/bitacross-worker/sidechain/block-verification/src/slot.rs b/bitacross-worker/sidechain/block-verification/src/slot.rs deleted file mode 100644 index 5eb2ede417..0000000000 --- a/bitacross-worker/sidechain/block-verification/src/slot.rs +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::AuthorityId; -pub use sp_consensus_slots::Slot; -use sp_runtime::app_crypto::Pair; -use std::time::Duration; - -/// Get slot author for given block along with authorities. -pub fn slot_author(slot: Slot, authorities: &[AuthorityId

]) -> Option<&AuthorityId

> { - if authorities.is_empty() { - log::warn!("Authorities list is empty, cannot determine slot author"); - return None - } - - let idx = *slot % (authorities.len() as u64); - assert!( - idx <= usize::MAX as u64, - "It is impossible to have a vector with length beyond the address space; qed", - ); - - let current_author = authorities.get(idx as usize).expect( - "authorities not empty; index constrained to list length;this is a valid index; qed", - ); - - Some(current_author) -} - -pub fn slot_from_timestamp_and_duration(timestamp: Duration, duration: Duration) -> Slot { - ((timestamp.as_millis() / duration.as_millis()) as u64).into() -} diff --git a/bitacross-worker/sidechain/consensus/aura/Cargo.toml b/bitacross-worker/sidechain/consensus/aura/Cargo.toml deleted file mode 100644 index a7a52de35e..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/Cargo.toml +++ /dev/null @@ -1,105 +0,0 @@ -[package] -name = "its-consensus-aura" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "chain-error"] } -finality-grandpa = { version = "0.16.0", default-features = false, features = ["derive-codec"] } -log = { version = "0.4", default-features = false } - -# sgx deps -sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } - -# substrate deps -sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -# local deps -ita-stf = { path = "../../../app-libs/stf", default-features = false } -itc-parentchain-block-import-dispatcher = { path = "../../../core/parentchain/block-import-dispatcher", default-features = false } -itc-peer-top-broadcaster = { path = "../../../core/peer-top-broadcaster", default-features = false } -itp-enclave-metrics = { path = "../../../core-primitives/enclave-metrics", default-features = false } -itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } -itp-settings = { path = "../../../core-primitives/settings" } -itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } -itp-sgx-externalities = { path = "../../../core-primitives/substrate-sgx/externalities", default-features = false } -itp-stf-executor = { path = "../../../core-primitives/stf-executor", default-features = false } -itp-stf-primitives = { path = "../../../core-primitives/stf-primitives", default-features = false } -itp-stf-state-handler = { path = "../../../core-primitives/stf-state-handler", default-features = false } -itp-time-utils = { path = "../../../core-primitives/time-utils", default-features = false } -itp-top-pool-author = { path = "../../../core-primitives/top-pool-author", default-features = false } -itp-types = { path = "../../../core-primitives/types", default-features = false } -its-block-composer = { path = "../../block-composer", default-features = false } -its-block-verification = { path = "../../block-verification", optional = true, default-features = false } -its-consensus-common = { path = "../common", default-features = false } -its-consensus-slots = { path = "../slots", default-features = false } -its-primitives = { path = "../../primitives", default-features = false } -its-state = { path = "../../state", default-features = false } -its-validateer-fetch = { path = "../../validateer-fetch", default-features = false } - -# litentry -itp-utils = { path = "../../../core-primitives/utils", default-features = false } -lc-scheduled-enclave = { path = "../../../litentry/core/scheduled-enclave", default-features = false } - -[dev-dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -env_logger = "0.9.0" -itc-parentchain-block-import-dispatcher = { path = "../../../core/parentchain/block-import-dispatcher", features = ["mocks"] } -itc-parentchain-test = { path = "../../../core/parentchain/test" } -itp-storage = { path = "../../../core-primitives/storage" } -itp-test = { path = "../../../core-primitives/test" } -its-test = { path = "../../../sidechain/test" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -[features] -default = ["std"] -std = [ - #crates.io - "codec/std", - "finality-grandpa/std", - "log/std", - #substrate - "sp-core/std", - "sp-runtime/std", - #local - "ita-stf/std", - "itc-parentchain-block-import-dispatcher/std", - "itc-peer-top-broadcaster/std", - "itp-enclave-metrics/std", - "itp-ocall-api/std", - "itp-sgx-crypto/std", - "itp-sgx-externalities/std", - "itp-stf-executor/std", - "itp-stf-primitives/std", - "itp-stf-state-handler/std", - "itp-time-utils/std", - "itp-types/std", - "its-block-composer/std", - "its-block-verification/std", - "its-consensus-common/std", - "its-consensus-slots/std", - "its-state/std", - "its-validateer-fetch/std", - "its-primitives/std", - "lc-scheduled-enclave/std", -] -sgx = [ - "sgx_tstd", - "ita-stf/sgx", - "itc-parentchain-block-import-dispatcher/sgx", - "itc-peer-top-broadcaster/sgx", - "itp-enclave-metrics/sgx", - "itp-sgx-crypto/sgx", - "itp-sgx-externalities/sgx", - "itp-stf-executor/sgx", - "itp-stf-state-handler/sgx", - "itp-time-utils/sgx", - "its-block-composer/sgx", - "its-consensus-common/sgx", - "its-consensus-slots/sgx", - "its-state/sgx", - "its-block-verification/sgx", - "lc-scheduled-enclave/sgx", -] diff --git a/bitacross-worker/sidechain/consensus/aura/src/block_importer.rs b/bitacross-worker/sidechain/consensus/aura/src/block_importer.rs deleted file mode 100644 index fb6f4e246a..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/block_importer.rs +++ /dev/null @@ -1,367 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -//! Implementation of the sidechain block importer struct. -//! Imports sidechain blocks and applies the accompanying state diff to its state. - -use codec::{Decode, Encode}; -use core::fmt::Debug; -// Reexport BlockImport trait which implements fn block_import() -use crate::{AuraVerifier, EnclaveOnChainOCallApi, SidechainBlockTrait}; -use itc_parentchain_block_import_dispatcher::triggered_dispatcher::TriggerParentchainBlockImport; -use itc_peer_top_broadcaster::PeerUpdater; -use itp_enclave_metrics::EnclaveMetric; -use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; -use itp_settings::sidechain::SLOT_DURATION; -use itp_sgx_crypto::{key_repository::AccessKey, StateCrypto}; -use itp_sgx_externalities::SgxExternalities; -use itp_stf_primitives::{traits::TrustedCallVerification, types::TrustedOperationOrHash}; -use itp_stf_state_handler::handle_state::HandleState; -use itp_top_pool_author::traits::{AuthorApi, OnBlockImported}; -use itp_types::H256; -pub use its_consensus_common::BlockImport; -use its_consensus_common::Error as ConsensusError; -use its_primitives::traits::{ - BlockData, Header as HeaderTrait, ShardIdentifierFor, SignedBlock as SignedBlockTrait, -}; -use its_validateer_fetch::ValidateerFetch; -use log::*; -use sp_core::{crypto::UncheckedFrom, Pair}; -use sp_runtime::{ - generic::SignedBlock as SignedParentchainBlock, - traits::{Block as ParentchainBlockTrait, Header}, -}; -use std::{marker::PhantomData, sync::Arc}; - -/// Implements `BlockImport`. -#[derive(Clone)] -pub struct BlockImporter< - Authority, - ParentchainBlock, - SignedSidechainBlock, - OCallApi, - StateHandler, - StateKeyRepository, - TopPoolAuthor, - ParentchainBlockImporter, - PeersUpdater, - TCS, - G, -> { - state_handler: Arc, - state_key_repository: Arc, - top_pool_author: Arc, - parentchain_block_importer: Arc, - ocall_api: Arc, - peer_updater: Arc, - _phantom: PhantomData<(Authority, ParentchainBlock, SignedSidechainBlock, TCS, G)>, -} - -impl< - Authority, - ParentchainBlock, - SignedSidechainBlock, - OCallApi, - StateHandler, - StateKeyRepository, - TopPoolAuthor, - ParentchainBlockImporter, - PeersUpdater, - TCS, - G, - > - BlockImporter< - Authority, - ParentchainBlock, - SignedSidechainBlock, - OCallApi, - StateHandler, - StateKeyRepository, - TopPoolAuthor, - ParentchainBlockImporter, - PeersUpdater, - TCS, - G, - > where - Authority: Pair, - Authority::Public: std::fmt::Debug + UncheckedFrom<[u8; 32]>, - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedBlockTrait + 'static, - <::Block as SidechainBlockTrait>::HeaderType: - HeaderTrait, - OCallApi: EnclaveSidechainOCallApi - + ValidateerFetch - + EnclaveOnChainOCallApi - + EnclaveMetricsOCallApi - + Send - + Sync, - StateHandler: HandleState, - StateKeyRepository: AccessKey, - ::KeyType: StateCrypto, - TopPoolAuthor: AuthorApi + OnBlockImported, - ParentchainBlockImporter: TriggerParentchainBlockImport> - + Send - + Sync, - PeersUpdater: PeerUpdater, - TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, - G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, -{ - pub fn new( - state_handler: Arc, - state_key_repository: Arc, - top_pool_author: Arc, - parentchain_block_importer: Arc, - ocall_api: Arc, - peer_updater: Arc, - ) -> Self { - Self { - state_handler, - state_key_repository, - top_pool_author, - parentchain_block_importer, - ocall_api, - peer_updater, - _phantom: Default::default(), - } - } - - fn update_top_pool(&self, sidechain_block: &SignedSidechainBlock::Block) { - // Notify pool about imported block for status updates of the calls. - self.top_pool_author.on_block_imported( - sidechain_block.block_data().signed_top_hashes(), - sidechain_block.hash(), - ); - - // Remove calls from pool. - let executed_operations = sidechain_block - .block_data() - .signed_top_hashes() - .iter() - .map(|hash| (TrustedOperationOrHash::Hash(*hash), true)) - .collect(); - - let _calls_failed_to_remove = self - .top_pool_author - .remove_calls_from_pool(sidechain_block.header().shard_id(), executed_operations); - - // In case the executed call did not originate in our own TOP pool, we will not be able to remove it from our TOP pool. - // So this error will occur frequently, without it meaning that something really went wrong. - // TODO: Once the TOP pools are synchronized, we will want this check again! - // for call_failed_to_remove in _calls_failed_to_remove { - // error!("Could not remove call {:?} from top pool", call_failed_to_remove); - // } - } -} - -impl< - Authority, - ParentchainBlock, - SignedSidechainBlock, - OCallApi, - StateHandler, - StateKeyRepository, - TopPoolAuthor, - ParentchainBlockImporter, - PeersUpdater, - TCS, - G, - > BlockImport - for BlockImporter< - Authority, - ParentchainBlock, - SignedSidechainBlock, - OCallApi, - StateHandler, - StateKeyRepository, - TopPoolAuthor, - ParentchainBlockImporter, - PeersUpdater, - TCS, - G, - > where - Authority: Pair, - Authority::Public: std::fmt::Debug + UncheckedFrom<[u8; 32]>, - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedBlockTrait + 'static, - <::Block as SidechainBlockTrait>::HeaderType: - HeaderTrait, - OCallApi: EnclaveSidechainOCallApi - + ValidateerFetch - + EnclaveOnChainOCallApi - + EnclaveMetricsOCallApi - + Send - + Sync, - StateHandler: HandleState, - StateKeyRepository: AccessKey, - ::KeyType: StateCrypto, - TopPoolAuthor: AuthorApi + OnBlockImported, - ParentchainBlockImporter: TriggerParentchainBlockImport> - + Send - + Sync, - PeersUpdater: PeerUpdater, - TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, - G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, -{ - type Verifier = AuraVerifier; - type SidechainState = SgxExternalities; - type StateCrypto = ::KeyType; - type Context = OCallApi; - - fn verifier( - &self, - maybe_last_sidechain_block: Option, - ) -> Self::Verifier { - AuraVerifier::::new( - SLOT_DURATION, - maybe_last_sidechain_block, - ) - } - - fn apply_state_update( - &self, - shard: &ShardIdentifierFor, - mutating_function: F, - ) -> Result<(), ConsensusError> - where - F: FnOnce(Self::SidechainState) -> Result, - { - let (write_lock, state) = self - .state_handler - .load_for_mutation(shard) - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; - - // We load a copy of the state and apply the update. In case the update fails, we don't write - // the state back to the state handler, and thus guaranteeing state integrity. - let updated_state = mutating_function(state)?; - - self.state_handler - .write_after_mutation(updated_state, write_lock, shard) - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; - - Ok(()) - } - - fn verify_import( - &self, - shard: &ShardIdentifierFor, - verifying_function: F, - ) -> Result - where - F: FnOnce(&Self::SidechainState) -> Result, - { - self.state_handler - .execute_on_current(shard, |state, _| verifying_function(state)) - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))? - } - - fn state_key(&self) -> Result { - self.state_key_repository - .retrieve_key() - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into())) - } - - fn get_context(&self) -> &Self::Context { - &self.ocall_api - } - - fn import_parentchain_block( - &self, - sidechain_block: &SignedSidechainBlock::Block, - last_imported_parentchain_header: &ParentchainBlock::Header, - ) -> Result { - // get new peer list on each parentchain block import - if let Ok(peers) = self.ocall_api.get_trusted_peers_urls() { - self.peer_updater.update(peers); - } - - // We trigger the import of parentchain blocks up until the last one we've seen in the - // sidechain block that we're importing. This is done to prevent forks in the sidechain (#423) - let maybe_latest_imported_block = self - .parentchain_block_importer - .import_until(|signed_parentchain_block| { - signed_parentchain_block.block.hash() - == sidechain_block.block_data().layer_one_head() - }) - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; - - Ok(maybe_latest_imported_block - .map(|b| b.block.header().clone()) - .unwrap_or_else(|| last_imported_parentchain_header.clone())) - } - - fn peek_parentchain_header( - &self, - sidechain_block: &SignedSidechainBlock::Block, - last_imported_parentchain_header: &ParentchainBlock::Header, - ) -> Result { - let last = last_imported_parentchain_header; - debug!("Peeking parentchain header"); - debug!( - "sidechain block parentchain head: {}", - sidechain_block.block_data().layer_one_head() - ); - debug!( - "last imported head: {}, number: {:?}, parenthash: {}", - last.hash(), - last.number(), - last.parent_hash() - ); - - let parentchain_header_hash_to_peek = sidechain_block.block_data().layer_one_head(); - if parentchain_header_hash_to_peek == last_imported_parentchain_header.hash() { - debug!("No queue peek necessary, sidechain block references latest imported parentchain block"); - return Ok(last_imported_parentchain_header.clone()) - } - - let maybe_signed_parentchain_block = self - .parentchain_block_importer - .peek(|parentchain_block| { - parentchain_block.block.header().hash() == parentchain_header_hash_to_peek - }) - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; - - maybe_signed_parentchain_block - .map(|signed_block| signed_block.block.header().clone()) - .ok_or_else(|| { - ConsensusError::Other( - format!( - "Failed to find parentchain header in import queue (hash: {}) that is \ - associated with the current sidechain block that is to be imported (number: {}, hash: {})", - parentchain_header_hash_to_peek, - sidechain_block.header().block_number(), - sidechain_block.hash() - ) - .into(), - ) - }) - } - - fn cleanup(&self, signed_sidechain_block: &SignedSidechainBlock) -> Result<(), ConsensusError> { - let sidechain_block = signed_sidechain_block.block(); - - // Remove all successfully applied trusted calls from the top pool. - self.update_top_pool(sidechain_block); - - // Send metric about sidechain block height (i.e. block number) - let block_height_metric = - EnclaveMetric::SetSidechainBlockHeight(sidechain_block.header().block_number()); - if let Err(e) = self.ocall_api.update_metric(block_height_metric) { - warn!("Failed to update sidechain block height metric: {:?}", e); - } - - Ok(()) - } -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/lib.rs b/bitacross-worker/sidechain/consensus/aura/src/lib.rs deleted file mode 100644 index 193eb0501c..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/lib.rs +++ /dev/null @@ -1,773 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Aura worker for the sidechain. -//! -//! It is inspired by parity's implementation but has been greatly amended. - -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(test, feature(assert_matches))] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -use codec::Encode; -use core::marker::PhantomData; -use itc_parentchain_block_import_dispatcher::triggered_dispatcher::TriggerParentchainBlockImport; -use itp_ocall_api::EnclaveOnChainOCallApi; -use itp_sgx_externalities::SgxExternalities; -use itp_stf_state_handler::handle_state::HandleState; -use itp_time_utils::duration_now; - -use itp_utils::hex::hex_encode; -use its_block_verification::slot::slot_author; -use its_consensus_common::{Environment, Error as ConsensusError, Proposer}; -use its_consensus_slots::{SimpleSlotWorker, Slot, SlotInfo}; -use its_primitives::{ - traits::{Block as SidechainBlockTrait, Header as HeaderTrait, SignedBlock}, - types::block::BlockHash, -}; -use its_validateer_fetch::ValidateerFetch; -use lc_scheduled_enclave::ScheduledEnclaveUpdater; -use sp_core::ByteArray; -use sp_runtime::{ - app_crypto::{sp_core::H256, Pair}, - generic::SignedBlock as SignedParentchainBlock, - traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}, -}; -use std::{string::ToString, sync::Arc, time::Duration, vec::Vec}; - -pub mod block_importer; -pub mod proposer_factory; -pub mod slot_proposer; -mod verifier; - -pub use verifier::*; - -#[cfg(test)] -mod test; - -/// Aura consensus struct. -pub struct Aura< - AuthorityPair, - ParentchainBlock, - SidechainBlock, - Environment, - OcallApi, - IntegriteeImportTrigger, - TargetAImportTrigger, - TargetBImportTrigger, - ScheduledEnclave, - StateHandler, -> { - authority_pair: AuthorityPair, - ocall_api: OcallApi, - parentchain_integritee_import_trigger: Arc, - maybe_parentchain_target_a_import_trigger: Option>, - maybe_parentchain_target_b_import_trigger: Option>, - environment: Environment, - claim_strategy: SlotClaimStrategy, - scheduled_enclave: Arc, - state_handler: Arc, - _phantom: PhantomData<(AuthorityPair, ParentchainBlock, SidechainBlock)>, -} - -impl< - AuthorityPair, - ParentchainBlock, - SidechainBlock, - Environment, - OcallApi, - IntegriteeImportTrigger, - TargetAImportTrigger, - TargetBImportTrigger, - ScheduledEnclave, - StateHandler, - > - Aura< - AuthorityPair, - ParentchainBlock, - SidechainBlock, - Environment, - OcallApi, - IntegriteeImportTrigger, - TargetAImportTrigger, - TargetBImportTrigger, - ScheduledEnclave, - StateHandler, - > -{ - #[allow(clippy::too_many_arguments)] - pub fn new( - authority_pair: AuthorityPair, - ocall_api: OcallApi, - parentchain_integritee_import_trigger: Arc, - maybe_parentchain_target_a_import_trigger: Option>, - maybe_parentchain_target_b_import_trigger: Option>, - environment: Environment, - scheduled_enclave: Arc, - state_handler: Arc, - ) -> Self { - Self { - authority_pair, - ocall_api, - parentchain_integritee_import_trigger, - maybe_parentchain_target_a_import_trigger, - maybe_parentchain_target_b_import_trigger, - environment, - claim_strategy: SlotClaimStrategy::RoundRobin, - scheduled_enclave, - state_handler, - _phantom: Default::default(), - } - } - - pub fn with_claim_strategy(mut self, claim_strategy: SlotClaimStrategy) -> Self { - self.claim_strategy = claim_strategy; - - self - } -} - -/// The fraction of total block time we are allowed to be producing the block. So that we have -/// enough time send create and send the block to fellow validateers. -pub const BLOCK_PROPOSAL_SLOT_PORTION: f32 = 0.7; - -#[derive(PartialEq, Eq, Debug)] -pub enum SlotClaimStrategy { - /// try to produce a block always even if it's not the authors slot - /// Intended for first phase to see if aura production works - Always, - /// Proper Aura strategy: Only produce blocks, when it's the authors slot. - RoundRobin, -} - -type AuthorityId

=

::Public; -type ShardIdentifierFor = - <<::Block as SidechainBlockTrait>::HeaderType as HeaderTrait>::ShardIdentifier; - -impl< - AuthorityPair, - ParentchainBlock, - SignedSidechainBlock, - E, - OcallApi, - IntegriteeImportTrigger, - TargetAImportTrigger, - TargetBImportTrigger, - ScheduledEnclave, - StateHandler, - > SimpleSlotWorker - for Aura< - AuthorityPair, - ParentchainBlock, - SignedSidechainBlock, - E, - OcallApi, - IntegriteeImportTrigger, - TargetAImportTrigger, - TargetBImportTrigger, - ScheduledEnclave, - StateHandler, - > where - AuthorityPair: Pair, - // todo: Relax hash trait bound, but this needs a change to some other parts in the code. - ParentchainBlock: ParentchainBlockTrait, - E: Environment, - E::Proposer: Proposer, - SignedSidechainBlock: SignedBlock + Send + 'static, - OcallApi: ValidateerFetch + EnclaveOnChainOCallApi + Send + 'static, - IntegriteeImportTrigger: - TriggerParentchainBlockImport>, - TargetAImportTrigger: - TriggerParentchainBlockImport>, - TargetBImportTrigger: - TriggerParentchainBlockImport>, - ScheduledEnclave: ScheduledEnclaveUpdater, - StateHandler: HandleState, -{ - type Proposer = E::Proposer; - type Claim = AuthorityPair::Public; - type EpochData = Vec>; - type Output = SignedSidechainBlock; - type ScheduledEnclave = ScheduledEnclave; - type StateHandler = StateHandler; - - fn logging_target(&self) -> &'static str { - "aura" - } - - fn get_scheduled_enclave(&mut self) -> Arc { - self.scheduled_enclave.clone() - } - - fn get_state_handler(&mut self) -> Arc { - self.state_handler.clone() - } - - fn epoch_data( - &self, - header: &ParentchainBlock::Header, - _shard: ShardIdentifierFor, - _slot: Slot, - ) -> Result { - authorities::<_, AuthorityPair, ParentchainBlock::Header>(&self.ocall_api, header) - } - - fn authorities_len(&self, epoch_data: &Self::EpochData) -> Option { - Some(epoch_data.len()) - } - - // While the header is not used in aura, it is used in different consensus systems, so it should be left there. - fn claim_slot( - &self, - _header: &ParentchainBlock::Header, - slot: Slot, - epoch_data: &Self::EpochData, - ) -> Option { - let expected_author = slot_author::(slot, epoch_data)?; - - if expected_author == &self.authority_pair.public() { - log::info!(target: self.logging_target(), "Claiming slot ({})", *slot); - return Some(self.authority_pair.public()) - } - - if self.claim_strategy == SlotClaimStrategy::Always { - log::debug!( - target: self.logging_target(), - "Not our slot but we still claim it." - ); - return Some(self.authority_pair.public()) - } - - None - } - - fn proposer( - &mut self, - header: ParentchainBlock::Header, - shard: ShardIdentifierFor, - ) -> Result { - self.environment.init(header, shard) - } - - fn proposing_remaining_duration(&self, slot_info: &SlotInfo) -> Duration { - proposing_remaining_duration(slot_info, duration_now()) - } - - // Design remark: the following may seem too explicit and it certainly could be abstracted. - // however, as pretty soon we may not want to assume same Block types for all parentchains, - // it may make sense to abstract once we do that. - - fn import_integritee_parentchain_blocks_until( - &self, - parentchain_header_hash: &::Hash, - ) -> Result, ConsensusError> { - log::trace!(target: self.logging_target(), "import Integritee blocks until {}", hex_encode(parentchain_header_hash.encode().as_ref())); - let maybe_parentchain_block = self - .parentchain_integritee_import_trigger - .import_until(|parentchain_block| { - parentchain_block.block.hash() == *parentchain_header_hash - }) - .map_err(|e| ConsensusError::Other(e.into()))?; - - Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) - } - - fn import_target_a_parentchain_blocks_until( - &self, - parentchain_header_hash: &::Hash, - ) -> Result, ConsensusError> { - log::trace!(target: self.logging_target(), "import TargetA blocks until {}", hex_encode(parentchain_header_hash.encode().as_ref())); - let maybe_parentchain_block = self - .maybe_parentchain_target_a_import_trigger - .clone() - .ok_or_else(|| ConsensusError::Other("no target_a assigned".into()))? - .import_until(|parentchain_block| { - parentchain_block.block.hash() == *parentchain_header_hash - }) - .map_err(|e| ConsensusError::Other(e.into()))?; - - Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) - } - - fn import_target_b_parentchain_blocks_until( - &self, - parentchain_header_hash: &::Hash, - ) -> Result, ConsensusError> { - log::trace!(target: self.logging_target(), "import TargetB blocks until {}", hex_encode(parentchain_header_hash.encode().as_ref())); - let maybe_parentchain_block = self - .maybe_parentchain_target_b_import_trigger - .clone() - .ok_or_else(|| ConsensusError::Other("no target_b assigned".into()))? - .import_until(|parentchain_block| { - parentchain_block.block.hash() == *parentchain_header_hash - }) - .map_err(|e| ConsensusError::Other(e.into()))?; - - Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) - } - - fn peek_latest_integritee_parentchain_header( - &self, - ) -> Result, ConsensusError> { - let maybe_parentchain_block = self - .parentchain_integritee_import_trigger - .peek_latest() - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; - - Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) - } - - fn peek_latest_target_a_parentchain_header( - &self, - ) -> Result, ConsensusError> { - let maybe_parentchain_block = self - .maybe_parentchain_target_a_import_trigger - .clone() - .ok_or_else(|| ConsensusError::Other("no target_a assigned".into()))? - .peek_latest() - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; - - Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) - } - - fn peek_latest_target_b_parentchain_header( - &self, - ) -> Result, ConsensusError> { - let maybe_parentchain_block = self - .maybe_parentchain_target_b_import_trigger - .clone() - .ok_or_else(|| ConsensusError::Other("no target_b assigned".into()))? - .peek_latest() - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; - - Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) - } -} - -/// unit-testable remaining duration fn. -fn proposing_remaining_duration( - slot_info: &SlotInfo, - now: Duration, -) -> Duration { - // if a `now` before slot begin is passed such that `slot_remaining` would be bigger than `slot.slot_duration` - // we take the total `slot_duration` as reference value. - let proposing_duration = slot_info.duration.mul_f32(BLOCK_PROPOSAL_SLOT_PORTION); - - let slot_remaining = slot_info - .ends_at - .checked_sub(now) - .map(|remaining| remaining.mul_f32(BLOCK_PROPOSAL_SLOT_PORTION)) - .unwrap_or_default(); - - std::cmp::min(slot_remaining, proposing_duration) -} - -fn authorities( - ocall_api: &ValidateerFetcher, - header: &ParentchainHeader, -) -> Result>, ConsensusError> -where - ValidateerFetcher: ValidateerFetch + EnclaveOnChainOCallApi, - P: Pair, - ParentchainHeader: ParentchainHeaderTrait, -{ - Ok(ocall_api - .current_validateers(header) - .map_err(|e| ConsensusError::CouldNotGetAuthorities(e.to_string()))? - .into_iter() - .filter_map(|e| AuthorityId::

::from_slice(e.pubkey.as_ref()).ok()) - .collect()) -} - -pub enum AnyImportTrigger { - Integritee(Integritee), - TargetA(TargetA), - TargetB(TargetB), -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::test::{ - fixtures::{types::TestAura, validateer, SLOT_DURATION}, - mocks::environment_mock::{EnvironmentMock, OutdatedBlockEnvironmentMock}, - }; - use itc_parentchain_block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; - use itc_parentchain_test::{ParentchainBlockBuilder, ParentchainHeaderBuilder}; - use itp_test::mock::{handle_state_mock::HandleStateMock, onchain_mock::OnchainMock}; - use itp_types::{ - Block as ParentchainBlock, Enclave, Header as ParentchainHeader, ShardIdentifier, - SignedBlock as SignedParentchainBlock, - }; - use its_consensus_slots::PerShardSlotWorkerScheduler; - use lc_scheduled_enclave::ScheduledEnclaveMock; - use sp_core::ed25519::Public; - use sp_keyring::ed25519::Keyring; - - fn get_aura( - onchain_mock: OnchainMock, - trigger_parentchain_import: Arc>, - ) -> TestAura { - Aura::new( - Keyring::Alice.pair(), - onchain_mock, - trigger_parentchain_import, - None, - None, - EnvironmentMock, - Arc::new(ScheduledEnclaveMock::default()), - Arc::new(HandleStateMock::from_shard(ShardIdentifier::default()).unwrap()), - ) - } - - fn get_aura_outdated( - onchain_mock: OnchainMock, - trigger_parentchain_import: Arc>, - ) -> TestAura { - Aura::new( - Keyring::Alice.pair(), - onchain_mock, - trigger_parentchain_import, - None, - None, - OutdatedBlockEnvironmentMock, - Arc::new(ScheduledEnclaveMock::default()), - Arc::new(HandleStateMock::from_shard(ShardIdentifier::default()).unwrap()), - ) - } - - fn get_default_aura() -> TestAura { - get_aura(Default::default(), Default::default()) - } - - fn now_slot(slot: Slot, header: &ParentchainHeader) -> SlotInfo { - let now = duration_now(); - SlotInfo { - slot, - timestamp: now, - duration: SLOT_DURATION, - ends_at: now + SLOT_DURATION, - last_imported_integritee_parentchain_head: header.clone(), - maybe_last_imported_target_a_parentchain_head: None, - maybe_last_imported_target_b_parentchain_head: None, - } - } - - fn now_slot_with_default_header(slot: Slot) -> SlotInfo { - now_slot(slot, &ParentchainHeaderBuilder::default().build()) - } - - fn default_authorities() -> Vec { - vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()] - } - - fn create_validateer_set_from_publics(authorities: Vec) -> Vec { - authorities.iter().map(|a| validateer(a.clone().into())).collect() - } - - fn onchain_mock( - parentchain_header: &ParentchainHeader, - authorities: Vec, - ) -> OnchainMock { - let validateers = create_validateer_set_from_publics(authorities); - OnchainMock::default().add_validateer_set(parentchain_header, Some(validateers)) - } - - fn onchain_mock_with_default_authorities_and_header() -> OnchainMock { - let parentchain_header = ParentchainHeaderBuilder::default().build(); - onchain_mock(&parentchain_header, default_authorities()) - } - - fn create_import_trigger_with_header( - header: ParentchainHeader, - ) -> Arc> { - let latest_parentchain_block = - ParentchainBlockBuilder::default().with_header(header).build_signed(); - Arc::new( - TriggerParentchainBlockImportMock::default() - .with_latest_imported(Some(latest_parentchain_block)), - ) - } - - #[test] - fn current_authority_should_claim_its_slot() { - let authorities = - vec![Keyring::Bob.public(), Keyring::Charlie.public(), Keyring::Alice.public()]; - let aura = get_default_aura(); - let header = ParentchainHeaderBuilder::default().build(); - - assert!(aura.claim_slot(&header, 0.into(), &authorities).is_none()); - assert!(aura.claim_slot(&header, 1.into(), &authorities).is_none()); - // this our authority - assert!(aura.claim_slot(&header, 2.into(), &authorities).is_some()); - - assert!(aura.claim_slot(&header, 3.into(), &authorities).is_none()); - assert!(aura.claim_slot(&header, 4.into(), &authorities).is_none()); - // this our authority - assert!(aura.claim_slot(&header, 5.into(), &authorities).is_some()); - } - - #[test] - fn current_authority_should_claim_all_slots() { - let header = ParentchainHeaderBuilder::default().build(); - let authorities = default_authorities(); - let aura = get_default_aura().with_claim_strategy(SlotClaimStrategy::Always); - - assert!(aura.claim_slot(&header, 0.into(), &authorities).is_some()); - assert!(aura.claim_slot(&header, 1.into(), &authorities).is_some()); - // this our authority - assert!(aura.claim_slot(&header, 2.into(), &authorities).is_some()); - assert!(aura.claim_slot(&header, 3.into(), &authorities).is_some()); - } - - #[test] - fn on_slot_returns_block() { - let _ = env_logger::builder().is_test(true).try_init(); - - let onchain_mock = onchain_mock_with_default_authorities_and_header(); - let mut aura = get_aura(onchain_mock, Default::default()); - - let slot_info = now_slot_with_default_header(0.into()); - - assert!( - SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false).is_some() - ); - } - - #[test] - fn on_slot_returns_no_block_if_slot_time_exceeded_for_multi_worker() { - let _ = env_logger::builder().is_test(true).try_init(); - - let onchain_mock = onchain_mock_with_default_authorities_and_header(); - let mut aura = get_aura_outdated(onchain_mock, Default::default()); - let slot_info = now_slot_with_default_header(0.into()); - - assert!( - SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false).is_none() - ); - } - - #[test] - fn on_slot_returns_block_if_slot_time_exceeded_for_single_worker() { - let _ = env_logger::builder().is_test(true).try_init(); - - let onchain_mock = onchain_mock_with_default_authorities_and_header(); - let mut aura = get_aura_outdated(onchain_mock, Default::default()); - let slot_info = now_slot_with_default_header(0.into()); - - assert!(SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), true).is_some()); - } - - #[test] - fn on_slot_for_multiple_shards_returns_blocks() { - let _ = env_logger::builder().is_test(true).try_init(); - - let onchain_mock = onchain_mock_with_default_authorities_and_header(); - let mut aura = get_aura(onchain_mock, Default::default()); - - let slot_info = now_slot_with_default_header(0.into()); - - let result = PerShardSlotWorkerScheduler::on_slot( - &mut aura, - slot_info, - vec![Default::default(), Default::default()], - false, - ); - - assert_eq!(result.len(), 2); - } - - #[test] - fn on_slot_with_nano_second_remaining_duration_does_not_panic() { - let _ = env_logger::builder().is_test(true).try_init(); - - let mut aura = get_default_aura(); - - let nano_dur = Duration::from_nanos(999); - let now = duration_now(); - - let slot_info = SlotInfo { - slot: 0.into(), - timestamp: now, - duration: nano_dur, - ends_at: now + nano_dur, - last_imported_integritee_parentchain_head: ParentchainHeaderBuilder::default().build(), - maybe_last_imported_target_a_parentchain_head: None, - maybe_last_imported_target_b_parentchain_head: None, - }; - - let result = PerShardSlotWorkerScheduler::on_slot( - &mut aura, - slot_info, - vec![Default::default(), Default::default()], - false, - ); - - assert_eq!(result.len(), 0); - } - - #[test] - fn on_slot_triggers_parentchain_block_import_if_slot_is_claimed() { - let _ = env_logger::builder().is_test(true).try_init(); - let latest_parentchain_header = ParentchainHeaderBuilder::default().with_number(84).build(); - let parentchain_block_import_trigger = - create_import_trigger_with_header(latest_parentchain_header.clone()); - let authorities = default_authorities(); - - let mut aura = get_aura( - onchain_mock(&latest_parentchain_header, authorities), - parentchain_block_import_trigger.clone(), - ); - - let slot_info = now_slot(0.into(), &latest_parentchain_header); - - let result = - SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false).unwrap(); - - assert_eq!( - result.block.block.block_data().layer_one_head, - latest_parentchain_header.hash() - ); - assert!(parentchain_block_import_trigger.has_import_been_called()); - } - - #[test] - fn on_slot_does_not_trigger_parentchain_block_import_if_slot_is_not_claimed() { - let _ = env_logger::builder().is_test(true).try_init(); - let latest_parentchain_header = ParentchainHeaderBuilder::default().with_number(84).build(); - let parentchain_block_import_trigger = - create_import_trigger_with_header(latest_parentchain_header.clone()); - let authorities = default_authorities(); - - let mut aura = get_aura( - onchain_mock(&latest_parentchain_header, authorities), - parentchain_block_import_trigger.clone(), - ); - - let slot_info = now_slot(2.into(), &latest_parentchain_header); - - let result = SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false); - - assert!(result.is_none()); - assert!(!parentchain_block_import_trigger.has_import_been_called()); - } - - #[test] - fn on_slot_claims_slot_if_latest_parentchain_header_in_queue_contains_correspondent_validateer_set( - ) { - let _ = env_logger::builder().is_test(true).try_init(); - let already_imported_parentchain_header = - ParentchainHeaderBuilder::default().with_number(84).build(); - let latest_parentchain_header = ParentchainHeaderBuilder::default().with_number(85).build(); - let parentchain_block_import_trigger = - create_import_trigger_with_header(latest_parentchain_header.clone()); - let validateer_set_one = create_validateer_set_from_publics(vec![ - Keyring::Alice.public(), - Keyring::Bob.public(), - ]); - let validateer_set_two = create_validateer_set_from_publics(vec![ - Keyring::Alice.public(), - Keyring::Bob.public(), - Keyring::Charlie.public(), - ]); - let onchain_mock = OnchainMock::default() - .add_validateer_set(&already_imported_parentchain_header, Some(validateer_set_one)) - .add_validateer_set(&latest_parentchain_header, Some(validateer_set_two)); - - let mut aura = get_aura(onchain_mock, parentchain_block_import_trigger.clone()); - - let slot_info = now_slot(3.into(), &already_imported_parentchain_header); - - let result = - SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false).unwrap(); - - assert_eq!( - result.block.block.block_data().layer_one_head, - latest_parentchain_header.hash() - ); - assert!(parentchain_block_import_trigger.has_import_been_called()); - } - - #[test] - fn on_slot_does_not_claim_slot_if_latest_parentchain_header_in_queue_contains_correspondent_validateer_set( - ) { - let _ = env_logger::builder().is_test(true).try_init(); - let already_imported_parentchain_header = - ParentchainHeaderBuilder::default().with_number(84).build(); - let latest_parentchain_header = ParentchainHeaderBuilder::default().with_number(85).build(); - let parentchain_block_import_trigger = - create_import_trigger_with_header(latest_parentchain_header.clone()); - let validateer_set_one = create_validateer_set_from_publics(vec![ - Keyring::Alice.public(), - Keyring::Bob.public(), - ]); - let validateer_set_two = create_validateer_set_from_publics(vec![ - Keyring::Alice.public(), - Keyring::Bob.public(), - Keyring::Charlie.public(), - ]); - let onchain_mock = OnchainMock::default() - .add_validateer_set(&already_imported_parentchain_header, Some(validateer_set_one)) - .add_validateer_set(&latest_parentchain_header, Some(validateer_set_two)); - - let mut aura = get_aura(onchain_mock, parentchain_block_import_trigger.clone()); - - // If the validateer set one (instead of the latest one) is looked up, the slot will be claimed. But it should not, as the latest one should be used. - let slot_info = now_slot(2.into(), &already_imported_parentchain_header); - let result = SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false); - - assert!(result.is_none()); - assert!(!parentchain_block_import_trigger.has_import_been_called()); - } - - #[test] - fn proposing_remaining_duration_works() { - let slot_info = now_slot_with_default_header(0.into()); - - // hard to compare actual numbers but we can at least ensure that the general concept works - assert!( - proposing_remaining_duration(&slot_info, duration_now()) - < SLOT_DURATION.mul_f32(BLOCK_PROPOSAL_SLOT_PORTION + 0.01) - ); - } - - #[test] - fn proposing_remaining_duration_works_for_now_before_slot_timestamp() { - let slot_info = now_slot_with_default_header(0.into()); - - assert!( - proposing_remaining_duration(&slot_info, Duration::from_millis(0)) - < SLOT_DURATION.mul_f32(BLOCK_PROPOSAL_SLOT_PORTION + 0.01) - ); - } - - #[test] - fn proposing_remaining_duration_returns_default_if_now_after_slot() { - let slot_info = now_slot_with_default_header(0.into()); - - assert_eq!( - proposing_remaining_duration(&slot_info, duration_now() + SLOT_DURATION), - Default::default() - ); - } -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/proposer_factory.rs b/bitacross-worker/sidechain/consensus/aura/src/proposer_factory.rs deleted file mode 100644 index 61fa21557f..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/proposer_factory.rs +++ /dev/null @@ -1,131 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::slot_proposer::{ExternalitiesFor, SlotProposer}; -use codec::Encode; -use finality_grandpa::BlockNumberOps; -use ita_stf::{Getter, TrustedCallSigned}; -use itp_ocall_api::EnclaveMetricsOCallApi; -use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; -use itp_stf_executor::traits::StateUpdateProposer; -use itp_top_pool_author::traits::AuthorApi; -use itp_types::H256; -use its_block_composer::ComposeBlock; -use its_consensus_common::{Environment, Error as ConsensusError}; -use its_primitives::traits::{ - Block as SidechainBlockTrait, Header as HeaderTrait, ShardIdentifierFor, - SignedBlock as SignedSidechainBlockTrait, -}; -use its_state::{SidechainState, SidechainSystemExt}; -use sp_runtime::{ - traits::{Block, NumberFor}, - MultiSignature, -}; -use std::{marker::PhantomData, sync::Arc}; - -///! `ProposerFactory` instance containing all the data to create the `SlotProposer` for the -/// next `Slot`. -pub struct ProposerFactory< - ParentchainBlock: Block, - TopPoolAuthor, - StfExecutor, - BlockComposer, - MetricsApi, -> { - top_pool_author: Arc, - stf_executor: Arc, - block_composer: Arc, - metrics_api: Arc, - _phantom: PhantomData, -} - -impl - ProposerFactory -{ - pub fn new( - top_pool_executor: Arc, - stf_executor: Arc, - block_composer: Arc, - metrics_api: Arc, - ) -> Self { - Self { - top_pool_author: top_pool_executor, - stf_executor, - block_composer, - metrics_api, - _phantom: Default::default(), - } - } -} - -impl< - ParentchainBlock: Block, - SignedSidechainBlock, - TopPoolAuthor, - StfExecutor, - BlockComposer, - MetricsApi, - > Environment - for ProposerFactory -where - NumberFor: BlockNumberOps, - SignedSidechainBlock: SignedSidechainBlockTrait - + 'static, - SignedSidechainBlock::Block: SidechainBlockTrait, - <::Block as SidechainBlockTrait>::HeaderType: - HeaderTrait, - TopPoolAuthor: - AuthorApi + Send + Sync + 'static, - StfExecutor: StateUpdateProposer + Send + Sync + 'static, - ExternalitiesFor: - SgxExternalitiesTrait + SidechainState + SidechainSystemExt + StateHash, - as SgxExternalitiesTrait>::SgxExternalitiesType: Encode, - BlockComposer: ComposeBlock< - ExternalitiesFor, - ParentchainBlock, - SignedSidechainBlock = SignedSidechainBlock, - > + Send - + Sync - + 'static, - MetricsApi: EnclaveMetricsOCallApi, -{ - type Proposer = SlotProposer< - ParentchainBlock, - SignedSidechainBlock, - TopPoolAuthor, - StfExecutor, - BlockComposer, - MetricsApi, - >; - type Error = ConsensusError; - - fn init( - &mut self, - parent_header: ParentchainBlock::Header, - shard: ShardIdentifierFor, - ) -> Result { - Ok(SlotProposer { - top_pool_author: self.top_pool_author.clone(), - stf_executor: self.stf_executor.clone(), - block_composer: self.block_composer.clone(), - parentchain_header: parent_header, - shard, - metrics_api: self.metrics_api.clone(), - _phantom: PhantomData, - }) - } -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/slot_proposer.rs b/bitacross-worker/sidechain/consensus/aura/src/slot_proposer.rs deleted file mode 100644 index 2baea76519..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/slot_proposer.rs +++ /dev/null @@ -1,206 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use codec::Encode; -use finality_grandpa::BlockNumberOps; -use ita_stf::{Getter, TrustedCallSigned}; -use itp_enclave_metrics::EnclaveMetric; -use itp_ocall_api::EnclaveMetricsOCallApi; -use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; -use itp_stf_executor::traits::StateUpdateProposer; -use itp_time_utils::now_as_millis; -use itp_top_pool_author::traits::AuthorApi; -use itp_types::H256; -use its_block_composer::ComposeBlock; -use its_consensus_common::{Error as ConsensusError, Proposal, Proposer}; -use its_primitives::traits::{ - Block as SidechainBlockTrait, Header as HeaderTrait, ShardIdentifierFor, - SignedBlock as SignedSidechainBlockTrait, -}; -use its_state::{SidechainState, SidechainSystemExt}; -use log::*; -use sp_runtime::{ - traits::{Block, NumberFor}, - MultiSignature, -}; -use std::{marker::PhantomData, string::ToString, sync::Arc, time::Duration, vec::Vec}; - -pub type ExternalitiesFor = >::Externalities; -///! `SlotProposer` instance that has access to everything needed to propose a sidechain block. -pub struct SlotProposer< - ParentchainBlock: Block, - SignedSidechainBlock: SignedSidechainBlockTrait, - TopPoolAuthor, - StfExecutor, - BlockComposer, - MetricsApi, -> { - pub(crate) top_pool_author: Arc, - pub(crate) stf_executor: Arc, - pub(crate) block_composer: Arc, - pub(crate) parentchain_header: ParentchainBlock::Header, - pub(crate) shard: ShardIdentifierFor, - pub(crate) metrics_api: Arc, - pub(crate) _phantom: PhantomData, -} - -impl< - ParentchainBlock, - SignedSidechainBlock, - TopPoolAuthor, - BlockComposer, - StfExecutor, - MetricsApi, - > Proposer - for SlotProposer< - ParentchainBlock, - SignedSidechainBlock, - TopPoolAuthor, - StfExecutor, - BlockComposer, - MetricsApi, - > where - ParentchainBlock: Block, - NumberFor: BlockNumberOps, - SignedSidechainBlock: SignedSidechainBlockTrait - + 'static, - SignedSidechainBlock::Block: SidechainBlockTrait, - <::Block as SidechainBlockTrait>::HeaderType: - HeaderTrait, - StfExecutor: StateUpdateProposer, - ExternalitiesFor: - SgxExternalitiesTrait + SidechainState + SidechainSystemExt + StateHash, - as SgxExternalitiesTrait>::SgxExternalitiesType: Encode, - TopPoolAuthor: - AuthorApi + Send + Sync + 'static, - BlockComposer: ComposeBlock< - ExternalitiesFor, - ParentchainBlock, - SignedSidechainBlock = SignedSidechainBlock, - > + Send - + Sync - + 'static, - MetricsApi: EnclaveMetricsOCallApi, -{ - /// Proposes a new sidechain block. - /// - /// This includes the following steps: - /// 1) Retrieve all trusted calls from the top pool. - /// 2) Calculate a new state that will be proposed in the sidechain block. - /// 3) Compose the sidechain block and the parentchain confirmation. - fn propose( - &self, - max_duration: Duration, - ) -> Result, ConsensusError> { - let mut started = std::time::Instant::now(); - let latest_parentchain_header = &self.parentchain_header; - - // 1) Retrieve trusted calls from top pool. - let trusted_calls = self.top_pool_author.get_pending_trusted_calls(self.shard); - - if !trusted_calls.is_empty() { - debug!("Got following trusted calls from pool: {:?}", trusted_calls); - } - - if let Err(e) = self - .metrics_api - .update_metric(EnclaveMetric::SidechainSlotPrepareTime(started.elapsed())) - { - warn!("Failed to update metric for sidechain slot prepare time: {:?}", e); - }; - - started = std::time::Instant::now(); - // 2) Execute trusted calls. - let batch_execution_result = self - .stf_executor - .propose_state_update( - &trusted_calls, - latest_parentchain_header, - &self.shard, - max_duration, - |mut sidechain_db| { - sidechain_db.reset_events(); - sidechain_db - .set_block_number(&sidechain_db.get_block_number().map_or(1, |n| n + 1)); - sidechain_db.set_timestamp(&now_as_millis()); - sidechain_db.set_parentchain_block_number(latest_parentchain_header); - sidechain_db - }, - ) - .map_err(|e| ConsensusError::Other(e.to_string().into()))?; - - let parentchain_extrinsics = batch_execution_result.get_extrinsic_callbacks(); - - let executed_operation_hashes: Vec<_> = - batch_execution_result.get_executed_operation_hashes().to_vec(); - let number_executed_transactions = executed_operation_hashes.len(); - - // store the rpc response value to top pool - let rpc_responses_values = batch_execution_result.get_connection_updates(); - self.top_pool_author.update_connection_state(rpc_responses_values); - - // Remove all not successfully executed operations from the top pool. - let failed_operations = batch_execution_result.get_failed_operations(); - self.top_pool_author.remove_calls_from_pool( - self.shard, - failed_operations - .into_iter() - .map(|e| { - let is_success = e.is_success(); - (e.trusted_operation_or_hash, is_success) - }) - .collect(), - ); - - if let Err(e) = self - .metrics_api - .update_metric(EnclaveMetric::SidechainSlotStfExecutionTime(started.elapsed())) - { - warn!("Failed to update metric for sidechain slot stf execution time: {:?}", e); - }; - - started = std::time::Instant::now(); - - // 3) Compose sidechain block. - let sidechain_block = self - .block_composer - .compose_block( - latest_parentchain_header, - executed_operation_hashes, - self.shard, - batch_execution_result.state_hash_before_execution, - &batch_execution_result.state_after_execution, - ) - .map_err(|e| ConsensusError::Other(e.to_string().into()))?; - - if let Err(e) = self - .metrics_api - .update_metric(EnclaveMetric::SidechainSlotBlockCompositionTime(started.elapsed())) - { - warn!("Failed to update metric for sidechain slot block composition time: {:?}", e); - }; - - info!( - "Queue/Timeslot/Transactions: {:?};{}ms;{}", - trusted_calls.len(), - max_duration.as_millis(), - number_executed_transactions - ); - - Ok(Proposal { block: sidechain_block, parentchain_effects: parentchain_extrinsics }) - } -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs b/bitacross-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs deleted file mode 100644 index 447aa18c62..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs +++ /dev/null @@ -1,318 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - block_importer::BlockImporter, - test::{fixtures::validateer, mocks::peer_updater_mock::PeerUpdaterMock}, - ShardIdentifierFor, -}; -use codec::Encode; -use core::assert_matches::assert_matches; -use itc_parentchain_block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; -use itc_parentchain_test::{ParentchainBlockBuilder, ParentchainHeaderBuilder}; -use itp_sgx_crypto::{aes::Aes, mocks::KeyRepositoryMock, StateCrypto}; -use itp_sgx_externalities::SgxExternalitiesDiffType; -use itp_stf_state_handler::handle_state::HandleState; -use itp_test::mock::{ - handle_state_mock::HandleStateMock, - onchain_mock::OnchainMock, - stf_mock::{GetterMock, TrustedCallSignedMock}, -}; -use itp_time_utils::{duration_now, now_as_millis}; -use itp_top_pool_author::mocks::AuthorApiMock; -use itp_types::{Block as ParentchainBlock, Header as ParentchainHeader, H256}; -use its_consensus_common::{BlockImport, Error as ConsensusError}; -use its_primitives::{ - traits::{SignBlock, SignedBlock}, - types::SignedBlock as SignedSidechainBlock, -}; -use its_state::StateUpdate; -use its_test::{ - sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}, - sidechain_block_data_builder::SidechainBlockDataBuilder, - sidechain_header_builder::SidechainHeaderBuilder, -}; -use sp_core::{blake2_256, ed25519::Pair}; -use sp_keyring::ed25519::Keyring; -use sp_runtime::generic::SignedBlock as SignedParentchainBlock; -use std::sync::Arc; - -type TestTopPoolAuthor = AuthorApiMock; -type TestParentchainBlockImportTrigger = - TriggerParentchainBlockImportMock>; -type TestStateKeyRepo = KeyRepositoryMock; -type TestBlockImporter = BlockImporter< - Pair, - ParentchainBlock, - SignedSidechainBlock, - OnchainMock, - HandleStateMock, - TestStateKeyRepo, - TestTopPoolAuthor, - TestParentchainBlockImportTrigger, - PeerUpdaterMock, - TrustedCallSignedMock, - GetterMock, ->; - -fn state_key() -> Aes { - Aes::new([3u8; 16], [0u8; 16]) -} - -fn shard() -> ShardIdentifierFor { - blake2_256(&[1, 2, 3, 4, 5, 6]).into() -} - -fn default_authority() -> Pair { - Keyring::Alice.pair() -} - -fn test_fixtures( - parentchain_header: &ParentchainHeader, - parentchain_block_import_trigger: Arc, -) -> (TestBlockImporter, Arc, Arc) { - let state_handler = Arc::new(HandleStateMock::from_shard(shard()).unwrap()); - let top_pool_author = Arc::new(TestTopPoolAuthor::default()); - let ocall_api = Arc::new(OnchainMock::default().add_validateer_set( - parentchain_header, - Some(vec![validateer(Keyring::Alice.public().into())]), - )); - let state_key_repository = Arc::new(TestStateKeyRepo::new(state_key())); - - let peer_updater_mock = Arc::new(PeerUpdaterMock {}); - - let block_importer = TestBlockImporter::new( - state_handler.clone(), - state_key_repository, - top_pool_author.clone(), - parentchain_block_import_trigger, - ocall_api, - peer_updater_mock, - ); - - (block_importer, state_handler, top_pool_author) -} - -fn test_fixtures_with_default_import_trigger( - parentchain_header: &ParentchainHeader, -) -> (TestBlockImporter, Arc, Arc) { - test_fixtures(parentchain_header, Arc::new(TestParentchainBlockImportTrigger::default())) -} - -fn empty_encrypted_state_update(state_handler: &HandleStateMock) -> Vec { - let (_, apriori_state_hash) = state_handler.load_cloned(&shard()).unwrap(); - let empty_state_diff = SgxExternalitiesDiffType::default(); - let mut state_update = - StateUpdate::new(apriori_state_hash, apriori_state_hash, empty_state_diff).encode(); - state_key().encrypt(&mut state_update).unwrap(); - state_update -} - -fn signed_block( - parentchain_header: &ParentchainHeader, - state_handler: &HandleStateMock, - signer: Pair, -) -> SignedSidechainBlock { - let state_update = empty_encrypted_state_update(state_handler); - - let header = SidechainHeaderBuilder::default() - .with_parent_hash(H256::default()) - .with_shard(shard()) - .build(); - - let block_data = SidechainBlockDataBuilder::default() - .with_timestamp(now_as_millis()) - .with_layer_one_head(parentchain_header.hash()) - .with_signer(signer.clone()) - .with_payload(state_update) - .build(); - - SidechainBlockBuilder::default() - .with_header(header) - .with_block_data(block_data) - .with_signer(signer) - .build_signed() -} - -fn default_authority_signed_block( - parentchain_header: &ParentchainHeader, - state_handler: &HandleStateMock, -) -> SignedSidechainBlock { - signed_block(parentchain_header, state_handler, default_authority()) -} - -#[test] -fn simple_block_import_works() { - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let (block_importer, state_handler, _) = - test_fixtures_with_default_import_trigger(&parentchain_header); - let signed_sidechain_block = - default_authority_signed_block(&parentchain_header, state_handler.as_ref()); - - block_importer - .import_block(signed_sidechain_block, &parentchain_header) - .unwrap(); -} - -#[test] -fn block_import_with_invalid_signature_fails() { - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let (block_importer, state_handler, _) = - test_fixtures_with_default_import_trigger(&parentchain_header); - - let state_update = empty_encrypted_state_update(state_handler.as_ref()); - - let header = SidechainHeaderBuilder::default() - .with_parent_hash(H256::default()) - .with_shard(shard()) - .build(); - - let block_data = SidechainBlockDataBuilder::default() - .with_timestamp(duration_now().as_millis() as u64) - .with_layer_one_head(parentchain_header.hash()) - .with_signer(Keyring::Charlie.pair()) - .with_payload(state_update) - .build(); - - let block = SidechainBlockBuilder::default() - .with_signer(Keyring::Charlie.pair()) - .with_header(header) - .with_block_data(block_data) - .build(); - - // Bob signs the block, but Charlie is set as the author -> invalid signature. - let invalid_signature_block: SignedSidechainBlock = block.sign_block(&Keyring::Bob.pair()); - - assert!(!invalid_signature_block.verify_signature()); - assert!(block_importer - .import_block(invalid_signature_block, &parentchain_header) - .is_err()); -} - -#[test] -fn block_import_with_invalid_parentchain_block_fails() { - let parentchain_header_invalid = ParentchainHeaderBuilder::default().with_number(2).build(); - let parentchain_header = ParentchainHeaderBuilder::default().with_number(10).build(); - let (block_importer, state_handler, _) = - test_fixtures_with_default_import_trigger(&parentchain_header); - - let signed_sidechain_block = - default_authority_signed_block(&parentchain_header_invalid, state_handler.as_ref()); - - assert!(block_importer - .import_block(signed_sidechain_block, &parentchain_header) - .is_err()); -} - -#[test] -fn cleanup_removes_tops_from_pool() { - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let (block_importer, state_handler, top_pool_author) = - test_fixtures_with_default_import_trigger(&parentchain_header); - let signed_sidechain_block = - default_authority_signed_block(&parentchain_header, state_handler.as_ref()); - let bob_signed_sidechain_block = - signed_block(&parentchain_header, state_handler.as_ref(), Keyring::Bob.pair()); - - block_importer.cleanup(&signed_sidechain_block).unwrap(); - block_importer.cleanup(&bob_signed_sidechain_block).unwrap(); - - assert_eq!(2, *top_pool_author.remove_attempts.read().unwrap()); -} - -#[test] -fn sidechain_block_import_triggers_parentchain_block_import() { - let previous_parentchain_header = ParentchainHeaderBuilder::default().with_number(4).build(); - let latest_parentchain_header = ParentchainHeaderBuilder::default() - .with_number(5) - .with_parent_hash(previous_parentchain_header.hash()) - .build(); - - let latest_parentchain_block = ParentchainBlockBuilder::default() - .with_header(latest_parentchain_header.clone()) - .build_signed(); - - let parentchain_block_import_trigger = Arc::new( - TestParentchainBlockImportTrigger::default() - .with_latest_imported(Some(latest_parentchain_block)), - ); - let (block_importer, state_handler, _) = - test_fixtures(&latest_parentchain_header, parentchain_block_import_trigger.clone()); - - let signed_sidechain_block = - default_authority_signed_block(&latest_parentchain_header, state_handler.as_ref()); - - block_importer - .import_block(signed_sidechain_block, &previous_parentchain_header) - .unwrap(); - - assert!(parentchain_block_import_trigger.has_import_been_called()); -} - -#[test] -fn peek_parentchain_block_finds_block_in_queue() { - let previous_parentchain_header = ParentchainHeaderBuilder::default().with_number(4).build(); - let latest_parentchain_header = ParentchainHeaderBuilder::default() - .with_number(5) - .with_parent_hash(previous_parentchain_header.hash()) - .build(); - - let latest_parentchain_block = ParentchainBlockBuilder::default() - .with_header(latest_parentchain_header.clone()) - .build_signed(); - - let parentchain_block_import_trigger = Arc::new( - TestParentchainBlockImportTrigger::default() - .with_latest_imported(Some(latest_parentchain_block)), - ); - - let (block_importer, state_handler, _) = - test_fixtures(&latest_parentchain_header, parentchain_block_import_trigger); - - let signed_sidechain_block = - default_authority_signed_block(&latest_parentchain_header, state_handler.as_ref()); - - let peeked_header = block_importer - .peek_parentchain_header(&signed_sidechain_block.block, &previous_parentchain_header) - .unwrap(); - - assert_eq!(peeked_header, latest_parentchain_header); -} - -#[test] -fn peek_parentchain_block_returns_error_if_no_corresponding_block_can_be_found() { - let previous_parentchain_header = ParentchainHeaderBuilder::default().with_number(1).build(); - let latest_parentchain_header = ParentchainHeaderBuilder::default() - .with_number(2) - .with_parent_hash(previous_parentchain_header.hash()) - .build(); - - let parentchain_block_import_trigger = Arc::new( - TestParentchainBlockImportTrigger::default(), // Parentchain block import queue is empty, so nothing will be found when peeked. - ); - - let (block_importer, state_handler, _) = - test_fixtures(&latest_parentchain_header, parentchain_block_import_trigger); - - let signed_sidechain_block = - default_authority_signed_block(&latest_parentchain_header, state_handler.as_ref()); - - let peek_result = block_importer - .peek_parentchain_header(&signed_sidechain_block.block, &previous_parentchain_header); - - assert_matches!(peek_result, Err(ConsensusError::Other(_))); -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs b/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs deleted file mode 100644 index 54d47324fa..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub mod types; - -use itp_types::{AccountId, Enclave}; -use std::time::Duration; - -pub const SLOT_DURATION: Duration = Duration::from_millis(300); - -pub fn validateer(account: AccountId) -> Enclave { - Enclave::new(account, Default::default(), Default::default(), Default::default()) -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/types.rs b/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/types.rs deleted file mode 100644 index b5eae68582..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/types.rs +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{test::mocks::environment_mock::EnvironmentMock, Aura}; -use itc_parentchain_block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; -use itp_test::mock::{handle_state_mock::HandleStateMock, onchain_mock::OnchainMock}; -use itp_types::Block as ParentchainBlock; -use its_primitives::{ - traits::{ - Block as SidechainBlockTrait, Header as SidechainHeaderTrait, - SignedBlock as SignedBlockTrait, - }, - types::block::SignedBlock as SignedSidechainBlock, -}; -use lc_scheduled_enclave::ScheduledEnclaveMock; -use sp_runtime::{app_crypto::ed25519, generic::SignedBlock}; - -type AuthorityPair = ed25519::Pair; - -pub type ShardIdentifierFor = - <<::Block as SidechainBlockTrait>::HeaderType as SidechainHeaderTrait>::ShardIdentifier; - -pub type TestAura = Aura< - AuthorityPair, - ParentchainBlock, - SignedSidechainBlock, - E, - OnchainMock, - TriggerParentchainBlockImportMock>, - TriggerParentchainBlockImportMock>, - TriggerParentchainBlockImportMock>, - ScheduledEnclaveMock, - HandleStateMock, ->; diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/environment_mock.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/environment_mock.rs deleted file mode 100644 index 58f98d3687..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/environment_mock.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - test::{ - fixtures::types::ShardIdentifierFor, - mocks::proposer_mock::{DefaultProposerMock, OutdatedBlockProposerMock}, - }, - ConsensusError, -}; -use itp_types::{Block as ParentchainBlock, Header}; -use its_consensus_common::Environment; -use its_primitives::types::block::SignedBlock as SignedSidechainBlock; - -/// Mock proposer environment. -pub struct EnvironmentMock; - -impl Environment for EnvironmentMock { - type Proposer = DefaultProposerMock; - type Error = ConsensusError; - - fn init( - &mut self, - header: Header, - _: ShardIdentifierFor, - ) -> Result { - Ok(DefaultProposerMock { parentchain_header: header }) - } -} - -pub struct OutdatedBlockEnvironmentMock; - -impl Environment for OutdatedBlockEnvironmentMock { - type Proposer = OutdatedBlockProposerMock; - type Error = ConsensusError; - - fn init( - &mut self, - header: Header, - _: ShardIdentifierFor, - ) -> Result { - Ok(OutdatedBlockProposerMock { parentchain_header: header }) - } -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/mod.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/mod.rs deleted file mode 100644 index f5c7248d2f..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub mod environment_mock; -pub mod peer_updater_mock; -pub mod proposer_mock; diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/peer_updater_mock.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/peer_updater_mock.rs deleted file mode 100644 index b474e825c1..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/peer_updater_mock.rs +++ /dev/null @@ -1,7 +0,0 @@ -use itc_peer_top_broadcaster::PeerUpdater; - -pub struct PeerUpdaterMock {} - -impl PeerUpdater for PeerUpdaterMock { - fn update(&self, _peers: Vec) {} -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/proposer_mock.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/proposer_mock.rs deleted file mode 100644 index 00f78298c3..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/proposer_mock.rs +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::ConsensusError; -use itp_time_utils::now_as_millis; -use itp_types::{Block as ParentchainBlock, Header}; -use its_consensus_common::{Proposal, Proposer}; -use its_primitives::types::block::SignedBlock as SignedSidechainBlock; -use its_test::{ - sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}, - sidechain_block_data_builder::SidechainBlockDataBuilder, -}; -use std::time::Duration; - -pub struct DefaultProposerMock { - pub(crate) parentchain_header: Header, -} - -impl Proposer for DefaultProposerMock { - fn propose( - &self, - _max_duration: Duration, - ) -> Result, ConsensusError> { - Ok(Proposal { - block: { - let block_data = SidechainBlockDataBuilder::random() - .with_layer_one_head(self.parentchain_header.hash()) - .build(); - SidechainBlockBuilder::random().with_block_data(block_data).build_signed() - }, - - parentchain_effects: Default::default(), - }) - } -} - -pub struct OutdatedBlockProposerMock { - pub(crate) parentchain_header: Header, -} - -impl Proposer for OutdatedBlockProposerMock { - fn propose( - &self, - _max_duration: Duration, - ) -> Result, ConsensusError> { - let past = now_as_millis() - 1000; - Ok(Proposal { - block: { - let block_data = SidechainBlockDataBuilder::random() - .with_layer_one_head(self.parentchain_header.hash()) - .with_timestamp(past) - .build(); - SidechainBlockBuilder::random().with_block_data(block_data).build_signed() - }, - - parentchain_effects: Default::default(), - }) - } -} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mod.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mod.rs deleted file mode 100644 index 7c40ba019d..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/test/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -mod block_importer_tests; -pub mod fixtures; -pub mod mocks; diff --git a/bitacross-worker/sidechain/consensus/aura/src/verifier.rs b/bitacross-worker/sidechain/consensus/aura/src/verifier.rs deleted file mode 100644 index 0c1f64b138..0000000000 --- a/bitacross-worker/sidechain/consensus/aura/src/verifier.rs +++ /dev/null @@ -1,89 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{authorities, EnclaveOnChainOCallApi, ShardIdentifierFor}; -use core::marker::PhantomData; -use its_block_verification::verify_sidechain_block; -use its_consensus_common::{Error as ConsensusError, Verifier}; -use its_primitives::{ - traits::{Block as SidechainBlockTrait, SignedBlock as SignedSidechainBlockTrait}, - types::block::BlockHash, -}; -use its_validateer_fetch::ValidateerFetch; -use sp_runtime::{app_crypto::Pair, traits::Block as ParentchainBlockTrait}; -use std::{fmt::Debug, time::Duration}; - -#[derive(Default)] -pub struct AuraVerifier -where - SignedSidechainBlock: SignedSidechainBlockTrait + 'static, - SignedSidechainBlock::Block: SidechainBlockTrait, -{ - slot_duration: Duration, - last_sidechain_block: Option, - _phantom: PhantomData<(AuthorityPair, ParentchainBlock, Context)>, -} - -impl - AuraVerifier -where - SignedSidechainBlock: SignedSidechainBlockTrait + 'static, - SignedSidechainBlock::Block: SidechainBlockTrait, -{ - pub fn new( - slot_duration: Duration, - last_sidechain_block: Option, - ) -> Self { - Self { slot_duration, last_sidechain_block, _phantom: Default::default() } - } -} - -impl - Verifier - for AuraVerifier -where - AuthorityPair: Pair, - AuthorityPair::Public: Debug, - // todo: Relax hash trait bound, but this needs a change to some other parts in the code. - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait + 'static, - SignedSidechainBlock::Block: SidechainBlockTrait, - Context: ValidateerFetch + EnclaveOnChainOCallApi + Send + Sync, -{ - type BlockImportParams = SignedSidechainBlock; - - type Context = Context; - - fn verify( - &self, - signed_block: SignedSidechainBlock, - parentchain_header: &ParentchainBlock::Header, - _shard: ShardIdentifierFor, - ctx: &Self::Context, - ) -> Result { - let authorities = - authorities::<_, AuthorityPair, ParentchainBlock::Header>(ctx, parentchain_header)?; - - Ok(verify_sidechain_block::( - signed_block, - self.slot_duration, - &self.last_sidechain_block, - parentchain_header, - &authorities, - )?) - } -} diff --git a/bitacross-worker/sidechain/consensus/common/Cargo.toml b/bitacross-worker/sidechain/consensus/common/Cargo.toml deleted file mode 100644 index 6408dd9c08..0000000000 --- a/bitacross-worker/sidechain/consensus/common/Cargo.toml +++ /dev/null @@ -1,85 +0,0 @@ -[package] -name = "its-consensus-common" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } -log = { version = "0.4", default-features = false } -thiserror = { version = "1.0.26", optional = true } - -# local deps -itc-parentchain-light-client = { path = "../../../core/parentchain/light-client", default-features = false } -itp-enclave-metrics = { path = "../../../core-primitives/enclave-metrics", default-features = false } -itp-extrinsics-factory = { path = "../../../core-primitives/extrinsics-factory", default-features = false } -itp-import-queue = { path = "../../../core-primitives/import-queue", default-features = false } -itp-node-api-metadata = { path = "../../../core-primitives/node-api/metadata", default-features = false } -itp-node-api-metadata-provider = { path = "../../../core-primitives/node-api/metadata-provider", default-features = false } -itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } -itp-settings = { path = "../../../core-primitives/settings" } -itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } -itp-types = { path = "../../../core-primitives/types", default-features = false } -its-block-verification = { path = "../../block-verification", optional = true, default-features = false } -its-primitives = { path = "../../primitives", default-features = false } -its-state = { path = "../../state", default-features = false } - -# sgx deps -sgx_tstd = { optional = true, git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master" } -sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master" } -thiserror-sgx = { package = "thiserror", optional = true, git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3" } - -# substrate deps -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -[dev-dependencies] -# local -itc-parentchain-test = { path = "../../../core/parentchain/test" } -itp-sgx-externalities = { default-features = false, path = "../../../core-primitives/substrate-sgx/externalities" } -itp-test = { path = "../../../core-primitives/test" } -its-test = { path = "../../test" } -fork-tree = { path = "../../fork-tree", default-features = false } - -# substrate -sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -[features] -default = ["std"] -std = [ - "codec/std", - "log/std", - "thiserror", - # local - "itc-parentchain-light-client/std", - "itp-import-queue/std", - "itp-enclave-metrics/std", - "itp-extrinsics-factory/std", - "itp-node-api-metadata/std", - "itp-node-api-metadata-provider/std", - "itp-ocall-api/std", - "itp-sgx-crypto/std", - "itp-sgx-externalities/std", - "itp-types/std", - "its-primitives/std", - "its-block-verification/std", - "its-state/std", - "fork-tree/std", - # substrate - "sp-runtime/std", -] -sgx = [ - "sgx_tstd", - "thiserror-sgx", - # local - "itc-parentchain-light-client/sgx", - "itp-import-queue/sgx", - "itp-enclave-metrics/sgx", - "itp-extrinsics-factory/sgx", - "itp-node-api-metadata-provider/sgx", - "itp-sgx-crypto/sgx", - "itp-sgx-externalities/sgx", - "its-state/sgx", - "fork-tree/sgx", - # scs - "its-block-verification/sgx", -] diff --git a/bitacross-worker/sidechain/consensus/common/src/block_import.rs b/bitacross-worker/sidechain/consensus/common/src/block_import.rs deleted file mode 100644 index 826b1e456b..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/block_import.rs +++ /dev/null @@ -1,201 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Abstraction around block import - -use crate::{Error, Verifier}; -use codec::Decode; -use itp_enclave_metrics::EnclaveMetric; -use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; -use itp_sgx_crypto::StateCrypto; -use its_primitives::traits::{ - Block as SidechainBlockTrait, BlockData, Header as HeaderTrait, ShardIdentifierFor, - SignedBlock as SignedSidechainBlockTrait, -}; -use its_state::{LastBlockExt, SidechainState}; -use log::*; -use sp_runtime::traits::Block as ParentchainBlockTrait; -use std::{time::Instant, vec::Vec}; - -pub trait BlockImport -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, -{ - /// The verifier for of the respective consensus instance. - type Verifier: Verifier< - ParentchainBlock, - SignedSidechainBlock, - BlockImportParams = SignedSidechainBlock, - Context = Self::Context, - >; - - /// Context needed to derive verifier relevant data. - type SidechainState: SidechainState + LastBlockExt; - - /// Provides the cryptographic functions for our the state encryption. - type StateCrypto: StateCrypto; - - /// Context needed to derive verifier relevant data. - type Context: EnclaveSidechainOCallApi + EnclaveMetricsOCallApi; - - /// Get a verifier instance. - fn verifier( - &self, - maybe_last_sidechain_block: Option, - ) -> Self::Verifier; - - /// Apply a state update by providing a mutating function. - fn apply_state_update( - &self, - shard: &ShardIdentifierFor, - mutating_function: F, - ) -> Result<(), Error> - where - F: FnOnce(Self::SidechainState) -> Result; - - /// Verify a sidechain block that is to be imported. - fn verify_import( - &self, - shard: &ShardIdentifierFor, - verifying_function: F, - ) -> Result - where - F: FnOnce(&Self::SidechainState) -> Result; - - /// Key that is used for state encryption. - fn state_key(&self) -> Result; - - /// Getter for the context. - fn get_context(&self) -> &Self::Context; - - /// Import parentchain blocks up to and including the one we see in the sidechain block that - /// is scheduled for import. - /// - /// Returns the latest header. If no block was imported with the trigger, - /// we return `last_imported_parentchain_header`. - fn import_parentchain_block( - &self, - sidechain_block: &SignedSidechainBlock::Block, - last_imported_parentchain_header: &ParentchainBlock::Header, - ) -> Result; - - /// Peek the parentchain import queue for the block that is associated with a given sidechain. - /// Does not perform the import or mutate the queue. - /// - /// Warning: Be aware that peeking the parentchain block means that it is not verified (that happens upon import). - fn peek_parentchain_header( - &self, - sidechain_block: &SignedSidechainBlock::Block, - last_imported_parentchain_header: &ParentchainBlock::Header, - ) -> Result; - /// Cleanup task after import is done. - fn cleanup(&self, signed_sidechain_block: &SignedSidechainBlock) -> Result<(), Error>; - - /// Import a sidechain block and mutate state by `apply_state_update`. - fn import_block( - &self, - signed_sidechain_block: SignedSidechainBlock, - parentchain_header: &ParentchainBlock::Header, - ) -> Result { - let start_time = Instant::now(); - - let sidechain_block = signed_sidechain_block.block().clone(); - let shard = sidechain_block.header().shard_id(); - let block_number = signed_sidechain_block.block().header().block_number(); - - debug!( - "Attempting to import sidechain block (number: {}, hash: {:?}, parentchain hash: {:?})", - block_number, - signed_sidechain_block.block().hash(), - signed_sidechain_block.block().block_data().layer_one_head() - ); - - let peeked_parentchain_header = - self.peek_parentchain_header(&sidechain_block, parentchain_header) - .unwrap_or_else(|e| { - warn!("Could not peek parentchain block, returning latest parentchain block ({:?})", e); - parentchain_header.clone() - }); - - let block_import_params = self.verify_import(&shard, |state| { - let verifier = self.verifier(state.get_last_block()); - verifier.verify( - signed_sidechain_block.clone(), - &peeked_parentchain_header, - shard, - self.get_context(), - ) - })?; - - let latest_parentchain_header = - self.import_parentchain_block(&sidechain_block, parentchain_header)?; - - let state_key = self.state_key()?; - - let state_update_start_time = Instant::now(); - self.apply_state_update(&shard, |mut state| { - let encrypted_state_diff = - block_import_params.block().block_data().encrypted_state_diff(); - - info!( - "Applying state diff for block {} of size {} bytes", - block_number, - encrypted_state_diff.len() - ); - - let update = state_update_from_encrypted(encrypted_state_diff, state_key)?; - - state.apply_state_update(&update).map_err(|e| Error::Other(e.into()))?; - - state.set_last_block(block_import_params.block()); - - Ok(state) - })?; - info!( - "Applying state update from block {} took {} ms", - block_number, - state_update_start_time.elapsed().as_millis() - ); - - self.cleanup(&signed_sidechain_block)?; - - // Store block in storage. - self.get_context().store_sidechain_blocks(vec![signed_sidechain_block])?; - - let import_duration = start_time.elapsed(); - info!("Importing block {} took {} ms", block_number, import_duration.as_millis()); - if let Err(e) = self - .get_context() - .update_metric(EnclaveMetric::SidechainBlockImportTime(import_duration)) - { - warn!("Failed to update metric for sidechain block import: {:?}", e); - }; - - Ok(latest_parentchain_header) - } -} - -fn state_update_from_encrypted( - encrypted: &[u8], - key: Key, -) -> Result { - let mut payload: Vec = encrypted.to_vec(); - key.decrypt(&mut payload).map_err(|e| Error::Other(format!("{:?}", e).into()))?; - - Ok(Decode::decode(&mut payload.as_slice())?) -} diff --git a/bitacross-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs b/bitacross-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs deleted file mode 100644 index be93feb51c..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs +++ /dev/null @@ -1,130 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::error::{Error, Result}; -use itc_parentchain_light_client::{ - concurrent_access::ValidatorAccess, BlockNumberOps, ExtrinsicSender, NumberFor, -}; -use itp_extrinsics_factory::CreateExtrinsics; -use itp_node_api_metadata::{pallet_sidechain::SidechainCallIndexes, NodeMetadataTrait}; -use itp_node_api_metadata_provider::AccessNodeMetadata; -use itp_settings::worker::BLOCK_NUMBER_FINALIZATION_DIFF; -use itp_types::{OpaqueCall, ShardIdentifier}; -use its_primitives::traits::Header as HeaderTrait; -use log::*; -use sp_runtime::traits::Block as ParentchainBlockTrait; -use std::{marker::PhantomData, sync::Arc}; - -/// Trait to confirm a sidechain block import. -pub trait ConfirmBlockImport { - fn confirm_import(&self, header: &SidechainHeader, shard: &ShardIdentifier) -> Result<()>; -} - -/// Creates and sends a sidechain block import confirmation extrsinic to the parentchain. -pub struct BlockImportConfirmationHandler< - ParentchainBlock, - SidechainHeader, - NodeMetadataRepository, - ExtrinsicsFactory, - ValidatorAccessor, -> { - metadata_repository: Arc, - extrinsics_factory: Arc, - validator_accessor: Arc, - _phantom: PhantomData<(ParentchainBlock, SidechainHeader)>, -} - -impl< - ParentchainBlock, - SidechainHeader, - NodeMetadataRepository, - ExtrinsicsFactory, - ValidatorAccessor, - > - BlockImportConfirmationHandler< - ParentchainBlock, - SidechainHeader, - NodeMetadataRepository, - ExtrinsicsFactory, - ValidatorAccessor, - > -{ - pub fn new( - metadata_repository: Arc, - extrinsics_factory: Arc, - validator_accessor: Arc, - ) -> Self { - Self { - metadata_repository, - extrinsics_factory, - validator_accessor, - _phantom: Default::default(), - } - } -} - -impl< - ParentchainBlock, - SidechainHeader, - NodeMetadataRepository, - ExtrinsicsFactory, - ValidatorAccessor, - > ConfirmBlockImport - for BlockImportConfirmationHandler< - ParentchainBlock, - SidechainHeader, - NodeMetadataRepository, - ExtrinsicsFactory, - ValidatorAccessor, - > where - ParentchainBlock: ParentchainBlockTrait, - NumberFor: BlockNumberOps, - SidechainHeader: HeaderTrait, - NodeMetadataRepository: AccessNodeMetadata, - NodeMetadataRepository::MetadataType: NodeMetadataTrait, - ExtrinsicsFactory: CreateExtrinsics, - ValidatorAccessor: ValidatorAccess + Send + Sync + 'static, -{ - fn confirm_import(&self, header: &SidechainHeader, shard: &ShardIdentifier) -> Result<()> { - let call = self - .metadata_repository - .get_from_metadata(|m| m.confirm_imported_sidechain_block_indexes()) - .map_err(|e| Error::Other(e.into()))? - .map_err(|e| Error::Other(format!("{:?}", e).into()))?; - - if header.block_number() == header.next_finalization_block_number() { - let opaque_call = OpaqueCall::from_tuple(&( - call, - shard, - header.block_number(), - header.next_finalization_block_number() + BLOCK_NUMBER_FINALIZATION_DIFF, - header.hash(), - )); - - let xts = self - .extrinsics_factory - .create_extrinsics(&[opaque_call], None) - .map_err(|e| Error::Other(e.into()))?; - - debug!("Sending sidechain block import confirmation extrinsic.."); - self.validator_accessor - .execute_mut_on_validator(|v| v.send_extrinsics(xts)) - .map_err(|e| Error::Other(e.into()))?; - } - Ok(()) - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/block_import_queue_worker.rs b/bitacross-worker/sidechain/consensus/common/src/block_import_queue_worker.rs deleted file mode 100644 index fc7d9a23ef..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/block_import_queue_worker.rs +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{Error, Result, SyncBlockFromPeer}; -use core::marker::PhantomData; -use itp_import_queue::PopFromQueue; -use its_primitives::traits::{Block as BlockTrait, SignedBlock as SignedSidechainBlockTrait}; -use log::debug; -use sp_runtime::traits::Block as ParentchainBlockTrait; -use std::{sync::Arc, time::Instant}; - -/// Trait to trigger working the sidechain block import queue. -pub trait ProcessBlockImportQueue { - /// Pop sidechain blocks from the import queue and import them until queue is empty. - fn process_queue( - &self, - current_parentchain_header: &ParentchainBlockHeader, - ) -> Result; -} - -pub struct BlockImportQueueWorker< - ParentchainBlock, - SignedSidechainBlock, - BlockImportQueue, - PeerBlockSyncer, -> { - block_import_queue: Arc, - peer_block_syncer: Arc, - _phantom: PhantomData<(ParentchainBlock, SignedSidechainBlock)>, -} - -impl - BlockImportQueueWorker -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, - SignedSidechainBlock::Block: BlockTrait, - BlockImportQueue: PopFromQueue, - PeerBlockSyncer: SyncBlockFromPeer, -{ - pub fn new( - block_import_queue: Arc, - peer_block_syncer: Arc, - ) -> Self { - BlockImportQueueWorker { - block_import_queue, - peer_block_syncer, - _phantom: Default::default(), - } - } - - fn record_timings(start_time: Instant, number_of_imported_blocks: usize) { - let elapsed_time_millis = start_time.elapsed().as_millis(); - let time_millis_per_block = - (elapsed_time_millis as f64 / number_of_imported_blocks as f64).ceil(); - debug!( - "Imported {} blocks in {} ms (average of {} ms per block)", - number_of_imported_blocks, elapsed_time_millis, time_millis_per_block - ); - } -} - -impl - ProcessBlockImportQueue - for BlockImportQueueWorker< - ParentchainBlock, - SignedSidechainBlock, - BlockImportQueue, - PeerBlockSyncer, - > where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, - SignedSidechainBlock::Block: BlockTrait, - BlockImportQueue: PopFromQueue, - PeerBlockSyncer: SyncBlockFromPeer, -{ - fn process_queue( - &self, - current_parentchain_header: &ParentchainBlock::Header, - ) -> Result { - let mut latest_imported_parentchain_header = current_parentchain_header.clone(); - let mut number_of_imported_blocks = 0usize; - let start_time = Instant::now(); - - loop { - match self.block_import_queue.pop_front() { - Ok(maybe_block) => match maybe_block { - Some(block) => { - latest_imported_parentchain_header = self - .peer_block_syncer - .sync_block(block, &latest_imported_parentchain_header)?; - number_of_imported_blocks += 1; - }, - None => { - Self::record_timings(start_time, number_of_imported_blocks); - return Ok(latest_imported_parentchain_header) - }, - }, - Err(e) => { - Self::record_timings(start_time, number_of_imported_blocks); - return Err(Error::FailedToPopBlockImportQueue(e)) - }, - } - } - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/block_production_suspension.rs b/bitacross-worker/sidechain/consensus/common/src/block_production_suspension.rs deleted file mode 100644 index ae664925da..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/block_production_suspension.rs +++ /dev/null @@ -1,112 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Mechanisms to (temporarily) suspend the production of sidechain blocks. - -#[cfg(feature = "sgx")] -use std::sync::SgxRwLock as RwLock; - -#[cfg(feature = "std")] -use std::sync::RwLock; - -use crate::error::{Error, Result}; -use log::*; - -/// Trait to suspend the production of sidechain blocks. -pub trait SuspendBlockProduction { - /// Suspend any sidechain block production. - fn suspend_for_sync(&self) -> Result<()>; - - /// Resume block sidechain block production. - fn resume(&self) -> Result<()>; -} - -/// Trait to query if sidechain block production is suspended. -pub trait IsBlockProductionSuspended { - fn is_suspended(&self) -> Result; - - fn is_sync_ongoing(&self) -> Result; -} - -/// Implementation for suspending and resuming sidechain block production. -#[derive(Default)] -pub struct BlockProductionSuspender { - is_suspended: RwLock, - sync_is_ongoing: RwLock, -} - -impl BlockProductionSuspender { - pub fn new(is_suspended: bool) -> Self { - BlockProductionSuspender { - is_suspended: RwLock::new(is_suspended), - sync_is_ongoing: RwLock::new(false), - } - } -} - -impl SuspendBlockProduction for BlockProductionSuspender { - fn suspend_for_sync(&self) -> Result<()> { - let mut suspended_lock = self.is_suspended.write().map_err(|_| Error::LockPoisoning)?; - *suspended_lock = true; - - let mut sync_is_ongoing_lock = - self.sync_is_ongoing.write().map_err(|_| Error::LockPoisoning)?; - *sync_is_ongoing_lock = true; - - info!("Suspend sidechain block production"); - Ok(()) - } - - fn resume(&self) -> Result<()> { - let mut suspended_lock = self.is_suspended.write().map_err(|_| Error::LockPoisoning)?; - *suspended_lock = false; - info!("Resume sidechain block production"); - Ok(()) - } -} - -impl IsBlockProductionSuspended for BlockProductionSuspender { - fn is_suspended(&self) -> Result { - Ok(*self.is_suspended.read().map_err(|_| Error::LockPoisoning)?) - } - - fn is_sync_ongoing(&self) -> Result { - Ok(*self.sync_is_ongoing.read().map_err(|_| Error::LockPoisoning)?) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn initial_production_is_not_suspended() { - let block_production_suspender = BlockProductionSuspender::default(); - assert!(!block_production_suspender.is_suspended().unwrap()); - } - - #[test] - fn suspending_production_works() { - let block_production_suspender = BlockProductionSuspender::default(); - - block_production_suspender.suspend_for_sync().unwrap(); - assert!(block_production_suspender.is_suspended().unwrap()); - - block_production_suspender.resume().unwrap(); - assert!(!block_production_suspender.is_suspended().unwrap()); - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/error.rs b/bitacross-worker/sidechain/consensus/common/src/error.rs deleted file mode 100644 index f6ba8b6fd0..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/error.rs +++ /dev/null @@ -1,99 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Error types in sidechain consensus - -use itp_types::BlockHash as ParentchainBlockHash; -use its_block_verification::error::Error as VerificationError; -use its_primitives::types::{block::BlockHash as SidechainBlockHash, BlockNumber}; -use sgx_types::sgx_status_t; -use std::{ - boxed::Box, - error, - string::{String, ToString}, - vec::Vec, -}; - -pub type Result = std::result::Result; - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -pub use thiserror_sgx as thiserror; - -#[derive(Debug, thiserror::Error)] -#[non_exhaustive] -pub enum Error { - #[error("SGX error, status: {0}")] - Sgx(sgx_status_t), - #[error("Unable to create block proposal.")] - CannotPropose, - #[error("Encountered poisoned lock")] - LockPoisoning, - #[error("Message sender {0} is not a valid authority")] - InvalidAuthority(String), - #[error("Could not get authorities: {0:?}.")] - CouldNotGetAuthorities(String), - #[error("Chain lookup failed: {0}")] - ChainLookup(String), - #[error("Failed to sign using key: {0:?}. Reason: {1}")] - CannotSign(Vec, String), - #[error("Bad parentchain block (Hash={0}). Reason: {1}")] - BadParentchainBlock(ParentchainBlockHash, String), - #[error("Bad sidechain block (Hash={0}). Reason: {1}")] - BadSidechainBlock(SidechainBlockHash, String), - #[error("Could not import new block due to {2}. (Last imported by number: {0:?})")] - BlockAncestryMismatch(BlockNumber, SidechainBlockHash, String), - #[error("Could not import new block. Expected first block, but found {0}. {1:?}")] - InvalidFirstBlock(BlockNumber, String), - #[error("Could not import block (number: {0}). A block with this number is already imported (current state block number: {1})")] - BlockAlreadyImported(BlockNumber, BlockNumber), - #[error("Failed to pop from block import queue: {0}")] - FailedToPopBlockImportQueue(#[from] itp_import_queue::error::Error), - #[error("Verification Error: {0}")] - VerificationError(its_block_verification::error::Error), - #[error(transparent)] - Other(#[from] Box), -} - -impl core::convert::From for Error { - fn from(e: std::io::Error) -> Self { - Self::Other(e.into()) - } -} - -impl core::convert::From for Error { - fn from(e: codec::Error) -> Self { - Self::Other(e.to_string().into()) - } -} - -impl From for Error { - fn from(sgx_status: sgx_status_t) -> Self { - Self::Sgx(sgx_status) - } -} - -impl From for Error { - fn from(e: VerificationError) -> Self { - match e { - VerificationError::BlockAncestryMismatch(a, b, c) => - Error::BlockAncestryMismatch(a, b, c), - VerificationError::InvalidFirstBlock(a, b) => Error::InvalidFirstBlock(a, b), - VerificationError::BlockAlreadyImported(a, b) => Error::BlockAlreadyImported(a, b), - _ => Error::VerificationError(e), - } - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/header_db.rs b/bitacross-worker/sidechain/consensus/common/src/header_db.rs deleted file mode 100644 index f15acd5028..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/header_db.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -use itp_types::H256; -use its_primitives::traits::Header as HeaderT; -use std::{collections::HashMap, convert::From, hash::Hash as HashT}; - -/// Normally implemented on the `client` in substrate. -/// Is a trait which can offer methods for interfacing with a block Database. -pub trait HeaderDbTrait { - type Header: HeaderT; - /// Retrieves Header for the corresponding block hash. - fn header(&self, hash: &H256) -> Option; -} - -/// A mocked Header Database which allows you to take a Block Hash and Query a Block Header. -pub struct HeaderDb(pub HashMap); - -impl HeaderDbTrait for HeaderDb -where - // TODO: the H256 trait bounds are needed because: #1203 - Hash: PartialEq + HashT + Into + From + core::cmp::Eq + Clone, - Header: HeaderT + Clone, -{ - type Header = Header; - - fn header(&self, hash: &H256) -> Option { - let header = self.0.get(&Hash::from(*hash))?; - Some(header.clone()) - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/is_descendant_of_builder.rs b/bitacross-worker/sidechain/consensus/common/src/is_descendant_of_builder.rs deleted file mode 100644 index 5e13c6f69a..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/is_descendant_of_builder.rs +++ /dev/null @@ -1,133 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -use crate::header_db::HeaderDbTrait; -use core::{hash::Hash as HashT, marker::PhantomData}; -use itp_types::H256; -use its_primitives::traits::Header as HeaderT; - -pub struct IsDescendantOfBuilder(PhantomData<(Hash, HeaderDb, Error)>); - -impl<'a, Hash, HeaderDb, Error> IsDescendantOfBuilder -where - Error: From<()>, - Hash: PartialEq + HashT + Default + Into + From + Clone, - HeaderDb: HeaderDbTrait, -{ - /// Builds the `is_descendant_of` closure for the fork-tree - /// used when adding and removing nodes from the tree. - pub fn build_is_descendant_of( - current: Option<(&'a Hash, &'a Hash)>, - header_db: &'a HeaderDb, - ) -> impl Fn(&Hash, &Hash) -> Result + 'a { - move |base, head| { - // If the base is equal to the proposed head, then the head is for sure not a descendant of the base. - if base == head { - return Ok(false) - } - - let mut head = head; - if let Some((current_hash, current_parent_hash)) = current { - // If the current hash is equal to the base, then it will not be a descendant of base. - if current_hash == base { - return Ok(false) - } - - // If the current hash is the head and the parent is the base, then we know that - // this current hash is the descendant of the parent. Otherwise we can set the - // head to the parent and find the lowest common ancestor between `head` - // and `base` in the tree. - if current_hash == head { - if current_parent_hash == base { - return Ok(true) - } else { - head = current_parent_hash; - } - } - } - - let ancestor = - >::find_lowest_common_ancestor( - head, base, header_db, - )?; - Ok(ancestor == *base) - } - } -} - -pub struct LowestCommonAncestorFinder(PhantomData<(Hash, HeaderDb)>); - -impl LowestCommonAncestorFinder -where - Hash: PartialEq + Default + Into + From + Clone, - HeaderDb: HeaderDbTrait, -{ - /// Used by the `build_is_descendant_of` to find the LCA of two nodes in the fork-tree. - fn find_lowest_common_ancestor(a: &Hash, b: &Hash, header_db: &HeaderDb) -> Result { - let header_1 = header_db.header(&a.clone().into()).ok_or(())?; - let header_2 = header_db.header(&b.clone().into()).ok_or(())?; - let mut blocknum_1 = header_1.block_number(); - let mut blocknum_2 = header_2.block_number(); - let mut parent_1 = Hash::from(header_1.parent_hash()); - let mut parent_2 = Hash::from(header_2.parent_hash()); - - if *a == parent_2 { - // Then a is the common ancestor of b and it means it is itself the ancestor - return Ok(parent_2) - } - - if *b == parent_1 { - // Then b is the common ancestor of a and it means it is itself the ancestor - return Ok(parent_1) - } - - while blocknum_1 > blocknum_2 { - // This means block 1 is further down in the tree than block 2 - let new_parent = header_db.header(&parent_1.clone().into()).ok_or(())?; - - if new_parent.block_number() >= blocknum_2 { - blocknum_1 = new_parent.block_number(); - parent_1 = Hash::from(new_parent.parent_hash()); - } else { - break - } - } - - while blocknum_2 > blocknum_1 { - // This means block 2 is further down in the tree than block 1 - let new_parent = header_db.header(&parent_2.clone().into()).ok_or(())?; - - if new_parent.block_number() >= blocknum_1 { - blocknum_2 = new_parent.block_number(); - parent_2 = Hash::from(new_parent.parent_hash()); - } else { - break - } - } - - // At this point will be at equal height - while parent_1 != parent_2 { - // go up on both nodes - let new_header_1 = header_db.header(&parent_1.into()).ok_or(())?; - let new_header_2 = header_db.header(&parent_2.into()).ok_or(())?; - parent_1 = Hash::from(new_header_1.parent_hash()); - parent_2 = Hash::from(new_header_2.parent_hash()); - } - - // Return any Parent node Hash as in worst case scenario it is the root which is shared amongst all - Ok(parent_1) - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/lib.rs b/bitacross-worker/sidechain/consensus/common/src/lib.rs deleted file mode 100644 index adb91d9ec8..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/lib.rs +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Common stuff that could be shared across multiple consensus engines - -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(test, feature(assert_matches))] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -use its_primitives::traits::{ShardIdentifierFor, SignedBlock as SignedSidechainBlockTrait}; -use sp_runtime::traits::Block as ParentchainBlockTrait; -use std::{time::Duration, vec::Vec}; - -mod block_import; -mod block_import_confirmation_handler; -mod block_import_queue_worker; -mod error; -mod header_db; -mod peer_block_sync; - -// The feature flag will be removed once we use the module outside of tests. -#[cfg(test)] -mod is_descendant_of_builder; - -#[cfg(test)] -mod test; - -pub use block_import::*; -pub use block_import_confirmation_handler::*; -pub use block_import_queue_worker::*; -pub use error::*; -use itp_types::parentchain::ParentchainCall; -pub use peer_block_sync::*; - -pub trait Verifier: Send + Sync -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, -{ - /// Contains all the relevant data needed for block import - type BlockImportParams; - - /// Context used to derive slot relevant data - type Context; - - /// Verify the given data and return the `BlockImportParams` if successful - fn verify( - &self, - block: SignedSidechainBlock, - parentchain_header: &ParentchainBlock::Header, - shard: ShardIdentifierFor, - ctx: &Self::Context, - ) -> Result; -} - -/// Environment for a Consensus instance. -/// -/// Creates proposer instance. -pub trait Environment< - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, -> -{ - /// The proposer type this creates. - type Proposer: Proposer + Send; - /// Error which can occur upon creation. - type Error: From + std::fmt::Debug + 'static; - - /// Initialize the proposal logic on top of a specific header. - fn init( - &mut self, - parent_header: ParentchainBlock::Header, - shard: ShardIdentifierFor, - ) -> std::result::Result; -} - -pub trait Proposer< - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, -> -{ - fn propose(&self, max_duration: Duration) -> Result>; -} - -/// A proposal that is created by a [`Proposer`]. -pub struct Proposal { - /// The sidechain block that was build. - pub block: SignedSidechainBlock, - /// Parentchain state transitions triggered by sidechain state transitions. - /// - /// Any sidechain stf that invokes a parentchain stf must not commit its state change - /// before the parentchain effect has been finalized. - pub parentchain_effects: Vec, -} diff --git a/bitacross-worker/sidechain/consensus/common/src/peer_block_sync.rs b/bitacross-worker/sidechain/consensus/common/src/peer_block_sync.rs deleted file mode 100644 index 945c1c014e..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/peer_block_sync.rs +++ /dev/null @@ -1,320 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{BlockImport, ConfirmBlockImport, Error, Result}; -use core::marker::PhantomData; -use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; -use itp_types::H256; -use its_primitives::{ - traits::{ - Block as BlockTrait, Header as HeaderTrait, ShardIdentifierFor, - SignedBlock as SignedSidechainBlockTrait, - }, - types::BlockHash, -}; -use log::*; -use sp_runtime::traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}; -use std::{sync::Arc, vec::Vec}; - -/// Trait for syncing sidechain blocks from a peer validateer. -/// -/// This entails importing blocks and detecting if we're out of date with our blocks, in which -/// case we fetch the missing blocks from a peer. -pub trait SyncBlockFromPeer -where - ParentchainHeader: ParentchainHeaderTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, -{ - fn sync_block( - &self, - sidechain_block: SignedSidechainBlock, - last_imported_parentchain_header: &ParentchainHeader, - ) -> Result; -} - -/// Sidechain peer block sync implementation. -pub struct PeerBlockSync< - ParentchainBlock, - SignedSidechainBlock, - BlockImporter, - OCallApi, - ImportConfirmationHandler, -> { - importer: Arc, - ocall_api: Arc, - import_confirmation_handler: Arc, - _phantom: PhantomData<(ParentchainBlock, SignedSidechainBlock)>, -} - -impl< - ParentchainBlock, - SignedSidechainBlock, - BlockImporter, - OCallApi, - ImportConfirmationHandler, - > - PeerBlockSync< - ParentchainBlock, - SignedSidechainBlock, - BlockImporter, - OCallApi, - ImportConfirmationHandler, - > where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, - <::Block as BlockTrait>::HeaderType: - HeaderTrait, - BlockImporter: BlockImport, - OCallApi: EnclaveSidechainOCallApi + EnclaveMetricsOCallApi, - ImportConfirmationHandler: ConfirmBlockImport< - <::Block as BlockTrait>::HeaderType, - >, -{ - pub fn new( - importer: Arc, - sidechain_ocall_api: Arc, - import_confirmation_handler: Arc, - ) -> Self { - PeerBlockSync { - importer, - ocall_api: sidechain_ocall_api, - import_confirmation_handler, - _phantom: Default::default(), - } - } - - fn fetch_and_import_blocks_from_peer( - &self, - last_imported_sidechain_block_hash: BlockHash, - import_until_block_hash: BlockHash, - current_parentchain_header: &ParentchainBlock::Header, - shard_identifier: ShardIdentifierFor, - ) -> Result { - info!( - "Initiating fetch blocks from peer, last imported block hash: {:?}, until block hash: {:?}", - last_imported_sidechain_block_hash, import_until_block_hash - ); - - let blocks_to_import: Vec = - self.ocall_api.fetch_sidechain_blocks_from_peer( - last_imported_sidechain_block_hash, - Some(import_until_block_hash), - shard_identifier, - )?; - - info!("Fetched {} blocks from peer to import", blocks_to_import.len()); - - let mut latest_imported_parentchain_header = current_parentchain_header.clone(); - - for block_to_import in blocks_to_import { - let block_number = block_to_import.block().header().block_number(); - - latest_imported_parentchain_header = match self - .importer - .import_block(block_to_import, &latest_imported_parentchain_header) - { - Err(e) => { - error!("Failed to import sidechain block that was fetched from peer: {:?}", e); - return Err(e) - }, - Ok(h) => { - info!( - "Successfully imported peer fetched sidechain block (number: {})", - block_number - ); - h - }, - }; - } - - Ok(latest_imported_parentchain_header) - } -} - -impl - SyncBlockFromPeer - for PeerBlockSync -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, - <::Block as BlockTrait>::HeaderType: - HeaderTrait, - BlockImporter: BlockImport, - OCallApi: EnclaveSidechainOCallApi + EnclaveMetricsOCallApi, - ImportConfirmationHandler: ConfirmBlockImport<<::Block as BlockTrait>::HeaderType>, -{ - fn sync_block( - &self, - sidechain_block: SignedSidechainBlock, - current_parentchain_header: &ParentchainBlock::Header, - ) -> Result { - let shard_identifier = sidechain_block.block().header().shard_id(); - let sidechain_block_number = sidechain_block.block().header().block_number(); - let sidechain_block_hash = sidechain_block.hash(); - - // Attempt to import the block - in case we encounter an ancestry error, we go into - // peer fetching mode to fetch sidechain blocks from a peer and import those first. - match self.importer.import_block(sidechain_block.clone(), current_parentchain_header) { - Err(e) => match e { - Error::BlockAncestryMismatch(_block_number, block_hash, _) => { - warn!("Got ancestry mismatch error upon block import. Attempting to fetch missing blocks from peer"); - let updated_parentchain_header = self.fetch_and_import_blocks_from_peer( - block_hash, - sidechain_block_hash, - current_parentchain_header, - shard_identifier, - )?; - - self.importer.import_block(sidechain_block, &updated_parentchain_header) - }, - Error::InvalidFirstBlock(block_number, _) => { - warn!("Got invalid first block error upon block import (expected first block, but got block with number {}). \ - Attempting to fetch missing blocks from peer", block_number); - let updated_parentchain_header = self.fetch_and_import_blocks_from_peer( - Default::default(), // This is the parent hash of the first block. So we import everything. - sidechain_block_hash, - current_parentchain_header, - shard_identifier, - )?; - - self.importer.import_block(sidechain_block, &updated_parentchain_header) - }, - Error::BlockAlreadyImported(to_import_block_number, last_known_block_number) => { - warn!("Sidechain block from queue (number: {}) was already imported (current block number: {}). Block will be ignored.", - to_import_block_number, last_known_block_number); - Ok(current_parentchain_header.clone()) - }, - _ => Err(e), - }, - Ok(latest_parentchain_header) => { - info!("Successfully imported broadcast sidechain block (number: {}), based on parentchain block {:?}", - sidechain_block_number, latest_parentchain_header.number()); - - // We confirm the successful block import. Only in this case, not when we're in - // on-boarding and importing blocks that were fetched from a peer. - if let Err(e) = self.import_confirmation_handler.confirm_import(sidechain_block.block().header(), &shard_identifier) { - error!("Failed to confirm sidechain block import: {:?}", e); - } - - Ok(latest_parentchain_header) - }, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::test::mocks::{ - block_importer_mock::BlockImportMock, confirm_block_import_mock::ConfirmBlockImportMock, - }; - use core::assert_matches::assert_matches; - use itc_parentchain_test::ParentchainHeaderBuilder; - use itp_test::mock::sidechain_ocall_api_mock::SidechainOCallApiMock; - use itp_types::Block as ParentchainBlock; - use its_primitives::types::block::SignedBlock as SignedSidechainBlock; - use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; - - type TestBlockImport = BlockImportMock; - type TestOCallApi = SidechainOCallApiMock; - type TestPeerBlockSync = PeerBlockSync< - ParentchainBlock, - SignedSidechainBlock, - TestBlockImport, - TestOCallApi, - ConfirmBlockImportMock, - >; - - #[test] - fn if_block_import_is_successful_no_peer_fetching_happens() { - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let signed_sidechain_block = SidechainBlockBuilder::default().build_signed(); - - let block_importer_mock = Arc::new( - BlockImportMock::::default() - .with_import_result_once(Ok(parentchain_header.clone())), - ); - - let sidechain_ocall_api = - Arc::new(SidechainOCallApiMock::::default()); - - let peer_syncer = - create_peer_syncer(block_importer_mock.clone(), sidechain_ocall_api.clone()); - - peer_syncer.sync_block(signed_sidechain_block, &parentchain_header).unwrap(); - - assert_eq!(1, block_importer_mock.get_imported_blocks().len()); - assert_eq!(0, sidechain_ocall_api.number_of_fetch_calls()); - } - - #[test] - fn error_is_propagated_if_import_returns_error_other_than_ancestry_mismatch() { - let block_importer_mock = Arc::new( - BlockImportMock::::default() - .with_import_result_once(Err(Error::InvalidAuthority("auth".to_string()))), - ); - - let sidechain_ocall_api = - Arc::new(SidechainOCallApiMock::::default()); - - let peer_syncer = - create_peer_syncer(block_importer_mock.clone(), sidechain_ocall_api.clone()); - - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let signed_sidechain_block = SidechainBlockBuilder::default().build_signed(); - - let sync_result = peer_syncer.sync_block(signed_sidechain_block, &parentchain_header); - - assert_matches!(sync_result, Err(Error::InvalidAuthority(_))); - assert_eq!(1, block_importer_mock.get_imported_blocks().len()); - assert_eq!(0, sidechain_ocall_api.number_of_fetch_calls()); - } - - #[test] - fn blocks_are_fetched_from_peer_if_initial_import_yields_ancestry_mismatch() { - let block_importer_mock = - Arc::new(BlockImportMock::::default().with_import_result_once( - Err(Error::BlockAncestryMismatch(1, H256::random(), "".to_string())), - )); - - let sidechain_ocall_api = Arc::new( - SidechainOCallApiMock::::default().with_peer_fetch_blocks(vec![ - SidechainBlockBuilder::random().build_signed(), - SidechainBlockBuilder::random().build_signed(), - ]), - ); - - let peer_syncer = - create_peer_syncer(block_importer_mock.clone(), sidechain_ocall_api.clone()); - - let parentchain_header = ParentchainHeaderBuilder::default().build(); - let signed_sidechain_block = SidechainBlockBuilder::default().build_signed(); - - peer_syncer.sync_block(signed_sidechain_block, &parentchain_header).unwrap(); - - assert_eq!(4, block_importer_mock.get_imported_blocks().len()); - assert_eq!(1, sidechain_ocall_api.number_of_fetch_calls()); - } - - fn create_peer_syncer( - block_importer: Arc, - ocall_api: Arc, - ) -> TestPeerBlockSync { - let import_confirmation_handler = Arc::new(ConfirmBlockImportMock {}); - TestPeerBlockSync::new(block_importer, ocall_api, import_confirmation_handler) - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_import_queue_worker_mock.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_import_queue_worker_mock.rs deleted file mode 100644 index fb2b0d8bcc..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_import_queue_worker_mock.rs +++ /dev/null @@ -1,263 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -use crate::{header_db::HeaderDb, is_descendant_of_builder::IsDescendantOfBuilder}; -use core::marker::PhantomData; -use fork_tree::ForkTree; -use itp_types::H256; -use its_primitives::{ - traits::{Block as BlockT, Header as HeaderT}, - types::{header::SidechainHeader as Header, Block}, -}; -use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; -use std::collections::VecDeque; - -#[derive(Default)] -pub struct BlockQueueBuilder { - queue: VecDeque, - _phantom_data: PhantomData, -} - -impl BlockQueueBuilder -where - Builder: SidechainBlockBuilderTrait + Default, - B: BlockT + From, -{ - fn new() -> Self { - Self { queue: VecDeque::new(), _phantom_data: PhantomData::default() } - } - - /// Allows definining a mock queue based and assumes that a genesis block - /// will need to be appended to the queue as the first item. - /// Returns: BuiltQueue - fn build_queue(self, f: impl FnOnce(VecDeque) -> VecDeque) -> VecDeque { - f(self.queue) - } - - fn add_genesis_block_to_queue(self) -> Self { - let mut self_mut = self; - let genesis_header = Header { - block_number: 0, - parent_hash: H256::from_slice(&[0; 32]), - ..Default::default() - }; - let block: B = Builder::default().with_header(genesis_header).build().into(); - self_mut.queue.push_back(block); - self_mut - } -} - -pub trait BlockQueueHeaderBuild { - type QueueHeader; - /// Helper trait to build a Header for a BlockQueue. - fn build_queue_header(block_number: BlockNumber, parent_hash: Hash) -> Self::QueueHeader; -} - -pub struct BlockQueueHeaderBuilder(PhantomData<(BlockNumber, Hash)>); - -impl BlockQueueHeaderBuild - for BlockQueueHeaderBuilder -where - BlockNumber: Into, - Hash: Into, -{ - type QueueHeader = Header; - /// Helper trait to build a Header for a BlockQueue. - fn build_queue_header(block_number: BlockNumber, parent_hash: Hash) -> Self::QueueHeader { - Header { - block_number: block_number.into(), - parent_hash: parent_hash.into(), - block_data_hash: H256::random(), - ..Default::default() - } - } -} - -#[derive(Debug)] -pub enum TestError { - Error, -} - -impl From<()> for TestError { - fn from(_a: ()) -> Self { - TestError::Error - } -} - -impl std::fmt::Display for TestError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "TestError") - } -} - -impl std::error::Error for TestError {} - -#[cfg(test)] -mod tests { - use super::*; - - fn fork_tree_from_header_queue(queue: VecDeque) -> ForkTree - where - B: BlockT, - { - // Store all block_headers in db - let db = HeaderDb::( - queue.iter().map(|block| (block.hash(), *block.header())).collect(), - ); - - // Import into forktree - let is_descendant_of = - , TestError>>::build_is_descendant_of(None, &db); - let mut tree = >::new(); - queue.iter().for_each(|block| { - let _ = tree - .import(block.header().hash(), block.header().block_number(), (), &is_descendant_of) - .unwrap(); - }); - tree - } - - #[test] - fn process_sequential_queue_no_forks() { - // Construct a queue which is sequential with 5 members all with distinct block numbers and parents - let mut queue = >::new() - .add_genesis_block_to_queue() - .build_queue(|mut queue| { - for i in 1..5 { - let parent_header = queue.back().unwrap().header(); - let header = >::build_queue_header( - i, - parent_header.hash(), - ); - queue.push_back(SidechainBlockBuilder::default().with_header(header).build()); - } - queue - }); - - // queue -> [0, 1, 2, 3, 4] - assert_eq!(queue.len(), 5); - - let mut tree = fork_tree_from_header_queue::(queue.clone()); - - // We have a tree which looks like this. H0 is the only root. - // - // H0 - H1 - H2 - H3 - H4 - // - - // We see that the only root of this tree is so far H0 - assert_eq!(tree.roots_hash_and_number(), vec![(&queue.front().unwrap().header.hash(), &0)]); - - // Now finalize H0 and so the new Root should be H1 - tree.finalize_root(&queue.front().unwrap().header.hash()).unwrap(); - let _ = queue.pop_front(); - assert_eq!(tree.roots_hash_and_number(), vec![(&queue.front().unwrap().header.hash(), &1)]); - } - - #[test] - fn process_sequential_queue_with_forks() { - // Construct a queue which is sequential and every odd member has 2 block numbers which are the same - let mut queue = >::new() - .add_genesis_block_to_queue() - .build_queue(|mut queue| { - for i in 1..8 { - let parent_header = queue.back().unwrap().header(); - if i % 2 == 0 && i != 1 { - // 1 is not even want all odds to have 2 of the same block_number - let header = >::build_queue_header( - i, - parent_header.hash(), - ); - queue.push_back( - SidechainBlockBuilder::default().with_header(header).build(), - ); - } else { - // build a Queue with 2 headers which are of the same block_number - let headers = vec![ - >::build_queue_header( - i, - parent_header.hash(), - ), - >::build_queue_header( - i, - parent_header.hash(), - ), - ]; - headers.iter().for_each(|header| { - queue.push_back( - SidechainBlockBuilder::default().with_header(*header).build(), - ); - }); - } - } - queue - }); - - // queue -> [0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7] - assert_eq!(queue.len(), 12); - - let mut tree = fork_tree_from_header_queue::(queue.clone()); - - // We have a tree which looks like the following - // - (H5, B3).. - // / - // - (H3, B2) - // / \ - // - (H1, B1) - (H4, B3).. - // / - // / - // (H0, B0) - // \ - // \ - // - (H2, B1).. - // - // - - // H0 is the first root - assert_eq!(tree.roots_hash_and_number(), vec![(&queue.front().unwrap().header.hash(), &0)]); - - // Now if we finalize H0 we should see 2 roots H1 and H2 - tree.finalize_root(&queue.front().unwrap().header.hash()).unwrap(); - let _ = queue.pop_front(); - assert_eq!( - tree.roots_hash_and_number(), - vec![(&queue[1].header.hash(), &1), (&queue[0].header.hash(), &1)] - ); - - // If we finalize (H1, B1) then we should see one roots (H3, B2) - let _ = queue.pop_front(); // remove (H1, B1) - tree.finalize_root(&queue.front().unwrap().header.hash()).unwrap(); - let _ = queue.pop_front(); // remove (H2, B1) - assert_eq!(tree.roots_hash_and_number(), vec![(&queue[0].header.hash(), &2)]); - - // If we finalize (H3, B2) we should see two roots (H4, B3), (H5, B3) - tree.finalize_root(&queue.front().unwrap().header.hash()).unwrap(); - let _ = queue.pop_front(); // remove (H3, B2) - assert_eq!( - tree.roots_hash_and_number(), - vec![(&queue[1].header.hash(), &3), (&queue[0].header.hash(), &3)] - ); - } - - #[test] - fn process_non_sequential_queue_without_forks() { - // TODO - } - - #[test] - fn process_non_sequential_queue_with_forks() { - // TODO - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_importer_mock.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_importer_mock.rs deleted file mode 100644 index 9d6060561f..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_importer_mock.rs +++ /dev/null @@ -1,168 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{test::mocks::verifier_mock::VerifierMock, BlockImport, Error, Result}; -use core::marker::PhantomData; -use itp_ocall_api::EnclaveMetricsOCallApi; -use itp_sgx_crypto::aes::Aes; -use itp_sgx_externalities::SgxExternalities; -use itp_test::mock::onchain_mock::OnchainMock; -use itp_types::H256; -use its_primitives::traits::{ShardIdentifierFor, SignedBlock as SignedSidechainBlockTrait}; -use sp_core::Pair; -use sp_runtime::traits::Block as ParentchainBlockTrait; -use std::{collections::VecDeque, sync::RwLock}; - -/// Block importer mock. -pub struct BlockImportMock -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: - SignedSidechainBlockTrait::Public> + 'static, -{ - import_result: RwLock>>, - imported_blocks: RwLock>, - _phantom: PhantomData<(ParentchainBlock, SignedSidechainBlock)>, -} - -impl BlockImportMock -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: - SignedSidechainBlockTrait::Public> + 'static, -{ - pub fn with_import_result_once(self, result: Result) -> Self { - let mut imported_results_lock = self.import_result.write().unwrap(); - imported_results_lock.push_back(result); - std::mem::drop(imported_results_lock); - self - } - - #[allow(unused)] - pub fn with_import_result_sequence( - self, - mut results: VecDeque>, - ) -> Self { - let mut imported_results_lock = self.import_result.write().unwrap(); - imported_results_lock.append(&mut results); - std::mem::drop(imported_results_lock); - self - } - - pub fn get_imported_blocks(&self) -> Vec { - (*self.imported_blocks.read().unwrap()).clone() - } -} - -impl Default - for BlockImportMock -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: - SignedSidechainBlockTrait::Public> + 'static, -{ - fn default() -> Self { - BlockImportMock { - import_result: RwLock::default(), - imported_blocks: RwLock::default(), - _phantom: Default::default(), - } - } -} - -impl BlockImport - for BlockImportMock -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: - SignedSidechainBlockTrait::Public> + 'static, -{ - type Verifier = - VerifierMock; - type SidechainState = SgxExternalities; - type StateCrypto = Aes; - type Context = OnchainMock; - - fn verifier( - &self, - _maybe_last_sidechain_block: Option, - ) -> Self::Verifier { - todo!() - } - - fn apply_state_update( - &self, - _shard: &ShardIdentifierFor, - _mutating_function: F, - ) -> Result<()> - where - F: FnOnce(Self::SidechainState) -> Result, - { - todo!() - } - - fn verify_import( - &self, - _shard: &ShardIdentifierFor, - _verifying_function: F, - ) -> core::result::Result - where - F: FnOnce(&Self::SidechainState) -> core::result::Result, - { - todo!() - } - - fn state_key(&self) -> Result { - todo!() - } - - fn get_context(&self) -> &Self::Context { - todo!() - } - - fn import_parentchain_block( - &self, - _sidechain_block: &SignedSidechainBlock::Block, - _last_imported_parentchain_header: &ParentchainBlock::Header, - ) -> Result { - todo!() - } - - fn peek_parentchain_header( - &self, - _sidechain_block: &SignedSidechainBlock::Block, - _last_imported_parentchain_header: &ParentchainBlock::Header, - ) -> core::result::Result { - todo!() - } - - fn cleanup(&self, _signed_sidechain_block: &SignedSidechainBlock) -> Result<()> { - todo!() - } - - fn import_block( - &self, - signed_sidechain_block: SignedSidechainBlock, - parentchain_header: &ParentchainBlock::Header, - ) -> Result { - let mut imported_blocks_lock = self.imported_blocks.write().unwrap(); - imported_blocks_lock.push(signed_sidechain_block); - - let mut imported_results_lock = self.import_result.write().unwrap(); - imported_results_lock.pop_front().unwrap_or(Ok(parentchain_header.clone())) - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/confirm_block_import_mock.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/confirm_block_import_mock.rs deleted file mode 100644 index a810da2f3b..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/test/mocks/confirm_block_import_mock.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{error::Result, ConfirmBlockImport}; -use itp_types::ShardIdentifier; -use its_primitives::types::header::SidechainHeader; - -/// Mock implementation of the `ConfirmBlockImport` trait. -pub struct ConfirmBlockImportMock; - -impl ConfirmBlockImport for ConfirmBlockImportMock { - fn confirm_import(&self, _header: &SidechainHeader, _shard: &ShardIdentifier) -> Result<()> { - Ok(()) - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/mod.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/mod.rs deleted file mode 100644 index 1408ce9402..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/test/mocks/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub mod block_import_queue_worker_mock; -pub mod block_importer_mock; -pub mod confirm_block_import_mock; -pub mod verifier_mock; diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/verifier_mock.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/verifier_mock.rs deleted file mode 100644 index e6d8cbeb0e..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/test/mocks/verifier_mock.rs +++ /dev/null @@ -1,62 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{Result, ShardIdentifierFor, Verifier}; -use itp_types::H256; -use its_primitives::traits::SignedBlock as SignedSidechainBlockTrait; -use sp_core::Pair; -use sp_runtime::traits::Block as ParentchainBlockTrait; -use std::marker::PhantomData; - -/// Verifier mock implementation. -pub struct VerifierMock< - ParentchainBlock, - SignedSidechainBlock, - BlockImportParameters, - VerifierContext, -> { - _phantom: PhantomData<( - ParentchainBlock, - SignedSidechainBlock, - BlockImportParameters, - VerifierContext, - )>, -} - -impl - Verifier - for VerifierMock -where - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: - SignedSidechainBlockTrait::Public> + 'static, - BlockImportParameters: Send + Sync, - VerifierContext: Send + Sync, -{ - type BlockImportParams = BlockImportParameters; - type Context = VerifierContext; - - fn verify( - &self, - _block: SignedSidechainBlock, - _parentchain_header: &ParentchainBlock::Header, - _shard: ShardIdentifierFor, - _ctx: &Self::Context, - ) -> Result { - todo!() - } -} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mod.rs b/bitacross-worker/sidechain/consensus/common/src/test/mod.rs deleted file mode 100644 index 43e6cb274d..0000000000 --- a/bitacross-worker/sidechain/consensus/common/src/test/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub mod mocks; diff --git a/bitacross-worker/sidechain/consensus/slots/Cargo.toml b/bitacross-worker/sidechain/consensus/slots/Cargo.toml deleted file mode 100644 index 41070d0af0..0000000000 --- a/bitacross-worker/sidechain/consensus/slots/Cargo.toml +++ /dev/null @@ -1,78 +0,0 @@ -[package] -name = "its-consensus-slots" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -derive_more = "0.99.16" -lazy_static = { version = "1.1.0", features = ["spin_no_std"] } -log = { version = "0.4", default-features = false } - -# local deps -itp-types = { path = "../../../core-primitives/types", default-features = false } -its-block-verification = { path = "../../block-verification", default-features = false } -its-primitives = { path = "../../primitives", default-features = false } - -# only for slot-stream -futures-timer = { version = "3.0", optional = true } - -# sgx deps -sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true, features = ["untrusted_time"] } - -# substrate deps -sp-consensus-slots = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -# local deps -itp-settings = { path = "../../../core-primitives/settings" } -itp-time-utils = { path = "../../../core-primitives/time-utils", default-features = false } -its-consensus-common = { path = "../common", default-features = false } - -# litentry -hex = { version = "0.4", default-features = false } -itp-sgx-externalities = { path = "../../../core-primitives/substrate-sgx/externalities", default-features = false } -itp-stf-state-handler = { path = "../../../core-primitives/stf-state-handler", default-features = false } -its-state = { path = "../../state", default-features = false } -lc-scheduled-enclave = { path = "../../../litentry/core/scheduled-enclave", default-features = false } - - -[dev-dependencies] -itc-parentchain-test = { path = "../../../core/parentchain/test" } -its-test = { path = "../../test" } -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -itp-test = { path = "../../../core-primitives/test" } -tokio = { version = "1.6.1", features = ["full"] } - -[features] -default = ["std"] -std = [ - "codec/std", - "log/std", - # only for slot-stream - "futures-timer", - # substrate - "sp-consensus-slots/std", - "sp-runtime/std", - # local - "itp-time-utils/std", - "itp-types/std", - "its-primitives/std", - "its-block-verification/std", - "its-consensus-common/std", - "itp-stf-state-handler/std", - "itp-sgx-externalities/std", - "its-state/std", - "lc-scheduled-enclave/std", -] -sgx = [ - "itp-time-utils/sgx", - "its-consensus-common/sgx", - "sgx_tstd", - "itp-stf-state-handler/sgx", - "itp-sgx-externalities/sgx", - "its-state/sgx", - "lc-scheduled-enclave/sgx", -] diff --git a/bitacross-worker/sidechain/consensus/slots/src/lib.rs b/bitacross-worker/sidechain/consensus/slots/src/lib.rs deleted file mode 100644 index 9c22327580..0000000000 --- a/bitacross-worker/sidechain/consensus/slots/src/lib.rs +++ /dev/null @@ -1,613 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Slots functionality for the integritee-sidechain. -//! -//! Some consensus algorithms have a concept of *slots*, which are intervals in -//! time during which certain events can and/or must occur. This crate -//! provides generic functionality for slots. - -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(test, feature(assert_matches))] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -use codec::Encode; -use core::str::FromStr; -use derive_more::From; -use itp_sgx_externalities::SgxExternalities; -use itp_stf_state_handler::handle_state::HandleState; -use itp_time_utils::{duration_difference, duration_now}; - -use its_consensus_common::{Error as ConsensusError, Proposer}; -use its_primitives::traits::{ - Block as SidechainBlockTrait, Header as HeaderTrait, ShardIdentifierFor, - SignedBlock as SignedSidechainBlockTrait, -}; -use its_state::SidechainSystemExt; -use lc_scheduled_enclave::ScheduledEnclaveUpdater; -use log::*; -pub use slots::*; -use sp_runtime::traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}; -use std::{fmt::Debug, sync::Arc, time::Duration, vec::Vec}; - -#[cfg(feature = "std")] -mod slot_stream; -mod slots; - -#[cfg(feature = "sgx")] -use std::sync::SgxRwLock as RwLock; - -#[cfg(feature = "std")] -use std::sync::RwLock; - -#[cfg(test)] -mod mocks; - -#[cfg(test)] -mod per_shard_slot_worker_tests; - -use itp_types::parentchain::ParentchainCall; -#[cfg(feature = "std")] -pub use slot_stream::*; -pub use slots::*; - -/// The result of [`SlotWorker::on_slot`]. -#[derive(Debug, Clone, Encode, From)] -pub struct SlotResult { - /// The result of a slot operation. - pub block: SignedSidechainBlock, - /// Parentchain state transitions triggered by sidechain state transitions. - /// - /// Any sidechain stf that invokes a parentchain stf must not commit its state change - /// before the parentchain effect has been finalized. - pub parentchain_effects: Vec, -} - -pub struct FailSlotOnDemand { - // we need to keep a internal counter because node's slot number is a function of slot_beginning_timestamp and SLOT_DURATION - current_slot: RwLock, - fail_at_slot: u64, - mode: FailSlotMode, -} - -impl FailSlotOnDemand { - pub fn new(fail_at_slot: u64, mode: FailSlotMode) -> Self { - Self { current_slot: Default::default(), fail_at_slot, mode } - } - - pub fn next_slot(&self) { - let mut current_slot_lock = self.current_slot.write().unwrap(); - *current_slot_lock += 1; - } - - pub fn check_before_on_slot(&self) -> bool { - let current_slot = self.current_slot.read().unwrap(); - *current_slot == self.fail_at_slot && matches!(&self.mode, FailSlotMode::BeforeOnSlot) - } - - pub fn check_after_on_slot(&self) -> bool { - let current_slot = self.current_slot.read().unwrap(); - *current_slot == self.fail_at_slot && matches!(&self.mode, FailSlotMode::AfterOnSlot) - } -} - -#[derive(Clone, Debug, PartialEq)] -pub enum FailSlotMode { - BeforeOnSlot, - AfterOnSlot, -} - -impl FromStr for FailSlotMode { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - match s { - "BeforeOnSlot" => Ok(FailSlotMode::BeforeOnSlot), - "AfterOnSlot" => Ok(FailSlotMode::AfterOnSlot), - _ => Err("no match"), - } - } -} - -/// A worker that should be invoked at every new slot for a specific shard. -/// -/// The implementation should not make any assumptions of the slot being bound to the time or -/// similar. The only valid assumption is that the slot number is always increasing. -pub trait SlotWorker { - /// Output generated after a slot - type Output: SignedSidechainBlockTrait + Send + 'static; - - /// Called when a new slot is triggered. - /// - /// Returns a [`SlotResult`] iff a block was successfully built in - /// the slot. Otherwise `None` is returned. - fn on_slot( - &mut self, - slot_info: SlotInfo, - shard: ShardIdentifierFor, - is_single_worker: bool, - ) -> Option>; -} - -/// A slot worker scheduler that should be invoked at every new slot. -/// -/// It manages the timeslots of individual per shard `SlotWorker`s. It gives each shard an equal -/// amount of time to produce it's result, equally distributing leftover time from a previous shard's -/// slot share to all subsequent slots. -pub trait PerShardSlotWorkerScheduler { - /// Output generated after a slot - type Output: Send + 'static; - - /// The shard type 'PerShardWorker's operate on. - type ShardIdentifier: Send + 'static + Debug + Clone; - - /// Called when a new slot is triggered. - /// - /// Returns a [`SlotResult`] iff a block was successfully built in - /// the slot. Otherwise `None` is returned. - fn on_slot( - &mut self, - slot_info: SlotInfo, - shard: Vec, - is_single_worker: bool, - ) -> Self::Output; -} - -/// A skeleton implementation for `SlotWorker` which tries to claim a slot at -/// its beginning and tries to produce a block if successfully claimed, timing -/// out if block production takes too long. -pub trait SimpleSlotWorker { - /// The type of proposer to use to build blocks. - type Proposer: Proposer; - - /// Data associated with a slot claim. - type Claim: Send + 'static; - - /// Epoch data necessary for authoring. - type EpochData: Send + 'static; - - /// Output generated after a slot - type Output: SignedSidechainBlockTrait + Send + 'static; - - /// Scheduled enclave context for authoring - type ScheduledEnclave: ScheduledEnclaveUpdater; - - /// State handler context for authoring - type StateHandler: HandleState; - - /// The logging target to use when logging messages. - fn logging_target(&self) -> &'static str; - - /// Get scheduled enclave - fn get_scheduled_enclave(&mut self) -> Arc; - - /// Get state handler for query and mutation - fn get_state_handler(&mut self) -> Arc; - - /// Returns the epoch data necessary for authoring. For time-dependent epochs, - /// use the provided slot number as a canonical source of time. - fn epoch_data( - &self, - header: &ParentchainBlock::Header, - shard: ShardIdentifierFor, - slot: Slot, - ) -> Result; - - /// Returns the number of authorities given the epoch data. - /// None indicate that the authorities information is incomplete. - fn authorities_len(&self, epoch_data: &Self::EpochData) -> Option; - - /// Tries to claim the given slot, returning an object with claim data if successful. - fn claim_slot( - &self, - header: &ParentchainBlock::Header, - slot: Slot, - epoch_data: &Self::EpochData, - ) -> Option; - - /// Creates the proposer for the current slot - fn proposer( - &mut self, - header: ParentchainBlock::Header, - shard: ShardIdentifierFor, - ) -> Result; - - /// Remaining duration for proposing. - fn proposing_remaining_duration(&self, slot_info: &SlotInfo) -> Duration; - - /// Trigger the import of the given parentchain block. - /// - /// Returns the header of the latest imported block. In case no block was imported with this trigger, - /// None is returned. - fn import_integritee_parentchain_blocks_until( - &self, - last_imported_parentchain_header: &::Hash, - ) -> Result, ConsensusError>; - - fn import_target_a_parentchain_blocks_until( - &self, - last_imported_parentchain_header: &::Hash, - ) -> Result, ConsensusError>; - - fn import_target_b_parentchain_blocks_until( - &self, - last_imported_parentchain_header: &::Hash, - ) -> Result, ConsensusError>; - - /// Peek the parentchain import queue for the latest block in queue. - /// Does not perform the import or mutate the queue. - fn peek_latest_integritee_parentchain_header( - &self, - ) -> Result, ConsensusError>; - - fn peek_latest_target_a_parentchain_header( - &self, - ) -> Result, ConsensusError>; - - fn peek_latest_target_b_parentchain_header( - &self, - ) -> Result, ConsensusError>; - - /// Implements [`SlotWorker::on_slot`]. This is an adaption from - /// substrate's sc-consensus-slots implementation. There, the slot worker handles all the - /// scheduling itself. Unfortunately, we can't use the same principle in the enclave due to some - /// futures-primitives not being available in sgx, e.g. `Delay` in our case. Hence, before - /// reimplementing the those things ourselves, we take a simplified approach and simply call - /// this function from the outside at each slot. - fn on_slot( - &mut self, - slot_info: SlotInfo, - shard: ShardIdentifierFor, - is_single_worker: bool, - ) -> Option> { - let (_timestamp, slot) = (slot_info.timestamp, slot_info.slot); - let logging_target = self.logging_target(); - - let remaining_duration = self.proposing_remaining_duration(&slot_info); - - if remaining_duration == Duration::default() { - debug!( - target: logging_target, - "Skipping proposal slot {} since there's no time left to propose", *slot, - ); - - return None - } - - let latest_integritee_parentchain_header = - match self.peek_latest_integritee_parentchain_header() { - Ok(Some(peeked_header)) => peeked_header, - Ok(None) => slot_info.last_imported_integritee_parentchain_head.clone(), - Err(e) => { - warn!( - target: logging_target, - "Failed to peek latest Integritee parentchain block header: {:?}", e - ); - return None - }, - }; - trace!( - target: logging_target, - "on_slot: a priori latest Integritee block number: {:?}", - latest_integritee_parentchain_header.number() - ); - // fixme: we need proper error handling here. we just assume there is no target_a if there is an error here, which is very brittle - let maybe_latest_target_a_parentchain_header = - match self.peek_latest_target_a_parentchain_header() { - Ok(Some(peeked_header)) => Some(peeked_header), - Ok(None) => slot_info.maybe_last_imported_target_a_parentchain_head.clone(), - Err(e) => { - debug!( - target: logging_target, - "Failed to peek latest target_a_parentchain block header: {:?}", e - ); - None - }, - }; - trace!( - target: logging_target, - "on_slot: a priori latest TargetA block number: {:?}", - maybe_latest_target_a_parentchain_header.clone().map(|h| *h.number()) - ); - - let maybe_latest_target_b_parentchain_header = - match self.peek_latest_target_b_parentchain_header() { - Ok(Some(peeked_header)) => Some(peeked_header), - Ok(None) => slot_info.maybe_last_imported_target_b_parentchain_head.clone(), - Err(e) => { - debug!( - target: logging_target, - "Failed to peek latest target_a_parentchain block header: {:?}", e - ); - None - }, - }; - trace!( - target: logging_target, - "on_slot: a priori latest TargetB block number: {:?}", - maybe_latest_target_b_parentchain_header.clone().map(|h| *h.number()) - ); - - let epoch_data = match self.epoch_data(&latest_integritee_parentchain_header, shard, slot) { - Ok(epoch_data) => epoch_data, - Err(e) => { - warn!( - target: logging_target, - "Unable to fetch epoch data at block {:?}: {:?}", - latest_integritee_parentchain_header.hash(), - e, - ); - - return None - }, - }; - - let authorities_len = self.authorities_len(&epoch_data); - - if !authorities_len.map(|a| a > 0).unwrap_or(false) { - debug!( - target: logging_target, - "Skipping proposal slot. Authorities len {:?}", authorities_len - ); - } - - // Return early if MRENCLAVE doesn't match - it implies that the enclave should be updated - let scheduled_enclave = self.get_scheduled_enclave(); - let state_handler = self.get_state_handler(); - // TODO: is this always consistent? Reference: `propose_state_update` in slot_proposer.rs - let (state, _) = state_handler.load_cloned(&shard.into()).ok()?; - let next_sidechain_number = state.get_block_number().map_or(1, |n| n + 1); - - if !scheduled_enclave.is_mrenclave_matching(next_sidechain_number) { - warn!( - target: logging_target, - "Skipping sidechain block {} due to mismatch MRENCLAVE, current: {:?}, expect: {:?}", - next_sidechain_number, - scheduled_enclave.get_current_mrenclave().map(hex::encode), - scheduled_enclave.get_expected_mrenclave(next_sidechain_number).map(hex::encode), - ); - if let Ok(false) = scheduled_enclave.is_block_production_paused() { - let _ = scheduled_enclave.set_block_production_paused(true); - info!("Pause sidechain block production"); - } - return None - } else { - // TODO: this block production pause/unpause is not strictly needed but I add it here as placeholder. - // Maybe we should add a field to describe the reason for pausing/unpausing, as - // it's possible that we want to manually/focibly pause the sidechain - if let Ok(true) = scheduled_enclave.is_block_production_paused() { - info!("Resume sidechain block production"); - let _ = scheduled_enclave.set_block_production_paused(false); - } - } - - // TODO: about the shard migration and state migration - // - the shard migration(copy-over) is done manually by the subcommand "migrate-shard". - // - the state migration is done via conditionally calling on_runtime_upgrade() by comparing - // the current runtime version and LastRuntimeUpgrade, see `stf_sgx.rs`. - // It means we need to bump the runtime version for the new enclave if we want the state - // migration to be executed. - - let _claim = self.claim_slot(&latest_integritee_parentchain_header, slot, &epoch_data)?; - - // Import the peeked parentchain header(s). - let last_imported_integritee_header = match self.import_integritee_parentchain_blocks_until( - &latest_integritee_parentchain_header.hash(), - ) { - Ok(h) => h, - Err(e) => { - debug!( - target: logging_target, - "Failed to import Integritee blocks until nr{:?}: {:?}", - latest_integritee_parentchain_header.number(), - e - ); - None - }, - }; - trace!( - target: logging_target, - "on_slot: a posteriori latest Integritee block number: {:?}", - last_imported_integritee_header.clone().map(|h| *h.number()) - ); - - let maybe_last_imported_target_a_header = - if let Some(ref header) = maybe_latest_target_a_parentchain_header { - match self.import_target_a_parentchain_blocks_until(&header.hash()) { - Ok(Some(h)) => Some(h), - Ok(None) => None, - Err(e) => { - debug!( - target: logging_target, - "Failed to import TargetA blocks until nr{:?}: {:?}", - header.number(), - e - ); - None - }, - } - } else { - None - }; - trace!( - target: logging_target, - "on_slot: a posteriori latest TargetA block number: {:?}", - maybe_last_imported_target_a_header.map(|h| *h.number()) - ); - - let maybe_last_imported_target_b_header = - if let Some(ref header) = maybe_latest_target_b_parentchain_header { - match self.import_target_b_parentchain_blocks_until(&header.hash()) { - Ok(Some(h)) => Some(h), - Ok(None) => None, - Err(e) => { - debug!( - target: logging_target, - "Failed to import TargetB blocks until nr{:?}: {:?}", - header.number(), - e - ); - None - }, - } - } else { - None - }; - - trace!( - target: logging_target, - "on_slot: a posteriori latest TargetB block number: {:?}", - maybe_last_imported_target_b_header.map(|h| *h.number()) - ); - - let proposer = match self.proposer(latest_integritee_parentchain_header.clone(), shard) { - Ok(p) => p, - Err(e) => { - warn!(target: logging_target, "Could not create proposer: {:?}", e); - return None - }, - }; - - let proposing = match proposer.propose(remaining_duration) { - Ok(p) => p, - Err(e) => { - warn!(target: logging_target, "Could not propose: {:?}", e); - return None - }, - }; - - if is_single_worker { - error!("Running as single worker, skipping timestamp within slot check") - } else if !timestamp_within_slot(&slot_info, &proposing.block) { - warn!( - target: logging_target, - "⌛️ Discarding proposal for slot {}, block number {}; block production took too long", - *slot, proposing.block.block().header().block_number(), - ); - - return None - } - - if last_imported_integritee_header.is_some() { - println!( - "Syncing Parentchains: Integritee: {:?} TargetA: {:?}, TargetB: {:?}, Sidechain: {:?}", - latest_integritee_parentchain_header.number(), - maybe_latest_target_a_parentchain_header.map(|h| *h.number()), - maybe_latest_target_b_parentchain_header.map(|h| *h.number()), - proposing.block.block().header().block_number() - ); - } - - info!("Proposing sidechain block (number: {}, hash: {}) based on integritee parentchain block (number: {:?}, hash: {:?})", - proposing.block.block().header().block_number(), proposing.block.hash(), - latest_integritee_parentchain_header.number(), latest_integritee_parentchain_header.hash() - ); - - Some(SlotResult { - block: proposing.block, - parentchain_effects: proposing.parentchain_effects, - }) - } -} - -impl + Send> - SlotWorker for T -{ - type Output = T::Output; - - fn on_slot( - &mut self, - slot_info: SlotInfo, - shard: ShardIdentifierFor, - is_single_worker: bool, - ) -> Option> { - SimpleSlotWorker::on_slot(self, slot_info, shard, is_single_worker) - } -} - -impl> - PerShardSlotWorkerScheduler for T -{ - type Output = Vec>; - - type ShardIdentifier = ShardIdentifierFor; - - fn on_slot( - &mut self, - slot_info: SlotInfo, - shards: Vec, - is_single_worker: bool, - ) -> Self::Output { - let logging_target = SimpleSlotWorker::logging_target(self); - - let mut remaining_shards = shards.len(); - let mut slot_results = Vec::with_capacity(remaining_shards); - - for shard in shards.into_iter() { - let now = duration_now(); // It's important we have a common `now` for all following computations. - let shard_remaining_duration = duration_difference(now, slot_info.ends_at) - .and_then(|time| time.checked_div(remaining_shards as u32)) - .unwrap_or_default(); - - // important to check against millis here. We had the corner-case in production - // setup where `shard_remaining_duration` contained only nanos. - if shard_remaining_duration.as_millis() == u128::default() { - info!( - target: logging_target, - "⌛️ Could not produce blocks for all shards; block production took too long", - ); - - return slot_results - } - - let shard_slot_ends_at = now + shard_remaining_duration; - let shard_slot = SlotInfo::new( - slot_info.slot, - now, - shard_remaining_duration, - shard_slot_ends_at, - slot_info.last_imported_integritee_parentchain_head.clone(), - slot_info.maybe_last_imported_target_a_parentchain_head.clone(), - slot_info.maybe_last_imported_target_b_parentchain_head.clone(), - ); - - match SimpleSlotWorker::on_slot(self, shard_slot.clone(), shard, is_single_worker) { - Some(res) => { - slot_results.push(res); - debug!( - target: logging_target, - "on_slot: produced block for slot: {:?} in shard {:?}", shard_slot, shard - ) - }, - None => info!( - target: logging_target, - "Did not propose a block for slot {} in shard {:?}", *slot_info.slot, shard - ), - } - - remaining_shards -= 1; - } - - slot_results - } -} diff --git a/bitacross-worker/sidechain/consensus/slots/src/mocks.rs b/bitacross-worker/sidechain/consensus/slots/src/mocks.rs deleted file mode 100644 index 409fb41987..0000000000 --- a/bitacross-worker/sidechain/consensus/slots/src/mocks.rs +++ /dev/null @@ -1,158 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{slots::Slot, SimpleSlotWorker, SlotInfo, SlotResult}; -pub use itp_test::mock::handle_state_mock::HandleStateMock; -use its_consensus_common::{Proposal, Proposer, Result}; -use its_primitives::{traits::ShardIdentifierFor, types::SignedBlock as SignedSidechainBlock}; -use lc_scheduled_enclave::ScheduledEnclaveMock; -use sp_runtime::traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}; -use std::{marker::PhantomData, sync::Arc, thread, time::Duration}; - -#[derive(Default)] -pub(crate) struct ProposerMock { - _phantom: PhantomData, -} - -impl Proposer for ProposerMock -where - B: ParentchainBlockTrait, -{ - fn propose(&self, _max_duration: Duration) -> Result> { - todo!() - } -} - -#[derive(Default)] -pub(crate) struct SimpleSlotWorkerMock -where - B: ParentchainBlockTrait, -{ - pub slot_infos: Vec>, - pub slot_time_spent: Option, -} - -impl SimpleSlotWorker for SimpleSlotWorkerMock -where - B: ParentchainBlockTrait, -{ - type Proposer = ProposerMock; - - type Claim = u64; - - type EpochData = u64; - - type Output = SignedSidechainBlock; - - type ScheduledEnclave = ScheduledEnclaveMock; - - type StateHandler = HandleStateMock; - - fn logging_target(&self) -> &'static str { - "test" - } - - fn get_scheduled_enclave(&mut self) -> Arc { - todo!() - } - - fn get_state_handler(&mut self) -> Arc { - todo!() - } - - fn epoch_data( - &self, - _header: &B::Header, - _shard: ShardIdentifierFor, - _slot: Slot, - ) -> Result { - todo!() - } - - fn authorities_len(&self, _epoch_data: &Self::EpochData) -> Option { - todo!() - } - - fn claim_slot( - &self, - _header: &B::Header, - _slot: Slot, - _epoch_data: &Self::EpochData, - ) -> Option { - todo!() - } - - fn proposer( - &mut self, - _header: B::Header, - _shard: ShardIdentifierFor, - ) -> Result { - todo!() - } - - fn proposing_remaining_duration(&self, _slot_info: &SlotInfo) -> Duration { - todo!() - } - - fn import_integritee_parentchain_blocks_until( - &self, - _last_imported_parentchain_header: &::Hash, - ) -> Result> { - todo!() - } - - fn peek_latest_integritee_parentchain_header(&self) -> Result> { - todo!() - } - - fn import_target_a_parentchain_blocks_until( - &self, - _last_imported_parentchain_header: &::Hash, - ) -> Result> { - todo!() - } - - fn peek_latest_target_a_parentchain_header(&self) -> Result> { - todo!() - } - - fn import_target_b_parentchain_blocks_until( - &self, - _last_imported_parentchain_header: &::Hash, - ) -> Result> { - todo!() - } - - fn peek_latest_target_b_parentchain_header(&self) -> Result> { - todo!() - } - - fn on_slot( - &mut self, - slot_info: SlotInfo, - _shard: ShardIdentifierFor, - _is_single_worker: bool, - ) -> Option> { - self.slot_infos.push(slot_info); - - if let Some(sleep_duration) = self.slot_time_spent { - thread::sleep(sleep_duration); - } - - None - } -} diff --git a/bitacross-worker/sidechain/consensus/slots/src/per_shard_slot_worker_tests.rs b/bitacross-worker/sidechain/consensus/slots/src/per_shard_slot_worker_tests.rs deleted file mode 100644 index b9bcaf92f0..0000000000 --- a/bitacross-worker/sidechain/consensus/slots/src/per_shard_slot_worker_tests.rs +++ /dev/null @@ -1,100 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{mocks::SimpleSlotWorkerMock, PerShardSlotWorkerScheduler, SlotInfo}; -use itc_parentchain_test::ParentchainHeaderBuilder; -use itp_settings::sidechain::SLOT_DURATION; -use itp_time_utils::duration_now; -use itp_types::{Block as ParentchainBlock, ShardIdentifier}; -use its_block_verification::slot::slot_from_timestamp_and_duration; - -type TestSlotWorker = SimpleSlotWorkerMock; - -#[test] -fn slot_timings_are_correct_with_multiple_shards() { - let slot_info = slot_info_from_now(); - let mut slot_worker = - TestSlotWorker { slot_infos: Vec::new(), slot_time_spent: Some(SLOT_DURATION / 10) }; - - let shards = - vec![ShardIdentifier::default(), ShardIdentifier::default(), ShardIdentifier::default()]; - - let _slot_results = PerShardSlotWorkerScheduler::on_slot( - &mut slot_worker, - slot_info.clone(), - shards.clone(), - false, - ); - - assert_eq!(slot_worker.slot_infos.len(), shards.len()); - - // end-time of the first shard slot should not exceed timestamp + 1/(n_shards) of the total slot duration - let first_shard_slot_end_time = slot_worker.slot_infos.first().unwrap().ends_at.as_millis(); - let expected_upper_bound = (slot_info.timestamp.as_millis() - + SLOT_DURATION.as_millis().checked_div(shards.len() as u128).unwrap()) - + 2u128; - assert!( - first_shard_slot_end_time <= expected_upper_bound, - "First shard end time, expected: {}, actual: {}", - expected_upper_bound, - first_shard_slot_end_time - ); - - // none of the shard slot end times should exceed the global slot end time - for shard_slot_info in slot_worker.slot_infos { - assert!( - shard_slot_info.ends_at.as_millis() <= slot_info.ends_at.as_millis(), - "shard slot info ends at: {} ms, total slot info ends at: {} ms", - shard_slot_info.ends_at.as_millis(), - slot_info.ends_at.as_millis() - ); - } -} - -#[test] -fn if_shard_takes_up_all_slot_time_subsequent_shards_are_not_served() { - let slot_info = slot_info_from_now(); - let mut slot_worker = - TestSlotWorker { slot_infos: Vec::new(), slot_time_spent: Some(SLOT_DURATION) }; - - let shards = - vec![ShardIdentifier::default(), ShardIdentifier::default(), ShardIdentifier::default()]; - - let _slot_results = PerShardSlotWorkerScheduler::on_slot( - &mut slot_worker, - slot_info.clone(), - shards.clone(), - false, - ); - - assert_eq!(1, slot_worker.slot_infos.len()); -} - -fn slot_info_from_now() -> SlotInfo { - let timestamp_now = duration_now(); - let slot = slot_from_timestamp_and_duration(timestamp_now, SLOT_DURATION); - let slot_ends_at = timestamp_now + SLOT_DURATION; - SlotInfo::new( - slot, - timestamp_now, - SLOT_DURATION, - slot_ends_at, - ParentchainHeaderBuilder::default().build(), - None, - None, - ) -} diff --git a/bitacross-worker/sidechain/consensus/slots/src/slot_stream.rs b/bitacross-worker/sidechain/consensus/slots/src/slot_stream.rs deleted file mode 100644 index 1c738419bf..0000000000 --- a/bitacross-worker/sidechain/consensus/slots/src/slot_stream.rs +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Slots functionality for Substrate. -//! -//! Some consensus algorithms have a concept of *slots*, which are intervals in -//! time during which certain events can and/or must occur. This crate -//! provides generic functionality for slots. - -use crate::time_until_next_slot; -use futures_timer::Delay; -use std::time::Duration; - -/// Executes given `task` repeatedly when the next slot becomes available. -pub async fn start_slot_worker(task: F, slot_duration: Duration) -where - F: Fn(), -{ - let mut slot_stream = SlotStream::new(slot_duration); - - loop { - slot_stream.next_slot().await; - task(); - } -} - -/// Stream to calculate the slot schedule with. -pub struct SlotStream { - slot_duration: Duration, - inner_delay: Option, -} - -impl SlotStream { - pub fn new(slot_duration: Duration) -> Self { - SlotStream { slot_duration, inner_delay: None } - } -} - -impl SlotStream { - /// Waits for the duration of `inner_delay`. - /// Upon timeout, `inner_delay` is reset according to the time left until next slot. - pub async fn next_slot(&mut self) { - self.inner_delay = match self.inner_delay.take() { - None => { - // Delay is not initialized in this case, - // so we have to initialize with the time until the next slot. - let wait_dur = time_until_next_slot(self.slot_duration); - Some(Delay::new(wait_dur)) - }, - Some(d) => Some(d), - }; - - if let Some(inner_delay) = self.inner_delay.take() { - inner_delay.await; - } - - let ends_in = time_until_next_slot(self.slot_duration); - - // Re-schedule delay for next slot. - self.inner_delay = Some(Delay::new(ends_in)); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::{thread, time::Instant}; - - const SLOT_DURATION: Duration = Duration::from_millis(300); - const SLOT_TOLERANCE: Duration = Duration::from_millis(10); - - #[tokio::test] - async fn short_task_execution_does_not_influence_next_slot() { - let mut slot_stream = SlotStream::new(SLOT_DURATION); - - slot_stream.next_slot().await; - let now = Instant::now(); - // Task execution is shorter than slot duration. - thread::sleep(Duration::from_millis(200)); - slot_stream.next_slot().await; - - let elapsed = now.elapsed(); - assert!(elapsed >= SLOT_DURATION - SLOT_TOLERANCE); - assert!(elapsed <= SLOT_DURATION + SLOT_TOLERANCE); - } - - #[tokio::test] - async fn long_task_execution_does_not_cause_drift() { - let mut slot_stream = SlotStream::new(SLOT_DURATION); - - slot_stream.next_slot().await; - let now = Instant::now(); - // Task execution is longer than slot duration. - thread::sleep(Duration::from_millis(500)); - slot_stream.next_slot().await; - slot_stream.next_slot().await; - - let elapsed = now.elapsed(); - assert!(elapsed >= 2 * SLOT_DURATION - SLOT_TOLERANCE); - assert!(elapsed <= 2 * SLOT_DURATION + SLOT_TOLERANCE); - } -} diff --git a/bitacross-worker/sidechain/consensus/slots/src/slots.rs b/bitacross-worker/sidechain/consensus/slots/src/slots.rs deleted file mode 100644 index 7f8a910a97..0000000000 --- a/bitacross-worker/sidechain/consensus/slots/src/slots.rs +++ /dev/null @@ -1,421 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Utility stream for yielding slots in a loop. -//! -//! This is used instead of `futures_timer::Interval` because it was unreliable. - -use itp_time_utils::duration_now; -use its_block_verification::slot::slot_from_timestamp_and_duration; -use its_consensus_common::Error as ConsensusError; -use its_primitives::traits::{ - Block as SidechainBlockTrait, BlockData, SignedBlock as SignedSidechainBlockTrait, -}; -use lazy_static::lazy_static; -use log::warn; -use sp_runtime::traits::Block as ParentchainBlockTrait; -use std::time::Duration; - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use std::sync::SgxRwLock as RwLock; - -#[cfg(all(feature = "std", not(feature = "sgx")))] -use std::sync::RwLock; - -pub use sp_consensus_slots::Slot; - -/// Returns the duration until the next slot from now. -pub fn time_until_next_slot(slot_duration: Duration) -> Duration { - let now = duration_now().as_millis(); - - if slot_duration.as_millis() == u128::default() { - log::warn!("[Slots]: slot_duration.as_millis() is 0"); - return Default::default() - } - - let next_slot = (now + slot_duration.as_millis()) / slot_duration.as_millis(); - let remaining_millis = next_slot * slot_duration.as_millis() - now; - Duration::from_millis(remaining_millis as u64) -} - -/// Information about a slot. -#[derive(Debug, Clone)] -pub struct SlotInfo { - /// The slot number as found in the inherent data. - pub slot: Slot, - /// Current timestamp as found in the inherent data. - pub timestamp: Duration, - /// Slot duration. - pub duration: Duration, - /// The time at which the slot ends. - pub ends_at: Duration, - /// Last imported parentchain header, potentially outdated. - pub last_imported_integritee_parentchain_head: ParentchainBlock::Header, - /// Last imported parentchain header, potentially outdated. - pub maybe_last_imported_target_a_parentchain_head: Option, - /// Last imported parentchain header, potentially outdated. - pub maybe_last_imported_target_b_parentchain_head: Option, -} - -impl SlotInfo { - /// Create a new [`SlotInfo`]. - /// - /// `ends_at` is calculated using `now` and `time_until_next_slot`. - pub fn new( - slot: Slot, - timestamp: Duration, - duration: Duration, - ends_at: Duration, - last_imported_integritee_parentchain_head: ParentchainBlock::Header, - maybe_last_imported_target_a_parentchain_head: Option, - maybe_last_imported_target_b_parentchain_head: Option, - ) -> Self { - Self { - slot, - timestamp, - duration, - ends_at, - last_imported_integritee_parentchain_head, - maybe_last_imported_target_a_parentchain_head, - maybe_last_imported_target_b_parentchain_head, - } - } - - pub fn duration_remaining(&self) -> Option { - let duration_now = duration_now(); - if self.ends_at <= duration_now { - return None - } - Some(self.ends_at - duration_now) - } -} - -/// The time at which the slot ends. -/// -/// !! Slot duration needs to be the 'global' slot duration that is used for the sidechain. -/// Do not use this with 'custom' slot durations, as used e.g. for the shard slots. -pub fn slot_ends_at(slot: Slot, slot_duration: Duration) -> Duration { - Duration::from_millis(*slot.saturating_add(1u64) * (slot_duration.as_millis() as u64)) -} - -#[allow(dead_code)] -pub(crate) fn timestamp_within_slot< - ParentchainBlock: ParentchainBlockTrait, - SignedSidechainBlock: SignedSidechainBlockTrait, ->( - slot: &SlotInfo, - proposal: &SignedSidechainBlock, -) -> bool { - let proposal_stamp = proposal.block().block_data().timestamp(); - - let is_within_slot = slot.timestamp.as_millis() as u64 <= proposal_stamp - && slot.ends_at.as_millis() as u64 >= proposal_stamp; - - if !is_within_slot { - warn!( - "Proposed block slot time: {} ms, slot start: {} ms , slot end: {} ms", - proposal_stamp, - slot.timestamp.as_millis(), - slot.ends_at.as_millis() - ); - } - - is_within_slot -} - -pub fn yield_next_slot( - timestamp: Duration, - duration: Duration, - integritee_header: ParentchainBlock::Header, - maybe_target_a_header: Option, - maybe_target_b_header: Option, - last_slot_getter: &mut SlotGetter, -) -> Result>, ConsensusError> -where - SlotGetter: LastSlotTrait, - ParentchainBlock: ParentchainBlockTrait, -{ - if duration == Default::default() { - return Err(ConsensusError::Other("Tried to yield next slot with 0 duration".into())) - } - - let last_slot = last_slot_getter.get_last_slot()?; - let slot = slot_from_timestamp_and_duration(timestamp, duration); - - if slot <= last_slot { - return Ok(None) - } - - last_slot_getter.set_last_slot(slot)?; - - let slot_ends_time = slot_ends_at(slot, duration); - Ok(Some(SlotInfo::new( - slot, - timestamp, - duration, - slot_ends_time, - integritee_header, - maybe_target_a_header, - maybe_target_b_header, - ))) -} - -pub trait LastSlotTrait { - fn get_last_slot(&self) -> Result; - fn set_last_slot(&mut self, slot: Slot) -> Result<(), ConsensusError>; -} - -pub struct LastSlot; - -lazy_static! { - static ref LAST_SLOT: RwLock = Default::default(); -} - -impl LastSlotTrait for LastSlot { - fn get_last_slot(&self) -> Result { - Ok(*LAST_SLOT.read().map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?) - } - - fn set_last_slot(&mut self, slot: Slot) -> Result<(), ConsensusError> { - *LAST_SLOT - .write() - .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))? = slot; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use core::assert_matches::assert_matches; - use itc_parentchain_test::ParentchainHeaderBuilder; - use itp_types::Block as ParentchainBlock; - use its_primitives::{ - traits::{Block as BlockT, SignBlock}, - types::block::{Block, SignedBlock}, - }; - use its_test::{ - sidechain_block_data_builder::SidechainBlockDataBuilder, - sidechain_header_builder::SidechainHeaderBuilder, - }; - use sp_keyring::ed25519::Keyring; - use std::{fmt::Debug, thread, time::SystemTime}; - - const SLOT_DURATION: Duration = Duration::from_millis(1000); - const ALLOWED_THRESHOLD: Duration = Duration::from_millis(1); - - fn test_block_with_time_stamp(timestamp: u64) -> SignedBlock { - let header = SidechainHeaderBuilder::default().build(); - - let block_data = SidechainBlockDataBuilder::default().with_timestamp(timestamp).build(); - - Block::new(header, block_data).sign_block(&Keyring::Alice.pair()) - } - - fn slot(slot: u64) -> SlotInfo { - SlotInfo { - slot: slot.into(), - timestamp: duration_now(), - duration: SLOT_DURATION, - ends_at: duration_now() + SLOT_DURATION, - last_imported_integritee_parentchain_head: ParentchainHeaderBuilder::default().build(), - maybe_last_imported_target_a_parentchain_head: None, - maybe_last_imported_target_b_parentchain_head: None, - } - } - - fn timestamp_in_the_future(later: Duration) -> u64 { - let moment = SystemTime::now() + later; - let dur = moment.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_else(|e| { - panic!("Current time {:?} is before unix epoch. Something is wrong: {:?}", moment, e) - }); - dur.as_millis() as u64 - } - - fn timestamp_in_the_past(earlier: Duration) -> u64 { - let moment = SystemTime::now() - earlier; - let dur = moment.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_else(|e| { - panic!("Current time {:?} is before unix epoch. Something is wrong: {:?}", moment, e) - }); - dur.as_millis() as u64 - } - - fn assert_consensus_other_err(result: Result, msg: &str) { - assert_matches!(result.unwrap_err(), ConsensusError::Other( - m, - ) if m.to_string() == msg) - } - - #[test] - fn time_until_next_slot_returns_default_on_nano_duration() { - // prevent panic: https://github.com/integritee-network/worker/issues/439 - assert_eq!(time_until_next_slot(Duration::from_nanos(999)), Default::default()) - } - - #[test] - fn slot_info_ends_at_does_not_change_after_second_calculation() { - let timestamp = duration_now(); - let pc_header = ParentchainHeaderBuilder::default().build(); - let slot: Slot = 1000.into(); - - let slot_end_time = slot_ends_at(slot, SLOT_DURATION); - let slot_one: SlotInfo = SlotInfo::new( - slot, - timestamp, - SLOT_DURATION, - slot_end_time, - pc_header.clone(), - None, - None, - ); - thread::sleep(Duration::from_millis(200)); - let slot_two: SlotInfo = - SlotInfo::new(slot, timestamp, SLOT_DURATION, slot_end_time, pc_header, None, None); - - let difference_of_ends_at = - (slot_one.ends_at.as_millis()).abs_diff(slot_two.ends_at.as_millis()); - - assert!( - difference_of_ends_at < ALLOWED_THRESHOLD.as_millis(), - "Diff in ends at timestamp: {} ms, tolerance: {} ms", - difference_of_ends_at, - ALLOWED_THRESHOLD.as_millis() - ); - } - - #[test] - fn duration_remaing_returns_none_if_ends_at_is_in_the_past() { - let slot: SlotInfo = SlotInfo { - slot: 1.into(), - timestamp: duration_now() - Duration::from_secs(5), - duration: SLOT_DURATION, - ends_at: duration_now() + SLOT_DURATION - Duration::from_secs(5), - last_imported_integritee_parentchain_head: ParentchainHeaderBuilder::default().build(), - maybe_last_imported_target_a_parentchain_head: None, - maybe_last_imported_target_b_parentchain_head: None, - }; - assert!(slot.duration_remaining().is_none()); - } - - #[test] - fn duration_remaining_returns_some_if_ends_at_is_in_the_future() { - let slot: SlotInfo = SlotInfo { - slot: 1.into(), - timestamp: duration_now() - Duration::from_secs(5), - duration: SLOT_DURATION, - ends_at: duration_now() + Duration::from_secs(60), - last_imported_integritee_parentchain_head: ParentchainHeaderBuilder::default().build(), - maybe_last_imported_target_a_parentchain_head: None, - maybe_last_imported_target_b_parentchain_head: None, - }; - let maybe_duration_remaining = slot.duration_remaining(); - assert!(maybe_duration_remaining.is_some()); - assert!(maybe_duration_remaining.unwrap() > Duration::from_secs(30)); - } - - #[test] - fn slot_info_ends_at_does_is_correct_even_if_delay_is_more_than_slot_duration() { - let timestamp = duration_now(); - let pc_header = ParentchainHeaderBuilder::default().build(); - let slot: Slot = 1000.into(); - let slot_end_time = slot_ends_at(slot, SLOT_DURATION); - - thread::sleep(SLOT_DURATION * 2); - let slot: SlotInfo = - SlotInfo::new(slot, timestamp, SLOT_DURATION, slot_end_time, pc_header, None, None); - - assert!(slot.ends_at < duration_now()); - } - - #[test] - fn timestamp_within_slot_returns_true_for_correct_timestamp() { - let slot = slot(1); - let time_stamp_in_slot = timestamp_in_the_future(SLOT_DURATION / 2); - - let block = test_block_with_time_stamp(time_stamp_in_slot); - - assert!(timestamp_within_slot(&slot, &block)); - } - - #[test] - fn timestamp_within_slot_returns_false_if_timestamp_after_slot() { - let slot = slot(1); - let time_stamp_after_slot = - timestamp_in_the_future(SLOT_DURATION + Duration::from_millis(10)); - - let block_too_late = test_block_with_time_stamp(time_stamp_after_slot); - - assert!(!timestamp_within_slot(&slot, &block_too_late)); - } - - #[test] - fn timestamp_within_slot_returns_false_if_timestamp_before_slot() { - let slot = slot(1); - let time_stamp_before_slot = timestamp_in_the_past(Duration::from_millis(10)); - - let block_too_early = test_block_with_time_stamp(time_stamp_before_slot); - - assert!(!timestamp_within_slot(&slot, &block_too_early)); - } - - #[test] - fn yield_next_slot_returns_none_when_slot_equals_last_slot() { - let _lock = - LastSlot.set_last_slot(slot_from_timestamp_and_duration(duration_now(), SLOT_DURATION)); - assert!(yield_next_slot::<_, ParentchainBlock>( - duration_now(), - SLOT_DURATION, - ParentchainHeaderBuilder::default().build(), - None, - None, - &mut LastSlot, - ) - .unwrap() - .is_none()) - } - - #[test] - fn yield_next_slot_returns_next_slot() { - let _lock = - LastSlot.set_last_slot(slot_from_timestamp_and_duration(duration_now(), SLOT_DURATION)); - assert!(yield_next_slot::<_, ParentchainBlock>( - duration_now() + SLOT_DURATION, - SLOT_DURATION, - ParentchainHeaderBuilder::default().build(), - None, - None, - &mut LastSlot - ) - .unwrap() - .is_some()) - } - - #[test] - fn yield_next_slot_returns_err_on_0_duration() { - assert_consensus_other_err( - yield_next_slot::<_, ParentchainBlock>( - duration_now(), - Default::default(), - ParentchainHeaderBuilder::default().build(), - None, - None, - &mut LastSlot, - ), - "Tried to yield next slot with 0 duration", - ) - } -} diff --git a/bitacross-worker/sidechain/fork-tree/Cargo.toml b/bitacross-worker/sidechain/fork-tree/Cargo.toml deleted file mode 100644 index 6b9c4fc561..0000000000 --- a/bitacross-worker/sidechain/fork-tree/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "fork-tree" -version = "3.0.0" -authors = ["Parity Technologies "] -edition = "2021" -license = "Apache-2.0" -homepage = "https://substrate.io" -repository = "https://github.com/paritytech/substrate/" -description = "Utility library for managing tree-like ordered data with logic for pruning the tree while finalizing nodes." -documentation = "https://docs.rs/fork-tree" -readme = "README.md" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.2.2", features = ["derive"], default-features = false } - -# sgx deps -sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } - -[features] -default = ["std"] -std = [ - "codec/std", -] -sgx = [ - # teaclave - "sgx_tstd", -] diff --git a/bitacross-worker/sidechain/fork-tree/src/lib.rs b/bitacross-worker/sidechain/fork-tree/src/lib.rs deleted file mode 100644 index 0af11b653b..0000000000 --- a/bitacross-worker/sidechain/fork-tree/src/lib.rs +++ /dev/null @@ -1,1552 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Utility library for managing tree-like ordered data with logic for pruning -//! the tree while finalizing nodes. - -#![cfg_attr(not(feature = "std"), no_std)] -#![warn(missing_docs)] - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use std::vec::Vec; - -use codec::{Decode, Encode}; -use core::cmp::Reverse; - -/// Error occurred when iterating with the tree. -#[derive(Clone, Debug, PartialEq)] -pub enum Error { - /// Adding duplicate node to tree. - Duplicate, - /// Finalizing descendent of tree node without finalizing ancestor(s). - UnfinalizedAncestor, - /// Imported or finalized node that is an ancestor of previously finalized node. - Revert, - /// Error throw by client when checking for node ancestry. - Client(E), -} - -impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let message = match *self { - Error::Duplicate => "Hash already exists in Tree".into(), - Error::UnfinalizedAncestor => "Finalized descendent of Tree node without finalizing its ancestor(s) first".into(), - Error::Revert => "Tried to import or finalize node that is an ancestor of a previously finalized node".into(), - Error::Client(ref err) => format!("Client error: {}", err), - }; - write!(f, "{}", message) - } -} - -impl std::error::Error for Error { - fn cause(&self) -> Option<&dyn std::error::Error> { - None - } -} - -impl From for Error { - fn from(err: E) -> Error { - Error::Client(err) - } -} - -/// Result of finalizing a node (that could be a part of the tree or not). -#[derive(Debug, PartialEq)] -pub enum FinalizationResult { - /// The tree has changed, optionally return the value associated with the finalized node. - Changed(Option), - /// The tree has not changed. - Unchanged, -} - -/// Filtering action. -#[derive(Debug, PartialEq)] -pub enum FilterAction { - /// Remove the node and its subtree. - Remove, - /// Maintain the node. - KeepNode, - /// Maintain the node and its subtree. - KeepTree, -} - -/// A tree data structure that stores several nodes across multiple branches. -/// -/// Top-level branches are called roots. The tree has functionality for -/// finalizing nodes, which means that that node is traversed, and all competing -/// branches are pruned. It also guarantees that nodes in the tree are finalized -/// in order. Each node is uniquely identified by its hash but can be ordered by -/// its number. In order to build the tree an external function must be provided -/// when interacting with the tree to establish a node's ancestry. -#[derive(Clone, Debug, Decode, Encode, PartialEq)] -pub struct ForkTree { - roots: Vec>, - best_finalized_number: Option, -} - -impl Default for ForkTree { - fn default() -> ForkTree { - ForkTree { roots: Vec::new(), best_finalized_number: None } - } -} - -impl ForkTree -where - H: PartialEq, - N: Ord, -{ - /// Create a new empty tree. - pub fn new() -> ForkTree { - ForkTree { roots: Vec::new(), best_finalized_number: None } - } - - /// Rebalance the tree, i.e. sort child nodes by max branch depth (decreasing). - /// - /// Most operations in the tree are performed with depth-first search - /// starting from the leftmost node at every level, since this tree is meant - /// to be used in a blockchain context, a good heuristic is that the node - /// we'll be looking for at any point will likely be in one of the deepest chains - /// (i.e. the longest ones). - pub fn rebalance(&mut self) { - self.roots.sort_by_key(|n| Reverse(n.max_depth())); - let mut stack: Vec<_> = self.roots.iter_mut().collect(); - while let Some(node) = stack.pop() { - node.children.sort_by_key(|n| Reverse(n.max_depth())); - stack.extend(node.children.iter_mut()); - } - } - - /// Import a new node into the tree. The given function `is_descendent_of` - /// should return `true` if the second hash (target) is a descendent of the - /// first hash (base). This method assumes that nodes in the same branch are - /// imported in order. - /// - /// Returns `true` if the imported node is a root. - // WARNING: some users of this method (i.e. consensus epoch changes tree) currently silently - // rely on a **post-order DFS** traversal. If we are using instead a top-down traversal method - // then the `is_descendent_of` closure, when used after a warp-sync, may end up querying the - // backend for a block (the one corresponding to the root) that is not present and thus will - // return a wrong result. - pub fn import( - &mut self, - hash: H, - number: N, - data: V, - is_descendent_of: &F, - ) -> Result> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - H: std::fmt::Debug, - { - if let Some(ref best_finalized_number) = self.best_finalized_number { - if number <= *best_finalized_number { - return Err(Error::Revert) - } - } - - let (children, is_root) = - match self.find_node_where_mut(&hash, &number, is_descendent_of, &|_| true)? { - Some(parent) => (&mut parent.children, false), - None => (&mut self.roots, true), - }; - - if children.iter().any(|elem| elem.hash == hash) { - return Err(Error::Duplicate) - } - - children.push(Node { data, hash, number, children: Default::default() }); - - if children.len() == 1 { - // Rebalance may be required only if we've extended the branch depth. - self.rebalance(); - } - - Ok(is_root) - } - - /// Iterates over the existing roots in the tree. - pub fn roots(&self) -> impl Iterator { - self.roots.iter().map(|node| (&node.hash, &node.number, &node.data)) - } - - /// Iterates over the roots and gives just the hash and block number - pub fn roots_hash_and_number(&self) -> Vec<(&H, &N)> { - self.roots.iter().map(|node| (&node.hash, &node.number)).collect::>() - } - - fn node_iter(&self) -> impl Iterator> { - // we need to reverse the order of roots to maintain the expected - // ordering since the iterator uses a stack to track state. - ForkTreeIterator { stack: self.roots.iter().rev().collect() } - } - - /// Iterates the nodes in the tree in pre-order. - pub fn iter(&self) -> impl Iterator { - self.node_iter().map(|node| (&node.hash, &node.number, &node.data)) - } - - /// Map fork tree into values of new types. - /// - /// Tree traversal technique (e.g. BFS vs DFS) is left as not specified and - /// may be subject to change in the future. In other words, your predicates - /// should not rely on the observed traversal technique currently in use. - pub fn map(self, f: &mut F) -> ForkTree - where - F: FnMut(&H, &N, V) -> VT, - { - let mut queue: Vec<_> = - self.roots.into_iter().rev().map(|node| (usize::MAX, node)).collect(); - let mut next_queue = Vec::new(); - let mut output = Vec::new(); - - while !queue.is_empty() { - for (parent_index, node) in queue.drain(..) { - let new_data = f(&node.hash, &node.number, node.data); - let new_node = Node { - hash: node.hash, - number: node.number, - data: new_data, - children: Vec::with_capacity(node.children.len()), - }; - - let node_id = output.len(); - output.push((parent_index, new_node)); - - for child in node.children.into_iter().rev() { - next_queue.push((node_id, child)); - } - } - - std::mem::swap(&mut queue, &mut next_queue); - } - - let mut roots = Vec::new(); - while let Some((parent_index, new_node)) = output.pop() { - if parent_index == usize::MAX { - roots.push(new_node); - } else { - output[parent_index].1.children.push(new_node); - } - } - - ForkTree { roots, best_finalized_number: self.best_finalized_number } - } - - /// Find a node in the tree that is the deepest ancestor of the given - /// block hash and which passes the given predicate. The given function - /// `is_descendent_of` should return `true` if the second hash (target) - /// is a descendent of the first hash (base). - pub fn find_node_where( - &self, - hash: &H, - number: &N, - is_descendent_of: &F, - predicate: &P, - ) -> Result>, Error> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - let maybe_path = self.find_node_index_where(hash, number, is_descendent_of, predicate)?; - Ok(maybe_path.map(|path| { - let children = - path.iter().take(path.len() - 1).fold(&self.roots, |curr, &i| &curr[i].children); - &children[path[path.len() - 1]] - })) - } - - /// Same as [`find_node_where`](ForkTree::find_node_where), but returns mutable reference. - pub fn find_node_where_mut( - &mut self, - hash: &H, - number: &N, - is_descendent_of: &F, - predicate: &P, - ) -> Result>, Error> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - let maybe_path = self.find_node_index_where(hash, number, is_descendent_of, predicate)?; - Ok(maybe_path.map(|path| { - let children = path - .iter() - .take(path.len() - 1) - .fold(&mut self.roots, |curr, &i| &mut curr[i].children); - &mut children[path[path.len() - 1]] - })) - } - - /// Same as [`find_node_where`](ForkTree::find_node_where), but returns indices. - /// - /// The returned indices represent the full path to reach the matching node starting - /// from first to last, i.e. the earliest index in the traverse path goes first, and the final - /// index in the traverse path goes last. If a node is found that matches the predicate - /// the returned path should always contain at least one index, otherwise `None` is - /// returned. - // WARNING: some users of this method (i.e. consensus epoch changes tree) currently silently - // rely on a **post-order DFS** traversal. If we are using instead a top-down traversal method - // then the `is_descendent_of` closure, when used after a warp-sync, will end up querying the - // backend for a block (the one corresponding to the root) that is not present and thus will - // return a wrong result. - pub fn find_node_index_where( - &self, - hash: &H, - number: &N, - is_descendent_of: &F, - predicate: &P, - ) -> Result>, Error> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - let mut stack = vec![]; - let mut root_idx = 0; - let mut found = false; - let mut is_descendent = false; - - while root_idx < self.roots.len() { - if *number <= self.roots[root_idx].number { - root_idx += 1; - continue - } - // The second element in the stack tuple tracks what is the **next** children - // index to search into. If we find an ancestor then we stop searching into - // alternative branches and we focus on the current path up to the root. - stack.push((&self.roots[root_idx], 0)); - while let Some((node, i)) = stack.pop() { - if i < node.children.len() && !is_descendent { - stack.push((node, i + 1)); - if node.children[i].number < *number { - stack.push((&node.children[i], 0)); - } - } else if is_descendent || is_descendent_of(&node.hash, hash)? { - is_descendent = true; - if predicate(&node.data) { - found = true; - break - } - } - } - - // If the element we are looking for is a descendent of the current root - // then we can stop the search. - if is_descendent { - break - } - root_idx += 1; - } - - Ok(if found { - // The path is the root index followed by the indices of all the children - // we were processing when we found the element (remember the stack - // contains the index of the **next** children to process). - let path: Vec<_> = - std::iter::once(root_idx).chain(stack.iter().map(|(_, i)| *i - 1)).collect(); - Some(path) - } else { - None - }) - } - - /// Prune the tree, removing all non-canonical nodes. We find the node in the - /// tree that is the deepest ancestor of the given hash and that passes the - /// given predicate. If such a node exists, we re-root the tree to this - /// node. Otherwise the tree remains unchanged. The given function - /// `is_descendent_of` should return `true` if the second hash (target) is a - /// descendent of the first hash (base). - /// - /// Returns all pruned node data. - pub fn prune( - &mut self, - hash: &H, - number: &N, - is_descendent_of: &F, - predicate: &P, - ) -> Result, Error> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - let root_index = - match self.find_node_index_where(hash, number, is_descendent_of, predicate)? { - Some(idx) => idx, - None => return Ok(RemovedIterator { stack: Vec::new() }), - }; - - let mut old_roots = std::mem::take(&mut self.roots); - - let curr_children = root_index - .iter() - .take(root_index.len() - 1) - .fold(&mut old_roots, |curr, idx| &mut curr[*idx].children); - let mut root = curr_children.remove(root_index[root_index.len() - 1]); - - let mut removed = old_roots; - - // we found the deepest ancestor of the finalized block, so we prune - // out any children that don't include the finalized block. - let root_children = std::mem::take(&mut root.children); - let mut is_first = true; - - for child in root_children { - if is_first - && (child.number == *number && child.hash == *hash - || child.number < *number && is_descendent_of(&child.hash, hash)?) - { - root.children.push(child); - // assuming that the tree is well formed only one child should pass this - // requirement due to ancestry restrictions (i.e. they must be different forks). - is_first = false; - } else { - removed.push(child); - } - } - - self.roots = vec![root]; - self.rebalance(); - - Ok(RemovedIterator { stack: removed }) - } - - /// Finalize a root in the tree and return it, return `None` in case no root - /// with the given hash exists. All other roots are pruned, and the children - /// of the finalized node become the new roots. - pub fn finalize_root(&mut self, hash: &H) -> Option { - self.roots - .iter() - .position(|node| node.hash == *hash) - .map(|position| self.finalize_root_at(position)) - } - - /// Finalize root at given position. See `finalize_root` comment for details. - fn finalize_root_at(&mut self, position: usize) -> V { - let node = self.roots.swap_remove(position); - self.roots = node.children; - self.best_finalized_number = Some(node.number); - node.data - } - - /// Finalize a node in the tree. This method will make sure that the node - /// being finalized is either an existing root (and return its data), or a - /// node from a competing branch (not in the tree), tree pruning is done - /// accordingly. The given function `is_descendent_of` should return `true` - /// if the second hash (target) is a descendent of the first hash (base). - pub fn finalize( - &mut self, - hash: &H, - number: N, - is_descendent_of: &F, - ) -> Result, Error> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - { - if let Some(ref best_finalized_number) = self.best_finalized_number { - if number <= *best_finalized_number { - return Err(Error::Revert) - } - } - - // check if one of the current roots is being finalized - if let Some(root) = self.finalize_root(hash) { - return Ok(FinalizationResult::Changed(Some(root))) - } - - // make sure we're not finalizing a descendent of any root - for root in self.roots.iter() { - if number > root.number && is_descendent_of(&root.hash, hash)? { - return Err(Error::UnfinalizedAncestor) - } - } - - // we finalized a block earlier than any existing root (or possibly - // another fork not part of the tree). make sure to only keep roots that - // are part of the finalized branch - let mut changed = false; - let roots = std::mem::take(&mut self.roots); - - for root in roots { - if root.number > number && is_descendent_of(hash, &root.hash)? { - self.roots.push(root); - } else { - changed = true; - } - } - - self.best_finalized_number = Some(number); - - if changed { - Ok(FinalizationResult::Changed(None)) - } else { - Ok(FinalizationResult::Unchanged) - } - } - - /// Finalize a node in the tree and all its ancestors. The given function - /// `is_descendent_of` should return `true` if the second hash (target) is - // a descendent of the first hash (base). - pub fn finalize_with_ancestors( - &mut self, - hash: &H, - number: N, - is_descendent_of: &F, - ) -> Result, Error> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - { - if let Some(ref best_finalized_number) = self.best_finalized_number { - if number <= *best_finalized_number { - return Err(Error::Revert) - } - } - - // check if one of the current roots is being finalized - if let Some(root) = self.finalize_root(hash) { - return Ok(FinalizationResult::Changed(Some(root))) - } - - // we need to: - // 1) remove all roots that are not ancestors AND not descendants of finalized block; - // 2) if node is descendant - just leave it; - // 3) if node is ancestor - 'open it' - let mut changed = false; - let mut idx = 0; - while idx != self.roots.len() { - let (is_finalized, is_descendant, is_ancestor) = { - let root = &self.roots[idx]; - let is_finalized = root.hash == *hash; - let is_descendant = - !is_finalized && root.number > number && is_descendent_of(hash, &root.hash)?; - let is_ancestor = !is_finalized - && !is_descendant && root.number < number - && is_descendent_of(&root.hash, hash)?; - (is_finalized, is_descendant, is_ancestor) - }; - - // if we have met finalized root - open it and return - if is_finalized { - return Ok(FinalizationResult::Changed(Some(self.finalize_root_at(idx)))) - } - - // if node is descendant of finalized block - just leave it as is - if is_descendant { - idx += 1; - continue - } - - // if node is ancestor of finalized block - remove it and continue with children - if is_ancestor { - let root = self.roots.swap_remove(idx); - self.roots.extend(root.children); - changed = true; - continue - } - - // if node is neither ancestor, nor descendant of the finalized block - remove it - self.roots.swap_remove(idx); - changed = true; - } - - self.best_finalized_number = Some(number); - - if changed { - Ok(FinalizationResult::Changed(None)) - } else { - Ok(FinalizationResult::Unchanged) - } - } - - /// Checks if any node in the tree is finalized by either finalizing the - /// node itself or a node's descendent that's not in the tree, guaranteeing - /// that the node being finalized isn't a descendent of (or equal to) any of - /// the node's children. Returns `Some(true)` if the node being finalized is - /// a root, `Some(false)` if the node being finalized is not a root, and - /// `None` if no node in the tree is finalized. The given `predicate` is - /// checked on the prospective finalized root and must pass for finalization - /// to occur. The given function `is_descendent_of` should return `true` if - /// the second hash (target) is a descendent of the first hash (base). - pub fn finalizes_any_with_descendent_if( - &self, - hash: &H, - number: N, - is_descendent_of: &F, - predicate: P, - ) -> Result, Error> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - if let Some(ref best_finalized_number) = self.best_finalized_number { - if number <= *best_finalized_number { - return Err(Error::Revert) - } - } - - // check if the given hash is equal or a descendent of any node in the - // tree, if we find a valid node that passes the predicate then we must - // ensure that we're not finalizing past any of its child nodes. - for node in self.node_iter() { - if predicate(&node.data) && (node.hash == *hash || is_descendent_of(&node.hash, hash)?) - { - for child in node.children.iter() { - if child.number <= number - && (child.hash == *hash || is_descendent_of(&child.hash, hash)?) - { - return Err(Error::UnfinalizedAncestor) - } - } - - return Ok(Some(self.roots.iter().any(|root| root.hash == node.hash))) - } - } - - Ok(None) - } - - /// Finalize a root in the tree by either finalizing the node itself or a - /// node's descendent that's not in the tree, guaranteeing that the node - /// being finalized isn't a descendent of (or equal to) any of the root's - /// children. The given `predicate` is checked on the prospective finalized - /// root and must pass for finalization to occur. The given function - /// `is_descendent_of` should return `true` if the second hash (target) is a - /// descendent of the first hash (base). - pub fn finalize_with_descendent_if( - &mut self, - hash: &H, - number: N, - is_descendent_of: &F, - predicate: P, - ) -> Result, Error> - where - E: std::error::Error, - F: Fn(&H, &H) -> Result, - P: Fn(&V) -> bool, - { - if let Some(ref best_finalized_number) = self.best_finalized_number { - if number <= *best_finalized_number { - return Err(Error::Revert) - } - } - - // check if the given hash is equal or a a descendent of any root, if we - // find a valid root that passes the predicate then we must ensure that - // we're not finalizing past any children node. - let mut position = None; - for (i, root) in self.roots.iter().enumerate() { - if predicate(&root.data) && (root.hash == *hash || is_descendent_of(&root.hash, hash)?) - { - for child in root.children.iter() { - if child.number <= number - && (child.hash == *hash || is_descendent_of(&child.hash, hash)?) - { - return Err(Error::UnfinalizedAncestor) - } - } - - position = Some(i); - break - } - } - - let node_data = position.map(|i| { - let node = self.roots.swap_remove(i); - self.roots = node.children; - self.best_finalized_number = Some(node.number); - node.data - }); - - // Retain only roots that are descendents of the finalized block (this - // happens if the node has been properly finalized) or that are - // ancestors (or equal) to the finalized block (in this case the node - // wasn't finalized earlier presumably because the predicate didn't - // pass). - let mut changed = false; - let roots = std::mem::take(&mut self.roots); - - for root in roots { - let retain = root.number > number && is_descendent_of(hash, &root.hash)? - || root.number == number && root.hash == *hash - || is_descendent_of(&root.hash, hash)?; - - if retain { - self.roots.push(root); - } else { - changed = true; - } - } - - self.best_finalized_number = Some(number); - - match (node_data, changed) { - (Some(data), _) => Ok(FinalizationResult::Changed(Some(data))), - (None, true) => Ok(FinalizationResult::Changed(None)), - (None, false) => Ok(FinalizationResult::Unchanged), - } - } - - /// Remove from the tree some nodes (and their subtrees) using a `filter` predicate. - /// - /// The `filter` is called over tree nodes and returns a filter action: - /// - `Remove` if the node and its subtree should be removed; - /// - `KeepNode` if we should maintain the node and keep processing the tree. - /// - `KeepTree` if we should maintain the node and its entire subtree. - /// - /// An iterator over all the pruned nodes is returned. - pub fn drain_filter(&mut self, filter: F) -> impl Iterator - where - F: Fn(&H, &N, &V) -> FilterAction, - { - let mut removed = vec![]; - let mut retained = Vec::new(); - - let mut queue: Vec<_> = std::mem::take(&mut self.roots) - .into_iter() - .rev() - .map(|node| (usize::MAX, node)) - .collect(); - let mut next_queue = Vec::new(); - - while !queue.is_empty() { - for (parent_idx, mut node) in queue.drain(..) { - match filter(&node.hash, &node.number, &node.data) { - FilterAction::KeepNode => { - let node_idx = retained.len(); - let children = std::mem::take(&mut node.children); - retained.push((parent_idx, node)); - for child in children.into_iter().rev() { - next_queue.push((node_idx, child)); - } - }, - FilterAction::KeepTree => { - retained.push((parent_idx, node)); - }, - FilterAction::Remove => { - removed.push(node); - }, - } - } - - std::mem::swap(&mut queue, &mut next_queue); - } - - while let Some((parent_idx, node)) = retained.pop() { - if parent_idx == usize::MAX { - self.roots.push(node); - } else { - retained[parent_idx].1.children.push(node); - } - } - - if !removed.is_empty() { - self.rebalance(); - } - RemovedIterator { stack: removed } - } -} - -// Workaround for: https://github.com/rust-lang/rust/issues/34537 -use node_implementation::Node; - -mod node_implementation { - use super::*; - - #[derive(Clone, Debug, Decode, Encode, PartialEq)] - pub struct Node { - pub hash: H, - pub number: N, - pub data: V, - pub children: Vec>, - } - - impl Node { - /// Finds the max depth among all branches descendent from this node. - pub fn max_depth(&self) -> usize { - let mut max: usize = 0; - let mut stack = vec![(self, 0)]; - while let Some((node, height)) = stack.pop() { - if height > max { - max = height; - } - node.children.iter().for_each(|n| stack.push((n, height + 1))); - } - max - } - } -} - -struct ForkTreeIterator<'a, H, N, V> { - stack: Vec<&'a Node>, -} - -impl<'a, H, N, V> Iterator for ForkTreeIterator<'a, H, N, V> { - type Item = &'a Node; - - fn next(&mut self) -> Option { - self.stack.pop().map(|node| { - // child nodes are stored ordered by max branch height (decreasing), - // we want to keep this ordering while iterating but since we're - // using a stack for iterator state we need to reverse it. - self.stack.extend(node.children.iter().rev()); - node - }) - } -} - -struct RemovedIterator { - stack: Vec>, -} - -impl Iterator for RemovedIterator { - type Item = (H, N, V); - - fn next(&mut self) -> Option { - self.stack.pop().map(|mut node| { - // child nodes are stored ordered by max branch height (decreasing), - // we want to keep this ordering while iterating but since we're - // using a stack for iterator state we need to reverse it. - let children = std::mem::take(&mut node.children); - - self.stack.extend(children.into_iter().rev()); - (node.hash, node.number, node.data) - }) - } -} - -#[cfg(test)] -mod test { - use crate::FilterAction; - - use super::{Error, FinalizationResult, ForkTree}; - - #[derive(Debug, PartialEq)] - struct TestError; - - impl std::fmt::Display for TestError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "TestError") - } - } - - impl std::error::Error for TestError {} - - fn test_fork_tree<'a>( - ) -> (ForkTree<&'a str, u64, ()>, impl Fn(&&str, &&str) -> Result) { - let mut tree = ForkTree::new(); - - #[rustfmt::skip] - // - // - B - C - D - E - // / - // / - G - // / / - // A - F - H - I - // \ \ - // \ - L - M - N - // \ \ - // \ - O - // - J - K - // - // (where N is not a part of fork tree) - // - // NOTE: the tree will get automatically rebalance on import and won't be laid out like the - // diagram above. the children will be ordered by subtree depth and the longest branches - // will be on the leftmost side of the tree. - let is_descendent_of = |base: &&str, block: &&str| -> Result { - let letters = vec!["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O"]; - match (*base, *block) { - ("A", b) => Ok(letters.into_iter().any(|n| n == b)), - ("B", b) => Ok(b == "C" || b == "D" || b == "E"), - ("C", b) => Ok(b == "D" || b == "E"), - ("D", b) => Ok(b == "E"), - ("E", _) => Ok(false), - ("F", b) => - Ok(b == "G" || b == "H" || b == "I" || b == "L" || b == "M" || b == "N" || b == "O"), - ("G", _) => Ok(false), - ("H", b) => Ok(b == "I" || b == "L" || b == "M" || b == "N" || b == "O"), - ("I", _) => Ok(false), - ("J", b) => Ok(b == "K"), - ("K", _) => Ok(false), - ("L", b) => Ok(b == "M" || b == "O" || b == "N"), - ("M", b) => Ok(b == "N"), - ("O", _) => Ok(false), - ("0", _) => Ok(true), - _ => Ok(false), - } - }; - - tree.import("A", 1, (), &is_descendent_of).unwrap(); - - tree.import("B", 2, (), &is_descendent_of).unwrap(); - tree.import("C", 3, (), &is_descendent_of).unwrap(); - tree.import("D", 4, (), &is_descendent_of).unwrap(); - tree.import("E", 5, (), &is_descendent_of).unwrap(); - - tree.import("F", 2, (), &is_descendent_of).unwrap(); - tree.import("G", 3, (), &is_descendent_of).unwrap(); - - tree.import("H", 3, (), &is_descendent_of).unwrap(); - tree.import("I", 4, (), &is_descendent_of).unwrap(); - tree.import("L", 4, (), &is_descendent_of).unwrap(); - tree.import("M", 5, (), &is_descendent_of).unwrap(); - tree.import("O", 5, (), &is_descendent_of).unwrap(); - - tree.import("J", 2, (), &is_descendent_of).unwrap(); - tree.import("K", 3, (), &is_descendent_of).unwrap(); - - (tree, is_descendent_of) - } - - #[test] - fn import_doesnt_revert() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - tree.finalize_root(&"A"); - - assert_eq!(tree.best_finalized_number, Some(1)); - - assert_eq!(tree.import("A", 1, (), &is_descendent_of), Err(Error::Revert)); - } - - #[test] - fn import_doesnt_add_duplicates() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - assert_eq!(tree.import("A", 1, (), &is_descendent_of), Err(Error::Duplicate)); - - assert_eq!(tree.import("I", 4, (), &is_descendent_of), Err(Error::Duplicate)); - - assert_eq!(tree.import("G", 3, (), &is_descendent_of), Err(Error::Duplicate)); - - assert_eq!(tree.import("K", 3, (), &is_descendent_of), Err(Error::Duplicate)); - } - - #[test] - fn finalize_root_works() { - let finalize_a = || { - let (mut tree, ..) = test_fork_tree(); - - assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("A", 1)]); - - // finalizing "A" opens up three possible forks - tree.finalize_root(&"A"); - - assert_eq!( - tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), - vec![("B", 2), ("F", 2), ("J", 2)], - ); - - tree - }; - - { - let mut tree = finalize_a(); - - // finalizing "B" will progress on its fork and remove any other competing forks - tree.finalize_root(&"B"); - - assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("C", 3)],); - - // all the other forks have been pruned - assert!(tree.roots.len() == 1); - } - - { - let mut tree = finalize_a(); - - // finalizing "J" will progress on its fork and remove any other competing forks - tree.finalize_root(&"J"); - - assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("K", 3)],); - - // all the other forks have been pruned - assert!(tree.roots.len() == 1); - } - } - - #[test] - fn finalize_works() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - let original_roots = tree.roots.clone(); - - // finalizing a block prior to any in the node doesn't change the tree - assert_eq!(tree.finalize(&"0", 0, &is_descendent_of), Ok(FinalizationResult::Unchanged)); - - assert_eq!(tree.roots, original_roots); - - // finalizing "A" opens up three possible forks - assert_eq!( - tree.finalize(&"A", 1, &is_descendent_of), - Ok(FinalizationResult::Changed(Some(()))), - ); - - assert_eq!( - tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), - vec![("B", 2), ("F", 2), ("J", 2)], - ); - - // finalizing anything lower than what we observed will fail - assert_eq!(tree.best_finalized_number, Some(1)); - - assert_eq!(tree.finalize(&"Z", 1, &is_descendent_of), Err(Error::Revert)); - - // trying to finalize a node without finalizing its ancestors first will fail - assert_eq!(tree.finalize(&"H", 3, &is_descendent_of), Err(Error::UnfinalizedAncestor)); - - // after finalizing "F" we can finalize "H" - assert_eq!( - tree.finalize(&"F", 2, &is_descendent_of), - Ok(FinalizationResult::Changed(Some(()))), - ); - - assert_eq!( - tree.finalize(&"H", 3, &is_descendent_of), - Ok(FinalizationResult::Changed(Some(()))), - ); - - assert_eq!( - tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), - vec![("L", 4), ("I", 4)], - ); - - // finalizing a node from another fork that isn't part of the tree clears the tree - assert_eq!( - tree.finalize(&"Z", 5, &is_descendent_of), - Ok(FinalizationResult::Changed(None)), - ); - - assert!(tree.roots.is_empty()); - } - - #[test] - fn finalize_with_ancestor_works() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - let original_roots = tree.roots.clone(); - - // finalizing a block prior to any in the node doesn't change the tree - assert_eq!( - tree.finalize_with_ancestors(&"0", 0, &is_descendent_of), - Ok(FinalizationResult::Unchanged), - ); - - assert_eq!(tree.roots, original_roots); - - // finalizing "A" opens up three possible forks - assert_eq!( - tree.finalize_with_ancestors(&"A", 1, &is_descendent_of), - Ok(FinalizationResult::Changed(Some(()))), - ); - - assert_eq!( - tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), - vec![("B", 2), ("F", 2), ("J", 2)], - ); - - // finalizing H: - // 1) removes roots that are not ancestors/descendants of H (B, J) - // 2) opens root that is ancestor of H (F -> G+H) - // 3) finalizes the just opened root H (H -> I + L) - assert_eq!( - tree.finalize_with_ancestors(&"H", 3, &is_descendent_of), - Ok(FinalizationResult::Changed(Some(()))), - ); - - assert_eq!( - tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), - vec![("L", 4), ("I", 4)], - ); - - assert_eq!(tree.best_finalized_number, Some(3)); - - // finalizing N (which is not a part of the tree): - // 1) removes roots that are not ancestors/descendants of N (I) - // 2) opens root that is ancestor of N (L -> M+O) - // 3) removes roots that are not ancestors/descendants of N (O) - // 4) opens root that is ancestor of N (M -> {}) - assert_eq!( - tree.finalize_with_ancestors(&"N", 6, &is_descendent_of), - Ok(FinalizationResult::Changed(None)), - ); - - assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![],); - - assert_eq!(tree.best_finalized_number, Some(6)); - } - - #[test] - fn finalize_with_descendent_works() { - #[derive(Debug, PartialEq)] - struct Change { - effective: u64, - } - - let (mut tree, is_descendent_of) = { - let mut tree = ForkTree::new(); - - let is_descendent_of = |base: &&str, block: &&str| -> Result { - // A0 #1 - (B #2) - (C #5) - D #10 - E #15 - (F #100) - // \ - // - (G #100) - // - // A1 #1 - // - // Nodes B, C, F and G are not part of the tree. - match (*base, *block) { - ("A0", b) => Ok(b == "B" || b == "C" || b == "D" || b == "E" || b == "G"), - ("A1", _) => Ok(false), - ("C", b) => Ok(b == "D"), - ("D", b) => Ok(b == "E" || b == "F" || b == "G"), - ("E", b) => Ok(b == "F"), - _ => Ok(false), - } - }; - - let is_root = tree.import("A0", 1, Change { effective: 5 }, &is_descendent_of).unwrap(); - assert!(is_root); - let is_root = tree.import("A1", 1, Change { effective: 5 }, &is_descendent_of).unwrap(); - assert!(is_root); - let is_root = - tree.import("D", 10, Change { effective: 10 }, &is_descendent_of).unwrap(); - assert!(!is_root); - let is_root = - tree.import("E", 15, Change { effective: 50 }, &is_descendent_of).unwrap(); - assert!(!is_root); - - (tree, is_descendent_of) - }; - - assert_eq!( - tree.finalizes_any_with_descendent_if( - &"B", - 2, - &is_descendent_of, - |c| c.effective <= 2, - ), - Ok(None), - ); - - // finalizing "D" is not allowed since it is not a root. - assert_eq!( - tree.finalize_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective <= 10), - Err(Error::UnfinalizedAncestor) - ); - - // finalizing "D" will finalize a block from the tree, but it can't be applied yet - // since it is not a root change. - assert_eq!( - tree.finalizes_any_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective - == 10), - Ok(Some(false)), - ); - - // finalizing "E" is not allowed since there are not finalized anchestors. - assert_eq!( - tree.finalizes_any_with_descendent_if(&"E", 15, &is_descendent_of, |c| c.effective - == 10), - Err(Error::UnfinalizedAncestor) - ); - - // finalizing "B" doesn't finalize "A0" since the predicate doesn't pass, - // although it will clear out "A1" from the tree - assert_eq!( - tree.finalize_with_descendent_if(&"B", 2, &is_descendent_of, |c| c.effective <= 2), - Ok(FinalizationResult::Changed(None)), - ); - - assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("A0", 1)],); - - // finalizing "C" will finalize the node "A0" and prune it out of the tree - assert_eq!( - tree.finalizes_any_with_descendent_if( - &"C", - 5, - &is_descendent_of, - |c| c.effective <= 5, - ), - Ok(Some(true)), - ); - - assert_eq!( - tree.finalize_with_descendent_if(&"C", 5, &is_descendent_of, |c| c.effective <= 5), - Ok(FinalizationResult::Changed(Some(Change { effective: 5 }))), - ); - - assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("D", 10)],); - - // finalizing "F" will fail since it would finalize past "E" without finalizing "D" first - assert_eq!( - tree.finalizes_any_with_descendent_if(&"F", 100, &is_descendent_of, |c| c.effective - <= 100,), - Err(Error::UnfinalizedAncestor), - ); - - // it will work with "G" though since it is not in the same branch as "E" - assert_eq!( - tree.finalizes_any_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective - <= 100), - Ok(Some(true)), - ); - - assert_eq!( - tree.finalize_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective <= 100), - Ok(FinalizationResult::Changed(Some(Change { effective: 10 }))), - ); - - // "E" will be pruned out - assert_eq!(tree.roots().count(), 0); - } - - #[test] - fn iter_iterates_in_preorder() { - let (tree, ..) = test_fork_tree(); - assert_eq!( - tree.iter().map(|(h, n, _)| (*h, *n)).collect::>(), - vec![ - ("A", 1), - ("B", 2), - ("C", 3), - ("D", 4), - ("E", 5), - ("F", 2), - ("H", 3), - ("L", 4), - ("M", 5), - ("O", 5), - ("I", 4), - ("G", 3), - ("J", 2), - ("K", 3), - ], - ); - } - - #[test] - fn minimizes_calls_to_is_descendent_of() { - use std::sync::atomic::{AtomicUsize, Ordering}; - - let n_is_descendent_of_calls = AtomicUsize::new(0); - - let is_descendent_of = |_: &&str, _: &&str| -> Result { - n_is_descendent_of_calls.fetch_add(1, Ordering::SeqCst); - Ok(true) - }; - - { - // Deep tree where we want to call `finalizes_any_with_descendent_if`. The - // search for the node should first check the predicate (which is cheaper) and - // only then call `is_descendent_of` - let mut tree = ForkTree::new(); - let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; - - for (i, letter) in letters.iter().enumerate() { - tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(true)).unwrap(); - } - - // "L" is a descendent of "K", but the predicate will only pass for "K", - // therefore only one call to `is_descendent_of` should be made - assert_eq!( - tree.finalizes_any_with_descendent_if(&"L", 11, &is_descendent_of, |i| *i == 10,), - Ok(Some(false)), - ); - - assert_eq!(n_is_descendent_of_calls.load(Ordering::SeqCst), 1); - } - - n_is_descendent_of_calls.store(0, Ordering::SeqCst); - - { - // Multiple roots in the tree where we want to call `finalize_with_descendent_if`. - // The search for the root node should first check the predicate (which is cheaper) - // and only then call `is_descendent_of` - let mut tree = ForkTree::new(); - let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; - - for (i, letter) in letters.iter().enumerate() { - tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(false)).unwrap(); - } - - // "L" is a descendent of "K", but the predicate will only pass for "K", - // therefore only one call to `is_descendent_of` should be made - assert_eq!( - tree.finalize_with_descendent_if(&"L", 11, &is_descendent_of, |i| *i == 10,), - Ok(FinalizationResult::Changed(Some(10))), - ); - - assert_eq!(n_is_descendent_of_calls.load(Ordering::SeqCst), 1); - } - } - - #[test] - fn map_works() { - let (mut tree, _) = test_fork_tree(); - - // Extend the single root fork-tree to also excercise the roots order during map. - let is_descendent_of = |_: &&str, _: &&str| -> Result { Ok(false) }; - let is_root = tree.import("A1", 1, (), &is_descendent_of).unwrap(); - assert!(is_root); - let is_root = tree.import("A2", 1, (), &is_descendent_of).unwrap(); - assert!(is_root); - - let old_tree = tree.clone(); - let new_tree = tree.map(&mut |hash, _, _| hash.to_owned()); - - // Check content and order - assert!(new_tree.iter().all(|(hash, _, data)| hash == data)); - assert_eq!( - old_tree.iter().map(|(hash, _, _)| *hash).collect::>(), - new_tree.iter().map(|(hash, _, _)| *hash).collect::>(), - ); - } - - #[test] - fn prune_works() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - let removed = tree.prune(&"C", &3, &is_descendent_of, &|_| true).unwrap(); - - assert_eq!(tree.roots.iter().map(|node| node.hash).collect::>(), vec!["B"]); - - assert_eq!( - tree.iter().map(|(hash, _, _)| *hash).collect::>(), - vec!["B", "C", "D", "E"], - ); - - assert_eq!( - removed.map(|(hash, _, _)| hash).collect::>(), - vec!["A", "F", "H", "L", "M", "O", "I", "G", "J", "K"] - ); - - let removed = tree.prune(&"E", &5, &is_descendent_of, &|_| true).unwrap(); - - assert_eq!(tree.roots.iter().map(|node| node.hash).collect::>(), vec!["D"]); - - assert_eq!(tree.iter().map(|(hash, _, _)| *hash).collect::>(), vec!["D", "E"]); - - assert_eq!(removed.map(|(hash, _, _)| hash).collect::>(), vec!["B", "C"]); - } - - #[test] - fn find_node_backtracks_after_finding_highest_descending_node() { - let mut tree = ForkTree::new(); - - // A - B - // \ - // — C - // - let is_descendent_of = |base: &&str, block: &&str| -> Result { - match (*base, *block) { - ("A", b) => Ok(b == "B" || b == "C" || b == "D"), - ("B", b) | ("C", b) => Ok(b == "D"), - ("0", _) => Ok(true), - _ => Ok(false), - } - }; - - tree.import("A", 1, 1, &is_descendent_of).unwrap(); - tree.import("B", 2, 2, &is_descendent_of).unwrap(); - tree.import("C", 2, 4, &is_descendent_of).unwrap(); - - // when searching the tree we reach node `C`, but the - // predicate doesn't pass. we should backtrack to `B`, but not to `A`, - // since "B" fulfills the predicate. - let node = tree.find_node_where(&"D", &3, &is_descendent_of, &|data| *data < 3).unwrap(); - - assert_eq!(node.unwrap().hash, "B"); - } - - #[test] - fn rebalance_works() { - let (mut tree, _) = test_fork_tree(); - - // the tree is automatically rebalanced on import, therefore we should iterate in preorder - // exploring the longest forks first. check the ascii art above to understand the expected - // output below. - assert_eq!( - tree.iter().map(|(h, _, _)| *h).collect::>(), - vec!["A", "B", "C", "D", "E", "F", "H", "L", "M", "O", "I", "G", "J", "K"], - ); - - // let's add a block "P" which is a descendent of block "O" - let is_descendent_of = |base: &&str, block: &&str| -> Result { - match (*base, *block) { - (b, "P") => Ok(vec!["A", "F", "H", "L", "O"].into_iter().any(|n| n == b)), - _ => Ok(false), - } - }; - - tree.import("P", 6, (), &is_descendent_of).unwrap(); - - // this should re-order the tree, since the branch "A -> B -> C -> D -> E" is no longer tied - // with 5 blocks depth. additionally "O" should be visited before "M" now, since it has one - // descendent "P" which makes that branch 6 blocks long. - assert_eq!( - tree.iter().map(|(h, _, _)| *h).collect::>(), - ["A", "F", "H", "L", "O", "P", "M", "I", "G", "B", "C", "D", "E", "J", "K"] - ); - } - - #[test] - fn drain_filter_works() { - let (mut tree, _) = test_fork_tree(); - - let filter = |h: &&str, _: &u64, _: &()| match *h { - "A" | "B" | "F" | "G" => FilterAction::KeepNode, - "C" => FilterAction::KeepTree, - "H" | "J" => FilterAction::Remove, - _ => panic!("Unexpected filtering for node: {}", *h), - }; - - let removed = tree.drain_filter(filter); - - assert_eq!( - tree.iter().map(|(h, _, _)| *h).collect::>(), - ["A", "B", "C", "D", "E", "F", "G"] - ); - - assert_eq!( - removed.map(|(h, _, _)| h).collect::>(), - ["H", "L", "M", "O", "I", "J", "K"] - ); - } - - #[test] - fn find_node_index_works() { - let (tree, is_descendent_of) = test_fork_tree(); - - let path = tree - .find_node_index_where(&"D", &4, &is_descendent_of, &|_| true) - .unwrap() - .unwrap(); - assert_eq!(path, [0, 0, 0]); - - let path = tree - .find_node_index_where(&"O", &5, &is_descendent_of, &|_| true) - .unwrap() - .unwrap(); - assert_eq!(path, [0, 1, 0, 0]); - - let path = tree - .find_node_index_where(&"N", &6, &is_descendent_of, &|_| true) - .unwrap() - .unwrap(); - assert_eq!(path, [0, 1, 0, 0, 0]); - } - - #[test] - fn find_node_index_with_predicate_works() { - let is_descendent_of = |parent: &char, child: &char| match *parent { - 'A' => Ok(['B', 'C', 'D', 'E', 'F'].contains(child)), - 'B' => Ok(['C', 'D'].contains(child)), - 'C' => Ok(['D'].contains(child)), - 'E' => Ok(['F'].contains(child)), - 'D' | 'F' => Ok(false), - _ => Err(TestError), - }; - - // A(t) --- B(f) --- C(t) --- D(f) - // \-- E(t) --- F(f) - let mut tree: ForkTree = ForkTree::new(); - tree.import('A', 1, true, &is_descendent_of).unwrap(); - tree.import('B', 2, false, &is_descendent_of).unwrap(); - tree.import('C', 3, true, &is_descendent_of).unwrap(); - tree.import('D', 4, false, &is_descendent_of).unwrap(); - - tree.import('E', 2, true, &is_descendent_of).unwrap(); - tree.import('F', 3, false, &is_descendent_of).unwrap(); - - let path = tree - .find_node_index_where(&'D', &4, &is_descendent_of, &|&value| !value) - .unwrap() - .unwrap(); - assert_eq!(path, [0, 0]); - - let path = tree - .find_node_index_where(&'D', &4, &is_descendent_of, &|&value| value) - .unwrap() - .unwrap(); - assert_eq!(path, [0, 0, 0]); - - let path = tree - .find_node_index_where(&'F', &3, &is_descendent_of, &|&value| !value) - .unwrap(); - assert_eq!(path, None); - - let path = tree - .find_node_index_where(&'F', &3, &is_descendent_of, &|&value| value) - .unwrap() - .unwrap(); - assert_eq!(path, [0, 1]); - } - - #[test] - fn find_node_works() { - let (tree, is_descendent_of) = test_fork_tree(); - - let node = tree.find_node_where(&"B", &2, &is_descendent_of, &|_| true).unwrap().unwrap(); - assert_eq!((node.hash, node.number), ("A", 1)); - - let node = tree.find_node_where(&"D", &4, &is_descendent_of, &|_| true).unwrap().unwrap(); - assert_eq!((node.hash, node.number), ("C", 3)); - - let node = tree.find_node_where(&"O", &5, &is_descendent_of, &|_| true).unwrap().unwrap(); - assert_eq!((node.hash, node.number), ("L", 4)); - - let node = tree.find_node_where(&"N", &6, &is_descendent_of, &|_| true).unwrap().unwrap(); - assert_eq!((node.hash, node.number), ("M", 5)); - } - - #[test] - fn post_order_traversal_requirement() { - let (mut tree, is_descendent_of) = test_fork_tree(); - - // Test for the post-order DFS traversal requirement as specified by the - // `find_node_index_where` and `import` comments. - let is_descendent_of_for_post_order = |parent: &&str, child: &&str| match *parent { - "A" => Err(TestError), - "K" if *child == "Z" => Ok(true), - _ => is_descendent_of(parent, child), - }; - - // Post order traversal requirement for `find_node_index_where` - let path = tree - .find_node_index_where(&"N", &6, &is_descendent_of_for_post_order, &|_| true) - .unwrap() - .unwrap(); - assert_eq!(path, [0, 1, 0, 0, 0]); - - // Post order traversal requirement for `import` - let res = tree.import(&"Z", 100, (), &is_descendent_of_for_post_order); - assert_eq!(res, Ok(false)); - assert_eq!( - tree.iter().map(|node| *node.0).collect::>(), - vec!["A", "B", "C", "D", "E", "F", "H", "L", "M", "O", "I", "G", "J", "K", "Z"], - ); - } -} diff --git a/bitacross-worker/sidechain/peer-fetch/Cargo.toml b/bitacross-worker/sidechain/peer-fetch/Cargo.toml deleted file mode 100644 index 63e2612d91..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "its-peer-fetch" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -# crates.io -async-trait = { version = "0.1.50" } -jsonrpsee = { version = "0.2.0", features = ["client", "ws-server", "macros"] } -log = { version = "0.4" } -serde = "1.0" -serde_json = "1.0" -thiserror = { version = "1.0" } - -# local -itc-rpc-client = { path = "../../core/rpc-client" } -itp-node-api = { path = "../../core-primitives/node-api" } -its-primitives = { path = "../primitives" } -its-rpc-handler = { path = "../rpc-handler" } -its-storage = { path = "../storage" } - -[dev-dependencies] -# crates.io -anyhow = "1.0.40" -tokio = { version = "1.6.1", features = ["full"] } -# local -itp-node-api = { path = "../../core-primitives/node-api", features = ["mocks"] } -itp-test = { path = "../../core-primitives/test" } -its-storage = { path = "../storage", features = ["mocks"] } -its-test = { path = "../test" } - -[features] -default = ["std"] -std = [] -mocks = [] diff --git a/bitacross-worker/sidechain/peer-fetch/src/block_fetch_client.rs b/bitacross-worker/sidechain/peer-fetch/src/block_fetch_client.rs deleted file mode 100644 index 320d916d7a..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/src/block_fetch_client.rs +++ /dev/null @@ -1,141 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{error::Result, untrusted_peer_fetch::FetchUntrustedPeers, FetchBlocksFromPeer}; -use async_trait::async_trait; -use its_primitives::{ - traits::SignedBlock as SignedBlockTrait, - types::{BlockHash, ShardIdentifier}, -}; -use its_rpc_handler::constants::RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER; -use jsonrpsee::{ - types::to_json_value, - ws_client::{traits::Client, WsClientBuilder}, -}; -use log::info; -use serde::de::DeserializeOwned; -use std::marker::PhantomData; - -/// Sidechain block fetcher implementation. -/// -/// Fetches block from a peer with an RPC request. -pub struct BlockFetcher { - peer_fetcher: PeerFetcher, - _phantom: PhantomData, -} - -impl BlockFetcher -where - SignedBlock: SignedBlockTrait + DeserializeOwned, - PeerFetcher: FetchUntrustedPeers + Send + Sync, -{ - pub fn new(peer_fetcher: PeerFetcher) -> Self { - BlockFetcher { peer_fetcher, _phantom: Default::default() } - } -} - -#[async_trait] -impl FetchBlocksFromPeer for BlockFetcher -where - SignedBlock: SignedBlockTrait + DeserializeOwned, - PeerFetcher: FetchUntrustedPeers + Send + Sync, -{ - type SignedBlockType = SignedBlock; - - async fn fetch_blocks_from_peer( - &self, - last_imported_block_hash: BlockHash, - maybe_until_block_hash: Option, - shard_identifier: ShardIdentifier, - ) -> Result> { - let sync_source_rpc_url = - self.peer_fetcher.get_untrusted_peer_url_of_shard(&shard_identifier)?; - - let rpc_parameters = vec![to_json_value(( - last_imported_block_hash, - maybe_until_block_hash, - shard_identifier, - ))?]; - - info!("Got untrusted url for peer block fetching: {}", sync_source_rpc_url); - - let client = WsClientBuilder::default().build(sync_source_rpc_url.as_str()).await?; - - info!("Sending fetch blocks from peer request"); - - client - .request::>( - RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER, - rpc_parameters.into(), - ) - .await - .map_err(|e| e.into()) - } -} - -#[cfg(test)] -mod tests { - - use super::*; - use crate::{ - block_fetch_server::BlockFetchServerModuleBuilder, - mocks::untrusted_peer_fetch_mock::UntrustedPeerFetcherMock, - }; - use its_primitives::types::block::SignedBlock; - use its_storage::fetch_blocks_mock::FetchBlocksMock; - use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; - use jsonrpsee::ws_server::WsServerBuilder; - use std::{net::SocketAddr, sync::Arc}; - - async fn run_server( - blocks: Vec, - web_socket_url: &str, - ) -> anyhow::Result { - let mut server = WsServerBuilder::default().build(web_socket_url).await?; - - let storage_block_fetcher = Arc::new(FetchBlocksMock::default().with_blocks(blocks)); - let module = BlockFetchServerModuleBuilder::new(storage_block_fetcher).build().unwrap(); - - server.register_module(module).unwrap(); - - let socket_addr = server.local_addr()?; - tokio::spawn(async move { server.start().await }); - Ok(socket_addr) - } - - #[tokio::test] - async fn fetch_blocks_without_bounds_from_peer_works() { - const W1_URL: &str = "127.0.0.1:2233"; - - let blocks_to_fetch = vec![ - SidechainBlockBuilder::random().build_signed(), - SidechainBlockBuilder::random().build_signed(), - ]; - run_server(blocks_to_fetch.clone(), W1_URL).await.unwrap(); - - let peer_fetch_mock = UntrustedPeerFetcherMock::new(format!("ws://{}", W1_URL)); - - let peer_fetcher_client = BlockFetcher::::new(peer_fetch_mock); - - let blocks_fetched = peer_fetcher_client - .fetch_blocks_from_peer(BlockHash::default(), None, ShardIdentifier::default()) - .await - .unwrap(); - - assert_eq!(blocks_to_fetch, blocks_fetched); - } -} diff --git a/bitacross-worker/sidechain/peer-fetch/src/block_fetch_server.rs b/bitacross-worker/sidechain/peer-fetch/src/block_fetch_server.rs deleted file mode 100644 index 592153f6eb..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/src/block_fetch_server.rs +++ /dev/null @@ -1,103 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::error::Result; -use its_primitives::types::{BlockHash, BlockNumber, ShardIdentifier, SignedBlock}; -use its_rpc_handler::constants::{ - RPC_METHOD_NAME_BLOCK_HASH, RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER, - RPC_METHOD_NAME_LATEST_BLOCK, -}; -use its_storage::interface::FetchBlocks; -use jsonrpsee::{types::error::CallError, RpcModule}; -use log::*; -use std::sync::Arc; - -/// RPC server module builder for fetching sidechain blocks from peers. -pub struct BlockFetchServerModuleBuilder { - sidechain_block_fetcher: Arc, -} - -impl BlockFetchServerModuleBuilder -where - // Have to use the concrete `SignedBlock` type, because the ShardIdentifier type - // does not have the Serialize/Deserialize trait bound. - FetchBlocksFromStorage: FetchBlocks + Send + Sync + 'static, -{ - pub fn new(sidechain_block_fetcher: Arc) -> Self { - BlockFetchServerModuleBuilder { sidechain_block_fetcher } - } - - pub fn build(self) -> Result>> { - let mut fetch_sidechain_blocks_module = RpcModule::new(self.sidechain_block_fetcher); - fetch_sidechain_blocks_module.register_method( - RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER, - |params, sidechain_block_fetcher| { - debug!("{}: {:?}", RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER, params); - - let (from_block_hash, maybe_until_block_hash, shard_identifier) = - params.one::<(BlockHash, Option, ShardIdentifier)>()?; - info!("Got request to fetch sidechain blocks from peer. Fetching sidechain blocks from storage \ - (last imported block hash: {:?}, until block hash: {:?}, shard: {}", - from_block_hash, maybe_until_block_hash, shard_identifier); - - match maybe_until_block_hash { - Some(until_block_hash) => sidechain_block_fetcher - .fetch_blocks_in_range( - &from_block_hash, - &until_block_hash, - &shard_identifier, - ) - .map_err(|e| { - error!("Failed to fetch sidechain blocks from storage: {:?}", e); - CallError::Failed(e.into()) - }), - None => sidechain_block_fetcher - .fetch_all_blocks_after(&from_block_hash, &shard_identifier) - .map_err(|e| { - error!("Failed to fetch sidechain blocks from storage: {:?}", e); - CallError::Failed(e.into()) - }), - } - }, - )?; - - fetch_sidechain_blocks_module.register_method( - RPC_METHOD_NAME_LATEST_BLOCK, - |params, sidechain_block_fetcher| { - debug!("{}: {:?}", RPC_METHOD_NAME_LATEST_BLOCK, params); - let shard = params.parse::()?; - match sidechain_block_fetcher.latest_block(&shard) { - None => Ok(None), - Some(e) => Ok(Some(e)), - } - }, - )?; - - fetch_sidechain_blocks_module.register_method( - RPC_METHOD_NAME_BLOCK_HASH, - |params, sidechain_block_fetcher| { - debug!("{}: {:?}", RPC_METHOD_NAME_BLOCK_HASH, params); - let (block_number, shard) = params.parse::<(BlockNumber, ShardIdentifier)>()?; - match sidechain_block_fetcher.block_hash(block_number, &shard) { - None => Ok(None), - Some(e) => Ok(Some(e)), - } - }, - )?; - Ok(fetch_sidechain_blocks_module) - } -} diff --git a/bitacross-worker/sidechain/peer-fetch/src/error.rs b/bitacross-worker/sidechain/peer-fetch/src/error.rs deleted file mode 100644 index 569cd01a1d..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/src/error.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Sidechain peer fetch error. - -pub type Result = core::result::Result; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("RPC client error: {0}")] - RpcClient(#[from] itc_rpc_client::error::Error), - #[error("Node API extensions error: {0:?}")] - NodeApiExtensions(itp_node_api::api_client::ApiClientError), - #[error("Node API factory error: {0}")] - NodeApiFactory(#[from] itp_node_api::node_api_factory::NodeApiFactoryError), - #[error("Serialization error: {0}")] - Serialization(#[from] serde_json::Error), - #[error("JSON RPC error: {0}")] - JsonRpc(#[from] jsonrpsee::types::Error), - #[error("Could not find any peers on-chain for shard: {0:?}")] - NoPeerFoundForShard(its_primitives::types::ShardIdentifier), - #[error(transparent)] - Other(#[from] Box), -} - -impl From for Error { - fn from(error: itp_node_api::api_client::ApiClientError) -> Self { - Error::NodeApiExtensions(error) - } -} diff --git a/bitacross-worker/sidechain/peer-fetch/src/lib.rs b/bitacross-worker/sidechain/peer-fetch/src/lib.rs deleted file mode 100644 index 5af3326970..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/src/lib.rs +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#![cfg_attr(not(feature = "std"), no_std)] - -pub mod block_fetch_client; -pub mod block_fetch_server; -pub mod error; -pub mod untrusted_peer_fetch; - -#[cfg(feature = "mocks")] -pub mod mocks; - -use crate::error::Result; -use async_trait::async_trait; -use its_primitives::{ - traits::SignedBlock, - types::{BlockHash, ShardIdentifier}, -}; -use std::vec::Vec; - -/// Trait to fetch block from peer validateers. -/// -/// This is used by an outdated validateer to get the most recent state. -#[async_trait] -pub trait FetchBlocksFromPeer { - type SignedBlockType: SignedBlock; - - async fn fetch_blocks_from_peer( - &self, - last_imported_block_hash: BlockHash, - maybe_until_block_hash: Option, - shard_identifier: ShardIdentifier, - ) -> Result>; -} diff --git a/bitacross-worker/sidechain/peer-fetch/src/mocks/fetch_blocks_from_peer_mock.rs b/bitacross-worker/sidechain/peer-fetch/src/mocks/fetch_blocks_from_peer_mock.rs deleted file mode 100644 index 09f9bb92fc..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/src/mocks/fetch_blocks_from_peer_mock.rs +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{FetchBlocksFromPeer, Result}; -use async_trait::async_trait; -use its_primitives::{ - traits::SignedBlock as SignedBlockTrait, - types::{BlockHash, ShardIdentifier}, -}; -use std::collections::HashMap; - -pub struct FetchBlocksFromPeerMock { - signed_blocks_map: HashMap>, -} - -impl FetchBlocksFromPeerMock { - pub fn with_signed_blocks( - mut self, - blocks_map: HashMap>, - ) -> Self { - self.signed_blocks_map = blocks_map; - self - } -} - -impl Default for FetchBlocksFromPeerMock { - fn default() -> Self { - FetchBlocksFromPeerMock { signed_blocks_map: HashMap::new() } - } -} - -#[async_trait] -impl FetchBlocksFromPeer for FetchBlocksFromPeerMock -where - SignedBlock: SignedBlockTrait, -{ - type SignedBlockType = SignedBlock; - - async fn fetch_blocks_from_peer( - &self, - _last_imported_block_hash: BlockHash, - _maybe_until_block_hash: Option, - shard_identifier: ShardIdentifier, - ) -> Result> { - Ok(self.signed_blocks_map.get(&shard_identifier).cloned().unwrap_or_default()) - } -} diff --git a/bitacross-worker/sidechain/peer-fetch/src/mocks/mod.rs b/bitacross-worker/sidechain/peer-fetch/src/mocks/mod.rs deleted file mode 100644 index 392f8e9b82..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/src/mocks/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub mod fetch_blocks_from_peer_mock; -pub mod untrusted_peer_fetch_mock; diff --git a/bitacross-worker/sidechain/peer-fetch/src/mocks/untrusted_peer_fetch_mock.rs b/bitacross-worker/sidechain/peer-fetch/src/mocks/untrusted_peer_fetch_mock.rs deleted file mode 100644 index 8b37b69e00..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/src/mocks/untrusted_peer_fetch_mock.rs +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{error::Result, untrusted_peer_fetch::FetchUntrustedPeers}; -use its_primitives::types::ShardIdentifier; - -pub struct UntrustedPeerFetcherMock { - url: String, -} - -impl UntrustedPeerFetcherMock { - pub fn new(url: String) -> Self { - UntrustedPeerFetcherMock { url } - } -} - -impl FetchUntrustedPeers for UntrustedPeerFetcherMock { - fn get_untrusted_peer_url_of_shard(&self, _shard: &ShardIdentifier) -> Result { - Ok(self.url.clone()) - } -} diff --git a/bitacross-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs b/bitacross-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs deleted file mode 100644 index 7ff9434103..0000000000 --- a/bitacross-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::error::{Error, Result}; -use itc_rpc_client::direct_client::{DirectApi, DirectClient as DirectWorkerApi}; -use itp_node_api::{api_client::PalletTeerexApi, node_api_factory::CreateNodeApi}; -use its_primitives::types::ShardIdentifier; -use std::sync::Arc; - -/// Trait to fetch untrusted peer servers. -pub trait FetchUntrustedPeers { - fn get_untrusted_peer_url_of_shard(&self, shard: &ShardIdentifier) -> Result; -} - -/// Fetches the untrusted peer servers -/// FIXME: Should probably be combined with the peer fetch in -/// service/src/worker.rs -pub struct UntrustedPeerFetcher { - node_api_factory: Arc, -} - -impl UntrustedPeerFetcher -where - NodeApiFactory: CreateNodeApi + Send + Sync, -{ - pub fn new(node_api: Arc) -> Self { - UntrustedPeerFetcher { node_api_factory: node_api } - } -} - -impl FetchUntrustedPeers for UntrustedPeerFetcher -where - NodeApiFactory: CreateNodeApi + Send + Sync, -{ - fn get_untrusted_peer_url_of_shard(&self, shard: &ShardIdentifier) -> Result { - let node_api = self.node_api_factory.create_api()?; - - let validateer = node_api - .worker_for_shard(shard, None)? - .ok_or_else(|| Error::NoPeerFoundForShard(*shard))?; - - let trusted_worker_client = DirectWorkerApi::new(validateer.url); - Ok(trusted_worker_client.get_untrusted_worker_url()?) - } -} diff --git a/bitacross-worker/sidechain/primitives/Cargo.toml b/bitacross-worker/sidechain/primitives/Cargo.toml deleted file mode 100644 index 548f4d5a18..0000000000 --- a/bitacross-worker/sidechain/primitives/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "its-primitives" -version = "0.1.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -homepage = 'https://litentry.com/' -repository = 'https://github.com/litentry/litentry-parachain' -license = "Apache-2.0" -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } -itp-types = { path = "../../core-primitives/types", default-features = false } -scale-info = { version = "2.4.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.13", default-features = false } - -# substrate dependencies -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - - -[features] -default = ["std", "full_crypto"] -full_crypto = [ - "sp-core/full_crypto", -] -std = [ - "codec/std", - "scale-info/std", - "serde/std", - "itp-types/std", - # substrate - "sp-core/std", - "sp-runtime/std", - "sp-std/std", -] diff --git a/bitacross-worker/sidechain/primitives/src/lib.rs b/bitacross-worker/sidechain/primitives/src/lib.rs deleted file mode 100644 index 708d9a7942..0000000000 --- a/bitacross-worker/sidechain/primitives/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#![cfg_attr(not(feature = "std"), no_std)] - -pub mod traits; -pub mod types; diff --git a/bitacross-worker/sidechain/primitives/src/traits/mod.rs b/bitacross-worker/sidechain/primitives/src/traits/mod.rs deleted file mode 100644 index 06e1e2d393..0000000000 --- a/bitacross-worker/sidechain/primitives/src/traits/mod.rs +++ /dev/null @@ -1,176 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Some basic abstractions used in sidechain -//! -//! Todo: This crate should be more generic and supply blanket implementations for -//! some generic structs. - -use codec::{Decode, Encode}; -use sp_core::{crypto::Public, H256}; -use sp_runtime::traits::{BlakeTwo256, Hash, Member}; -use sp_std::{fmt::Debug, prelude::*}; - -pub trait Header: Encode + Decode + Clone { - /// Identifier for the shards. - type ShardIdentifier: Encode + Decode + sp_std::hash::Hash + Copy + Member + Into; - - /// Get block number. - fn block_number(&self) -> u64; - /// get parent hash of block - fn parent_hash(&self) -> H256; - /// get shard id of block - fn shard_id(&self) -> Self::ShardIdentifier; - /// get hash of the block's payload - fn block_data_hash(&self) -> H256; - - /// get the `blake2_256` hash of the header. - fn hash(&self) -> H256 { - self.using_encoded(BlakeTwo256::hash) - } - - fn next_finalization_block_number(&self) -> u64; - - fn new( - block_number: u64, - parent_hash: H256, - shard: Self::ShardIdentifier, - block_data_hash: H256, - next_finalization_block_number: u64, - ) -> Self; -} - -pub trait BlockData: Encode + Decode + Send + Sync + Debug + Clone { - /// Public key type of the block author - type Public: Public; - - /// get timestamp of block - fn timestamp(&self) -> u64; - /// get layer one head of block - fn layer_one_head(&self) -> H256; - /// get author of block - fn block_author(&self) -> &Self::Public; - /// get reference of extrinsics of block - fn signed_top_hashes(&self) -> &[H256]; - /// get encrypted payload - fn encrypted_state_diff(&self) -> &Vec; - /// get the `blake2_256` hash of the block - fn hash(&self) -> H256 { - self.using_encoded(BlakeTwo256::hash) - } - - fn new( - author: Self::Public, - layer_one_head: H256, - signed_top_hashes: Vec, - encrypted_payload: Vec, - timestamp: u64, - ) -> Self; -} - -/// Abstraction around a sidechain block. -pub trait Block: Encode + Decode + Send + Sync + Debug + Clone { - /// Sidechain block header type. - type HeaderType: Header; - - /// Sidechain block data type. - type BlockDataType: BlockData; - - /// Public key type of the block author - type Public: Public; - - /// get the `blake2_256` hash of the block - fn hash(&self) -> H256 { - self.header().hash() - } - - /// Get header of the block. - fn header(&self) -> &Self::HeaderType; - - /// Get header of the block. - fn block_data(&self) -> &Self::BlockDataType; - - fn new(header: Self::HeaderType, block_data: Self::BlockDataType) -> Self; -} - -/// ShardIdentifier for a [`SignedBlock`] -pub type ShardIdentifierFor = -<<::Block as Block>::HeaderType as Header>::ShardIdentifier; - -/// A block and it's corresponding signature by the [`Block`] author. -pub trait SignedBlock: Encode + Decode + Send + Sync + Debug + Clone { - /// The block type of the [`SignedBlock`] - type Block: Block; - - /// Public key type of the signer and the block author - type Public: Public; - - /// Signature type of the [`SignedBlock`]'s signature - type Signature; - - /// create a new block instance - fn new(block: Self::Block, signer: Self::Signature) -> Self; - - /// get block reference - fn block(&self) -> &Self::Block; - - /// get signature reference - fn signature(&self) -> &Self::Signature; - - /// get `blake2_256` hash of block - fn hash(&self) -> H256 { - self.block().hash() - } - - /// Verify the signature of a [`Block`] - fn verify_signature(&self) -> bool; -} - -#[cfg(feature = "full_crypto")] -pub use crypto::*; - -#[cfg(feature = "full_crypto")] -mod crypto { - use super::*; - use sp_core::Pair; - - /// Provide signing logic blanket implementations for all block types satisfying the trait bounds. - pub trait SignBlock< - SidechainBlock: Block, - SignedSidechainBlock: SignedBlock, - > - { - fn sign_block(self, signer: &P) -> SignedSidechainBlock - where - ::Signature: From<

::Signature>; - } - - impl SignBlock - for SidechainBlock - where - SidechainBlock: Block, - SignedSidechainBlock: SignedBlock, - { - fn sign_block(self, signer: &P) -> SignedSidechainBlock - where - ::Signature: From<

::Signature>, - { - let signature = self.using_encoded(|b| signer.sign(b)).into(); - SignedSidechainBlock::new(self, signature) - } - } -} diff --git a/bitacross-worker/sidechain/primitives/src/types/block.rs b/bitacross-worker/sidechain/primitives/src/types/block.rs deleted file mode 100644 index 8e7902d62d..0000000000 --- a/bitacross-worker/sidechain/primitives/src/types/block.rs +++ /dev/null @@ -1,159 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - traits::{Block as BlockTrait, SignedBlock as SignedBlockTrait}, - types::{block_data::BlockData, header::SidechainHeader as Header}, -}; -use codec::{Decode, Encode}; -use sp_core::{ed25519, H256}; -use sp_runtime::{traits::Verify, MultiSignature}; - -pub type BlockHash = H256; -pub type BlockNumber = u64; -pub type ShardIdentifier = H256; -pub type Timestamp = u64; - -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; - -//FIXME: Should use blocknumber from sgxruntime -// Problem: sgxruntime only with sgx, no std enviornment -// but block.rs should be available in std? -//use sgx_runtime::BlockNumber; - -pub type Signature = MultiSignature; - -/// signed version of block to verify block origin -#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct SignedBlock { - /// Plain sidechain block without author signature. - pub block: Block, - /// Block author signature. - pub signature: Signature, -} - -/// Simplified block structure for relay chain submission as an extrinsic. -#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Block { - /// Sidechain Header - pub header: Header, - - /// Sidechain Block data - pub block_data: BlockData, -} - -impl BlockTrait for Block { - type HeaderType = Header; - - type BlockDataType = BlockData; - - type Public = ed25519::Public; - - fn header(&self) -> &Self::HeaderType { - &self.header - } - - fn block_data(&self) -> &Self::BlockDataType { - &self.block_data - } - - fn new(header: Self::HeaderType, block_data: Self::BlockDataType) -> Self { - Self { header, block_data } - } -} - -impl SignedBlockTrait for SignedBlock { - type Block = Block; - - type Public = ed25519::Public; - - type Signature = Signature; - - fn new(block: Self::Block, signature: Self::Signature) -> Self { - Self { block, signature } - } - - /// get block reference - fn block(&self) -> &Self::Block { - &self.block - } - - /// get signature reference - fn signature(&self) -> &Signature { - &self.signature - } - - /// Verifies the signature of a Block - fn verify_signature(&self) -> bool { - self.block.using_encoded(|p| { - self.signature.verify(p, &self.block.block_data().block_author.into()) - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::traits::{Block as BlockT, BlockData, Header, SignBlock}; - use sp_core::Pair; - use std::time::{SystemTime, UNIX_EPOCH}; - - /// gets the timestamp of the block as seconds since unix epoch - fn timestamp_now() -> Timestamp { - SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as Timestamp - } - - fn test_block() -> Block { - let header = Header::new(0, H256::random(), H256::random(), Default::default(), 1); - let block_data = BlockData::new( - ed25519::Pair::from_string("//Alice", None).unwrap().public().into(), - H256::random(), - Default::default(), - Default::default(), - timestamp_now(), - ); - - Block::new(header, block_data) - } - - #[test] - fn signing_works() { - let block = test_block(); - let signer = ed25519::Pair::from_string("//Alice", None).unwrap(); - - let signature: Signature = - Signature::Ed25519(signer.sign(block.encode().as_slice().into())); - let signed_block: SignedBlock = block.clone().sign_block(&signer); - - assert_eq!(signed_block.block(), &block); - assert_eq!(signed_block.signature(), &signature); - assert!(signed_block.verify_signature()); - } - - #[test] - fn tampered_block_verify_signature_fails() { - let signer = ed25519::Pair::from_string("//Alice", None).unwrap(); - - let mut signed_block: SignedBlock = test_block().sign_block(&signer); - signed_block.block.header.block_number = 1; - - assert!(!signed_block.verify_signature()); - } -} diff --git a/bitacross-worker/sidechain/primitives/src/types/block_data.rs b/bitacross-worker/sidechain/primitives/src/types/block_data.rs deleted file mode 100644 index a48d4148e4..0000000000 --- a/bitacross-worker/sidechain/primitives/src/types/block_data.rs +++ /dev/null @@ -1,82 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::traits::BlockData as BlockDataTrait; -use codec::{Decode, Encode}; -use sp_core::{ed25519, H256}; -use sp_std::vec::Vec; - -pub type Timestamp = u64; - -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; - -#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct BlockData { - pub timestamp: u64, - /// Parentchain header this block is based on. - pub layer_one_head: H256, - /// Must be registered on layer one as an enclave for the respective shard. - pub block_author: ed25519::Public, - /// Hashes of signed trusted operations. - pub signed_top_hashes: Vec, - /// Encrypted state payload. - pub encrypted_state_diff: Vec, -} - -impl BlockDataTrait for BlockData { - type Public = ed25519::Public; - - /// Get timestamp of block. - fn timestamp(&self) -> Timestamp { - self.timestamp - } - /// Get layer one head of block. - fn layer_one_head(&self) -> H256 { - self.layer_one_head - } - /// Get author of block. - fn block_author(&self) -> &Self::Public { - &self.block_author - } - /// Get reference of extrinisics of block. - fn signed_top_hashes(&self) -> &[H256] { - &self.signed_top_hashes - } - /// Get encrypted payload. - fn encrypted_state_diff(&self) -> &Vec { - &self.encrypted_state_diff - } - /// Constructs block data. - fn new( - block_author: Self::Public, - layer_one_head: H256, - signed_top_hashes: Vec, - encrypted_state_diff: Vec, - timestamp: Timestamp, - ) -> BlockData { - // create block - BlockData { - timestamp, - layer_one_head, - signed_top_hashes, - block_author, - encrypted_state_diff, - } - } -} diff --git a/bitacross-worker/sidechain/primitives/src/types/header.rs b/bitacross-worker/sidechain/primitives/src/types/header.rs deleted file mode 100644 index 962917f534..0000000000 --- a/bitacross-worker/sidechain/primitives/src/types/header.rs +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//!Primitives for the sidechain -use crate::traits::Header as HeaderTrait; -use codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_core::H256; -use sp_runtime::traits::{BlakeTwo256, Hash}; -use sp_std::prelude::*; - -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; - -pub use itp_types::ShardIdentifier; - -#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug, Copy, Default, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct SidechainHeader { - /// The parent hash. - pub parent_hash: H256, - - /// The block number. - pub block_number: u64, - - /// The Shard id. - pub shard_id: ShardIdentifier, - - /// The payload hash. - pub block_data_hash: H256, - - /// The latest finalized block number - pub next_finalization_block_number: u64, -} - -impl SidechainHeader { - /// get the `blake2_256` hash of the header. - pub fn hash(&self) -> H256 { - self.using_encoded(BlakeTwo256::hash) - } -} - -impl HeaderTrait for SidechainHeader { - type ShardIdentifier = H256; - - fn block_number(&self) -> u64 { - self.block_number - } - fn parent_hash(&self) -> H256 { - self.parent_hash - } - fn shard_id(&self) -> Self::ShardIdentifier { - self.shard_id - } - fn block_data_hash(&self) -> H256 { - self.block_data_hash - } - fn next_finalization_block_number(&self) -> u64 { - self.next_finalization_block_number - } - - fn new( - block_number: u64, - parent_hash: H256, - shard: Self::ShardIdentifier, - block_data_hash: H256, - next_finalization_block_number: u64, - ) -> SidechainHeader { - SidechainHeader { - block_number, - parent_hash, - shard_id: shard, - block_data_hash, - next_finalization_block_number, - } - } -} diff --git a/bitacross-worker/sidechain/primitives/src/types/mod.rs b/bitacross-worker/sidechain/primitives/src/types/mod.rs deleted file mode 100644 index 2056953387..0000000000 --- a/bitacross-worker/sidechain/primitives/src/types/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub mod block; -pub mod block_data; -pub mod header; - -pub use block::*; diff --git a/bitacross-worker/sidechain/rpc-handler/Cargo.toml b/bitacross-worker/sidechain/rpc-handler/Cargo.toml deleted file mode 100644 index 58cf470bf7..0000000000 --- a/bitacross-worker/sidechain/rpc-handler/Cargo.toml +++ /dev/null @@ -1,57 +0,0 @@ -[package] -name = "its-rpc-handler" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -# sgx dependencies -sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } - -# local dependencies -itp-rpc = { path = "../../core-primitives/rpc", default-features = false } -itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } -itp-top-pool-author = { path = "../../core-primitives/top-pool-author", default-features = false } -itp-types = { path = "../../core-primitives/types", default-features = false } -itp-utils = { path = "../../core-primitives/utils", default-features = false } -its-primitives = { path = "../primitives", default-features = false } - -litentry-primitives = { path = "../../litentry/primitives", default-features = false } - -# sgx enabled external libraries -futures_sgx = { package = "futures", git = "https://github.com/mesalock-linux/futures-rs-sgx", optional = true } -jsonrpc-core_sgx = { package = "jsonrpc-core", git = "https://github.com/scs/jsonrpc", branch = "no_std_v18", default-features = false, optional = true } -rust-base58_sgx = { package = "rust-base58", rev = "sgx_1.1.3", git = "https://github.com/mesalock-linux/rust-base58-sgx", optional = true, default-features = false, features = ["mesalock_sgx"] } - -# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) -futures = { version = "0.3.8", optional = true } -jsonrpc-core = { version = "18", optional = true } -rust-base58 = { package = "rust-base58", version = "0.0.4", optional = true } - -# no-std compatible libraries -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -log = { version = "0.4", default-features = false } -sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -[features] -default = ["std"] -std = [ - "futures", - "itp-rpc/std", - "itp-stf-primitives/std", - "itp-top-pool-author/std", - "itp-types/std", - "its-primitives/std", - "litentry-primitives/std", - "jsonrpc-core", - "log/std", - "rust-base58", -] -sgx = [ - "futures_sgx", - "sgx_tstd", - "itp-rpc/sgx", - "itp-top-pool-author/sgx", - "jsonrpc-core_sgx", - "rust-base58_sgx", -] diff --git a/bitacross-worker/sidechain/rpc-handler/src/constants.rs b/bitacross-worker/sidechain/rpc-handler/src/constants.rs deleted file mode 100644 index bff9ea019b..0000000000 --- a/bitacross-worker/sidechain/rpc-handler/src/constants.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Sidechain constants - -// RPC method names. -pub const RPC_METHOD_NAME_IMPORT_BLOCKS: &str = "sidechain_importBlock"; -pub const RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER: &str = "sidechain_fetchBlocksFromPeer"; -pub const RPC_METHOD_NAME_LATEST_BLOCK: &str = "sidechain_latestBlock"; -pub const RPC_METHOD_NAME_BLOCK_HASH: &str = "sidechain_blockHash"; diff --git a/bitacross-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs b/bitacross-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs deleted file mode 100644 index 5de9ed776a..0000000000 --- a/bitacross-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs +++ /dev/null @@ -1,320 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; -use core::fmt::Debug; - -#[cfg(feature = "std")] -use rust_base58::base58::FromBase58; - -#[cfg(feature = "sgx")] -use base58::FromBase58; - -use codec::{Decode, Encode}; -use itp_rpc::RpcReturnValue; -use itp_stf_primitives::types::AccountId; -use itp_top_pool_author::traits::AuthorApi; -use itp_types::{DirectRequestStatus, RsaRequest, ShardIdentifier, TrustedOperationStatus}; -use itp_utils::{FromHexPrefixed, ToHexPrefixed}; -use jsonrpc_core::{futures::executor, serde_json::json, Error as RpcError, IoHandler, Params}; -use litentry_primitives::AesRequest; -use log::*; -use std::{ - borrow::ToOwned, - format, - string::{String, ToString}, - sync::Arc, - vec, - vec::Vec, -}; - -type Hash = sp_core::H256; - -pub fn add_top_pool_direct_rpc_methods( - top_pool_author: Arc, - mut io_handler: IoHandler, -) -> IoHandler -where - R: AuthorApi + Send + Sync + 'static, - TCS: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, - G: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, -{ - let watch_author = top_pool_author.clone(); - io_handler.add_sync_method("author_submitAndWatchRsaRequest", move |params: Params| { - debug!("worker_api_direct rpc was called: author_submitAndWatchRsaRequest"); - let json_value = match author_submit_extrinsic_inner( - watch_author.clone(), - params, - Some("author_submitAndWatchBroadcastedRsaRequest".to_owned()), - ) { - Ok(hash_value) => RpcReturnValue { - do_watch: true, - value: vec![], - status: DirectRequestStatus::TrustedOperationStatus( - TrustedOperationStatus::Submitted, - hash_value, - ), - } - .to_hex(), - Err(error) => compute_hex_encoded_return_error(error.as_str()), - }; - Ok(json!(json_value)) - }); - - // author_submitAndWatchBroadcastedRsaRequest - let watch_author = top_pool_author.clone(); - io_handler.add_sync_method( - "author_submitAndWatchBroadcastedRsaRequest", - move |params: Params| { - let json_value = match author_submit_extrinsic_inner(watch_author.clone(), params, None) - { - Ok(hash_value) => { - RpcReturnValue { - do_watch: true, - value: vec![], - status: DirectRequestStatus::TrustedOperationStatus( - TrustedOperationStatus::Submitted, - hash_value, - ), - } - } - .to_hex(), - Err(error) => compute_hex_encoded_return_error(error.as_str()), - }; - Ok(json!(json_value)) - }, - ); - - // author_submitRsaRequest - let submit_author = top_pool_author.clone(); - io_handler.add_sync_method("author_submitRsaRequest", move |params: Params| { - debug!("worker_api_direct rpc was called: author_submitRsaRequest"); - let json_value = match author_submit_extrinsic_inner(submit_author.clone(), params, None) { - Ok(hash_value) => RpcReturnValue { - do_watch: false, - value: vec![], - status: DirectRequestStatus::TrustedOperationStatus( - TrustedOperationStatus::Submitted, - hash_value, - ), - } - .to_hex(), - Err(error) => compute_hex_encoded_return_error(error.as_str()), - }; - Ok(json!(json_value)) - }); - - // Litentry: a morphling of `author_submitAndWatchRsaRequest` - // a different name is used to highlight the request type - let watch_author = top_pool_author.clone(); - io_handler.add_sync_method("author_submitAndWatchAesRequest", move |params: Params| { - debug!("worker_api_direct rpc was called: author_submitAndWatchAesRequest"); - let json_value = match author_submit_aes_request_inner( - watch_author.clone(), - params, - Some("author_submitAndWatchBroadcastedAesRequest".to_owned()), - ) { - Ok(hash_value) => RpcReturnValue { - do_watch: true, - value: vec![], - status: DirectRequestStatus::TrustedOperationStatus( - TrustedOperationStatus::Submitted, - hash_value, - ), - } - .to_hex(), - Err(error) => compute_hex_encoded_return_error(error.as_str()), - }; - Ok(json!(json_value)) - }); - - let watch_author = top_pool_author.clone(); - io_handler.add_sync_method( - "author_submitAndWatchBroadcastedAesRequest", - move |params: Params| { - let json_value = - match author_submit_aes_request_inner(watch_author.clone(), params, None) { - Ok(hash_value) => RpcReturnValue { - do_watch: true, - value: vec![], - status: DirectRequestStatus::TrustedOperationStatus( - TrustedOperationStatus::Submitted, - hash_value, - ), - } - .to_hex(), - Err(error) => compute_hex_encoded_return_error(error.as_str()), - }; - Ok(json!(json_value)) - }, - ); - - // author_pendingExtrinsics - let pending_author = top_pool_author.clone(); - io_handler.add_sync_method("author_pendingExtrinsics", move |params: Params| { - debug!("worker_api_direct rpc was called: author_pendingExtrinsics"); - match params.parse::>() { - Ok(shards) => { - let mut retrieved_operations = vec![]; - for shard_base58 in shards.iter() { - let shard = match decode_shard_from_base58(shard_base58.as_str()) { - Ok(id) => id, - Err(msg) => { - let error_msg: String = - format!("Could not retrieve pending calls due to: {}", msg); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; - if let Ok(vec_of_operations) = pending_author.pending_tops(shard) { - retrieved_operations.push(vec_of_operations); - } - } - let json_value = RpcReturnValue { - do_watch: false, - value: retrieved_operations.encode(), - status: DirectRequestStatus::Ok, - }; - Ok(json!(json_value.to_hex())) - }, - Err(e) => { - let error_msg: String = format!("Could not retrieve pending calls due to: {}", e); - Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - } - }); - - let pending_author = top_pool_author; - io_handler.add_sync_method("author_pendingTrustedCallsFor", move |params: Params| { - debug!("worker_api_direct rpc was called: author_pendingTrustedCallsFor"); - match params.parse::<(String, String)>() { - Ok((shard_base58, account_hex)) => { - let shard = match decode_shard_from_base58(shard_base58.as_str()) { - Ok(id) => id, - Err(msg) => { - let error_msg: String = - format!("Could not retrieve pending trusted calls due to: {}", msg); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; - let account = match AccountId::from_hex(account_hex.as_str()) { - Ok(acc) => acc, - Err(msg) => { - let error_msg: String = - format!("Could not retrieve pending trusted calls due to: {:?}", msg); - return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - }; - let trusted_calls = pending_author.get_pending_trusted_calls_for(shard, &account); - let json_value = RpcReturnValue { - do_watch: false, - value: trusted_calls.encode(), - status: DirectRequestStatus::Ok, - }; - Ok(json!(json_value.to_hex())) - }, - Err(e) => { - let error_msg: String = - format!("Could not retrieve pending trusted calls due to: {}", e); - Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) - }, - } - }); - - io_handler -} - -// converts the rpc methods vector to a string and adds commas and brackets for readability -pub fn decode_shard_from_base58(shard_base58: &str) -> Result { - let shard_vec = match shard_base58.from_base58() { - Ok(vec) => vec, - Err(_) => return Err("Invalid base58 format of shard id".to_owned()), - }; - let shard = match ShardIdentifier::decode(&mut shard_vec.as_slice()) { - Ok(hash) => hash, - Err(_) => return Err("Shard ID is not of type H256".to_owned()), - }; - Ok(shard) -} - -fn compute_hex_encoded_return_error(error_msg: &str) -> String { - RpcReturnValue::from_error_message(error_msg).to_hex() -} - -// we expect our `params` to be "by-position array" -// see https://www.jsonrpc.org/specification#parameter_structures -fn get_request_payload(params: Params) -> Result { - let s_vec = params.parse::>().map_err(|e| format!("{}", e))?; - - let s = s_vec.get(0).ok_or_else(|| "Empty params".to_string())?; - debug!("Request payload: {}", s); - Ok(s.to_owned()) -} - -fn author_submit_extrinsic_inner( - author: Arc, - params: Params, - json_rpc_method: Option, -) -> Result -where - R: AuthorApi + Send + Sync + 'static, - TCS: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, - G: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, -{ - let payload = get_request_payload(params)?; - let request = RsaRequest::from_hex(&payload).map_err(|e| format!("{:?}", e))?; - - let response: Result = if let Some(method) = json_rpc_method { - executor::block_on(async { author.watch_and_broadcast_top(request, method).await }) - } else { - executor::block_on(async { author.watch_top(request).await }) - }; - - match &response { - Ok(h) => debug!("Trusted operation submitted successfully ({:?})", h), - Err(e) => warn!("Submitting trusted operation failed: {:?}", e), - } - - response.map_err(|e| format!("{:?}", e)) -} - -fn author_submit_aes_request_inner( - author: Arc, - params: Params, - json_rpc_method: Option, -) -> Result -where - R: AuthorApi + Send + Sync + 'static, - TCS: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, - G: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, -{ - let payload = get_request_payload(params)?; - let request = AesRequest::from_hex(&payload).map_err(|e| format!("{:?}", e))?; - - let response: Result = if let Some(method) = json_rpc_method { - executor::block_on(async { author.watch_and_broadcast_top(request, method).await }) - } else { - executor::block_on(async { author.watch_top(request).await }) - }; - - match &response { - Ok(h) => debug!("AesRequest submitted successfully ({:?})", h), - Err(e) => warn!("Submitting AesRequest failed: {:?}", e), - } - - response.map_err(|e| format!("{:?}", e)) -} diff --git a/bitacross-worker/sidechain/rpc-handler/src/import_block_api.rs b/bitacross-worker/sidechain/rpc-handler/src/import_block_api.rs deleted file mode 100644 index a34ff829ef..0000000000 --- a/bitacross-worker/sidechain/rpc-handler/src/import_block_api.rs +++ /dev/null @@ -1,126 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; -use itp_utils::FromHexPrefixed; -use its_primitives::types::SignedBlock; -use jsonrpc_core::{IoHandler, Params, Value}; -use log::*; -use std::{borrow::ToOwned, fmt::Debug, string::String, vec::Vec}; - -pub fn add_import_block_rpc_method( - import_fn: ImportFn, - mut io_handler: IoHandler, -) -> IoHandler -where - ImportFn: Fn(SignedBlock) -> Result<(), Error> + Sync + Send + 'static, - Error: Debug, -{ - let sidechain_import_import_name: &str = RPC_METHOD_NAME_IMPORT_BLOCKS; - io_handler.add_sync_method(sidechain_import_import_name, move |sidechain_blocks: Params| { - debug!("{} rpc. Params: {:?}", RPC_METHOD_NAME_IMPORT_BLOCKS, sidechain_blocks); - - let hex_encoded_block_vec: Vec = sidechain_blocks.parse()?; - - let blocks = Vec::::from_hex(&hex_encoded_block_vec[0]).map_err(|_| { - jsonrpc_core::error::Error::invalid_params_with_details( - "Could not decode Vec", - hex_encoded_block_vec, - ) - })?; - - debug!("{}. Blocks: {:?}", RPC_METHOD_NAME_IMPORT_BLOCKS, blocks); - - for block in blocks { - info!("Add block {} to import queue", block.block.header.block_number); - let _ = import_fn(block).map_err(|e| { - let error = jsonrpc_core::error::Error::invalid_params_with_details( - "Failed to import Block.", - e, - ); - error!("{:?}", error); - }); - } - - Ok(Value::String("ok".to_owned())) - }); - - io_handler -} - -#[cfg(test)] -pub mod tests { - - use super::*; - - fn rpc_response(result: T) -> String { - format!(r#"{{"jsonrpc":"2.0","result":{},"id":1}}"#, result.to_string()) - } - - fn io_handler() -> IoHandler { - let io_handler = IoHandler::new(); - add_import_block_rpc_method::<_, String>(|_| Ok(()), io_handler) - } - - #[test] - pub fn sidechain_import_block_is_ok() { - let io = io_handler(); - let enclave_req = r#"{"jsonrpc":"2.0","method":"sidechain_importBlock","params":["0x04a7417cf9370af5ea5cf64f107aa49ebf320dbf10c6d0ef200ef7c5d57c9f4b956d000000000000007dba6b8e1f8f38f7f517dbd4a3eaeb27a97958d7a1d1541f69db5d24b3c48cd0dc376b08fcb44dca19a08a0445023a5f4bef80019b518296313e83fc105c669064000000000000005f08a5f98301000081bd02d7e1f8b6ab9a64fa8fdaa379fc1c9208bf0d341689c2342ce8a314e174768f40dfe0fadf2e7347f2ec83a541427a0931ce54ce7a4506184198c2e7aed3006d031b2cc662bbcd54ca1cc09f0021d956673c4905b07edf0b9f323d2078fc4d8cbaefe34353bc731f9a1ef14dfd6b58274a6efbbc6c2c4261d304b979305f501819df33452f2f276add2f3650b825c700abf23790a6787baf1cabb208633eb33fb66e987a99193fbd2c07374502dc0fdff6d7a5d462b2a9c0196711437aa6a30ce52ae6e4818a643df256c026b08d7ccca2de46f368630512073b271397719f34c9b8612c7f1707d06b45206da268f49b5b5159b3418093512700ecb67ccbc5bd9a1731a9c67372b39ec3761d12afb445a6c8580b97a090f4bb06ff70001bc44f7f91ada7f92f0064188d08c16594ddb4fd09f65bee5f4b3c92b80091d3fe5bc89f3fb95a96941563126a6379b806981dd7f225c7e3ac4e1ee0509de406"],"id":1}"#; - - let response_string = io.handle_request_sync(enclave_req).unwrap(); - - assert_eq!(response_string, rpc_response("\"ok\"")); - } - - #[test] - pub fn sidechain_import_block_returns_invalid_param_err() { - let io = io_handler(); - let enclave_req = - r#"{"jsonrpc":"2.0","method":"sidechain_importBlock","params":[4,214,133,100],"id":1}"#; - - let response_string = io.handle_request_sync(enclave_req).unwrap(); - - let err_msg = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: invalid type: integer `4`, expected a string."},"id":1}"#; - assert_eq!(response_string, err_msg); - } - - #[test] - pub fn sidechain_import_block_returns_decode_err() { - let io = io_handler(); - let enclave_req = r#"{"jsonrpc":"2.0","method":"sidechain_importBlock","params":["SophisticatedInvalidParam"],"id":1}"#; - - let response_string = io.handle_request_sync(enclave_req).unwrap(); - - let err_msg = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid parameters: Could not decode Vec","data":"[\"SophisticatedInvalidParam\"]"},"id":1}"#; - assert_eq!(response_string, err_msg); - } - - pub fn sidechain_import_block_returns_decode_err_for_valid_hex() { - let io = io_handler(); - - let enclave_req = - r#"{"jsonrpc":"2.0","method":"sidechain_importBlock","params": ["0x11"],"id":1}"#; - - let response_string = io.handle_request_sync(enclave_req).unwrap(); - - let err_msg = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid parameters: Could not decode Vec","data":"[17]"},"id":1}"#; - assert_eq!(response_string, err_msg); - } -} diff --git a/bitacross-worker/sidechain/rpc-handler/src/lib.rs b/bitacross-worker/sidechain/rpc-handler/src/lib.rs deleted file mode 100644 index 5daf1d1f7e..0000000000 --- a/bitacross-worker/sidechain/rpc-handler/src/lib.rs +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#![feature(trait_alias)] -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -extern crate core; -#[cfg(all(not(feature = "std"), feature = "sgx"))] -extern crate sgx_tstd as std; - -// re-export module to properly feature gate sgx and regular std environment -#[cfg(all(not(feature = "std"), feature = "sgx"))] -pub mod sgx_reexport_prelude { - pub use futures_sgx as futures; - pub use jsonrpc_core_sgx as jsonrpc_core; - pub use rust_base58_sgx as base58; -} - -pub mod constants; -pub mod direct_top_pool_api; -pub mod import_block_api; diff --git a/bitacross-worker/sidechain/sidechain-crate/Cargo.toml b/bitacross-worker/sidechain/sidechain-crate/Cargo.toml deleted file mode 100644 index dee5728123..0000000000 --- a/bitacross-worker/sidechain/sidechain-crate/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "its-sidechain" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[features] -default = ["std"] -std = [ - "its-block-composer/std", - "its-consensus-aura/std", - "its-consensus-common/std", - "its-consensus-slots/std", - "its-rpc-handler/std", - "its-primitives/std", - "its-state/std", - "its-validateer-fetch/std", -] -sgx = [ - "its-block-composer/sgx", - "its-consensus-aura/sgx", - "its-consensus-common/sgx", - "its-consensus-slots/sgx", - "its-rpc-handler/sgx", - "its-state/sgx", -] - -[dependencies] -its-block-composer = { path = "../block-composer", default-features = false } -its-consensus-aura = { path = "../consensus/aura", default-features = false } -its-consensus-common = { path = "../consensus/common", default-features = false } -its-consensus-slots = { path = "../consensus/slots", default-features = false } -its-primitives = { path = "../primitives", default-features = false } -its-rpc-handler = { path = "../rpc-handler", default-features = false } -its-state = { path = "../state", default-features = false } -its-validateer-fetch = { path = "../validateer-fetch", default-features = false } diff --git a/bitacross-worker/sidechain/sidechain-crate/src/lib.rs b/bitacross-worker/sidechain/sidechain-crate/src/lib.rs deleted file mode 100644 index 59821318a8..0000000000 --- a/bitacross-worker/sidechain/sidechain-crate/src/lib.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Reexport all the sidechain stuff in one crate - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -pub use its_block_composer as block_composer; - -pub use its_consensus_aura as aura; - -pub use its_consensus_common as consensus_common; - -pub use its_consensus_slots as slots; - -pub use its_primitives as primitives; - -pub use its_rpc_handler as rpc_handler; - -pub use its_state as state; - -pub use its_validateer_fetch as validateer_fetch; diff --git a/bitacross-worker/sidechain/state/Cargo.toml b/bitacross-worker/sidechain/state/Cargo.toml deleted file mode 100644 index 538fb34c50..0000000000 --- a/bitacross-worker/sidechain/state/Cargo.toml +++ /dev/null @@ -1,56 +0,0 @@ -[package] -name = "its-state" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "chain-error"] } -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -log = { version = "0.4", default-features = false } - -# optional std deps -thiserror = { version = "1.0.9", optional = true } - -# sgx deps -sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } - -# sgx forks -thiserror_sgx = { package = "thiserror", version = "1.0.9", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } - -# local deps -itp-sgx-externalities = { default-features = false, path = "../../core-primitives/substrate-sgx/externalities" } -itp-storage = { path = "../../core-primitives/storage", default-features = false } -its-primitives = { path = "../primitives", default-features = false } -sp-io = { optional = true, default-features = false, features = ["disable_oom", "disable_panic_handler", "disable_allocator"], path = "../../core-primitives/substrate-sgx/sp-io" } - -# substrate deps -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -[features] -default = ["std"] -std = [ - "log/std", - # substrate - "sp-core/std", - # local crates - "itp-sgx-externalities/std", - "itp-storage/std", - "its-primitives/std", - "sp-io/std", - # optional std crates - "codec/std", - "thiserror", - "sp-runtime/std", -] -sgx = [ - # teaclave - "sgx_tstd", - # local crates - "itp-sgx-externalities/sgx", - "itp-storage/sgx", - "sp-io/sgx", - # sgx versions of std crates - "thiserror_sgx", -] diff --git a/bitacross-worker/sidechain/state/src/error.rs b/bitacross-worker/sidechain/state/src/error.rs deleted file mode 100644 index 82838b376e..0000000000 --- a/bitacross-worker/sidechain/state/src/error.rs +++ /dev/null @@ -1,31 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexports::*; - -use std::string::String; - -#[derive(Debug, thiserror::Error, PartialEq, Eq)] -pub enum Error { - #[error("Invalid apriori state hash supplied")] - InvalidAprioriHash, - #[error("Invalid storage diff")] - InvalidStorageDiff, - #[error("Codec error when accessing module: {1}, storage: {2}. Error: {0:?}")] - DB(codec::Error, String, String), -} diff --git a/bitacross-worker/sidechain/state/src/impls.rs b/bitacross-worker/sidechain/state/src/impls.rs deleted file mode 100644 index b69727085c..0000000000 --- a/bitacross-worker/sidechain/state/src/impls.rs +++ /dev/null @@ -1,184 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Implement the sidechain state traits. - -use crate::{Error, SidechainState, StateUpdate}; -use codec::{Decode, Encode}; -use core::fmt::Debug; -use frame_support::ensure; -use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; -use itp_storage::keys::storage_value_key; -use log::{debug, error, info}; -use sp_io::{storage, KillStorageResult}; - -impl SidechainState for T -where - ::SgxExternalitiesType: Encode, -{ - type Externalities = Self; - type StateUpdate = StateUpdate; - - fn apply_state_update(&mut self, state_payload: &Self::StateUpdate) -> Result<(), Error> { - info!("Current state size: {}", self.state().encoded_size()); - debug!("Current hash: {}", self.hash()); - debug!("State_payload hash: {}", state_payload.state_hash_apriori()); - debug!("self is: {:?}", &self); - debug!("state_payload is: {:?}", &state_payload); - ensure!(self.hash() == state_payload.state_hash_apriori(), Error::InvalidAprioriHash); - - self.execute_with(|| { - state_payload.state_update.iter().for_each(|(k, v)| { - match v { - Some(value) => storage::set(k, value), - None => storage::clear(k), - }; - }) - }); - - ensure!(self.hash() == state_payload.state_hash_aposteriori(), Error::InvalidStorageDiff); - self.prune_state_diff(); - Ok(()) - } - - fn get_with_name(&self, module_prefix: &str, storage_prefix: &str) -> Option { - let res = self - .get(&storage_value_key(module_prefix, storage_prefix)) - .map(|v| Decode::decode(&mut v.as_slice())) - .transpose(); - - match res { - Ok(res) => res, - Err(e) => { - error!( - "Error decoding storage: {}, {}. Error: {:?}", - module_prefix, storage_prefix, e - ); - None - }, - } - } - - fn set_with_name(&mut self, module_prefix: &str, storage_prefix: &str, value: V) { - self.set(&storage_value_key(module_prefix, storage_prefix), &value.encode()) - } - - fn clear_with_name(&mut self, module_prefix: &str, storage_prefix: &str) { - self.clear(&storage_value_key(module_prefix, storage_prefix)) - } - - fn clear_prefix_with_name( - &mut self, - module_prefix: &str, - storage_prefix: &str, - ) -> KillStorageResult { - self.clear_sidechain_prefix(&storage_value_key(module_prefix, storage_prefix)) - } - - fn set(&mut self, key: &[u8], value: &[u8]) { - self.execute_with(|| sp_io::storage::set(key, value)) - } - - fn clear(&mut self, key: &[u8]) { - self.execute_with(|| sp_io::storage::clear(key)) - } - - fn clear_sidechain_prefix(&mut self, prefix: &[u8]) -> KillStorageResult { - self.execute_with(|| sp_io::storage::clear_prefix(prefix, None)) - } -} - -#[cfg(test)] -pub mod tests { - use super::*; - use crate::StateUpdate; - use frame_support::{assert_err, assert_ok}; - use itp_sgx_externalities::{SgxExternalities, SgxExternalitiesTrait}; - use sp_core::H256; - - pub fn default_db() -> SgxExternalities { - SgxExternalities::default() - } - - #[test] - pub fn apply_state_update_works() { - let mut state1 = default_db(); - let mut state2 = default_db(); - - let apriori = state1.hash(); - state1.set(b"Hello", b"World"); - let aposteriori = state1.hash(); - - let mut state_update = StateUpdate::new(apriori, aposteriori, state1.state_diff().clone()); - - assert_ok!(state2.apply_state_update(&mut state_update)); - assert_eq!(state2.hash(), aposteriori); - assert_eq!(state2.get(b"Hello").unwrap(), b"World"); - assert!(state2.state_diff().is_empty()); - } - - #[test] - pub fn apply_state_update_returns_storage_hash_mismatch_err() { - let mut state1 = default_db(); - let mut state2 = default_db(); - - let apriori = H256::from([1; 32]); - state1.set(b"Hello", b"World"); - let aposteriori = state1.hash(); - - let mut state_update = StateUpdate::new(apriori, aposteriori, state1.state_diff().clone()); - - assert_err!(state2.apply_state_update(&mut state_update), Error::InvalidAprioriHash); - assert_eq!(state2, default_db()); - } - - #[test] - pub fn apply_state_update_returns_invalid_storage_diff_err() { - let mut state1 = default_db(); - let mut state2 = default_db(); - - let apriori = state1.hash(); - state1.set(b"Hello", b"World"); - let aposteriori = H256::from([1; 32]); - - let mut state_update = StateUpdate::new(apriori, aposteriori, state1.state_diff().clone()); - - assert_err!(state2.apply_state_update(&mut state_update), Error::InvalidStorageDiff); - // After an error, the state is not guaranteed to be reverted and is potentially corrupted! - assert_ne!(state2, default_db()); - } - - #[test] - pub fn sp_io_storage_set_creates_storage_diff() { - let mut state1 = default_db(); - - state1.execute_with(|| { - storage::set(b"hello", b"world"); - }); - - assert_eq!(state1.state_diff().get(&b"hello"[..]).unwrap(), &Some(b"world".encode())); - } - - #[test] - pub fn create_state_diff_without_setting_externalities_works() { - let mut state1 = default_db(); - - state1.set(b"hello", b"world"); - - assert_eq!(state1.state_diff().get(&b"hello"[..]).unwrap(), &Some(b"world".encode())); - } -} diff --git a/bitacross-worker/sidechain/state/src/lib.rs b/bitacross-worker/sidechain/state/src/lib.rs deleted file mode 100644 index 01f5e086ec..0000000000 --- a/bitacross-worker/sidechain/state/src/lib.rs +++ /dev/null @@ -1,208 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -extern crate sgx_tstd as std; - -mod error; -mod impls; - -pub use error::*; -pub use impls::*; - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -mod sgx_reexports { - pub use thiserror_sgx as thiserror; -} - -use codec::{Decode, Encode}; -use itp_sgx_externalities::{SgxExternalitiesDiffType, SgxExternalitiesTrait, StateHash}; -use its_primitives::{ - traits::Block as SidechainBlockTrait, - types::{BlockHash, BlockNumber, Timestamp}, -}; -use sp_core::H256; -use sp_io::KillStorageResult; -use sp_runtime::traits::Header as ParentchainHeaderTrait; - -/// Contains the necessary data to update the `SidechainDB` when importing a `SidechainBlock`. -#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] -pub struct StateUpdate { - /// state hash before the `state_update` was applied. - state_hash_apriori: H256, - /// state hash after the `state_update` was applied. - state_hash_aposteriori: H256, - /// state diff applied to state with hash `state_hash_apriori` - /// leading to state with hash `state_hash_aposteriori` - state_update: SgxExternalitiesDiffType, -} - -impl StateUpdate { - /// get state hash before the `state_update` was applied. - pub fn state_hash_apriori(&self) -> H256 { - self.state_hash_apriori - } - /// get state hash after the `state_update` was applied. - pub fn state_hash_aposteriori(&self) -> H256 { - self.state_hash_aposteriori - } - /// reference to the `state_update` - pub fn state_update(&self) -> &SgxExternalitiesDiffType { - &self.state_update - } - - /// create new `StatePayload` instance. - pub fn new(apriori: H256, aposteriori: H256, update: SgxExternalitiesDiffType) -> StateUpdate { - StateUpdate { - state_hash_apriori: apriori, - state_hash_aposteriori: aposteriori, - state_update: update, - } - } -} -/// Abstraction around the sidechain state. -pub trait SidechainState: Clone { - type Externalities: SgxExternalitiesTrait + StateHash; - - type StateUpdate: Encode + Decode; - - /// Apply the state update to the state. - /// - /// Does not guarantee state consistency in case of a failure. - /// Caller is responsible for discarding corrupt/inconsistent state. - fn apply_state_update(&mut self, state_payload: &Self::StateUpdate) -> Result<(), Error>; - - /// Get a storage value by its full name. - fn get_with_name(&self, module_prefix: &str, storage_prefix: &str) -> Option; - - /// Set a storage value by its full name. - fn set_with_name(&mut self, module_prefix: &str, storage_prefix: &str, value: V); - - /// Clear a storage value by its full name. - fn clear_with_name(&mut self, module_prefix: &str, storage_prefix: &str); - - /// Clear all storage values for the given prefix. - fn clear_prefix_with_name( - &mut self, - module_prefix: &str, - storage_prefix: &str, - ) -> KillStorageResult; - - /// Set a storage value by its storage hash. - fn set(&mut self, key: &[u8], value: &[u8]); - - /// Clear a storage value by its storage hash. - fn clear(&mut self, key: &[u8]); - - /// Clear a all storage values starting the given prefix. - fn clear_sidechain_prefix(&mut self, prefix: &[u8]) -> KillStorageResult; -} - -/// trait to set and get the last sidechain block of the sidechain state -pub trait LastBlockExt { - /// get the last block of the sidechain state - fn get_last_block(&self) -> Option; - - /// set the last block of the sidechain state - fn set_last_block(&mut self, block: &SidechainBlock); -} - -impl - LastBlockExt for E -{ - fn get_last_block(&self) -> Option { - self.get_with_name("System", "LastBlock") - } - - fn set_last_block(&mut self, block: &SidechainBlock) { - self.set_last_block_hash(&block.hash()); - self.set_with_name("System", "LastBlock", block) - } -} - -/// System extension for the `SidechainDB`. -pub trait SidechainSystemExt { - /// Get the last block number. - fn get_block_number(&self) -> Option; - - /// Set the last block number. - fn set_block_number(&mut self, number: &BlockNumber); - - /// Get the last block hash. - fn get_last_block_hash(&self) -> Option; - - /// Set the last block hash. - fn set_last_block_hash(&mut self, hash: &BlockHash); - - /// Get the timestamp of. - fn get_timestamp(&self) -> Option; - - /// Set the timestamp. - fn set_timestamp(&mut self, timestamp: &Timestamp); - - /// Resets the events. - fn reset_events(&mut self); - - /// Litentry: set the parentchain block number from the parentchain header - /// The reasons to put it here instead of calling `ParentchainPalletInterface::update_parentchain_block` somewhere are: - /// 1. The Stf::update_parentchain_block is too heavy weighted, where the whole state is loaded upon each parentchain - /// block import - btw it's not reachable for now as `storage_hashes_to_update_on_block` is always empty - /// 2. It represents the parentchain block number on which the current sidechain block is built, it's more natural to - /// call it in the state preprocessing before proposing a sidechain block - fn set_parentchain_block_number(&mut self, header: &PH); -} - -impl SidechainSystemExt for T { - fn get_block_number(&self) -> Option { - self.get_with_name("System", "Number") - } - - fn set_block_number(&mut self, number: &BlockNumber) { - self.set_with_name("System", "Number", number) - } - - fn get_last_block_hash(&self) -> Option { - self.get_with_name("System", "LastHash") - } - - fn set_last_block_hash(&mut self, hash: &BlockHash) { - self.set_with_name("System", "LastHash", hash) - } - - fn get_timestamp(&self) -> Option { - self.get_with_name("System", "Timestamp") - } - - fn set_timestamp(&mut self, timestamp: &Timestamp) { - self.set_with_name("System", "Timestamp", timestamp) - } - - fn reset_events(&mut self) { - self.clear_with_name("System", "Events"); - self.clear_with_name("System", "EventCount"); - self.clear_prefix_with_name("System", "EventTopics"); - } - - fn set_parentchain_block_number(&mut self, header: &PH) { - self.set_with_name("Parentchain", "Number", header.number()) - } -} diff --git a/bitacross-worker/sidechain/storage/Cargo.toml b/bitacross-worker/sidechain/storage/Cargo.toml deleted file mode 100644 index 7df586896f..0000000000 --- a/bitacross-worker/sidechain/storage/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "its-storage" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -# crate.io -codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } -log = "0.4" -parking_lot = "0.12.1" -rocksdb = { version = "0.20.1", default_features = false } -serde = { version = "1.0", features = ["derive"] } -thiserror = "1.0" - -# integritee -itp-settings = { path = "../../core-primitives/settings" } - -its-primitives = { path = "../primitives" } - -# Substrate dependencies -sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -[dev-dependencies] -# crate.io -mockall = "0.11" -temp-dir = "0.1" -# local -itp-time-utils = { path = "../../core-primitives/time-utils" } -its-test = { path = "../test" } -itp-types = { path = "../../core-primitives/types" } - -[features] -mocks = [] diff --git a/bitacross-worker/sidechain/storage/src/db.rs b/bitacross-worker/sidechain/storage/src/db.rs deleted file mode 100644 index 6e51a749fb..0000000000 --- a/bitacross-worker/sidechain/storage/src/db.rs +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use super::{Error, Result}; -use codec::{Decode, Encode}; -use rocksdb::{WriteBatch, DB}; -use std::path::PathBuf; - -/// Sidechain DB Storage structure: -/// STORED_SHARDS_KEY -> Vec<(Shard)> -/// (LAST_BLOCK_KEY, Shard) -> (Blockhash, BlockNr) (look up current blockchain state) -/// (Shard , Block number) -> Blockhash (needed for block pruning) -/// Blockhash -> Signed Block (actual block storage) - -/// Interface struct to rocks DB -pub struct SidechainDB { - db: DB, -} - -impl SidechainDB { - pub fn open_default(path: PathBuf) -> Result { - Ok(SidechainDB { db: DB::open_default(path)? }) - } - - /// returns the decoded value of the DB entry, if there is one - pub fn get(&self, key: K) -> Result> { - match self.db.get(key.encode())? { - None => Ok(None), - Some(encoded_hash) => Ok(Some(V::decode(&mut encoded_hash.as_slice())?)), - } - } - - /// writes a batch to the DB - pub fn write(&mut self, batch: WriteBatch) -> Result<()> { - self.db.write(batch).map_err(Error::Operational) - } - - /// adds a given key value pair to the batch - pub fn add_to_batch(batch: &mut WriteBatch, key: K, value: V) { - batch.put(key.encode(), &value.encode()) - } - - /// adds a delte key command to the batch - pub fn delete_to_batch(batch: &mut WriteBatch, key: K) { - batch.delete(key.encode()) - } - - /// add an entry to the DB - #[cfg(test)] - pub fn put(&mut self, key: K, value: V) -> Result<()> { - self.db.put(key.encode(), value.encode()).map_err(Error::Operational) - } -} diff --git a/bitacross-worker/sidechain/storage/src/error.rs b/bitacross-worker/sidechain/storage/src/error.rs deleted file mode 100644 index 983909f1a4..0000000000 --- a/bitacross-worker/sidechain/storage/src/error.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use thiserror::Error; - -pub type Result = std::result::Result; - -#[derive(Error, Debug)] -pub enum Error { - #[error("Could not interact with file storage: {0:?}")] - Operational(#[from] rocksdb::Error), - #[error("Last Block of shard {0} not found")] - LastBlockNotFound(String), - #[error("Failed to find parent block")] - FailedToFindParentBlock, - #[error("Could not decode: {0:?}")] - Decode(#[from] codec::Error), - #[error("Given block is not a successor of the last known block")] - HeaderAncestryMismatch, -} diff --git a/bitacross-worker/sidechain/storage/src/fetch_blocks_mock.rs b/bitacross-worker/sidechain/storage/src/fetch_blocks_mock.rs deleted file mode 100644 index 4ba476164d..0000000000 --- a/bitacross-worker/sidechain/storage/src/fetch_blocks_mock.rs +++ /dev/null @@ -1,71 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{error::Result, interface::FetchBlocks, storage::LastSidechainBlock}; -use its_primitives::{ - traits::{Block, ShardIdentifierFor}, - types::{BlockHash, BlockNumber, SignedBlock}, -}; - -#[derive(Default)] -pub struct FetchBlocksMock { - blocks_to_be_fetched: Vec, -} - -impl FetchBlocksMock { - pub fn with_blocks(mut self, blocks: Vec) -> Self { - self.blocks_to_be_fetched = blocks; - self - } -} - -impl FetchBlocks for FetchBlocksMock { - fn fetch_all_blocks_after( - &self, - _block_hash: &BlockHash, - _shard_identifier: &ShardIdentifierFor, - ) -> Result> { - Ok(self.blocks_to_be_fetched.clone()) - } - - fn fetch_blocks_in_range( - &self, - _block_hash_from: &BlockHash, - _block_hash_until: &BlockHash, - _shard_identifier: &ShardIdentifierFor, - ) -> Result> { - Ok(self.blocks_to_be_fetched.clone()) - } - - fn latest_block( - &self, - _shard_identifier: &ShardIdentifierFor, - ) -> Option { - self.blocks_to_be_fetched.get(0).map(|block| LastSidechainBlock { - hash: block.block.hash(), - number: block.block.header.block_number, - }) - } - - fn block_hash( - &self, - _block_number: BlockNumber, - _shard_identifier: &ShardIdentifierFor, - ) -> Option { - None - } -} diff --git a/bitacross-worker/sidechain/storage/src/interface.rs b/bitacross-worker/sidechain/storage/src/interface.rs deleted file mode 100644 index 03b41d6d76..0000000000 --- a/bitacross-worker/sidechain/storage/src/interface.rs +++ /dev/null @@ -1,154 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(test)] -use mockall::predicate::*; -#[cfg(test)] -use mockall::*; - -use super::{ - storage::{LastSidechainBlock, SidechainStorage}, - Result, -}; -use its_primitives::{ - traits::{ShardIdentifierFor, SignedBlock as SignedBlockT}, - types::{BlockHash, BlockNumber}, -}; -use parking_lot::RwLock; -use std::path::PathBuf; - -/// Lock wrapper around sidechain storage -pub struct SidechainStorageLock { - storage: RwLock>, -} - -impl SidechainStorageLock { - pub fn from_base_path(path: PathBuf) -> Result> { - Ok(SidechainStorageLock { - storage: RwLock::new(SidechainStorage::::load_from_base_path(path)?), - }) - } -} - -/// Storage interface Trait -#[cfg_attr(test, automock)] -pub trait BlockStorage { - // Type is not working because broadcaster needs to work with the same block type, - // so it needs to be defined somewhere more global. - // type SignedBlock: SignedBlockT; - fn store_blocks(&self, blocks: Vec) -> Result<()>; -} - -pub trait BlockPruner { - /// Prune all blocks except the newest n, where n = `number_of_blocks_to_keep`. - fn prune_blocks_except(&self, number_of_blocks_to_keep: u64); -} - -#[cfg_attr(test, automock)] -pub trait FetchBlocks { - /// Fetch all child blocks of a specified block. - /// - /// Returns an empty vector if specified block hash cannot be found in storage. - fn fetch_all_blocks_after( - &self, - block_hash: &BlockHash, - shard_identifier: &ShardIdentifierFor, - ) -> Result>; - - /// Fetch all blocks within a range, defined by a starting block (lower bound) and end block (upper bound) hash. - /// - /// Does NOT include the bound defining blocks in the result. ]from..until[. - /// Returns an empty vector if 'from' cannot be found in storage. - /// Returns the same as 'fetch_all_blocks_after' if 'until' cannot be found in storage. - fn fetch_blocks_in_range( - &self, - block_hash_from: &BlockHash, - block_hash_until: &BlockHash, - shard_identifier: &ShardIdentifierFor, - ) -> Result>; - - // litentry - fn latest_block( - &self, - shard_identifier: &ShardIdentifierFor, - ) -> Option; - - fn block_hash( - &self, - block_number: BlockNumber, - shard_identifier: &ShardIdentifierFor, - ) -> Option; -} - -impl BlockStorage for SidechainStorageLock { - fn store_blocks(&self, blocks: Vec) -> Result<()> { - self.storage.write().store_blocks(blocks) - } -} - -impl BlockPruner for SidechainStorageLock { - fn prune_blocks_except(&self, number_of_blocks_to_keep: BlockNumber) { - self.storage.write().prune_shards(number_of_blocks_to_keep); - } -} - -impl FetchBlocks for SidechainStorageLock { - fn fetch_all_blocks_after( - &self, - block_hash: &BlockHash, - shard_identifier: &ShardIdentifierFor, - ) -> Result> { - self.storage.read().get_blocks_after(block_hash, shard_identifier) - } - - fn fetch_blocks_in_range( - &self, - block_hash_from: &BlockHash, - block_hash_until: &BlockHash, - shard_identifier: &ShardIdentifierFor, - ) -> Result> { - self.storage - .read() - .get_blocks_in_range(block_hash_from, block_hash_until, shard_identifier) - } - - fn latest_block( - &self, - shard_identifier: &ShardIdentifierFor, - ) -> Option { - self.storage - .read() - .last_block_of_shard(shard_identifier) - .map(|e| LastSidechainBlock { hash: e.hash, number: e.number }) - } - - fn block_hash( - &self, - block_number: BlockNumber, - shard_identifier: &ShardIdentifierFor, - ) -> Option { - match self.storage.read().get_block_hash(shard_identifier, block_number) { - Ok(Some(block_hash)) => - Some(LastSidechainBlock { hash: block_hash, number: block_number }), - Ok(None) => None, - Err(e) => { - log::error!("failed to get block_hash. due to:{:?}", e); - None - }, - } - } -} diff --git a/bitacross-worker/sidechain/storage/src/lib.rs b/bitacross-worker/sidechain/storage/src/lib.rs deleted file mode 100644 index 7b6030ff90..0000000000 --- a/bitacross-worker/sidechain/storage/src/lib.rs +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#![cfg_attr(test, feature(assert_matches))] - -use its_primitives::types::BlockNumber; -use std::{ - sync::Arc, - thread, - time::{Duration, SystemTime}, -}; - -mod db; -mod error; -pub mod interface; -mod storage; - -#[cfg(test)] -mod storage_tests_get_blocks_after; - -#[cfg(test)] -mod storage_tests_get_blocks_in_range; - -#[cfg(test)] -mod test_utils; - -#[cfg(feature = "mocks")] -pub mod fetch_blocks_mock; - -pub use error::{Error, Result}; -pub use interface::{BlockPruner, BlockStorage, SidechainStorageLock}; -pub use storage::LastSidechainBlock; - -pub fn start_sidechain_pruning_loop( - storage: &Arc, - purge_interval: u64, - purge_limit: BlockNumber, -) where - D: BlockPruner, -{ - let interval_time = Duration::from_secs(purge_interval); - let mut interval_start = SystemTime::now(); - loop { - if let Ok(elapsed) = interval_start.elapsed() { - if elapsed >= interval_time { - // update interval time - interval_start = SystemTime::now(); - storage.prune_blocks_except(purge_limit); - } else { - // sleep for the rest of the interval - let sleep_time = interval_time - elapsed; - thread::sleep(sleep_time); - } - } - } -} diff --git a/bitacross-worker/sidechain/storage/src/storage.rs b/bitacross-worker/sidechain/storage/src/storage.rs deleted file mode 100644 index 4e5667627b..0000000000 --- a/bitacross-worker/sidechain/storage/src/storage.rs +++ /dev/null @@ -1,1176 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use super::{db::SidechainDB, Error, Result}; -use codec::{Decode, Encode}; -use itp_settings::files::SIDECHAIN_STORAGE_PATH; -use its_primitives::{ - traits::{Block as BlockTrait, Header as HeaderTrait, SignedBlock as SignedBlockT}, - types::{BlockHash, BlockNumber}, -}; -use log::*; -use rocksdb::WriteBatch; -use serde::Serialize; -use sp_core::H256; -use std::{collections::HashMap, fmt::Debug, path::PathBuf}; - -/// key value of sidechain db of last block -const LAST_BLOCK_KEY: &[u8] = b"last_sidechainblock"; -/// key value of the stored shards vector -const STORED_SHARDS_KEY: &[u8] = b"stored_shards"; - -/// ShardIdentifier type -type ShardIdentifierFor = - <<::Block as BlockTrait>::HeaderType as HeaderTrait>::ShardIdentifier; - -/// Helper struct, contains the blocknumber -/// and blockhash of the last sidechain block -#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, Default, Serialize)] -pub struct LastSidechainBlock { - /// hash of the last sidechain block - pub hash: H256, - /// block number of the last sidechain block - pub number: BlockNumber, -} - -/// Struct used to insert newly produced sidechainblocks -/// into the database -pub struct SidechainStorage { - /// database - db: SidechainDB, - /// shards in database - shards: Vec>, - /// map to last sidechain block of every shard - last_blocks: HashMap, LastSidechainBlock>, -} - -impl SidechainStorage { - /// Loads or initializes the DB at a given path. - /// - /// Loads existing shards and their last blocks in memory for better performance. - pub fn load_from_base_path(base_path: PathBuf) -> Result> { - // load db - let db = SidechainDB::open_default(base_path.join(SIDECHAIN_STORAGE_PATH))?; - let mut storage = SidechainStorage { db, shards: vec![], last_blocks: HashMap::new() }; - storage.shards = storage.load_shards_from_db()?; - // get last block of each shard - for shard in storage.shards.iter() { - if let Some(last_block) = storage.load_last_block_from_db(shard)? { - storage.last_blocks.insert(*shard, last_block); - } else { - // an empty shard sidechain storage should not exist. Consider deleting this shard from the shards list. - error!("Sidechain storage of shard {:?} is empty", shard); - } - } - Ok(storage) - } - - /// gets all shards of currently loaded sidechain db - pub fn shards(&self) -> &Vec> { - &self.shards - } - - /// gets the last block of the current sidechain DB and the given shard - pub fn last_block_of_shard( - &self, - shard: &ShardIdentifierFor, - ) -> Option<&LastSidechainBlock> { - self.last_blocks.get(shard) - } - - /// gets the block hash of the sidechain block of the given shard and block number, if there is such a block - pub fn get_block_hash( - &self, - shard: &ShardIdentifierFor, - block_number: BlockNumber, - ) -> Result> { - self.db.get((*shard, block_number)) - } - - /// gets the block of the given blockhash, if there is such a block - #[allow(unused)] - pub fn get_block(&self, block_hash: &BlockHash) -> Result> { - self.db.get(block_hash) - } - - /// Get all blocks after (i.e. children of) a specified block. - pub fn get_blocks_after( - &self, - block_hash: &BlockHash, - shard_identifier: &ShardIdentifierFor, - ) -> Result> { - // Ensure we find the block in storage (otherwise we would return all blocks for a specific shard). - // The exception is, if the hash is the default hash, which represents block 0. In that case we want to return all blocks. - if block_hash != &BlockHash::default() && self.get_block(block_hash)?.is_none() { - warn!("Could not find starting block in storage, returning empty vector"); - return Ok(Vec::new()) - } - - // We get the latest block and then traverse the parents until we find our starting block. - let last_block_of_shard = self.last_block_of_shard(shard_identifier).ok_or_else(|| { - Error::LastBlockNotFound("Failed to find last block information".to_string()) - })?; - let latest_block = self.get_block(&last_block_of_shard.hash)?.ok_or_else(|| { - Error::LastBlockNotFound("Failed to retrieve last block from storage".to_string()) - })?; - - let mut current_block = latest_block; - let mut blocks_to_return = Vec::::new(); - while ¤t_block.hash() != block_hash { - let parent_block_hash = current_block.block().header().parent_hash(); - - blocks_to_return.push(current_block); - - if parent_block_hash == BlockHash::default() { - break - } - - current_block = - self.get_block(&parent_block_hash)?.ok_or(Error::FailedToFindParentBlock)?; - } - - // Reverse because we iterate from newest to oldest, but result should be oldest first. - blocks_to_return.reverse(); - - Ok(blocks_to_return) - } - - /// Get blocks in a range, defined by 'from' and 'until' (result does NOT include the bound defining blocks). - pub fn get_blocks_in_range( - &self, - block_hash_from: &BlockHash, - block_hash_until: &BlockHash, - shard_identifier: &ShardIdentifierFor, - ) -> Result> { - let all_blocks_from_lower_bound = - self.get_blocks_after(block_hash_from, shard_identifier)?; - - Ok(all_blocks_from_lower_bound - .into_iter() - .take_while(|b| b.hash() != *block_hash_until) - .collect()) - } - - /// Update sidechain storage with blocks. - /// - /// Blocks are iterated through one by one. In case more than one block per shard is included, - /// be sure to give them in the correct order (oldest first). - pub fn store_blocks(&mut self, blocks_to_store: Vec) -> Result<()> { - let mut batch = WriteBatch::default(); - let mut new_shard = false; - for block in blocks_to_store.into_iter() { - if let Err(e) = self.add_block_to_batch(&block, &mut new_shard, &mut batch) { - error!("Could not store block {:?} due to: {:?}", block, e); - }; - } - // Update stored_shards_key -> vec only if a new shard was included, - if new_shard { - SidechainDB::add_to_batch(&mut batch, STORED_SHARDS_KEY, self.shards().clone()); - } - // Store everything. - self.db.write(batch) - } - - /// purges a shard and its block from the db storage - pub fn purge_shard(&mut self, shard: &ShardIdentifierFor) -> Result<()> { - // get last block of shard - let last_block = self.get_last_block_of_shard(shard)?; - - // remove last block from db storage - let mut batch = WriteBatch::default(); - self.delete_last_block(&mut batch, &last_block, shard); - - // Remove the rest of the blocks from the db - let mut current_block_number = last_block.number; - while let Some(previous_block) = self.get_previous_block(shard, current_block_number)? { - current_block_number = previous_block.number; - self.delete_block(&mut batch, &previous_block.hash, ¤t_block_number, shard); - } - // Remove shard from list. - // STORED_SHARDS_KEY -> Vec<(Shard)> - self.shards.retain(|&x| x != *shard); - // Add updated shards to batch. - SidechainDB::add_to_batch(&mut batch, STORED_SHARDS_KEY, &self.shards); - // Update DB - self.db.write(batch) - } - - /// purges a shard and its block from the db storage - /// FIXME: Add delete functions? - pub fn prune_shard_from_block_number( - &mut self, - shard: &ShardIdentifierFor, - block_number: BlockNumber, - ) -> Result<()> { - let last_block = self.get_last_block_of_shard(shard)?; - if last_block.number == block_number { - // given block number is last block of chain - purge whole shard - self.purge_shard(shard) - } else { - // iterate through chain and add all blocks to WriteBatch (delete cmd) - let mut batch = WriteBatch::default(); - let mut current_block_number = block_number; - // Remove blocks from db until no block anymore - while let Some(block_hash) = self.get_block_hash(shard, current_block_number)? { - self.delete_block(&mut batch, &block_hash, ¤t_block_number, shard); - current_block_number -= 1; - } - // Update DB - self.db.write(batch) - } - } - - /// Prunes all shards except for the newest blocks (according to blocknumber). - pub fn prune_shards(&mut self, number_of_blocks_to_keep: BlockNumber) { - for shard in self.shards().clone() { - // get last block: - if let Some(last_block) = self.last_block_of_shard(&shard) { - let threshold_block = last_block.number - number_of_blocks_to_keep; - if let Err(e) = self.prune_shard_from_block_number(&shard, threshold_block) { - error!("Could not purge shard {:?} due to {:?}", shard, e); - } - } else { - error!("Last block not found in shard {:?}", shard); - } - } - } - - fn add_block_to_batch( - &mut self, - signed_block: &SignedBlock, - new_shard: &mut bool, - batch: &mut WriteBatch, - ) -> Result<()> { - let shard = &signed_block.block().header().shard_id(); - if self.shards.contains(shard) { - if !self.verify_block_ancestry(signed_block.block()) { - // Do not include block if its not a direct ancestor of the last block in line. - return Err(Error::HeaderAncestryMismatch) - } - } else { - self.shards.push(*shard); - *new_shard = true; - } - // Add block to DB batch. - self.add_last_block(batch, signed_block); - Ok(()) - } - - fn verify_block_ancestry(&self, block: &::Block) -> bool { - let shard = &block.header().shard_id(); - let current_block_nr = block.header().block_number(); - if let Some(last_block) = self.last_block_of_shard(shard) { - if last_block.number != current_block_nr - 1 { - error!("[Sidechain DB] Sidechainblock (nr: {:?}) is not a succession of the previous block (nr: {:?}) in shard: {:?}", - current_block_nr, last_block.number, *shard); - return false - } - } else { - error!( - "[Sidechain DB] Shard {:?} does not have a last block. Skipping block (nr: {:?}) inclusion", - *shard, current_block_nr - ); - return false - } - true - } - - /// Implementations of helper functions, not meant for pub use - /// gets the previous block of given shard and block number, if there is one. - fn get_previous_block( - &self, - shard: &ShardIdentifierFor, - current_block_number: BlockNumber, - ) -> Result> { - let prev_block_number = current_block_number - 1; - Ok(self - .get_block_hash(shard, prev_block_number)? - .map(|block_hash| LastSidechainBlock { hash: block_hash, number: prev_block_number })) - } - fn load_shards_from_db(&self) -> Result>> { - Ok(self.db.get(STORED_SHARDS_KEY)?.unwrap_or_default()) - } - - fn load_last_block_from_db( - &self, - shard: &ShardIdentifierFor, - ) -> Result> { - self.db.get((LAST_BLOCK_KEY, *shard)) - } - - fn get_last_block_of_shard( - &self, - shard: &ShardIdentifierFor, - ) -> Result { - match self.last_blocks.get(shard) { - Some(last_block) => Ok(*last_block), - None => { - // Try to read from db: - self.load_last_block_from_db(shard)? - .ok_or_else(|| Error::LastBlockNotFound(format!("{:?}", *shard))) - }, - } - } - - /// Adds the block to the WriteBatch. - fn add_last_block(&mut self, batch: &mut WriteBatch, block: &SignedBlock) { - let hash = block.hash(); - let block_number = block.block().header().block_number(); - let shard = block.block().header().shard_id(); - // Block hash -> Signed Block. - SidechainDB::add_to_batch(batch, hash, block); - - // (Shard, Block number) -> Blockhash (for block pruning). - SidechainDB::add_to_batch(batch, (shard, block_number), hash); - - // (last_block_key, shard) -> (Blockhash, BlockNr) current blockchain state. - let last_block = LastSidechainBlock { hash, number: block_number }; - self.last_blocks.insert(shard, last_block); // add in memory - SidechainDB::add_to_batch(batch, (LAST_BLOCK_KEY, shard), last_block); - } - - /// Add delete block to the WriteBatch. - fn delete_block( - &self, - batch: &mut WriteBatch, - block_hash: &H256, - block_number: &BlockNumber, - shard: &ShardIdentifierFor, - ) { - // Block hash -> Signed Block. - SidechainDB::delete_to_batch(batch, block_hash); - // (Shard, Block number) -> Blockhash (for block pruning). - SidechainDB::delete_to_batch(batch, (shard, block_number)); - } - - /// Add delete command to remove last block to WriteBatch and remove it from memory. - /// - /// This includes adding a delete command of the following: - /// - Block hash -> Signed Block. - /// - (Shard, Block number) -> Blockhash (for block pruning). - /// - ((LAST_BLOCK_KEY, shard) -> BlockHash) -> Blockhash (for block pruning). - /// - /// Careful usage of this command: In case the last block is deleted, (LAST_BLOCK_KEY, shard) will be empty - /// even though there might be a new last block (i.e. the previous block of the removed last block). - fn delete_last_block( - &mut self, - batch: &mut WriteBatch, - last_block: &LastSidechainBlock, - shard: &ShardIdentifierFor, - ) { - // Add delete block to batch. - // (LAST_BLOCK_KEY, Shard) -> LastSidechainBlock. - SidechainDB::delete_to_batch(batch, (LAST_BLOCK_KEY, *shard)); - self.delete_block(batch, &last_block.hash, &last_block.number, shard); - - // Delete last block from local memory. - // Careful here: This deletes the local memory before db has been actually pruned - // (it's only been added to the write batch). - // But this can be fixed upon reloading the db / restarting the worker. - self.last_blocks.remove(shard); - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::test_utils::{ - create_signed_block_with_shard as create_signed_block, create_temp_dir, get_storage, - }; - use itp_types::ShardIdentifier; - use its_primitives::{traits::SignedBlock as SignedBlockT, types::SignedBlock}; - use sp_core::H256; - - #[test] - fn load_shards_from_db_works() { - // given - let temp_dir = create_temp_dir(); - let shard_one = H256::from_low_u64_be(1); - let shard_two = H256::from_low_u64_be(2); - // when - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // ensure db starts empty - assert_eq!(sidechain_db.load_shards_from_db().unwrap(), vec![]); - // write signed_block to db - sidechain_db.db.put(STORED_SHARDS_KEY, vec![shard_one, shard_two]).unwrap(); - } - - // then - { - // open new DB of same path: - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let loaded_shards = updated_sidechain_db.load_shards_from_db().unwrap(); - assert!(loaded_shards.contains(&shard_one)); - assert!(loaded_shards.contains(&shard_two)); - } - } - - #[test] - fn load_last_block_from_db_works() { - // given - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(20, shard); - let signed_last_block = LastSidechainBlock { - hash: signed_block.hash(), - number: signed_block.block().header().block_number(), - }; - // when - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // ensure db starts empty - assert!(sidechain_db.load_last_block_from_db(&shard).unwrap().is_none()); - // write signed_block to db - sidechain_db.db.put((LAST_BLOCK_KEY, shard), signed_last_block.clone()).unwrap(); - } - - // then - { - // open new DB of same path: - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let loaded_block = - updated_sidechain_db.load_last_block_from_db(&shard).unwrap().unwrap(); - assert_eq!(loaded_block, signed_last_block); - } - } - - #[test] - fn create_new_sidechain_storage_works() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let shard_vector = vec![shard]; - let signed_block = create_signed_block(20, shard); - let signed_last_block = LastSidechainBlock { - hash: signed_block.hash(), - number: signed_block.block().header().block_number(), - }; - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // ensure db starts empty - assert!(sidechain_db.load_last_block_from_db(&shard).unwrap().is_none()); - // write shards to db - sidechain_db.db.put((LAST_BLOCK_KEY, shard), signed_last_block.clone()).unwrap(); - // write shards to db - sidechain_db.db.put(STORED_SHARDS_KEY, shard_vector.clone()).unwrap(); - } - - { - // open new DB of same path: - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - assert_eq!(updated_sidechain_db.shards, shard_vector); - assert_eq!(*updated_sidechain_db.last_blocks.get(&shard).unwrap(), signed_last_block); - } - } - - #[test] - fn add_last_block_works() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let mut batch = WriteBatch::default(); - sidechain_db.add_last_block(&mut batch, &signed_block); - sidechain_db.db.write(batch).unwrap(); - - // ensure DB contains previously stored data: - let last_block = sidechain_db.last_block_of_shard(&shard).unwrap(); - assert_eq!(last_block.number, signed_block.block().header().block_number()); - assert_eq!(last_block.hash, signed_block.hash()); - let stored_block_hash = - sidechain_db.get_block_hash(&shard, last_block.number).unwrap().unwrap(); - assert_eq!(stored_block_hash, signed_block.hash()); - assert_eq!(sidechain_db.get_block(&stored_block_hash).unwrap().unwrap(), signed_block); - } - } - - #[test] - fn delete_block_works() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - { - // fill db - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.db.put(signed_block.hash(), signed_block.clone()).unwrap(); - sidechain_db - .db - .put((shard, signed_block.block().header().block_number()), signed_block.hash()) - .unwrap(); - assert_eq!( - sidechain_db - .db - .get::<(ShardIdentifier, BlockNumber), H256>(( - shard, - signed_block.block().header().block_number() - )) - .unwrap() - .unwrap(), - signed_block.hash() - ); - assert_eq!( - sidechain_db.db.get::(signed_block.hash()).unwrap().unwrap(), - signed_block - ); - - // when - let mut batch = WriteBatch::default(); - sidechain_db.delete_block( - &mut batch, - &signed_block.hash(), - &signed_block.block().header().block_number(), - &shard, - ); - sidechain_db.db.write(batch).unwrap(); - } - - { - // open new DB of same path: - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // ensure DB does not contain block anymore: - assert!(updated_sidechain_db - .db - .get::<(ShardIdentifier, BlockNumber), H256>(( - shard, - signed_block.block().header().block_number() - )) - .unwrap() - .is_none()); - assert!(updated_sidechain_db - .db - .get::(signed_block.hash()) - .unwrap() - .is_none()); - } - } - - #[test] - fn delete_last_block_works() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - let last_block = LastSidechainBlock { - hash: signed_block.hash(), - number: signed_block.block().header().block_number(), - }; - { - // fill db - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.db.put(signed_block.hash(), signed_block.clone()).unwrap(); - sidechain_db - .db - .put((shard, signed_block.block().header().block_number()), signed_block.hash()) - .unwrap(); - sidechain_db.db.put((LAST_BLOCK_KEY, shard), last_block.clone()).unwrap(); - assert_eq!( - sidechain_db - .db - .get::<(ShardIdentifier, BlockNumber), H256>(( - shard, - signed_block.block().header().block_number() - )) - .unwrap() - .unwrap(), - signed_block.hash() - ); - assert_eq!( - sidechain_db.db.get::(signed_block.hash()).unwrap().unwrap(), - signed_block - ); - assert_eq!( - sidechain_db - .db - .get::<(&[u8], ShardIdentifier), LastSidechainBlock>((LAST_BLOCK_KEY, shard)) - .unwrap() - .unwrap(), - last_block - ); - - // when - let mut batch = WriteBatch::default(); - sidechain_db.delete_last_block(&mut batch, &last_block, &shard); - sidechain_db.db.write(batch).unwrap(); - - // then - assert!(sidechain_db.last_blocks.get(&shard).is_none()); - assert!(sidechain_db - .db - .get::<(ShardIdentifier, BlockNumber), H256>(( - shard, - signed_block.block().header().block_number() - )) - .unwrap() - .is_none()); - assert!(sidechain_db - .db - .get::(signed_block.hash()) - .unwrap() - .is_none()); - assert!(sidechain_db - .db - .get::<(&[u8], ShardIdentifier), LastSidechainBlock>((LAST_BLOCK_KEY, shard)) - .unwrap() - .is_none()); - } - } - - #[test] - fn verify_block_ancestry_returns_true_if_correct_successor() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - let last_block = LastSidechainBlock { - hash: signed_block.hash(), - number: signed_block.block().header().block_number(), - }; - let signed_block_two = create_signed_block(9, shard); - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.shards.push(shard); - sidechain_db.last_blocks.insert(shard, last_block); - // when - let result = sidechain_db.verify_block_ancestry(&signed_block_two.block()); - - // then - assert!(result); - } - } - - #[test] - fn verify_block_ancestry_returns_false_if_not_correct_successor() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - let last_block = LastSidechainBlock { - hash: signed_block.hash(), - number: signed_block.block().header().block_number(), - }; - let signed_block_two = create_signed_block(5, shard); - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.shards.push(shard); - sidechain_db.last_blocks.insert(shard, last_block); - - // when - let result = sidechain_db.verify_block_ancestry(&signed_block_two.block()); - - // then - assert!(!result); - } - } - - #[test] - fn verify_block_ancestry_returns_false_no_last_block_registered() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.shards.push(shard); - // when - let result = sidechain_db.verify_block_ancestry(&signed_block.block()); - - // then - assert!(!result); - } - } - - #[test] - fn verify_block_ancestry_returns_false_if_no_shard() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - { - let sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let result = sidechain_db.verify_block_ancestry(&signed_block.block()); - assert!(!result); - } - } - - #[test] - fn add_block_to_batch_works_with_new_shard() { - // given - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - let mut new_shard = false; - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let mut batch = WriteBatch::default(); - assert!(batch.is_empty()); - - sidechain_db - .add_block_to_batch(&signed_block, &mut new_shard, &mut batch) - .unwrap(); - - assert!(new_shard); - assert!(!batch.is_empty()); - } - } - - #[test] - fn add_block_to_batch_does_not_add_shard_if_existent() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - let last_block = LastSidechainBlock { - hash: signed_block.hash(), - number: signed_block.block().header().block_number(), - }; - let signed_block_two = create_signed_block(9, shard); - let mut new_shard = false; - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let mut batch = WriteBatch::default(); - assert!(batch.is_empty()); - sidechain_db.shards.push(shard); - sidechain_db.last_blocks.insert(shard, last_block); - - sidechain_db - .add_block_to_batch(&signed_block_two, &mut new_shard, &mut batch) - .unwrap(); - - assert!(!new_shard); - assert!(!batch.is_empty()); - } - } - - #[test] - fn add_block_to_batch_does_not_add_block_if_not_ancestor() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(8, shard); - let last_block = LastSidechainBlock { - hash: signed_block.hash(), - number: signed_block.block().header().block_number(), - }; - let signed_block_two = create_signed_block(10, shard); - let mut new_shard = false; - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let mut batch = WriteBatch::default(); - sidechain_db.shards.push(shard); - sidechain_db.last_blocks.insert(shard, last_block); - - let result = - sidechain_db.add_block_to_batch(&signed_block_two, &mut new_shard, &mut batch); - - assert!(result.is_err()); - assert!(!new_shard); - assert!(batch.is_empty()); - } - } - - #[test] - fn store_block_works() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block = create_signed_block(20, shard); - let signed_block_vector: Vec = vec![signed_block.clone()]; - - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // db needs to start empty - assert_eq!(sidechain_db.shards, vec![]); - sidechain_db.store_blocks(signed_block_vector).unwrap(); - } - - { - // open new DB of same path: - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // ensure DB contains previously stored data: - assert_eq!(*updated_sidechain_db.shards(), vec![shard]); - let last_block = updated_sidechain_db.last_block_of_shard(&shard).unwrap(); - assert_eq!(last_block.number, signed_block.block().header().block_number()); - assert_eq!(last_block.hash, signed_block.hash()); - let stored_block_hash = - updated_sidechain_db.get_block_hash(&shard, last_block.number).unwrap().unwrap(); - assert_eq!(stored_block_hash, signed_block.hash()); - assert_eq!( - updated_sidechain_db.get_block(&stored_block_hash).unwrap().unwrap(), - signed_block - ); - } - } - - #[test] - fn store_blocks_on_multi_sharding_works() { - let temp_dir = create_temp_dir(); - let shard_one = H256::from_low_u64_be(1); - let shard_two = H256::from_low_u64_be(2); - let signed_block_one = create_signed_block(20, shard_one); - let signed_block_two = create_signed_block(1, shard_two); - - let signed_block_vector: Vec = - vec![signed_block_one.clone(), signed_block_two.clone()]; - - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // db needs to start empty - assert_eq!(sidechain_db.shards, vec![]); - sidechain_db.store_blocks(signed_block_vector).unwrap(); - } - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - assert_eq!(updated_sidechain_db.shards()[0], shard_one); - assert_eq!(updated_sidechain_db.shards()[1], shard_two); - let last_block_one: &LastSidechainBlock = - updated_sidechain_db.last_blocks.get(&shard_one).unwrap(); - let last_block_two: &LastSidechainBlock = - updated_sidechain_db.last_blocks.get(&shard_two).unwrap(); - assert_eq!(last_block_one.number, 20); - assert_eq!(last_block_two.number, 1); - assert_eq!(last_block_one.hash, signed_block_one.hash()); - assert_eq!(last_block_two.hash, signed_block_two.hash()); - } - } - - #[test] - fn store_mulitple_block_on_one_shard_works() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block_one = create_signed_block(20, shard); - let signed_block_two = create_signed_block(21, shard); - let signed_block_vector_one = vec![signed_block_one.clone()]; - let signed_block_vector_two = vec![signed_block_two.clone()]; - - { - // first iteration - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(signed_block_vector_one).unwrap(); - } - { - // second iteration - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(signed_block_vector_two).unwrap(); - } - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // last block is really equal to second block: - let last_block: &LastSidechainBlock = - updated_sidechain_db.last_blocks.get(&shard).unwrap(); - assert_eq!(last_block.number, 21); - // storage contains both blocks: - // (shard,blocknumber) -> blockhash - let db_block_hash_one = - updated_sidechain_db.get_block_hash(&shard, 20).unwrap().unwrap(); - let db_block_hash_two = - updated_sidechain_db.get_block_hash(&shard, 21).unwrap().unwrap(); - assert_eq!(db_block_hash_one, signed_block_one.hash()); - assert_eq!(db_block_hash_two, signed_block_two.hash()); - - // block hash -> signed block - let db_block_one = - updated_sidechain_db.get_block(&signed_block_one.hash()).unwrap().unwrap(); - let db_block_two = - updated_sidechain_db.get_block(&signed_block_two.hash()).unwrap().unwrap(); - assert_eq!(db_block_one, signed_block_one); - assert_eq!(db_block_two, signed_block_two); - } - } - - #[test] - fn wrong_succession_order_does_not_get_accepted() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block_one = create_signed_block(7, shard); - let signed_block_two = create_signed_block(21, shard); - let signed_block_vector_one = vec![signed_block_one.clone()]; - let signed_block_vector_two = vec![signed_block_two.clone()]; - - { - // first iteration - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(signed_block_vector_one).unwrap(); - } - { - // second iteration - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(signed_block_vector_two).unwrap(); - } - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // last block is equal to first block: - let last_block: &LastSidechainBlock = - updated_sidechain_db.last_blocks.get(&shard).unwrap(); - assert_eq!(last_block.number, signed_block_one.block().header().block_number()); - - // storage contains only one blocks: - // (shard,blocknumber) -> blockhash - let db_block_hash_one = updated_sidechain_db - .get_block_hash(&shard, signed_block_one.block().header().block_number()) - .unwrap() - .unwrap(); - let db_block_hash_empty = updated_sidechain_db - .get_block_hash(&shard, signed_block_two.block().header().block_number()) - .unwrap(); - assert!(db_block_hash_empty.is_none()); - assert_eq!(db_block_hash_one, signed_block_one.hash()); - } - } - - #[test] - fn get_previous_block_returns_correct_block() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let signed_block_one = create_signed_block(1, shard); - // create sidechain_db - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(vec![signed_block_one.clone()]).unwrap(); - // create last block one for comparison - let last_block = LastSidechainBlock { - hash: signed_block_one.hash(), - number: signed_block_one.block().header().block_number(), - }; - - // then - let some_block = sidechain_db - .get_previous_block(&shard, signed_block_one.block().header().block_number() + 1) - .unwrap() - .unwrap(); - - // when - assert_eq!(some_block, last_block); - } - } - - #[test] - fn get_previous_block_returns_none_when_no_block() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - { - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(vec![create_signed_block(1, shard)]).unwrap(); - - let no_block = sidechain_db.get_previous_block(&shard, 1).unwrap(); - - assert!(no_block.is_none()); - } - } - - #[test] - fn purge_shard_works() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let block_one = create_signed_block(1, shard); - let block_two = create_signed_block(2, shard); - let block_three = create_signed_block(3, shard); - { - // create sidechain_db - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(vec![block_one.clone()]).unwrap(); - sidechain_db.store_blocks(vec![block_two.clone()]).unwrap(); - sidechain_db.store_blocks(vec![block_three.clone()]).unwrap(); - - sidechain_db.purge_shard(&shard).unwrap(); - - // test if local storage has been cleansed - assert!(!sidechain_db.shards.contains(&shard)); - assert!(sidechain_db.last_blocks.get(&shard).is_none()); - } - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // test if local storage is still clean - assert!(!updated_sidechain_db.shards.contains(&shard)); - assert!(updated_sidechain_db.last_blocks.get(&shard).is_none()); - // test if db is clean - assert!(updated_sidechain_db.last_block_of_shard(&shard).is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard, 3).unwrap().is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard, 2).unwrap().is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard, 1).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_one.hash()).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_two.hash()).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_three.hash()).unwrap().is_none()); - } - } - - #[test] - fn purge_shard_from_block_works() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let block_one = create_signed_block(1, shard); - let block_two = create_signed_block(2, shard); - let block_three = create_signed_block(3, shard); - let last_block = LastSidechainBlock { - hash: block_three.hash(), - number: block_three.block().header().block_number(), - }; - - { - // create sidechain_db - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(vec![block_one.clone()]).unwrap(); - sidechain_db.store_blocks(vec![block_two.clone()]).unwrap(); - sidechain_db.store_blocks(vec![block_three.clone()]).unwrap(); - - sidechain_db.prune_shard_from_block_number(&shard, 2).unwrap(); - } - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // test local memory - assert!(updated_sidechain_db.shards.contains(&shard)); - assert_eq!(*updated_sidechain_db.last_blocks.get(&shard).unwrap(), last_block); - // assert block three is still there - assert_eq!(*updated_sidechain_db.last_block_of_shard(&shard).unwrap(), last_block); - assert_eq!( - updated_sidechain_db.get_block_hash(&shard, 3).unwrap().unwrap(), - block_three.hash() - ); - assert_eq!( - updated_sidechain_db.get_block(&block_three.hash()).unwrap().unwrap(), - block_three - ); - // assert the lower blocks have been purged - assert!(updated_sidechain_db.get_block_hash(&shard, 2).unwrap().is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard, 1).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_two.hash()).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_one.hash()).unwrap().is_none()); - } - } - - #[test] - fn purge_shard_from_block_works_for_last_block() { - let temp_dir = create_temp_dir(); - let shard = H256::from_low_u64_be(1); - let block_one = create_signed_block(1, shard); - let block_two = create_signed_block(2, shard); - let block_three = create_signed_block(3, shard); - { - // create sidechain_db - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(vec![block_one.clone()]).unwrap(); - sidechain_db.store_blocks(vec![block_two.clone()]).unwrap(); - sidechain_db.store_blocks(vec![block_three.clone()]).unwrap(); - - sidechain_db.prune_shard_from_block_number(&shard, 3).unwrap(); - - // test if local storage has been cleansed - assert!(!sidechain_db.shards.contains(&shard)); - assert!(sidechain_db.last_blocks.get(&shard).is_none()); - } - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // test if local storage is still clean - assert!(!updated_sidechain_db.shards.contains(&shard)); - assert!(updated_sidechain_db.last_blocks.get(&shard).is_none()); - // test if db is clean - assert!(updated_sidechain_db.last_block_of_shard(&shard).is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard, 3).unwrap().is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard, 2).unwrap().is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard, 1).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_one.hash()).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_two.hash()).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_three.hash()).unwrap().is_none()); - } - } - - #[test] - fn prune_shards_works_for_multiple_shards() { - let temp_dir = create_temp_dir(); - // shard one - let shard_one = H256::from_low_u64_be(1); - let block_one = create_signed_block(1, shard_one); - let block_two = create_signed_block(2, shard_one); - let block_three = create_signed_block(3, shard_one); - let last_block_one = LastSidechainBlock { - hash: block_three.hash(), - number: block_three.block().header().block_number(), - }; - // shard two - let shard_two = H256::from_low_u64_be(2); - let block_one_s = create_signed_block(1, shard_two); - let block_two_s = create_signed_block(2, shard_two); - let block_three_s = create_signed_block(3, shard_two); - let block_four_s = create_signed_block(4, shard_two); - let last_block_two = LastSidechainBlock { - hash: block_four_s.hash(), - number: block_four_s.block().header().block_number(), - }; - { - // create sidechain_db - let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); - sidechain_db.store_blocks(vec![block_one.clone(), block_one_s.clone()]).unwrap(); - sidechain_db.store_blocks(vec![block_two.clone(), block_two_s.clone()]).unwrap(); - sidechain_db - .store_blocks(vec![block_three.clone(), block_three_s.clone()]) - .unwrap(); - sidechain_db.store_blocks(vec![block_four_s.clone()]).unwrap(); - - sidechain_db.prune_shards(2); - } - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - // test if shard one has been cleansed of block 1, with 2 and 3 still beeing there: - assert_eq!( - *updated_sidechain_db.last_block_of_shard(&shard_one).unwrap(), - last_block_one - ); - assert_eq!( - updated_sidechain_db.get_block_hash(&shard_one, 3).unwrap().unwrap(), - block_three.hash() - ); - assert_eq!( - updated_sidechain_db.get_block(&block_three.hash()).unwrap().unwrap(), - block_three - ); - assert_eq!( - updated_sidechain_db.get_block_hash(&shard_one, 2).unwrap().unwrap(), - block_two.hash() - ); - assert_eq!( - updated_sidechain_db.get_block(&block_two.hash()).unwrap().unwrap(), - block_two - ); - assert!(updated_sidechain_db.get_block(&block_one.hash()).unwrap().is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard_one, 1).unwrap().is_none()); - // test if shard two has been cleansed of block 1 and 2, with 3 and 4 still beeing there: - assert_eq!( - *updated_sidechain_db.last_block_of_shard(&shard_two).unwrap(), - last_block_two - ); - assert_eq!( - updated_sidechain_db.get_block_hash(&shard_two, 4).unwrap().unwrap(), - block_four_s.hash() - ); - assert_eq!( - updated_sidechain_db.get_block(&block_four_s.hash()).unwrap().unwrap(), - block_four_s - ); - assert_eq!( - updated_sidechain_db.get_block_hash(&shard_two, 3).unwrap().unwrap(), - block_three_s.hash() - ); - assert_eq!( - updated_sidechain_db.get_block(&block_three_s.hash()).unwrap().unwrap(), - block_three_s - ); - assert!(updated_sidechain_db.get_block_hash(&shard_two, 2).unwrap().is_none()); - assert!(updated_sidechain_db.get_block_hash(&shard_two, 1).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_one_s.hash()).unwrap().is_none()); - assert!(updated_sidechain_db.get_block(&block_two_s.hash()).unwrap().is_none()); - } - } -} diff --git a/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_after.rs b/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_after.rs deleted file mode 100644 index 0795e54ca7..0000000000 --- a/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_after.rs +++ /dev/null @@ -1,124 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - error::Error, - test_utils::{ - create_signed_block_with_parenthash as create_signed_block, default_shard, - fill_storage_with_blocks, get_storage, - }, -}; -use its_primitives::{traits::SignedBlock, types::BlockHash}; -use std::assert_matches::assert_matches; - -#[test] -fn get_blocks_after_works_for_regular_case() { - let block_1 = create_signed_block(1, BlockHash::default()); - let block_2 = create_signed_block(2, block_1.hash()); - let block_3 = create_signed_block(3, block_2.hash()); - let block_4 = create_signed_block(4, block_3.hash()); - - let temp_dir = - fill_storage_with_blocks(vec![block_1.clone(), block_2.clone(), block_3, block_4.clone()]); - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let blocks_after_1 = updated_sidechain_db - .get_blocks_after(&block_1.hash(), &default_shard()) - .unwrap(); - - assert_eq!(3, blocks_after_1.len()); - assert_eq!(block_2.hash(), blocks_after_1.first().unwrap().hash()); - assert_eq!(block_4.hash(), blocks_after_1.last().unwrap().hash()); - } -} - -#[test] -fn get_blocks_after_returns_empty_vec_if_block_not_found() { - let block_1 = create_signed_block(1, BlockHash::random()); - - let temp_dir = fill_storage_with_blocks(vec![block_1.clone()]); - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let block_hash = BlockHash::from_low_u64_be(1); - // Off-chance that random() generates exactly the same hash - assert_ne!(block_1.hash(), block_hash); - - assert_eq!( - updated_sidechain_db.get_blocks_after(&block_hash, &default_shard()).unwrap(), - Vec::new() - ); - } -} - -#[test] -fn get_blocks_returns_none_if_last_is_already_most_recent_block() { - let block_1 = create_signed_block(1, BlockHash::random()); - - let temp_dir = fill_storage_with_blocks(vec![block_1.clone()]); - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - - assert_eq!( - updated_sidechain_db - .get_blocks_after(&block_1.hash(), &default_shard()) - .unwrap(), - Vec::new() - ); - } -} - -#[test] -fn get_blocks_after_returns_all_blocks_if_last_known_is_default() { - let block_1 = create_signed_block(1, BlockHash::default()); - let block_2 = create_signed_block(2, block_1.hash()); - let block_3 = create_signed_block(3, block_2.hash()); - - let blocks = vec![block_1.clone(), block_2.clone(), block_3.clone()]; - - let temp_dir = fill_storage_with_blocks(blocks.clone()); - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let default_hash = BlockHash::default(); - - assert_eq!( - updated_sidechain_db.get_blocks_after(&default_hash, &default_shard()).unwrap(), - blocks - ); - } -} - -#[test] -fn given_block_with_invalid_ancestry_returns_error() { - let block_1 = create_signed_block(1, BlockHash::default()); - // Should be block_1 hash, but we deliberately introduce an invalid parent hash. - let block_2 = create_signed_block(2, BlockHash::random()); - - let temp_dir = fill_storage_with_blocks(vec![block_1.clone(), block_2]); - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - - assert_matches!( - updated_sidechain_db.get_blocks_after(&block_1.hash(), &default_shard()), - Err(Error::FailedToFindParentBlock) - ); - } -} diff --git a/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_in_range.rs b/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_in_range.rs deleted file mode 100644 index c0c505d4d0..0000000000 --- a/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_in_range.rs +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::test_utils::{ - create_signed_block_with_parenthash as create_signed_block, default_shard, - fill_storage_with_blocks, get_storage, -}; -use itp_types::BlockHash; -use its_primitives::traits::SignedBlock; - -#[test] -fn get_blocks_in_range_works_for_regular_case() { - let block_1 = create_signed_block(1, BlockHash::default()); - let block_2 = create_signed_block(2, block_1.hash()); - let block_3 = create_signed_block(3, block_2.hash()); - let block_4 = create_signed_block(4, block_3.hash()); - let block_5 = create_signed_block(5, block_4.hash()); - - let temp_dir = fill_storage_with_blocks(vec![ - block_1.clone(), - block_2.clone(), - block_3, - block_4.clone(), - block_5.clone(), - ]); - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let blocks_2_to_4 = updated_sidechain_db - .get_blocks_in_range(&block_1.hash(), &block_5.hash(), &default_shard()) - .unwrap(); - - assert_eq!(3, blocks_2_to_4.len()); - assert_eq!(block_2.hash(), blocks_2_to_4.first().unwrap().hash()); - assert_eq!(block_4.hash(), blocks_2_to_4.last().unwrap().hash()); - } -} - -#[test] -fn get_blocks_in_range_returns_empty_vec_if_from_is_invalid() { - let block_1 = create_signed_block(1, BlockHash::default()); - let block_2 = create_signed_block(2, block_1.hash()); - let block_3 = create_signed_block(3, block_2.hash()); - let block_4 = create_signed_block(4, block_3.hash()); - - let temp_dir = fill_storage_with_blocks(vec![ - block_1.clone(), - block_2.clone(), - block_3.clone(), - block_4.clone(), - ]); - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let invalid_block_hash = BlockHash::from_low_u64_be(1); - - assert!(updated_sidechain_db - .get_blocks_in_range(&invalid_block_hash, &block_3.hash(), &default_shard()) - .unwrap() - .is_empty()); - } -} - -#[test] -fn get_blocks_in_range_returns_all_blocks_if_upper_bound_is_invalid() { - let block_1 = create_signed_block(1, BlockHash::default()); - let block_2 = create_signed_block(2, block_1.hash()); - let block_3 = create_signed_block(3, block_2.hash()); - let block_4 = create_signed_block(4, block_3.hash()); - let block_5 = create_signed_block(5, block_4.hash()); - - let temp_dir = fill_storage_with_blocks(vec![ - block_1.clone(), - block_2.clone(), - block_3.clone(), - block_4.clone(), - block_5.clone(), - ]); - - { - let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); - let blocks_in_range = updated_sidechain_db - .get_blocks_in_range(&block_2.hash(), &BlockHash::from_low_u64_be(1), &default_shard()) - .unwrap(); - - assert_eq!(3, blocks_in_range.len()); - assert_eq!(block_3.hash(), blocks_in_range.first().unwrap().hash()); - assert_eq!(block_5.hash(), blocks_in_range.last().unwrap().hash()); - } -} diff --git a/bitacross-worker/sidechain/storage/src/test_utils.rs b/bitacross-worker/sidechain/storage/src/test_utils.rs deleted file mode 100644 index c0c7d8fdd8..0000000000 --- a/bitacross-worker/sidechain/storage/src/test_utils.rs +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::storage::SidechainStorage; -use itp_time_utils::now_as_millis; -use itp_types::ShardIdentifier; -use its_primitives::types::{BlockHash, SignedBlock as SignedSidechainBlock}; -use its_test::{ - sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}, - sidechain_block_data_builder::SidechainBlockDataBuilder, - sidechain_header_builder::SidechainHeaderBuilder, -}; -use sp_core::{crypto::Pair, ed25519, H256}; -use std::{path::PathBuf, vec::Vec}; -use temp_dir::TempDir; - -pub fn fill_storage_with_blocks(blocks: Vec) -> TempDir { - let dir = create_temp_dir(); - let mut sidechain_db = get_storage(dir.path().to_path_buf()); - sidechain_db.store_blocks(blocks).unwrap(); - dir -} - -pub fn create_temp_dir() -> TempDir { - TempDir::new().unwrap() -} - -pub fn get_storage(path: PathBuf) -> SidechainStorage { - SidechainStorage::::load_from_base_path(path).unwrap() -} - -pub fn default_shard() -> ShardIdentifier { - ShardIdentifier::default() -} - -pub fn create_signed_block_with_parenthash( - block_number: u64, - parent_hash: BlockHash, -) -> SignedSidechainBlock { - let header = default_header_builder() - .with_parent_hash(parent_hash) - .with_block_number(block_number) - .build(); - - let block_data = default_block_data_builder().build(); - - SidechainBlockBuilder::default() - .with_header(header) - .with_block_data(block_data) - .build_signed() -} - -pub fn create_signed_block_with_shard( - block_number: u64, - shard: ShardIdentifier, -) -> SignedSidechainBlock { - let header = default_header_builder() - .with_shard(shard) - .with_block_number(block_number) - .build(); - - let block_data = default_block_data_builder().build(); - - SidechainBlockBuilder::default() - .with_header(header) - .with_block_data(block_data) - .build_signed() -} - -fn default_header_builder() -> SidechainHeaderBuilder { - SidechainHeaderBuilder::default() - .with_parent_hash(H256::random()) - .with_block_number(Default::default()) - .with_shard(default_shard()) -} - -fn default_block_data_builder() -> SidechainBlockDataBuilder { - SidechainBlockDataBuilder::default() - .with_timestamp(now_as_millis()) - .with_layer_one_head(H256::random()) - .with_signer(ed25519::Pair::from_string("//Alice", None).unwrap()) -} diff --git a/bitacross-worker/sidechain/test/Cargo.toml b/bitacross-worker/sidechain/test/Cargo.toml deleted file mode 100644 index d80a6a825b..0000000000 --- a/bitacross-worker/sidechain/test/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "its-test" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -homepage = 'https://litentry.com/' -repository = 'https://github.com/litentry/litentry-parachain' -license = "Apache-2.0" -edition = "2021" - -[dependencies] - -# sgx dependencies -sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["untrusted_time"], optional = true } - -# Substrate dependencies -sp-core = { default_features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -# local -itp-types = { path = "../../core-primitives/types", default_features = false } -its-primitives = { path = "../primitives", default_features = false, features = ["full_crypto"] } - -[features] -default = ["std"] -std = [ - "itp-types/std", - "its-primitives/std", - # substrate - "sp-core/std", -] -sgx = [ - "sgx_tstd", -] diff --git a/bitacross-worker/sidechain/test/src/lib.rs b/bitacross-worker/sidechain/test/src/lib.rs deleted file mode 100644 index e9164d6d8b..0000000000 --- a/bitacross-worker/sidechain/test/src/lib.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#![feature(trait_alias)] -#![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), not(feature = "sgx")))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be disabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -pub mod sidechain_block_builder; -pub mod sidechain_block_data_builder; -pub mod sidechain_header_builder; diff --git a/bitacross-worker/sidechain/test/src/sidechain_block_builder.rs b/bitacross-worker/sidechain/test/src/sidechain_block_builder.rs deleted file mode 100644 index 1261cf51bc..0000000000 --- a/bitacross-worker/sidechain/test/src/sidechain_block_builder.rs +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Builder pattern for a signed sidechain block. - -use crate::{ - sidechain_block_data_builder::SidechainBlockDataBuilder, - sidechain_header_builder::SidechainHeaderBuilder, -}; -use its_primitives::{ - traits::{Block as BlockT, SignBlock}, - types::{block_data::BlockData, header::SidechainHeader as Header, Block, SignedBlock}, -}; -use sp_core::{ed25519, Pair}; - -type Seed = [u8; 32]; -const ENCLAVE_SEED: Seed = *b"12345678901234567890123456789012"; - -#[derive(Clone)] -pub struct SidechainBlockBuilder { - signer: ed25519::Pair, - header: Header, - block_data: BlockData, -} - -impl Default for SidechainBlockBuilder { - fn default() -> Self { - SidechainBlockBuilder { - signer: Pair::from_seed(&ENCLAVE_SEED), - header: SidechainHeaderBuilder::default().build(), - block_data: SidechainBlockDataBuilder::default().build(), - } - } -} - -pub trait SidechainBlockBuilderTrait { - type Block: BlockT; - fn random() -> Self; - fn with_header(self, header: Header) -> Self; - fn with_block_data(self, block_data: BlockData) -> Self; - fn with_signer(self, signer: ed25519::Pair) -> Self; - fn build(&self) -> Self::Block; - fn build_signed(&self) -> SignedBlock; -} - -impl SidechainBlockBuilderTrait for SidechainBlockBuilder { - type Block = Block; - fn random() -> Self { - SidechainBlockBuilder { - signer: Pair::from_seed(&ENCLAVE_SEED), - header: SidechainHeaderBuilder::random().build(), - block_data: SidechainBlockDataBuilder::random().build(), - } - } - - fn with_header(self, header: Header) -> Self { - let mut self_mut = self; - self_mut.header = header; - self_mut - } - - fn with_block_data(self, block_data: BlockData) -> Self { - let mut self_mut = self; - self_mut.block_data = block_data; - self_mut - } - - fn with_signer(self, signer: ed25519::Pair) -> Self { - let mut self_mut = self; - self_mut.signer = signer; - self_mut - } - - fn build(&self) -> Self::Block { - Block { header: self.header, block_data: self.block_data.clone() } - } - - fn build_signed(&self) -> SignedBlock { - let signer = self.signer; - self.build().sign_block(&signer) - } -} - -#[test] -fn build_signed_block_has_valid_signature() { - use its_primitives::traits::SignedBlock as SignedBlockTrait; - - let signed_block = SidechainBlockBuilder::default().build_signed(); - assert!(signed_block.verify_signature()); -} diff --git a/bitacross-worker/sidechain/test/src/sidechain_block_data_builder.rs b/bitacross-worker/sidechain/test/src/sidechain_block_data_builder.rs deleted file mode 100644 index e1197ce65c..0000000000 --- a/bitacross-worker/sidechain/test/src/sidechain_block_data_builder.rs +++ /dev/null @@ -1,102 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Builder pattern for sidechain block data. - -use itp_types::H256; -use its_primitives::types::{ - block::{BlockHash, Timestamp}, - block_data::BlockData, -}; -use sp_core::{ed25519, Pair}; -use std::{time::SystemTime, vec}; - -type Seed = [u8; 32]; -const ENCLAVE_SEED: Seed = *b"12345678901234567890123456789012"; - -pub struct SidechainBlockDataBuilder { - timestamp: Timestamp, - layer_one_head: H256, - signer: ed25519::Pair, - signed_top_hashes: Vec, - encrypted_state_diff: Vec, -} - -impl Default for SidechainBlockDataBuilder { - fn default() -> Self { - SidechainBlockDataBuilder { - timestamp: Default::default(), - layer_one_head: Default::default(), - signer: Pair::from_seed(&ENCLAVE_SEED), - signed_top_hashes: Default::default(), - encrypted_state_diff: Default::default(), - } - } -} - -impl SidechainBlockDataBuilder { - pub fn random() -> Self { - SidechainBlockDataBuilder { - timestamp: now_as_millis(), - layer_one_head: BlockHash::random(), - signer: Pair::from_seed(&ENCLAVE_SEED), - signed_top_hashes: vec![H256::random(), H256::random()], - encrypted_state_diff: vec![1, 3, 42, 8, 11, 33], - } - } - - pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { - self.timestamp = timestamp; - self - } - - pub fn with_signer(mut self, signer: ed25519::Pair) -> Self { - self.signer = signer; - self - } - - pub fn with_layer_one_head(mut self, layer_one_head: H256) -> Self { - self.layer_one_head = layer_one_head; - self - } - - pub fn with_signed_top_hashes(mut self, signed_top_hashes: Vec) -> Self { - self.signed_top_hashes = signed_top_hashes; - self - } - - pub fn with_payload(mut self, payload: Vec) -> Self { - self.encrypted_state_diff = payload; - self - } - - pub fn build(self) -> BlockData { - BlockData { - timestamp: self.timestamp, - block_author: self.signer.public(), - layer_one_head: self.layer_one_head, - signed_top_hashes: self.signed_top_hashes, - encrypted_state_diff: self.encrypted_state_diff, - } - } -} - -/// gets the timestamp of the block as seconds since unix epoch -fn now_as_millis() -> u64 { - SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis() as u64 -} diff --git a/bitacross-worker/sidechain/test/src/sidechain_header_builder.rs b/bitacross-worker/sidechain/test/src/sidechain_header_builder.rs deleted file mode 100644 index fca8b52b8c..0000000000 --- a/bitacross-worker/sidechain/test/src/sidechain_header_builder.rs +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Builder pattern for a sidechain header. - -use its_primitives::types::{header::SidechainHeader as Header, ShardIdentifier}; -use sp_core::H256; - -pub struct SidechainHeaderBuilder { - parent_hash: H256, - block_number: u64, - shard_id: ShardIdentifier, - block_data_hash: H256, - next_finalization_block_number: u64, -} - -impl Default for SidechainHeaderBuilder { - fn default() -> Self { - SidechainHeaderBuilder { - parent_hash: Default::default(), - block_number: 1, - shard_id: Default::default(), - block_data_hash: Default::default(), - next_finalization_block_number: 1, - } - } -} - -impl SidechainHeaderBuilder { - pub fn random() -> Self { - SidechainHeaderBuilder { - parent_hash: H256::random(), - block_number: 42, - shard_id: ShardIdentifier::random(), - block_data_hash: H256::random(), - next_finalization_block_number: 1, - } - } - - pub fn with_parent_hash(mut self, parent_hash: H256) -> Self { - self.parent_hash = parent_hash; - self - } - - pub fn with_block_number(mut self, block_number: u64) -> Self { - self.block_number = block_number; - self - } - - pub fn with_shard(mut self, shard_id: ShardIdentifier) -> Self { - self.shard_id = shard_id; - self - } - - pub fn with_block_data_hash(mut self, block_data_hash: H256) -> Self { - self.block_data_hash = block_data_hash; - self - } - - pub fn with_next_finalization_block_number( - mut self, - next_finalization_block_number: u64, - ) -> Self { - self.next_finalization_block_number = next_finalization_block_number; - self - } - - pub fn build(self) -> Header { - Header { - parent_hash: self.parent_hash, - block_number: self.block_number, - shard_id: self.shard_id, - block_data_hash: self.block_data_hash, - next_finalization_block_number: self.next_finalization_block_number, - } - } -} diff --git a/bitacross-worker/sidechain/validateer-fetch/Cargo.toml b/bitacross-worker/sidechain/validateer-fetch/Cargo.toml deleted file mode 100644 index 7aca2dbf7a..0000000000 --- a/bitacross-worker/sidechain/validateer-fetch/Cargo.toml +++ /dev/null @@ -1,38 +0,0 @@ -[package] -name = "its-validateer-fetch" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "chain-error"] } -derive_more = "0.99.16" - -# substrate deps -sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -# local deps -itp-ocall-api = { path = "../../core-primitives/ocall-api", default-features = false } -itp-teerex-storage = { path = "../../core-primitives/teerex-storage", default-features = false } -itp-types = { path = "../../core-primitives/types", default-features = false } - -# litentry -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -[features] -default = ["std"] -std = [ - "codec/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", - "itp-types/std", - "itp-ocall-api/std", - "frame-support/std", -] - -[dev-dependencies] -itp-test = { path = "../../core-primitives/test" } -itc-parentchain-test = { path = "../../core/parentchain/test" } diff --git a/bitacross-worker/sidechain/validateer-fetch/src/error.rs b/bitacross-worker/sidechain/validateer-fetch/src/error.rs deleted file mode 100644 index 3b5d4a3f2c..0000000000 --- a/bitacross-worker/sidechain/validateer-fetch/src/error.rs +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use derive_more::{Display, From}; - -pub type Result = core::result::Result; - -#[derive(Debug, Display, From)] -pub enum Error { - Codec(codec::Error), - Onchain(itp_ocall_api::Error), - Other(&'static str), -} diff --git a/bitacross-worker/sidechain/validateer-fetch/src/lib.rs b/bitacross-worker/sidechain/validateer-fetch/src/lib.rs deleted file mode 100644 index 8c68402101..0000000000 --- a/bitacross-worker/sidechain/validateer-fetch/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#![cfg_attr(not(feature = "std"), no_std)] - -mod error; -mod validateer; - -pub use error::Error; -pub use validateer::*; diff --git a/bitacross-worker/sidechain/validateer-fetch/src/validateer.rs b/bitacross-worker/sidechain/validateer-fetch/src/validateer.rs deleted file mode 100644 index 4af8d86274..0000000000 --- a/bitacross-worker/sidechain/validateer-fetch/src/validateer.rs +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::error::{Error, Result}; -use frame_support::ensure; -use itp_ocall_api::EnclaveOnChainOCallApi; -use itp_teerex_storage::{TeeRexStorage, TeerexStorageKeys}; -use itp_types::{parentchain::ParentchainId, Enclave}; -use sp_core::H256; -use sp_runtime::traits::Header as HeaderT; -use sp_std::prelude::Vec; - -pub trait ValidateerFetch { - fn current_validateers>( - &self, - latest_header: &Header, - ) -> Result>; - fn validateer_count>(&self, latest_header: &Header) - -> Result; -} - -impl ValidateerFetch for OnchainStorage { - fn current_validateers>( - &self, - header: &Header, - ) -> Result> { - let count = self.validateer_count(header)?; - - let mut hashes = Vec::with_capacity(count as usize); - for i in 1..=count { - hashes.push(TeeRexStorage::enclave(i)) - } - - let enclaves: Vec = self - .get_multiple_storages_verified(hashes, header, &ParentchainId::Litentry)? - .into_iter() - .filter_map(|e| e.into_tuple().1) - .collect(); - ensure!( - enclaves.len() == count as usize, - Error::Other("Found less validateers onchain than validateer count") - ); - Ok(enclaves) - } - - fn validateer_count>(&self, header: &Header) -> Result { - self.get_storage_verified(TeeRexStorage::enclave_count(), header, &ParentchainId::Litentry)? - .into_tuple() - .1 - .ok_or_else(|| Error::Other("Could not get validateer count from chain")) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use codec::Encode; - use itc_parentchain_test::ParentchainHeaderBuilder; - use itp_test::mock::onchain_mock::{validateer_set, OnchainMock}; - use std::string::ToString; - - #[test] - pub fn get_validateer_count_works() { - let header = ParentchainHeaderBuilder::default().build(); - let mock = OnchainMock::default().add_validateer_set(&header, None); - assert_eq!(mock.validateer_count(&header).unwrap(), 4u64); - } - - #[test] - pub fn get_validateer_set_works() { - let header = ParentchainHeaderBuilder::default().build(); - let mock = OnchainMock::default().add_validateer_set(&header, None); - - let validateers = validateer_set(); - - assert_eq!(mock.current_validateers(&header).unwrap(), validateers); - } - - #[test] - pub fn if_validateer_count_bigger_than_returned_validateers_return_err() { - let header = ParentchainHeaderBuilder::default().build(); - let mut mock = OnchainMock::default().add_validateer_set(&header, None); - mock.insert_at_header(&header, TeeRexStorage::enclave_count(), 5u64.encode()); - - assert_eq!( - mock.current_validateers(&header).unwrap_err().to_string(), - "Found less validateers onchain than validateer count".to_string() - ); - } -} diff --git a/node/Cargo.toml b/node/Cargo.toml index de0ebf6ed6..3b9fff4981 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -22,7 +22,7 @@ futures = { version = "0.3.30", features = ["compat"] } log = "0.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -tokio = { version = "1.35.1", features = ["macros", "sync"] } +tokio = { version = "1.36.0", features = ["macros", "sync"] } # Substrate dependencies sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } diff --git a/node/src/chain_specs/rococo.rs b/node/src/chain_specs/rococo.rs index 0e6e80facf..433b77769a 100644 --- a/node/src/chain_specs/rococo.rs +++ b/node/src/chain_specs/rococo.rs @@ -17,10 +17,10 @@ use super::*; use cumulus_primitives_core::ParaId; use rococo_parachain_runtime::{ - AccountId, AuraId, Balance, BalancesConfig, CouncilMembershipConfig, GenesisConfig, - ParachainInfoConfig, ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, SudoConfig, - SystemConfig, TechnicalCommitteeMembershipConfig, TeerexConfig, VCManagementConfig, UNIT, - WASM_BINARY, + AccountId, AuraId, Balance, BalancesConfig, BitacrossConfig, CouncilMembershipConfig, + GenesisConfig, ParachainInfoConfig, ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, + SudoConfig, SystemConfig, TechnicalCommitteeMembershipConfig, TeebagConfig, + TeebagOperationalMode, TeerexConfig, VCManagementConfig, UNIT, WASM_BINARY, }; use sc_service::ChainType; use sc_telemetry::TelemetryEndpoints; @@ -245,10 +245,16 @@ fn generate_genesis( admin: Some(root_key.clone()), skip_scheduled_enclave_check, }, - vc_management: VCManagementConfig { admin: Some(root_key) }, + vc_management: VCManagementConfig { admin: Some(root_key.clone()) }, transaction_payment: Default::default(), tokens: Default::default(), ethereum: Default::default(), evm: Default::default(), + teebag: TeebagConfig { + allow_sgx_debug_mode: true, + admin: Some(root_key.clone()), + mode: TeebagOperationalMode::Development, + }, + bitacross: BitacrossConfig { admin: Some(root_key) }, } } diff --git a/pallets/bitacross/Cargo.toml b/pallets/bitacross/Cargo.toml new file mode 100644 index 0000000000..baa1f201bf --- /dev/null +++ b/pallets/bitacross/Cargo.toml @@ -0,0 +1,48 @@ +[package] +authors = ['Trust Computing GmbH '] +edition = '2021' +homepage = 'https://litentry.com' +name = "pallet-bitacross" +repository = 'https://github.com/litentry/litentry-parachain' +version = '0.1.0' + +[dependencies] +# third-party dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } +scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } + +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false, optional = true } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } + +core-primitives = { path = "../../primitives/core", default-features = false } + +[dev-dependencies] +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", +] +std = [ + "codec/std", + "scale-info/std", + "sp-std/std", + "sp-runtime/std", + "sp-io/std", + "sp-core/std", + "frame-support/std", + "frame-system/std", + "frame-benchmarking?/std", + "core-primitives/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/bitacross/src/custodial_wallet.rs b/pallets/bitacross/src/custodial_wallet.rs new file mode 100644 index 0000000000..02243d315d --- /dev/null +++ b/pallets/bitacross/src/custodial_wallet.rs @@ -0,0 +1,37 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; + +pub type PubKey = [u8; 33]; + +/// custodial wallet that each tee worker generates and holds +#[derive(Encode, Decode, Clone, Default, Debug, PartialEq, Eq, TypeInfo)] +pub struct CustodialWallet { + pub btc: Option, + pub eth: Option, +} + +impl CustodialWallet { + pub fn has_btc(&self) -> bool { + self.btc.is_some() + } + + pub fn has_eth(&self) -> bool { + self.eth.is_some() + } +} diff --git a/pallets/bitacross/src/lib.rs b/pallets/bitacross/src/lib.rs new file mode 100644 index 0000000000..c216c2f355 --- /dev/null +++ b/pallets/bitacross/src/lib.rs @@ -0,0 +1,196 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use core_primitives::Identity; +use frame_support::{ + dispatch::{DispatchResult, DispatchResultWithPostInfo}, + ensure, + pallet_prelude::*, + traits::Get, +}; +use frame_system::pallet_prelude::*; + +pub use pallet::*; + +mod custodial_wallet; +pub use custodial_wallet::*; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + // some extrinsics should only be called by origins from TEE + type TEECallOrigin: EnsureOrigin; + // origin to manage Relayer Admin + type SetAdminOrigin: EnsureOrigin; + } + + #[pallet::storage] + #[pallet::getter(fn admin)] + pub type Admin = StorageValue<_, T::AccountId, OptionQuery>; + + // use `Identity` as key to keep the flexibility, however we do further check its type when + // adding them + #[pallet::storage] + #[pallet::getter(fn relayer)] + pub type Relayer = StorageMap<_, Blake2_128Concat, Identity, (), OptionQuery>; + + // `ValueQuery` is used as each field in CustodialWallet is optional already + // not using Option either as each field is set separately + #[pallet::storage] + #[pallet::getter(fn vault)] + pub type Vault = + StorageMap<_, Blake2_128Concat, T::AccountId, CustodialWallet, ValueQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + AdminSet { new_admin: Option }, + RelayerAdded { who: Identity }, + RelayerRemoved { who: Identity }, + BtcWalletGenerated { pub_key: PubKey }, + EthWalletGenerated { pub_key: PubKey }, + } + + #[pallet::error] + pub enum Error { + RequireAdminOrRoot, + RelayerNotExist, + UnsupportedRelayerType, + BtcWalletAlreadyExist, + EthWalletAlreadyExist, + } + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub admin: Option, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { admin: None } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + if let Some(ref admin) = self.admin { + Admin::::put(admin); + } + } + } + + #[pallet::call] + impl Pallet { + /// Set the admin account + /// + /// Weights should be 2 DB writes: 1 for mode and 1 for event + #[pallet::call_index(0)] + #[pallet::weight((2 * T::DbWeight::get().write, DispatchClass::Normal, Pays::No))] + pub fn set_admin( + origin: OriginFor, + new_admin: T::AccountId, + ) -> DispatchResultWithPostInfo { + T::SetAdminOrigin::ensure_origin(origin)?; + Admin::::put(new_admin.clone()); + Self::deposit_event(Event::AdminSet { new_admin: Some(new_admin) }); + Ok(Pays::No.into()) + } + + #[pallet::call_index(1)] + #[pallet::weight({195_000_000})] + pub fn add_relayer(origin: OriginFor, account: Identity) -> DispatchResult { + Self::ensure_admin_or_root(origin)?; + ensure!(account.is_substrate() || account.is_evm(), Error::::UnsupportedRelayerType); + // we don't care if `account` already exists + Relayer::::insert(account.clone(), ()); + Self::deposit_event(Event::RelayerAdded { who: account }); + Ok(()) + } + + #[pallet::call_index(2)] + #[pallet::weight({195_000_000})] + pub fn remove_relayer(origin: OriginFor, account: Identity) -> DispatchResult { + Self::ensure_admin_or_root(origin)?; + ensure!(Relayer::::contains_key(&account), Error::::RelayerNotExist); + Relayer::::remove(account.clone()); + Self::deposit_event(Event::RelayerRemoved { who: account }); + Ok(()) + } + + /// --------------------------------------------------- + /// The following extrinsics are supposed to be called by TEE only + /// --------------------------------------------------- + #[pallet::call_index(30)] + #[pallet::weight(({195_000_000}, DispatchClass::Normal, Pays::No))] + pub fn btc_wallet_generated( + origin: OriginFor, + pub_key: PubKey, + ) -> DispatchResultWithPostInfo { + let tee_account = T::TEECallOrigin::ensure_origin(origin)?; + Vault::::try_mutate(tee_account, |v| { + ensure!(!v.has_btc(), Error::::BtcWalletAlreadyExist); + v.btc = Some(pub_key); + Self::deposit_event(Event::BtcWalletGenerated { pub_key }); + Ok(Pays::No.into()) + }) + } + + #[pallet::call_index(31)] + #[pallet::weight(({195_000_000}, DispatchClass::Normal, Pays::No))] + pub fn eth_wallet_generated( + origin: OriginFor, + pub_key: PubKey, + ) -> DispatchResultWithPostInfo { + let tee_account = T::TEECallOrigin::ensure_origin(origin)?; + Vault::::try_mutate(tee_account, |v| { + ensure!(!v.has_eth(), Error::::EthWalletAlreadyExist); + v.eth = Some(pub_key); + Self::deposit_event(Event::EthWalletGenerated { pub_key }); + Ok(Pays::No.into()) + }) + } + + // TODO: placeholder + #[pallet::call_index(32)] + #[pallet::weight(({195_000_000}, DispatchClass::Normal, Pays::No))] + pub fn task_complete(origin: OriginFor) -> DispatchResultWithPostInfo { + let _ = T::TEECallOrigin::ensure_origin(origin)?; + Ok(Pays::No.into()) + } + } +} + +impl Pallet { + fn ensure_admin_or_root(origin: OriginFor) -> DispatchResult { + ensure!( + ensure_root(origin.clone()).is_ok() || Some(ensure_signed(origin)?) == Self::admin(), + Error::::RequireAdminOrRoot + ); + Ok(()) + } +} diff --git a/pallets/identity-management/Cargo.toml b/pallets/identity-management/Cargo.toml index 1f281705d8..808ca921c5 100644 --- a/pallets/identity-management/Cargo.toml +++ b/pallets/identity-management/Cargo.toml @@ -9,7 +9,6 @@ version = '0.1.0' [dependencies] # third-party dependencies codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } -pallet-teerex = { path = "../teerex", default-features = false } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } # primitives @@ -27,12 +26,11 @@ test-utils = { path = "../test-utils", default-features = false, optional = true # local core-primitives = { path = "../../primitives/core", default-features = false } -teerex-primitives = { path = "../../primitives/teerex", default-features = false } +pallet-teebag = { path = "../teebag", default-features = false } [dev-dependencies] pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } pallet-group = { path = "../../pallets/group" } -pallet-teerex = { path = "../teerex" } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } test-utils = { path = "../test-utils" } @@ -47,7 +45,6 @@ runtime-benchmarks = [ "test-utils", ] skip-ias-check = [ - "pallet-teerex/skip-ias-check", ] std = [ "codec/std", @@ -60,7 +57,6 @@ std = [ "frame-system/std", "frame-benchmarking?/std", "core-primitives/std", - "teerex-primitives/std", - "pallet-teerex/std", + "pallet-teebag/std", ] try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/identity-management/src/lib.rs b/pallets/identity-management/src/lib.rs index c876f045ee..a311a0e78a 100644 --- a/pallets/identity-management/src/lib.rs +++ b/pallets/identity-management/src/lib.rs @@ -21,9 +21,9 @@ //! However, there are so many error cases in TEE that I'm not even sure //! if it's a good idea to have a matching extrinsic for error propagation. //! -//! The reasons that we don't use pallet_teerex::call_worker directly are: -//! - call teerex::call_worker inside IMP won't trigger the handler, because it's not called as -//! extrinsics so won't be scraped +//! The reasons that we don't use pallet_teebag::post_opaque_task directly are: +//! - call pallet_teebag::post_opaque_task inside IMP won't trigger the handler, because it's not +//! called as extrinsics so won't be scraped //! - the origin is discarded in call_worker but we need it //! - to simplify the F/E usage, we only need to encrypt the needed parameters (see e.g. //! shield_funds) @@ -43,9 +43,9 @@ pub mod weights; pub use crate::weights::WeightInfo; pub use pallet::*; +use pallet_teebag::ShardIdentifier; use sp_core::H256; use sp_std::vec::Vec; -pub use teerex_primitives::ShardIdentifier; #[frame_support::pallet] pub mod pallet { diff --git a/pallets/identity-management/src/mock.rs b/pallets/identity-management/src/mock.rs index 7a4fcfdfbf..feae0dc9d1 100644 --- a/pallets/identity-management/src/mock.rs +++ b/pallets/identity-management/src/mock.rs @@ -45,7 +45,7 @@ type SystemAccountId = ::AccountId; pub struct EnsureEnclaveSigner(PhantomData); impl EnsureOrigin for EnsureEnclaveSigner where - T: frame_system::Config + pallet_teerex::Config + pallet_timestamp::Config, + T: frame_system::Config + pallet_teebag::Config + pallet_timestamp::Config, ::AccountId: From<[u8; 32]>, ::Hash: From<[u8; 32]>, { @@ -53,7 +53,7 @@ where fn try_origin(o: T::RuntimeOrigin) -> Result { o.into().and_then(|o| match o { frame_system::RawOrigin::Signed(who) - if pallet_teerex::Pallet::::ensure_registered_enclave(&who) == Ok(()) => + if pallet_teebag::EnclaveRegistry::::contains_key(&who) => Ok(who), r => Err(T::RuntimeOrigin::from(r)), }) @@ -61,17 +61,13 @@ where #[cfg(feature = "runtime-benchmarks")] fn try_successful_origin() -> Result { - use test_utils::ias::{ - consts::{TEST8_MRENCLAVE, TEST8_SIGNER_PUB}, - TestEnclave, - }; + use test_utils::ias::consts::{TEST8_MRENCLAVE, TEST8_SIGNER_PUB}; let signer: ::AccountId = test_utils::get_signer(TEST8_SIGNER_PUB); - if !pallet_teerex::EnclaveIndex::::contains_key(signer.clone()) { - assert_ok!(pallet_teerex::Pallet::::add_enclave( + if !pallet_teebag::EnclaveRegistry::::contains_key(signer.clone()) { + assert_ok!(pallet_teebag::Pallet::::add_enclave( &signer, - &teerex_primitives::Enclave::test_enclave(signer.clone()) - .with_mr_enclave(TEST8_MRENCLAVE), + &pallet_teebag::Enclave::default().with_mrenclave(TEST8_MRENCLAVE), )); } Ok(frame_system::RawOrigin::Signed(signer).into()) @@ -87,8 +83,8 @@ frame_support::construct_runtime!( { System: frame_system, Balances: pallet_balances, + Teebag: pallet_teebag, Timestamp: pallet_timestamp, - Teerex: pallet_teerex, IdentityManagement: pallet_identity_management, IMPExtrinsicWhitelist: pallet_group, } @@ -150,16 +146,13 @@ impl pallet_balances::Config for Test { parameter_types! { pub const MomentsPerDay: u64 = 86_400_000; // [ms/d] - pub const MaxSilenceTime: u64 = 172_800_000; // 48h } -impl pallet_teerex::Config for Test { +impl pallet_teebag::Config for Test { type RuntimeEvent = RuntimeEvent; - type Currency = Balances; type MomentsPerDay = MomentsPerDay; - type MaxSilenceTime = MaxSilenceTime; - type WeightInfo = (); type SetAdminOrigin = EnsureRoot; + type MaxEnclaveIdentifier = ConstU32<3>; } impl pallet_identity_management::Config for Test { @@ -184,21 +177,24 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let _ = IdentityManagement::add_delegatee(RuntimeOrigin::root(), eddie); System::set_block_number(1); use test_utils::ias::consts::{TEST8_CERT, TEST8_SIGNER_PUB, TEST8_TIMESTAMP, URL}; - let teerex_signer: SystemAccountId = test_utils::get_signer(TEST8_SIGNER_PUB); - assert_ok!(Teerex::set_admin(RuntimeOrigin::root(), teerex_signer.clone())); - assert_ok!(Teerex::set_skip_scheduled_enclave_check( - RuntimeOrigin::signed(teerex_signer.clone()), - true + let signer: SystemAccountId = test_utils::get_signer(TEST8_SIGNER_PUB); + assert_ok!(Teebag::set_admin(RuntimeOrigin::root(), signer.clone())); + assert_ok!(Teebag::set_mode( + RuntimeOrigin::signed(signer.clone()), + pallet_teebag::OperationalMode::Development )); Timestamp::set_timestamp(TEST8_TIMESTAMP); - if !pallet_teerex::EnclaveIndex::::contains_key(teerex_signer.clone()) { - assert_ok!(Teerex::register_enclave( - RuntimeOrigin::signed(teerex_signer), + if !pallet_teebag::EnclaveRegistry::::contains_key(signer.clone()) { + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer), + pallet_teebag::WorkerType::Identity, + pallet_teebag::WorkerMode::Sidechain, TEST8_CERT.to_vec(), URL.to_vec(), None, None, + pallet_teebag::AttestationType::Ias, )); } }); diff --git a/pallets/identity-management/src/tests.rs b/pallets/identity-management/src/tests.rs index 4db8abf85d..142001b857 100644 --- a/pallets/identity-management/src/tests.rs +++ b/pallets/identity-management/src/tests.rs @@ -127,12 +127,15 @@ fn tee_callback_with_registered_enclave_works() { &[119, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 57, 57, 49]; new_test_ext().execute_with(|| { let alice: SystemAccountId = test_utils::get_signer(ALICE_PUBKEY); - assert_ok!(Teerex::register_enclave( + assert_ok!(Teebag::register_enclave( RuntimeOrigin::signed(alice.clone()), + Default::default(), + Default::default(), TEST8_CERT.to_vec(), URL.to_vec(), None, None, + Default::default(), )); assert_ok!(IdentityManagement::some_error( diff --git a/pallets/teeracle/Cargo.toml b/pallets/teebag/Cargo.toml similarity index 54% rename from pallets/teeracle/Cargo.toml rename to pallets/teebag/Cargo.toml index 9eb337f4ab..ec93cb6335 100644 --- a/pallets/teeracle/Cargo.toml +++ b/pallets/teebag/Cargo.toml @@ -1,75 +1,78 @@ [package] -name = "pallet-teeracle" -description = "A pallet to store cryptocurrency market data" -version = "0.1.0" -authors = ['Trust Computing GmbH '] -homepage = 'https://litentry.com/' +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = '2021' +homepage = 'https://litentry.com' +name = 'pallet-teebag' +description = 'Pallet for tee-worker registration and management' repository = 'https://github.com/litentry/litentry-parachain' -license = "Apache-2.0" -edition = "2021" +license = 'GPL-3.0' +version = '0.1.0' [dependencies] +base64 = { version = "0.13", default-features = false, features = ["alloc"] } +chrono = { version = "0.4", default-features = false, features = ["serde"] } codec = { version = "3.0.0", default-features = false, features = ["derive"], package = "parity-scale-codec" } +der = { default-features = false, version = "0.6.0" } +hex = { default-features = false, version = "0.4.3", features = ["alloc"] } log = { version = "0.4", default-features = false } +ring = { version = "0.16.20", default-features = false, features = ["alloc"] } scale-info = { version = "2.10.0", default-features = false, features = ["derive"] } +serde = { default-features = false, version = "1.0", features = ["derive"] } +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } +webpki = { git = "https://github.com/rustls/webpki", version = "=0.102.0-alpha.3", rev = "da923ed", package = "rustls-webpki", default-features = false, features = ["alloc", "ring"] } +x509-cert = { default-features = false, version = "0.1.0", features = ["alloc"] } -# local -pallet-teerex = { path = "../teerex", default-features = false } -teeracle-primitives = { path = "../../primitives/teeracle", default-features = false } - -# encointer -substrate-fixed = { tag = "v0.5.9", default-features = false, git = "https://github.com/encointer/substrate-fixed.git" } - -# substrate frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } frame-system = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-io = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -# benchmarking frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } hex-literal = { version = "0.4.1", optional = true } -test-utils = { path = "../test-utils", optional = true, default-features = false } -timestamp = { package = "pallet-timestamp", default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-balances = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +test-utils = { path = "../test-utils", default-features = false, optional = true } [dev-dependencies] +env_logger = "0.9.0" externalities = { package = "sp-externalities", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } frame-benchmarking = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } hex-literal = "0.4.1" -sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } test-utils = { path = "../test-utils" } -timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -# litentry -pallet-teerex = { path = "../teerex" } [features] default = ["std"] std = [ + "base64/std", + "chrono/std", + "der/std", + "hex/std", + "serde/std", + "serde_json/std", + "ring/std", + "x509-cert/std", "codec/std", "log/std", "scale-info/std", - # local - "pallet-teerex/std", - "teeracle-primitives/std", - # encointer - "substrate-fixed/std", - # substrate + "webpki/std", "frame-support/std", "frame-system/std", "sp-core/std", "sp-io/std", "sp-runtime/std", "sp-std/std", + "pallet-timestamp/std", + "pallet-balances?/std", ] runtime-benchmarks = [ - "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", "hex-literal", + "pallet-balances?/runtime-benchmarks", "test-utils", - "timestamp/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", ] - try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/teebag/README.md b/pallets/teebag/README.md new file mode 100644 index 0000000000..644ddcf42f --- /dev/null +++ b/pallets/teebag/README.md @@ -0,0 +1,11 @@ +Pallet for Litentry's tee-worker registration and management. + +Currently it expects the following worker type: +- identity worker +- bitacross worker + +It serves as the registry for public information such as MRENCLAVE, worker-endpoint, vc-pubkey etc. + +TBA: MAA / RA information + +This crate is partially based on `teerex` and `sidechain` crate on https://github.com/integritee-network/pallets/commit/e124aebb2d3d05a9a65f209f8e6304c6790f15d5 - for the code part / file that is (mostly) copied from intergritee, the original licence is kept. \ No newline at end of file diff --git a/pallets/teebag/src/lib.rs b/pallets/teebag/src/lib.rs new file mode 100644 index 0000000000..4424227944 --- /dev/null +++ b/pallets/teebag/src/lib.rs @@ -0,0 +1,789 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::too_many_arguments)] + +use codec::Decode; +use frame_support::{ + dispatch::{DispatchErrorWithPostInfo, DispatchResult, DispatchResultWithPostInfo}, + ensure, + pallet_prelude::*, + traits::Get, +}; +use frame_system::pallet_prelude::*; +use sp_core::{ed25519::Public as Ed25519Public, H256}; +use sp_runtime::traits::{CheckedSub, SaturatedConversion}; +use sp_std::{prelude::*, str}; + +mod sgx_verify; +pub use sgx_verify::{ + deserialize_enclave_identity, deserialize_tcb_info, extract_certs, + extract_tcb_info_from_raw_dcap_quote, verify_certificate_chain, verify_dcap_quote, + verify_ias_report, SgxReport, +}; + +pub use pallet::*; + +mod types; +pub use types::*; + +mod quoting_enclave; +pub use quoting_enclave::*; + +mod tcb; +pub use tcb::*; + +const MAX_RA_REPORT_LEN: usize = 5244; +const MAX_DCAP_QUOTE_LEN: usize = 5000; +const MAX_URL_LEN: usize = 256; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_timestamp::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type MomentsPerDay: Get; + /// The origin who can set the admin account + type SetAdminOrigin: EnsureOrigin; + /// Maximum number of enclave identifiers allowed to be registered for a specific + /// `worker_type` + #[pallet::constant] + type MaxEnclaveIdentifier: Get; + } + + // TODO: maybe add more sidechain lifecycle events + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + ModeSet { + new_mode: OperationalMode, + }, + AdminSet { + new_admin: Option, + }, + EnclaveAdded { + who: T::AccountId, + worker_type: WorkerType, + url: Vec, + }, + EnclaveRemoved { + who: T::AccountId, + }, + OpaqueTaskPosted { + shard: ShardIdentifier, + }, + ParentchainBlockProcessed { + who: T::AccountId, + block_number: T::BlockNumber, + block_hash: H256, + task_merkle_root: H256, + }, + SidechainBlockFinalized { + who: T::AccountId, + sidechain_block_number: SidechainBlockNumber, + }, + ScheduledEnclaveSet { + worker_type: WorkerType, + sidechain_block_number: SidechainBlockNumber, + mrenclave: MrEnclave, + }, + ScheduledEnclaveRemoved { + worker_type: WorkerType, + sidechain_block_number: SidechainBlockNumber, + }, + } + + #[pallet::error] + pub enum Error { + /// This operation needs the admin permission + RequireAdminOrRoot, + /// Failed to decode enclave signer. + EnclaveSignerDecodeError, + /// Sender does not match attested enclave in report. + SenderIsNotAttestedEnclave, + /// Verifying RA report failed. + RemoteAttestationVerificationFailed, + /// RA report is too old. + RemoteAttestationTooOld, + /// Invalid attestion type, e.g., an `Ignore` type under non-dev mode + InvalidAttestationType, + /// The enclave cannot attest, because its building mode is not allowed. + InvalidSgxMode, + /// The enclave doesn't exist. + EnclaveNotExist, + /// The enclave identifier doesn't exist. + EnclaveIdentifierNotExist, + /// The enclave identifier already exists. + EnclaveIdentifierAlreadyExist, + /// The worker type is unexpected, becuase e.g. when we try to re-register an + /// existing enclave with a differnet worker type + UnexpectedWorkerType, + /// The shard doesn't match the enclave. + WrongMrenclaveForShard, + /// The worker url is too long. + EnclaveUrlTooLong, + /// The raw attestation data is too long. + AttestationTooLong, + /// The worker mode is unexpected, because e.g. a non-sidechain worker calls + /// sidechain specific extrinsic + UnexpectedWorkerMode, + /// Can not found the desired scheduled enclave. + ScheduledEnclaveNotExist, + /// Enclave not in the scheduled list, therefore unexpected. + EnclaveNotInSchedule, + /// The provided collateral data is invalid. + CollateralInvalid, + /// MaxEnclaveIdentifier overflow. + MaxEnclaveIdentifierOverflow, + /// A proposed block is unexpected. + ReceivedUnexpectedSidechainBlock, + /// The value for the next finalization candidate is invalid. + InvalidNextFinalizationCandidateBlockNumber, + } + + #[pallet::storage] + #[pallet::getter(fn admin)] + pub type Admin = StorageValue<_, T::AccountId, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn mode)] + pub type Mode = StorageValue<_, OperationalMode, ValueQuery>; + + // records the enclave identifier list for each worker_type + // T::AccountId is used as identifier as it's unique for each enclave + #[pallet::storage] + #[pallet::getter(fn enclave_identifier)] + pub type EnclaveIdentifier = StorageMap< + _, + Blake2_128Concat, + WorkerType, + BoundedVec, + ValueQuery, + >; + + // registry that holds all registered enclaves, using T::AccountId as the key + // having `worker_type` and `mrenclave` in each `Enclave` instance might seem a bit redundant, + // but it increases flexibility where we **could** allow the same type of worker to have + // distinct mrenclaves: e.g. when multiple versions of enclave are permitted in TEE cluster. + // + // It simplifies the lookup a bit too, otherwise we might need several storages. + #[pallet::storage] + #[pallet::getter(fn enclave_registry)] + pub type EnclaveRegistry = + StorageMap<_, Blake2_128Concat, T::AccountId, Enclave, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn allow_sgx_debug_mode)] + pub type AllowSGXDebugMode = StorageValue<_, bool, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn quoting_enclave_registry)] + pub type QuotingEnclaveRegistry = StorageValue<_, QuotingEnclave, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn tcb_info)] + pub type TcbInfo = + StorageMap<_, Blake2_128Concat, Fmspc, TcbInfoOnChain, ValueQuery>; + + // keep track of a list of scheduled/allowed enchalves, mainly used for enclave updates, + // can only be modified by AdminOrigin + // (worker_type, sidechain_block_number) -> expected MrEnclave + // + // about the first time enclave registration: + // prior to `register_enclave` this map needs to be populated with ((worker_type, 0), + // expected-mrenclave), otherwise the registration will fail + // + // For NON-sidechain worker_type, we still use this storage to whitelist mrenclave, in this case + // the `SidechainBlockNumber` is ignored - you could always set it to 0. + // + // Theorectically we could always push the enclave in `register_enclave`, but we want to + // limit the mrenclave that can be registered, as the parachain is supposed to process enclaves + // with specific mrenclaves. + #[pallet::storage] + #[pallet::getter(fn scheduled_enclave)] + pub type ScheduledEnclave = + StorageMap<_, Blake2_128Concat, (WorkerType, SidechainBlockNumber), MrEnclave, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn latest_sidechain_block_confirmation)] + pub type LatestSidechainBlockConfirmation = + StorageMap<_, Blake2_128Concat, ShardIdentifier, SidechainBlockConfirmation, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn sidechain_block_finalization_candidate)] + pub type SidechainBlockFinalizationCandidate = + StorageMap<_, Blake2_128Concat, ShardIdentifier, SidechainBlockNumber, ValueQuery>; + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub allow_sgx_debug_mode: bool, + pub admin: Option, + pub mode: OperationalMode, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { allow_sgx_debug_mode: false, admin: None, mode: OperationalMode::Production } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + AllowSGXDebugMode::::put(self.allow_sgx_debug_mode); + Mode::::put(self.mode); + if let Some(ref admin) = self.admin { + Admin::::put(admin); + } + } + } + + #[pallet::call] + impl Pallet + where + // Needed for the conversion of `mrenclave` to a `Hash`. + // The condition holds for all known chains. + ::Hash: From<[u8; 32]>, + { + /// Set the admin account + /// + /// Weights should be 2 DB writes: 1 for mode and 1 for event + #[pallet::call_index(0)] + #[pallet::weight((2 * T::DbWeight::get().write, DispatchClass::Normal, Pays::No))] + pub fn set_admin( + origin: OriginFor, + new_admin: T::AccountId, + ) -> DispatchResultWithPostInfo { + T::SetAdminOrigin::ensure_origin(origin)?; + Admin::::put(new_admin.clone()); + Self::deposit_event(Event::AdminSet { new_admin: Some(new_admin) }); + Ok(Pays::No.into()) + } + + /// Set the mode + /// + /// Weights should be 2 DB writes: 1 for mode and 1 for event + #[pallet::call_index(1)] + #[pallet::weight((2 * T::DbWeight::get().write, DispatchClass::Normal, Pays::Yes))] + pub fn set_mode( + origin: OriginFor, + new_mode: OperationalMode, + ) -> DispatchResultWithPostInfo { + Self::ensure_admin_or_root(origin)?; + Mode::::put(new_mode); + Self::deposit_event(Event::ModeSet { new_mode }); + Ok(().into()) + } + + #[pallet::call_index(2)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn force_add_enclave( + origin: OriginFor, + who: T::AccountId, + enclave: Enclave, + ) -> DispatchResultWithPostInfo { + Self::ensure_admin_or_root(origin)?; + Self::add_enclave(&who, &enclave)?; + Ok(Pays::No.into()) + } + + #[pallet::call_index(3)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn force_remove_enclave( + origin: OriginFor, + who: T::AccountId, + ) -> DispatchResultWithPostInfo { + Self::ensure_admin_or_root(origin)?; + Self::remove_enclave(&who)?; + Ok(Pays::No.into()) + } + + #[pallet::call_index(4)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn force_remove_enclave_by_mrenclave( + origin: OriginFor, + mrenclave: MrEnclave, + ) -> DispatchResultWithPostInfo { + Self::ensure_admin_or_root(origin)?; + let accounts = EnclaveRegistry::::iter() + .filter_map( + |(who, enclave)| { + if enclave.mrenclave == mrenclave { + Some(who) + } else { + None + } + }, + ) + .collect::>(); + + for who in accounts.into_iter() { + Self::remove_enclave(&who)?; + } + Ok(Pays::No.into()) + } + + #[pallet::call_index(5)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn force_remove_enclave_by_worker_type( + origin: OriginFor, + worker_type: WorkerType, + ) -> DispatchResultWithPostInfo { + Self::ensure_admin_or_root(origin)?; + let accounts = EnclaveRegistry::::iter() + .filter_map( + |(who, enclave)| { + if enclave.worker_type == worker_type { + Some(who) + } else { + None + } + }, + ) + .collect::>(); + + for who in accounts.into_iter() { + Self::remove_enclave(&who)?; + } + + Ok(Pays::No.into()) + } + + #[pallet::call_index(6)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn set_scheduled_enclave( + origin: OriginFor, + worker_type: WorkerType, + sidechain_block_number: SidechainBlockNumber, + mrenclave: MrEnclave, + ) -> DispatchResultWithPostInfo { + Self::ensure_admin_or_root(origin)?; + ScheduledEnclave::::insert((worker_type, sidechain_block_number), mrenclave); + Self::deposit_event(Event::ScheduledEnclaveSet { + worker_type, + sidechain_block_number, + mrenclave, + }); + Ok(().into()) + } + + #[pallet::call_index(7)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn remove_scheduled_enclave( + origin: OriginFor, + worker_type: WorkerType, + sidechain_block_number: SidechainBlockNumber, + ) -> DispatchResultWithPostInfo { + Self::ensure_admin_or_root(origin)?; + ensure!( + ScheduledEnclave::::contains_key((worker_type, sidechain_block_number)), + Error::::ScheduledEnclaveNotExist + ); + ScheduledEnclave::::remove((worker_type, sidechain_block_number)); + Self::deposit_event(Event::ScheduledEnclaveRemoved { + worker_type, + sidechain_block_number, + }); + Ok(().into()) + } + + #[pallet::call_index(8)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::Yes))] + pub fn register_enclave( + origin: OriginFor, + worker_type: WorkerType, + worker_mode: WorkerMode, + attestation: Vec, + worker_url: Vec, + shielding_pubkey: Option>, + vc_pubkey: Option, + attestation_type: AttestationType, + ) -> DispatchResultWithPostInfo { + let sender = ensure_signed(origin)?; + + ensure!(worker_url.len() <= MAX_URL_LEN, Error::::EnclaveUrlTooLong); + + let mut enclave = Enclave::new(worker_type) + .with_worker_mode(worker_mode) + .with_url(worker_url) + .with_shielding_pubkey(shielding_pubkey) + .with_vc_pubkey(vc_pubkey) + .with_attestation_type(attestation_type); + + match attestation_type { + AttestationType::Ignore => { + ensure!( + Self::mode() == OperationalMode::Development, + Error::::InvalidAttestationType + ); + enclave.mrenclave = + ::decode(&mut attestation.as_slice()).unwrap_or_default(); + enclave.last_seen_timestamp = Self::now().saturated_into(); + enclave.sgx_build_mode = SgxBuildMode::default(); + }, + AttestationType::Ias => { + let report = Self::verify_ias(&sender, attestation)?; + enclave.mrenclave = report.mr_enclave; + enclave.last_seen_timestamp = report.timestamp; + enclave.sgx_build_mode = report.build_mode; + }, + AttestationType::Dcap(_) => { + let report = Self::verify_dcap(&sender, attestation)?; + enclave.mrenclave = report.mr_enclave; + enclave.last_seen_timestamp = report.timestamp; + enclave.sgx_build_mode = report.build_mode; + }, + }; + + match Self::mode() { + OperationalMode::Production | OperationalMode::Maintenance => { + if !Self::allow_sgx_debug_mode() && + enclave.sgx_build_mode == SgxBuildMode::Debug + { + return Err(Error::::InvalidSgxMode.into()) + } + ensure!( + ScheduledEnclave::::iter_values().any(|m| m == enclave.mrenclave), + Error::::EnclaveNotInSchedule + ); + }, + OperationalMode::Development => { + // populate the registry if the entry doesn't exist + if !ScheduledEnclave::::contains_key((worker_type, 0)) { + ScheduledEnclave::::insert((worker_type, 0), enclave.mrenclave); + } + }, + }; + Self::add_enclave(&sender, &enclave)?; + Ok(().into()) + } + + #[pallet::call_index(9)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::Yes))] + pub fn unregister_enclave(origin: OriginFor) -> DispatchResultWithPostInfo { + let sender = ensure_signed(origin)?; + Self::remove_enclave(&sender)?; + Ok(().into()) + } + + #[pallet::call_index(10)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn register_quoting_enclave( + origin: OriginFor, + enclave_identity: Vec, + signature: Vec, + certificate_chain: Vec, + ) -> DispatchResultWithPostInfo { + // Quoting enclaves are registered globally and not for a specific sender + let _ = ensure_signed(origin)?; + let quoting_enclave = + Self::verify_quoting_enclave(enclave_identity, signature, certificate_chain)?; + >::put(quoting_enclave); + Ok(().into()) + } + + #[pallet::call_index(11)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn register_tcb_info( + origin: OriginFor, + tcb_info: Vec, + signature: Vec, + certificate_chain: Vec, + ) -> DispatchResultWithPostInfo { + // TCB info is registered globally and not for a specific sender + let _ = ensure_signed(origin)?; + let (fmspc, on_chain_info) = + Self::verify_tcb_info(tcb_info, signature, certificate_chain)?; + TcbInfo::::insert(fmspc, on_chain_info); + Ok(().into()) + } + + // =============================================================================== + // Following extrinsics are for runtime communication between parachain and worker + // =============================================================================== + + #[pallet::call_index(20)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::Yes))] + pub fn post_opaque_task(origin: OriginFor, request: RsaRequest) -> DispatchResult { + let _ = ensure_signed(origin)?; + Self::deposit_event(Event::OpaqueTaskPosted { shard: request.shard }); + Ok(()) + } + + #[pallet::call_index(21)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn parentchain_block_processed( + origin: OriginFor, + block_hash: H256, + block_number: T::BlockNumber, + task_merkle_root: H256, + ) -> DispatchResultWithPostInfo { + let sender = ensure_signed(origin)?; + let mut enclave = + EnclaveRegistry::::get(&sender).ok_or(Error::::EnclaveNotExist)?; + enclave.last_seen_timestamp = Self::now().saturated_into(); + Self::deposit_event(Event::ParentchainBlockProcessed { + who: sender, + block_number, + block_hash, + task_merkle_root, + }); + Ok(().into()) + } + + #[pallet::call_index(22)] + #[pallet::weight((195_000_000, DispatchClass::Normal, Pays::No))] + pub fn sidechain_block_imported( + origin: OriginFor, + shard: ShardIdentifier, + block_number: u64, + next_finalization_candidate_block_number: u64, + block_header_hash: H256, + ) -> DispatchResultWithPostInfo { + let confirmation = SidechainBlockConfirmation { block_number, block_header_hash }; + + let sender = ensure_signed(origin)?; + let mut sender_enclave = + EnclaveRegistry::::get(&sender).ok_or(Error::::EnclaveNotExist)?; + + ensure!( + sender_enclave.mrenclave.as_ref() == shard.as_ref(), + Error::::WrongMrenclaveForShard + ); + + ensure!( + sender_enclave.worker_mode == WorkerMode::Sidechain, + Error::::UnexpectedWorkerMode + ); + + sender_enclave.last_seen_timestamp = Self::now().saturated_into(); + + // Simple logic for now: only accept blocks from first registered enclave. + let primary_enclave_identifier = + EnclaveIdentifier::::get(sender_enclave.worker_type) + .get(0) + .cloned() + .ok_or(Error::::EnclaveIdentifierNotExist)?; + if sender != primary_enclave_identifier { + log::debug!( + "Ignore block confirmation from non primary enclave identifier: {:?}, primary: {:?}", + sender, primary_enclave_identifier + ); + return Ok(().into()) + } + + let block_number = confirmation.block_number; + let finalization_candidate_block_number = + SidechainBlockFinalizationCandidate::::try_get(shard).unwrap_or(1); + + ensure!( + block_number == finalization_candidate_block_number, + Error::::ReceivedUnexpectedSidechainBlock + ); + ensure!( + next_finalization_candidate_block_number > finalization_candidate_block_number, + Error::::InvalidNextFinalizationCandidateBlockNumber + ); + + SidechainBlockFinalizationCandidate::::insert( + shard, + next_finalization_candidate_block_number, + ); + + Self::finalize_block(sender, shard, confirmation); + Ok(().into()) + } + } +} + +impl Pallet { + fn ensure_admin_or_root(origin: OriginFor) -> DispatchResultWithPostInfo { + ensure!( + ensure_root(origin.clone()).is_ok() || Some(ensure_signed(origin)?) == Self::admin(), + Error::::RequireAdminOrRoot + ); + Ok(().into()) + } + + fn add_enclave_identifier(worker_type: WorkerType, who: &T::AccountId) -> Result<(), Error> { + EnclaveIdentifier::::try_mutate(worker_type, |v| { + ensure!(!v.contains(who), Error::::EnclaveIdentifierAlreadyExist); + v.try_push(who.clone()).map_err(|_| Error::::MaxEnclaveIdentifierOverflow) + }) + } + + pub fn add_enclave(sender: &T::AccountId, enclave: &Enclave) -> Result<(), Error> { + match EnclaveRegistry::::get(sender) { + Some(old_enclave) => ensure!( + old_enclave.worker_type == enclave.worker_type, + Error::::UnexpectedWorkerType + ), + None => Self::add_enclave_identifier(enclave.worker_type, sender)?, + }; + EnclaveRegistry::::insert(sender, enclave); + Self::deposit_event(Event::::EnclaveAdded { + who: sender.clone(), + worker_type: enclave.worker_type, + url: enclave.url.clone(), + }); + Ok(()) + } + + fn remove_enclave(sender: &T::AccountId) -> DispatchResultWithPostInfo { + let enclave = EnclaveRegistry::::get(sender).ok_or(Error::::EnclaveNotExist)?; + + EnclaveIdentifier::::try_mutate(enclave.worker_type, |v| { + ensure!(v.contains(sender), Error::::EnclaveIdentifierNotExist); + v.retain(|e| e != sender); + Ok::<(), DispatchErrorWithPostInfo>(()) + })?; + + EnclaveRegistry::::remove(sender); + Self::deposit_event(Event::::EnclaveRemoved { who: sender.clone() }); + Ok(().into()) + } + + pub fn enclave_count(worker_type: WorkerType) -> u32 { + EnclaveIdentifier::::get(worker_type).iter().count() as u32 + } + + fn verify_ias( + sender: &T::AccountId, + ra_report: Vec, + ) -> Result { + ensure!(ra_report.len() <= MAX_RA_REPORT_LEN, Error::::AttestationTooLong); + let report = verify_ias_report(&ra_report) + .map_err(|_| Error::::RemoteAttestationVerificationFailed)?; + + let enclave_signer = T::AccountId::decode(&mut &report.pubkey[..]) + .map_err(|_| Error::::EnclaveSignerDecodeError)?; + + ensure!(sender == &enclave_signer, Error::::SenderIsNotAttestedEnclave); + + Self::ensure_timestamp_within_24_hours(report.timestamp)?; + Ok(report) + } + + fn verify_dcap( + sender: &T::AccountId, + dcap_quote: Vec, + ) -> Result { + ensure!(dcap_quote.len() <= MAX_DCAP_QUOTE_LEN, Error::::AttestationTooLong); + let timestamp = Self::now(); + let qe = >::get(); + let (fmspc, tcb_info, report) = + verify_dcap_quote(&dcap_quote, timestamp.saturated_into(), &qe).map_err(|e| { + log::warn!("verify_dcap_quote failed: {:?}", e); + Error::::RemoteAttestationVerificationFailed + })?; + + let tcb_info_on_chain = >::get(fmspc); + ensure!(tcb_info_on_chain.verify_examinee(&tcb_info), "tcb_info is outdated"); + + let enclave_signer = T::AccountId::decode(&mut &report.pubkey[..]) + .map_err(|_| Error::::EnclaveSignerDecodeError)?; + ensure!(sender == &enclave_signer, Error::::SenderIsNotAttestedEnclave); + + Ok(report) + } + + fn verify_quoting_enclave( + enclave_identity: Vec, + signature: Vec, + certificate_chain: Vec, + ) -> Result { + let verification_time: u64 = Self::now().saturated_into(); + let certs = extract_certs(&certificate_chain); + ensure!(certs.len() >= 2, "Certificate chain must have at least two certificates"); + let intermediate_slices: Vec = + certs[1..].iter().map(|c| c.as_slice().into()).collect(); + let leaf_cert_der = webpki::types::CertificateDer::from(certs[0].as_slice()); + let leaf_cert = webpki::EndEntityCert::try_from(&leaf_cert_der) + .map_err(|_| "Failed to parse leaf certificate")?; + verify_certificate_chain(&leaf_cert, &intermediate_slices, verification_time)?; + let enclave_identity = + deserialize_enclave_identity(&enclave_identity, &signature, &leaf_cert)?; + + if enclave_identity.is_valid(verification_time.try_into().unwrap()) { + Ok(enclave_identity.to_quoting_enclave()) + } else { + Err(Error::::CollateralInvalid.into()) + } + } + + pub fn verify_tcb_info( + tcb_info: Vec, + signature: Vec, + certificate_chain: Vec, + ) -> Result<(Fmspc, TcbInfoOnChain), DispatchErrorWithPostInfo> { + let verification_time: u64 = Self::now().saturated_into(); + let certs = extract_certs(&certificate_chain); + ensure!(certs.len() >= 2, "Certificate chain must have at least two certificates"); + let intermediate_slices: Vec = + certs[1..].iter().map(|c| c.as_slice().into()).collect(); + let leaf_cert_der = webpki::types::CertificateDer::from(certs[0].as_slice()); + let leaf_cert = webpki::EndEntityCert::try_from(&leaf_cert_der) + .map_err(|_| "Failed to parse leaf certificate")?; + verify_certificate_chain(&leaf_cert, &intermediate_slices, verification_time)?; + let tcb_info = deserialize_tcb_info(&tcb_info, &signature, &leaf_cert)?; + if tcb_info.is_valid(verification_time.try_into().unwrap()) { + Ok(tcb_info.to_chain_tcb_info()) + } else { + Err(Error::::CollateralInvalid.into()) + } + } + + fn ensure_timestamp_within_24_hours(report_timestamp: u64) -> DispatchResultWithPostInfo { + let elapsed_time = Self::now() + .checked_sub(&T::Moment::saturated_from(report_timestamp)) + .ok_or("Underflow while calculating elapsed time since report creation")?; + + if elapsed_time < T::MomentsPerDay::get() { + Ok(().into()) + } else { + Err(Error::::RemoteAttestationTooOld.into()) + } + } + + fn finalize_block( + sender: T::AccountId, + shard: ShardIdentifier, + confirmation: SidechainBlockConfirmation, + ) { + LatestSidechainBlockConfirmation::::insert(shard, confirmation); + Self::deposit_event(Event::SidechainBlockFinalized { + who: sender, + sidechain_block_number: confirmation.block_number, + }); + } + + fn now() -> T::Moment { + pallet_timestamp::Pallet::::now() + } +} + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; diff --git a/pallets/teeracle/src/mock.rs b/pallets/teebag/src/mock.rs similarity index 60% rename from pallets/teeracle/src/mock.rs rename to pallets/teebag/src/mock.rs index f5955bd20e..945948cdda 100644 --- a/pallets/teeracle/src/mock.rs +++ b/pallets/teebag/src/mock.rs @@ -1,25 +1,30 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -use crate as pallet_teeracle; -use frame_support::{assert_ok, pallet_prelude::GenesisBuild, parameter_types}; +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![allow(dead_code, unused_imports, const_item_mutation)] +use crate::{self as pallet_teebag, OperationalMode}; +use frame_support::{ + assert_ok, construct_runtime, + pallet_prelude::GenesisBuild, + parameter_types, + traits::{OnFinalize, OnInitialize}, +}; use frame_system as system; use frame_system::EnsureRoot; -use pallet_teeracle::Config; -use sp_core::H256; +use sp_core::{ConstU32, H256}; use sp_keyring::AccountKeyring; use sp_runtime::{ generic, @@ -45,7 +50,7 @@ pub type SignedExtra = ( frame_system::CheckWeight, ); -frame_support::construct_runtime!( +construct_runtime!( pub enum Test where Block = Block, NodeBlock = Block, @@ -53,9 +58,8 @@ frame_support::construct_runtime!( { System: frame_system, Balances: pallet_balances, - Timestamp: timestamp, - Teerex: pallet_teerex, - Teeracle: pallet_teeracle, + Timestamp: pallet_timestamp, + Teebag: pallet_teebag, } ); @@ -117,60 +121,66 @@ parameter_types! { pub type Moment = u64; -impl timestamp::Config for Test { +impl pallet_timestamp::Config for Test { type Moment = Moment; - type OnTimestampSet = Teerex; + type OnTimestampSet = (); type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } parameter_types! { pub const MomentsPerDay: u64 = 86_400_000; // [ms/d] - pub const MaxSilenceTime: u64 = 172_800_000; // 48h - pub const MaxWhitelistedReleases: u32 = 10; - pub const MaxOracleBlobLen: u32 = 4096; } -impl pallet_teerex::Config for Test { +impl pallet_teebag::Config for Test { type RuntimeEvent = RuntimeEvent; - type Currency = Balances; type MomentsPerDay = MomentsPerDay; - type WeightInfo = (); type SetAdminOrigin = EnsureRoot; - type MaxSilenceTime = MaxSilenceTime; -} - -impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); - type MaxWhitelistedReleases = MaxWhitelistedReleases; - type MaxOracleBlobLen = MaxOracleBlobLen; + type MaxEnclaveIdentifier = ConstU32<1>; } // This function basically just builds a genesis storage key/value store according to // our desired mockup. RA from enclave compiled in debug mode is allowed -pub fn new_test_ext() -> sp_io::TestExternalities { +pub fn new_test_ext(is_dev_mode: bool) -> sp_io::TestExternalities { let mut t = system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![(AccountKeyring::Alice.to_account_id(), 1 << 60)], } .assimilate_storage(&mut t) .unwrap(); - let teerex_config = pallet_teerex::GenesisConfig { + + let mut genesis_config: pallet_teebag::GenesisConfig = crate::GenesisConfig { allow_sgx_debug_mode: true, - admin: None, - skip_scheduled_enclave_check: true, + admin: Some(AccountKeyring::Alice.to_account_id()), + mode: OperationalMode::Production, }; - GenesisBuild::::assimilate_storage(&teerex_config, &mut t).unwrap(); + + if is_dev_mode { + genesis_config.mode = OperationalMode::Development; + } + + GenesisBuild::::assimilate_storage(&genesis_config, &mut t).unwrap(); let mut ext: sp_io::TestExternalities = t.into(); ext.execute_with(|| { System::set_block_number(1); - assert_ok!(Teerex::set_admin(RuntimeOrigin::root(), AccountKeyring::Alice.to_account_id())); - assert_ok!(Teerex::set_skip_scheduled_enclave_check( - RuntimeOrigin::signed(AccountKeyring::Alice.to_account_id()), - true - )); }); ext } + +/// Helper method for the OnTimestampSet to be called +pub fn set_timestamp(t: u64) { + let _ = pallet_timestamp::Pallet::::set(RuntimeOrigin::none(), t); +} + +/// Run until a particular block. +pub fn run_to_block(n: u32) { + while System::block_number() < n { + if System::block_number() > 1 { + System::on_finalize(System::block_number()); + } + Timestamp::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::on_initialize(System::block_number()); + } +} diff --git a/pallets/teebag/src/quoting_enclave.rs b/pallets/teebag/src/quoting_enclave.rs new file mode 100644 index 0000000000..b05c64623a --- /dev/null +++ b/pallets/teebag/src/quoting_enclave.rs @@ -0,0 +1,78 @@ +/* +Copyright 2021 Integritee AG and Supercomputing Systems AG + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +// `QuotingEnclave` primitive part, copied from Integritee + +use crate::{MrSigner, QeTcb, Vec}; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_core::RuntimeDebug; + +/// This represents all the collateral data that we need to store on chain in order to verify +/// the quoting enclave validity of another enclave that wants to register itself on chain +#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct QuotingEnclave { + // Todo: make timestamp: Moment + pub issue_date: u64, // unix epoch in milliseconds + // Todo: make timestamp: Moment + pub next_update: u64, // unix epoch in milliseconds + pub miscselect: [u8; 4], + pub miscselect_mask: [u8; 4], + pub attributes: [u8; 16], + pub attributes_mask: [u8; 16], + pub mrsigner: MrSigner, + pub isvprodid: u16, + /// Contains only the TCB versions that are considered UpToDate + pub tcb: Vec, +} + +impl QuotingEnclave { + #[allow(clippy::too_many_arguments)] + pub fn new( + issue_date: u64, + next_update: u64, + miscselect: [u8; 4], + miscselect_mask: [u8; 4], + attributes: [u8; 16], + attributes_mask: [u8; 16], + mrsigner: MrSigner, + isvprodid: u16, + tcb: Vec, + ) -> Self { + Self { + issue_date, + next_update, + miscselect, + miscselect_mask, + attributes, + attributes_mask, + mrsigner, + isvprodid, + tcb, + } + } + + pub fn attributes_flags_mask_as_u64(&self) -> u64 { + let slice_as_array: [u8; 8] = self.attributes_mask[0..8].try_into().unwrap(); + u64::from_le_bytes(slice_as_array) + } + + pub fn attributes_flags_as_u64(&self) -> u64 { + let slice_as_array: [u8; 8] = self.attributes[0..8].try_into().unwrap(); + u64::from_le_bytes(slice_as_array) + } +} diff --git a/pallets/teebag/src/sgx_verify/AttestationReportSigningCACert.pem b/pallets/teebag/src/sgx_verify/AttestationReportSigningCACert.pem new file mode 100644 index 0000000000..948b4c0cdd --- /dev/null +++ b/pallets/teebag/src/sgx_verify/AttestationReportSigningCACert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFSzCCA7OgAwIBAgIJANEHdl0yo7CUMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV +BAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0 +YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwIBcNMTYxMTE0MTUzNzMxWhgPMjA0OTEy +MzEyMzU5NTlaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwL +U2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQD +DCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwggGiMA0G +CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCfPGR+tXc8u1EtJzLA10Feu1Wg+p7e +LmSRmeaCHbkQ1TF3Nwl3RmpqXkeGzNLd69QUnWovYyVSndEMyYc3sHecGgfinEeh +rgBJSEdsSJ9FpaFdesjsxqzGRa20PYdnnfWcCTvFoulpbFR4VBuXnnVLVzkUvlXT +L/TAnd8nIZk0zZkFJ7P5LtePvykkar7LcSQO85wtcQe0R1Raf/sQ6wYKaKmFgCGe +NpEJUmg4ktal4qgIAxk+QHUxQE42sxViN5mqglB0QJdUot/o9a/V/mMeH8KvOAiQ +byinkNndn+Bgk5sSV5DFgF0DffVqmVMblt5p3jPtImzBIH0QQrXJq39AT8cRwP5H +afuVeLHcDsRp6hol4P+ZFIhu8mmbI1u0hH3W/0C2BuYXB5PC+5izFFh/nP0lc2Lf +6rELO9LZdnOhpL1ExFOq9H/B8tPQ84T3Sgb4nAifDabNt/zu6MmCGo5U8lwEFtGM +RoOaX4AS+909x00lYnmtwsDVWv9vBiJCXRsCAwEAAaOByTCBxjBgBgNVHR8EWTBX +MFWgU6BRhk9odHRwOi8vdHJ1c3RlZHNlcnZpY2VzLmludGVsLmNvbS9jb250ZW50 +L0NSTC9TR1gvQXR0ZXN0YXRpb25SZXBvcnRTaWduaW5nQ0EuY3JsMB0GA1UdDgQW +BBR4Q3t2pn680K9+QjfrNXw7hwFRPDAfBgNVHSMEGDAWgBR4Q3t2pn680K9+Qjfr +NXw7hwFRPDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkq +hkiG9w0BAQsFAAOCAYEAeF8tYMXICvQqeXYQITkV2oLJsp6J4JAqJabHWxYJHGir +IEqucRiJSSx+HjIJEUVaj8E0QjEud6Y5lNmXlcjqRXaCPOqK0eGRz6hi+ripMtPZ +sFNaBwLQVV905SDjAzDzNIDnrcnXyB4gcDFCvwDFKKgLRjOB/WAqgscDUoGq5ZVi +zLUzTqiQPmULAQaB9c6Oti6snEFJiCQ67JLyW/E83/frzCmO5Ru6WjU4tmsmy8Ra +Ud4APK0wZTGtfPXU7w+IBdG5Ez0kE1qzxGQaL4gINJ1zMyleDnbuS8UicjJijvqA +152Sq049ESDz+1rRGc2NVEqh1KaGXmtXvqxXcTB+Ljy5Bw2ke0v8iGngFBPqCTVB +3op5KBG3RjbF6RRSzwzuWfL7QErNC8WEy5yDVARzTA5+xmBc388v9Dm21HGfcC8O +DD+gT9sSpssq0ascmvH49MOgjt1yoysLtdCtJW/9FZpoOypaHx0R+mJTLwPXVMrv +DaVzWh5aiEx+idkSGMnX +-----END CERTIFICATE----- diff --git a/pallets/teebag/src/sgx_verify/collateral.rs b/pallets/teebag/src/sgx_verify/collateral.rs new file mode 100644 index 0000000000..53f3c55af4 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/collateral.rs @@ -0,0 +1,276 @@ +/* + Copyright 2022 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pub extern crate alloc; + +use crate::{Fmspc, MrSigner, Pcesvn, QeTcb, QuotingEnclave, TcbInfoOnChain, TcbVersionStatus}; +use alloc::string::String; +use chrono::prelude::{DateTime, Utc}; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; +use sp_std::prelude::*; + +/// The data structures in here are designed such that they can be used to serialize/deserialize +/// the "TCB info" and "enclave identity" collateral data in JSON format provided by intel +/// See https://api.portal.trustedservices.intel.com/documentation for further information and examples + +#[derive(Serialize, Deserialize)] +pub struct Tcb { + isvsvn: u16, +} + +impl Tcb { + pub fn is_valid(&self) -> bool { + // At the time of writing this code everything older than 6 is outdated + // Intel does the same check in their DCAP implementation + self.isvsvn >= 6 + } +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TcbLevel { + tcb: Tcb, + /// Intel does not verify the tcb_date in their code and their API documentation also does + /// not mention it needs verification. + tcb_date: DateTime, + tcb_status: String, + #[serde(rename = "advisoryIDs")] + #[serde(skip_serializing_if = "Option::is_none")] + advisory_ids: Option>, +} + +impl TcbLevel { + pub fn is_valid(&self) -> bool { + // UpToDate is the only valid status (the other being OutOfDate and Revoked) + // A possible extension would be to also verify that the advisory_ids list is empty, + // but I think this could also lead to all TcbLevels being invalid + self.tcb.is_valid() && self.tcb_status == "UpToDate" + } +} + +#[derive(Serialize, Deserialize)] +struct TcbComponent { + svn: u8, + #[serde(skip_serializing_if = "Option::is_none")] + category: Option, + #[serde(rename = "type")] //type is a keyword so we rename the field + #[serde(skip_serializing_if = "Option::is_none")] + tcb_type: Option, +} + +#[derive(Serialize, Deserialize)] +pub struct TcbFull { + sgxtcbcomponents: [TcbComponent; 16], + pcesvn: Pcesvn, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TcbLevelFull { + tcb: TcbFull, + /// Intel does not verify the tcb_date in their code and their API documentation also does + /// not mention it needs verification. + tcb_date: DateTime, + tcb_status: String, + #[serde(rename = "advisoryIDs")] + #[serde(skip_serializing_if = "Option::is_none")] + advisory_ids: Option>, +} + +impl TcbLevelFull { + pub fn is_valid(&self) -> bool { + // A possible extension would be to also verify that the advisory_ids list is empty, + // but I think this could also lead to all TcbLevels being invalid + self.tcb_status == "UpToDate" || self.tcb_status == "SWHardeningNeeded" + } +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EnclaveIdentity { + id: String, + version: u16, + issue_date: DateTime, + next_update: DateTime, + tcb_evaluation_data_number: u16, + #[serde(deserialize_with = "deserialize_from_hex::<_, 4>")] + #[serde(serialize_with = "serialize_to_hex::<_, 4>")] + miscselect: [u8; 4], + #[serde(deserialize_with = "deserialize_from_hex::<_, 4>")] + #[serde(serialize_with = "serialize_to_hex::<_, 4>")] + miscselect_mask: [u8; 4], + #[serde(deserialize_with = "deserialize_from_hex::<_, 16>")] + #[serde(serialize_with = "serialize_to_hex::<_, 16>")] + attributes: [u8; 16], + #[serde(deserialize_with = "deserialize_from_hex::<_, 16>")] + #[serde(serialize_with = "serialize_to_hex::<_, 16>")] + attributes_mask: [u8; 16], + #[serde(deserialize_with = "deserialize_from_hex::<_, 32>")] + #[serde(serialize_with = "serialize_to_hex::<_, 32>")] + mrsigner: MrSigner, + pub isvprodid: u16, + pub tcb_levels: Vec, +} + +fn serialize_to_hex(x: &[u8; N], s: S) -> Result +where + S: Serializer, +{ + s.serialize_str(&hex::encode(x).to_uppercase()) +} + +fn deserialize_from_hex<'de, D, const N: usize>(deserializer: D) -> Result<[u8; N], D::Error> +where + D: Deserializer<'de>, +{ + let s: &str = Deserialize::deserialize(deserializer)?; + let hex = hex::decode(s).map_err(|_| D::Error::custom("Failed to deserialize hex string"))?; + hex.try_into().map_err(|_| D::Error::custom("Invalid hex length")) +} + +impl EnclaveIdentity { + /// This extracts the necessary information into the struct that we actually store in the chain + pub fn to_quoting_enclave(&self) -> QuotingEnclave { + let mut valid_tcbs: Vec = Vec::new(); + for tcb in &self.tcb_levels { + if tcb.is_valid() { + valid_tcbs.push(QeTcb::new(tcb.tcb.isvsvn)); + } + } + QuotingEnclave::new( + self.issue_date + .timestamp_millis() + .try_into() + .expect("no support for negative unix timestamps"), + self.next_update + .timestamp_millis() + .try_into() + .expect("no support for negative unix timestamps"), + self.miscselect, + self.miscselect_mask, + self.attributes, + self.attributes_mask, + self.mrsigner, + self.isvprodid, + valid_tcbs, + ) + } + + pub fn is_valid(&self, timestamp_millis: i64) -> bool { + self.id == "QE" && + self.version == 2 && + self.issue_date.timestamp_millis() < timestamp_millis && + timestamp_millis < self.next_update.timestamp_millis() + } +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TcbInfo { + id: String, + version: u8, + issue_date: DateTime, + next_update: DateTime, + #[serde(deserialize_with = "deserialize_from_hex::<_, 6>")] + #[serde(serialize_with = "serialize_to_hex::<_, 6>")] + pub fmspc: Fmspc, + pce_id: String, + tcb_type: u16, + tcb_evaluation_data_number: u16, + tcb_levels: Vec, +} + +impl TcbInfo { + /// This extracts the necessary information into a tuple (`(Key, Value)`) that we actually store + /// in the chain + pub fn to_chain_tcb_info(&self) -> (Fmspc, TcbInfoOnChain) { + let valid_tcbs: Vec = self + .tcb_levels + .iter() + // Only store TCB levels on chain that are currently valid + .filter(|tcb| tcb.is_valid()) + .map(|tcb| { + let mut components = [0u8; 16]; + for (i, t) in tcb.tcb.sgxtcbcomponents.iter().enumerate() { + components[i] = t.svn; + } + TcbVersionStatus::new(components, tcb.tcb.pcesvn) + }) + .collect(); + ( + self.fmspc, + TcbInfoOnChain::new( + self.issue_date + .timestamp_millis() + .try_into() + .expect("no support for negative unix timestamps"), + self.next_update + .timestamp_millis() + .try_into() + .expect("no support for negative unix timestamps"), + valid_tcbs, + ), + ) + } + + pub fn is_valid(&self, timestamp_millis: i64) -> bool { + self.id == "SGX" && + self.version == 3 && + self.issue_date.timestamp_millis() < timestamp_millis && + timestamp_millis < self.next_update.timestamp_millis() + } +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TcbInfoSigned { + pub tcb_info: TcbInfo, + pub signature: String, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct EnclaveIdentitySigned { + pub enclave_identity: EnclaveIdentity, + pub signature: String, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn tcb_level_is_valid() { + let t: TcbLevel = serde_json::from_str( + r#"{"tcb":{"isvsvn":6}, "tcbDate":"2021-11-10T00:00:00Z", "tcbStatus":"UpToDate" }"#, + ) + .unwrap(); + assert!(t.is_valid()); + + let t: TcbLevel = serde_json::from_str( + r#"{"tcb":{"isvsvn":6}, "tcbDate":"2021-11-10T00:00:00Z", "tcbStatus":"OutOfDate" }"#, + ) + .unwrap(); + assert!(!t.is_valid()); + + let t: TcbLevel = serde_json::from_str( + r#"{"tcb":{"isvsvn":5}, "tcbDate":"2021-11-10T00:00:00Z", "tcbStatus":"UpToDate" }"#, + ) + .unwrap(); + assert!(!t.is_valid()); + } +} diff --git a/pallets/teebag/src/sgx_verify/ephemeral_key.rs b/pallets/teebag/src/sgx_verify/ephemeral_key.rs new file mode 100644 index 0000000000..29bc989704 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/ephemeral_key.rs @@ -0,0 +1,31 @@ +use super::{utils::length_from_raw_data, CertDer}; +use sp_std::convert::TryFrom; + +pub struct EphemeralKey<'a>(&'a [u8]); + +pub const PRIME256V1_OID: &[u8; 10] = &[0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]; +impl<'a> TryFrom> for EphemeralKey<'a> { + type Error = &'static str; + + fn try_from(value: CertDer<'a>) -> Result { + let cert_der = value.0; + + let mut offset = cert_der + .windows(PRIME256V1_OID.len()) + .position(|window| window == PRIME256V1_OID) + .ok_or("Certificate does not contain 'PRIME256V1_OID'")?; + + offset += PRIME256V1_OID.len() + 1; // OID length + TAG (0x03) + + // Obtain Public Key length + let len = length_from_raw_data(cert_der, &mut offset)?; + + // Obtain Public Key + offset += 1; + let pub_k = cert_der.get(offset + 2..offset + len).ok_or("Index out of bounds")?; // skip "00 04" + + #[cfg(test)] + println!("verifyRA ephemeral public key: {:x?}", pub_k); + Ok(EphemeralKey(pub_k)) + } +} diff --git a/pallets/teebag/src/sgx_verify/fuzz/Cargo.lock b/pallets/teebag/src/sgx_verify/fuzz/Cargo.lock new file mode 100644 index 0000000000..d9f131e6a9 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/fuzz/Cargo.lock @@ -0,0 +1,3589 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli 0.26.2", +] + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli 0.27.2", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.8", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom 0.2.8", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anyhow" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" + +[[package]] +name = "arbitrary" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0224938f92e7aef515fac2ff2d18bd1115c1394ddf4a092e0c87e8be9499ee5" + +[[package]] +name = "array-bytes" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "async-trait" +version = "0.1.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.4", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line 0.19.0", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.30.2", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.6", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.6", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "bounded-collections" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a071c348a5ef6da1d3a87166b408170b46002382b1dda83992b5c2208cefb370" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-expr" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +dependencies = [ + "iana-time-zone", + "num-integer", + "num-traits", + "serde", + "winapi", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "const-oid" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-entity" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42ea692c7b450ad18b8c9889661505d51c09ec4380cf1c2d278dbb2da22cae1" +dependencies = [ + "serde", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array 0.14.6", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.6", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.6", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.6", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder", + "digest 0.8.1", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "cxx" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c00419335c41018365ddf7e4d5f1c12ee3659ddcf3e01974650ba1de73d038" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb8307ad413a98fff033c8545ecf133e3257747b3bae935e7602aab8aa92d4ca" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.4", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc52e2eb08915cb12596d29d55f0b5384f00d697a646dbd269b6ecb0fbd9d31" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "631569015d0d8d54e6c241733f944042623ab6df7bc3be7466874b05fcdb1c5f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.4", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "der_derive", + "flagset", + "zeroize", +] + +[[package]] +name = "der_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef71ddb5b3a1f53dee24817c8f70dfa1cb29e804c18d88c228d4bc9c86ee3b9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79116f119dd1dba1abf1f3405f03b9b0e79a27a3883864bfebded8a3dc768cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.6", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ed25519" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.0", + "ed25519", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest 0.10.6", + "ff", + "generic-array 0.14.6", + "group", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "errno" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "flagset" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "frame-metadata" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df6bb8542ef006ef0de09a5c4420787d79823c0ed7924225822362fd2bf2ff2d" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "frame-support" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "bitflags", + "frame-metadata", + "frame-support-procedural", + "impl-trait-for-tuples", + "k256", + "log", + "once_cell", + "parity-scale-codec", + "paste", + "scale-info", + "serde", + "smallvec", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-core-hashing-proc-macro", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-weights", + "tt-call", +] + +[[package]] +name = "frame-support-procedural" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "Inflector", + "cfg-expr", + "derive-syn-parse", + "frame-support-procedural-tools", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "frame-support-procedural-tools-derive", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "3.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" + +[[package]] +name = "futures-executor" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" + +[[package]] +name = "futures-macro" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "futures-sink" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" + +[[package]] +name = "futures-task" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" + +[[package]] +name = "futures-util" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.6", + "hmac 0.8.1", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.45.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2 0.10.6", +] + +[[package]] +name = "keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fff891139ee62800da71b7fd5b508d570b9ad95e614a53c6f453ca08366038" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memfd" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb" +dependencies = [ + "rustix", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memory-db" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e0c7cba9ce19ac7ffd2053ac9f49843bbd3f4318feedfd74e85c19d5fb0ba66" +dependencies = [ + "hash-db", + "hashbrown 0.12.3", +] + +[[package]] +name = "memory_units" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" + +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec 0.7.2", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "object" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +dependencies = [ + "crc32fast", + "hashbrown 0.12.3", + "indexmap", + "memchr", +] + +[[package]] +name = "object" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b8c786513eb403643f2a88c244c2aaa270ef2153f55094587d0c48a3cf22a83" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "parity-scale-codec" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637935964ff85a605d114591d4d2c13c5d1ba2806dae97cea6bf180238a749ac" +dependencies = [ + "arrayvec 0.7.2", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parity-wasm" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.45.0", +] + +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.4", +] + +[[package]] +name = "regex" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac 0.12.1", + "zeroize", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "git+https://github.com/betrusted-io/ring-xous?branch=0.16.20-cleanup#4296c2e7904898766cf7d8d589759a129794783b" +dependencies = [ + "cc", + "libc", + "log", + "once_cell", + "rkyv", + "spin", + "untrusted 0.7.1", + "winapi", + "xous", + "xous-api-names", + "xous-ipc", +] + +[[package]] +name = "rkyv" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70de01b38fe7baba4ecdd33b777096d2b326993d8ea99bc5b6ede691883d3010" +dependencies = [ + "memoffset", + "ptr_meta", + "rkyv_derive", +] + +[[package]] +name = "rkyv_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a169f6bc5a81033e86ed39d0f4150e2608160b73d2b93c6e8e6a3efa873f14" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustix" +version = "0.36.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6da3636faa25820d8648e0e31c5d519bbb01f72fdf57131f0f5f7da5fed36eab" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustls-pki-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47003264dea418db67060fa420ad16d0d2f8f0a0360d825c00e177ac52cb5d8" + +[[package]] +name = "rustls-webpki" +version = "0.102.0-alpha.3" +source = "git+https://github.com/rustls/webpki?rev=da923ed#da923edaab56f599971e58773617fb574cd019dc" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "scale-info" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "schnellru" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +dependencies = [ + "ahash 0.8.3", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "getrandom 0.1.16", + "merlin", + "rand 0.7.3", + "rand_core 0.5.1", + "sha2 0.8.2", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scratch" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array 0.14.6", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9512ffd81e3a3503ed401f79c33168b9148c75038956039166cd750eaa037c3" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.160" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.160" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.4", +] + +[[package]] +name = "serde_json" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sgx-verify" +version = "0.1.4" +dependencies = [ + "base64", + "chrono", + "der", + "frame-support", + "hex", + "parity-scale-codec", + "ring", + "rustls-webpki", + "scale-info", + "serde", + "serde_json", + "sp-core", + "sp-std", + "teerex-primitives", + "x509-cert", +] + +[[package]] +name = "sgx-verify-fuzz" +version = "0.0.0" +dependencies = [ + "base64", + "libfuzzer-sys", + "parity-scale-codec", + "rustls-webpki", + "serde_json", + "sgx-verify", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.6", +] + +[[package]] +name = "sha3" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +dependencies = [ + "digest 0.10.6", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.6", + "rand_core 0.6.4", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "sp-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "sp-api-proc-macro", + "sp-core", + "sp-runtime", + "sp-state-machine", + "sp-std", + "sp-trie", + "sp-version", + "thiserror", +] + +[[package]] +name = "sp-api-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "blake2", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp-application-crypto" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sp-arithmetic" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-core" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "array-bytes", + "base58", + "bitflags", + "blake2", + "bounded-collections", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "lazy_static", + "libsecp256k1", + "log", + "merlin", + "parity-scale-codec", + "parking_lot", + "primitive-types", + "rand 0.8.5", + "regex", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-core-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tiny-bip39", + "zeroize", +] + +[[package]] +name = "sp-core-hashing" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "blake2", + "byteorder", + "digest 0.10.6", + "sha2 0.10.6", + "sha3", + "sp-std", + "twox-hash", +] + +[[package]] +name = "sp-core-hashing-proc-macro" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "proc-macro2", + "quote", + "sp-core-hashing", + "syn 1.0.109", +] + +[[package]] +name = "sp-debug-derive" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp-externalities" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std", + "sp-storage", +] + +[[package]] +name = "sp-inherents" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "async-trait", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", + "thiserror", +] + +[[package]] +name = "sp-io" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "bytes", + "ed25519", + "ed25519-dalek", + "futures", + "libsecp256k1", + "log", + "parity-scale-codec", + "secp256k1", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "async-trait", + "futures", + "merlin", + "parity-scale-codec", + "parking_lot", + "schnorrkel", + "sp-core", + "sp-externalities", + "thiserror", +] + +[[package]] +name = "sp-panic-handler" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "Inflector", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp-staking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-state-machine" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand 0.8.5", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-std", + "sp-trie", + "thiserror", + "tracing", +] + +[[package]] +name = "sp-std" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" + +[[package]] +name = "sp-storage" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "sp-tracing" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "parity-scale-codec", + "sp-std", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-trie" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "ahash 0.8.3", + "hash-db", + "hashbrown 0.12.3", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "scale-info", + "schnellru", + "sp-core", + "sp-std", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-version" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "parity-wasm", + "scale-info", + "serde", + "sp-core-hashing-proc-macro", + "sp-runtime", + "sp-std", + "sp-version-proc-macro", + "thiserror", +] + +[[package]] +name = "sp-version-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp-wasm-interface" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std", + "wasmi", + "wasmtime", +] + +[[package]] +name = "sp-weights" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#1837f423b494254e1d27834b1c9da34b2c0c2375" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-core", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ss58-registry" +version = "1.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecf0bd63593ef78eca595a7fc25e9a443ca46fe69fd472f8f09f5245cdcd769d" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "substrate-bip39" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c" +dependencies = [ + "hmac 0.11.0", + "pbkdf2 0.8.0", + "schnorrkel", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c622ae390c9302e214c31013517c2061ecb2699935882c60a9b37f82f8625ae" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" + +[[package]] +name = "teerex-primitives" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.4", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac 0.12.1", + "once_cell", + "pbkdf2 0.11.0", + "rand 0.8.5", + "rustc-hash", + "sha2 0.10.6", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" + +[[package]] +name = "toml_edit" +version = "0.19.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc18466501acd8ac6a3f615dd29a3438f8ca6bb3b19537138b3106e575621274" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "trie-db" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3390c0409daaa6027d6681393316f4ccd3ff82e1590a1e4725014e3ae2bf1920" +dependencies = [ + "hash-db", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a36c5ca3911ed3c9a5416ee6c679042064b93fc637ded67e25f92e68d783891" +dependencies = [ + "hash-db", +] + +[[package]] +name = "tt-call" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.6", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "wasmi" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c326c93fbf86419608361a2c925a31754cf109da1b8b55737070b4d6669422" +dependencies = [ + "parity-wasm", + "wasmi-validation", + "wasmi_core", +] + +[[package]] +name = "wasmi-validation" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ff416ad1ff0c42e5a926ed5d5fab74c0f098749aa0ad8b2a34b982ce0e867b" +dependencies = [ + "parity-wasm", +] + +[[package]] +name = "wasmi_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d20cb3c59b788653d99541c646c561c9dd26506f25c0cebfe810659c54c6d7" +dependencies = [ + "downcast-rs", + "libm", + "memory_units", + "num-rational", + "num-traits", +] + +[[package]] +name = "wasmparser" +version = "0.100.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4" +dependencies = [ + "indexmap", + "url", +] + +[[package]] +name = "wasmtime" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a222f5fa1e14b2cefc286f1b68494d7a965f4bf57ec04c59bb62673d639af6" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "indexmap", + "libc", + "log", + "object 0.29.0", + "once_cell", + "paste", + "psm", + "serde", + "target-lexicon", + "wasmparser", + "wasmtime-environ", + "wasmtime-jit", + "wasmtime-runtime", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4407a7246e7d2f3d8fb1cf0c72fda8dbafdb6dd34d555ae8bea0e5ae031089cc" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-environ" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b8b50962eae38ee319f7b24900b7cf371f03eebdc17400c1dc8575fc10c9a7" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli 0.26.2", + "indexmap", + "log", + "object 0.29.0", + "serde", + "target-lexicon", + "thiserror", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-jit" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffaed4f9a234ba5225d8e64eac7b4a5d13b994aeb37353cde2cbeb3febda9eaa" +dependencies = [ + "addr2line 0.17.0", + "anyhow", + "bincode", + "cfg-if", + "cpp_demangle", + "gimli 0.26.2", + "log", + "object 0.29.0", + "rustc-demangle", + "serde", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed41cbcbf74ce3ff6f1d07d1b707888166dc408d1a880f651268f4f7c9194b2" +dependencies = [ + "once_cell", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a28ae1e648461bfdbb79db3efdaee1bca5b940872e4175390f465593a2e54c" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e704b126e4252788ccfc3526d4d4511d4b23c521bf123e447ac726c14545217b" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "indexmap", + "libc", + "log", + "mach", + "memfd", + "memoffset", + "paste", + "rand 0.8.5", + "rustix", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-jit-debug", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-types" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e5572c5727c1ee7e8f28717aaa8400e4d22dcbd714ea5457d85b5005206568" +dependencies = [ + "cranelift-entity", + "serde", + "thiserror", + "wasmparser", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d020b441f92996c80d94ae9166e8501e59c7bb56121189dc9eab3bd8216966" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x509-cert" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d224a125dec5adda27d0346b9cae9794830279c4f9c27e4ab0b6c408d54012" +dependencies = [ + "const-oid", + "der", + "flagset", + "spki", +] + +[[package]] +name = "xous" +version = "0.9.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a9f0a696320940ab2652fa1d20c98dc59eb7ba4591eeb91a3b8e40bc9255a1" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "xous-api-log" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e07c190c743d6d9e076f715333e94c48de41b99078343d174c707803df28c7" +dependencies = [ + "log", + "num-derive", + "num-traits", + "xous", + "xous-ipc", +] + +[[package]] +name = "xous-api-names" +version = "0.9.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d8361077e67966d25922056284d17d042cbb1c96a7ebc2584eb8181427cbb0" +dependencies = [ + "log", + "num-derive", + "num-traits", + "rkyv", + "xous", + "xous-api-log", + "xous-ipc", +] + +[[package]] +name = "xous-ipc" +version = "0.9.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee1d318dacbd6242e4e2291dee7c4532249e5a0845de05d264c20fc871a0a1a" +dependencies = [ + "bitflags", + "rkyv", + "xous", +] + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] diff --git a/pallets/teebag/src/sgx_verify/fuzz/Cargo.toml b/pallets/teebag/src/sgx_verify/fuzz/Cargo.toml new file mode 100644 index 0000000000..7742a90c27 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/fuzz/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "sgx-verify-fuzz" +version = "0.0.0" +publish = false +edition = "2021" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +base64 = { version = "0.13", default-features = false, features = ["alloc"] } +codec = { version = "3.0.0", default-features = false, features = ["derive"], package = "parity-scale-codec" } +libfuzzer-sys = "0.4" +serde_json = { version = "1.0" } +webpki = { git = "https://github.com/rustls/webpki", version = "=0.102.0-alpha.3", rev = "da923ed", package = "rustls-webpki", default-features = false, features = ["alloc", "ring"] } + +[dependencies.sgx-verify] +path = ".." + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[profile.release] +debug = 1 + +[[bin]] +name = "decode_quote" +path = "fuzz_targets/decode_quote.rs" +test = false +doc = false + +[[bin]] +name = "deserialize_json" +path = "fuzz_targets/deserialize_json.rs" +test = false +doc = false + +[[bin]] +name = "signature_check" +path = "fuzz_targets/signature_check.rs" +test = false +doc = false + +[[bin]] +name = "extract_tcb_info" +path = "fuzz_targets/extract_tcb_info.rs" +test = false +doc = false + +[[bin]] +name = "verify_ias_report" +path = "fuzz_targets/verify_ias_report.rs" +test = false +doc = false + +[patch.crates-io] +ring = { git = "https://github.com/betrusted-io/ring-xous", branch = "0.16.20-cleanup" } diff --git a/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/decode_quote.rs b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/decode_quote.rs new file mode 100644 index 0000000000..eea9f6dd86 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/decode_quote.rs @@ -0,0 +1,15 @@ +#![no_main] + +use codec::{Decode}; +use libfuzzer_sys::fuzz_target; +use sgx_verify::DcapQuote; + +fuzz_target!(|data: &[u8]| { + let mut copy = data; + let _quote: Result = Decode::decode(&mut copy); + + // This assert is commented out because the fuzzer manages to find a "valid" quote that can + // at least be decoded into memory. We would need additional verification steps (for example signature) + // to enable this check. + //assert!(quote.is_err()); +}); diff --git a/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/deserialize_json.rs b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/deserialize_json.rs new file mode 100644 index 0000000000..d5ac8e06fc --- /dev/null +++ b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/deserialize_json.rs @@ -0,0 +1,11 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use sgx_verify::collateral::{EnclaveIdentity, TcbInfo}; + +fuzz_target!(|data: &[u8]| { + let enclave: Result = serde_json::from_slice(data); + assert!(enclave.is_err()); + let tcb_info: Result = serde_json::from_slice(data); + assert!(tcb_info.is_err()); +}); diff --git a/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/extract_tcb_info.rs b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/extract_tcb_info.rs new file mode 100644 index 0000000000..3f082eed1d --- /dev/null +++ b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/extract_tcb_info.rs @@ -0,0 +1,8 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use sgx_verify::extract_tcb_info; + +fuzz_target!(|data: &[u8]| { + assert!(extract_tcb_info(data).is_err()); +}); diff --git a/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/signature_check.rs b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/signature_check.rs new file mode 100644 index 0000000000..054a3f7b15 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/signature_check.rs @@ -0,0 +1,25 @@ +#![no_main] +#![feature(core_panic)] + +pub extern crate alloc; +extern crate core; + +use libfuzzer_sys::fuzz_target; +use sgx_verify::deserialize_enclave_identity; + +fuzz_target!(|data: &[u8]| { + if data.len() < 64 { + return + } + + let cert = include_str!("../../test/dcap/qe_identity_cert.pem"); + let cert = cert.replace('\n', ""); + let decoded_cert = base64::decode(&cert).unwrap(); + let cert_der = webpki::types::CertificateDer::from(decoded_cert.as_slice()); + let cert = webpki::EndEntityCert::try_from(&cert_der).unwrap(); + let quoting_enclave = br#"{"id":"QE","version":2,"issueDate":"2022-10-18T21:55:07Z","nextUpdate":"2022-11-17T21:55:07Z","tcbEvaluationDataNumber":12,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":6},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate"}]}"#; + let signature = &data[0..64]; + + let res = deserialize_enclave_identity("ing_enclave[..], &signature, &cert); + assert!(res.is_err(), "Found a valid signature"); +}); diff --git a/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/verify_ias_report.rs b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/verify_ias_report.rs new file mode 100644 index 0000000000..99610e5375 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/fuzz/fuzz_targets/verify_ias_report.rs @@ -0,0 +1,9 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; +use sgx_verify::verify_ias_report; + +fuzz_target!(|data: &[u8]| { + // Check test that there is now panic and that the provided data is not a valid IAS report + assert!(verify_ias_report(data).is_err()); +}); diff --git a/pallets/teebag/src/sgx_verify/mod.rs b/pallets/teebag/src/sgx_verify/mod.rs new file mode 100644 index 0000000000..9572fd879a --- /dev/null +++ b/pallets/teebag/src/sgx_verify/mod.rs @@ -0,0 +1,881 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Contains all the logic for understanding and verifying SGX remote attestation reports. +//! +//! Intel's documentation is scattered across different documents: +//! +//! "Intel® Software Guard Extensions: PCK Certificate and Certificate Revocation List Profile +//! Specification", further denoted as `PCK_Certificate_CRL_Spec-1.1`. +//! +//! * https://download.01.org/intel-sgx/dcap-1.2/linux/docs/Intel_SGX_PCK_Certificate_CRL_Spec-1.1.pdf +//! +//! Intel® SGX Developer Guide, further denoted as `SGX_Developer_Guide`: +//! +//! * https://download.01.org/intel-sgx/linux-1.5/docs/Intel_SGX_Developer_Guide.pdf + +pub extern crate alloc; + +use self::{ + collateral::{EnclaveIdentity, TcbInfo}, + netscape_comment::NetscapeComment, + utils::length_from_raw_data, +}; +use crate::{ + Cpusvn, Fmspc, MrEnclave, MrSigner, Pcesvn, QuotingEnclave, SgxBuildMode, TcbVersionStatus, +}; +use alloc::string::String; +use chrono::DateTime; +use codec::{Decode, Encode, Input}; +use core::time::Duration; +use der::asn1::ObjectIdentifier; +use frame_support::{ensure, traits::Len}; +use ring::signature::{self}; +use scale_info::TypeInfo; +use serde_json::Value; +use sp_std::{ + convert::{TryFrom, TryInto}, + prelude::*, +}; +use x509_cert::Certificate; + +pub mod collateral; +mod ephemeral_key; +mod netscape_comment; +#[cfg(test)] +mod tests; +mod utils; + +const SGX_REPORT_DATA_SIZE: usize = 64; +#[derive(Debug, Encode, Decode, PartialEq, Eq, Copy, Clone, TypeInfo)] +#[repr(C)] +pub struct SgxReportData { + d: [u8; SGX_REPORT_DATA_SIZE], +} + +#[derive(Debug, Encode, Decode, PartialEq, Eq, Copy, Clone, TypeInfo)] +#[repr(C)] +pub struct SGXAttributes { + flags: u64, + xfrm: u64, +} + +/// This is produced by an SGX platform, when it wants to be attested. +#[derive(Debug, Decode, Clone, TypeInfo)] +#[repr(C)] +pub struct DcapQuote { + header: DcapQuoteHeader, + body: SgxReportBody, + signature_data_len: u32, + quote_signature_data: EcdsaQuoteSignature, +} + +/// All the documentation about this can be found in the `PCK_Certificate_CRL_Spec-1.1` page 62. +#[derive(Debug, Encode, Decode, Copy, Clone, TypeInfo)] +#[repr(C)] +pub struct DcapQuoteHeader { + /// Version of the Quote data structure. + /// + /// This is version 3 for the DCAP ECDSA attestation. + version: u16, + /// Type of the Attestation Key used by the Quoting Enclave. + /// • Supported values: + /// - 2 (ECDSA-256-with-P-256 curve) + /// - 3 (ECDSA-384-with-P-384 curve) (Note: currently not supported) + attestation_key_type: u16, + /// Reserved field, value 0. + reserved: u32, + /// Security Version of the Quoting Enclave currently loaded on the platform. + qe_svn: u16, + /// Security Version of the Provisioning Certification Enclave currently loaded on the + /// platform. + pce_svn: u16, + /// Unique identifier of the QE Vendor. + /// + /// This will usually be Intel's Quoting enclave with the ID: 939A7233F79C4CA9940A0DB3957F0607. + qe_vendor_id: [u8; 16], + /// Custom user-defined data. + user_data: [u8; 20], +} + +const ATTESTATION_KEY_SIZE: usize = 64; +const REPORT_SIGNATURE_SIZE: usize = 64; + +#[derive(Debug, Decode, Clone, TypeInfo)] +#[repr(C)] +pub struct EcdsaQuoteSignature { + isv_enclave_report_signature: [u8; REPORT_SIGNATURE_SIZE], + ecdsa_attestation_key: [u8; ATTESTATION_KEY_SIZE], + qe_report: SgxReportBody, + qe_report_signature: [u8; REPORT_SIGNATURE_SIZE], + qe_authentication_data: QeAuthenticationData, + qe_certification_data: QeCertificationData, +} + +#[derive(Debug, Clone, TypeInfo)] +#[repr(C)] +pub struct QeAuthenticationData { + size: u16, + certification_data: Vec, +} + +impl Decode for QeAuthenticationData { + fn decode(input: &mut I) -> Result { + let mut size_buf: [u8; 2] = [0; 2]; + input.read(&mut size_buf)?; + let size = u16::from_le_bytes(size_buf); + + let mut certification_data = vec![0; size.into()]; + input.read(&mut certification_data)?; + + Ok(Self { size, certification_data }) + } +} + +#[derive(Debug, Clone, TypeInfo)] +#[repr(C)] +pub struct QeCertificationData { + certification_data_type: u16, + size: u32, + certification_data: Vec, +} + +impl Decode for QeCertificationData { + fn decode(input: &mut I) -> Result { + let mut certification_data_type_buf: [u8; 2] = [0; 2]; + input.read(&mut certification_data_type_buf)?; + let certification_data_type = u16::from_le_bytes(certification_data_type_buf); + + let mut size_buf: [u8; 4] = [0; 4]; + input.read(&mut size_buf)?; + let size = u32::from_le_bytes(size_buf); + // This is an arbitrary limit to prevent out of memory issues. Intel does not specify a max + // value + if size > 65_000 { + return Result::Err(codec::Error::from( + "Certification data too long. Max 65000 bytes are allowed", + )) + } + + // Safety: The try_into() can only fail due to overflow on a 16-bit system, but we anyway + // ensure the value is small enough above. + let mut certification_data = vec![0; size.try_into().unwrap()]; + input.read(&mut certification_data)?; + + Ok(Self { certification_data_type, size, certification_data }) + } +} + +// see Intel SGX SDK https://github.com/intel/linux-sgx/blob/master/common/inc/sgx_report.h +const SGX_REPORT_BODY_RESERVED1_BYTES: usize = 12; +const SGX_REPORT_BODY_RESERVED2_BYTES: usize = 32; +const SGX_REPORT_BODY_RESERVED3_BYTES: usize = 32; +const SGX_REPORT_BODY_RESERVED4_BYTES: usize = 42; +const SGX_FLAGS_DEBUG: u64 = 0x0000000000000002; + +/// SGX report about an enclave. +/// +/// We don't verify all of the fields, as some contain business logic specific data that is +/// not related to the overall validity of an enclave. We only check security related fields. The +/// only exception to this is the quoting enclave, where we validate specific fields against known +/// values. +#[derive(Debug, Encode, Decode, Copy, Clone, TypeInfo)] +#[repr(C)] +pub struct SgxReportBody { + /// Security version of the CPU. + /// + /// Reflects the processors microcode update version. + cpu_svn: [u8; 16], /* ( 0) Security Version of the CPU */ + /// State Save Area (SSA) extended feature set. Flags used for specific exception handling + /// settings. Unless, you know what you are doing these should all be 0. + /// + /// See: https://cdrdv2-public.intel.com/671544/exception-handling-in-intel-sgx.pdf. + misc_select: [u8; 4], /* ( 16) Which fields defined in SSA.MISC */ + /// Unused reserved bytes. + reserved1: [u8; SGX_REPORT_BODY_RESERVED1_BYTES], /* ( 20) */ + /// Extended Product ID of an enclave. + isv_ext_prod_id: [u8; 16], /* ( 32) ISV assigned Extended Product ID */ + /// Attributes, defines features that should be enabled for an enclave. + /// + /// Here, we only check if the Debug mode is enabled. + /// + /// More details in `SGX_Developer_Guide` under `Debug (Opt-in) Enclave Consideration` on page + /// 24. + attributes: SGXAttributes, /* ( 48) Any special Capabilities the Enclave possess */ + /// Enclave measurement. + /// + /// A single 256-bit hash that identifies the code and initial data to + /// be placed inside the enclave, the expected order and position in which they are to be + /// placed, and the security properties of those pages. More details in `SGX_Developer_Guide` + /// page 6. + mr_enclave: MrEnclave, /* ( 64) The value of the enclave's ENCLAVE measurement */ + /// Unused reserved bytes. + reserved2: [u8; SGX_REPORT_BODY_RESERVED2_BYTES], /* ( 96) */ + /// The enclave author’s public key. + /// + /// More details in `SGX_Developer_Guide` page 6. + mr_signer: MrSigner, /* (128) The value of the enclave's SIGNER measurement */ + /// Unused reserved bytes. + reserved3: [u8; SGX_REPORT_BODY_RESERVED3_BYTES], /* (160) */ + /// Config ID of an enclave. + /// + /// Todo: #142 - Investigate the relevancy of this value. + config_id: [u8; 64], /* (192) CONFIGID */ + /// The Product ID of the enclave. + /// + /// The Independent Software Vendor (ISV) should configure a unique ISVProdID for each product + /// that may want to share sealed data between enclaves signed with a specific `MRSIGNER`. + isv_prod_id: u16, /* (256) Product ID of the Enclave */ + /// ISV security version of the enclave. + /// + /// This is the enclave author's responsibility to increase it whenever a security related + /// update happened. Here, we will only check it for the `Quoting Enclave` to ensure that the + /// quoting enclave is recent enough. + /// + /// More details in `SGX_Developer_Guide` page 6. + isv_svn: u16, /* (258) Security Version of the Enclave */ + /// Config Security version of the enclave. + config_svn: u16, /* (260) CONFIGSVN */ + /// Unused reserved bytes. + reserved4: [u8; SGX_REPORT_BODY_RESERVED4_BYTES], /* (262) */ + /// Family ID assigned by the ISV. + /// + /// Todo: #142 - Investigate the relevancy of this value. + isv_family_id: [u8; 16], /* (304) ISV assigned Family ID */ + /// Custom data to be defined by the enclave author. + /// + /// We use this to provide the public key of the enclave that is to be registered on the chain. + /// Doing this, will prove that the public key is from a legitimate SGX enclave when it is + /// verified together with the remote attestation. + report_data: SgxReportData, /* (320) Data provided by the user */ +} + +impl SgxReportBody { + pub fn sgx_build_mode(&self) -> SgxBuildMode { + #[cfg(test)] + println!("attributes flag : {:x}", self.attributes.flags); + if self.attributes.flags & SGX_FLAGS_DEBUG == SGX_FLAGS_DEBUG { + SgxBuildMode::Debug + } else { + SgxBuildMode::Production + } + } + + fn verify_misc_select_field(&self, o: &QuotingEnclave) -> bool { + for i in 0..self.misc_select.len() { + if (self.misc_select[i] & o.miscselect_mask[i]) != + (o.miscselect[i] & o.miscselect_mask[i]) + { + return false + } + } + true + } + + fn verify_attributes_field(&self, o: &QuotingEnclave) -> bool { + let attributes_flags = self.attributes.flags; + + let quoting_enclave_attributes_mask = o.attributes_flags_mask_as_u64(); + let quoting_enclave_attributes_flags = o.attributes_flags_as_u64(); + + (attributes_flags & quoting_enclave_attributes_mask) == quoting_enclave_attributes_flags + } + + pub fn verify(&self, o: &QuotingEnclave) -> bool { + if self.isv_prod_id != o.isvprodid || self.mr_signer != o.mrsigner { + return false + } + if !self.verify_misc_select_field(o) { + return false + } + if !self.verify_attributes_field(o) { + return false + } + for tcb in &o.tcb { + // If the enclave isvsvn is bigger than one of the + if self.isv_svn >= tcb.isvsvn { + return true + } + } + false + } +} +// see Intel SGX SDK https://github.com/intel/linux-sgx/blob/master/common/inc/sgx_quote.h +#[derive(Encode, Decode, Copy, Clone, TypeInfo)] +#[repr(C)] +pub struct SgxQuote { + version: u16, /* 0 */ + sign_type: u16, /* 2 */ + epid_group_id: u32, /* 4 */ + qe_svn: u16, /* 8 */ + pce_svn: u16, /* 10 */ + xeid: u32, /* 12 */ + basename: [u8; 32], /* 16 */ + report_body: SgxReportBody, /* 48 */ +} + +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, sp_core::RuntimeDebug, TypeInfo, Default)] +pub enum SgxStatus { + #[default] + #[codec(index = 0)] + Invalid, + #[codec(index = 1)] + Ok, + #[codec(index = 2)] + GroupOutOfDate, + #[codec(index = 3)] + GroupRevoked, + #[codec(index = 4)] + ConfigurationNeeded, +} + +#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, sp_core::RuntimeDebug, TypeInfo)] +pub struct SgxReport { + pub mr_enclave: MrEnclave, + pub pubkey: [u8; 32], + pub status: SgxStatus, + pub timestamp: u64, // unix timestamp in milliseconds + pub build_mode: SgxBuildMode, +} + +type SignatureAlgorithms = &'static [&'static dyn webpki::types::SignatureVerificationAlgorithm]; +static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[ + webpki::ring::RSA_PKCS1_2048_8192_SHA256, + webpki::ring::RSA_PKCS1_2048_8192_SHA384, + webpki::ring::RSA_PKCS1_2048_8192_SHA512, + webpki::ring::RSA_PKCS1_3072_8192_SHA384, +]; + +//pub const IAS_REPORT_CA: &[u8] = include_bytes!("../AttestationReportSigningCACert.pem"); + +pub static IAS_SERVER_ROOTS: &[webpki::types::TrustAnchor<'static>; 1] = &[ + /* + * -----BEGIN CERTIFICATE----- + * MIIFSzCCA7OgAwIBAgIJANEHdl0yo7CUMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV + * BAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV + * BAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0 + * YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwIBcNMTYxMTE0MTUzNzMxWhgPMjA0OTEy + * MzEyMzU5NTlaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwL + * U2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQD + * DCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwggGiMA0G + * CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCfPGR+tXc8u1EtJzLA10Feu1Wg+p7e + * LmSRmeaCHbkQ1TF3Nwl3RmpqXkeGzNLd69QUnWovYyVSndEMyYc3sHecGgfinEeh + * rgBJSEdsSJ9FpaFdesjsxqzGRa20PYdnnfWcCTvFoulpbFR4VBuXnnVLVzkUvlXT + * L/TAnd8nIZk0zZkFJ7P5LtePvykkar7LcSQO85wtcQe0R1Raf/sQ6wYKaKmFgCGe + * NpEJUmg4ktal4qgIAxk+QHUxQE42sxViN5mqglB0QJdUot/o9a/V/mMeH8KvOAiQ + * byinkNndn+Bgk5sSV5DFgF0DffVqmVMblt5p3jPtImzBIH0QQrXJq39AT8cRwP5H + * afuVeLHcDsRp6hol4P+ZFIhu8mmbI1u0hH3W/0C2BuYXB5PC+5izFFh/nP0lc2Lf + * 6rELO9LZdnOhpL1ExFOq9H/B8tPQ84T3Sgb4nAifDabNt/zu6MmCGo5U8lwEFtGM + * RoOaX4AS+909x00lYnmtwsDVWv9vBiJCXRsCAwEAAaOByTCBxjBgBgNVHR8EWTBX + * MFWgU6BRhk9odHRwOi8vdHJ1c3RlZHNlcnZpY2VzLmludGVsLmNvbS9jb250ZW50 + * L0NSTC9TR1gvQXR0ZXN0YXRpb25SZXBvcnRTaWduaW5nQ0EuY3JsMB0GA1UdDgQW + * BBR4Q3t2pn680K9+QjfrNXw7hwFRPDAfBgNVHSMEGDAWgBR4Q3t2pn680K9+Qjfr + * NXw7hwFRPDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkq + * hkiG9w0BAQsFAAOCAYEAeF8tYMXICvQqeXYQITkV2oLJsp6J4JAqJabHWxYJHGir + * IEqucRiJSSx+HjIJEUVaj8E0QjEud6Y5lNmXlcjqRXaCPOqK0eGRz6hi+ripMtPZ + * sFNaBwLQVV905SDjAzDzNIDnrcnXyB4gcDFCvwDFKKgLRjOB/WAqgscDUoGq5ZVi + * zLUzTqiQPmULAQaB9c6Oti6snEFJiCQ67JLyW/E83/frzCmO5Ru6WjU4tmsmy8Ra + * Ud4APK0wZTGtfPXU7w+IBdG5Ez0kE1qzxGQaL4gINJ1zMyleDnbuS8UicjJijvqA + * 152Sq049ESDz+1rRGc2NVEqh1KaGXmtXvqxXcTB+Ljy5Bw2ke0v8iGngFBPqCTVB + * 3op5KBG3RjbF6RRSzwzuWfL7QErNC8WEy5yDVARzTA5+xmBc388v9Dm21HGfcC8O + * DD+gT9sSpssq0ascmvH49MOgjt1yoysLtdCtJW/9FZpoOypaHx0R+mJTLwPXVMrv + * DaVzWh5aiEx+idkSGMnX + * -----END CERTIFICATE----- + */ + webpki::types::TrustAnchor { + subject: webpki::types::Der::from_slice(b"1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x0b0\t\x06\x03U\x04\x08\x0c\x02CA1\x140\x12\x06\x03U\x04\x07\x0c\x0bSanta Clara1\x1a0\x18\x06\x03U\x04\n\x0c\x11Intel Corporation100.\x06\x03U\x04\x03\x0c\'Intel SGX Attestation Report Signing CA"), + subject_public_key_info: webpki::types::Der::from_slice(b"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x8f\x000\x82\x01\x8a\x02\x82\x01\x81\x00\x9f@u1@N6\xb3\x15b7\x99\xaa\x82Pt@\x97T\xa2\xdf\xe8\xf5\xaf\xd5\xfec\x1e\x1f\xc2\xaf8\x08\x90o(\xa7\x90\xd9\xdd\x9f\xe0`\x93\x9b\x12W\x90\xc5\x80]\x03}\xf5j\x99S\x1b\x96\xdei\xde3\xed\"l\xc1 }\x10B\xb5\xc9\xab\x7f@O\xc7\x11\xc0\xfeGi\xfb\x95x\xb1\xdc\x0e\xc4i\xea\x1a%\xe0\xff\x99\x14\x88n\xf2i\x9b#[\xb4\x84}\xd6\xff@\xb6\x06\xe6\x17\x07\x93\xc2\xfb\x98\xb3\x14X\x7f\x9c\xfd%sb\xdf\xea\xb1\x0b;\xd2\xd9vs\xa1\xa4\xbdD\xc4S\xaa\xf4\x7f\xc1\xf2\xd3\xd0\xf3\x84\xf7J\x06\xf8\x9c\x08\x9f\r\xa6\xcd\xb7\xfc\xee\xe8\xc9\x82\x1a\x8eT\xf2\\\x04\x16\xd1\x8cF\x83\x9a_\x80\x12\xfb\xdd=\xc7M%by\xad\xc2\xc0\xd5Z\xffo\x06\"B]\x1b\x02\x03\x01\x00\x01"), + name_constraints: None + }, +]; + +/// The needed code for a trust anchor can be extracted using `webpki` with something like this: +/// println!("{:?}", webpki::TrustAnchor::try_from_cert_der(&root_cert)); +#[allow(clippy::zero_prefixed_literal)] +pub static DCAP_SERVER_ROOTS: &[webpki::types::TrustAnchor<'static>; 1] = + &[webpki::types::TrustAnchor { + subject: webpki::types::Der::from_slice(&[ + 49, 26, 48, 24, 06, 03, 85, 04, 03, 12, 17, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, + 82, 111, 111, 116, 32, 67, 65, 49, 26, 48, 24, 06, 03, 85, 04, 10, 12, 17, 73, 110, + 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, + 06, 03, 85, 04, 07, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, + 09, 06, 03, 85, 04, 08, 12, 02, 67, 65, 49, 11, 48, 09, 06, 03, 85, 04, 06, 19, 02, 85, + 83, + ]), + subject_public_key_info: webpki::types::Der::from_slice(&[ + 48, 19, 06, 07, 42, 134, 72, 206, 61, 02, 01, 06, 08, 42, 134, 72, 206, 61, 03, 01, 07, + 03, 66, 00, 04, 11, 169, 196, 192, 192, 200, 97, 147, 163, 254, 35, 214, 176, 44, 218, + 16, 168, 187, 212, 232, 142, 72, 180, 69, 133, 97, 163, 110, 112, 85, 37, 245, 103, + 145, 142, 46, 220, 136, 228, 13, 134, 11, 208, 204, 78, 226, 106, 172, 201, 136, 229, + 05, 169, 83, 85, 140, 69, 63, 107, 09, 04, 174, 115, 148, + ]), + name_constraints: None, + }]; + +/// Contains an unvalidated ias remote attestation certificate. +/// +/// Wrapper to implemented parsing and verification traits on it. +pub struct CertDer<'a>(&'a [u8]); + +/// Encode two 32-byte values in DER format +/// This is meant for 256 bit ECC signatures or public keys +pub fn encode_as_der(data: &[u8]) -> Result, &'static str> { + if data.len() != 64 { + return Result::Err("Key must be 64 bytes long") + } + let mut sequence = der::asn1::SequenceOf::::new(); + sequence + .add(der::asn1::UIntRef::new(&data[0..32]).map_err(|_| "Invalid public key")?) + .map_err(|_| "Invalid public key")?; + sequence + .add(der::asn1::UIntRef::new(&data[32..]).map_err(|_| "Invalid public key")?) + .map_err(|_| "Invalid public key")?; + // 72 should be enough in all cases. 2 + 2 x (32 + 3) + let mut asn1 = vec![0u8; 72]; + let mut writer = der::SliceWriter::new(&mut asn1); + writer.encode(&sequence).map_err(|_| "Could not encode public key to DER")?; + Ok(writer.finish().map_err(|_| "Could not convert public key to DER")?.to_vec()) +} + +/// Extracts the specified data into a `EnclaveIdentity` instance. +/// Also verifies that the data matches the given signature, was produced by the given certificate +/// and matches the data +pub fn deserialize_enclave_identity( + data: &[u8], + signature: &[u8], + certificate: &webpki::EndEntityCert, +) -> Result { + let signature = encode_as_der(signature)?; + verify_signature(certificate, data, &signature, webpki::ring::ECDSA_P256_SHA256)?; + serde_json::from_slice(data).map_err(|_| "Deserialization failed") +} + +/// Extracts the specified data into a `TcbInfo` instance. +/// Also verifies that the data matches the given signature, was produced by the given certificate +/// and matches the data +pub fn deserialize_tcb_info( + data: &[u8], + signature: &[u8], + certificate: &webpki::EndEntityCert, +) -> Result { + let signature = encode_as_der(signature)?; + verify_signature(certificate, data, &signature, webpki::ring::ECDSA_P256_SHA256)?; + serde_json::from_slice(data).map_err(|_| "Deserialization failed") +} + +/// Extract a list of certificates from a byte vec. The certificates must be separated by +/// `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` markers +pub fn extract_certs(cert_chain: &[u8]) -> Vec> { + // The certificates should be valid UTF-8 but if not we continue. The certificate verification + // will fail at a later point. + let certs_concat = String::from_utf8_lossy(cert_chain); + let certs_concat = certs_concat.replace('\n', ""); + let certs_concat = certs_concat.replace("-----BEGIN CERTIFICATE-----", ""); + // Use the end marker to split the string into certificates + let parts = certs_concat.split("-----END CERTIFICATE-----"); + parts.filter(|p| !p.is_empty()).filter_map(|p| base64::decode(p).ok()).collect() +} + +/// Verifies that the `leaf_cert` in combination with the `intermediate_certs` establishes +/// a valid certificate chain that is rooted in one of the trust anchors that was compiled into to +/// the pallet +pub fn verify_certificate_chain<'a>( + leaf_cert: &webpki::EndEntityCert<'a>, + intermediate_certs: &[webpki::types::CertificateDer<'a>], + verification_time: u64, +) -> Result<(), &'static str> { + let time = + webpki::types::UnixTime::since_unix_epoch(Duration::from_secs(verification_time / 1000)); + let sig_algs = &[webpki::ring::ECDSA_P256_SHA256]; + leaf_cert + .verify_for_usage( + sig_algs, + DCAP_SERVER_ROOTS, + intermediate_certs, + time, + webpki::KeyUsage::client_auth(), + None, + ) + .map_err(|_| "Invalid certificate chain")?; + Ok(()) +} +#[allow(unused)] +pub fn extract_tcb_info_from_raw_dcap_quote( + dcap_quote_raw: &[u8], +) -> Result<(Fmspc, TcbVersionStatus), &'static str> { + let mut dcap_quote_clone = dcap_quote_raw; + let quote: DcapQuote = + Decode::decode(&mut dcap_quote_clone).map_err(|_| "Failed to decode attestation report")?; + + ensure!(quote.header.version == 3, "Only support for version 3"); + ensure!(quote.header.attestation_key_type == 2, "Only support for ECDSA-256"); + ensure!( + quote.quote_signature_data.qe_certification_data.certification_data_type == 5, + "Only support for PEM formatted PCK Cert Chain" + ); + + let certs = extract_certs("e.quote_signature_data.qe_certification_data.certification_data); + + let (fmspc, tcb_info) = extract_tcb_info(&certs[0])?; + + Ok((fmspc, tcb_info)) +} + +pub fn verify_dcap_quote( + dcap_quote_raw: &[u8], + verification_time: u64, + qe: &QuotingEnclave, +) -> Result<(Fmspc, TcbVersionStatus, SgxReport), &'static str> { + let mut dcap_quote_clone = dcap_quote_raw; + let quote: DcapQuote = + Decode::decode(&mut dcap_quote_clone).map_err(|_| "Failed to decode attestation report")?; + + #[cfg(test)] + println!("{:?}", quote); + + ensure!(quote.header.version == 3, "Only support for version 3"); + ensure!(quote.header.attestation_key_type == 2, "Only support for ECDSA-256"); + ensure!( + quote.quote_signature_data.qe_certification_data.certification_data_type == 5, + "Only support for PEM formatted PCK Cert Chain" + ); + ensure!(quote.quote_signature_data.qe_report.verify(qe), "Enclave rejected by quoting enclave"); + let mut xt_signer_array = [0u8; 32]; + xt_signer_array.copy_from_slice("e.body.report_data.d[..32]); + + let certs = extract_certs("e.quote_signature_data.qe_certification_data.certification_data); + ensure!(certs.len() >= 2, "Certificate chain must have at least two certificates"); + let intermediate_certificate_slices: Vec = + certs[1..].iter().map(|c| c.as_slice().into()).collect(); + let leaf_cert_der = webpki::types::CertificateDer::from(certs[0].as_slice()); + let leaf_cert = webpki::EndEntityCert::try_from(&leaf_cert_der) + .map_err(|_| "Failed to parse leaf certificate")?; + verify_certificate_chain(&leaf_cert, &intermediate_certificate_slices, verification_time)?; + + let (fmspc, tcb_info) = extract_tcb_info(&certs[0])?; + + // For this part some understanding of the document (Especially chapter A.4: Quote Format) + // Intel® Software Guard Extensions (Intel® SGX) Data Center Attestation Primitives: ECDSA Quote + // Library API https://download.01.org/intel-sgx/latest/dcap-latest/linux/docs/Intel_SGX_ECDSA_QuoteLibReference_DCAP_API.pdf + + const AUTHENTICATION_DATA_SIZE: usize = 32; // This is actually variable but assume 32 for now. This is also hard-coded to 32 in the Intel + // DCAP repo + const DCAP_QUOTE_HEADER_SIZE: usize = core::mem::size_of::(); + const REPORT_SIZE: usize = core::mem::size_of::(); + const QUOTE_SIGNATURE_DATA_LEN_SIZE: usize = core::mem::size_of::(); + + let attestation_key_offset = DCAP_QUOTE_HEADER_SIZE + + REPORT_SIZE + + QUOTE_SIGNATURE_DATA_LEN_SIZE + + REPORT_SIGNATURE_SIZE; + let authentication_data_offset = attestation_key_offset + + ATTESTATION_KEY_SIZE + + REPORT_SIZE + + REPORT_SIGNATURE_SIZE + + core::mem::size_of::(); //Size of the QE authentication data. We ignore this for now and assume 32. See + // AUTHENTICATION_DATA_SIZE + let mut hash_data = [0u8; ATTESTATION_KEY_SIZE + AUTHENTICATION_DATA_SIZE]; + hash_data[0..ATTESTATION_KEY_SIZE].copy_from_slice( + &dcap_quote_raw[attestation_key_offset..(attestation_key_offset + ATTESTATION_KEY_SIZE)], + ); + hash_data[ATTESTATION_KEY_SIZE..].copy_from_slice( + &dcap_quote_raw + [authentication_data_offset..(authentication_data_offset + AUTHENTICATION_DATA_SIZE)], + ); + // Ensure that the hash matches the intel signed hash in the QE report. This establishes trust + // into the attestation key. + let hash = ring::digest::digest(&ring::digest::SHA256, &hash_data); + ensure!( + hash.as_ref() == "e.quote_signature_data.qe_report.report_data.d[0..32], + "Hashes must match" + ); + + let qe_report_offset = attestation_key_offset + ATTESTATION_KEY_SIZE; + let qe_report_slice = &dcap_quote_raw[qe_report_offset..(qe_report_offset + REPORT_SIZE)]; + let mut pub_key = [0x04u8; 65]; //Prepend 0x04 to specify uncompressed format + pub_key[1..].copy_from_slice("e.quote_signature_data.ecdsa_attestation_key); + + let peer_public_key = + signature::UnparsedPublicKey::new(&signature::ECDSA_P256_SHA256_FIXED, pub_key); + let isv_report_slice = &dcap_quote_raw[0..(DCAP_QUOTE_HEADER_SIZE + REPORT_SIZE)]; + // Verify that the enclave data matches the signature generated by the trusted attestation key. + // This establishes trust into the data of the enclave we actually want to verify + peer_public_key + .verify(isv_report_slice, "e.quote_signature_data.isv_enclave_report_signature) + .map_err(|_| "Failed to verify report signature")?; + + // Verify that the QE report was signed by Intel. This establishes trust into the QE report. + let asn1_signature = encode_as_der("e.quote_signature_data.qe_report_signature)?; + verify_signature( + &leaf_cert, + qe_report_slice, + &asn1_signature, + webpki::ring::ECDSA_P256_SHA256, + )?; + + ensure!(dcap_quote_clone.is_empty(), "There should be no bytes left over after decoding"); + let report = SgxReport { + mr_enclave: quote.body.mr_enclave, + status: SgxStatus::Ok, + pubkey: xt_signer_array, + timestamp: verification_time, + build_mode: quote.body.sgx_build_mode(), + }; + Ok((fmspc, tcb_info, report)) +} + +// make sure this function doesn't panic! +pub fn verify_ias_report(cert_der: &[u8]) -> Result { + // Before we reach here, the runtime already verified the extrinsic is properly signed by the + // extrinsic sender Hence, we skip: EphemeralKey::try_from(cert)?; + + #[cfg(test)] + println!("verifyRA: start verifying RA cert"); + + let cert = CertDer(cert_der); + let netscape = NetscapeComment::try_from(cert)?; + let sig_cert_der = webpki::types::CertificateDer::from(netscape.sig_cert.as_slice()); + let sig_cert = webpki::EndEntityCert::try_from(&sig_cert_der).map_err(|_| "Bad der")?; + + verify_signature( + &sig_cert, + netscape.attestation_raw, + &netscape.sig, + webpki::ring::RSA_PKCS1_2048_8192_SHA256, + )?; + + // FIXME: now hardcoded. but certificate renewal would have to be done manually anyway... + // chain wasm update or by some sudo call + let valid_until = webpki::types::UnixTime::since_unix_epoch(Duration::from_secs(1573419050)); + verify_server_cert(&sig_cert, valid_until)?; + + parse_report(&netscape) +} + +fn parse_report(netscape: &NetscapeComment) -> Result { + let report_raw: &[u8] = netscape.attestation_raw; + // parse attestation report + let attn_report: Value = match serde_json::from_slice(report_raw) { + Ok(report) => report, + Err(_) => return Err("RA report parsing error"), + }; + + let _ra_timestamp = match &attn_report["timestamp"] { + Value::String(time) => { + let time_fixed = time.clone() + "+0000"; + match DateTime::parse_from_str(&time_fixed, "%Y-%m-%dT%H:%M:%S%.f%z") { + Ok(d) => d.timestamp(), + Err(_) => return Err("RA report timestamp parsing error"), + } + }, + _ => return Err("Failed to fetch timestamp from attestation report"), + }; + + // in milliseconds + let ra_timestamp: u64 = (_ra_timestamp * 1000) + .try_into() + .map_err(|_| "Error converting report.timestamp to u64")?; + + #[cfg(test)] + println!("verifyRA attestation timestamp [unix epoch]: {}", ra_timestamp); + + // get quote status (mandatory field) + let ra_status = match &attn_report["isvEnclaveQuoteStatus"] { + Value::String(quote_status) => match quote_status.as_ref() { + "OK" => SgxStatus::Ok, + "GROUP_OUT_OF_DATE" => SgxStatus::GroupOutOfDate, + "GROUP_REVOKED" => SgxStatus::GroupRevoked, + "CONFIGURATION_NEEDED" => SgxStatus::ConfigurationNeeded, + _ => SgxStatus::Invalid, + }, + _ => return Err("Failed to fetch isvEnclaveQuoteStatus from attestation report"), + }; + + #[cfg(test)] + println!("verifyRA attestation status is: {:?}", ra_status); + // parse quote body + if let Value::String(quote_raw) = &attn_report["isvEnclaveQuoteBody"] { + let quote = match base64::decode(quote_raw) { + Ok(q) => q, + Err(_) => return Err("Quote Decoding Error"), + }; + #[cfg(test)] + println!("Quote read. len={}", quote.len()); + // TODO: lack security check here + let sgx_quote: SgxQuote = match Decode::decode(&mut "e[..]) { + Ok(q) => q, + Err(_) => return Err("could not decode quote"), + }; + + #[cfg(test)] + { + println!("sgx quote version = {}", sgx_quote.version); + println!("sgx quote signature type = {}", sgx_quote.sign_type); + //println!("sgx quote report_data = {:?}", sgx_quote.report_body.report_data.d[..32]); + println!("sgx quote mr_enclave = {:x?}", sgx_quote.report_body.mr_enclave); + println!("sgx quote mr_signer = {:x?}", sgx_quote.report_body.mr_signer); + println!("sgx quote report_data = {:x?}", sgx_quote.report_body.report_data.d.to_vec()); + } + + let mut xt_signer_array = [0u8; 32]; + xt_signer_array.copy_from_slice(&sgx_quote.report_body.report_data.d[..32]); + Ok(SgxReport { + mr_enclave: sgx_quote.report_body.mr_enclave, + status: ra_status, + pubkey: xt_signer_array, + timestamp: ra_timestamp, + build_mode: sgx_quote.report_body.sgx_build_mode(), + }) + } else { + Err("Failed to parse isvEnclaveQuoteBody from attestation report") + } +} + +/// * `signature` - Must be encoded in DER format. +pub fn verify_signature( + entity_cert: &webpki::EndEntityCert, + data: &[u8], + signature: &[u8], + signature_algorithm: &dyn webpki::types::SignatureVerificationAlgorithm, +) -> Result<(), &'static str> { + match entity_cert.verify_signature(signature_algorithm, data, signature) { + Ok(()) => { + #[cfg(test)] + println!("IAS signature is valid"); + Ok(()) + }, + Err(_e) => { + #[cfg(test)] + println!("RSA Signature ERROR: {}", _e); + Err("bad signature") + }, + } +} + +pub fn verify_server_cert( + sig_cert: &webpki::EndEntityCert, + timestamp_valid_until: webpki::types::UnixTime, +) -> Result<(), &'static str> { + let chain: Vec = Vec::new(); + match sig_cert.verify_for_usage( + SUPPORTED_SIG_ALGS, + IAS_SERVER_ROOTS, + &chain, + timestamp_valid_until, + webpki::KeyUsage::server_auth(), + None, + ) { + Ok(()) => { + #[cfg(test)] + println!("CA is valid"); + Ok(()) + }, + Err(_e) => { + #[cfg(test)] + println!("CA ERROR: {}", _e); + Err("CA verification failed") + }, + } +} + +/// See document "Intel® Software Guard Extensions: PCK Certificate and Certificate Revocation List +/// Profile Specification" https://download.01.org/intel-sgx/dcap-1.2/linux/docs/Intel_SGX_PCK_Certificate_CRL_Spec-1.1.pdf +const INTEL_SGX_EXTENSION_OID: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113741.1.13.1"); +const OID_FMSPC: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113741.1.13.1.4"); +const OID_PCESVN: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113741.1.13.1.2.17"); +const OID_CPUSVN: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113741.1.13.1.2.18"); + +pub fn extract_tcb_info(cert: &[u8]) -> Result<(Fmspc, TcbVersionStatus), &'static str> { + let extension_section = get_intel_extension(cert)?; + + let fmspc = get_fmspc(&extension_section)?; + let cpusvn = get_cpusvn(&extension_section)?; + let pcesvn = get_pcesvn(&extension_section)?; + + Ok((fmspc, TcbVersionStatus::new(cpusvn, pcesvn))) +} + +fn get_intel_extension(der_encoded: &[u8]) -> Result, &'static str> { + let cert: Certificate = + der::Decode::from_der(der_encoded).map_err(|_| "Error parsing certificate")?; + let mut extension_iter = cert + .tbs_certificate + .extensions + .as_deref() + .unwrap_or(&[]) + .iter() + .filter(|e| e.extn_id == INTEL_SGX_EXTENSION_OID) + .map(|e| e.extn_value); + + let extension = extension_iter.next(); + ensure!( + extension.is_some() && extension_iter.next().is_none(), + "There should only be one section containing Intel extensions" + ); + // SAFETY: Ensured above that extension.is_some() == true + Ok(extension.unwrap().to_vec()) +} + +fn get_fmspc(der: &[u8]) -> Result { + let bytes_oid = OID_FMSPC.as_bytes(); + let mut offset = der + .windows(bytes_oid.len()) + .position(|window| window == bytes_oid) + .ok_or("Certificate does not contain 'FMSPC_OID'")?; + offset += 12; // length oid (10) + asn1 tag (1) + asn1 length10 (1) + + let fmspc_size = core::mem::size_of::() / core::mem::size_of::(); + let data = der.get(offset..offset + fmspc_size).ok_or("Index out of bounds")?; + data.try_into().map_err(|_| "FMSPC must be 6 bytes long") +} + +fn get_cpusvn(der: &[u8]) -> Result { + let bytes_oid = OID_CPUSVN.as_bytes(); + let mut offset = der + .windows(bytes_oid.len()) + .position(|window| window == bytes_oid) + .ok_or("Certificate does not contain 'CPUSVN_OID'")?; + offset += 13; // length oid (11) + asn1 tag (1) + asn1 length10 (1) + + // CPUSVN is specified to have length 16 + let len = 16; + let data = der.get(offset..offset + len).ok_or("Index out of bounds")?; + data.try_into().map_err(|_| "CPUSVN must be 16 bytes long") +} + +fn get_pcesvn(der: &[u8]) -> Result { + let bytes_oid = OID_PCESVN.as_bytes(); + let mut offset = der + .windows(bytes_oid.len()) + .position(|window| window == bytes_oid) + .ok_or("Certificate does not contain 'PCESVN_OID'")?; + // length oid + asn1 tag (1 byte) + offset += bytes_oid.len() + 1; + // PCESVN can be 1 or 2 bytes + let len = length_from_raw_data(der, &mut offset)?; + offset += 1; // length_from_raw_data does not move the offset when the length is encoded in a single byte + ensure!(len == 1 || len == 2, "PCESVN must be 1 or 2 bytes"); + let data = der.get(offset..offset + len).ok_or("Index out of bounds")?; + if data.len() == 1 { + Ok(u16::from(data[0])) + } else { + // Unwrap is fine here as we check the length above + // DER integers are encoded in big endian + Ok(u16::from_be_bytes(data.try_into().unwrap())) + } +} diff --git a/pallets/teebag/src/sgx_verify/netscape_comment.rs b/pallets/teebag/src/sgx_verify/netscape_comment.rs new file mode 100644 index 0000000000..3d39d22e19 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/netscape_comment.rs @@ -0,0 +1,48 @@ +use super::{utils::length_from_raw_data, CertDer}; +use frame_support::ensure; +use sp_std::{convert::TryFrom, prelude::Vec}; + +pub struct NetscapeComment<'a> { + pub attestation_raw: &'a [u8], + pub sig: Vec, + pub sig_cert: Vec, +} + +pub const NS_CMT_OID: &[u8; 11] = + &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x42, 0x01, 0x0D]; + +impl<'a> TryFrom> for NetscapeComment<'a> { + type Error = &'static str; + + fn try_from(value: CertDer<'a>) -> Result { + // Search for Netscape Comment OID + let cert_der = value.0; + + let mut offset = cert_der + .windows(NS_CMT_OID.len()) + .position(|window| window == NS_CMT_OID) + .ok_or("Certificate does not contain 'ns_cmt_oid'")?; + + offset += 12; // 11 + TAG (0x04) + + #[cfg(test)] + println!("netscape"); + // Obtain Netscape Comment length + let len = length_from_raw_data(cert_der, &mut offset)?; + // Obtain Netscape Comment + offset += 1; + let netscape_raw = cert_der + .get(offset..offset + len) + .ok_or("Index out of bounds")? + .split(|x| *x == 0x7C) // 0x7C is the character '|' + .collect::>(); + ensure!(netscape_raw.len() == 3, "Invalid netscape payload"); + + let sig = base64::decode(netscape_raw[1]).map_err(|_| "Signature Decoding Error")?; + + let sig_cert = base64::decode_config(netscape_raw[2], base64::STANDARD) + .map_err(|_| "Cert Decoding Error")?; + + Ok(NetscapeComment { attestation_raw: netscape_raw[0], sig, sig_cert }) + } +} diff --git a/pallets/teebag/src/sgx_verify/test/dcap/dcap_quote_cert.der b/pallets/teebag/src/sgx_verify/test/dcap/dcap_quote_cert.der new file mode 100644 index 0000000000..accd665a19 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/dcap_quote_cert.der @@ -0,0 +1,25 @@ +MIIEjjCCBDSgAwIBAgIVAMyWqlD3mkxu2FhYuPtrCp2bId06MAoGCCqGSM49BAMC +MHExIzAhBgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQK +DBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV +BAgMAkNBMQswCQYDVQQGEwJVUzAeFw0yMjA1MjMxNTA3MDRaFw0yOTA1MjMxNTA3 +MDRaMHAxIjAgBgNVBAMMGUludGVsIFNHWCBQQ0sgQ2VydGlmaWNhdGUxGjAYBgNV +BAoMEUludGVsIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkG +A1UECAwCQ0ExCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +7pMyqXdHOoVduZAG8j3Wliu0FYWhT+tjjYj9Tdlmr51x8iudHDGTxVU2oeZCnhea +tQuqCBJ0hV7A6gLn5fvXbqOCAqgwggKkMB8GA1UdIwQYMBaAFNDoqtp11/kuSReY +PHsUZdDV8llNMGwGA1UdHwRlMGMwYaBfoF2GW2h0dHBzOi8vYXBpLnRydXN0ZWRz +ZXJ2aWNlcy5pbnRlbC5jb20vc2d4L2NlcnRpZmljYXRpb24vdjMvcGNrY3JsP2Nh +PXByb2Nlc3NvciZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFPW1Uov5Ucy1jHgCeBpx +b6/tkgpoMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIIB1AYJKoZIhvhN +AQ0BBIIBxTCCAcEwHgYKKoZIhvhNAQ0BAQQQs95DBukqMBDQJyrEH4oTxDCCAWQG +CiqGSIb4TQENAQIwggFUMBAGCyqGSIb4TQENAQIBAgERMBAGCyqGSIb4TQENAQIC +AgERMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgEEMBAGCyqGSIb4 +TQENAQIFAgEBMBEGCyqGSIb4TQENAQIGAgIAgDAQBgsqhkiG+E0BDQECBwIBBzAQ +BgsqhkiG+E0BDQECCAIBADAQBgsqhkiG+E0BDQECCQIBADAQBgsqhkiG+E0BDQEC +CgIBADAQBgsqhkiG+E0BDQECCwIBADAQBgsqhkiG+E0BDQECDAIBADAQBgsqhkiG ++E0BDQECDQIBADAQBgsqhkiG+E0BDQECDgIBADAQBgsqhkiG+E0BDQECDwIBADAQ +BgsqhkiG+E0BDQECEAIBADAQBgsqhkiG+E0BDQECEQIBCzAfBgsqhkiG+E0BDQEC +EgQQERECBAGABwAAAAAAAAAAADAQBgoqhkiG+E0BDQEDBAIAADAUBgoqhkiG+E0B +DQEEBAYAkG6hAAAwDwYKKoZIhvhNAQ0BBQoBADAKBggqhkjOPQQDAgNIADBFAiB4 +20uxl1Ncxh6j1CtI1cJHsZxvWg00c1eRWWY2prTWPQIhAIhmmQUOcyRxubRUyGHW +/SbMjV5v6ZVVQn2IIuZUWM64 \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/dcap/pck_crl.der b/pallets/teebag/src/sgx_verify/test/dcap/pck_crl.der new file mode 100644 index 0000000000..5dad4cd40a --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/pck_crl.der @@ -0,0 +1 @@ +308201cd30820173020101300a06082a8648ce3d04030230703122302006035504030c19496e74656c205347582050434b20506c6174666f726d204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3232313032333231353534345a170d3232313132323231353534345a3081a030330214639f139a5040fdcff191e8a4fb1bf086ed603971170d3232313032333231353534345a300c300a0603551d1504030a01013034021500959d533f9249dc1e513544cdc830bf19b7f1f301170d3232313032333231353534345a300c300a0603551d1504030a0101303302140fda43a00b68ea79b7c2deaeac0b498bdfb2af90170d3232313032333231353534345a300c300a0603551d1504030a0101a02f302d300a0603551d140403020101301f0603551d23041830168014956f5dcdbd1be1e94049c9d4f433ce01570bde54300a06082a8648ce3d040302034800304502200809ebf5477e3129f8efa8f3c67b4c204c879919efa78e08c7510a3631c0fe410221008e9cd32a3a1d97242a46cee7589013d220d7bf426607275af6fd3f17f78282a3 \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/dcap/pck_crl_issuer_chain.pem b/pallets/teebag/src/sgx_verify/test/dcap/pck_crl_issuer_chain.pem new file mode 100644 index 0000000000..265ae12bda --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/pck_crl_issuer_chain.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIICmDCCAj6gAwIBAgIVANDoqtp11/kuSReYPHsUZdDV8llNMAoGCCqGSM49BAMC +MGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD +b3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw +CQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHExIzAh +BgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQKDBFJbnRl +bCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNB +MQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL9q+NMp2IOg +tdl1bk/uWZ5+TGQm8aCi8z78fs+fKCQ3d+uDzXnVTAT2ZhDCifyIuJwvN3wNBp9i +HBSSMJMJrBOjgbswgbgwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqww +UgYDVR0fBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNl +cnZpY2VzLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFNDo +qtp11/kuSReYPHsUZdDV8llNMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG +AQH/AgEAMAoGCCqGSM49BAMCA0gAMEUCIQCJgTbtVqOyZ1m3jqiAXM6QYa6r5sWS +4y/G7y8uIJGxdwIgRqPvBSKzzQagBLQq5s5A70pdoiaRJ8z/0uDz4NgV91k= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/dcap/qe_identity.json b/pallets/teebag/src/sgx_verify/test/dcap/qe_identity.json new file mode 100644 index 0000000000..d977ca5fd3 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/qe_identity.json @@ -0,0 +1 @@ +{"enclaveIdentity":{"id":"QE","version":2,"issueDate":"2022-12-04T22:45:33Z","nextUpdate":"2023-01-03T22:45:33Z","tcbEvaluationDataNumber":13,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":6},"tcbDate":"2022-11-09T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]}]},"signature":"47accba321e57c20722a0d3d1db11c9b52661239857dc578ca1bde13976ee288cf39f72111ffe445c7389ef56447c79e30e6b83a8863ed9880de5bde4a8d5c91"} \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/dcap/qe_identity_cert.pem b/pallets/teebag/src/sgx_verify/test/dcap/qe_identity_cert.pem new file mode 100644 index 0000000000..6624ca3837 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/qe_identity_cert.pem @@ -0,0 +1,14 @@ +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/dcap/qe_identity_issuer_chain.pem b/pallets/teebag/src/sgx_verify/test/dcap/qe_identity_issuer_chain.pem new file mode 100644 index 0000000000..396841a8b8 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/qe_identity_issuer_chain.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/dcap/root_ca_crl.der b/pallets/teebag/src/sgx_verify/test/dcap/root_ca_crl.der new file mode 100644 index 0000000000..0c1b57ca43 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/root_ca_crl.der @@ -0,0 +1 @@ +308201213081c8020101300a06082a8648ce3d0403023068311a301806035504030c11496e74656c2053475820526f6f74204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3232303431393038333131385a170d3233303431393038333131385aa02f302d300a0603551d140403020101301f0603551d2304183016801422650cd65a9d3489f383b49552bf501b392706ac300a06082a8648ce3d0403020348003045022100b7805acf592113584c45c8b0e11b2b8a9db462a215bbf8d4fd416539d7f5ab7502207ff56984c5199cf2b23d97d37b104ec0ebb5243674f41346887a6bdfbfdfeb42 \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/dcap/tcb_info.json b/pallets/teebag/src/sgx_verify/test/dcap/tcb_info.json new file mode 100644 index 0000000000..0bf74af582 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/tcb_info.json @@ -0,0 +1 @@ +{"tcbInfo":{"id":"SGX","version":3,"issueDate":"2022-11-17T12:45:32Z","nextUpdate":"2023-04-16T12:45:32Z","fmspc":"00906EA10000","pceId":"0000","tcbType":0,"tcbEvaluationDataNumber":12,"tcbLevels":[{"tcb":{"sgxtcbcomponents":[{"svn":17},{"svn":17},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":7},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":11},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"SWHardeningNeeded","advisoryIDs":["INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":17},{"svn":17},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":7},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":17},{"svn":17},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":11},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"ConfigurationAndSWHardeningNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":17},{"svn":17},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00477","INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":15},{"svn":15},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":7},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-06-10T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":15},{"svn":15},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-06-10T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":14},{"svn":14},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":7},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2019-12-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":14},{"svn":14},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2019-12-11T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":13},{"svn":13},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":3},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":9},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":13},{"svn":13},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":9},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":6},{"svn":6},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":7},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":6},{"svn":6},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":7},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":7},"tcbDate":"2019-01-09T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00233","INTEL-SA-00161","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":6},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":7},"tcbDate":"2019-01-09T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":6},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00203","INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":4},{"svn":4},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":5},"tcbDate":"2018-01-04T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00106","INTEL-SA-00115","INTEL-SA-00135","INTEL-SA-00203","INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":2},{"svn":2},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":4},"tcbDate":"2017-07-26T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00088","INTEL-SA-00106","INTEL-SA-00115","INTEL-SA-00135","INTEL-SA-00203","INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]}]},"signature":"71746f2148ecba04e35cf1ac77a7e6267ce99f6781c1031f724bb5bd94b8c1b6e4c07c01dc151692aa75be80dfba7350bb80c58314a6975189597e28e9bbc75c"} \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/dcap/tcb_info_issuer_chain.pem b/pallets/teebag/src/sgx_verify/test/dcap/tcb_info_issuer_chain.pem new file mode 100644 index 0000000000..396841a8b8 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/dcap/tcb_info_issuer_chain.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST4.bin b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST4.bin new file mode 100644 index 0000000000..1d3eba0f34 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST4.bin @@ -0,0 +1,2 @@ +˹E݁}R&ln6 + \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST5.bin b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST5.bin new file mode 100644 index 0000000000..1d3eba0f34 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST5.bin @@ -0,0 +1,2 @@ +˹E݁}R&ln6 + \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST6.bin b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST6.bin new file mode 100644 index 0000000000..4ccf832d61 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST6.bin @@ -0,0 +1 @@ + GҬʮ;X4\Э \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST7.bin b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST7.bin new file mode 100644 index 0000000000..d43d92f82b --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST7.bin @@ -0,0 +1 @@ +r\٪=(Ud.ږtΤBW \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST8-PRODUCTION.bin b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST8-PRODUCTION.bin new file mode 100644 index 0000000000..536943ebf3 Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/enclave-signing-pubkey-TEST8-PRODUCTION.bin differ diff --git a/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST4.der b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST4.der new file mode 100644 index 0000000000..2e775236d6 Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST4.der differ diff --git a/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST5.der b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST5.der new file mode 100644 index 0000000000..bf5fe0cf0d Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST5.der differ diff --git a/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST6.der b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST6.der new file mode 100644 index 0000000000..889e5e0a85 Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST6.der differ diff --git a/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST7.der b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST7.der new file mode 100644 index 0000000000..8e6d2f7418 Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST7.der differ diff --git a/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST8_PRODUCTION.der b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST8_PRODUCTION.der new file mode 100644 index 0000000000..8a8144f445 Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/ra_dump_cert_TEST8_PRODUCTION.der differ diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER1_MRENCLAVE1.der b/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER1_MRENCLAVE1.der new file mode 100644 index 0000000000..fefdd47ed8 Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER1_MRENCLAVE1.der differ diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER2_MRENCLAVE2.der b/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER2_MRENCLAVE2.der new file mode 100644 index 0000000000..e05c35e561 Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER2_MRENCLAVE2.der differ diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER3_MRENCLAVE2.der b/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER3_MRENCLAVE2.der new file mode 100644 index 0000000000..5ff453b3cc Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/test_ra_cert_MRSIGNER3_MRENCLAVE2.der differ diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER1_MRENCLAVE1.bin b/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER1_MRENCLAVE1.bin new file mode 100644 index 0000000000..d7149d37d5 Binary files /dev/null and b/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER1_MRENCLAVE1.bin differ diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER2_MRENCLAVE2.bin b/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER2_MRENCLAVE2.bin new file mode 100644 index 0000000000..5009698a26 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER2_MRENCLAVE2.bin @@ -0,0 +1 @@ +?_ΰoc@Re tj@V=Mk gQs]4AXc \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER3_MRENCLAVE2.bin b/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER3_MRENCLAVE2.bin new file mode 100644 index 0000000000..df8e511e12 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/test_ra_signer_attn_MRSIGNER3_MRENCLAVE2.bin @@ -0,0 +1,2 @@ +(rORpDso.QV>ojk s( IJp4O}eVp +z~Q7 \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER1_MRENCLAVE1.bin b/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER1_MRENCLAVE1.bin new file mode 100644 index 0000000000..65c2e61c25 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER1_MRENCLAVE1.bin @@ -0,0 +1 @@ +"ZTKd pIļ@C_^< \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER2_MRENCLAVE2.bin b/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER2_MRENCLAVE2.bin new file mode 100644 index 0000000000..8cc7d123bf --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER2_MRENCLAVE2.bin @@ -0,0 +1 @@ ++%Q!ڜeV{3 A/ 4u3*;8 \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER3_MRENCLAVE2.bin b/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER3_MRENCLAVE2.bin new file mode 100644 index 0000000000..19c4874d4b --- /dev/null +++ b/pallets/teebag/src/sgx_verify/test/test_ra_signer_pubkey_MRSIGNER3_MRENCLAVE2.bin @@ -0,0 +1 @@ +7^䠺,(j|tv 댓ҡ \ No newline at end of file diff --git a/pallets/teebag/src/sgx_verify/tests.rs b/pallets/teebag/src/sgx_verify/tests.rs new file mode 100644 index 0000000000..e8a9e4a560 --- /dev/null +++ b/pallets/teebag/src/sgx_verify/tests.rs @@ -0,0 +1,298 @@ +#![allow(dead_code, unused_imports, const_item_mutation)] + +use super::{ + collateral::{EnclaveIdentitySigned, TcbInfoSigned}, + *, +}; +use codec::Decode; +use frame_support::assert_err; +use hex_literal::hex; + +// reproduce with "litentry-worker dump_ra" +const TEST1_CERT: &[u8] = include_bytes!("./test/test_ra_cert_MRSIGNER1_MRENCLAVE1.der"); +const TEST2_CERT: &[u8] = include_bytes!("./test/test_ra_cert_MRSIGNER2_MRENCLAVE2.der"); +const TEST3_CERT: &[u8] = include_bytes!("./test/test_ra_cert_MRSIGNER3_MRENCLAVE2.der"); +const TEST4_CERT: &[u8] = include_bytes!("./test/ra_dump_cert_TEST4.der"); +const TEST5_CERT: &[u8] = include_bytes!("./test/ra_dump_cert_TEST5.der"); +const TEST6_CERT: &[u8] = include_bytes!("./test/ra_dump_cert_TEST6.der"); +const TEST7_CERT: &[u8] = include_bytes!("./test/ra_dump_cert_TEST7.der"); +const TEST8_CERT: &[u8] = include_bytes!("./test/ra_dump_cert_TEST8_PRODUCTION.der"); + +const TEST1_SIGNER_ATTN: &[u8] = + include_bytes!("./test/test_ra_signer_attn_MRSIGNER1_MRENCLAVE1.bin"); +const TEST2_SIGNER_ATTN: &[u8] = + include_bytes!("./test/test_ra_signer_attn_MRSIGNER2_MRENCLAVE2.bin"); +const TEST3_SIGNER_ATTN: &[u8] = + include_bytes!("./test/test_ra_signer_attn_MRSIGNER3_MRENCLAVE2.bin"); + +// reproduce with "litentry-worker signing-key" +const TEST1_SIGNER_PUB: &[u8] = + include_bytes!("./test/test_ra_signer_pubkey_MRSIGNER1_MRENCLAVE1.bin"); +const TEST2_SIGNER_PUB: &[u8] = + include_bytes!("./test/test_ra_signer_pubkey_MRSIGNER2_MRENCLAVE2.bin"); +const TEST3_SIGNER_PUB: &[u8] = + include_bytes!("./test/test_ra_signer_pubkey_MRSIGNER3_MRENCLAVE2.bin"); +const TEST4_SIGNER_PUB: &[u8] = include_bytes!("./test/enclave-signing-pubkey-TEST4.bin"); +// equal to TEST4! +const TEST5_SIGNER_PUB: &[u8] = include_bytes!("./test/enclave-signing-pubkey-TEST5.bin"); +const TEST6_SIGNER_PUB: &[u8] = include_bytes!("./test/enclave-signing-pubkey-TEST6.bin"); +const TEST7_SIGNER_PUB: &[u8] = include_bytes!("./test/enclave-signing-pubkey-TEST7.bin"); +const QE_IDENTITY_CERT: &str = include_str!("./test/dcap/qe_identity_cert.pem"); +const DCAP_QUOTE_CERT: &str = include_str!("./test/dcap/dcap_quote_cert.der"); +const PCK_CRL: &[u8] = include_bytes!("./test/dcap/pck_crl.der"); + +// reproduce with "make mrenclave" in worker repo root +const TEST1_MRENCLAVE: &[u8] = &[ + 62, 252, 187, 232, 60, 135, 108, 204, 87, 78, 35, 169, 241, 237, 106, 217, 251, 241, 99, 189, + 138, 157, 86, 136, 77, 91, 93, 23, 192, 104, 140, 167, +]; +const TEST2_MRENCLAVE: &[u8] = &[ + 4, 190, 230, 132, 211, 129, 59, 237, 101, 78, 55, 174, 144, 177, 91, 134, 1, 240, 27, 174, 81, + 139, 8, 22, 32, 241, 228, 103, 189, 43, 44, 102, +]; +const TEST3_MRENCLAVE: &[u8] = &[ + 4, 190, 230, 132, 211, 129, 59, 237, 101, 78, 55, 174, 144, 177, 91, 134, 1, 240, 27, 174, 81, + 139, 8, 22, 32, 241, 228, 103, 189, 43, 44, 102, +]; + +// MRSIGNER is 83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e +const TEST4_MRENCLAVE: MrEnclave = + hex!("7a3454ec8f42e265cb5be7dfd111e1d95ac6076ed82a0948b2e2a45cf17b62a0"); +const TEST5_MRENCLAVE: MrEnclave = + hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d1"); +// equal to TEST5! +const TEST6_MRENCLAVE: MrEnclave = + hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d1"); +// equal to TEST6! +const TEST7_MRENCLAVE: MrEnclave = + hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d1"); + +// production mode +// MRSIGNER is 117f95f65f06afb5764b572156b8b525c6230db7d6b1c94e8ebdb7fba068f4e8 +const TEST8_MRENCLAVE: MrEnclave = + hex!("bcf66abfc6b3ef259e9ecfe4cf8df667a7f5a546525dee16822741b38f6e6050"); + +// unix epoch. must be later than this +const TEST1_TIMESTAMP: i64 = 1580587262i64; +/// Collateral test data mus be valid at this time (2022-10-11 14:01:02) for the tests to work +const COLLATERAL_VERIFICATION_TIMESTAMP: u64 = 1665489662000; + +//const CERT: &[u8] = +// b"0\x82\x0c\x8c0\x82\x0c2\xa0\x03\x02\x01\x02\x02\x01\x010\n\x06\x08*\x86H\xce=\x04\x03\x020\ +// x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0\x1e\x17\r190617124609Z\x17\r190915124609Z0\x121\ +// x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\ +// x03\x01\x07\x03B\0\x04RT\x16\x16 +// \xef_\xd8\xe7\xc3\xb7\x03\x1d\xd6:\x1fF\xe3\xf2b!\xa9/\x8b\xd4\x82\x8f\xd1\xff[\x9c\x97\xbc\xf27\ +// xb8,L\x8a\x01\xb0r;;\xa9\x83\xdc\x86\x9f\x1d%y\xf4;I\xe4Y\xc80'$K[\xd6\xa3\x82\x0bw0\x82\x0bs0\ +// x82\x0bo\x06\t`\x86H\x01\x86\xf8B\x01\r\x04\x82\x0b`{\"id\":\" +// 117077750682263877593646412006783680848\",\"timestamp\":\"2019-06-17T12:46:04.002066\",\"version\ +// ":3,\"isvEnclaveQuoteStatus\":\"GROUP_OUT_OF_DATE\",\"platformInfoBlob\":\" +// 1502006504000900000909020401800000000000000000000008000009000000020000000000000B401A355B313FC939B4F48A54349C914A32A3AE2C4871BFABF22E960C55635869FC66293A3D9B2D58ED96CA620B65D669A444C80291314EF691E896F664317CF80C\ +// ",\"isvEnclaveQuoteBody\":\"AgAAAEALAAAIAAcAAAAAAOE6wgoHKsZsnVWSrsWX9kky0kWt9K4xcan0fQ996Ct+CAj// +// wGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAFJJYIbPVot9NzRCjW2z9+k+9K8BsHQKzVMEHOR14hNbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSVBYWIO9f2OfDtwMd1jofRuPyYiGpL4vUgo/ +// R/1ucl7zyN7gsTIoBsHI7O6mD3IafHSV59DtJ5FnIMCckS1vW\"}|EbPFH/ThUaS/ +// dMZoDKC5EgmdUXUORFtQzF49Umi1P55oeESreJaUvmA0sg/ +// ATSTn5t2e+e6ZoBQIUbLHjcWLMLzK4pJJUeHhok7EfVgoQ378i+eGR9v7ICNDGX7a1rroOe0s1OKxwo/ +// 0hid2KWvtAUBvf1BDkqlHy025IOiXWhXFLkb/ +// qQwUZDWzrV4dooMfX5hfqJPi1q9s18SsdLPmhrGBheh9keazeCR9hiLhRO9TbnVgR9zJk43SPXW+pHkbNigW+2STpVAi5ugWaSwBOdK11ZjaEU1paVIpxQnlW1D6dj1Zc3LibMH+ly9ZGrbYtuJks4eRnjPhroPXxlJWpQ==|MIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIwMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1NhbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwkSW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/ +// Es/BA+tbeCTUR106AL1ENcWA4FX3K+E9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtIdcv/ +// uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuvLUK7eyRPfJW/ +// ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV+W9tOhAImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt++qO/ +// 6+KAXJuKwZqjRlEtSEz8gZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGhMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN+s1fDuHAVE8MA4GA1UdDwEB/ +// wQEAwIGwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVkc2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJlcG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4rRq+ZKE+7k50/ +// OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/ +// LpFa9lpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYvWLrtXXfFBSSPD4Afn7+3/ +// XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUdZseZCcaZZZn65tdqee8UXZlDvx0+NdO0LR+5pFy+juM0wWbu59MvzcmTXbjsi7HY6zd53Yq5K244fwFHRQ8eOB0IWB+4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW72uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN+KwPbpA39+xOsStjhP9N1Y1a2tQAVo+yVgLgV2Hws73Fc0o3wC78qPEA+v2aRs/ +// Be3ZFDgDyghc/1fgU+7C+P6kbqd4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA==0\n\x06\x08*\x86H\ +// xce=\x04\x03\x02\x03H\00E\x02!\0\xae6\x06\t@Sy\x8f\x8ec\x9d\xdci^Ex*\x92}\xdcG\x15A\x97\xd7\xd7\ +// xd1\xccx\xe0\x1e\x08\x02 +// \x15Q\xa0BT\xde'~\xec\xbd\x027\xd3\xd8\x83\xf7\xe6Z\xc5H\xb4D\xf7\xe2\r\xa7\xe4^f\x10\x85p"; +const CERT_FAKE_QUOTE_STATUS: &[u8] = b"0\x82\x0c\x8c0\x82\x0c2\xa0\x03\x02\x01\x02\x02\x01\x010\n\x06\x08*\x86H\xce=\x04\x03\x020\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0\x1e\x17\r190617124609Z\x17\r190915124609Z0\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\0\x04RT\x16\x16 \xef_\xd8\xe7\xc3\xb7\x03\x1d\xd6:\x1fF\xe3\xf2b!\xa9/\x8b\xd4\x82\x8f\xd1\xff[\x9c\x97\xbc\xf27\xb8,L\x8a\x01\xb0r;;\xa9\x83\xdc\x86\x9f\x1d%y\xf4;I\xe4Y\xc80'$K[\xd6\xa3\x82\x0bw0\x82\x0bs0\x82\x0bo\x06\t`\x86H\x01\x86\xf8B\x01\r\x04\x82\x0b`{\"id\":\"117077750682263877593646412006783680848\",\"timestamp\":\"2019-06-17T12:46:04.002066\",\"version\":3,\"isvEnclaveQuoteStatus\":\"OK\",\"platformInfoBlob\":\"1602006504000900000909020401800000000000000000000008000009000000020000000000000B401A355B313FC939B4F48A54349C914A32A3AE2C4871BFABF22E960C55635869FC66293A3D9B2D58ED96CA620B65D669A444C80291314EF691E896F664317CF80C\",\"isvEnclaveQuoteBody\":\"AgAAAEALAAAIAAcAAAAAAOE6wgoHKsZsnVWSrsWX9kky0kWt9K4xcan0fQ996Ct+CAj//wGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAFJJYIbPVot9NzRCjW2z9+k+9K8BsHQKzVMEHOR14hNbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSVBYWIO9f2OfDtwMd1jofRuPyYiGpL4vUgo/R/1ucl7zyN7gsTIoBsHI7O6mD3IafHSV59DtJ5FnIMCckS1vW\"}|EbPFH/ThUaS/dMZoDKC5EgmdUXUORFtQzF49Umi1P55oeESreJaUvmA0sg/ATSTn5t2e+e6ZoBQIUbLHjcWLMLzK4pJJUeHhok7EfVgoQ378i+eGR9v7ICNDGX7a1rroOe0s1OKxwo/0hid2KWvtAUBvf1BDkqlHy025IOiXWhXFLkb/qQwUZDWzrV4dooMfX5hfqJPi1q9s18SsdLPmhrGBheh9keazeCR9hiLhRO9TbnVgR9zJk43SPXW+pHkbNigW+2STpVAi5ugWaSwBOdK11ZjaEU1paVIpxQnlW1D6dj1Zc3LibMH+ly9ZGrbYtuJks4eRnjPhroPXxlJWpQ==|MIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIwMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1NhbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwkSW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA+tbeCTUR106AL1ENcWA4FX3K+E9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtIdcv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuvLUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV+W9tOhAImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt++qO/6+KAXJuKwZqjRlEtSEz8gZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGhMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN+s1fDuHAVE8MA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVkc2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJlcG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4rRq+ZKE+7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9lpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYvWLrtXXfFBSSPD4Afn7+3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUdZseZCcaZZZn65tdqee8UXZlDvx0+NdO0LR+5pFy+juM0wWbu59MvzcmTXbjsi7HY6zd53Yq5K244fwFHRQ8eOB0IWB+4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW72uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN+KwPbpA39+xOsStjhP9N1Y1a2tQAVo+yVgLgV2Hws73Fc0o3wC78qPEA+v2aRs/Be3ZFDgDyghc/1fgU+7C+P6kbqd4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA==0\n\x06\x08*\x86H\xce=\x04\x03\x02\x03H\x000E\x02!\0\xae6\x06\t@Sy\x8f\x8ec\x9d\xdci^Ex*\x92}\xdcG\x15A\x97\xd7\xd7\xd1\xccx\xe0\x1e\x08\x02 \x15Q\xa0BT\xde'~\xec\xbd\x027\xd3\xd8\x83\xf7\xe6Z\xc5H\xb4D\xf7\xe2\r\xa7\xe4^f\x10\x85p"; +const CERT_WRONG_PLATFORM_BLOB: &[u8] = b"0\x82\x0c\x8c0\x82\x0c2\xa0\x03\x02\x01\x02\x02\x01\x010\n\x06\x08*\x86H\xce=\x04\x03\x020\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0\x1e\x17\r190617124609Z\x17\r190915124609Z0\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\0\x04RT\x16\x16 \xef_\xd8\xe7\xc3\xb7\x03\x1d\xd6:\x1fF\xe3\xf2b!\xa9/\x8b\xd4\x82\x8f\xd1\xff[\x9c\x97\xbc\xf27\xb8,L\x8a\x01\xb0r;;\xa9\x83\xdc\x86\x9f\x1d%y\xf4;I\xe4Y\xc80'$K[\xd6\xa3\x82\x0bw0\x82\x0bs0\x82\x0bo\x06\t`\x86H\x01\x86\xf8B\x01\r\x04\x82\x0b`{\"id\":\"117077750682263877593646412006783680848\",\"timestamp\":\"2019-06-17T12:46:04.002066\",\"version\":3,\"isvEnclaveQuoteStatus\":\"GROUP_OUT_OF_DATE\",\"platformInfoBlob\":\"1602006504000900000909020401800000000000000000000008000009000000020000000000000B401A355B313FC939B4F48A54349C914A32A3AE2C4871BFABF22E960C55635869FC66293A3D9B2D58ED96CA620B65D669A444C80291314EF691E896F664317CF80C\",\"isvEnclaveQuoteBody\":\"AgAAAEALAAAIAAcAAAAAAOE6wgoHKsZsnVWSrsWX9kky0kWt9K4xcan0fQ996Ct+CAj//wGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAFJJYIbPVot9NzRCjW2z9+k+9K8BsHQKzVMEHOR14hNbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSVBYWIO9f2OfDtwMd1jofRuPyYiGpL4vUgo/R/1ucl7zyN7gsTIoBsHI7O6mD3IafHSV59DtJ5FnIMCckS1vW\"}|EbPFH/ThUaS/dMZoDKC5EgmdUXUORFtQzF49Umi1P55oeESreJaUvmA0sg/ATSTn5t2e+e6ZoBQIUbLHjcWLMLzK4pJJUeHhok7EfVgoQ378i+eGR9v7ICNDGX7a1rroOe0s1OKxwo/0hid2KWvtAUBvf1BDkqlHy025IOiXWhXFLkb/qQwUZDWzrV4dooMfX5hfqJPi1q9s18SsdLPmhrGBheh9keazeCR9hiLhRO9TbnVgR9zJk43SPXW+pHkbNigW+2STpVAi5ugWaSwBOdK11ZjaEU1paVIpxQnlW1D6dj1Zc3LibMH+ly9ZGrbYtuJks4eRnjPhroPXxlJWpQ==|MIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIwMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1NhbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwkSW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA+tbeCTUR106AL1ENcWA4FX3K+E9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtIdcv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuvLUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV+W9tOhAImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt++qO/6+KAXJuKwZqjRlEtSEz8gZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGhMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN+s1fDuHAVE8MA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVkc2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJlcG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4rRq+ZKE+7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9lpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYvWLrtXXfFBSSPD4Afn7+3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUdZseZCcaZZZn65tdqee8UXZlDvx0+NdO0LR+5pFy+juM0wWbu59MvzcmTXbjsi7HY6zd53Yq5K244fwFHRQ8eOB0IWB+4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW72uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN+KwPbpA39+xOsStjhP9N1Y1a2tQAVo+yVgLgV2Hws73Fc0o3wC78qPEA+v2aRs/Be3ZFDgDyghc/1fgU+7C+P6kbqd4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA==0\n\x06\x08*\x86H\xce=\x04\x03\x02\x03H\x000E\x02!\0\xae6\x06\t@Sy\x8f\x8ec\x9d\xdci^Ex*\x92}\xdcG\x15A\x97\xd7\xd7\xd1\xccx\xe0\x1e\x08\x02 \x15Q\xa0BT\xde'~\xec\xbd\x027\xd3\xd8\x83\xf7\xe6Z\xc5H\xb4D\xf7\xe2\r\xa7\xe4^f\x10\x85p"; +const CERT_WRONG_SIG: &[u8] = b"0\x82\x0c\x8c0\x82\x0c2\xa0\x03\x02\x01\x02\x02\x01\x010\n\x06\x08*\x86H\xce=\x04\x03\x020\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0\x1e\x17\r190617124609Z\x17\r190915124609Z0\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\0\x04RT\x16\x16 \xef_\xd8\xe7\xc3\xb7\x03\x1d\xd6:\x1fF\xe3\xf2b!\xa9/\x8b\xd4\x82\x8f\xd1\xff[\x9c\x97\xbc\xf27\xb8,L\x8a\x01\xb0r;;\xa9\x83\xdc\x86\x9f\x1d%y\xf4;I\xe4Y\xc80'$K[\xd6\xa3\x82\x0bw0\x82\x0bs0\x82\x0bo\x06\t`\x86H\x01\x86\xf8B\x01\r\x04\x82\x0b`{\"id\":\"117077750682263877593646412006783680848\",\"timestamp\":\"2019-06-17T12:46:04.002066\",\"version\":3,\"isvEnclaveQuoteStatus\":\"GROUP_OUT_OF_DATE\",\"platformInfoBlob\":\"1602006504000900000909020401800000000000000000000008000009000000020000000000000B401A355B313FC939B4F48A54349C914A32A3AE2C4871BFABF22E960C55635869FC66293A3D9B2D58ED96CA620B65D669A444C80291314EF691E896F664317CF80C\",\"isvEnclaveQuoteBody\":\"AgAAAEALAAAIAAcAAAAAAOE6wgoHKsZsnVWSrsWX9kky0kWt9K4xcan0fQ996Ct+CAj//wGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAFJJYIbPVot9NzRCjW2z9+k+9K8BsHQKzVMEHOR14hNbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSVBYWIO9f2OfDtwMd1jofRuPyYiGpL4vUgo/R/1ucl7zyN7gsTIoBsHI7O6mD3IafHSV59DtJ5FnIMCckS1vW\"}|EbPFH/ThUaS/dMZoDKC5EgmdUXUORFtQzF49Umi1P55oeESreJaUvmA0sg/ATSTn5t2e+e6ZoBQIUbLHjcWLMLzK4pJJUeHhok7EfVgoQ378i+eGR9v7ICNDGX7a1rroOe0s1OKxwo/0hid2KWvtAUBvf1BDkqlHy025IOiXWhXFLkb/qQwUZDWzrV4dooMfX5hfqJPi1q9s18SsdLPmhrGBheh9keazeCR9hiLhRO9TbnVgR9zJk43SPXW+pHkbNigW+2STpVAi5ugWaSwBOdK11ZjaEU1paVIpxQnlW1D6dj1Zc3LibMH+ly9ZGrbYtuJks4eRnjPhroPXxlJWpQ==|MIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIwMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1NhbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwkSW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA+tbeCTUR106AL1ENcWA4FX3K+E9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtIdcv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuvLUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV+W9tOhAImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt++qO/6+KAXJuKwZqjRlEtSEz8gZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGhMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN+s1fDuHAVE8MA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVkc2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJlcG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4rRq+ZKE+7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9lpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEaRHz91kpG6Uvyn2tLmnIdJbPE4vYvWLrtXXfFBSSPD4Afn7+3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUdZseZCcaZZZn65tdqee8UXZlDvx0+NdO0LR+5pFy+juM0wWbu59MvzcmTXbjsi7HY6zd53Yq5K244fwFHRQ8eOB0IWB+4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW72uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN+KwPbpA39+xOsStjhP9N1Y1a2tQAVo+yVgLgV2Hws73Fc0o3wC78qPEA+v2aRs/Be3ZFDgDyghc/1fgU+7C+P6kbqd4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA==0\n\x06\x08*\x86H\xce=\x04\x03\x02\x03H\x000E\x02!\0\xae6\x06\t@Sy\x8f\x8ec\x9d\xdci^Ex*\x92}\xdcG\x15A\x97\xd7\xd7\xd1\xccx\xe0\x1e\x08\x02 \x15Q\xa0BT\xde'~\xec\xbd\x027\xd3\xd8\x83\xf7\xe6Z\xc5H\xb4D\xf7\xe2\r\xa7\xe4^f\x10\x85p"; +const CERT_TOO_SHORT1: &[u8] = b"0\x82\x0c\x8c0\x82\x0c2\xa0\x03\x02\x01\x02\x02\x01\x010\n\x06\x08*\x86H\xce=\x04\x03\x020\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0\x1e\x17\r190617124609Z\x17\r190915124609Z0\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\0\x04RT\x16\x16 \xef_\xd8\xe7\xc3\xb7\x03\x1d\xd6:\x1fF\xe3\xf2b!\xa9/\x8b\xd4\x82\x8f\xd1\xff[\x9c\x97\xbc\xf27\xb8,L\x8a\x01\xb0r;;\xa9\x83\xdc\x86\x9f\x1d%y\xf4;I\xe4Y\xc80'$K[\xd6\xa3\x82\x0bw0\x82\x0bs0\x82\x0bo\x06\t`\x86H\x01\x86\xf8B\x01\r\x04\x82\x0b`{\"id\":\"117077750682263877593646412006783680848\",\"timestamp\":\"2019-06-17T12:46:04.002066\",\"version\":3,\"isvEnclaveQuoteStatus\":\"GROUP_OUT_OF_DATE\",\"platformInfoBlob\":\"1602006504000900000909020401800000000000000000000008000009000000020000000000000B401A355B313FC939B4F48A54349C91\x03\x02\x03H\x000E\x02!\0\xae6\x06\t@Sy\x8f\x8ec\x9d\xdci^Ex*\x92}\xdcG\x15A\x97\xd7\xd7\xd1\xccx\xe0\x1e\x08\x02 \x15Q\xa0BT\xde'~\xec\xbd\x027\xd3\xd8\x83\xf7\xe6Z\xc5H\xb4D\xf7\xe2\r\xa7\xe4^f\x10\x85p"; +const CERT_TOO_SHORT2: &[u8] = b"0\x82\x0c\x8c0"; + +#[test] +fn verify_ias_report_should_work() { + let _signer_attn: [u32; 16] = Decode::decode(&mut TEST1_SIGNER_ATTN).unwrap(); + let report = verify_ias_report(TEST4_CERT); + let report = report.unwrap(); + assert_eq!(report.mr_enclave, TEST4_MRENCLAVE); + assert!(report.timestamp >= TEST1_TIMESTAMP.try_into().unwrap()); + assert_eq!(report.pubkey, TEST4_SIGNER_PUB); + //assert_eq!(report.status, SgxStatus::GroupOutOfDate); + assert_eq!(report.status, SgxStatus::ConfigurationNeeded); + assert_eq!(report.build_mode, SgxBuildMode::Debug); +} + +#[test] +fn verify_zero_length_cert_returns_err() { + // CERT empty, argument 2 and 3 are wrong too! + let _signer_attn: [u32; 16] = Decode::decode(&mut TEST1_SIGNER_ATTN).unwrap(); + assert!(verify_ias_report(&Vec::new()[..]).is_err()) +} + +#[test] +fn verify_wrong_cert_is_err() { + // CERT wrong, argument 2 and 3 are wrong too! + let _signer_attn: [u32; 16] = Decode::decode(&mut TEST1_SIGNER_ATTN).unwrap(); + assert!(verify_ias_report(CERT_WRONG_PLATFORM_BLOB).is_err()) +} + +#[test] +fn verify_wrong_fake_enclave_quote_is_err() { + // quote wrong, argument 2 and 3 are wrong too! + let _signer_attn: [u32; 16] = Decode::decode(&mut TEST1_SIGNER_ATTN).unwrap(); + assert!(verify_ias_report(CERT_FAKE_QUOTE_STATUS).is_err()) +} + +#[test] +fn verify_wrong_sig_is_err() { + // sig wrong, argument 2 and 3 are wrong too! + let _signer_attn: [u32; 16] = Decode::decode(&mut TEST1_SIGNER_ATTN).unwrap(); + assert!(verify_ias_report(CERT_WRONG_SIG).is_err()) +} + +#[test] +fn verify_short_cert_is_err() { + let _signer_attn: [u32; 16] = Decode::decode(&mut TEST1_SIGNER_ATTN).unwrap(); + assert!(verify_ias_report(CERT_TOO_SHORT1).is_err()); + assert!(verify_ias_report(CERT_TOO_SHORT2).is_err()); +} + +#[test] +fn fix_incorrect_handling_of_iterator() { + // In `verify_ias_report` we called `iter.next()` with unwrap three times, which could fail + // for certain invalid reports as the one in this test. This test verifies that the issue + // has been fixed. + // + // For context, see: https://github.com/integritee-network/pallet-teerex/issues/35 + + let report: [u8; 56] = [ + 224, 224, 224, 224, 224, 224, 224, 224, 235, 2, 0, 1, 5, 40, 0, 8, 255, 6, 8, 42, 134, 72, + 206, 61, 3, 1, 7, 0, 2, 183, 64, 48, 48, 0, 1, 10, 23, 3, 6, 9, 96, 134, 72, 1, 134, 248, + 66, 1, 13, 0, 0, 0, 13, 1, 14, 177, + ]; + + assert_err!(verify_ias_report(&report), "Invalid netscape payload"); +} + +#[test] +fn verify_sgx_build_mode_works() { + //verify report from enclave in debug mode + let report = verify_ias_report(TEST4_CERT); + let report = report.unwrap(); + assert_eq!(report.build_mode, SgxBuildMode::Debug); + //verify report from enclave in production mode + let report = verify_ias_report(TEST8_CERT); + let report = report.unwrap(); + assert_eq!(report.build_mode, SgxBuildMode::Production); +} + +#[test] +fn decode_qe_authentication_data() { + assert!(QeAuthenticationData::decode(&mut &[0u8][..]).is_err()); + assert!(QeAuthenticationData::decode(&mut &[1u8][..]).is_err()); + assert_eq!(0, QeAuthenticationData::decode(&mut &[0u8, 0][..]).unwrap().size); + let d = QeAuthenticationData::decode(&mut &[1u8, 0, 5][..]).unwrap(); + assert_eq!(1, d.size); + assert_eq!(5, d.certification_data[0]); +} + +#[test] +fn decode_qe_certification_data() { + assert!(QeCertificationData::decode(&mut &[0u8][..]).is_err()); + assert!(QeCertificationData::decode(&mut &[1u8, 0, 0, 0, 0][..]).is_err()); + assert_eq!(0, QeCertificationData::decode(&mut &[0u8, 0, 0, 0, 0, 0][..]).unwrap().size); + let d = QeCertificationData::decode(&mut &[0u8, 0, 1, 0, 0, 0, 5][..]).unwrap(); + assert_eq!(1, d.size); + assert_eq!(5, d.certification_data[0]); + assert!(QeCertificationData::decode(&mut &[0u8, 0, 2, 0, 0, 0, 5][..]).is_err()); +} + +#[test] +fn deserialize_qe_identity_works() { + let certs = extract_certs(include_bytes!("./test/dcap/qe_identity_issuer_chain.pem")); + let intermediate_slices: Vec = + certs[1..].iter().map(|c| c.as_slice().into()).collect(); + let leaf_cert_der = webpki::types::CertificateDer::from(certs[0].as_slice()); + let leaf_cert = webpki::EndEntityCert::try_from(&leaf_cert_der).unwrap(); + verify_certificate_chain(&leaf_cert, &intermediate_slices, COLLATERAL_VERIFICATION_TIMESTAMP) + .unwrap(); + let json: EnclaveIdentitySigned = + serde_json::from_slice(include_bytes!("./test/dcap/qe_identity.json")).unwrap(); + let json_data = serde_json::to_vec(&json.enclave_identity).unwrap(); + let signature = hex::decode(json.signature).unwrap(); + + let e = deserialize_enclave_identity(&json_data, &signature, &leaf_cert).unwrap(); + assert_eq!(1, e.isvprodid); + assert_eq!(5, e.tcb_levels.len()); +} + +#[test] +fn deserialize_tcb_info_works() { + let certs = extract_certs(include_bytes!("./test/dcap/tcb_info_issuer_chain.pem")); + let intermediate_slices: Vec = + certs[1..].iter().map(|c| c.as_slice().into()).collect(); + let leaf_cert_der = webpki::types::CertificateDer::from(certs[0].as_slice()); + let leaf_cert = webpki::EndEntityCert::try_from(&leaf_cert_der).unwrap(); + verify_certificate_chain(&leaf_cert, &intermediate_slices, COLLATERAL_VERIFICATION_TIMESTAMP) + .unwrap(); + let json: TcbInfoSigned = + serde_json::from_slice(include_bytes!("./test/dcap/tcb_info.json")).unwrap(); + + let json_data = serde_json::to_vec(&json.tcb_info).unwrap(); + let signature = hex::decode(json.signature).unwrap(); + + let _e = deserialize_tcb_info(&json_data, &signature, &leaf_cert).unwrap(); + assert_eq!(hex!("00906EA10000"), json.tcb_info.fmspc); +} + +#[test] +fn verify_tcb_info_signature() { + let cert = QE_IDENTITY_CERT.replace('\n', ""); + let leaf_cert = base64::decode(cert).unwrap(); + let leaf_cert_der = webpki::types::CertificateDer::from(leaf_cert.as_slice()); + let leaf_cert = webpki::EndEntityCert::try_from(&leaf_cert_der).unwrap(); + let data = br#"{"version":2,"issueDate":"2022-10-18T21:45:02Z","nextUpdate":"2022-11-17T21:45:02Z","fmspc":"00906EA10000","pceId":"0000","tcbType":0,"tcbEvaluationDataNumber":12,"tcbLevels":[{"tcb":{"sgxtcbcomp01svn":17,"sgxtcbcomp02svn":17,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":7,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":11},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"SWHardeningNeeded"},{"tcb":{"sgxtcbcomp01svn":17,"sgxtcbcomp02svn":17,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":7,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":10},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"sgxtcbcomp01svn":17,"sgxtcbcomp02svn":17,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":11},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"ConfigurationAndSWHardeningNeeded"},{"tcb":{"sgxtcbcomp01svn":17,"sgxtcbcomp02svn":17,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":10},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded"},{"tcb":{"sgxtcbcomp01svn":15,"sgxtcbcomp02svn":15,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":7,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":10},"tcbDate":"2020-06-10T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"sgxtcbcomp01svn":15,"sgxtcbcomp02svn":15,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":10},"tcbDate":"2020-06-10T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded"},{"tcb":{"sgxtcbcomp01svn":14,"sgxtcbcomp02svn":14,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":7,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":10},"tcbDate":"2019-12-11T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"sgxtcbcomp01svn":14,"sgxtcbcomp02svn":14,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":10},"tcbDate":"2019-12-11T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded"},{"tcb":{"sgxtcbcomp01svn":13,"sgxtcbcomp02svn":13,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":3,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":9},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"sgxtcbcomp01svn":13,"sgxtcbcomp02svn":13,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":9},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded"},{"tcb":{"sgxtcbcomp01svn":6,"sgxtcbcomp02svn":6,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":1,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":7},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"sgxtcbcomp01svn":6,"sgxtcbcomp02svn":6,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":7},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded"},{"tcb":{"sgxtcbcomp01svn":5,"sgxtcbcomp02svn":5,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":1,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":7},"tcbDate":"2019-01-09T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"sgxtcbcomp01svn":5,"sgxtcbcomp02svn":5,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":1,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":6},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"sgxtcbcomp01svn":5,"sgxtcbcomp02svn":5,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":7},"tcbDate":"2019-01-09T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded"},{"tcb":{"sgxtcbcomp01svn":5,"sgxtcbcomp02svn":5,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":6},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded"},{"tcb":{"sgxtcbcomp01svn":4,"sgxtcbcomp02svn":4,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":5},"tcbDate":"2018-01-04T00:00:00Z","tcbStatus":"OutOfDate"},{"tcb":{"sgxtcbcomp01svn":2,"sgxtcbcomp02svn":2,"sgxtcbcomp03svn":2,"sgxtcbcomp04svn":4,"sgxtcbcomp05svn":1,"sgxtcbcomp06svn":128,"sgxtcbcomp07svn":0,"sgxtcbcomp08svn":0,"sgxtcbcomp09svn":0,"sgxtcbcomp10svn":0,"sgxtcbcomp11svn":0,"sgxtcbcomp12svn":0,"sgxtcbcomp13svn":0,"sgxtcbcomp14svn":0,"sgxtcbcomp15svn":0,"sgxtcbcomp16svn":0,"pcesvn":4},"tcbDate":"2017-07-26T00:00:00Z","tcbStatus":"OutOfDate"}]}"#; + let signature = hex!("e0cc3102e9ffdb21cf156ba30f13d027210ab11f3bff349e670e4c49b2f0cb6889c7eeb436149c7efe53e15c97e6ec3fc9f34c3440e732a4c760f8eb91834a36"); + let signature = encode_as_der(&signature).unwrap(); + verify_signature(&leaf_cert, data, &signature, webpki::ring::ECDSA_P256_SHA256).unwrap(); +} + +/// This is demo code of how a CRL certificate can be parsed and how the revoked serials can be +/// extracted The part that is missing/open is how to verify the certificate chain of the CRL +/// TODO: Implement CRL handling +#[test] +fn parse_pck_crl() { + let crl_decoded = hex::decode(PCK_CRL).unwrap(); + let crl: x509_cert::crl::CertificateList = der::Decode::from_der(&crl_decoded).unwrap(); + + let mut serials = vec![]; + if let Some(certs) = crl.tbs_cert_list.revoked_certificates { + for c in certs { + let serial = c.serial_number.as_bytes().to_vec(); + serials.push(serial); + } + } + assert_eq!(3, serials.len()); +} + +#[test] +fn parse_pck_certificate() { + let der = DCAP_QUOTE_CERT.replace('\n', ""); + let der = base64::decode(der).unwrap(); + + let ext = get_intel_extension(&der).unwrap(); + assert_eq!(453, ext.len()); + + let fmspc = get_fmspc(&ext).unwrap(); + assert_eq!(hex!("00906EA10000"), fmspc); + + let cpusvn = get_cpusvn(&ext).unwrap(); + assert_eq!(hex!("11110204018007000000000000000000"), cpusvn); + + let pcesvn = get_pcesvn(&ext).unwrap(); + assert_eq!(u16::from_be_bytes(hex!("000B")), pcesvn); +} diff --git a/pallets/teebag/src/sgx_verify/utils.rs b/pallets/teebag/src/sgx_verify/utils.rs new file mode 100644 index 0000000000..14a1315a0a --- /dev/null +++ b/pallets/teebag/src/sgx_verify/utils.rs @@ -0,0 +1,38 @@ +fn safe_indexing_one(data: &[u8], idx: usize) -> Result { + let elt = data.get(idx).ok_or("Index out of bounds")?; + Ok(*elt as usize) +} + +pub fn length_from_raw_data(data: &[u8], offset: &mut usize) -> Result { + let mut len = safe_indexing_one(data, *offset)?; + if len > 0x80 { + len = (safe_indexing_one(data, *offset + 1)?) * 0x100 + + (safe_indexing_one(data, *offset + 2)?); + *offset += 2; + } + Ok(len) +} + +#[cfg(test)] +mod test { + use super::*; + use frame_support::assert_err; + + #[test] + fn index_equal_length_returns_err() { + // It was discovered a panic occurs if `index == data.len()` due to out of bound + // indexing. Here the fix is tested. + // + // For context see: https://github.com/integritee-network/pallet-teerex/issues/34 + let data: [u8; 7] = [0, 1, 2, 3, 4, 5, 6]; + assert_err!(safe_indexing_one(&data, data.len()), "Index out of bounds"); + } + + #[test] + fn safe_indexing_works() { + let data: [u8; 7] = [0, 1, 2, 3, 4, 5, 6]; + assert_eq!(safe_indexing_one(&data, 0), Ok(0)); + assert_eq!(safe_indexing_one(&data, 3), Ok(3)); + assert!(safe_indexing_one(&data, 10).is_err()); + } +} diff --git a/pallets/teebag/src/tcb.rs b/pallets/teebag/src/tcb.rs new file mode 100644 index 0000000000..0c6ba53156 --- /dev/null +++ b/pallets/teebag/src/tcb.rs @@ -0,0 +1,103 @@ +/* +Copyright 2021 Integritee AG and Supercomputing Systems AG + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +// `Tcb...` primitive part, copied from Integritee + +use crate::{Cpusvn, Pcesvn, Vec}; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_core::RuntimeDebug; + +/// The list of valid TCBs for an enclave. +#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct QeTcb { + pub isvsvn: u16, +} + +impl QeTcb { + pub fn new(isvsvn: u16) -> Self { + Self { isvsvn } + } +} + +#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct TcbVersionStatus { + pub cpusvn: Cpusvn, + pub pcesvn: Pcesvn, +} + +impl TcbVersionStatus { + pub fn new(cpusvn: Cpusvn, pcesvn: Pcesvn) -> Self { + Self { cpusvn, pcesvn } + } + + pub fn verify_examinee(&self, examinee: &TcbVersionStatus) -> bool { + for (v, r) in self.cpusvn.iter().zip(examinee.cpusvn.iter()) { + if *v > *r { + return false + } + } + self.pcesvn <= examinee.pcesvn + } +} + +/// This represents all the collateral data that we need to store on chain in order to verify +/// the quoting enclave validity of another enclave that wants to register itself on chain +#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct TcbInfoOnChain { + // Todo: make timestamp: Moment + pub issue_date: u64, // unix epoch in milliseconds + // Todo: make timestamp: Moment + pub next_update: u64, // unix epoch in milliseconds + tcb_levels: Vec, +} + +impl TcbInfoOnChain { + pub fn new(issue_date: u64, next_update: u64, tcb_levels: Vec) -> Self { + Self { issue_date, next_update, tcb_levels } + } + + pub fn verify_examinee(&self, examinee: &TcbVersionStatus) -> bool { + for tb in &self.tcb_levels { + if tb.verify_examinee(examinee) { + return true + } + } + false + } +} + +#[cfg(test)] +mod tests { + use super::*; + use hex_literal::hex; + + #[test] + fn tcb_full_is_valid() { + // The strings are the hex encodings of the 16-byte CPUSVN numbers + let reference = TcbVersionStatus::new(hex!("11110204018007000000000000000000"), 7); + assert!(reference.verify_examinee(&reference)); + assert!(reference + .verify_examinee(&TcbVersionStatus::new(hex!("11110204018007000000000000000000"), 7))); + assert!(reference + .verify_examinee(&TcbVersionStatus::new(hex!("21110204018007000000000000000001"), 7))); + assert!(!reference + .verify_examinee(&TcbVersionStatus::new(hex!("10110204018007000000000000000000"), 6))); + assert!(!reference + .verify_examinee(&TcbVersionStatus::new(hex!("11110204018007000000000000000000"), 6))); + } +} diff --git a/pallets/teebag/src/tests.rs b/pallets/teebag/src/tests.rs new file mode 100644 index 0000000000..1763242c85 --- /dev/null +++ b/pallets/teebag/src/tests.rs @@ -0,0 +1,445 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +// TODO: add `sidechain_block_imported` tests + +#![allow(dead_code, unused_imports)] +use crate::{ + mock::*, AttestationType, DcapProvider, Enclave, EnclaveRegistry, Error, Event as TeebagEvent, + ScheduledEnclave, SgxBuildMode, WorkerType, H256, +}; +use frame_support::{assert_noop, assert_ok}; +use hex_literal::hex; +use sp_keyring::AccountKeyring; +use sp_runtime::AccountId32; +use test_utils::{get_signer, ias::consts::*}; + +const VALID_TIMESTAMP: Moment = 1671606747000; + +fn alice() -> AccountId32 { + AccountKeyring::Alice.to_account_id() +} + +fn default_enclave() -> Enclave { + Enclave::new(WorkerType::Identity) + .with_attestation_type(AttestationType::Ignore) + .with_url(URL.to_vec()) + .with_last_seen_timestamp(pallet_timestamp::Pallet::::now()) +} + +fn register_quoting_enclave() { + let quoting_enclave = br#"{"id":"QE","version":2,"issueDate":"2022-12-04T22:45:33Z","nextUpdate":"2023-01-03T22:45:33Z","tcbEvaluationDataNumber":13,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":6},"tcbDate":"2022-11-09T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]}]}"#; + let signature = hex!("47accba321e57c20722a0d3d1db11c9b52661239857dc578ca1bde13976ee288cf39f72111ffe445c7389ef56447c79e30e6b83a8863ed9880de5bde4a8d5c91"); + let certificate_chain = include_bytes!("./sgx_verify/test/dcap/qe_identity_issuer_chain.pem"); + + let pubkey: [u8; 32] = [ + 65, 89, 193, 118, 86, 172, 17, 149, 206, 160, 174, 75, 219, 151, 51, 235, 110, 135, 20, 55, + 147, 162, 106, 110, 143, 207, 57, 64, 67, 63, 203, 95, + ]; + let signer: AccountId32 = get_signer(&pubkey); + assert_ok!(Teebag::register_quoting_enclave( + RuntimeOrigin::signed(signer), + quoting_enclave.to_vec(), + signature.to_vec(), + certificate_chain.to_vec(), + )); +} + +fn register_tcb_info() { + let tcb_info = br#"{"id":"SGX","version":3,"issueDate":"2022-11-17T12:45:32Z","nextUpdate":"2023-04-16T12:45:32Z","fmspc":"00906EA10000","pceId":"0000","tcbType":0,"tcbEvaluationDataNumber":12,"tcbLevels":[{"tcb":{"sgxtcbcomponents":[{"svn":17},{"svn":17},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":7},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":11},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"SWHardeningNeeded","advisoryIDs":["INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":17},{"svn":17},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":7},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":17},{"svn":17},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":11},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"ConfigurationAndSWHardeningNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":17},{"svn":17},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00477","INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":15},{"svn":15},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":7},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-06-10T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":15},{"svn":15},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-06-10T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":14},{"svn":14},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":7},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2019-12-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":14},{"svn":14},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2019-12-11T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":13},{"svn":13},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":3},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":9},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":13},{"svn":13},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":9},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":6},{"svn":6},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":7},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00161","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":6},{"svn":6},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":7},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":7},"tcbDate":"2019-01-09T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00233","INTEL-SA-00161","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":6},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":7},"tcbDate":"2019-01-09T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":6},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00203","INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":4},{"svn":4},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":5},"tcbDate":"2018-01-04T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00106","INTEL-SA-00115","INTEL-SA-00135","INTEL-SA-00203","INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]},{"tcb":{"sgxtcbcomponents":[{"svn":2},{"svn":2},{"svn":2},{"svn":4},{"svn":1},{"svn":128},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":4},"tcbDate":"2017-07-26T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00088","INTEL-SA-00106","INTEL-SA-00115","INTEL-SA-00135","INTEL-SA-00203","INTEL-SA-00161","INTEL-SA-00233","INTEL-SA-00220","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00219","INTEL-SA-00289","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00334"]}]}"#; + let signature = hex!("71746f2148ecba04e35cf1ac77a7e6267ce99f6781c1031f724bb5bd94b8c1b6e4c07c01dc151692aa75be80dfba7350bb80c58314a6975189597e28e9bbc75c"); + let certificate_chain = include_bytes!("./sgx_verify/test/dcap/tcb_info_issuer_chain.pem"); + + let pubkey: [u8; 32] = [ + 65, 89, 193, 118, 86, 172, 17, 149, 206, 160, 174, 75, 219, 151, 51, 235, 110, 135, 20, 55, + 147, 162, 106, 110, 143, 207, 57, 64, 67, 63, 203, 95, + ]; + let signer: AccountId32 = get_signer(&pubkey); + assert_ok!(Teebag::register_tcb_info( + RuntimeOrigin::signed(signer), + tcb_info.to_vec(), + signature.to_vec(), + certificate_chain.to_vec(), + )); +} + +// ===================================================== +// Unittest in `Development` mode, where: +// - AttestationType::Ignore is possible +// - No scheduled enclave check +// - No sgx_build_mode check +// ===================================================== + +#[test] +fn register_enclave_dev_works_with_no_scheduled_enclave() { + new_test_ext(true).execute_with(|| { + // it works with no entry in scheduled_enclave + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(alice()), + Default::default(), + Default::default(), + TEST4_MRENCLAVE.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ignore, + )); + + let enclave = default_enclave().with_mrenclave(TEST4_MRENCLAVE); + + assert_eq!(Teebag::enclave_count(WorkerType::Identity), 1); + assert_eq!(Teebag::enclave_count(WorkerType::BitAcross), 0); + assert_eq!(EnclaveRegistry::::get(alice()).unwrap(), enclave); + assert_eq!( + ScheduledEnclave::::get((WorkerType::default(), 0)).unwrap().to_vec(), + TEST4_MRENCLAVE.to_vec() + ); + }) +} + +#[test] +fn register_enclave_dev_works_with_sgx_build_mode_debug() { + new_test_ext(true).execute_with(|| { + // we'll need to use real attestation data + set_timestamp(TEST4_TIMESTAMP); + let signer4: AccountId32 = get_signer(TEST4_SIGNER_PUB); + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer4.clone()), + Default::default(), + Default::default(), + TEST4_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + )); + + let enclave = default_enclave() + .with_mrenclave(TEST4_MRENCLAVE) + .with_last_seen_timestamp(TEST4_TIMESTAMP) + .with_sgx_build_mode(SgxBuildMode::Debug) + .with_attestation_type(AttestationType::Ias); + + assert_eq!(Teebag::enclave_count(WorkerType::Identity), 1); + assert_eq!(Teebag::enclave_count(WorkerType::BitAcross), 0); + assert_eq!(EnclaveRegistry::::get(signer4).unwrap(), enclave); + }) +} + +#[test] +fn parentchain_block_processed_works() { + new_test_ext(true).execute_with(|| { + Timestamp::set_timestamp(TEST7_TIMESTAMP); + + // start from block 2, otherwise we get `TimeStamp not set` error, + // because `run_to_block` calls `Timestamp::on_finalize` + run_to_block(2); + Timestamp::set_timestamp(TEST7_TIMESTAMP + 12 * 1000); + + let block_hash = H256::default(); + let merkle_root = H256::default(); + let block_number = 2; + let signer7: AccountId32 = get_signer(TEST7_SIGNER_PUB); + + // Ensure that enclave is registered + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer7.clone()), + WorkerType::BitAcross, + Default::default(), + TEST7_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + )); + assert_eq!(Teebag::enclave_count(WorkerType::BitAcross), 1); + + run_to_block(3); + Timestamp::set_timestamp(TEST7_TIMESTAMP + 24 * 1000); + + assert_ok!(Teebag::parentchain_block_processed( + RuntimeOrigin::signed(signer7.clone()), + block_hash, + block_number, + merkle_root, + )); + + let expected_event = RuntimeEvent::Teebag(TeebagEvent::ParentchainBlockProcessed { + who: signer7, + block_number, + block_hash, + task_merkle_root: merkle_root, + }); + assert!(System::events().iter().any(|a| a.event == expected_event)); + }) +} + +#[test] +fn register_dcap_enclave_works() { + new_test_ext(true).execute_with(|| { + Timestamp::set_timestamp(VALID_TIMESTAMP); + register_quoting_enclave(); + register_tcb_info(); + + let pubkey: [u8; 32] = [ + 65, 89, 193, 118, 86, 172, 17, 149, 206, 160, 174, 75, 219, 151, 51, 235, 110, 135, 20, + 55, 147, 162, 106, 110, 143, 207, 57, 64, 67, 63, 203, 95, + ]; + let signer: AccountId = get_signer(&pubkey); + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer.clone()), + WorkerType::Identity, + Default::default(), + TEST1_DCAP_QUOTE.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Dcap(DcapProvider::Integritee) + )); + assert_eq!(Teebag::enclave_count(WorkerType::Identity), 1); + assert_eq!(Teebag::enclave_registry(&signer).unwrap().last_seen_timestamp, VALID_TIMESTAMP); + assert_ok!(Teebag::unregister_enclave(RuntimeOrigin::signed(signer))); + assert_eq!(Teebag::enclave_count(WorkerType::Identity), 0); + }) +} + +// ===================================================== +// Unittest in `Production` mode +// ===================================================== + +#[test] +fn register_enclave_prod_works_with_sgx_build_mode_debug() { + new_test_ext(false).execute_with(|| { + assert_ok!(Teebag::set_scheduled_enclave( + RuntimeOrigin::signed(alice()), + WorkerType::Identity, + 0, + TEST4_MRENCLAVE + )); + + set_timestamp(TEST4_TIMESTAMP); + let signer4: AccountId32 = get_signer(TEST4_SIGNER_PUB); + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer4.clone()), + Default::default(), + Default::default(), + TEST4_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + )); + + let enclave = default_enclave() + .with_mrenclave(TEST4_MRENCLAVE) + .with_last_seen_timestamp(TEST4_TIMESTAMP) + .with_sgx_build_mode(SgxBuildMode::Debug) + .with_attestation_type(AttestationType::Ias); + + assert_eq!(Teebag::enclave_count(WorkerType::Identity), 1); + assert_eq!(Teebag::enclave_count(WorkerType::BitAcross), 0); + assert_eq!(EnclaveRegistry::::get(signer4).unwrap(), enclave); + }) +} + +#[test] +fn register_enclave_prod_works_with_sgx_build_mode_production() { + new_test_ext(false).execute_with(|| { + assert_ok!(Teebag::set_scheduled_enclave( + RuntimeOrigin::signed(alice()), + WorkerType::Identity, + 0, + TEST8_MRENCLAVE + )); + + set_timestamp(TEST8_TIMESTAMP); + let signer8: AccountId32 = get_signer(TEST8_SIGNER_PUB); + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer8.clone()), + Default::default(), + Default::default(), + TEST8_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + )); + + let enclave = default_enclave() + .with_mrenclave(TEST8_MRENCLAVE) + .with_last_seen_timestamp(TEST8_TIMESTAMP) + .with_sgx_build_mode(SgxBuildMode::Production) + .with_attestation_type(AttestationType::Ias); + + assert_eq!(Teebag::enclave_count(WorkerType::Identity), 1); + assert_eq!(Teebag::enclave_count(WorkerType::BitAcross), 0); + assert_eq!(EnclaveRegistry::::get(signer8).unwrap(), enclave); + }) +} + +#[test] +fn register_enclave_prod_fails_with_wrong_attestation_type() { + new_test_ext(false).execute_with(|| { + assert_noop!( + Teebag::register_enclave( + RuntimeOrigin::signed(alice()), + Default::default(), + Default::default(), + TEST4_MRENCLAVE.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ignore, // only allowed in dev mode + ), + Error::::InvalidAttestationType + ); + }) +} + +#[test] +fn register_enclave_prod_fails_with_no_scheduled_enclave() { + new_test_ext(false).execute_with(|| { + Timestamp::set_timestamp(TEST4_TIMESTAMP); + let signer = get_signer(TEST4_SIGNER_PUB); + assert_noop!( + Teebag::register_enclave( + RuntimeOrigin::signed(signer), + Default::default(), + Default::default(), + TEST4_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + ), + Error::::EnclaveNotInSchedule + ); + }) +} + +#[test] +fn register_enclave_prod_fails_with_max_limit_reached() { + new_test_ext(false).execute_with(|| { + ScheduledEnclave::::insert((WorkerType::BitAcross, 0), TEST5_MRENCLAVE); + ScheduledEnclave::::insert((WorkerType::BitAcross, 1), TEST6_MRENCLAVE); + ScheduledEnclave::::insert((WorkerType::Identity, 0), TEST5_MRENCLAVE); + ScheduledEnclave::::insert((WorkerType::Identity, 1), TEST6_MRENCLAVE); + + let signer5: AccountId32 = get_signer(TEST5_SIGNER_PUB); + let signer6: AccountId32 = get_signer(TEST6_SIGNER_PUB); + + Timestamp::set_timestamp(TEST5_TIMESTAMP); + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer5.clone()), + WorkerType::BitAcross, + Default::default(), + TEST5_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + )); + Timestamp::set_timestamp(TEST6_TIMESTAMP); + assert_noop!( + Teebag::register_enclave( + RuntimeOrigin::signed(signer6.clone()), + WorkerType::BitAcross, + Default::default(), + TEST6_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + ), + Error::::MaxEnclaveIdentifierOverflow + ); + + // re-register them as WorkerType::Identity is not allowed + Timestamp::set_timestamp(TEST5_TIMESTAMP); + assert_noop!( + Teebag::register_enclave( + RuntimeOrigin::signed(signer5.clone()), + WorkerType::Identity, + Default::default(), + TEST5_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + ), + Error::::UnexpectedWorkerType + ); + + // remove and re-register it should work + assert_ok!(Teebag::force_remove_enclave(RuntimeOrigin::signed(alice()), signer5.clone(),)); + + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer5), + WorkerType::Identity, + Default::default(), + TEST5_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + )); + + Timestamp::set_timestamp(TEST6_TIMESTAMP); + assert_noop!( + Teebag::register_enclave( + RuntimeOrigin::signed(signer6), + WorkerType::Identity, + Default::default(), + TEST6_CERT.to_vec(), + URL.to_vec(), + None, + None, + AttestationType::Ias, + ), + Error::::MaxEnclaveIdentifierOverflow + ); + + assert_eq!(Teebag::enclave_count(WorkerType::Identity), 1); + assert_eq!(Teebag::enclave_count(WorkerType::BitAcross), 0); + }) +} + +#[test] +fn register_quoting_enclave_works() { + new_test_ext(false).execute_with(|| { + let qe = Teebag::quoting_enclave_registry(); + assert_eq!(qe.mrsigner, [0u8; 32]); + assert_eq!(qe.isvprodid, 0); + Timestamp::set_timestamp(VALID_TIMESTAMP); + register_quoting_enclave(); + let qe = Teebag::quoting_enclave_registry(); + assert_eq!(qe.isvprodid, 1); + }) +} + +#[test] +fn register_tcb_info_works() { + new_test_ext(false).execute_with(|| { + Timestamp::set_timestamp(VALID_TIMESTAMP); + + register_tcb_info(); + let fmspc = hex!("00906EA10000"); + let tcb_info = Teebag::tcb_info(fmspc); + // This is the date that the is registered in register_tcb_info and represents the date + // 2023-04-16T12:45:32Z + assert_eq!(tcb_info.next_update, 1681649132000); + }) +} diff --git a/pallets/teebag/src/types.rs b/pallets/teebag/src/types.rs new file mode 100644 index 0000000000..b67e9df6b8 --- /dev/null +++ b/pallets/teebag/src/types.rs @@ -0,0 +1,178 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::Ed25519Public; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_core::{RuntimeDebug, H256}; +use sp_std::prelude::*; + +pub type MrSigner = [u8; 32]; +pub type MrEnclave = [u8; 32]; +pub type Fmspc = [u8; 6]; +pub type Cpusvn = [u8; 16]; +pub type Pcesvn = u16; +pub type ShardIdentifier = H256; +pub type EnclaveFingerprint = H256; +pub type SidechainBlockNumber = u64; + +/// Different modes that control enclave registration and running: +/// - `Production`: default value. It perfroms all checks for enclave registration and runtime +/// - `Development`: the most lenient, most check are skipped during registration or runtime +/// - `Maintenance`: a placeholder value for now - maybe to stall sidechain block production +/// +/// please note: +/// `Attestation::Ignore` is only possible under `OperationalMode::Development`, but not vice versa. +/// So if you define `Attestation::Ias`, the attestation will be verified even in `Development` mode +#[derive(PartialEq, Eq, Clone, Copy, Default, Encode, Decode, Debug, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum OperationalMode { + #[default] + #[codec(index = 0)] + Production, + #[codec(index = 1)] + Development, + #[codec(index = 2)] + Maintenance, +} + +#[derive(Encode, Decode, Default, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub enum DcapProvider { + #[default] + MAA, + Intel, + Local, + Integritee, +} + +#[derive(Encode, Decode, Clone, Copy, Default, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub enum AttestationType { + #[default] + Ignore, + Ias, + Dcap(DcapProvider), +} + +#[derive(Encode, Decode, Clone, Copy, Default, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub enum WorkerType { + #[default] + Identity, + BitAcross, +} + +#[derive(Encode, Decode, Clone, Copy, Default, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub enum WorkerMode { + #[default] + OffChainWorker, + Sidechain, +} + +#[derive(Encode, Decode, Copy, Clone, Default, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub enum SgxBuildMode { + #[default] + #[codec(index = 0)] + Production, + #[codec(index = 1)] + Debug, +} + +#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug, Copy, Default, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct SidechainBlockConfirmation { + pub block_number: SidechainBlockNumber, + pub block_header_hash: H256, +} + +#[derive(Encode, Decode, Clone, Default, PartialEq, Eq, RuntimeDebug, TypeInfo)] +pub struct Enclave { + pub worker_type: WorkerType, + pub worker_mode: WorkerMode, + pub mrenclave: MrEnclave, + pub last_seen_timestamp: u64, // unix epoch in milliseconds when it's last seen + pub url: Vec, // utf8 encoded url + pub shielding_pubkey: Option>, // JSON serialised enclave shielding pub key + pub vc_pubkey: Option, + pub sgx_build_mode: SgxBuildMode, + pub attestation_type: AttestationType, +} + +impl Enclave { + pub fn new(worker_type: WorkerType) -> Self { + Enclave { worker_type, ..Default::default() } + } + + pub fn with_worker_mode(mut self, worker_mode: WorkerMode) -> Self { + self.worker_mode = worker_mode; + self + } + + pub fn with_mrenclave(mut self, mrenclave: MrEnclave) -> Self { + self.mrenclave = mrenclave; + self + } + + pub fn with_url(mut self, url: Vec) -> Self { + self.url = url; + self + } + + pub fn with_shielding_pubkey(mut self, shielding_pubkey: Option>) -> Self { + self.shielding_pubkey = shielding_pubkey; + self + } + + pub fn with_vc_pubkey(mut self, vc_pubkey: Option) -> Self { + self.vc_pubkey = vc_pubkey; + self + } + + pub fn with_last_seen_timestamp(mut self, t: u64) -> Self { + self.last_seen_timestamp = t; + self + } + + pub fn with_attestation_type(mut self, attestation_type: AttestationType) -> Self { + self.attestation_type = attestation_type; + self + } + + pub fn with_sgx_build_mode(mut self, sgx_build_mode: SgxBuildMode) -> Self { + self.sgx_build_mode = sgx_build_mode; + self + } +} + +// use the name `RsaRequest` to differentiate from `AesRequest` (see aes_request.rs in +// tee-worker) `Rsa` implies that the payload is RSA-encrypted (using enclave's shielding key) +#[macro_export] +macro_rules! decl_rsa_request { + ($($t:meta),*) => { + #[derive(Encode, Decode, Default, Clone, PartialEq, Eq, $($t),*)] + pub struct RsaRequest { + pub shard: ShardIdentifier, + pub payload: Vec, + } + impl RsaRequest { + pub fn new(shard: ShardIdentifier, payload: Vec) -> Self { + Self { shard, payload } + } + } + }; +} + +decl_rsa_request!(TypeInfo, RuntimeDebug); diff --git a/pallets/teeracle/README.md b/pallets/teeracle/README.md deleted file mode 100644 index ecb505a2f1..0000000000 --- a/pallets/teeracle/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# pallet-teeracle - -A pallet for [Integritee](https://integritee.network) which provides functionality for handling exchange rates of the coin (ex: TEER) to different currencies diff --git a/pallets/teeracle/src/benchmarking.rs b/pallets/teeracle/src/benchmarking.rs deleted file mode 100644 index 286c0c7a51..0000000000 --- a/pallets/teeracle/src/benchmarking.rs +++ /dev/null @@ -1,160 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Teeracle pallet benchmarking -#![allow(dead_code, unused_imports, const_item_mutation)] -#![cfg(any(test, feature = "runtime-benchmarks"))] - -use super::*; - -use crate::Pallet as Teeracle; -use frame_benchmarking::benchmarks; -use frame_system::RawOrigin; -use pallet_teerex::Pallet as Teerex; -use sp_runtime::traits::CheckedConversion; -use sp_std::prelude::*; -use teeracle_primitives::{DataSource, OracleDataName, TradingPairString}; - -use test_utils::{ - get_signer, - ias::{consts::*, setups::*}, -}; - -fn ensure_not_skipping_ra_check() { - #[cfg(not(test))] - if cfg!(feature = "skip-ias-check") { - panic!("Benchmark does not allow the `skip-ias-check` flag."); - }; -} -benchmarks! { - where_clause { where T::AccountId: From<[u8; 32]>, T::Hash: From<[u8; 32]> } - update_exchange_rate { - ensure_not_skipping_ra_check(); - timestamp::Pallet::::set_timestamp(TEST4_SETUP.timestamp.checked_into().unwrap()); - let signer: T::AccountId = get_signer(TEST4_SETUP.signer_pub); - let trading_pair: TradingPairString = "DOT/USD".into(); - let rate = U32F32::from_num(43.65); - let data_source: DataSource = "https://api.coingecko.com".into(); - - Teerex::::set_admin( - RawOrigin::Root.into(), - signer.clone(), - ).unwrap(); - - // we need different parameters, unfortunately - since the way to calculate - // MRENCLAVE differs depending on if `skip-ias-check` feature is present. - Teerex::::update_scheduled_enclave( - RawOrigin::Signed(signer.clone()).into(), - 0u64, - #[cfg(feature = "skip-ias-check")] - MrEnclave::decode(&mut TEST4_SETUP.cert).unwrap_or_default(), - #[cfg(not(feature = "skip-ias-check"))] - TEST4_MRENCLAVE, - ).unwrap(); - - // simply register the enclave before to make sure it already - // exists when running the benchmark - Teerex::::register_enclave( - RawOrigin::Signed(signer.clone()).into(), - TEST4_SETUP.cert.to_vec(), - URL.to_vec(), - None, - None, - ).unwrap(); - let mrenclave = Teerex::::enclave(1).unwrap().mr_enclave; - Teeracle::::add_to_whitelist(RawOrigin::Root.into(), data_source.clone(), mrenclave).unwrap(); - - }: _(RawOrigin::Signed(signer), data_source.clone(), trading_pair.clone(), Some(rate)) - verify { - assert_eq!(Teeracle::::exchange_rate(trading_pair, data_source), U32F32::from_num(43.65)); - } - - update_oracle { - ensure_not_skipping_ra_check(); - timestamp::Pallet::::set_timestamp(TEST4_SETUP.timestamp.checked_into().unwrap()); - let signer: T::AccountId = get_signer(TEST4_SETUP.signer_pub); - let oracle_name = OracleDataName::from("Test_Oracle_Name"); - let data_source = DataSource::from("Test_Source_Name"); - let oracle_blob: crate::OracleDataBlob = - vec![1].try_into().expect("Can Convert to OracleDataBlob; QED"); - - Teerex::::set_admin( - RawOrigin::Root.into(), - signer.clone(), - ).unwrap(); - - // we need different parameters, unfortunately - since the way to calculate - // MRENCLAVE differs depending on if `skip-ias-check` feature is present. - Teerex::::update_scheduled_enclave( - RawOrigin::Signed(signer.clone()).into(), - 0u64, - #[cfg(feature = "skip-ias-check")] - MrEnclave::decode(&mut TEST4_SETUP.cert).unwrap_or_default(), - #[cfg(not(feature = "skip-ias-check"))] - TEST4_MRENCLAVE, - ).unwrap(); - - Teerex::::set_skip_scheduled_enclave_check( - RawOrigin::Signed(signer.clone()).into(), - true - ).unwrap(); - - // simply register the enclave before to make sure it already - // exists when running the benchmark - Teerex::::register_enclave( - RawOrigin::Signed(signer.clone()).into(), - TEST4_SETUP.cert.to_vec(), - URL.to_vec(), - None, - None, - ).unwrap(); - let mrenclave = Teerex::::enclave(1).unwrap().mr_enclave; - Teeracle::::add_to_whitelist(RawOrigin::Root.into(), data_source.clone(), mrenclave).unwrap(); - }: _(RawOrigin::Signed(signer), oracle_name.clone(), data_source.clone(), oracle_blob.clone()) - verify { - assert_eq!(Teeracle::::oracle_data(oracle_name, data_source), oracle_blob); - } - - add_to_whitelist { - let mrenclave = TEST4_MRENCLAVE; - let data_source: DataSource = "https://api.coingecko.com".into(); - - }: _(RawOrigin::Root, data_source.clone(), mrenclave) - verify { - assert_eq!(Teeracle::::whitelist(data_source).len(), 1, "mrenclave not added to whitelist") - } - - remove_from_whitelist { - let mrenclave = TEST4_MRENCLAVE; - let data_source: DataSource = "https://api.coingecko.com".into(); - - Teeracle::::add_to_whitelist(RawOrigin::Root.into(), data_source.clone(), mrenclave).unwrap(); - - }: _(RawOrigin::Root, data_source.clone(), mrenclave) - verify { - assert_eq!(Teeracle::::whitelist(data_source).len(), 0, "mrenclave not removed from whitelist") - } -} - -#[cfg(test)] -use crate::{Config, Pallet as PalletModule}; - -#[cfg(test)] -use frame_benchmarking::impl_benchmark_test_suite; - -#[cfg(test)] -impl_benchmark_test_suite!(PalletModule, crate::mock::new_test_ext(), crate::mock::Test,); diff --git a/pallets/teeracle/src/lib.rs b/pallets/teeracle/src/lib.rs deleted file mode 100644 index a7122eec0d..0000000000 --- a/pallets/teeracle/src/lib.rs +++ /dev/null @@ -1,260 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -//! # Cryptocurrency teeracle pallet -//! -//! The teeracle pallet provides functionality for handling exchange rates of the coin (ex: TEER) to -//! different currencies -//! -//! - [`Config`] -//! - [`Call`] -//! - [`Pallet`] -//! -//! ## Overview -//! -//! The teeracle pallet provides functions for: -//! -//! - Setting exchange rates. -#![cfg_attr(not(feature = "std"), no_std)] -pub use crate::weights::WeightInfo; -pub use pallet::*; -pub use substrate_fixed::types::U32F32; -use teeracle_primitives::{DataSource, MAX_ORACLE_DATA_NAME_LEN}; - -const MAX_TRADING_PAIR_LEN: usize = 11; -const MAX_SOURCE_LEN: usize = 40; - -#[frame_support::pallet] -pub mod pallet { - use super::*; - use frame_support::{pallet_prelude::*, BoundedVec, WeakBoundedVec}; - use frame_system::pallet_prelude::*; - use sp_std::prelude::*; - use teeracle_primitives::*; - - pub type OracleDataBlob = BoundedVec::MaxOracleBlobLen>; - - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - #[pallet::config] - pub trait Config: frame_system::Config + pallet_teerex::Config { - /// The overarching event type. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - type WeightInfo: WeightInfo; - /// Max number of whitelisted oracle's releases allowed - #[pallet::constant] - type MaxWhitelistedReleases: Get; - - #[pallet::constant] - type MaxOracleBlobLen: Get; - } - - /// Exchange rates chain's cryptocurrency/currency (trading pair) from different sources - #[pallet::storage] - #[pallet::getter(fn exchange_rate)] - pub(super) type ExchangeRates = StorageDoubleMap< - _, - Blake2_128Concat, - TradingPairString, - Blake2_128Concat, - DataSource, - ExchangeRate, - ValueQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn oracle_data)] - pub(super) type OracleData = StorageDoubleMap< - _, - Blake2_128Concat, - OracleDataName, - Blake2_128Concat, - DataSource, - OracleDataBlob, - ValueQuery, - >; - - /// whitelist of trusted oracle's releases for different data sources - #[pallet::storage] - #[pallet::getter(fn whitelist)] - pub(super) type Whitelists = StorageMap< - _, - Blake2_128Concat, - DataSource, - WeakBoundedVec<[u8; 32], T::MaxWhitelistedReleases>, - ValueQuery, - >; - - // pub(super) type Whitelist = - // StorageValue<_, WeakBoundedVec<[u8; 32], T::MaxWhitelistedReleases>, ValueQuery>; - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// The exchange rate of trading pair was set/updated with value from source. - /// \[data_source], [trading_pair], [new value\] - ExchangeRateUpdated(DataSource, TradingPairString, Option), - ExchangeRateDeleted(DataSource, TradingPairString), - OracleUpdated(OracleDataName, DataSource), - AddedToWhitelist(DataSource, [u8; 32]), - RemovedFromWhitelist(DataSource, [u8; 32]), - } - - #[pallet::error] - pub enum Error { - InvalidCurrency, - /// Too many MrEnclave in the whitelist. - ReleaseWhitelistOverflow, - ReleaseNotWhitelisted, - ReleaseAlreadyWhitelisted, - TradingPairStringTooLong, - OracleDataNameStringTooLong, - DataSourceStringTooLong, - OracleBlobTooBig, - } - - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::call] - impl Pallet { - #[pallet::call_index(0)] - #[pallet::weight(::WeightInfo::add_to_whitelist())] - pub fn add_to_whitelist( - origin: OriginFor, - data_source: DataSource, - mrenclave: [u8; 32], - ) -> DispatchResult { - ensure_root(origin)?; - ensure!(data_source.len() <= MAX_SOURCE_LEN, Error::::DataSourceStringTooLong); - ensure!( - !Self::is_whitelisted(&data_source, mrenclave), - >::ReleaseAlreadyWhitelisted - ); - >::try_mutate(data_source.clone(), |mrenclave_vec| { - mrenclave_vec.try_push(mrenclave) - }) - .map_err(|_| Error::::ReleaseWhitelistOverflow)?; - Self::deposit_event(Event::AddedToWhitelist(data_source, mrenclave)); - Ok(()) - } - #[pallet::call_index(1)] - #[pallet::weight(::WeightInfo::remove_from_whitelist())] - pub fn remove_from_whitelist( - origin: OriginFor, - data_source: DataSource, - mrenclave: [u8; 32], - ) -> DispatchResult { - ensure_root(origin)?; - ensure!( - Self::is_whitelisted(&data_source, mrenclave), - >::ReleaseNotWhitelisted - ); - >::mutate(&data_source, |mrenclave_vec| { - mrenclave_vec.retain(|m| *m != mrenclave) - }); - Self::deposit_event(Event::RemovedFromWhitelist(data_source, mrenclave)); - Ok(()) - } - - #[pallet::call_index(2)] - #[pallet::weight(::WeightInfo::update_oracle())] - pub fn update_oracle( - origin: OriginFor, - oracle_name: OracleDataName, - data_source: DataSource, - new_blob: OracleDataBlob, - ) -> DispatchResultWithPostInfo { - let signer = ensure_signed(origin)?; - >::ensure_registered_enclave(&signer)?; - let signer_index = >::enclave_index(signer); - let signer_enclave = >::enclave(signer_index) - .ok_or(pallet_teerex::Error::::EmptyEnclaveRegistry)?; - - ensure!( - Self::is_whitelisted(&data_source, signer_enclave.mr_enclave), - >::ReleaseNotWhitelisted - ); - ensure!( - oracle_name.len() <= MAX_ORACLE_DATA_NAME_LEN, - Error::::OracleDataNameStringTooLong - ); - ensure!(data_source.len() <= MAX_SOURCE_LEN, Error::::DataSourceStringTooLong); - ensure!( - new_blob.len() as u32 <= T::MaxOracleBlobLen::get(), - Error::::OracleBlobTooBig - ); - - OracleData::::insert(&oracle_name, &data_source, new_blob); - Self::deposit_event(Event::::OracleUpdated(oracle_name, data_source)); - Ok(().into()) - } - - #[pallet::call_index(3)] - #[pallet::weight(::WeightInfo::update_exchange_rate())] - pub fn update_exchange_rate( - origin: OriginFor, - data_source: DataSource, - trading_pair: TradingPairString, - new_value: Option, - ) -> DispatchResultWithPostInfo { - let sender = ensure_signed(origin)?; - >::ensure_registered_enclave(&sender)?; - let sender_index = >::enclave_index(sender); - let sender_enclave = >::enclave(sender_index) - .ok_or(pallet_teerex::Error::::EmptyEnclaveRegistry)?; - // Todo: Never checks data source len - ensure!( - trading_pair.len() <= MAX_TRADING_PAIR_LEN, - Error::::TradingPairStringTooLong - ); - ensure!( - Self::is_whitelisted(&data_source, sender_enclave.mr_enclave), - >::ReleaseNotWhitelisted - ); - if new_value.is_none() || new_value == Some(U32F32::from_num(0)) { - log::info!("Delete exchange rate : {:?}", new_value); - ExchangeRates::::mutate_exists(&trading_pair, &data_source, |rate| *rate = None); - Self::deposit_event(Event::ExchangeRateDeleted(data_source, trading_pair)); - } else { - log::info!("Update exchange rate : {:?}", new_value); - ExchangeRates::::mutate_exists(&trading_pair, &data_source, |rate| { - *rate = new_value - }); - Self::deposit_event(Event::ExchangeRateUpdated( - data_source, - trading_pair, - new_value, - )); - } - Ok(().into()) - } - } -} -impl Pallet { - fn is_whitelisted(data_source: &DataSource, mrenclave: [u8; 32]) -> bool { - Self::whitelist(data_source).contains(&mrenclave) - } -} - -mod benchmarking; -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; -pub mod weights; diff --git a/pallets/teeracle/src/tests.rs b/pallets/teeracle/src/tests.rs deleted file mode 100644 index 0afb5bb4a2..0000000000 --- a/pallets/teeracle/src/tests.rs +++ /dev/null @@ -1,524 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -#![allow(dead_code, unused_imports, const_item_mutation)] - -use crate::{mock::*, ExchangeRates}; -use frame_support::{assert_err, assert_noop, assert_ok}; -use hex_literal::hex; -use pallet_teerex::Error; -use sp_runtime::DispatchError::BadOrigin; -use substrate_fixed::types::U32F32; -use teeracle_primitives::*; -use test_utils::ias::consts::{ - TEST4_CERT, TEST4_MRENCLAVE, TEST4_SIGNER_PUB, TEST4_TIMESTAMP, TEST5_MRENCLAVE, - TEST5_SIGNER_PUB, TEST8_MRENCLAVE, URL, -}; - -const COINGECKO_SRC: &str = "https://api.coingecko.com"; -const COINMARKETCAP_SRC: &str = "https://coinmarketcap.com/"; - -const DOT_USD_TRADING_PAIR: &str = "DOT/USD"; - -// give get_signer a concrete type -fn get_signer(pubkey: &[u8; 32]) -> AccountId { - test_utils::get_signer(pubkey) -} - -fn register_enclave_and_add_oracle_to_whitelist_ok(src: &str) { - Timestamp::set_timestamp(TEST4_TIMESTAMP); - let signer = get_signer(TEST4_SIGNER_PUB); - assert_ok!(Teerex::register_enclave( - RuntimeOrigin::signed(signer), - TEST4_CERT.to_vec(), - URL.to_vec(), - None, - None, - )); - let mrenclave = Teerex::enclave(1).unwrap().mr_enclave; - assert_ok!(Teeracle::add_to_whitelist(RuntimeOrigin::root(), src.to_owned(), mrenclave)); -} - -fn update_exchange_rate_dot_dollars_ok(src: &str, rate: Option) { - let signer = get_signer(TEST4_SIGNER_PUB); - assert_ok!(Teeracle::update_exchange_rate( - RuntimeOrigin::signed(signer), - src.to_owned(), - DOT_USD_TRADING_PAIR.to_owned(), - rate - )); -} - -#[test] -fn update_exchange_rate_works() { - new_test_ext().execute_with(|| { - register_enclave_and_add_oracle_to_whitelist_ok(COINGECKO_SRC); - - let rate = U32F32::from_num(43.65); - update_exchange_rate_dot_dollars_ok(COINGECKO_SRC, Some(rate)); - let expected_event = RuntimeEvent::Teeracle(crate::Event::ExchangeRateUpdated( - COINGECKO_SRC.to_owned(), - DOT_USD_TRADING_PAIR.to_owned(), - Some(rate), - )); - assert!(System::events().iter().any(|a| a.event == expected_event)); - assert_eq!( - Teeracle::exchange_rate(DOT_USD_TRADING_PAIR.to_owned(), COINGECKO_SRC.to_owned()), - rate - ); - - let rate2 = U32F32::from_num(4294967295.65); - update_exchange_rate_dot_dollars_ok(COINGECKO_SRC, Some(rate2)); - assert_eq!( - Teeracle::exchange_rate(DOT_USD_TRADING_PAIR.to_owned(), COINGECKO_SRC.to_owned()), - rate2 - ); - }) -} - -#[test] -fn update_oracle_works() { - new_test_ext().execute_with(|| { - let signer = get_signer(TEST4_SIGNER_PUB); - register_enclave_and_add_oracle_to_whitelist_ok(&DataSource::from("Test_Source_Name")); - let oracle_blob: crate::OracleDataBlob = - vec![1].try_into().expect("Can Convert to BoundedVec; QED"); - assert_ok!(Teeracle::update_oracle( - RuntimeOrigin::signed(signer), - OracleDataName::from("Test_Oracle_Name"), - DataSource::from("Test_Source_Name"), - oracle_blob.clone() - ),); - let expected_event = RuntimeEvent::Teeracle(crate::Event::OracleUpdated( - OracleDataName::from("Test_Oracle_Name"), - DataSource::from("Test_Source_Name"), - )); - assert!(System::events().iter().any(|a| a.event == expected_event)); - - assert_eq!( - Teeracle::oracle_data( - OracleDataName::from("Test_Oracle_Name"), - DataSource::from("Test_Source_Name") - ), - oracle_blob - ); - }) -} - -#[test] -fn get_existing_exchange_rate_works() { - new_test_ext().execute_with(|| { - let rate = U32F32::from_num(43.65); - register_enclave_and_add_oracle_to_whitelist_ok(COINGECKO_SRC); - update_exchange_rate_dot_dollars_ok(COINGECKO_SRC, Some(rate)); - assert_eq!( - Teeracle::exchange_rate(DOT_USD_TRADING_PAIR.to_owned(), COINGECKO_SRC.to_owned()), - rate - ); - }) -} - -#[test] -fn get_inexisting_exchange_rate_is_zero() { - new_test_ext().execute_with(|| { - assert!(!ExchangeRates::::contains_key( - DOT_USD_TRADING_PAIR.to_owned(), - COINGECKO_SRC.to_owned() - )); - assert_eq!( - Teeracle::exchange_rate(DOT_USD_TRADING_PAIR.to_owned(), COINGECKO_SRC.to_owned()), - U32F32::from_num(0) - ); - }) -} - -#[test] -fn update_exchange_rate_to_none_delete_exchange_rate() { - new_test_ext().execute_with(|| { - register_enclave_and_add_oracle_to_whitelist_ok(COINGECKO_SRC); - let rate = U32F32::from_num(43.65); - update_exchange_rate_dot_dollars_ok(COINGECKO_SRC, Some(rate)); - - update_exchange_rate_dot_dollars_ok(COINGECKO_SRC, None); - - let expected_event = RuntimeEvent::Teeracle(crate::Event::ExchangeRateDeleted( - COINGECKO_SRC.to_owned(), - DOT_USD_TRADING_PAIR.to_owned(), - )); - assert!(System::events().iter().any(|a| a.event == expected_event)); - assert!(!ExchangeRates::::contains_key( - DOT_USD_TRADING_PAIR.to_owned(), - COINGECKO_SRC.to_owned() - )); - }) -} - -#[test] -fn update_exchange_rate_to_zero_delete_exchange_rate() { - new_test_ext().execute_with(|| { - register_enclave_and_add_oracle_to_whitelist_ok(COINGECKO_SRC); - let rate = Some(U32F32::from_num(43.65)); - update_exchange_rate_dot_dollars_ok(COINGECKO_SRC, rate); - - update_exchange_rate_dot_dollars_ok(COINGECKO_SRC, Some(U32F32::from_num(0))); - - let expected_event = RuntimeEvent::Teeracle(crate::Event::ExchangeRateDeleted( - COINGECKO_SRC.to_owned(), - DOT_USD_TRADING_PAIR.to_owned(), - )); - - assert!(System::events().iter().any(|a| a.event == expected_event)); - assert!(!ExchangeRates::::contains_key( - DOT_USD_TRADING_PAIR.to_owned(), - COINGECKO_SRC.to_owned() - )); - }) -} - -#[test] -fn update_exchange_rate_from_not_registered_enclave_fails() { - new_test_ext().execute_with(|| { - let signer = get_signer(TEST4_SIGNER_PUB); - let rate = U32F32::from_num(43.65); - assert_err!( - Teeracle::update_exchange_rate( - RuntimeOrigin::signed(signer), - COINGECKO_SRC.to_owned(), - DOT_USD_TRADING_PAIR.to_owned(), - Some(rate) - ), - Error::::EnclaveIsNotRegistered - ); - }) -} - -#[test] -fn update_oracle_from_not_registered_enclave_fails() { - new_test_ext().execute_with(|| { - let signer = get_signer(TEST4_SIGNER_PUB); - assert_noop!( - Teeracle::update_oracle( - RuntimeOrigin::signed(signer), - OracleDataName::from("Test_Oracle_Name"), - DataSource::from("Test_Source_Name"), - vec![0].try_into().expect("Can Convert to BoundedVec; QED") - ), - Error::::EnclaveIsNotRegistered - ); - }) -} - -#[test] -fn update_exchange_rate_from_not_whitelisted_oracle_fails() { - new_test_ext().execute_with(|| { - Timestamp::set_timestamp(TEST4_TIMESTAMP); - let signer = get_signer(TEST4_SIGNER_PUB); - assert_ok!(Teerex::register_enclave( - RuntimeOrigin::signed(signer.clone()), - TEST4_CERT.to_vec(), - URL.to_vec(), - None, - None, - )); - - let rate = U32F32::from_num(43.65); - assert_err!( - Teeracle::update_exchange_rate( - RuntimeOrigin::signed(signer), - COINGECKO_SRC.to_owned(), - DOT_USD_TRADING_PAIR.to_owned(), - Some(rate) - ), - crate::Error::::ReleaseNotWhitelisted - ); - }) -} - -#[test] -fn update_oracle_from_not_whitelisted_oracle_fails() { - new_test_ext().execute_with(|| { - Timestamp::set_timestamp(TEST4_TIMESTAMP); - let signer = get_signer(TEST4_SIGNER_PUB); - assert_ok!(Teerex::register_enclave( - RuntimeOrigin::signed(signer.clone()), - TEST4_CERT.to_vec(), - URL.to_vec(), - None, - None, - )); - - assert_noop!( - Teeracle::update_oracle( - RuntimeOrigin::signed(signer), - OracleDataName::from("Test_Oracle_Name"), - DataSource::from("Test_Source_Name"), - vec![0].try_into().expect("Can Convert to BoundedVec; QED") - ), - crate::Error::::ReleaseNotWhitelisted - ); - }) -} - -#[test] -fn update_exchange_rate_with_too_long_trading_pair_fails() { - new_test_ext().execute_with(|| { - register_enclave_and_add_oracle_to_whitelist_ok(COINGECKO_SRC); - - let rate = Some(U32F32::from_num(43.65)); - let signer = get_signer(TEST4_SIGNER_PUB); - let too_long_trading_pair = "123456789_12".to_owned(); - assert_err!( - Teeracle::update_exchange_rate( - RuntimeOrigin::signed(signer), - COINGECKO_SRC.to_owned(), - too_long_trading_pair, - rate - ), - crate::Error::::TradingPairStringTooLong - ); - }) -} - -#[test] -fn add_to_whitelist_works() { - new_test_ext().execute_with(|| { - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - )); - let expected_event = RuntimeEvent::Teeracle(crate::Event::AddedToWhitelist( - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE, - )); - assert!(System::events().iter().any(|a| a.event == expected_event)); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 1); - }) -} - -#[test] -fn add_mulitple_src_to_whitelists_works() { - new_test_ext().execute_with(|| { - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINMARKETCAP_SRC.to_owned(), - TEST4_MRENCLAVE - )); - let expected_event = RuntimeEvent::Teeracle(crate::Event::AddedToWhitelist( - COINMARKETCAP_SRC.to_owned(), - TEST4_MRENCLAVE, - )); - - assert!(System::events().iter().any(|a| a.event == expected_event)); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 1); - assert_eq!(Teeracle::whitelist(COINMARKETCAP_SRC.to_owned()).len(), 1); - }) -} - -#[test] -fn add_two_times_to_whitelist_fails() { - new_test_ext().execute_with(|| { - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - )); - assert_err!( - Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - ), - crate::Error::::ReleaseAlreadyWhitelisted - ); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 1); - }) -} - -#[test] -fn add_too_many_oracles_to_whitelist_fails() { - new_test_ext().execute_with(|| { - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST5_MRENCLAVE - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d2") - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d3") - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d4") - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d5") - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d6") - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d7") - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d8") - )); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - hex!("f4dedfc9e5fcc48443332bc9b23161c34a3c3f5a692eaffdb228db27b704d9d9") - )); - assert_err!( - Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST8_MRENCLAVE - ), - crate::Error::::ReleaseWhitelistOverflow - ); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 10); - }) -} -#[test] -fn add_to_whitelist_too_long_source_fails() { - new_test_ext().execute_with(|| { - let too_long_source = "123456789_223456789_323456789_423456789_1".to_owned(); - assert_err!( - Teeracle::add_to_whitelist(RuntimeOrigin::root(), too_long_source, TEST4_MRENCLAVE), - crate::Error::::DataSourceStringTooLong - ); - }) -} - -#[test] -fn non_root_add_to_whitelist_fails() { - new_test_ext().execute_with(|| { - let signer = get_signer(TEST5_SIGNER_PUB); - assert_err!( - Teeracle::add_to_whitelist( - RuntimeOrigin::signed(signer), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - ), - BadOrigin - ); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 0); - }) -} - -#[test] -fn remove_from_whitelist_works() { - new_test_ext().execute_with(|| { - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - )); - assert_ok!(Teeracle::remove_from_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - )); - let expected_event = RuntimeEvent::Teeracle(crate::Event::RemovedFromWhitelist( - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE, - )); - assert!(System::events().iter().any(|a| a.event == expected_event)); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 0); - }) -} - -#[test] -fn remove_from_whitelist_not_whitelisted_fails() { - new_test_ext().execute_with(|| { - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - )); - assert_err!( - Teeracle::remove_from_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST5_MRENCLAVE - ), - crate::Error::::ReleaseNotWhitelisted - ); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 1); - }) -} - -#[test] -fn remove_from_empty_whitelist_doesnt_crash() { - new_test_ext().execute_with(|| { - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 0); - assert_err!( - Teeracle::remove_from_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST5_MRENCLAVE - ), - crate::Error::::ReleaseNotWhitelisted - ); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 0); - }) -} - -#[test] -fn non_root_remove_from_whitelist_fails() { - new_test_ext().execute_with(|| { - let signer = get_signer(TEST5_SIGNER_PUB); - assert_ok!(Teeracle::add_to_whitelist( - RuntimeOrigin::root(), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - )); - assert_err!( - Teeracle::remove_from_whitelist( - RuntimeOrigin::signed(signer), - COINGECKO_SRC.to_owned(), - TEST4_MRENCLAVE - ), - BadOrigin - ); - assert_eq!(Teeracle::whitelist(COINGECKO_SRC.to_owned()).len(), 1); - }) -} diff --git a/pallets/teeracle/src/weights.rs b/pallets/teeracle/src/weights.rs deleted file mode 100644 index cd3798a18f..0000000000 --- a/pallets/teeracle/src/weights.rs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -//! Autogenerated weights for pallet_teeracle -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-12-27, STEPS: `20`, REPEAT: 50, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 20 - -// Executed Command: -// ./target/release/litentry-collator -// benchmark -// pallet -// --chain=rococo-dev -// --execution=wasm -// --db-cache=20 -// --wasm-execution=compiled -// --pallet=pallet_teeracle -// --extrinsic=* -// --heap-pages=4096 -// --steps=20 -// --repeat=50 -// --header=./LICENSE_HEADER -// --template=./templates/benchmark/pallet-weight-template.hbs -// --output=./pallets/teeracle/src/weights.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(clippy::unnecessary_cast)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for pallet_teeracle. -pub trait WeightInfo { - fn add_to_whitelist() -> Weight; - fn remove_from_whitelist() -> Weight; - fn update_exchange_rate() -> Weight; - fn update_oracle() -> Weight; -} - -/// Weights for pallet_teeracle using the Litentry node and recommended hardware. -pub struct LitentryWeight(PhantomData); -impl WeightInfo for LitentryWeight { - // Storage: Teerex EnclaveIndex (r:1 w:0) - // Storage: Teerex EnclaveRegistry (r:1 w:0) - // Storage: Teeracle Whitelists (r:1 w:0) - // Storage: Teeracle ExchangeRates (r:1 w:1) - fn update_exchange_rate() -> Weight { - Weight::from_parts(44_063_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: Teerex EnclaveIndex (r:1 w:0) - // Storage: Teerex EnclaveRegistry (r:1 w:0) - // Storage: Teeracle Whitelists (r:1 w:0) - // Storage: Teeracle OracleData (r:0 w:1) - fn update_oracle() -> Weight { - Weight::from_parts(39_144_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: Teeracle Whitelists (r:1 w:1) - fn add_to_whitelist() -> Weight { - Weight::from_parts(22_062_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: Teeracle Whitelists (r:1 w:1) - fn remove_from_whitelist() -> Weight { - Weight::from_parts(24_196_000 as u64, 0) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - // Storage: Teerex EnclaveIndex (r:1 w:0) - // Storage: Teerex EnclaveRegistry (r:1 w:0) - // Storage: Teeracle Whitelists (r:1 w:0) - // Storage: Teeracle ExchangeRates (r:1 w:1) - fn update_exchange_rate() -> Weight { - Weight::from_parts(44_063_000 as u64, 0) - .saturating_add(RocksDbWeight::get().reads(4 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: Teerex EnclaveIndex (r:1 w:0) - // Storage: Teerex EnclaveRegistry (r:1 w:0) - // Storage: Teeracle Whitelists (r:1 w:0) - // Storage: Teeracle OracleData (r:0 w:1) - fn update_oracle() -> Weight { - Weight::from_parts(39_144_000 as u64, 0) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: Teeracle Whitelists (r:1 w:1) - fn add_to_whitelist() -> Weight { - Weight::from_parts(22_062_000 as u64, 0) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: Teeracle Whitelists (r:1 w:1) - fn remove_from_whitelist() -> Weight { - Weight::from_parts(24_196_000 as u64, 0) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } -} - diff --git a/pallets/vc-management/Cargo.toml b/pallets/vc-management/Cargo.toml index 8566ffd22d..e349b51bd3 100644 --- a/pallets/vc-management/Cargo.toml +++ b/pallets/vc-management/Cargo.toml @@ -22,7 +22,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "polk # local core-primitives = { path = "../../primitives/core", default-features = false } -teerex-primitives = { path = "../../primitives/teerex", default-features = false } +pallet-teebag = { path = "../teebag", default-features = false } # benchmarking frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false, optional = true } @@ -32,7 +32,6 @@ test-utils = { path = "../test-utils", default-features = false, optional = true frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } pallet-group = { path = "../../pallets/group" } -pallet-teerex = { path = "../../pallets/teerex" } pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } test-utils = { path = "../test-utils" } @@ -57,7 +56,7 @@ std = [ "frame-system/std", "frame-benchmarking?/std", "core-primitives/std", - "teerex-primitives/std", + "pallet-teebag/std", "pallet-balances/std", "pallet-group/std", ] diff --git a/pallets/vc-management/src/lib.rs b/pallets/vc-management/src/lib.rs index d59b6f3791..14c86c447c 100644 --- a/pallets/vc-management/src/lib.rs +++ b/pallets/vc-management/src/lib.rs @@ -35,9 +35,9 @@ pub mod weights; pub use crate::weights::WeightInfo; pub use pallet::*; +use pallet_teebag::ShardIdentifier; use sp_core::H256; use sp_std::vec::Vec; -use teerex_primitives::ShardIdentifier; mod schema; pub use schema::*; diff --git a/pallets/vc-management/src/mock.rs b/pallets/vc-management/src/mock.rs index 9ac8374515..ceb086d59b 100644 --- a/pallets/vc-management/src/mock.rs +++ b/pallets/vc-management/src/mock.rs @@ -43,7 +43,7 @@ type SystemAccountId = ::AccountId; pub struct EnsureEnclaveSigner(PhantomData); impl EnsureOrigin for EnsureEnclaveSigner where - T: frame_system::Config + pallet_teerex::Config + pallet_timestamp::Config, + T: frame_system::Config + pallet_teebag::Config + pallet_timestamp::Config, ::AccountId: From<[u8; 32]>, ::Hash: From<[u8; 32]>, { @@ -51,7 +51,7 @@ where fn try_origin(o: T::RuntimeOrigin) -> Result { o.into().and_then(|o| match o { frame_system::RawOrigin::Signed(who) - if pallet_teerex::Pallet::::ensure_registered_enclave(&who) == Ok(()) => + if pallet_teebag::EnclaveRegistry::::contains_key(&who) => Ok(who), r => Err(T::RuntimeOrigin::from(r)), }) @@ -59,17 +59,13 @@ where #[cfg(feature = "runtime-benchmarks")] fn try_successful_origin() -> Result { - use test_utils::ias::{ - consts::{TEST8_MRENCLAVE, TEST8_SIGNER_PUB}, - TestEnclave, - }; + use test_utils::ias::consts::{TEST8_MRENCLAVE, TEST8_SIGNER_PUB}; let signer: ::AccountId = test_utils::get_signer(TEST8_SIGNER_PUB); - if !pallet_teerex::EnclaveIndex::::contains_key(signer.clone()) { - assert_ok!(pallet_teerex::Pallet::::add_enclave( + if !pallet_teebag::EnclaveRegistry::::contains_key(signer.clone()) { + assert_ok!(pallet_teebag::Pallet::::add_enclave( &signer, - &teerex_primitives::Enclave::test_enclave(signer.clone()) - .with_mr_enclave(TEST8_MRENCLAVE), + &pallet_teebag::Enclave::default().with_mrenclave(TEST8_MRENCLAVE), )); } Ok(frame_system::RawOrigin::Signed(signer).into()) @@ -85,7 +81,7 @@ frame_support::construct_runtime!( { System: frame_system, Balances: pallet_balances, - Teerex: pallet_teerex, + Teebag: pallet_teebag, Timestamp: pallet_timestamp, VCManagement: pallet_vc_management, VCMPExtrinsicWhitelist: pallet_group, @@ -157,16 +153,13 @@ impl pallet_vc_management::Config for Test { parameter_types! { pub const MomentsPerDay: u64 = 86_400_000; // [ms/d] - pub const MaxSilenceTime: u64 = 172_800_000; // 48h } -impl pallet_teerex::Config for Test { +impl pallet_teebag::Config for Test { type RuntimeEvent = RuntimeEvent; - type Currency = Balances; type MomentsPerDay = MomentsPerDay; - type MaxSilenceTime = MaxSilenceTime; - type WeightInfo = (); type SetAdminOrigin = EnsureRoot; + type MaxEnclaveIdentifier = ConstU32<3>; } impl pallet_group::Config for Test { @@ -183,22 +176,25 @@ pub fn new_test_ext() -> sp_io::TestExternalities { System::set_block_number(1); let _ = VCManagement::set_admin(RuntimeOrigin::root(), alice.clone()); let _ = VCManagement::add_delegatee(RuntimeOrigin::root(), eddie); - assert_ok!(Teerex::set_admin(RuntimeOrigin::root(), alice.clone())); - assert_ok!(Teerex::set_skip_scheduled_enclave_check( + assert_ok!(Teebag::set_admin(RuntimeOrigin::root(), alice.clone())); + assert_ok!(Teebag::set_mode( RuntimeOrigin::signed(alice.clone()), - true + pallet_teebag::OperationalMode::Development )); use test_utils::ias::consts::{TEST8_CERT, TEST8_SIGNER_PUB, TEST8_TIMESTAMP, URL}; Timestamp::set_timestamp(TEST8_TIMESTAMP); - let teerex_signer: SystemAccountId = test_utils::get_signer(TEST8_SIGNER_PUB); - if !pallet_teerex::EnclaveIndex::::contains_key(teerex_signer.clone()) { - assert_ok!(Teerex::register_enclave( - RuntimeOrigin::signed(teerex_signer), + let signer: SystemAccountId = test_utils::get_signer(TEST8_SIGNER_PUB); + if !pallet_teebag::EnclaveRegistry::::contains_key(signer.clone()) { + assert_ok!(Teebag::register_enclave( + RuntimeOrigin::signed(signer), + pallet_teebag::WorkerType::Identity, + pallet_teebag::WorkerMode::Sidechain, TEST8_CERT.to_vec(), URL.to_vec(), None, None, + pallet_teebag::AttestationType::Ias, )); } }); diff --git a/primitives/common/Cargo.toml b/primitives/common/Cargo.toml deleted file mode 100644 index cf8f8b94bd..0000000000 --- a/primitives/common/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -authors = ['Trust Computing GmbH '] -edition = "2021" -homepage = 'https://litentry.com/' -license = "Apache-2.0" -name = "common-primitives" -repository = 'https://github.com/litentry/litentry-parachain' -version = "0.1.0" - -[dependencies] - -# substrate deps -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -[features] -default = ["std"] -std = [ - "sp-std/std", -] diff --git a/primitives/common/src/lib.rs b/primitives/common/src/lib.rs deleted file mode 100644 index 144071644c..0000000000 --- a/primitives/common/src/lib.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -#![cfg_attr(not(feature = "std"), no_std)] -//!Primitives for all pallets - -#[cfg(not(feature = "std"))] -use sp_std::vec::Vec; - -/// Substrate runtimes provide no string type. Hence, for arbitrary data of varying length the -/// `Vec` is used. In the polkadot-js the typedef `Text` is used to automatically -/// utf8 decode bytes into a string. -#[cfg(not(feature = "std"))] -pub type PalletString = Vec; - -#[cfg(feature = "std")] -pub type PalletString = String; - -pub trait AsByteOrNoop { - fn as_bytes_or_noop(&self) -> &[u8]; -} - -impl AsByteOrNoop for PalletString { - #[cfg(feature = "std")] - fn as_bytes_or_noop(&self) -> &[u8] { - self.as_bytes() - } - - #[cfg(not(feature = "std"))] - fn as_bytes_or_noop(&self) -> &[u8] { - self - } -} diff --git a/primitives/core/proc-macros/src/lib.rs b/primitives/core/proc-macros/src/lib.rs index 16ac88fe39..4e803e10e7 100644 --- a/primitives/core/proc-macros/src/lib.rs +++ b/primitives/core/proc-macros/src/lib.rs @@ -35,7 +35,7 @@ This works similar with `#[cfg(..)]` that sets the target only appear on the spe ``` use litentry_proc_macros::reuse; -#[reuse(x, y)] . // Define the cases that the following implementation expands for each one +#[reuse(x, y)] // Define the cases that the following implementation expands for each one mod __ { // Leave mod name with double discards, which is to be replaced by the cases #[x] // This item would only appear on case `x` fn u() { diff --git a/primitives/core/src/assertion.rs b/primitives/core/src/assertion.rs index 99de17a200..3d983db39f 100644 --- a/primitives/core/src/assertion.rs +++ b/primitives/core/src/assertion.rs @@ -19,8 +19,8 @@ use crate::{ all_web3networks, AccountId, BnbDigitDomainType, BoundedWeb3Network, EVMTokenType, - GenericDiscordRoleType, OneBlockCourseType, VIP3MembershipCardLevel, Web3Network, - Web3TokenType, + GenericDiscordRoleType, OneBlockCourseType, PlatformUserType, VIP3MembershipCardLevel, + Web3Network, Web3NftType, Web3TokenType, }; use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; @@ -29,100 +29,68 @@ use sp_std::{vec, vec::Vec}; pub type ParameterString = BoundedVec>; -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableAmountHolding { - pub name: ParameterString, - pub chain: Web3Network, - pub amount: ParameterString, - pub date: ParameterString, - pub token: Option, +macro_rules! AchainableRequestParams { + ($type_name:ident, {$( $field_name:ident : $field_type:ty , )* }) => { + #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] + pub struct $type_name { + pub name: ParameterString, + pub chain: BoundedWeb3Network, + $( pub $field_name: $field_type ),* + } + }; } -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableAmountToken { - pub name: ParameterString, - - // Considering the uniformity of the structure, all relevant chain structures should be changed - // to BoundedWeb3Network. However, this would be a significant modification for the previous - // VC. Considering the tight timeline for this New Year compain, we will temporarily only - // change this AchainableAmountToken' chain field to BoundedWeb3Network. Afterwards, it needs - // to be modified to be consistent. - pub chain: BoundedWeb3Network, - - pub amount: ParameterString, - pub token: Option, -} +AchainableRequestParams!(AchainableAmountHolding, { + amount: ParameterString, + date: ParameterString, + token: Option, +}); -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableAmount { - pub name: ParameterString, - pub chain: Web3Network, - pub amount: ParameterString, -} +AchainableRequestParams!(AchainableAmountToken, { + amount: ParameterString, + token: Option, +}); -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableAmounts { - pub name: ParameterString, - pub chain: Web3Network, - pub amount1: ParameterString, - pub amount2: ParameterString, -} +AchainableRequestParams!(AchainableAmount, { + amount: ParameterString, +}); -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableBasic { - pub name: ParameterString, - pub chain: Web3Network, -} +AchainableRequestParams!(AchainableAmounts, { + amount1: ParameterString, + amount2: ParameterString, +}); -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableBetweenPercents { - pub name: ParameterString, - pub chain: Web3Network, - pub greater_than_or_equal_to: ParameterString, - pub less_than_or_equal_to: ParameterString, -} +AchainableRequestParams!(AchainableBasic, {}); -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableClassOfYear { - pub name: ParameterString, - pub chain: Web3Network, -} +AchainableRequestParams!(AchainableBetweenPercents, { + greater_than_or_equal_to: ParameterString, + less_than_or_equal_to: ParameterString, +}); -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableDateInterval { - pub name: ParameterString, - pub chain: Web3Network, - pub start_date: ParameterString, - pub end_date: ParameterString, -} +AchainableRequestParams!(AchainableClassOfYear, {}); -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableDatePercent { - pub name: ParameterString, - pub chain: Web3Network, - pub token: ParameterString, - pub date: ParameterString, - pub percent: ParameterString, -} -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableDate { - pub name: ParameterString, - pub chain: Web3Network, - pub date: ParameterString, -} -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableToken { - pub name: ParameterString, - pub chain: Web3Network, - pub token: ParameterString, -} +AchainableRequestParams!(AchainableDateInterval, { + start_date: ParameterString, + end_date: ParameterString, +}); -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] -pub struct AchainableMirror { - pub name: ParameterString, - pub chain: Web3Network, - pub post_quantity: Option, -} +AchainableRequestParams!(AchainableDatePercent, { + token: ParameterString, + date: ParameterString, + percent: ParameterString, +}); + +AchainableRequestParams!(AchainableDate, { + date: ParameterString, +}); + +AchainableRequestParams!(AchainableToken, { + token: ParameterString, +}); + +AchainableRequestParams!(AchainableMirror, { + post_quantity: Option, +}); #[rustfmt::skip] #[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] @@ -173,18 +141,18 @@ impl AchainableParams { pub fn chains(&self) -> Vec { match self { - AchainableParams::AmountHolding(arg) => vec![arg.chain], + AchainableParams::AmountHolding(arg) => arg.chain.to_vec(), AchainableParams::AmountToken(arg) => arg.chain.to_vec(), - AchainableParams::Amount(arg) => vec![arg.chain], - AchainableParams::Amounts(arg) => vec![arg.chain], - AchainableParams::Basic(arg) => vec![arg.chain], - AchainableParams::BetweenPercents(arg) => vec![arg.chain], - AchainableParams::ClassOfYear(arg) => vec![arg.chain], - AchainableParams::DateInterval(arg) => vec![arg.chain], - AchainableParams::DatePercent(arg) => vec![arg.chain], - AchainableParams::Date(arg) => vec![arg.chain], - AchainableParams::Token(arg) => vec![arg.chain], - AchainableParams::Mirror(arg) => vec![arg.chain], + AchainableParams::Amount(arg) => arg.chain.to_vec(), + AchainableParams::Amounts(arg) => arg.chain.to_vec(), + AchainableParams::Basic(arg) => arg.chain.to_vec(), + AchainableParams::BetweenPercents(arg) => arg.chain.to_vec(), + AchainableParams::ClassOfYear(arg) => arg.chain.to_vec(), + AchainableParams::DateInterval(arg) => arg.chain.to_vec(), + AchainableParams::DatePercent(arg) => arg.chain.to_vec(), + AchainableParams::Date(arg) => arg.chain.to_vec(), + AchainableParams::Token(arg) => arg.chain.to_vec(), + AchainableParams::Mirror(arg) => arg.chain.to_vec(), } } } @@ -225,9 +193,9 @@ pub enum Assertion { #[codec(index = 12)] A20, - // For Oneblock + // For OneBlock #[codec(index = 13)] - Oneblock(OneBlockCourseType), + OneBlock(OneBlockCourseType), // GenericDiscordRole #[codec(index = 14)] @@ -261,6 +229,12 @@ pub enum Assertion { #[codec(index = 24)] TokenHoldingAmount(Web3TokenType), + + #[codec(index = 25)] + PlatformUser(PlatformUserType), + + #[codec(index = 26)] + NftHolder(Web3NftType), } impl Assertion { @@ -290,8 +264,8 @@ impl Assertion { Self::A14 => vec![Web3Network::Polkadot], // Achainable Assertions Self::Achainable(arg) => arg.chains(), - // Oneblock Assertion - Self::Oneblock(..) => vec![Web3Network::Polkadot, Web3Network::Kusama], + // OneBlock Assertion + Self::OneBlock(..) => vec![Web3Network::Polkadot, Web3Network::Kusama], // SPACEID Assertions Self::BnbDomainHolding | Self::BnbDigitDomainClub(..) => vec![Web3Network::Bsc], // LITStaking @@ -309,6 +283,8 @@ impl Assertion { // no web3 network is allowed Self::A2(..) | Self::A3(..) | Self::A6 | Self::GenericDiscordRole(..) => vec![], Self::TokenHoldingAmount(t_type) => t_type.get_supported_networks(), + Self::PlatformUser(p_type) => p_type.get_supported_networks(), + Self::NftHolder(t_type) => t_type.get_supported_networks(), } } } diff --git a/primitives/core/src/identity.rs b/primitives/core/src/identity.rs index 77876b362a..499e58e7f0 100644 --- a/primitives/core/src/identity.rs +++ b/primitives/core/src/identity.rs @@ -59,7 +59,7 @@ impl Encode for IdentityString { } } -#[derive(Eq, PartialEq, Clone, MaxEncodedLen, Default)] +#[derive(Eq, PartialEq, Clone, MaxEncodedLen, Default, Ord, PartialOrd)] pub struct IdentityString { pub inner: IdentityInnerString, } @@ -91,7 +91,9 @@ impl Debug for IdentityString { } } -#[derive(Encode, Decode, Copy, Clone, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[derive( + Encode, Decode, Copy, Clone, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen, Ord, PartialOrd, +)] pub struct Address20([u8; 20]); impl AsRef<[u8; 20]> for Address20 { @@ -128,7 +130,9 @@ impl Debug for Address20 { } } -#[derive(Encode, Decode, Copy, Clone, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[derive( + Encode, Decode, Copy, Clone, Default, PartialEq, Eq, TypeInfo, MaxEncodedLen, Ord, PartialOrd, +)] pub struct Address32([u8; 32]); impl AsRef<[u8; 32]> for Address32 { fn as_ref(&self) -> &[u8; 32] { @@ -197,7 +201,7 @@ impl Debug for Address32 { } // TODO: maybe use macros to reduce verbosity -#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen, PartialOrd, Ord)] pub struct Address33([u8; 33]); impl AsRef<[u8; 33]> for Address33 { fn as_ref(&self) -> &[u8; 33] { @@ -261,7 +265,9 @@ impl Debug for Address33 { /// Web2 and Web3 Identity based on handle/public key /// We only include the network categories (substrate/evm) without concrete types /// see https://github.com/litentry/litentry-parachain/issues/1841 -#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen, EnumIter)] +#[derive( + Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen, EnumIter, Ord, PartialOrd, +)] pub enum Identity { // web2 #[codec(index = 0)] diff --git a/primitives/core/src/lib.rs b/primitives/core/src/lib.rs index 25e3402370..ad0cb102be 100644 --- a/primitives/core/src/lib.rs +++ b/primitives/core/src/lib.rs @@ -62,6 +62,12 @@ pub use evm_amount_holding::*; mod web3_token; pub use web3_token::*; +mod platform_user; +pub use platform_user::*; + +mod web3_nft; +pub use web3_nft::*; + /// Common types of parachains. mod types { use sp_runtime::{ diff --git a/primitives/core/src/network.rs b/primitives/core/src/network.rs index ddad0cef7e..8f8d92061e 100644 --- a/primitives/core/src/network.rs +++ b/primitives/core/src/network.rs @@ -90,6 +90,12 @@ pub enum Web3Network { BitcoinP2wpkh, #[codec(index = 13)] BitcoinP2wsh, + + // evm + #[codec(index = 14)] + Polygon, + #[codec(index = 15)] + Arbitrum, } // mainly used in CLI @@ -114,7 +120,7 @@ impl Web3Network { } pub fn is_evm(&self) -> bool { - matches!(self, Self::Ethereum | Self::Bsc) + matches!(self, Self::Ethereum | Self::Bsc | Self::Polygon | Self::Arbitrum) } pub fn is_bitcoin(&self) -> bool { @@ -175,6 +181,8 @@ mod tests { Web3Network::BitcoinP2sh => false, Web3Network::BitcoinP2wpkh => false, Web3Network::BitcoinP2wsh => false, + Web3Network::Polygon => true, + Web3Network::Arbitrum => true, } ) }) @@ -200,6 +208,8 @@ mod tests { Web3Network::BitcoinP2sh => false, Web3Network::BitcoinP2wpkh => false, Web3Network::BitcoinP2wsh => false, + Web3Network::Polygon => false, + Web3Network::Arbitrum => false, } ) }) @@ -225,6 +235,8 @@ mod tests { Web3Network::BitcoinP2sh => true, Web3Network::BitcoinP2wpkh => true, Web3Network::BitcoinP2wsh => true, + Web3Network::Polygon => false, + Web3Network::Arbitrum => false, } ) }) diff --git a/bitacross-worker/core-primitives/utils/src/macros.rs b/primitives/core/src/platform_user.rs similarity index 58% rename from bitacross-worker/core-primitives/utils/src/macros.rs rename to primitives/core/src/platform_user.rs index 69783ff727..c7977a0e50 100644 --- a/bitacross-worker/core-primitives/utils/src/macros.rs +++ b/primitives/core/src/platform_user.rs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 Trust Computing GmbH. +// Copyright 2020-2024 Trust Computing GmbH. // This file is part of Litentry. // // Litentry is free software: you can redistribute it and/or modify @@ -14,22 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -#[macro_export] -macro_rules! if_production_or { - ($prod_variant:expr, $non_prod_variant:expr) => { - if cfg!(feature = "production") { - $prod_variant - } else { - $non_prod_variant - } - }; +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_std::vec::Vec; + +use crate::{all_evm_web3networks, Web3Network}; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +pub enum PlatformUserType { + #[codec(index = 0)] + KaratDaoUser, } -#[macro_export] -macro_rules! if_not_production { - ($expression:expr) => { - if cfg!(not(feature = "production")) { - $expression +impl PlatformUserType { + pub fn get_supported_networks(&self) -> Vec { + match self { + Self::KaratDaoUser => all_evm_web3networks(), } - }; + } } diff --git a/primitives/core/src/web3_nft.rs b/primitives/core/src/web3_nft.rs new file mode 100644 index 0000000000..4f11cb30f0 --- /dev/null +++ b/primitives/core/src/web3_nft.rs @@ -0,0 +1,38 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_std::{vec, vec::Vec}; + +use crate::Web3Network; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, MaxEncodedLen, TypeInfo)] +pub enum Web3NftType { + #[codec(index = 0)] + WeirdoGhostGang, + #[codec(index = 1)] + Club3Sbt, +} + +impl Web3NftType { + pub fn get_supported_networks(&self) -> Vec { + match self { + Self::WeirdoGhostGang => vec![Web3Network::Ethereum], + Self::Club3Sbt => vec![Web3Network::Bsc, Web3Network::Polygon, Web3Network::Arbitrum], + } + } +} diff --git a/primitives/teeracle/Cargo.toml b/primitives/teeracle/Cargo.toml deleted file mode 100644 index 83b443bf43..0000000000 --- a/primitives/teeracle/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -authors = ['Trust Computing GmbH '] -edition = "2021" -homepage = 'https://litentry.com/' -license = "Apache-2.0" -name = "teeracle-primitives" -repository = 'https://github.com/litentry/litentry-parachain' -version = "0.1.0" - -[dependencies] -# local -common-primitives = { path = "../common", default-features = false } - -# encointer -substrate-fixed = { tag = "v0.5.9", default-features = false, git = "https://github.com/encointer/substrate-fixed.git" } - - -[features] -default = ["std"] -std = [ - "common-primitives/std", - "substrate-fixed/std", -] diff --git a/primitives/teeracle/src/lib.rs b/primitives/teeracle/src/lib.rs deleted file mode 100644 index e9f7f6d808..0000000000 --- a/primitives/teeracle/src/lib.rs +++ /dev/null @@ -1,12 +0,0 @@ -//!Primitives for teeracle -#![cfg_attr(not(feature = "std"), no_std)] -use common_primitives::PalletString; -use substrate_fixed::types::U32F32; - -pub const MAX_ORACLE_DATA_NAME_LEN: usize = 40; - -pub type ExchangeRate = U32F32; -pub type TradingPairString = PalletString; -pub type MarketDataSourceString = PalletString; -pub type OracleDataName = PalletString; -pub type DataSource = PalletString; diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 73ad2c4b6c..3e44be3b92 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -47,6 +47,7 @@ core-primitives = { path = "../../primitives/core", default-features = false } pallet-asset-manager = { path = "../../pallets/xcm-asset-manager", default-features = false } pallet-extrinsic-filter = { path = "../../pallets/extrinsic-filter", default-features = false } pallet-group = { path = "../../pallets/group", default-features = false } +pallet-teebag = { path = "../../pallets/teebag", default-features = false } pallet-teerex = { path = "../../pallets/teerex", default-features = false } teerex-primitives = { path = "../../primitives/teerex", default-features = false, optional = true } @@ -97,6 +98,7 @@ std = [ "core-primitives/std", "pallet-teerex/std", "teerex-primitives?/std", + "pallet-teebag/std", ] runtime-benchmarks = [ @@ -104,6 +106,7 @@ runtime-benchmarks = [ "pallet-teerex/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "teerex-primitives", + "pallet-teebag/runtime-benchmarks", "test-utils", "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks", diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 0297efb21a..c6161535ee 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -338,7 +338,7 @@ where pub struct EnsureEnclaveSigner(PhantomData); impl EnsureOrigin for EnsureEnclaveSigner where - T: frame_system::Config + pallet_teerex::Config, + T: frame_system::Config + pallet_teebag::Config + pallet_teebag::Config, ::AccountId: From<[u8; 32]>, ::Hash: From<[u8; 32]>, { @@ -346,7 +346,7 @@ where fn try_origin(o: T::RuntimeOrigin) -> Result { o.into().and_then(|o| match o { frame_system::RawOrigin::Signed(who) - if pallet_teerex::Pallet::::ensure_registered_enclave(&who) == Ok(()) => + if pallet_teebag::EnclaveRegistry::::contains_key(&who) => Ok(who), r => Err(T::RuntimeOrigin::from(r)), }) @@ -354,23 +354,12 @@ where #[cfg(feature = "runtime-benchmarks")] fn try_successful_origin() -> Result { - use test_utils::ias::{ - consts::{TEST8_MRENCLAVE, TEST8_SIGNER_PUB}, - TestEnclave, - }; - // The below is the hardcode TEST8_SIGNER_PUB. We should save it for convenience. - // let TEST8_SIGNER_PUB_DIRECT: [u8; 32] = [ - // 54, 176, 127, 194, 139, 9, 249, 13, 217, 106, 6, 124, 75, 0, 109, 18, 202, 202, 240, - // 124, 214, 235, 255, 249, 47, 135, 174, 246, 167, 5, 6, 224, - // ]; + use test_utils::ias::consts::{TEST8_MRENCLAVE, TEST8_SIGNER_PUB}; let signer: ::AccountId = test_utils::get_signer(TEST8_SIGNER_PUB); - if !pallet_teerex::EnclaveIndex::::contains_key(signer.clone()) { - assert_ok!(pallet_teerex::Pallet::::add_enclave( - &signer, - &teerex_primitives::Enclave::test_enclave(signer.clone()) - .with_mr_enclave(TEST8_MRENCLAVE), - )); + let enclave = pallet_teebag::Enclave::default().with_mrenclave(TEST8_MRENCLAVE); + if !pallet_teebag::EnclaveRegistry::::contains_key(signer.clone()) { + assert_ok!(pallet_teebag::Pallet::::add_enclave(&signer, &enclave)); } Ok(frame_system::RawOrigin::Signed(signer).into()) } diff --git a/runtime/litentry/src/lib.rs b/runtime/litentry/src/lib.rs index 7158892b06..9be9cf7a2a 100644 --- a/runtime/litentry/src/lib.rs +++ b/runtime/litentry/src/lib.rs @@ -142,7 +142,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("litentry-parachain"), authoring_version: 1, // same versioning-mechanism as polkadot: use last digit for minor updates - spec_version: 9173, + spec_version: 9174, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -837,20 +837,6 @@ impl pallet_bridge_transfer::Config for Runtime { type WeightInfo = weights::pallet_bridge_transfer::WeightInfo; } -parameter_types! { - pub const SlashPercent: Percent = Percent::from_percent(20); -} - -impl pallet_drop3::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type PoolId = u64; - type SetAdminOrigin = EnsureRootOrHalfCouncil; - type Currency = Balances; - type WeightInfo = weights::pallet_drop3::WeightInfo; - type SlashPercent = SlashPercent; - type MaximumNameLength = ConstU32<16>; -} - impl pallet_extrinsic_filter::Config for Runtime { type RuntimeEvent = RuntimeEvent; type UpdateOrigin = EnsureRootOrHalfTechnicalCommittee; @@ -928,7 +914,6 @@ construct_runtime! { // Litentry pallets ChainBridge: pallet_bridge = 60, BridgeTransfer: pallet_bridge_transfer = 61, - Drop3: pallet_drop3 = 62, ExtrinsicFilter: pallet_extrinsic_filter = 63, AssetManager: pallet_asset_manager = 64, @@ -1017,7 +1002,6 @@ mod benches { [pallet_proxy, Proxy] [pallet_membership, CouncilMembership] [pallet_multisig, Multisig] - [pallet_drop3, Drop3] [pallet_extrinsic_filter, ExtrinsicFilter] [pallet_scheduler, Scheduler] [pallet_preimage, Preimage] diff --git a/runtime/litentry/src/weights/mod.rs b/runtime/litentry/src/weights/mod.rs index 91e65a5b49..ac1f92c554 100644 --- a/runtime/litentry/src/weights/mod.rs +++ b/runtime/litentry/src/weights/mod.rs @@ -24,7 +24,6 @@ pub mod pallet_bridge; pub mod pallet_bridge_transfer; pub mod pallet_collective; pub mod pallet_democracy; -pub mod pallet_drop3; pub mod pallet_extrinsic_filter; pub mod pallet_identity; pub mod pallet_membership; diff --git a/runtime/litentry/src/weights/pallet_drop3.rs b/runtime/litentry/src/weights/pallet_drop3.rs deleted file mode 100644 index 3cbc4782e4..0000000000 --- a/runtime/litentry/src/weights/pallet_drop3.rs +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -//! Autogenerated weights for `pallet_drop3` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-17, STEPS: `20`, REPEAT: `50`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `parachain-benchmark`, CPU: `Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("litentry-dev"), DB CACHE: 20 - -// Executed Command: -// ./litentry-collator -// benchmark -// pallet -// --chain=litentry-dev -// --execution=wasm -// --db-cache=20 -// --wasm-execution=compiled -// --pallet=pallet_drop3 -// --extrinsic=* -// --heap-pages=4096 -// --steps=20 -// --repeat=50 -// --header=./LICENSE_HEADER -// --output=./runtime/litentry/src/weights/pallet_drop3.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_drop3`. -pub struct WeightInfo(PhantomData); -impl pallet_drop3::WeightInfo for WeightInfo { - /// Storage: Drop3 Admin (r:1 w:1) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn set_admin() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `1489` - // Minimum execution time: 13_718_000 picoseconds. - Weight::from_parts(14_166_000, 0) - .saturating_add(Weight::from_parts(0, 1489)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - fn approve_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 22_750_000 picoseconds. - Weight::from_parts(23_174_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - fn reject_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `365` - // Estimated: `3830` - // Minimum execution time: 72_798_000 picoseconds. - Weight::from_parts(73_833_000, 0) - .saturating_add(Weight::from_parts(0, 3830)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn start_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 22_765_000 picoseconds. - Weight::from_parts(23_419_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn stop_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 22_772_000 picoseconds. - Weight::from_parts(25_459_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - fn close_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `365` - // Estimated: `3830` - // Minimum execution time: 46_124_000 picoseconds. - Weight::from_parts(47_229_000, 0) - .saturating_add(Weight::from_parts(0, 3830)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 CurrentMaxPoolId (r:1 w:1) - /// Proof Skipped: Drop3 CurrentMaxPoolId (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:0 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// The range of component `n` is `[0, 16]`. - fn propose_reward_pool(_n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `105` - // Estimated: `3593` - // Minimum execution time: 41_888_000 picoseconds. - Weight::from_parts(43_378_625, 0) - .saturating_add(Weight::from_parts(0, 3593)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(4)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn send_reward() -> Weight { - // Proof Size summary in bytes: - // Measured: `449` - // Estimated: `6196` - // Minimum execution time: 49_512_000 picoseconds. - Weight::from_parts(50_424_000, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } -} diff --git a/runtime/litmus/Cargo.toml b/runtime/litmus/Cargo.toml index d69d3b9d9a..8276559faf 100644 --- a/runtime/litmus/Cargo.toml +++ b/runtime/litmus/Cargo.toml @@ -96,7 +96,6 @@ runtime-common = { path = '../common', default-features = false } # TEE pallets pallet-group = { path = "../../pallets/group", default-features = false } pallet-sidechain = { path = "../../pallets/sidechain", default-features = false } -pallet-teeracle = { path = "../../pallets/teeracle", default-features = false } pallet-teerex = { path = "../../pallets/teerex", default-features = false } [dev-dependencies] @@ -149,7 +148,6 @@ runtime-benchmarks = [ "pallet-identity-management/runtime-benchmarks", "pallet-teerex/runtime-benchmarks", "pallet-sidechain/runtime-benchmarks", - "pallet-teeracle/runtime-benchmarks", "pallet-vc-management/runtime-benchmarks", ] std = [ @@ -223,7 +221,6 @@ std = [ "pallet-identity-management/std", "pallet-teerex/std", "pallet-sidechain/std", - "pallet-teeracle/std", "pallet-vc-management/std", ] try-runtime = [ @@ -259,7 +256,6 @@ try-runtime = [ "pallet-scheduler/try-runtime", "pallet-session/try-runtime", "pallet-sidechain/try-runtime", - "pallet-teeracle/try-runtime", "pallet-teerex/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", diff --git a/runtime/litmus/src/lib.rs b/runtime/litmus/src/lib.rs index add4b7349d..a9e4b9d472 100644 --- a/runtime/litmus/src/lib.rs +++ b/runtime/litmus/src/lib.rs @@ -40,7 +40,6 @@ use hex_literal::hex; // for TEE pub use pallet_balances::Call as BalancesCall; pub use pallet_sidechain; -pub use pallet_teeracle; pub use pallet_teerex; use sp_api::impl_runtime_apis; @@ -151,7 +150,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("litmus-parachain"), authoring_version: 1, // same versioning-mechanism as polkadot: use last digit for minor updates - spec_version: 9172, + spec_version: 9174, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -778,20 +777,6 @@ impl pallet_bridge_transfer::Config for Runtime { type WeightInfo = weights::pallet_bridge_transfer::WeightInfo; } -parameter_types! { - pub const SlashPercent: Percent = Percent::from_percent(20); -} - -impl pallet_drop3::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type PoolId = u64; - type SetAdminOrigin = EnsureRootOrHalfCouncil; - type Currency = Balances; - type WeightInfo = weights::pallet_drop3::WeightInfo; - type SlashPercent = SlashPercent; - type MaximumNameLength = ConstU32<16>; -} - impl pallet_extrinsic_filter::Config for Runtime { type RuntimeEvent = RuntimeEvent; type UpdateOrigin = EnsureRootOrHalfTechnicalCommittee; @@ -820,13 +805,6 @@ impl pallet_sidechain::Config for Runtime { type WeightInfo = weights::pallet_sidechain::WeightInfo; } -impl pallet_teeracle::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = weights::pallet_teeracle::WeightInfo; - type MaxWhitelistedReleases = ConstU32<10>; - type MaxOracleBlobLen = ConstU32<4096>; -} - impl runtime_common::BaseRuntimeRequirements for Runtime {} impl runtime_common::ParaRuntimeRequirements for Runtime {} @@ -894,14 +872,12 @@ construct_runtime! { // Litmus pallets ChainBridge: pallet_bridge = 60, BridgeTransfer: pallet_bridge_transfer = 61, - Drop3: pallet_drop3 = 62, ExtrinsicFilter: pallet_extrinsic_filter = 63, AssetManager: pallet_asset_manager = 65, // TEE Teerex: pallet_teerex = 90, Sidechain: pallet_sidechain = 91, - Teeracle: pallet_teeracle = 92, } } @@ -984,7 +960,6 @@ mod benches { [pallet_proxy, Proxy] [pallet_membership, CouncilMembership] [pallet_multisig, Multisig] - [pallet_drop3, Drop3] [pallet_extrinsic_filter, ExtrinsicFilter] [pallet_scheduler, Scheduler] [pallet_preimage, Preimage] @@ -994,7 +969,6 @@ mod benches { [cumulus_pallet_xcmp_queue, XcmpQueue] [pallet_teerex, Teerex] [pallet_sidechain, Sidechain] - [pallet_teeracle, Teeracle] [pallet_bridge,ChainBridge] [pallet_bridge_transfer,BridgeTransfer] ); diff --git a/runtime/litmus/src/weights/mod.rs b/runtime/litmus/src/weights/mod.rs index 4dd3450d13..44a01085d1 100644 --- a/runtime/litmus/src/weights/mod.rs +++ b/runtime/litmus/src/weights/mod.rs @@ -25,7 +25,6 @@ pub mod pallet_bridge_transfer; pub mod pallet_collator_selection; pub mod pallet_collective; pub mod pallet_democracy; -pub mod pallet_drop3; pub mod pallet_extrinsic_filter; pub mod pallet_identity; pub mod pallet_membership; @@ -35,7 +34,6 @@ pub mod pallet_proxy; pub mod pallet_scheduler; pub mod pallet_session; pub mod pallet_sidechain; -pub mod pallet_teeracle; pub mod pallet_teerex; pub mod pallet_timestamp; pub mod pallet_treasury; diff --git a/runtime/litmus/src/weights/pallet_drop3.rs b/runtime/litmus/src/weights/pallet_drop3.rs deleted file mode 100644 index 222c028456..0000000000 --- a/runtime/litmus/src/weights/pallet_drop3.rs +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -//! Autogenerated weights for `pallet_drop3` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-17, STEPS: `20`, REPEAT: `50`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `parachain-benchmark`, CPU: `Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("litmus-dev"), DB CACHE: 20 - -// Executed Command: -// ./litentry-collator -// benchmark -// pallet -// --chain=litmus-dev -// --execution=wasm -// --db-cache=20 -// --wasm-execution=compiled -// --pallet=pallet_drop3 -// --extrinsic=* -// --heap-pages=4096 -// --steps=20 -// --repeat=50 -// --header=./LICENSE_HEADER -// --output=./runtime/litmus/src/weights/pallet_drop3.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_drop3`. -pub struct WeightInfo(PhantomData); -impl pallet_drop3::WeightInfo for WeightInfo { - /// Storage: Drop3 Admin (r:1 w:1) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn set_admin() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `1489` - // Minimum execution time: 13_429_000 picoseconds. - Weight::from_parts(14_049_000, 0) - .saturating_add(Weight::from_parts(0, 1489)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - fn approve_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 22_492_000 picoseconds. - Weight::from_parts(23_602_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - fn reject_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `365` - // Estimated: `3830` - // Minimum execution time: 72_618_000 picoseconds. - Weight::from_parts(73_440_000, 0) - .saturating_add(Weight::from_parts(0, 3830)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn start_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 22_769_000 picoseconds. - Weight::from_parts(23_335_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn stop_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 22_458_000 picoseconds. - Weight::from_parts(22_907_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - fn close_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `365` - // Estimated: `3830` - // Minimum execution time: 45_729_000 picoseconds. - Weight::from_parts(46_801_000, 0) - .saturating_add(Weight::from_parts(0, 3830)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 CurrentMaxPoolId (r:1 w:1) - /// Proof Skipped: Drop3 CurrentMaxPoolId (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:0 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// The range of component `n` is `[0, 16]`. - fn propose_reward_pool(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `105` - // Estimated: `3593` - // Minimum execution time: 40_985_000 picoseconds. - Weight::from_parts(42_517_928, 0) - .saturating_add(Weight::from_parts(0, 3593)) - // Standard Error: 9_347 - .saturating_add(Weight::from_parts(31_854, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(4)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn send_reward() -> Weight { - // Proof Size summary in bytes: - // Measured: `449` - // Estimated: `6196` - // Minimum execution time: 48_658_000 picoseconds. - Weight::from_parts(49_698_000, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } -} diff --git a/runtime/litmus/src/weights/pallet_teeracle.rs b/runtime/litmus/src/weights/pallet_teeracle.rs deleted file mode 100644 index d0ff0ba31b..0000000000 --- a/runtime/litmus/src/weights/pallet_teeracle.rs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -//! Autogenerated weights for `pallet_teeracle` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-17, STEPS: `20`, REPEAT: `50`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `parachain-benchmark`, CPU: `Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("litmus-dev"), DB CACHE: 20 - -// Executed Command: -// ./litentry-collator -// benchmark -// pallet -// --chain=litmus-dev -// --execution=wasm -// --db-cache=20 -// --wasm-execution=compiled -// --pallet=pallet_teeracle -// --extrinsic=* -// --heap-pages=4096 -// --steps=20 -// --repeat=50 -// --header=./LICENSE_HEADER -// --output=./runtime/litmus/src/weights/pallet_teeracle.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_teeracle`. -pub struct WeightInfo(PhantomData); -impl pallet_teeracle::WeightInfo for WeightInfo { - /// Storage: Teerex EnclaveIndex (r:1 w:0) - /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Teerex EnclaveRegistry (r:1 w:0) - /// Proof Skipped: Teerex EnclaveRegistry (max_values: None, max_size: None, mode: Measured) - /// Storage: Teeracle Whitelists (r:1 w:0) - /// Proof Skipped: Teeracle Whitelists (max_values: None, max_size: None, mode: Measured) - /// Storage: Teeracle ExchangeRates (r:1 w:1) - /// Proof Skipped: Teeracle ExchangeRates (max_values: None, max_size: None, mode: Measured) - fn update_exchange_rate() -> Weight { - // Proof Size summary in bytes: - // Measured: `3401` - // Estimated: `6866` - // Minimum execution time: 46_610_000 picoseconds. - Weight::from_parts(48_666_000, 0) - .saturating_add(Weight::from_parts(0, 6866)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Teerex EnclaveIndex (r:1 w:0) - /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Teerex EnclaveRegistry (r:1 w:0) - /// Proof Skipped: Teerex EnclaveRegistry (max_values: None, max_size: None, mode: Measured) - /// Storage: Teeracle Whitelists (r:1 w:0) - /// Proof Skipped: Teeracle Whitelists (max_values: None, max_size: None, mode: Measured) - /// Storage: Teeracle OracleData (r:0 w:1) - /// Proof Skipped: Teeracle OracleData (max_values: None, max_size: None, mode: Measured) - fn update_oracle() -> Weight { - // Proof Size summary in bytes: - // Measured: `3392` - // Estimated: `6857` - // Minimum execution time: 40_934_000 picoseconds. - Weight::from_parts(42_127_000, 0) - .saturating_add(Weight::from_parts(0, 6857)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Teeracle Whitelists (r:1 w:1) - /// Proof Skipped: Teeracle Whitelists (max_values: None, max_size: None, mode: Measured) - fn add_to_whitelist() -> Weight { - // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `3607` - // Minimum execution time: 18_686_000 picoseconds. - Weight::from_parts(19_223_000, 0) - .saturating_add(Weight::from_parts(0, 3607)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Teeracle Whitelists (r:1 w:1) - /// Proof Skipped: Teeracle Whitelists (max_values: None, max_size: None, mode: Measured) - fn remove_from_whitelist() -> Weight { - // Proof Size summary in bytes: - // Measured: `244` - // Estimated: `3709` - // Minimum execution time: 20_760_000 picoseconds. - Weight::from_parts(21_141_000, 0) - .saturating_add(Weight::from_parts(0, 3709)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/runtime/rococo/Cargo.toml b/runtime/rococo/Cargo.toml index e5593685ef..4b2a9d896c 100644 --- a/runtime/rococo/Cargo.toml +++ b/runtime/rococo/Cargo.toml @@ -88,6 +88,7 @@ frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", d # Rococo pallets pallet-account-fix = { path = "../../pallets/account-fix", default-features = false } pallet-asset-manager = { path = "../../pallets/xcm-asset-manager", default-features = false } +pallet-bitacross = { path = "../../pallets/bitacross", default-features = false } pallet-bridge = { path = "../../pallets/bridge", default-features = false } pallet-bridge-transfer = { path = "../../pallets/bridge-transfer", default-features = false } pallet-drop3 = { path = "../../pallets/drop3", default-features = false } @@ -100,7 +101,7 @@ runtime-common = { path = '../common', default-features = false } # TEE pallets pallet-group = { path = "../../pallets/group", default-features = false } pallet-sidechain = { path = "../../pallets/sidechain", default-features = false } -pallet-teeracle = { path = "../../pallets/teeracle", default-features = false } +pallet-teebag = { path = "../../pallets/teebag", default-features = false } pallet-teerex = { path = "../../pallets/teerex", default-features = false } # EVM/Frontier @@ -177,8 +178,8 @@ runtime-benchmarks = [ "pallet-group/runtime-benchmarks", "pallet-identity-management/runtime-benchmarks", "pallet-teerex/runtime-benchmarks", + "pallet-teebag/runtime-benchmarks", "pallet-sidechain/runtime-benchmarks", - "pallet-teeracle/runtime-benchmarks", "pallet-vc-management/runtime-benchmarks", "pallet-account-fix/runtime-benchmarks", ] @@ -267,13 +268,14 @@ std = [ "pallet-group/std", "pallet-identity-management/std", "pallet-teerex/std", + "pallet-teebag/std", "pallet-sidechain/std", - "pallet-teeracle/std", "pallet-vc-management/std", "pallet-account-fix/std", "moonbeam-evm-tracer/std", "moonbeam-rpc-primitives-debug/std", "moonbeam-rpc-primitives-txpool/std", + "pallet-bitacross/std", ] tee-dev = [ "pallet-teerex/skip-ias-check", @@ -315,8 +317,8 @@ try-runtime = [ "pallet-session/try-runtime", "pallet-sidechain/try-runtime", "pallet-sudo/try-runtime", - "pallet-teeracle/try-runtime", "pallet-teerex/try-runtime", + "pallet-teebag/try-runtime", "pallet-timestamp/try-runtime", "pallet-tips/try-runtime", "pallet-transaction-payment/try-runtime", @@ -327,4 +329,5 @@ try-runtime = [ "pallet-xcm/try-runtime", "parachain-info/try-runtime", "pallet-account-fix/try-runtime", + "pallet-bitacross/try-runtime", ] diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index 069c4fa555..608107e2ad 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -17,7 +17,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::identity_op)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. -#![recursion_limit = "256"] +#![recursion_limit = "512"] #[cfg(feature = "runtime-benchmarks")] #[macro_use] @@ -41,7 +41,7 @@ use runtime_common::EnsureEnclaveSigner; // for TEE pub use pallet_balances::Call as BalancesCall; pub use pallet_sidechain; -pub use pallet_teeracle; +pub use pallet_teebag::{self, OperationalMode as TeebagOperationalMode}; pub use pallet_teerex; use sp_api::impl_runtime_apis; @@ -245,7 +245,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { impl_name: create_runtime_str!("rococo-parachain"), authoring_version: 1, // same versioning-mechanism as polkadot: use last digit for minor updates - spec_version: 9173, + spec_version: 9174, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1, @@ -968,20 +968,6 @@ impl pallet_bridge_transfer::Config for Runtime { type WeightInfo = weights::pallet_bridge_transfer::WeightInfo; } -parameter_types! { - pub const SlashPercent: Percent = Percent::from_percent(20); -} - -impl pallet_drop3::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type PoolId = u64; - type SetAdminOrigin = EnsureRootOrHalfCouncil; - type Currency = Balances; - type WeightInfo = weights::pallet_drop3::WeightInfo; - type SlashPercent = SlashPercent; - type MaximumNameLength = ConstU32<16>; -} - impl pallet_extrinsic_filter::Config for Runtime { type RuntimeEvent = RuntimeEvent; type UpdateOrigin = EnsureRootOrHalfTechnicalCommittee; @@ -1017,11 +1003,11 @@ impl pallet_sidechain::Config for Runtime { type WeightInfo = weights::pallet_sidechain::WeightInfo; } -impl pallet_teeracle::Config for Runtime { +impl pallet_teebag::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = weights::pallet_teeracle::WeightInfo; - type MaxWhitelistedReleases = ConstU32<10>; - type MaxOracleBlobLen = ConstU32<4096>; + type MomentsPerDay = MomentsPerDay; + type SetAdminOrigin = EnsureRootOrHalfCouncil; + type MaxEnclaveIdentifier = ConstU32<3>; } impl pallet_identity_management::Config for Runtime { @@ -1032,6 +1018,12 @@ impl pallet_identity_management::Config for Runtime { type ExtrinsicWhitelistOrigin = IMPExtrinsicWhitelist; } +impl pallet_bitacross::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type TEECallOrigin = EnsureEnclaveSigner; + type SetAdminOrigin = EnsureRootOrAllCouncil; +} + impl pallet_group::Config for Runtime { type RuntimeEvent = RuntimeEvent; type GroupManagerOrigin = EnsureRootOrAllCouncil; @@ -1243,18 +1235,18 @@ construct_runtime! { // Rococo pallets ChainBridge: pallet_bridge = 60, BridgeTransfer: pallet_bridge_transfer = 61, - Drop3: pallet_drop3 = 62, ExtrinsicFilter: pallet_extrinsic_filter = 63, IdentityManagement: pallet_identity_management = 64, AssetManager: pallet_asset_manager = 65, VCManagement: pallet_vc_management = 66, IMPExtrinsicWhitelist: pallet_group:: = 67, VCMPExtrinsicWhitelist: pallet_group:: = 68, + Bitacross: pallet_bitacross = 70, // TEE Teerex: pallet_teerex = 90, Sidechain: pallet_sidechain = 91, - Teeracle: pallet_teeracle = 92, + Teebag: pallet_teebag = 93, // Frontier EVM: pallet_evm = 120, @@ -1331,7 +1323,7 @@ impl Contains for NormalModeFilter { // TEE pallets RuntimeCall::Teerex(_) | RuntimeCall::Sidechain(_) | - RuntimeCall::Teeracle(_) | + RuntimeCall::Teebag(_) | // ParachainStaking; Only the collator part RuntimeCall::ParachainStaking(pallet_parachain_staking::Call::join_candidates { .. }) | RuntimeCall::ParachainStaking(pallet_parachain_staking::Call::schedule_leave_candidates { .. }) | @@ -1351,7 +1343,8 @@ impl Contains for NormalModeFilter { // So no EVM pallet RuntimeCall::Ethereum(_) | // AccountFix - RuntimeCall::AccountFix(_) + RuntimeCall::AccountFix(_) | + RuntimeCall::Bitacross(_) ) } } @@ -1370,7 +1363,6 @@ mod benches { [pallet_proxy, Proxy] [pallet_membership, CouncilMembership] [pallet_multisig, Multisig] - [pallet_drop3, Drop3] [paleet_evm, EVM] [pallet_extrinsic_filter, ExtrinsicFilter] [pallet_scheduler, Scheduler] @@ -1382,7 +1374,6 @@ mod benches { [pallet_vc_management, VCManagement] [pallet_teerex, Teerex] [pallet_sidechain, Sidechain] - [pallet_teeracle, Teeracle] [pallet_bridge,ChainBridge] [pallet_bridge_transfer,BridgeTransfer] ); diff --git a/runtime/rococo/src/weights/mod.rs b/runtime/rococo/src/weights/mod.rs index 47af2c4cc6..7e857c9a81 100644 --- a/runtime/rococo/src/weights/mod.rs +++ b/runtime/rococo/src/weights/mod.rs @@ -24,7 +24,6 @@ pub mod pallet_bridge; pub mod pallet_bridge_transfer; pub mod pallet_collective; pub mod pallet_democracy; -pub mod pallet_drop3; pub mod pallet_evm; pub mod pallet_extrinsic_filter; pub mod pallet_identity; @@ -37,7 +36,6 @@ pub mod pallet_proxy; pub mod pallet_scheduler; pub mod pallet_session; pub mod pallet_sidechain; -pub mod pallet_teeracle; pub mod pallet_teerex; pub mod pallet_timestamp; pub mod pallet_treasury; diff --git a/runtime/rococo/src/weights/pallet_drop3.rs b/runtime/rococo/src/weights/pallet_drop3.rs deleted file mode 100644 index 4a9cbee7ca..0000000000 --- a/runtime/rococo/src/weights/pallet_drop3.rs +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -//! Autogenerated weights for `pallet_drop3` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-17, STEPS: `20`, REPEAT: `50`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `parachain-benchmark`, CPU: `Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 20 - -// Executed Command: -// ./litentry-collator -// benchmark -// pallet -// --chain=rococo-dev -// --execution=wasm -// --db-cache=20 -// --wasm-execution=compiled -// --pallet=pallet_drop3 -// --extrinsic=* -// --heap-pages=4096 -// --steps=20 -// --repeat=50 -// --header=./LICENSE_HEADER -// --output=./runtime/rococo/src/weights/pallet_drop3.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_drop3`. -pub struct WeightInfo(PhantomData); -impl pallet_drop3::WeightInfo for WeightInfo { - /// Storage: Drop3 Admin (r:1 w:1) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn set_admin() -> Weight { - // Proof Size summary in bytes: - // Measured: `4` - // Estimated: `1489` - // Minimum execution time: 14_412_000 picoseconds. - Weight::from_parts(14_711_000, 0) - .saturating_add(Weight::from_parts(0, 1489)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - fn approve_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 22_259_000 picoseconds. - Weight::from_parts(22_808_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - fn reject_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `365` - // Estimated: `3830` - // Minimum execution time: 71_555_000 picoseconds. - Weight::from_parts(72_466_000, 0) - .saturating_add(Weight::from_parts(0, 3830)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn start_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 22_465_000 picoseconds. - Weight::from_parts(22_907_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - fn stop_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 21_132_000 picoseconds. - Weight::from_parts(21_632_000, 0) - .saturating_add(Weight::from_parts(0, 3729)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 Admin (r:1 w:0) - /// Proof Skipped: Drop3 Admin (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - fn close_reward_pool() -> Weight { - // Proof Size summary in bytes: - // Measured: `365` - // Estimated: `3830` - // Minimum execution time: 44_315_000 picoseconds. - Weight::from_parts(45_012_000, 0) - .saturating_add(Weight::from_parts(0, 3830)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: Drop3 CurrentMaxPoolId (r:1 w:1) - /// Proof Skipped: Drop3 CurrentMaxPoolId (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Drop3 RewardPoolOwners (r:0 w:1) - /// Proof Skipped: Drop3 RewardPoolOwners (max_values: None, max_size: None, mode: Measured) - /// Storage: Drop3 RewardPools (r:0 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// The range of component `n` is `[0, 16]`. - fn propose_reward_pool(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `105` - // Estimated: `3593` - // Minimum execution time: 40_590_000 picoseconds. - Weight::from_parts(41_673_286, 0) - .saturating_add(Weight::from_parts(0, 3593)) - // Standard Error: 10_395 - .saturating_add(Weight::from_parts(154_934, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(4)) - } - /// Storage: Drop3 RewardPools (r:1 w:1) - /// Proof Skipped: Drop3 RewardPools (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn send_reward() -> Weight { - // Proof Size summary in bytes: - // Measured: `449` - // Estimated: `6196` - // Minimum execution time: 48_032_000 picoseconds. - Weight::from_parts(50_660_000, 0) - .saturating_add(Weight::from_parts(0, 6196)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } -} diff --git a/runtime/rococo/src/weights/pallet_teeracle.rs b/runtime/rococo/src/weights/pallet_teeracle.rs deleted file mode 100644 index f38318ebb8..0000000000 --- a/runtime/rococo/src/weights/pallet_teeracle.rs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -//! Autogenerated weights for `pallet_teeracle` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-10-17, STEPS: `20`, REPEAT: `50`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `parachain-benchmark`, CPU: `Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("rococo-dev"), DB CACHE: 20 - -// Executed Command: -// ./litentry-collator -// benchmark -// pallet -// --chain=rococo-dev -// --execution=wasm -// --db-cache=20 -// --wasm-execution=compiled -// --pallet=pallet_teeracle -// --extrinsic=* -// --heap-pages=4096 -// --steps=20 -// --repeat=50 -// --header=./LICENSE_HEADER -// --output=./runtime/rococo/src/weights/pallet_teeracle.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::Weight}; -use core::marker::PhantomData; - -/// Weight functions for `pallet_teeracle`. -pub struct WeightInfo(PhantomData); -impl pallet_teeracle::WeightInfo for WeightInfo { - /// Storage: Teerex EnclaveIndex (r:1 w:0) - /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Teerex EnclaveRegistry (r:1 w:0) - /// Proof Skipped: Teerex EnclaveRegistry (max_values: None, max_size: None, mode: Measured) - /// Storage: Teeracle Whitelists (r:1 w:0) - /// Proof Skipped: Teeracle Whitelists (max_values: None, max_size: None, mode: Measured) - /// Storage: Teeracle ExchangeRates (r:1 w:1) - /// Proof Skipped: Teeracle ExchangeRates (max_values: None, max_size: None, mode: Measured) - fn update_exchange_rate() -> Weight { - // Proof Size summary in bytes: - // Measured: `3401` - // Estimated: `6866` - // Minimum execution time: 48_341_000 picoseconds. - Weight::from_parts(57_660_000, 0) - .saturating_add(Weight::from_parts(0, 6866)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Teerex EnclaveIndex (r:1 w:0) - /// Proof Skipped: Teerex EnclaveIndex (max_values: None, max_size: None, mode: Measured) - /// Storage: Teerex EnclaveRegistry (r:1 w:0) - /// Proof Skipped: Teerex EnclaveRegistry (max_values: None, max_size: None, mode: Measured) - /// Storage: Teeracle Whitelists (r:1 w:0) - /// Proof Skipped: Teeracle Whitelists (max_values: None, max_size: None, mode: Measured) - /// Storage: Teeracle OracleData (r:0 w:1) - /// Proof Skipped: Teeracle OracleData (max_values: None, max_size: None, mode: Measured) - fn update_oracle() -> Weight { - // Proof Size summary in bytes: - // Measured: `3392` - // Estimated: `6857` - // Minimum execution time: 41_386_000 picoseconds. - Weight::from_parts(42_413_000, 0) - .saturating_add(Weight::from_parts(0, 6857)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Teeracle Whitelists (r:1 w:1) - /// Proof Skipped: Teeracle Whitelists (max_values: None, max_size: None, mode: Measured) - fn add_to_whitelist() -> Weight { - // Proof Size summary in bytes: - // Measured: `142` - // Estimated: `3607` - // Minimum execution time: 18_800_000 picoseconds. - Weight::from_parts(19_354_000, 0) - .saturating_add(Weight::from_parts(0, 3607)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: Teeracle Whitelists (r:1 w:1) - /// Proof Skipped: Teeracle Whitelists (max_values: None, max_size: None, mode: Measured) - fn remove_from_whitelist() -> Weight { - // Proof Size summary in bytes: - // Measured: `244` - // Estimated: `3709` - // Minimum execution time: 21_200_000 picoseconds. - Weight::from_parts(21_772_000, 0) - .saturating_add(Weight::from_parts(0, 3709)) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } -} diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh index beec0ab4a9..7d8c45ee59 100755 --- a/scripts/pre-commit.sh +++ b/scripts/pre-commit.sh @@ -8,7 +8,11 @@ function worker_clippy() { cargo clippy --release -- -D warnings cargo clippy --release --features evm -- -D warnings cargo clippy --release --features sidechain -- -D warnings - cargo clippy --release --features teeracle -- -D warnings + cargo clippy --release --features offchain-worker -- -D warnings +} + +function bitacross_clippy() { + cargo clippy --release -- -D warnings cargo clippy --release --features offchain-worker -- -D warnings } @@ -62,10 +66,10 @@ cd "$root_dir/tee-worker/bin" ./litentry-worker test --all echo "[Step 6], bitacross-worker clippy" -cd "$root_dir/bitacross-worker" && worker_clippy +cd "$root_dir/bitacross-worker" && bitacross_clippy echo "[Step 7], bitacross-worker enclave clippy" -cd "$root_dir/bitacross-worker/enclave-runtime" && worker_clippy +cd "$root_dir/bitacross-worker/enclave-runtime" && bitacross_clippy echo "[Step 8], bitacross-worker cargo test" cd "$root_dir/bitacross-worker" diff --git a/scripts/ts-utils/setup-enclave.ts b/scripts/ts-utils/setup-enclave.ts index f4e989c358..829ce280a7 100644 --- a/scripts/ts-utils/setup-enclave.ts +++ b/scripts/ts-utils/setup-enclave.ts @@ -31,11 +31,11 @@ async function transfer(api: any, Alice: any) { }); }); } -async function setTeerexAdmin(api: any, Alice: any) { +async function teebagSetAdmin(api: any, Alice: any) { return new Promise(async (resolve, reject) => { // Note: The hardcoded address is that of Alice on dev chain await api.tx.sudo - .sudo(api.tx.teerex.setAdmin("esqZdrqhgH8zy1wqYh1aLKoRyoRWLFbX9M62eKfaTAoK67pJ5")) + .sudo(api.tx.teebag.setAdmin("esqZdrqhgH8zy1wqYh1aLKoRyoRWLFbX9M62eKfaTAoK67pJ5")) .signAndSend(Alice, ({ status, events, dispatchError }) => { if (status.isInBlock || status.isFinalized) { if (dispatchError) { @@ -47,23 +47,23 @@ async function setTeerexAdmin(api: any, Alice: any) { const { docs, name, section } = decoded; console.log(colors.red(`${section}.${name}: ${docs.join(" ")}`)); - reject("updateScheduledEnclave failed"); + reject("teebag.setAdmin failed"); } else { // Other, CannotLookup, BadOrigin, no extra info console.log(dispatchError.toString()); - reject("updateScheduledEnclave failed"); + reject("teebag.setAdmin failed"); } } else { - console.log(colors.green("updateScheduledEnclave completed")); - resolve("updateScheduledEnclave done"); + console.log(colors.green("teebag.setAdmin completed")); + resolve("teebag.setAdmin done"); } } }); }); } -async function updateScheduledEnclave(api: any, Alice: any, block: any) { +async function teebagSetScheduledEnclave(api: any, Alice: any, block: any) { return new Promise(async (resolve, reject) => { - await api.tx.teerex.updateScheduledEnclave(block, hexToU8a(`0x${mrenclave}`)) + await api.tx.teebag.setScheduledEnclave("Identity", block, hexToU8a(`0x${mrenclave}`)) .signAndSend(Alice, ({ status, events, dispatchError }) => { if (status.isInBlock || status.isFinalized) { if (dispatchError) { @@ -75,15 +75,15 @@ async function updateScheduledEnclave(api: any, Alice: any, block: any) { const { docs, name, section } = decoded; console.log(colors.red(`${section}.${name}: ${docs.join(" ")}`)); - reject("updateScheduledEnclave failed"); + reject("teebag.setScheduledEnclave failed"); } else { // Other, CannotLookup, BadOrigin, no extra info console.log(dispatchError.toString()); - reject("updateScheduledEnclave failed"); + reject("teebag.setScheduledEnclave failed"); } } else { - console.log(colors.green("updateScheduledEnclave completed")); - resolve("updateScheduledEnclave done"); + console.log(colors.green("teebag.setScheduledEnclave completed")); + resolve("teebag.setScheduledEnclave done"); } } }); @@ -100,8 +100,8 @@ async function main() { const Alice = keyring.addFromUri("//Alice", { name: "Alice default" }); await transfer(defaultAPI, Alice); - await setTeerexAdmin(defaultAPI, Alice); - await updateScheduledEnclave(defaultAPI, Alice, block); + await teebagSetAdmin(defaultAPI, Alice); + await teebagSetScheduledEnclave(defaultAPI, Alice, block); console.log(colors.green("done")); process.exit(); diff --git a/tee-worker/.github/workflows/build_and_test.yml b/tee-worker/.github/workflows/build_and_test.yml deleted file mode 100644 index d007fe1eb4..0000000000 --- a/tee-worker/.github/workflows/build_and_test.yml +++ /dev/null @@ -1,599 +0,0 @@ -name: Build, Test, Clippy - -on: - workflow_dispatch: - push: - branches: - - master - - 'sdk-v[0-9]+.[0-9]+.[0-9]+-*' - tags: - - 'v[0-9]+.[0-9]+.[0-9]+*' - pull_request: - branches: - - master - - 'sdk-v[0-9]+.[0-9]+.[0-9]+-*' - -env: - CARGO_TERM_COLOR: always - LOG_DIR: logs - BUILD_CONTAINER_NAME: integritee_worker_enclave_test - -jobs: - cancel_previous_runs: - name: Cancel Previous Runs - runs-on: ubuntu-latest - steps: - - uses: styfle/cancel-workflow-action@0.11.0 - with: - access_token: ${{ secrets.GITHUB_TOKEN }} - - build-test: - runs-on: ${{ matrix.host }} - strategy: - fail-fast: false - matrix: - include: - - flavor_id: sidechain - mode: sidechain - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: offchain-worker - mode: offchain-worker - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: teeracle - mode: teeracle - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: sidechain-evm - mode: sidechain - additional_features: evm,dcap - host: integritee-builder-sgx - sgx_mode: HW - - steps: - - uses: actions/checkout@v3 - - - name: Set env - run: | - fingerprint=$RANDOM - echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV - SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") - echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV - if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then - echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV - else - echo "DOCKER_DEVICES=" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=" >> $GITHUB_ENV - fi - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - buildkitd-flags: --debug - driver: docker-container - - - name: Build Worker - env: - DOCKER_BUILDKIT: 1 - run: > - docker build -t integritee-worker-${{ env.IMAGE_SUFFIX }} - --target deployed-worker - --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg FINGERPRINT=${FINGERPRINT} --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} --build-arg SGX_MODE=${{ matrix.sgx_mode }} - -f build.Dockerfile . - - - run: docker images --all - - - name: Test Enclave # cargo test is not supported in the enclave, see: https://github.com/apache/incubator-teaclave-sgx-sdk/issues/232 - run: docker run --rm ${{ env.DOCKER_DEVICES }} ${{ env.DOCKER_VOLUMES }} integritee-worker-${{ env.IMAGE_SUFFIX }} test --all - - - name: Export worker image - run: | - docker image save integritee-worker-${{ env.IMAGE_SUFFIX }} | gzip > integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - - - name: Upload worker image - uses: actions/upload-artifact@v3 - with: - name: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - path: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - - - name: Create Enclave Digest File - run: | - mrenclave_hex=$(docker run integritee-worker-${{ env.IMAGE_SUFFIX }} mrenclave | grep -oP ':\s*\K[a-fA-F0-9]+') - echo "$mrenclave_hex" > mrenclave-${{ env.IMAGE_SUFFIX }}.hex - - - name: Upload Enclave Digest File - uses: actions/upload-artifact@v3 - with: - name: mrenclave-${{ env.IMAGE_SUFFIX }}.hex - path: mrenclave-${{ env.IMAGE_SUFFIX }}.hex - - - name: Delete images - run: | - if [[ "$(docker images -q integritee-worker-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee-worker-${{ env.IMAGE_SUFFIX }} 2>/dev/null - fi - docker images --all - - build-client: - runs-on: ${{ matrix.host }} - strategy: - fail-fast: false - matrix: - include: - - flavor_id: sidechain - mode: sidechain - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: offchain-worker - mode: offchain-worker - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: teeracle - mode: teeracle - host: integritee-builder-sgx - sgx_mode: HW - additional_features: dcap - - flavor_id: sidechain-evm - mode: sidechain - additional_features: evm,dcap - host: integritee-builder-sgx - sgx_mode: HW - - steps: - - uses: actions/checkout@v3 - - - name: Set env - run: | - fingerprint=$RANDOM - echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV - SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") - echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV - if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then - echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV - else - echo "DOCKER_DEVICES=" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=" >> $GITHUB_ENV - fi - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - buildkitd-flags: --debug - driver: docker-container - - - name: Build CLI client - env: - DOCKER_BUILDKIT: 1 - run: > - docker build -t integritee-cli-client-${{ env.IMAGE_SUFFIX }} - --target deployed-client - --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} - -f build.Dockerfile . - - - run: docker images --all - - - name: Export client image - run: | - docker image save integritee-cli-client-${{ env.IMAGE_SUFFIX }} | gzip > integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - - - name: Upload CLI client image - uses: actions/upload-artifact@v3 - with: - name: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - path: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - - - name: Delete images - run: | - if [[ "$(docker images -q integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2>/dev/null - fi - docker images --all - - code-quality: - runs-on: ubuntu-latest - container: "integritee/integritee-dev:0.2.2" - strategy: - fail-fast: false - matrix: - check: [ - # Workspace - cargo test --release, - # Worker - # Use release mode as the CI runs out of disk space otherwise. - cargo clippy --release -- -D warnings, - cargo clippy --release --features evm -- -D warnings, - cargo clippy --release --features sidechain -- -D warnings, - cargo clippy --release --features teeracle -- -D warnings, - cargo clippy --release --features offchain-worker -- -D warnings, - - # Enclave - cd enclave-runtime && cargo clippy -- -D warnings, - cd enclave-runtime && cargo clippy --features evm -- -D warnings, - cd enclave-runtime && cargo clippy --features sidechain -- -D warnings, - cd enclave-runtime && cargo clippy --features teeracle -- -D warnings, - cd enclave-runtime && cargo clippy --features offchain-worker -- -D warnings, - - # Fmt - cargo fmt --all -- --check, - cd enclave-runtime && cargo fmt --all -- --check, - ] - steps: - - uses: actions/checkout@v3 - - name: init-rust-target - # Enclave is not in the same workspace - run: rustup show && cd enclave-runtime && rustup show - - - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.check }} - - - name: ${{ matrix.check }} - run: ${{ matrix.check }} - - toml-fmt: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: init rust - run: rustup show - - - name: Install taplo - run: cargo install taplo-cli --locked - - name: Cargo.toml fmt - run: taplo fmt --check - - - name: Fail-fast; cancel other jobs - if: failure() - uses: andymckay/cancel-action@0.3 - - integration-tests: - runs-on: ${{ matrix.host }} - if: ${{ always() }} - needs: [build-test, build-client] - env: - WORKER_IMAGE_TAG: integritee-worker:dev - CLIENT_IMAGE_TAG: integritee-cli:dev - COINMARKETCAP_KEY: ${{ secrets.COINMARKETCAP_KEY }} - # IAS_EPID_SPID: ${{ secrets.IAS_SPID }} - # IAS_EPID_KEY: ${{ secrets.IAS_PRIMARY_KEY }} - TEERACLE_INTERVAL_SECONDS: 10 - - strategy: - fail-fast: false - matrix: - include: - - test: M6 - flavor_id: sidechain - demo_name: demo-shielding-unshielding-multiworker - host: test-runner-sgx - sgx_mode: HW - - test: M8 - flavor_id: sidechain - demo_name: demo-direct-call - host: test-runner-sgx - sgx_mode: HW - - test: Sidechain - flavor_id: sidechain - demo_name: demo-sidechain - host: test-runner-sgx - sgx_mode: HW - - test: M6 - flavor_id: offchain-worker - demo_name: demo-shielding-unshielding-multiworker - host: test-runner-sgx - sgx_mode: HW - - test: Teeracle - flavor_id: teeracle - demo_name: demo-teeracle - host: test-runner-sgx - sgx_mode: HW - - test: Teeracle - flavor_id: teeracle - demo_name: demo-teeracle-generic - host: test-runner-sgx - sgx_mode: HW - - test: Benchmark - flavor_id: sidechain - demo_name: sidechain-benchmark - host: test-runner-sgx - sgx_mode: HW - - test: EVM - flavor_id: sidechain-evm - demo_name: demo-smart-contract - host: test-runner-sgx - sgx_mode: HW - - steps: - - uses: actions/checkout@v3 - - - name: Set env - run: | - version=$RANDOM - SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") - echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV - echo "FLAVOR_ID=${{ matrix.flavor_id }}" >> $GITHUB_ENV - echo "PROJECT=${{ matrix.flavor_id }}-${{ matrix.demo_name }}" >> $GITHUB_ENV - echo "VERSION=dev.$version" >> $GITHUB_ENV - echo "WORKER_IMAGE_TAG=integritee-worker:dev.$version" >> $GITHUB_ENV - echo "INTEGRITEE_NODE=integritee-node:1.1.3.$version" >> $GITHUB_ENV - echo "CLIENT_IMAGE_TAG=integritee-cli:dev.$version" >> $GITHUB_ENV - if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then - echo "SGX_PROVISION=/dev/sgx/provision" >> $GITHUB_ENV - echo "SGX_ENCLAVE=/dev/sgx/enclave" >> $GITHUB_ENV - echo "AESMD=/var/run/aesmd" >> $GITHUB_ENV - echo "SGX_QCNL=/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV - fi - - echo "LOG_DIR=./logs-$version" >> $GITHUB_ENV - - - name: Download Worker Image - uses: actions/download-artifact@v3 - with: - name: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - path: . - - - name: Download CLI client Image - uses: actions/download-artifact@v3 - with: - name: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - path: . - - - name: Load Worker & Client Images - env: - DOCKER_BUILDKIT: 1 - run: | - docker image load --input integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz - docker image load --input integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz - docker images --all - - ## - # Before tagging, delete the old "stuck" ones to be sure that the newly created ones are the latest - # Without if the docker image rmi throws an error if the image doesn't exist. - ## - - name: Re-name Image Tags - run: | - if [[ "$(docker images -q ${{ env.WORKER_IMAGE_TAG }} 2> /dev/null)" == "" ]]; then - docker image rmi --force ${{ env.WORKER_IMAGE_TAG }} 2>/dev/null - fi - if [[ "$(docker images -q ${{ env.CLIENT_IMAGE_TAG }} 2> /dev/null)" == "" ]]; then - docker image rmi --force ${{ env.CLIENT_IMAGE_TAG }} 2>/dev/null - fi - docker tag integritee-worker-${{ env.IMAGE_SUFFIX }} ${{ env.WORKER_IMAGE_TAG }} - docker tag integritee-cli-client-${{ env.IMAGE_SUFFIX }} ${{ env.CLIENT_IMAGE_TAG }} - docker pull integritee/integritee-node:1.1.3 - docker tag integritee/integritee-node:1.1.3 ${{ env.INTEGRITEE_NODE }} - docker images --all - - ## - # Stop any stucked/running compose projects - ## - - name: Stop docker containers - if: always() - continue-on-error: true - run: | - cd docker - docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} stop - - - name: Integration Test ${{ matrix.test }}-${{ matrix.flavor_id }} - run: | - cd docker - docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} up ${{ matrix.demo_name }} --no-build --exit-code-from ${{ matrix.demo_name }} --remove-orphans - - - - name: Collect Docker Logs - continue-on-error: true - if: always() - uses: jwalton/gh-docker-logs@v2 - with: - images: '${{ env.WORKER_IMAGE_TAG }},${{ env.CLIENT_IMAGE_TAG }},${{ env.INTEGRITEE_NODE }}' - tail: all - dest: ${{ env.LOG_DIR }} - - - name: Upload logs - if: always() - uses: actions/upload-artifact@v3 - with: - name: logs-${{ matrix.test }}-${{ matrix.flavor_id }} - path: ${{ env.LOG_DIR }} - - - name: Stop docker containers - if: always() - continue-on-error: true - run: | - cd docker - docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} stop - - - name: Delete images - run: | - if [[ "$(docker images -q integritee-worker-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee-worker-${{ env.IMAGE_SUFFIX }} 2>/dev/null - fi - if [[ "$(docker images -q integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2>/dev/null - fi - if [[ "$(docker images -q ${{ env.WORKER_IMAGE_TAG }} 2> /dev/null)" != "" ]]; then - docker image rmi --force ${{ env.WORKER_IMAGE_TAG }} 2>/dev/null - fi - if [[ "$(docker images -q ${{ env.CLIENT_IMAGE_TAG }} 2> /dev/null)" != "" ]]; then - docker image rmi --force ${{ env.CLIENT_IMAGE_TAG }} 2>/dev/null - fi - if [[ "$(docker images -q ${{ env.INTEGRITEE_NODE }} 2> /dev/null)" != "" ]]; then - docker image rmi --force ${{ env.INTEGRITEE_NODE }} 2>/dev/null - fi - docker images --all - - release-build: - runs-on: integritee-builder-sgx - name: Release Build of teeracle - if: startsWith(github.ref, 'refs/tags/') - needs: [ build-test, integration-tests ] - - strategy: - fail-fast: false - matrix: - include: - - flavor_id: teeracle - mode: teeracle - sgx_mode: HW - additional_features: dcap - - flavor_id: sidechain - mode: sidechain - sgx_mode: HW - additional_features: dcap - - steps: - - uses: actions/checkout@v3 - - - name: Add masks - run: | - echo "::add-mask::$VAULT_TOKEN" - echo "::add-mask::$PRIVKEY_B64" - echo "::add-mask::$PRIVKEY_PASS" - - - name: Set env - run: | - fingerprint=$RANDOM - echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV - SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") - echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV - if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then - echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV - else - echo "DOCKER_DEVICES=" >> $GITHUB_ENV - echo "DOCKER_VOLUMES=" >> $GITHUB_ENV - fi - echo "VAULT_TOKEN=$VAULT_TOKEN" >> "$GITHUB_ENV" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - buildkitd-flags: --debug - driver: docker-container - - - name: Import secrets - uses: hashicorp/vault-action@v2 - id: import-secrets - with: - url: ${{ secrets.VAULT_URL }} - tlsSkipVerify: false - token: ${{ env.VAULT_TOKEN }} - exportEnv: false - secrets: | - ${{ secrets.VAULT_PATH }} intel_sgx_pem_base64 | PRIVKEY_B64 ; - ${{ secrets.VAULT_PATH }} password | PRIVKEY_PASS - - - name: Get secrets - env: - PRIVKEY_B64: ${{ steps.import-secrets.outputs.PRIVKEY_B64 }} - PRIVKEY_PASS: ${{ steps.import-secrets.outputs.PRIVKEY_PASS }} - run: | - echo $PRIVKEY_B64 | base64 --ignore-garbage --decode > enclave-runtime/intel_sgx.pem - echo $PRIVKEY_PASS > enclave-runtime/passfile.txt - - - name: Build Worker & Run Cargo Test - env: - DOCKER_BUILDKIT: 1 - run: > - docker build -t integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} - --target deployed-worker - --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg SGX_COMMERCIAL_KEY=enclave-runtime/intel_sgx.pem --build-arg SGX_PASSFILE=enclave-runtime/passfile.txt --build-arg SGX_PRODUCTION=1 --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} --build-arg SGX_MODE=${{ matrix.sgx_mode }} - -f build.Dockerfile . - - - name: Save released teeracle - run: | - docker image save integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} | gzip > integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz - docker images --all - - - name: Upload teeracle image - uses: actions/upload-artifact@v3 - with: - name: integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz - path: integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz - - - name: Delete images - run: | - if [[ "$(docker images -q integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} 2>/dev/null - fi - docker images --all - - release: - runs-on: ubuntu-latest - name: Draft Release - if: startsWith(github.ref, 'refs/tags/') - needs: [ build-test, integration-tests, release-build ] - outputs: - release_url: ${{ steps.create-release.outputs.html_url }} - asset_upload_url: ${{ steps.create-release.outputs.upload_url }} - steps: - - uses: actions/checkout@v3 - - - name: Download Worker Image - uses: actions/download-artifact@v3 - with: - name: integritee-worker-teeracle-${{ github.ref_name }}.tar.gz - path: . - - - name: Download Worker Image - uses: actions/download-artifact@v3 - with: - name: integritee-worker-sidechain-${{ github.ref_name }}.tar.gz - path: . - - # - # Temporary comment out until we decide what to release - # - # - name: Download Integritee Client - # uses: actions/download-artifact@v3 - # with: - # name: integritee-client-sidechain-${{ github.sha }} - # path: integritee-client-tmp - - # - name: Download Enclave Signed - # uses: actions/download-artifact@v3 - # with: - # name: enclave-signed-sidechain-${{ github.sha }} - # path: enclave-signed-tmp - - # - name: Move service binaries - # run: mv integritee-worker-tmp/integritee-service ./integritee-demo-validateer - - # - name: Move service client binaries - # run: mv integritee-client-tmp/integritee-cli ./integritee-client - - # - name: Move service client binaries - # run: mv enclave-signed-tmp/enclave.signed.so ./enclave.signed.so - - - name: Changelog - uses: scottbrenner/generate-changelog-action@master - id: Changelog - - - name: Display structure of downloaded files - run: ls -R - working-directory: . - - - name: Release - id: create-release - uses: softprops/action-gh-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - body: | - ${{ steps.Changelog.outputs.changelog }} - draft: true - name: Docker ${{ github.ref_name }} - files: | - integritee-worker-teeracle-${{ github.ref_name }}.tar.gz - integritee-worker-sidechain-${{ github.ref_name }}.tar.gz - integritee-client - integritee-demo-validateer - enclave.signed.so diff --git a/tee-worker/.github/workflows/check_labels.yml b/tee-worker/.github/workflows/check_labels.yml deleted file mode 100644 index 9511ed0b93..0000000000 --- a/tee-worker/.github/workflows/check_labels.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Labels Check -on: - pull_request: - types: [opened, labeled, unlabeled, synchronize, ready_for_review] -jobs: - A-label-check: - uses: ./.github/workflows/label-checker.yml - with: - predefined_labels: "A0-core,A1-cli,A2-applibs,A3-sidechain,A4-offchain,A5-teeracle,A6-evm,A7-somethingelse" - - B-label-check: - uses: ./.github/workflows/label-checker.yml - with: - predefined_labels: "B0-silent,B1-releasenotes" - - C-label-check: - uses: ./.github/workflows/label-checker.yml - with: - predefined_labels: "C1-low 📌,C3-medium 📣,C7-high ❗️,C9-critical ‼️" - - E-label-check: - uses: ./.github/workflows/label-checker.yml - with: - predefined_labels: "E0-breaksnothing,E3-hardmerge,E5-publicapi,E6-parentchain,E8-breakseverything" diff --git a/tee-worker/.github/workflows/delete-release.yml b/tee-worker/.github/workflows/delete-release.yml deleted file mode 100644 index 53fbdbb0f3..0000000000 --- a/tee-worker/.github/workflows/delete-release.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Delete-Release - -on: - release: - types: [deleted] # should be deleted - -jobs: - purge-image: - name: Delete image from ghcr.io - runs-on: ubuntu-latest - strategy: - matrix: - #binary: ["integritee-client", "integritee-demo-validateer"] - binary: ["teeracle"] - steps: - - uses: actions/checkout@v2 - - - name: Set output - id: vars - run: echo "{tag}={$GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT - - - name: Get Tag - id: get_tag - run: echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//} - - - name: Check output - env: - RELEASE_VERSION: ${{ steps.get_tag.outputs.TAG }} - run: | - echo $RELEASE_VERSION - echo ${{ steps.vars.outputs.tag }} - echo ${{github.event.pull_request.number}} - - - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - # Unfortunately accessing the repo with personal access token is not possible - # Workaround: disable 2FA and user password instead of TOKEN - - name: Delete docker tag - run: | - ORGANIZATION="integritee" - IMAGE="${{ matrix.binary }}" - TAG="${{ steps.get_tag.outputs.TAG }}" - - login_data() { - cat < /dev/null)" != "" ]]; then - docker image rmi --force integritee/sidechain:${{ github.event.release.tag_name }} 2>/dev/null - fi - docker images --all diff --git a/tee-worker/.github/workflows/publish-docker-teeracle.yml b/tee-worker/.github/workflows/publish-docker-teeracle.yml deleted file mode 100644 index 01a9a6f8b0..0000000000 --- a/tee-worker/.github/workflows/publish-docker-teeracle.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Publish Docker image for new teeracle release - -on: - release: - types: - - published - -jobs: - main: - name: Push Integritee Teeracle to Dockerhub - runs-on: [ self-hosted ] - steps: - - uses: actions/checkout@v3 - - - name: Download teeracle from release - uses: dsaltares/fetch-gh-release-asset@master - with: - version: "tags/${{ github.event.release.tag_name }}" - file: integritee-worker-teeracle-${{ github.event.release.tag_name }}.tar.gz - target: "integritee-worker-teeracle.tar.gz" - token: ${{ secrets.GITHUB_TOKEN }} - - - - name: Login to Dockerhub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - - name: Load Worker & Push - env: - DOCKER_BUILDKIT: 1 - run: | - docker image load --input integritee-worker-teeracle.tar.gz - docker images --all - docker push integritee/teeracle:${{ github.event.release.tag_name }} - - - name: Delete images - run: | - if [[ "$(docker images -q integritee/teeracle:${{ github.event.release.tag_name }} 2> /dev/null)" != "" ]]; then - docker image rmi --force integritee/teeracle:${{ github.event.release.tag_name }} 2>/dev/null - fi - docker images --all diff --git a/tee-worker/.github/workflows/publish-draft-release.yml b/tee-worker/.github/workflows/publish-draft-release.yml deleted file mode 100644 index 0e8c72dd6c..0000000000 --- a/tee-worker/.github/workflows/publish-draft-release.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Release - Publish draft - -on: - push: - tags: - # Catches only v1.2.3 (-dev,-rc1 etc won't be released as SDK) - - v[0-9]+.[0-9]+.[0-9]+ - -jobs: - publish-draft-release: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v3 - with: - fetch-depth: 0 - path: worker - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 3.0.0 - - - name: Download srtool json output - uses: actions/download-artifact@v3 - - - name: Prepare tooling - run: | - cd worker/scripts/changelog - gem install bundler changelogerator:0.9.1 - bundle install - changelogerator --help - URL=https://github.com/chevdor/tera-cli/releases/download/v0.2.1/tera-cli_linux_amd64.deb - wget $URL -O tera.deb - sudo dpkg -i tera.deb - tera --version - - - name: Generate release notes - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DEBUG: 1 - PRE_RELEASE: ${{ github.event.inputs.pre_release }} - run: | - find ${{env.GITHUB_WORKSPACE}} -type f -name "*_srtool_output.json" - - cd worker/scripts/changelog - - ./bin/changelog ${GITHUB_REF} - ls -al release-notes.md - ls -al context.json - - - name: Archive artifact context.json - uses: actions/upload-artifact@v3 - with: - name: release-notes-context - path: | - worker/scripts/changelog/context.json - **/*_srtool_output.json - - - name: Create draft release - id: create-release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: SDK ${{ github.ref }} - body_path: ./worker/scripts/changelog/release-notes.md - draft: true diff --git a/tee-worker/Cargo.lock b/tee-worker/Cargo.lock index 151af2fadf..1e44b39c41 100644 --- a/tee-worker/Cargo.lock +++ b/tee-worker/Cargo.lock @@ -1225,13 +1225,6 @@ dependencies = [ "thiserror 1.0.44", ] -[[package]] -name = "common-primitives" -version = "0.1.0" -dependencies = [ - "sp-std 5.0.0", -] - [[package]] name = "concurrent-queue" version = "2.2.0" @@ -4486,25 +4479,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ita-oracle" -version = "0.9.0" -dependencies = [ - "itc-rest-client", - "itp-enclave-metrics", - "itp-ocall-api", - "lazy_static", - "log 0.4.20", - "parity-scale-codec", - "serde 1.0.193", - "sgx_tstd", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", - "thiserror 1.0.44", - "thiserror 1.0.9", - "url 2.1.1", - "url 2.4.0", -] - [[package]] name = "ita-parentchain-interface" version = "0.9.0" @@ -4829,7 +4803,6 @@ dependencies = [ "serde_json 1.0.103", "sgx_crypto_helper", "sp-core", - "teerex-primitives", "thiserror 1.0.44", "url 2.4.0", "ws", @@ -4998,6 +4971,7 @@ dependencies = [ "itp-storage", "itp-types", "log 0.4.20", + "pallet-teebag", "parity-scale-codec", "serde_json 1.0.103", "sgx_crypto_helper", @@ -5005,7 +4979,6 @@ dependencies = [ "sgx_urts", "sp-core", "sp-runtime", - "teerex-primitives", "thiserror 1.0.44", ] @@ -5157,6 +5130,9 @@ dependencies = [ [[package]] name = "itp-settings" version = "0.9.0" +dependencies = [ + "litentry-primitives", +] [[package]] name = "itp-sgx-crypto" @@ -5206,7 +5182,6 @@ name = "itp-sgx-runtime-primitives" version = "0.9.0" dependencies = [ "frame-system", - "litentry-primitives", "pallet-balances", "sp-core", "sp-runtime", @@ -5332,14 +5307,6 @@ dependencies = [ "thiserror 1.0.9", ] -[[package]] -name = "itp-teerex-storage" -version = "0.9.0" -dependencies = [ - "itp-storage", - "sp-std 5.0.0", -] - [[package]] name = "itp-test" version = "0.9.0" @@ -5354,10 +5321,10 @@ dependencies = [ "itp-stf-primitives", "itp-stf-state-handler", "itp-storage", - "itp-teerex-storage", "itp-time-utils", "itp-types", "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", + "lc-teebag-storage", "litentry-primitives", "log 0.4.20", "parity-scale-codec", @@ -5618,6 +5585,7 @@ dependencies = [ "itc-rpc-client", "itp-node-api", "itp-test", + "itp-types", "its-primitives", "its-rpc-handler", "its-storage", @@ -5734,12 +5702,11 @@ name = "its-validateer-fetch" version = "0.9.0" dependencies = [ "derive_more", - "frame-support", "itc-parentchain-test", "itp-ocall-api", - "itp-teerex-storage", "itp-test", "itp-types", + "lc-teebag-storage", "parity-scale-codec", "sp-core", "sp-runtime", @@ -6405,6 +6372,15 @@ dependencies = [ "url 2.4.0", ] +[[package]] +name = "lc-teebag-storage" +version = "0.1.0" +dependencies = [ + "itp-storage", + "itp-types", + "sp-std 5.0.0", +] + [[package]] name = "lc-vc-task-receiver" version = "0.1.0" @@ -7103,7 +7079,6 @@ dependencies = [ "log 0.4.20", "pallet-balances", "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", - "pallet-teerex", "parity-scale-codec", "rand 0.8.5", "rayon", @@ -7151,6 +7126,7 @@ dependencies = [ "litentry-hex-utils", "log 0.4.20", "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "pallet-teebag", "parity-scale-codec", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", @@ -7165,7 +7141,6 @@ dependencies = [ "sp-std 5.0.0", "strum 0.26.1", "strum_macros 0.26.1", - "teerex-primitives", ] [[package]] @@ -7235,7 +7210,6 @@ dependencies = [ "serde 1.0.193", "serde_derive 1.0.193", "serde_json 1.0.103", - "sgx-verify", "sgx_crypto_helper", "sgx_types", "sp-consensus-grandpa", @@ -7243,7 +7217,6 @@ dependencies = [ "sp-keyring", "sp-runtime", "substrate-api-client", - "teerex-primitives", "thiserror 1.0.44", "tokio", "warp", @@ -8723,6 +8696,21 @@ dependencies = [ "sp-std 5.0.0", ] +[[package]] +name = "pallet-bitacross" +version = "0.1.0" +dependencies = [ + "core-primitives", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + [[package]] name = "pallet-bounties" version = "4.0.0-dev" @@ -9110,13 +9098,12 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", - "pallet-teerex", + "pallet-teebag", "parity-scale-codec", "scale-info", "sp-core", "sp-runtime", "sp-std 5.0.0", - "teerex-primitives", ] [[package]] @@ -9340,21 +9327,29 @@ dependencies = [ ] [[package]] -name = "pallet-teeracle" +name = "pallet-teebag" version = "0.1.0" dependencies = [ + "base64 0.13.1", + "chrono 0.4.26", + "der 0.6.1", "frame-support", "frame-system", + "hex 0.4.3", "log 0.4.20", - "pallet-teerex", + "pallet-balances", + "pallet-timestamp", "parity-scale-codec", + "ring 0.16.20", + "rustls-webpki", "scale-info", + "serde 1.0.193", + "serde_json 1.0.103", "sp-core", "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", "sp-runtime", "sp-std 5.0.0", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", - "teeracle-primitives", + "x509-cert", ] [[package]] @@ -9482,12 +9477,12 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "pallet-teebag", "parity-scale-codec", "scale-info", "sp-core", "sp-runtime", "sp-std 5.0.0", - "teerex-primitives", ] [[package]] @@ -11180,6 +11175,7 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-bitacross", "pallet-bounties", "pallet-bridge", "pallet-bridge-transfer", @@ -11210,7 +11206,7 @@ dependencies = [ "pallet-session", "pallet-sidechain", "pallet-sudo", - "pallet-teeracle", + "pallet-teebag", "pallet-teerex", "pallet-timestamp", "pallet-tips", @@ -11338,6 +11334,7 @@ dependencies = [ "pallet-group", "pallet-membership", "pallet-multisig", + "pallet-teebag", "pallet-teerex", "pallet-transaction-payment", "pallet-treasury", @@ -14440,14 +14437,6 @@ version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d2faeef5759ab89935255b1a4cd98e0baf99d1085e37d36599c625dac49ae8e" -[[package]] -name = "teeracle-primitives" -version = "0.1.0" -dependencies = [ - "common-primitives", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", -] - [[package]] name = "teerex-primitives" version = "0.1.0" diff --git a/tee-worker/Cargo.toml b/tee-worker/Cargo.toml index 120306da83..a7d31e4593 100644 --- a/tee-worker/Cargo.toml +++ b/tee-worker/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ - "app-libs/oracle", "app-libs/parentchain-interface", "app-libs/sgx-runtime", "app-libs/stf", @@ -51,7 +50,6 @@ members = [ "core-primitives/substrate-sgx/environmental", "core-primitives/substrate-sgx/externalities", "core-primitives/substrate-sgx/sp-io", - "core-primitives/teerex-storage", "core-primitives/test", "core-primitives/time-utils", "core-primitives/top-pool", @@ -97,24 +95,3 @@ sgx_urts = { version = "1.1.6", git = "https://github.com/apache/incubator-teacl [patch.crates-io] ring = { git = "https://github.com/betrusted-io/ring-xous", branch = "0.16.20-cleanup" } - -#[patch."https://github.com/integritee-network/integritee-node"] -#my-node-runtime = { package = "integritee-node-runtime", git = "https://github.com/integritee-network//integritee-node", branch = "ab/integrate-pallet-teerex-refactoring" } - -#[patch."https://github.com/scs/substrate-api-client"] -#substrate-api-client = { path = "../../scs/substrate-api-client" } -#substrate-client-keystore = { path = "../../scs/substrate-api-client/client-keystore" } - -#[patch."https://github.com/integritee-network/pallets.git"] -#pallet-claims = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#pallet-enclave-bridge = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#pallet-teerex = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#pallet-sidechain = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#sgx-verify = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#pallet-teeracle = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#test-utils = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#claims-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#enclave-bridge-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#teerex-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#teeracle-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } -#common-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } diff --git a/tee-worker/app-libs/oracle/Cargo.toml b/tee-worker/app-libs/oracle/Cargo.toml deleted file mode 100644 index eb8fa135e2..0000000000 --- a/tee-worker/app-libs/oracle/Cargo.toml +++ /dev/null @@ -1,48 +0,0 @@ -[package] -name = "ita-oracle" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] - -# std dependencies -thiserror = { version = "1.0.26", optional = true } -url = { version = "2.0.0", optional = true } - -# sgx dependencies -sgx_tstd = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } -thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } -url_sgx = { package = "url", git = "https://github.com/mesalock-linux/rust-url-sgx", tag = "sgx_1.1.3", optional = true } - -# no_std dependencies -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -lazy_static = { version = "1.1.0", features = ["spin_no_std"] } -log = { version = "0.4", default-features = false } -serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } -substrate-fixed = { default-features = false, git = "https://github.com/encointer/substrate-fixed", tag = "v0.5.9" } - -# internal dependencies -itc-rest-client = { path = "../../core/rest-client", default-features = false } -itp-enclave-metrics = { path = "../../core-primitives/enclave-metrics", default-features = false } -itp-ocall-api = { path = "../../core-primitives/ocall-api", default-features = false } - -[features] -default = ["std"] -std = [ - "itc-rest-client/std", - "itp-enclave-metrics/std", - "itp-ocall-api/std", - "log/std", - "serde/std", - "substrate-fixed/std", - "thiserror", - "url", -] -sgx = [ - "itc-rest-client/sgx", - "itp-enclave-metrics/sgx", - "sgx_tstd", - "thiserror_sgx", - "url_sgx", -] diff --git a/tee-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem b/tee-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem deleted file mode 100644 index a6f3e92af5..0000000000 --- a/tee-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- diff --git a/tee-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem b/tee-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem deleted file mode 100644 index 519028c63b..0000000000 --- a/tee-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- diff --git a/tee-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem b/tee-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem deleted file mode 100644 index 57d4a3766c..0000000000 --- a/tee-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- \ No newline at end of file diff --git a/tee-worker/app-libs/oracle/src/certificates/open_meteo_root.pem b/tee-worker/app-libs/oracle/src/certificates/open_meteo_root.pem deleted file mode 100644 index b85c8037f6..0000000000 --- a/tee-worker/app-libs/oracle/src/certificates/open_meteo_root.pem +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE----- diff --git a/tee-worker/app-libs/oracle/src/error.rs b/tee-worker/app-libs/oracle/src/error.rs deleted file mode 100644 index df72280f34..0000000000 --- a/tee-worker/app-libs/oracle/src/error.rs +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::types::TradingPair; -use std::{boxed::Box, string::String}; - -/// Exchange rate error -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Rest client error")] - RestClient(#[from] itc_rest_client::error::Error), - #[error("Could not retrieve any data from {0} for {1}")] - NoValidData(String, String), - #[error("Value for exchange rate is null")] - EmptyExchangeRate(TradingPair), - #[error("Invalid id for crypto currency")] - InvalidCryptoCurrencyId, - #[error("Invalid id for fiat currency")] - InvalidFiatCurrencyId, - #[error(transparent)] - Other(#[from] Box), -} diff --git a/tee-worker/app-libs/oracle/src/lib.rs b/tee-worker/app-libs/oracle/src/lib.rs deleted file mode 100644 index 6faee79a63..0000000000 --- a/tee-worker/app-libs/oracle/src/lib.rs +++ /dev/null @@ -1,84 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(test, feature(assert_matches))] - -#[cfg(all(feature = "std", feature = "sgx"))] -compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -// re-export module to properly feature gate sgx and regular std environment -#[cfg(all(not(feature = "std"), feature = "sgx"))] -pub mod sgx_reexport_prelude { - pub use thiserror_sgx as thiserror; - pub use url_sgx as url; -} - -use crate::{error::Error, metrics_exporter::MetricsExporter}; -use itp_ocall_api::EnclaveMetricsOCallApi; -use std::sync::Arc; - -pub mod error; -pub mod metrics_exporter; -pub mod traits; -pub mod types; - -pub mod oracles; -pub use oracles::{exchange_rate_oracle::ExchangeRateOracle, weather_oracle::WeatherOracle}; - -pub mod oracle_sources; -pub use oracle_sources::{ - coin_gecko::CoinGeckoSource, coin_market_cap::CoinMarketCapSource, - weather_oracle_source::WeatherOracleSource, -}; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod test; - -pub type CoinGeckoExchangeRateOracle = - ExchangeRateOracle>; - -pub type CoinMarketCapExchangeRateOracle = - ExchangeRateOracle>; - -pub type OpenMeteoWeatherOracle = - WeatherOracle>; - -pub fn create_coin_gecko_oracle( - ocall_api: Arc, -) -> CoinGeckoExchangeRateOracle { - ExchangeRateOracle::new(CoinGeckoSource {}, Arc::new(MetricsExporter::new(ocall_api))) -} - -pub fn create_coin_market_cap_oracle( - ocall_api: Arc, -) -> CoinMarketCapExchangeRateOracle { - ExchangeRateOracle::new(CoinMarketCapSource {}, Arc::new(MetricsExporter::new(ocall_api))) -} - -pub fn create_open_meteo_weather_oracle( - ocall_api: Arc, -) -> OpenMeteoWeatherOracle { - WeatherOracle::new(WeatherOracleSource {}, Arc::new(MetricsExporter::new(ocall_api))) -} diff --git a/tee-worker/app-libs/oracle/src/metrics_exporter.rs b/tee-worker/app-libs/oracle/src/metrics_exporter.rs deleted file mode 100644 index aa10516fd1..0000000000 --- a/tee-worker/app-libs/oracle/src/metrics_exporter.rs +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::types::{ExchangeRate, TradingPair}; -use itp_enclave_metrics::{EnclaveMetric, ExchangeRateOracleMetric, OracleMetric}; -use itp_ocall_api::EnclaveMetricsOCallApi; -use log::error; -use std::{string::String, sync::Arc, time::Instant}; - -/// Trait to export metrics for any Teeracle. -pub trait ExportMetrics { - fn increment_number_requests(&self, source: String); - - fn record_response_time(&self, source: String, timer: Instant); - - fn update_exchange_rate( - &self, - source: String, - exchange_rate: ExchangeRate, - trading_pair: TradingPair, - ); - - fn update_weather(&self, source: String, metrics_info: MetricsInfo); -} - -pub trait UpdateMetric { - fn update_metric(&self, metric: OracleMetric); -} - -/// Metrics exporter implementation. -pub struct MetricsExporter { - ocall_api: Arc, -} - -impl UpdateMetric for MetricsExporter -where - OCallApi: EnclaveMetricsOCallApi, -{ - fn update_metric(&self, _metric: OracleMetric) { - // TODO: Implement me - } -} - -impl MetricsExporter -where - OCallApi: EnclaveMetricsOCallApi, -{ - pub fn new(ocall_api: Arc) -> Self { - MetricsExporter { ocall_api } - } - - fn update_metric(&self, metric: ExchangeRateOracleMetric) { - if let Err(e) = self.ocall_api.update_metric(EnclaveMetric::ExchangeRateOracle(metric)) { - error!("Failed to update enclave metric, sgx_status_t: {}", e) - } - } -} - -impl ExportMetrics for MetricsExporter -where - OCallApi: EnclaveMetricsOCallApi, -{ - fn increment_number_requests(&self, source: String) { - self.update_metric(ExchangeRateOracleMetric::NumberRequestsIncrement(source)); - } - - fn record_response_time(&self, source: String, timer: Instant) { - self.update_metric(ExchangeRateOracleMetric::ResponseTime( - source, - timer.elapsed().as_millis(), - )); - } - - fn update_exchange_rate( - &self, - source: String, - exchange_rate: ExchangeRate, - trading_pair: TradingPair, - ) { - self.update_metric(ExchangeRateOracleMetric::ExchangeRate( - source, - trading_pair.key(), - exchange_rate, - )); - } - - fn update_weather(&self, _source: String, _metrics_info: MetricsInfo) { - // TODO: Implement me - } -} diff --git a/tee-worker/app-libs/oracle/src/mock.rs b/tee-worker/app-libs/oracle/src/mock.rs deleted file mode 100644 index f12224b0ea..0000000000 --- a/tee-worker/app-libs/oracle/src/mock.rs +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(feature = "sgx")] -use std::sync::SgxRwLock as RwLock; - -#[cfg(feature = "std")] -use std::sync::RwLock; - -use crate::{ - error::Error, - metrics_exporter::ExportMetrics, - traits::OracleSource, - types::{ExchangeRate, TradingPair}, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, -}; -use std::{ - time::{Duration, Instant}, - vec, - vec::Vec, -}; -use url::Url; - -/// Mock metrics exporter. -#[derive(Default)] -pub(crate) struct MetricsExporterMock { - number_requests: RwLock, - response_times: RwLock>, - exchange_rates: RwLock>, -} - -impl MetricsExporterMock { - pub fn get_number_request(&self) -> u64 { - *self.number_requests.read().unwrap() - } - - pub fn get_response_times(&self) -> Vec { - self.response_times.read().unwrap().clone() - } - - pub fn get_exchange_rates(&self) -> Vec<(TradingPair, ExchangeRate)> { - self.exchange_rates.read().unwrap().clone() - } -} - -impl ExportMetrics for MetricsExporterMock { - fn increment_number_requests(&self, _source: String) { - (*self.number_requests.write().unwrap()) += 1; - } - - fn record_response_time(&self, _source: String, timer: Instant) { - self.response_times.write().unwrap().push(timer.elapsed().as_millis()); - } - - fn update_exchange_rate( - &self, - _source: String, - exchange_rate: ExchangeRate, - trading_pair: TradingPair, - ) { - self.exchange_rates.write().unwrap().push((trading_pair, exchange_rate)); - } - - fn update_weather(&self, _source: String, _metrics_info: MetricsInfo) {} -} - -/// Mock oracle source. -#[derive(Default)] -pub(crate) struct OracleSourceMock; - -impl OracleSource for OracleSourceMock { - type OracleRequestResult = Result; - - fn metrics_id(&self) -> String { - "source_mock".to_string() - } - - fn request_timeout(&self) -> Option { - None - } - - fn base_url(&self) -> Result { - Url::parse("https://mock.base.url").map_err(|e| Error::Other(format!("{:?}", e).into())) - } - - fn root_certificates_content(&self) -> Vec { - vec!["MOCK_CERTIFICATE".to_string()] - } - fn execute_exchange_rate_request( - &self, - _rest_client: &mut RestClient>, - _trading_pair: TradingPair, - ) -> Result { - Ok(ExchangeRate::from_num(42.3f32)) - } - - fn execute_request( - _rest_client: &mut RestClient>, - _source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult { - Ok(42.3f32) - } -} diff --git a/tee-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs b/tee-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs deleted file mode 100644 index d9b8ad91ee..0000000000 --- a/tee-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs +++ /dev/null @@ -1,220 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - error::Error, - traits::OracleSource, - types::{ExchangeRate, TradingInfo, TradingPair}, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, - RestGet, RestPath, -}; -use lazy_static::lazy_static; -use log::{debug, error}; -use serde::{Deserialize, Serialize}; -use std::{ - collections::HashMap, - string::{String, ToString}, - time::Duration, - vec::Vec, -}; -use url::Url; - -const COINGECKO_URL: &str = "https://api.coingecko.com"; -const COINGECKO_PARAM_CURRENCY: &str = "vs_currency"; -const COINGECKO_PARAM_COIN: &str = "ids"; -const COINGECKO_PATH: &str = "api/v3/coins/markets"; -const COINGECKO_TIMEOUT: Duration = Duration::from_secs(20u64); -const COINGECKO_ROOT_CERTIFICATE_BALTIMORE: &str = - include_str!("../certificates/baltimore_cyber_trust_root_v3.pem"); -const COINGECKO_ROOT_CERTIFICATE_LETSENCRYPT: &str = - include_str!("../certificates/lets_encrypt_root_cert.pem"); - -lazy_static! { - static ref SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = HashMap::from([ - ("DOT", "polkadot"), - ("TEER", "integritee"), - ("KSM", "kusama"), - ("BTC", "bitcoin"), - ]); -} - -/// CoinGecko oracle source. -#[derive(Default)] -pub struct CoinGeckoSource; - -impl CoinGeckoSource { - fn map_crypto_currency_id(trading_pair: &TradingPair) -> Result { - let key = &trading_pair.crypto_currency; - match SYMBOL_ID_MAP.get(key.as_str()) { - Some(v) => Ok(v.to_string()), - None => Err(Error::InvalidCryptoCurrencyId), - } - } -} - -impl> OracleSource for CoinGeckoSource { - type OracleRequestResult = Result<(), Error>; - - fn metrics_id(&self) -> String { - "coin_gecko".to_string() - } - - fn request_timeout(&self) -> Option { - Some(COINGECKO_TIMEOUT) - } - - fn base_url(&self) -> Result { - Url::parse(COINGECKO_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) - } - - fn root_certificates_content(&self) -> Vec { - vec![ - COINGECKO_ROOT_CERTIFICATE_LETSENCRYPT.to_string(), - COINGECKO_ROOT_CERTIFICATE_BALTIMORE.to_string(), - ] - } - - fn execute_request( - _rest_client: &mut RestClient>, - source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult { - let _trading_info: TradingInfo = source_info.into(); - // TODO Implement me - Ok(()) - } - - fn execute_exchange_rate_request( - &self, - rest_client: &mut RestClient>, - trading_pair: TradingPair, - ) -> Result { - let fiat_id = trading_pair.fiat_currency.clone(); - let crypto_id = Self::map_crypto_currency_id(&trading_pair)?; - - let response = rest_client.get_with::( - COINGECKO_PATH.to_string(), - &[(COINGECKO_PARAM_CURRENCY, &fiat_id), (COINGECKO_PARAM_COIN, &crypto_id)], - ); - - let response = match response { - Ok(response) => response, - Err(e) => { - error!("coingecko execute_exchange_rate_request() failed with: {:?}", &e); - return Err(Error::RestClient(e)) - }, - }; - - debug!("coingecko received response: {:?}", &response); - let list = response.0; - if list.is_empty() { - return Err(Error::NoValidData(COINGECKO_URL.to_string(), trading_pair.key())) - } - - match list[0].current_price { - Some(r) => Ok(ExchangeRate::from_num(r)), - None => Err(Error::EmptyExchangeRate(trading_pair)), - } - } -} - -#[derive(Serialize, Deserialize, Debug)] -struct CoinGeckoMarketStruct { - id: String, - symbol: String, - name: String, - current_price: Option, - last_updated: Option, -} - -#[derive(Serialize, Deserialize, Debug)] -struct CoinGeckoMarket(pub Vec); - -impl RestPath for CoinGeckoMarket { - fn get_path(path: String) -> Result { - Ok(path) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - mock::MetricsExporterMock, - oracles::exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, - }; - use core::assert_matches::assert_matches; - use std::sync::Arc; - - type TestCoinGeckoClient = ExchangeRateOracle; - - fn get_coin_gecko_crypto_currency_id(crypto_currency: &str) -> Result { - let trading_pair = TradingPair { - crypto_currency: crypto_currency.to_string(), - fiat_currency: "USD".to_string(), - }; - CoinGeckoSource::map_crypto_currency_id(&trading_pair) - } - - #[test] - fn crypto_currency_id_works_for_dot() { - let coin_id = get_coin_gecko_crypto_currency_id("DOT").unwrap(); - assert_eq!(&coin_id, "polkadot"); - } - - #[test] - fn crypto_currency_id_works_for_teer() { - let coin_id = get_coin_gecko_crypto_currency_id("TEER").unwrap(); - assert_eq!(&coin_id, "integritee"); - } - - #[test] - fn crypto_currency_id_works_for_ksm() { - let coin_id = get_coin_gecko_crypto_currency_id("KSM").unwrap(); - assert_eq!(&coin_id, "kusama"); - } - - #[test] - fn crypto_currency_id_works_for_btc() { - let coin_id = get_coin_gecko_crypto_currency_id("BTC").unwrap(); - assert_eq!(&coin_id, "bitcoin"); - } - - #[test] - fn crypto_currency_id_fails_for_undefined_crypto_currency() { - let result = get_coin_gecko_crypto_currency_id("Undefined"); - assert_matches!(result, Err(Error::InvalidCryptoCurrencyId)); - } - - #[test] - fn get_exchange_rate_for_undefined_fiat_currency_fails() { - let coin_gecko_client = create_coin_gecko_client(); - let trading_pair = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CH".to_string() }; - let result = coin_gecko_client.get_exchange_rate(trading_pair); - assert_matches!(result, Err(Error::RestClient(_))); - } - - fn create_coin_gecko_client() -> TestCoinGeckoClient { - TestCoinGeckoClient::new(CoinGeckoSource {}, Arc::new(MetricsExporterMock::default())) - } -} diff --git a/tee-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs b/tee-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs deleted file mode 100644 index a0e053b8e6..0000000000 --- a/tee-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs +++ /dev/null @@ -1,242 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - error::Error, - traits::OracleSource, - types::{ExchangeRate, TradingInfo, TradingPair}, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, - RestGet, RestPath, -}; -use lazy_static::lazy_static; -use serde::{Deserialize, Serialize}; -use std::{ - collections::{BTreeMap, HashMap}, - env, - string::{String, ToString}, - time::Duration, - vec::Vec, -}; -use url::Url; - -const COINMARKETCAP_URL: &str = "https://pro-api.coinmarketcap.com"; -const COINMARKETCAP_KEY_PARAM: &str = "CMC_PRO_API_KEY"; -const FIAT_CURRENCY_PARAM: &str = "convert_id"; -const CRYPTO_CURRENCY_PARAM: &str = "id"; -const COINMARKETCAP_PATH: &str = "v2/cryptocurrency/quotes/latest"; // API endpoint to get the exchange rate with a basic API plan (free) -const COINMARKETCAP_TIMEOUT: Duration = Duration::from_secs(3u64); -const COINMARKETCAP_ROOT_CERTIFICATE: &str = include_str!("../certificates/amazon_root_ca_a.pem"); - -lazy_static! { - static ref CRYPTO_SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = - HashMap::from([("DOT", "6636"), ("TEER", "13323"), ("KSM", "5034"), ("BTC", "1"),]); - static ref COINMARKETCAP_KEY: String = env::var("COINMARKETCAP_KEY").unwrap_or_default(); -} - -lazy_static! { - static ref FIAT_SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = - HashMap::from([("USD", "2781"), ("EUR", "2790"), ("CHF", "2785"), ("JPY", "2797"),]); -} - -#[derive(Default)] -pub struct CoinMarketCapSource; - -impl CoinMarketCapSource { - fn map_crypto_currency_id(trading_pair: &TradingPair) -> Result { - CRYPTO_SYMBOL_ID_MAP - .get(trading_pair.crypto_currency.as_str()) - .map(|v| v.to_string()) - .ok_or(Error::InvalidCryptoCurrencyId) - } - - fn map_fiat_currency_id(trading_pair: &TradingPair) -> Result { - FIAT_SYMBOL_ID_MAP - .get(trading_pair.fiat_currency.as_str()) - .map(|v| v.to_string()) - .ok_or(Error::InvalidFiatCurrencyId) - } -} - -impl> OracleSource for CoinMarketCapSource { - // TODO Change this to return something useful? - type OracleRequestResult = Result<(), Error>; - - fn metrics_id(&self) -> String { - "coin_market_cap".to_string() - } - - fn request_timeout(&self) -> Option { - Some(COINMARKETCAP_TIMEOUT) - } - - fn base_url(&self) -> Result { - Url::parse(COINMARKETCAP_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) - } - - fn root_certificates_content(&self) -> Vec { - vec![COINMARKETCAP_ROOT_CERTIFICATE.to_string()] - } - - fn execute_request( - _rest_client: &mut RestClient>, - source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult { - let trading_info: TradingInfo = source_info.into(); - let _fiat_currency = trading_info.trading_pair.fiat_currency; - let _crypto_currency = trading_info.trading_pair.crypto_currency; - // TODO Implement me - Ok(()) - } - - fn execute_exchange_rate_request( - &self, - rest_client: &mut RestClient>, - trading_pair: TradingPair, - ) -> Result { - let fiat_id = Self::map_fiat_currency_id(&trading_pair)?; - let crypto_id = Self::map_crypto_currency_id(&trading_pair)?; - - let response = rest_client - .get_with::( - COINMARKETCAP_PATH.to_string(), - &[ - (FIAT_CURRENCY_PARAM, &fiat_id), - (CRYPTO_CURRENCY_PARAM, &crypto_id), - (COINMARKETCAP_KEY_PARAM, &COINMARKETCAP_KEY), - ], - ) - .map_err(Error::RestClient)?; - - let data_struct = response.0; - - let data = match data_struct.data.get(&crypto_id) { - Some(d) => d, - None => - return Err(Error::NoValidData( - COINMARKETCAP_URL.to_string(), - trading_pair.crypto_currency, - )), - }; - - let quote = match data.quote.get(&fiat_id) { - Some(q) => q, - None => - return Err(Error::NoValidData(COINMARKETCAP_URL.to_string(), trading_pair.key())), - }; - match quote.price { - Some(r) => Ok(ExchangeRate::from_num(r)), - None => Err(Error::EmptyExchangeRate(trading_pair)), - } - } -} - -#[derive(Serialize, Deserialize, Debug)] -struct DataStruct { - id: Option, - name: String, - symbol: String, - quote: BTreeMap, -} - -#[derive(Serialize, Deserialize, Debug)] -struct QuoteStruct { - price: Option, - last_updated: Option, -} - -#[derive(Serialize, Deserialize, Debug)] -struct CoinMarketCapMarketStruct { - data: BTreeMap, -} - -#[derive(Serialize, Deserialize, Debug)] -struct CoinMarketCapMarket(pub CoinMarketCapMarketStruct); - -impl RestPath for CoinMarketCapMarket { - fn get_path(path: String) -> Result { - Ok(path) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - mock::MetricsExporterMock, - oracles::exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, - }; - use core::assert_matches::assert_matches; - use std::sync::Arc; - - type TestClient = ExchangeRateOracle; - - fn get_coin_market_cap_crypto_currency_id(crypto_currency: &str) -> Result { - let trading_pair = TradingPair { - crypto_currency: crypto_currency.to_string(), - fiat_currency: "USD".to_string(), - }; - CoinMarketCapSource::map_crypto_currency_id(&trading_pair) - } - - #[test] - fn crypto_currency_id_works_for_dot() { - let coin_id = get_coin_market_cap_crypto_currency_id("DOT").unwrap(); - assert_eq!(&coin_id, "6636"); - } - - #[test] - fn crypto_currency_id_works_for_teer() { - let coin_id = get_coin_market_cap_crypto_currency_id("TEER").unwrap(); - assert_eq!(&coin_id, "13323"); - } - - #[test] - fn crypto_currency_id_works_for_ksm() { - let coin_id = get_coin_market_cap_crypto_currency_id("KSM").unwrap(); - assert_eq!(&coin_id, "5034"); - } - - #[test] - fn crypto_currency_id_works_for_btc() { - let coin_id = get_coin_market_cap_crypto_currency_id("BTC").unwrap(); - assert_eq!(&coin_id, "1"); - } - - #[test] - fn crypto_currency_id_fails_for_undefined_crypto_currency() { - let coin_id = get_coin_market_cap_crypto_currency_id("Undefined"); - assert_matches!(coin_id, Err(Error::InvalidCryptoCurrencyId)); - } - - #[test] - fn get_exchange_rate_for_undefined_fiat_currency_fails() { - let coin_market_cap_client = create_client(); - let trading_pair = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CH".to_string() }; - let result = coin_market_cap_client.get_exchange_rate(trading_pair); - assert_matches!(result, Err(Error::InvalidFiatCurrencyId)); - } - - fn create_client() -> TestClient { - TestClient::new(CoinMarketCapSource {}, Arc::new(MetricsExporterMock::default())) - } -} diff --git a/tee-worker/app-libs/oracle/src/oracle_sources/mod.rs b/tee-worker/app-libs/oracle/src/oracle_sources/mod.rs deleted file mode 100644 index d2d88153c3..0000000000 --- a/tee-worker/app-libs/oracle/src/oracle_sources/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -pub mod coin_gecko; -pub mod coin_market_cap; -pub mod weather_oracle_source; diff --git a/tee-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs b/tee-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs deleted file mode 100644 index 9f199be5dc..0000000000 --- a/tee-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs +++ /dev/null @@ -1,120 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - error::Error, - traits::OracleSource, - types::{ExchangeRate, TradingPair, WeatherInfo}, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, - RestGet, RestPath, -}; -use serde::{Deserialize, Serialize}; -use std::{ - string::{String, ToString}, - time::Duration, - vec::Vec, -}; -use url::Url; - -const WEATHER_URL: &str = "https://api.open-meteo.com"; -const WEATHER_PARAM_LONGITUDE: &str = "longitude"; -const WEATHER_PARAM_LATITUDE: &str = "latitude"; -// const WEATHER_PARAM_HOURLY: &str = "hourly"; // TODO: Add to Query -const WEATHER_PATH: &str = "v1/forecast"; -const WEATHER_TIMEOUT: Duration = Duration::from_secs(3u64); -const WEATHER_ROOT_CERTIFICATE: &str = include_str!("../certificates/open_meteo_root.pem"); - -// TODO: Change f32 types to appropriate Substrate Fixed Type -#[derive(Default)] -pub struct WeatherOracleSource; - -impl> OracleSource for WeatherOracleSource { - type OracleRequestResult = Result; // TODO: Change from f32 type - - fn metrics_id(&self) -> String { - "weather".to_string() - } - - fn request_timeout(&self) -> Option { - Some(WEATHER_TIMEOUT) - } - - fn base_url(&self) -> Result { - Url::parse(WEATHER_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) - } - - /// The server's root certificate. A valid certificate is required to open a tls connection - fn root_certificates_content(&self) -> Vec { - vec![WEATHER_ROOT_CERTIFICATE.to_string()] - } - - fn execute_exchange_rate_request( - &self, - _rest_client: &mut RestClient>, - _trading_pair: TradingPair, - ) -> Result { - Err(Error::NoValidData("None".into(), "None".into())) - } - - // TODO: Make this take a variant perhaps or a Closure so that it is more generic - fn execute_request( - rest_client: &mut RestClient>, - source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult { - let weather_info: WeatherInfo = source_info.into(); - let query = weather_info.weather_query; - - // TODO: - // This part is opinionated towards a hard coded query need to make more generic - let response = rest_client - .get_with::( - WEATHER_PATH.into(), - &[ - (WEATHER_PARAM_LATITUDE, &query.latitude), - (WEATHER_PARAM_LONGITUDE, &query.longitude), - //(WEATHER_PARAM_HOURLY), &query.hourly), - ], - ) - .map_err(Error::RestClient)?; - - let open_meteo_weather_struct = response.0; - - Ok(open_meteo_weather_struct.longitude) - } -} - -#[derive(Serialize, Deserialize, Debug)] -struct OpenMeteoWeatherStruct { - latitude: f32, - longitude: f32, - //hourly: String, -} - -#[derive(Serialize, Deserialize, Debug)] -struct OpenMeteo(pub OpenMeteoWeatherStruct); - -impl RestPath for OpenMeteo { - fn get_path(path: String) -> Result { - Ok(path) - } -} diff --git a/tee-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs b/tee-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs deleted file mode 100644 index 0198a5fe1b..0000000000 --- a/tee-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs +++ /dev/null @@ -1,154 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - metrics_exporter::ExportMetrics, - traits::OracleSource, - types::{ExchangeRate, TradingInfo, TradingPair}, - Error, -}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, -}; -use log::*; -use std::{ - sync::Arc, - thread, - time::{Duration, Instant}, -}; -use url::Url; - -#[allow(unused)] -pub struct ExchangeRateOracle { - oracle_source: OracleSourceType, - metrics_exporter: Arc, -} - -impl ExchangeRateOracle { - pub fn new(oracle_source: OracleSourceType, metrics_exporter: Arc) -> Self { - ExchangeRateOracle { oracle_source, metrics_exporter } - } -} - -pub trait GetExchangeRate { - /// Get the cryptocurrency/fiat_currency exchange rate - fn get_exchange_rate(&self, trading_pair: TradingPair) -> Result<(ExchangeRate, Url), Error>; -} - -impl GetExchangeRate - for ExchangeRateOracle -where - OracleSourceType: OracleSource, - MetricsExporter: ExportMetrics, -{ - fn get_exchange_rate(&self, trading_pair: TradingPair) -> Result<(ExchangeRate, Url), Error> { - let source_id = self.oracle_source.metrics_id(); - self.metrics_exporter.increment_number_requests(source_id.clone()); - - let base_url = self.oracle_source.base_url()?; - let root_certificates = self.oracle_source.root_certificates_content(); - let request_timeout = self.oracle_source.request_timeout(); - - debug!("Get exchange rate from URI: {}, trading pair: {:?}", base_url, trading_pair); - - let http_client = HttpClient::new( - SendWithCertificateVerification::new(root_certificates), - true, - request_timeout, - None, - None, - ); - let mut rest_client = RestClient::new(http_client, base_url.clone()); - - // Due to possible failures that may be temporarily this function tries to fetch the exchange rates `number_of_tries` times. - // If it still fails for the last attempt, then only in that case will it be considered a non-recoverable error. - let number_of_tries = 3; - let timer_start = Instant::now(); - - let mut tries = 0; - let result = loop { - tries += 1; - let exchange_result = self - .oracle_source - .execute_exchange_rate_request(&mut rest_client, trading_pair.clone()); - - match exchange_result { - Ok(exchange_rate) => { - self.metrics_exporter.record_response_time(source_id.clone(), timer_start); - self.metrics_exporter.update_exchange_rate( - source_id, - exchange_rate, - trading_pair, - ); - - debug!("Successfully executed exchange rate request"); - break Ok((exchange_rate, base_url)) - }, - Err(e) => - if tries < number_of_tries { - error!( - "Getting exchange rate from {} failed with {}, trying again in {:?}.", - &base_url, e, request_timeout - ); - debug!("Check that the API endpoint is available, for coingecko: https://status.coingecko.com/"); - thread::sleep( - request_timeout.unwrap_or_else(|| Duration::from_secs(number_of_tries)), - ); - } else { - error!( - "Getting exchange rate from {} failed {} times, latest error is: {}.", - &base_url, number_of_tries, &e - ); - break Err(e) - }, - } - }; - result - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::{MetricsExporterMock, OracleSourceMock}; - - type TestOracle = ExchangeRateOracle; - - #[test] - fn get_exchange_rate_updates_metrics() { - let metrics_exporter = Arc::new(MetricsExporterMock::default()); - let test_client = TestOracle::new(OracleSourceMock {}, metrics_exporter.clone()); - - let trading_pair = - TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "USD".to_string() }; - let _bit_usd = test_client.get_exchange_rate(trading_pair.clone()).unwrap(); - - assert_eq!(1, metrics_exporter.get_number_request()); - assert_eq!(1, metrics_exporter.get_response_times().len()); - assert_eq!(1, metrics_exporter.get_exchange_rates().len()); - - let (metric_trading_pair, exchange_rate) = - metrics_exporter.get_exchange_rates().first().unwrap().clone(); - - assert_eq!(trading_pair, metric_trading_pair); - assert_eq!(ExchangeRate::from_num(42.3f32), exchange_rate); - } -} diff --git a/tee-worker/app-libs/oracle/src/oracles/mod.rs b/tee-worker/app-libs/oracle/src/oracles/mod.rs deleted file mode 100644 index d6100d2469..0000000000 --- a/tee-worker/app-libs/oracle/src/oracles/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -pub mod exchange_rate_oracle; -pub mod weather_oracle; diff --git a/tee-worker/app-libs/oracle/src/oracles/weather_oracle.rs b/tee-worker/app-libs/oracle/src/oracles/weather_oracle.rs deleted file mode 100644 index 66809f7f3a..0000000000 --- a/tee-worker/app-libs/oracle/src/oracles/weather_oracle.rs +++ /dev/null @@ -1,83 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{metrics_exporter::ExportMetrics, traits::OracleSource, types::WeatherInfo, Error}; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, -}; -use log::*; -use std::sync::Arc; -use url::Url; - -#[allow(unused)] -pub struct WeatherOracle { - oracle_source: OracleSourceType, - metrics_exporter: Arc, -} - -impl WeatherOracle -where - OracleSourceType: OracleSource, -{ - pub fn new(oracle_source: OracleSourceType, metrics_exporter: Arc) -> Self { - WeatherOracle { oracle_source, metrics_exporter } - } - - pub fn get_base_url(&self) -> Result { - self.oracle_source.base_url() - } -} - -pub trait GetLongitude { - type LongitudeResult; - fn get_longitude(&self, weather_info: WeatherInfo) -> Self::LongitudeResult; -} - -impl GetLongitude - for WeatherOracle -where - OracleSourceType: OracleSource>, - MetricsExporter: ExportMetrics, -{ - type LongitudeResult = Result; - - fn get_longitude(&self, weather_info: WeatherInfo) -> Self::LongitudeResult { - let query = weather_info.weather_query.clone(); - - let base_url = self.oracle_source.base_url()?; - let root_certificates = self.oracle_source.root_certificates_content(); - - debug!("Get longitude from URI: {}, query: {:?}", base_url, query); - - let http_client = HttpClient::new( - SendWithCertificateVerification::new(root_certificates), - true, - self.oracle_source.request_timeout(), - None, - None, - ); - let mut rest_client = RestClient::new(http_client, base_url); - >::execute_request( - &mut rest_client, - weather_info, - ) - } -} diff --git a/tee-worker/app-libs/oracle/src/test.rs b/tee-worker/app-libs/oracle/src/test.rs deleted file mode 100644 index 8d083a18a0..0000000000 --- a/tee-worker/app-libs/oracle/src/test.rs +++ /dev/null @@ -1,125 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Integration tests for concrete exchange rate oracle implementations. -//! Uses real HTTP requests, so the sites must be available for these tests. - -use crate::{ - error::Error, - mock::MetricsExporterMock, - oracle_sources::{ - coin_gecko::CoinGeckoSource, coin_market_cap::CoinMarketCapSource, - weather_oracle_source::WeatherOracleSource, - }, - oracles::{ - exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, - weather_oracle::{GetLongitude, WeatherOracle}, - }, - traits::OracleSource, - types::{TradingInfo, TradingPair, WeatherInfo, WeatherQuery}, -}; -use core::assert_matches::assert_matches; -use std::sync::Arc; -use substrate_fixed::transcendental::ZERO; - -type TestOracle = ExchangeRateOracle; -type TestWeatherOracle = WeatherOracle; - -#[test] -#[ignore = "requires API key for CoinMarketCap"] -fn get_exchange_rate_from_coin_market_cap_works() { - test_suite_exchange_rates::(); -} - -#[test] -#[ignore = "requires external coin gecko service, disabled temporarily"] -fn get_exchange_rate_from_coin_gecko_works() { - test_suite_exchange_rates::(); -} - -#[test] -fn get_longitude_from_open_meteo_works() { - let oracle = create_weather_oracle::(); - let weather_query = - WeatherQuery { latitude: "52.52".into(), longitude: "13.41".into(), hourly: "none".into() }; - // Todo: hourly param is temperature_2m to get temp or relativehumidity_2m to get humidity - let weather_info = WeatherInfo { weather_query }; - let expected_longitude = 13.41f32; - let response_longitude = - oracle.get_longitude(weather_info).expect("Can grab longitude from oracle"); - assert!((response_longitude - expected_longitude) < 0.5); -} - -#[test] -fn get_exchange_rate_for_undefined_coin_market_cap_crypto_currency_fails() { - get_exchange_rate_for_undefined_crypto_currency_fails::(); -} - -#[test] -fn get_exchange_rate_for_undefined_coin_gecko_crypto_currency_fails() { - get_exchange_rate_for_undefined_crypto_currency_fails::(); -} - -fn create_weather_oracle>( -) -> TestWeatherOracle { - let oracle_source = OracleSourceType::default(); - WeatherOracle::new(oracle_source, Arc::new(MetricsExporterMock::default())) -} - -fn create_exchange_rate_oracle>( -) -> TestOracle { - let oracle_source = OracleSourceType::default(); - ExchangeRateOracle::new(oracle_source, Arc::new(MetricsExporterMock::default())) -} - -fn get_exchange_rate_for_undefined_crypto_currency_fails< - OracleSourceType: OracleSource, ->() { - let oracle = create_exchange_rate_oracle::(); - let trading_pair = TradingPair { - crypto_currency: "invalid_coin".to_string(), - fiat_currency: "USD".to_string(), - }; - let result = oracle.get_exchange_rate(trading_pair); - assert_matches!(result, Err(Error::InvalidCryptoCurrencyId)); -} - -fn test_suite_exchange_rates>() { - let oracle = create_exchange_rate_oracle::(); - let dot_to_usd = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; - let dot_usd = oracle.get_exchange_rate(dot_to_usd).unwrap().0; - assert!(dot_usd > 0f32); - let btc_to_usd = - TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "USD".to_string() }; - let bit_usd = oracle.get_exchange_rate(btc_to_usd).unwrap().0; - assert!(bit_usd > 0f32); - let dot_to_chf = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CHF".to_string() }; - let dot_chf = oracle.get_exchange_rate(dot_to_chf).unwrap().0; - assert!(dot_chf > 0f32); - let bit_to_chf = - TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "CHF".to_string() }; - let bit_chf = oracle.get_exchange_rate(bit_to_chf).unwrap().0; - - // Ensure that get_exchange_rate returns a positive rate - assert!(dot_usd > ZERO); - - // Ensure that get_exchange_rate returns a valid value by checking - // that the values obtained for DOT/BIT from different exchange rates are the same - assert_eq!((dot_usd / bit_usd).round(), (dot_chf / bit_chf).round()); -} diff --git a/tee-worker/app-libs/oracle/src/traits.rs b/tee-worker/app-libs/oracle/src/traits.rs deleted file mode 100644 index 1ca1d21428..0000000000 --- a/tee-worker/app-libs/oracle/src/traits.rs +++ /dev/null @@ -1,55 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -#[cfg(all(not(feature = "std"), feature = "sgx"))] -use crate::sgx_reexport_prelude::*; - -use crate::{ - types::{ExchangeRate, TradingPair}, - Error, -}; -use core::time::Duration; -use itc_rest_client::{ - http_client::{HttpClient, SendWithCertificateVerification}, - rest_client::RestClient, -}; -use std::{string::String, vec::Vec}; -use url::Url; - -pub trait OracleSource: Default { - type OracleRequestResult; - - fn metrics_id(&self) -> String; - - fn request_timeout(&self) -> Option; - - fn base_url(&self) -> Result; - - /// The server's root certificate(s). A valid certificate is required to open a tls connection - fn root_certificates_content(&self) -> Vec; - - fn execute_exchange_rate_request( - &self, - rest_client: &mut RestClient>, - trading_pair: TradingPair, - ) -> Result; - - fn execute_request( - rest_client: &mut RestClient>, - source_info: OracleSourceInfo, - ) -> Self::OracleRequestResult; -} diff --git a/tee-worker/app-libs/oracle/src/types.rs b/tee-worker/app-libs/oracle/src/types.rs deleted file mode 100644 index ef969ccb90..0000000000 --- a/tee-worker/app-libs/oracle/src/types.rs +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use codec::{Decode, Encode}; -use std::string::String; -use substrate_fixed::types::U32F32; - -#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct WeatherInfo { - pub weather_query: WeatherQuery, -} - -#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct WeatherQuery { - pub longitude: String, - pub latitude: String, - pub hourly: String, -} - -impl WeatherQuery { - pub fn key(self) -> String { - format!("{}/{}", self.latitude, self.longitude) - } -} - -#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct TradingInfo { - pub trading_pair: TradingPair, - pub exchange_rate: ExchangeRate, -} -/// Market identifier for order -#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct TradingPair { - pub crypto_currency: String, - pub fiat_currency: String, -} - -impl TradingPair { - pub fn key(self) -> String { - format!("{}/{}", self.crypto_currency, self.fiat_currency) - } -} - -/// TODO Fix https://github.com/integritee-network/pallets/issues/71 and get it from https://github.com/integritee-network/pallets.git -/// Teeracle types -pub type ExchangeRate = U32F32; -// pub type Coordinate = U32F32; diff --git a/tee-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs b/tee-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs index f2ae695c9e..5e6069b1a9 100644 --- a/tee-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs +++ b/tee-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs @@ -21,29 +21,35 @@ use itc_parentchain_indirect_calls_executor::{ IndirectDispatch, }; use itp_stf_primitives::traits::IndirectExecutor; -use itp_types::{MrEnclave, SidechainBlockNumber}; +use itp_types::{MrEnclave, SidechainBlockNumber, WorkerType}; use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; -use log::debug; +use log::*; #[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] -pub struct UpdateScheduledEnclaveArgs { +pub struct SetScheduledEnclaveArgs { + worker_type: WorkerType, sbn: codec::Compact, mrenclave: MrEnclave, } impl> - IndirectDispatch for UpdateScheduledEnclaveArgs + IndirectDispatch for SetScheduledEnclaveArgs { type Args = (); fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { - debug!("execute indirect call: UpdateScheduledEnclave, sidechain_block_number: {:?}, mrenclave: {:?}", self.sbn, self.mrenclave); - GLOBAL_SCHEDULED_ENCLAVE.update(self.sbn.into(), self.mrenclave)?; + debug!("execute indirect call: SetScheduledEnclave, worker_type: {:?}, sidechain_block_number: {:?}, mrenclave: {:?}", self.worker_type, self.sbn, self.mrenclave); + if self.worker_type == WorkerType::Identity { + GLOBAL_SCHEDULED_ENCLAVE.update(self.sbn.into(), self.mrenclave)?; + } else { + warn!("Ignore SetScheduledEnclave due to wrong worker_type"); + } Ok(()) } } #[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] pub struct RemoveScheduledEnclaveArgs { + worker_type: WorkerType, sbn: codec::Compact, } @@ -53,10 +59,15 @@ impl> type Args = (); fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { debug!( - "execute indirect call: RemoveScheduledEnclave, sidechain_block_number: {:?}", + "execute indirect call: RemoveScheduledEnclave, worker_type: {:?}, sidechain_block_number: {:?}", + self.worker_type, self.sbn ); - GLOBAL_SCHEDULED_ENCLAVE.remove(self.sbn.into())?; + if self.worker_type == WorkerType::Identity { + GLOBAL_SCHEDULED_ENCLAVE.remove(self.sbn.into())?; + } else { + warn!("Ignore RemoveScheduledEnclave due to wrong worker_type"); + } Ok(()) } } diff --git a/tee-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs b/tee-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs index 7b65f61b30..d14caeeb20 100644 --- a/tee-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs +++ b/tee-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs @@ -26,7 +26,7 @@ pub use litentry::{ deactivate_identity::DeactivateIdentityArgs, link_identity::LinkIdentityArgs, request_vc::RequestVCArgs, - scheduled_enclave::{RemoveScheduledEnclaveArgs, UpdateScheduledEnclaveArgs}, + scheduled_enclave::{RemoveScheduledEnclaveArgs, SetScheduledEnclaveArgs}, }; pub use shield_funds::ShieldFundsArgs; pub use transfer_to_alice_shields_funds::{TransferToAliceShieldsFundsArgs, ALICE_ACCOUNT_ID}; diff --git a/tee-worker/app-libs/parentchain-interface/src/integritee/mod.rs b/tee-worker/app-libs/parentchain-interface/src/integritee/mod.rs index 5dc036b76a..05803f81ac 100644 --- a/tee-worker/app-libs/parentchain-interface/src/integritee/mod.rs +++ b/tee-worker/app-libs/parentchain-interface/src/integritee/mod.rs @@ -23,7 +23,7 @@ use crate::{ decode_and_log_error, indirect_calls::{ ActivateIdentityArgs, DeactivateIdentityArgs, InvokeArgs, LinkIdentityArgs, - RemoveScheduledEnclaveArgs, RequestVCArgs, ShieldFundsArgs, UpdateScheduledEnclaveArgs, + RemoveScheduledEnclaveArgs, RequestVCArgs, SetScheduledEnclaveArgs, ShieldFundsArgs, }, integritee::extrinsic_parser::ParseExtrinsic, }; @@ -63,7 +63,7 @@ pub enum IndirectCall { #[codec(index = 5)] RequestVC(RequestVCArgs, Option>, H256), #[codec(index = 6)] - UpdateScheduledEnclave(UpdateScheduledEnclaveArgs), + SetScheduledEnclave(SetScheduledEnclaveArgs), #[codec(index = 7)] RemoveScheduledEnclave(RemoveScheduledEnclaveArgs), #[codec(index = 8)] @@ -88,7 +88,7 @@ impl> activate_identity.dispatch(executor, (address.clone(), *hash)), IndirectCall::RequestVC(request_vc, address, hash) => request_vc.dispatch(executor, (address.clone(), *hash)), - IndirectCall::UpdateScheduledEnclave(update_enclave_args) => + IndirectCall::SetScheduledEnclave(update_enclave_args) => update_enclave_args.dispatch(executor, ()), IndirectCall::RemoveScheduledEnclave(remove_enclave_args) => remove_enclave_args.dispatch(executor, ()), @@ -143,11 +143,7 @@ where "[ShieldFundsAndInvokeFilter] attempting to execute indirect call with index {:?}", index ); - if index == metadata.shield_funds_call_indexes().ok()? { - log::debug!("executing shield funds call"); - let args = decode_and_log_error::(call_args)?; - Some(IndirectCall::ShieldFunds(args)) - } else if index == metadata.invoke_call_indexes().ok()? { + if index == metadata.post_opaque_task_call_indexes().ok()? { log::debug!("executing invoke call"); let args = decode_and_log_error::(call_args)?; Some(IndirectCall::Invoke(args)) @@ -168,10 +164,10 @@ where let args = decode_and_log_error::(call_args)?; let hashed_extrinsic = xt.hashed_extrinsic; Some(IndirectCall::RequestVC(args, address, hashed_extrinsic)) - } else if index == metadata.update_scheduled_enclave().ok()? { - let args = decode_and_log_error::(call_args)?; - Some(IndirectCall::UpdateScheduledEnclave(args)) - } else if index == metadata.remove_scheduled_enclave().ok()? { + } else if index == metadata.set_scheduled_enclave_call_indexes().ok()? { + let args = decode_and_log_error::(call_args)?; + Some(IndirectCall::SetScheduledEnclave(args)) + } else if index == metadata.remove_scheduled_enclave_call_indexes().ok()? { let args = decode_and_log_error::(call_args)?; Some(IndirectCall::RemoveScheduledEnclave(args)) } else if index == metadata.batch_all_call_indexes().ok()? { @@ -193,10 +189,7 @@ fn parse_batch_all( log::debug!("Received BatchAll including {} calls", call_count.len()); for _i in 0..call_count.len() { let index: CallIndex = Decode::decode(call_args).ok()?; - if index == metadata.shield_funds_call_indexes().ok()? { - let args = decode_and_log_error::(call_args)?; - calls.push(IndirectCall::ShieldFunds(args)) - } else if index == metadata.invoke_call_indexes().ok()? { + if index == metadata.post_opaque_task_call_indexes().ok()? { let args = decode_and_log_error::(call_args)?; calls.push(IndirectCall::Invoke(args)) } else if index == metadata.link_identity_call_indexes().ok()? { @@ -215,10 +208,10 @@ fn parse_batch_all( let args = decode_and_log_error::(call_args)?; let hashed_extrinsic = hash; calls.push(IndirectCall::RequestVC(args, address.clone(), hashed_extrinsic)) - } else if index == metadata.update_scheduled_enclave().ok()? { - let args = decode_and_log_error::(call_args)?; - calls.push(IndirectCall::UpdateScheduledEnclave(args)) - } else if index == metadata.remove_scheduled_enclave().ok()? { + } else if index == metadata.set_scheduled_enclave_call_indexes().ok()? { + let args = decode_and_log_error::(call_args)?; + calls.push(IndirectCall::SetScheduledEnclave(args)) + } else if index == metadata.remove_scheduled_enclave_call_indexes().ok()? { let args = decode_and_log_error::(call_args)?; calls.push(IndirectCall::RemoveScheduledEnclave(args)) } diff --git a/tee-worker/app-libs/sgx-runtime/src/lib.rs b/tee-worker/app-libs/sgx-runtime/src/lib.rs index 0c2c5f715a..f6ffcf34c2 100644 --- a/tee-worker/app-libs/sgx-runtime/src/lib.rs +++ b/tee-worker/app-libs/sgx-runtime/src/lib.rs @@ -57,8 +57,7 @@ use sp_version::RuntimeVersion; pub use itp_sgx_runtime_primitives::{ constants::SLOT_DURATION, types::{ - AccountData, AccountId, Address, Balance, BlockNumber, ConvertAccountId, Hash, Header, - Index, SgxParentchainTypeConverter, Signature, + AccountData, AccountId, Address, Balance, BlockNumber, Hash, Header, Index, Signature, }, }; @@ -139,7 +138,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node-template"), impl_name: create_runtime_str!("node-template"), authoring_version: 1, - spec_version: 103, + spec_version: 104, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/tee-worker/app-libs/stf/src/getter.rs b/tee-worker/app-libs/stf/src/getter.rs index c80cc31fbf..c3405ba208 100644 --- a/tee-worker/app-libs/stf/src/getter.rs +++ b/tee-worker/app-libs/stf/src/getter.rs @@ -23,6 +23,7 @@ use itp_utils::stringify::account_id_to_string; use litentry_macros::if_production_or; use litentry_primitives::{Identity, LitentryMultiSignature}; use log::*; +use sp_core::blake2_256; use sp_std::vec; use std::prelude::v1::*; @@ -145,7 +146,7 @@ impl TrustedGetter { } pub fn sign(&self, pair: &KeyPair) -> TrustedGetterSigned { - let signature = pair.sign(self.encode().as_slice()); + let signature = pair.sign(&blake2_256(self.encode().as_slice())); TrustedGetterSigned { getter: self.clone(), signature } } } @@ -162,18 +163,18 @@ impl TrustedGetterSigned { } pub fn verify_signature(&self) -> bool { + let payload = self.getter.encode(); // in non-prod, we accept signature from Alice too if_production_or!( { - self.signature - .verify(self.getter.encode().as_slice(), self.getter.sender_identity()) + self.signature.verify(&payload, self.getter.sender_identity()) + || self.signature.verify(&blake2_256(&payload), self.getter.sender_identity()) }, { - self.signature - .verify(self.getter.encode().as_slice(), self.getter.sender_identity()) - || self - .signature - .verify(self.getter.encode().as_slice(), &ALICE_ACCOUNTID32.into()) + self.signature.verify(&payload, self.getter.sender_identity()) + || self.signature.verify(&blake2_256(&payload), self.getter.sender_identity()) + || self.signature.verify(&payload, &ALICE_ACCOUNTID32.into()) + || self.signature.verify(&blake2_256(&payload), &ALICE_ACCOUNTID32.into()) } ) } diff --git a/tee-worker/app-libs/stf/src/trusted_call.rs b/tee-worker/app-libs/stf/src/trusted_call.rs index 045eaa5c6a..725e8ee2fa 100644 --- a/tee-worker/app-libs/stf/src/trusted_call.rs +++ b/tee-worker/app-libs/stf/src/trusted_call.rs @@ -43,7 +43,7 @@ pub use ita_sgx_runtime::{Balance, IDGraph, Index, Runtime, System}; use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; use itp_node_api_metadata::{ pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, - pallet_proxy::ProxyCallIndexes, pallet_teerex::TeerexCallIndexes, pallet_vcmp::VCMPCallIndexes, + pallet_proxy::ProxyCallIndexes, pallet_vcmp::VCMPCallIndexes, }; use itp_stf_interface::{ExecuteCall, SHARD_VAULT_KEY}; pub use itp_stf_primitives::{ @@ -264,7 +264,8 @@ impl TrustedCallSigning for TrustedCall { payload.append(&mut mrenclave.encode()); payload.append(&mut shard.encode()); - TrustedCallSigned { call: self.clone(), nonce, signature: pair.sign(payload.as_slice()) } + // use blake2_256 hash to shorten the payload - see `verify_signature` below + TrustedCallSigned { call: self.clone(), nonce, signature: pair.sign(&blake2_256(&payload)) } } } @@ -317,7 +318,9 @@ impl TrustedCallVerification for TrustedCallSigned { payload.append(&mut mrenclave.encode()); payload.append(&mut shard.encode()); - self.signature.verify(payload.as_slice(), self.call.sender_identity()) + // make it backwards compatible for now - will deprecate the old way later + self.signature.verify(&blake2_256(&payload), self.call.sender_identity()) + || self.signature.verify(&payload, self.call.sender_identity()) } fn metric_name(&self) -> &'static str { @@ -374,7 +377,6 @@ where node_metadata_repo: Arc, ) -> Result { let sender = self.call.sender_identity().clone(); - let call_hash = blake2_256(&self.call.encode()); let account_id: AccountId = sender.to_account_id().ok_or(Self::Error::InvalidAccount)?; let system_nonce = System::account_nonce(&account_id); ensure!(self.nonce == system_nonce, Self::Error::InvalidNonce(self.nonce, system_nonce)); @@ -521,16 +523,7 @@ where debug!("balance_shield({}, {})", account_id_to_string(&who), value); shield_funds(who, value)?; - // Send proof of execution on chain. - calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( - node_metadata_repo - .get_from_metadata(|m| m.publish_hash_call_indexes()) - .map_err(|_| StfError::InvalidMetadata)? - .map_err(|_| StfError::InvalidMetadata)?, - call_hash, - Vec::::new(), - b"shielded some funds!".to_vec(), - )))); + // Litentry: we don't have publish_hash call in teebag Ok(TrustedCallResult::Empty) }, #[cfg(feature = "evm")] diff --git a/tee-worker/cli/Cargo.toml b/tee-worker/cli/Cargo.toml index f3ad923d46..40eb67a1c9 100644 --- a/tee-worker/cli/Cargo.toml +++ b/tee-worker/cli/Cargo.toml @@ -56,14 +56,12 @@ ita-sgx-runtime = { path = "../app-libs/sgx-runtime" } litentry-hex-utils = { path = "../../primitives/hex", default-features = false } litentry-primitives = { path = "../litentry/primitives" } my-node-runtime = { package = "rococo-parachain-runtime", path = "../../runtime/rococo" } -pallet-teerex = { path = "../../pallets/teerex", default-features = false } scale-value = "0.6.0" sp-core-hashing = "6.0.0" [features] default = [] evm = ["ita-stf/evm_std", "pallet-evm"] -teeracle = [] sidechain = [] offchain-worker = [] production = [] diff --git a/tee-worker/cli/lit_parentchain_nonce.sh b/tee-worker/cli/lit_parentchain_nonce.sh index 34c6419892..a89eaef9db 100755 --- a/tee-worker/cli/lit_parentchain_nonce.sh +++ b/tee-worker/cli/lit_parentchain_nonce.sh @@ -62,7 +62,7 @@ ${CLIENT} trusted --mrenclave $MRENCLAVE --direct send-erroneous-parentchain-cal echo "" sleep 20 -# wait for 10 `ProcessedParentchainBlock` events, which should take around 2 min (1 worker) +# wait for 10 `ParentchainBlockProcessed` events, which should take around 2 min (1 worker) # if the incoming parentchain extrinsic is blocked (due to the wrong nonce), there won't be # such many events. set -e diff --git a/tee-worker/cli/lit_set_heartbeat_timeout.sh b/tee-worker/cli/lit_set_heartbeat_timeout.sh deleted file mode 100755 index 7c806480c4..0000000000 --- a/tee-worker/cli/lit_set_heartbeat_timeout.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# Copyright 2020-2024 Trust Computing GmbH. - -while getopts ":p:A:B:u:W:V:C:" opt; do - case $opt in - p) - NPORT=$OPTARG - ;; - A) - WORKER1PORT=$OPTARG - ;; - B) - WORKER2PORT=$OPTARG - ;; - u) - NODEURL=$OPTARG - ;; - V) - WORKER1URL=$OPTARG - ;; - W) - WORKER2URL=$OPTARG - ;; - C) - CLIENT_BIN=$OPTARG - ;; - esac -done - -# Using default port if none given as arguments. -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} - -WORKER1PORT=${WORKER1PORT:-2000} -WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} - -CLIENT_BIN=${CLIENT_BIN:-"../bin/litentry-cli"} - -LOG_FOLDER="./../log" - -echo "Using client binary $CLIENT_BIN" -echo "Using node uri $NODEURL:$NPORT" -echo "Using trusted-worker uri $WORKER1URL:$WORKER1PORT" -echo "" - -TIMEOUT=5000 # 5 seconds, smaller than 12s (the block duration) - -CLIENT="$CLIENT_BIN -p $NPORT -P $WORKER1PORT -u $NODEURL -U $WORKER1URL" -echo "CLIENT is: $CLIENT" - -echo "* Query on-chain enclave registry:" -WORKERS=$($CLIENT list-workers) -echo "WORKERS: " -echo "${WORKERS}" -echo "" - -if [ "$READMRENCLAVE" = "file" ] -then - read MRENCLAVE <<< $(cat ~/mrenclave.b58) - echo "Reading MRENCLAVE from file: ${MRENCLAVE}" -else - # This will always take the first MRENCLAVE found in the registry !! - read MRENCLAVE <<< $(echo "$WORKERS" | awk '/ MRENCLAVE: / { print $2; exit }') - echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" -fi -[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } - - -# indirect call that will be sent to the parachain, it will be synchronously handled -sleep 10 -echo "* Set heartbeat timeout to $TIMEOUT" -${CLIENT} set-heartbeat-timeout "$TIMEOUT" -echo "" - -sleep 120 - -read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') -if [[ -z $MRENCLAVE ]] -then - echo "All workers removed, test passed" -else - echo "Worker(s) still exist(s), test fail" - exit 1 -fi diff --git a/tee-worker/cli/lit_ts_integration_test.sh b/tee-worker/cli/lit_ts_integration_test.sh index 4549d32048..9a29ce291a 100755 --- a/tee-worker/cli/lit_ts_integration_test.sh +++ b/tee-worker/cli/lit_ts_integration_test.sh @@ -68,4 +68,4 @@ pnpm run build cd /ts-tests pnpm install -pnpm --filter integration-tests run $TEST:staging +NODE_ENV=staging pnpm --filter integration-tests run test $TEST diff --git a/tee-worker/cli/lit_ts_worker_test.sh b/tee-worker/cli/lit_ts_worker_test.sh index a4983a99ae..0c836b2e6e 100755 --- a/tee-worker/cli/lit_ts_worker_test.sh +++ b/tee-worker/cli/lit_ts_worker_test.sh @@ -22,4 +22,4 @@ echo "Using node endpoint: $NODE_ENDPOINT" cd /ts-tests pnpm install -pnpm --filter worker run $TEST:staging +NODE_ENV=staging pnpm --filter worker run test $TEST diff --git a/tee-worker/cli/src/base_cli/commands/listen.rs b/tee-worker/cli/src/base_cli/commands/listen.rs index 27a9b15811..734ffb9af8 100644 --- a/tee-worker/cli/src/base_cli/commands/listen.rs +++ b/tee-worker/cli/src/base_cli/commands/listen.rs @@ -73,70 +73,55 @@ impl ListenCommand { }, } }, - RuntimeEvent::Teerex(ee) => { - println!(">>>>>>>>>> integritee teerex event: {:?}", ee); + RuntimeEvent::Teebag(ee) => { + println!(">>>>>>>>>> litentry teebag event: {:?}", ee); count += 1; match &ee { - my_node_runtime::pallet_teerex::Event::AddedEnclave( - accountid, + my_node_runtime::pallet_teebag::Event::EnclaveAdded { + who, + worker_type, url, - ) => { + } => { println!( - "AddedEnclave: {:?} at url {}", - accountid, + "EnclaveAdded: {:?} [{:?}] at url {}", + who, + worker_type, String::from_utf8(url.to_vec()) .unwrap_or_else(|_| "error".to_string()) ); }, - my_node_runtime::pallet_teerex::Event::RemovedEnclave( - accountid, - ) => { - println!("RemovedEnclave: {:?}", accountid); + my_node_runtime::pallet_teebag::Event::EnclaveRemoved { + who, + } => { + println!("EnclaveRemoved: {:?}", who); }, - my_node_runtime::pallet_teerex::Event::Forwarded(shard) => { + my_node_runtime::pallet_teebag::Event::OpaqueTaskPosted { shard } => { println!( - "Forwarded request for shard {}", + "OpaqueTaskPosted for shard {}", shard.encode().to_base58() ); }, - my_node_runtime::pallet_teerex::Event::ProcessedParentchainBlock( - accountid, - block_hash, - merkle_root, + my_node_runtime::pallet_teebag::Event::ParentchainBlockProcessed { + who, block_number, - ) => { + block_hash, + task_merkle_root, + } => { println!( - "ProcessedParentchainBlock from {} with hash {:?}, number {} and merkle root {:?}", - accountid, block_hash, merkle_root, block_number + "ParentchainBlockProcessed from {} with hash {:?}, number {} and merkle root {:?}", + who, block_hash, block_number, task_merkle_root ); }, - my_node_runtime::pallet_teerex::Event::ShieldFunds( - incognito_account, - ) => { - println!("ShieldFunds for {:?}", incognito_account); - }, - my_node_runtime::pallet_teerex::Event::UnshieldedFunds( - public_account, - ) => { - println!("UnshieldFunds for {:?}", public_account); - }, - _ => debug!("ignoring unsupported teerex event: {:?}", ee), - } - }, - RuntimeEvent::Sidechain(ee) => { - println!(">>>>>>>>>> integritee sidechain event: {:?}", ee); - count += 1; - match &ee { - my_node_runtime::pallet_sidechain::Event::ProposedSidechainBlock( - accountid, - block_hash, - ) => { + my_node_runtime::pallet_teebag::Event::SidechainBlockFinalized { + who, + sidechain_block_number, + } => { println!( - "ProposedSidechainBlock from {} with hash {:?}", - accountid, block_hash + "SidechainBlockFinalized from {} with number {:?}", + who, sidechain_block_number ); }, - _ => debug!("ignoring unsupported sidechain event: {:?}", ee), + _ => debug!("ignoring unsupported teebag event: {:?}", ee), } }, _ => debug!("ignoring unsupported module event: {:?}", evr.event), diff --git a/tee-worker/cli/src/base_cli/commands/litentry/link_identity.rs b/tee-worker/cli/src/base_cli/commands/litentry/link_identity.rs deleted file mode 100644 index 7c7f85a08a..0000000000 --- a/tee-worker/cli/src/base_cli/commands/litentry/link_identity.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -use super::IMP; -use crate::{ - command_utils::{get_chain_api, *}, - Cli, CliResult, CliResultOk, -}; -use base58::FromBase58; -use codec::{Decode, Encode}; -use itp_sgx_crypto::ShieldingCryptoEncrypt; -use itp_stf_primitives::types::ShardIdentifier; -use litentry_primitives::Identity; -use log::*; -use sp_application_crypto::Pair; -use sp_core::sr25519 as sr25519_core; -use substrate_api_client::{ac_compose_macros::compose_extrinsic, SubmitAndWatch, XtStatus}; - -#[derive(Parser)] -pub struct LinkIdentityCommand { - /// AccountId in ss58check format - account: String, - /// Identity to be created, in did form - did: String, - /// Shard identifier - shard: String, -} - -impl LinkIdentityCommand { - pub(crate) fn run(&self, cli: &Cli) -> CliResult { - let mut chain_api = get_chain_api(cli); - - let shard_opt = match self.shard.from_base58() { - Ok(s) => ShardIdentifier::decode(&mut &s[..]), - _ => panic!("shard argument must be base58 encoded"), - }; - - let shard = match shard_opt { - Ok(shard) => shard, - Err(e) => panic!("{}", e), - }; - - let who = sr25519_core::Pair::from_string(&self.account, None).unwrap(); - chain_api.set_signer(who.clone().into()); - - let identity = Identity::from_did(self.did.as_str()).unwrap(); - let tee_shielding_key = get_shielding_key(cli).unwrap(); - let encrypted_identity = tee_shielding_key.encrypt(&identity.encode()).unwrap(); - - // TODO: the params are incorrect - and need to be reworked too - let vdata: Option> = None; - let xt = compose_extrinsic!( - chain_api, - IMP, - "link_identity", - shard, - who.public().0, - encrypted_identity.to_vec(), - vdata - ); - - let tx_hash = chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap(); - println!("[+] LinkIdentityCommand TrustedOperation got finalized. Hash: {:?}\n", tx_hash); - - Ok(CliResultOk::None) - } -} diff --git a/tee-worker/cli/src/base_cli/commands/litentry/mod.rs b/tee-worker/cli/src/base_cli/commands/litentry/mod.rs index 71f772d2ed..d5be3f9c67 100644 --- a/tee-worker/cli/src/base_cli/commands/litentry/mod.rs +++ b/tee-worker/cli/src/base_cli/commands/litentry/mod.rs @@ -15,8 +15,3 @@ // along with Litentry. If not, see . pub mod id_graph_hash; -pub mod link_identity; -pub mod set_heartbeat_timeout; - -// TODO: maybe move it to use itp_node_api::api_client -pub const IMP: &str = "IdentityManagement"; diff --git a/tee-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs b/tee-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs deleted file mode 100644 index 996b369a59..0000000000 --- a/tee-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -use crate::{command_utils::get_chain_api, Cli}; - -use crate::{CliResult, CliResultOk}; -use itp_node_api::api_client::TEEREX; -use log::*; -use sp_keyring::AccountKeyring; -use substrate_api_client::{ac_compose_macros::compose_extrinsic, SubmitAndWatch, XtStatus}; -#[derive(Parser)] -pub struct SetHeartbeatTimeoutCommand { - /// Heartbeat timeout - timeout: u64, -} - -impl SetHeartbeatTimeoutCommand { - pub(crate) fn run(&self, cli: &Cli) -> CliResult { - let mut chain_api = get_chain_api(cli); - - // has to be //Alice as this is the genesis admin for teerex pallet, - // otherwise `set_heartbeat_timeout` call won't work - chain_api.set_signer(AccountKeyring::Alice.pair().into()); - - // call set_heartbeat_timeout - let xt = compose_extrinsic!( - chain_api, - TEEREX, - "set_heartbeat_timeout", - codec::Compact(self.timeout) - ); - - let tx_hash = chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap(); - println!( - "[+] SetHeartbeatTimeoutCommand TrustedOperation got finalized. Hash: {:?}\n", - tx_hash - ); - - Ok(CliResultOk::None) - } -} diff --git a/tee-worker/cli/src/base_cli/commands/mod.rs b/tee-worker/cli/src/base_cli/commands/mod.rs index 313a32249c..033b15b253 100644 --- a/tee-worker/cli/src/base_cli/commands/mod.rs +++ b/tee-worker/cli/src/base_cli/commands/mod.rs @@ -3,5 +3,4 @@ pub mod faucet; pub mod listen; pub mod litentry; pub mod register_tcb_info; -pub mod shield_funds; pub mod transfer; diff --git a/tee-worker/cli/src/base_cli/commands/register_tcb_info.rs b/tee-worker/cli/src/base_cli/commands/register_tcb_info.rs index 7802794a09..4ab9b55a45 100644 --- a/tee-worker/cli/src/base_cli/commands/register_tcb_info.rs +++ b/tee-worker/cli/src/base_cli/commands/register_tcb_info.rs @@ -19,7 +19,7 @@ use crate::{ command_utils::{get_chain_api, *}, Cli, CliResult, CliResultOk, }; -use itp_node_api::api_client::TEEREX; +use itp_node_api::api_client::TEEBAG; use itp_types::{parentchain::Hash, OpaqueCall}; use itp_utils::ToHexPrefixed; use log::*; @@ -106,7 +106,7 @@ impl RegisterTcbInfoCommand { let call = OpaqueCall::from_tuple(&compose_call!( chain_api.metadata(), - TEEREX, + TEEBAG, "register_tcb_info", tcb_info, intel_signature, diff --git a/tee-worker/cli/src/base_cli/commands/shield_funds.rs b/tee-worker/cli/src/base_cli/commands/shield_funds.rs deleted file mode 100644 index ec45da50fb..0000000000 --- a/tee-worker/cli/src/base_cli/commands/shield_funds.rs +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - command_utils::{get_accountid_from_str, get_chain_api, *}, - Cli, CliError, CliResult, CliResultOk, -}; -use base58::FromBase58; -use codec::{Decode, Encode}; -use itp_node_api::api_client::TEEREX; -use itp_sgx_crypto::ShieldingCryptoEncrypt; -use itp_stf_primitives::types::ShardIdentifier; -use litentry_primitives::ParentchainBalance as Balance; -use log::*; -use sp_core::sr25519 as sr25519_core; -use substrate_api_client::{ac_compose_macros::compose_extrinsic, SubmitAndWatch, XtStatus}; - -#[derive(Parser)] -pub struct ShieldFundsCommand { - /// Sender's parentchain AccountId in ss58check format. - from: String, - /// Recipient's incognito AccountId in ss58check format. - to: String, - /// Amount to be transferred. - amount: Balance, - /// Shard identifier. - shard: String, -} - -impl ShieldFundsCommand { - pub(crate) fn run(&self, cli: &Cli) -> CliResult { - let mut chain_api = get_chain_api(cli); - - let shard_opt = match self.shard.from_base58() { - Ok(s) => ShardIdentifier::decode(&mut &s[..]), - _ => panic!("shard argument must be base58 encoded"), - }; - - let shard = match shard_opt { - Ok(shard) => shard, - Err(e) => panic!("{}", e), - }; - - // Get the sender. - let from = get_pair_from_str(&self.from); - chain_api.set_signer(sr25519_core::Pair::from(from).into()); - - // Get the recipient. - let to = get_accountid_from_str(&self.to); - - let encryption_key = get_shielding_key(cli).unwrap(); - let encrypted_recevier = encryption_key.encrypt(&to.encode()).unwrap(); - - // Compose the extrinsic. - let xt = compose_extrinsic!( - chain_api, - TEEREX, - "shield_funds", - encrypted_recevier, - self.amount, - shard - ); - - match chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized) { - Ok(xt_report) => { - println!( - "[+] shield funds success. extrinsic hash: {:?} / status: {:?} / block hash: {:?}", - xt_report.extrinsic_hash, xt_report.status, xt_report.block_hash.unwrap() - ); - Ok(CliResultOk::H256 { hash: xt_report.block_hash.unwrap() }) - }, - Err(e) => { - error!("shield_funds extrinsic failed {:?}", e); - Err(CliError::Extrinsic { msg: format!("{:?}", e) }) - }, - } - } -} diff --git a/tee-worker/cli/src/base_cli/mod.rs b/tee-worker/cli/src/base_cli/mod.rs index 7270dd8dbb..225348d2d5 100644 --- a/tee-worker/cli/src/base_cli/mod.rs +++ b/tee-worker/cli/src/base_cli/mod.rs @@ -17,15 +17,8 @@ use crate::{ base_cli::commands::{ - balance::BalanceCommand, - faucet::FaucetCommand, - listen::ListenCommand, - litentry::{ - id_graph_hash::IDGraphHashCommand, link_identity::LinkIdentityCommand, - set_heartbeat_timeout::SetHeartbeatTimeoutCommand, - }, - register_tcb_info::RegisterTcbInfoCommand, - shield_funds::ShieldFundsCommand, + balance::BalanceCommand, faucet::FaucetCommand, listen::ListenCommand, + litentry::id_graph_hash::IDGraphHashCommand, register_tcb_info::RegisterTcbInfoCommand, transfer::TransferCommand, }, command_utils::*, @@ -35,7 +28,8 @@ use base58::ToBase58; use chrono::{DateTime, Utc}; use clap::Subcommand; use itc_rpc_client::direct_client::DirectApi; -use itp_node_api::api_client::PalletTeerexApi; +use itp_node_api::api_client::PalletTeebagApi; +use itp_types::WorkerType; use sp_core::crypto::Ss58Codec; use sp_keystore::Keystore; use std::{ @@ -78,21 +72,12 @@ pub enum BaseCommand { /// Register TCB info for FMSPC RegisterTcbInfo(RegisterTcbInfoCommand), - /// Transfer funds from an parentchain account to an incognito account - ShieldFunds(ShieldFundsCommand), - // Litentry's commands below /// query sgx-runtime metadata and print the raw (hex-encoded) metadata to stdout /// we could have added a parameter like `--raw` to `PrintSgxMetadata`, but /// we want to keep our changes isolated PrintSgxMetadataRaw, - /// create idenity graph - LinkIdentity(LinkIdentityCommand), - - /// set heartbeat timeout storage - SetHeartbeatTimeout(SetHeartbeatTimeoutCommand), - /// get the IDGraph hash of the given identity IDGraphHash(IDGraphHashCommand), } @@ -110,11 +95,8 @@ impl BaseCommand { BaseCommand::ListWorkers => list_workers(cli), BaseCommand::Listen(cmd) => cmd.run(cli), BaseCommand::RegisterTcbInfo(cmd) => cmd.run(cli), - BaseCommand::ShieldFunds(cmd) => cmd.run(cli), // Litentry's commands below BaseCommand::PrintSgxMetadataRaw => print_sgx_metadata_raw(cli), - BaseCommand::LinkIdentity(cmd) => cmd.run(cli), - BaseCommand::SetHeartbeatTimeout(cmd) => cmd.run(cli), BaseCommand::IDGraphHash(cmd) => cmd.run(cli), } } @@ -178,29 +160,22 @@ fn print_sgx_metadata_raw(cli: &Cli) -> CliResult { fn list_workers(cli: &Cli) -> CliResult { let api = get_chain_api(cli); - let wcount = api.enclave_count(None).unwrap(); - println!("number of workers registered: {}", wcount); - - let mut mr_enclaves = Vec::with_capacity(wcount as usize); - - for w in 1..=wcount { - let enclave = api.enclave(w, None).unwrap(); - if enclave.is_none() { - println!("error reading enclave data"); - continue - }; - let enclave = enclave.unwrap(); - let timestamp = - DateTime::::from(UNIX_EPOCH + Duration::from_millis(enclave.timestamp)); - let mr_enclave = enclave.mr_enclave.to_base58(); - println!("Enclave {}", w); - println!(" AccountId: {}", enclave.pubkey.to_ss58check()); - println!(" MRENCLAVE: {}", mr_enclave); - println!(" RA timestamp: {}", timestamp); - println!(" URL: {}", enclave.url); - - mr_enclaves.push(mr_enclave); - } + let enclaves = api.all_enclaves(WorkerType::Identity, None).unwrap(); + println!("number of enclaves registered: {}", enclaves.len()); + + let mr_enclaves = enclaves + .iter() + .map(|enclave| { + println!("Enclave"); + println!(" MRENCLAVE: {}", enclave.mrenclave.to_base58()); + let timestamp = DateTime::::from( + UNIX_EPOCH + Duration::from_millis(enclave.last_seen_timestamp), + ); + println!(" Last seen: {}", timestamp); + println!(" URL: {}", String::from_utf8_lossy(enclave.url.as_slice())); + enclave.mrenclave.to_base58() + }) + .collect(); Ok(CliResultOk::MrEnclaveBase58 { mr_enclaves }) } diff --git a/tee-worker/cli/src/commands.rs b/tee-worker/cli/src/commands.rs index e01a79d930..17b5ea42c4 100644 --- a/tee-worker/cli/src/commands.rs +++ b/tee-worker/cli/src/commands.rs @@ -19,9 +19,6 @@ extern crate chrono; use crate::{base_cli::BaseCommand, trusted_cli::TrustedCli, Cli, CliResult, CliResultOk}; use clap::Subcommand; -#[cfg(feature = "teeracle")] -use crate::oracle::OracleCommand; - use crate::attesteer::AttesteerCommand; #[derive(Subcommand)] @@ -33,11 +30,6 @@ pub enum Commands { #[clap(after_help = "stf subcommands depend on the stf crate this has been built against")] Trusted(TrustedCli), - /// Subcommands for the oracle. - #[cfg(feature = "teeracle")] - #[clap(subcommand)] - Oracle(OracleCommand), - /// Subcommand for the attesteer. #[clap(subcommand)] Attesteer(AttesteerCommand), @@ -47,11 +39,6 @@ pub fn match_command(cli: &Cli) -> CliResult { match &cli.command { Commands::Base(cmd) => cmd.run(cli), Commands::Trusted(trusted_cli) => trusted_cli.run(cli), - #[cfg(feature = "teeracle")] - Commands::Oracle(cmd) => { - cmd.run(cli); - Ok(CliResultOk::None) - }, Commands::Attesteer(cmd) => { cmd.run(cli); Ok(CliResultOk::None) diff --git a/tee-worker/cli/src/lib.rs b/tee-worker/cli/src/lib.rs index 5c39e1ff19..c7b2bb5b63 100644 --- a/tee-worker/cli/src/lib.rs +++ b/tee-worker/cli/src/lib.rs @@ -35,8 +35,6 @@ mod command_utils; mod error; #[cfg(feature = "evm")] mod evm; -#[cfg(feature = "teeracle")] -mod oracle; mod trusted_base_cli; mod trusted_cli; mod trusted_command_utils; @@ -61,7 +59,6 @@ pub(crate) const ED25519_KEY_TYPE: KeyTypeId = KeyTypeId(*b"ed25"); #[clap(version = VERSION)] #[clap(author = "Trust Computing GmbH ")] #[clap(about = "cli tool to interact with litentry-parachain and workers", long_about = None)] -#[cfg_attr(feature = "teeracle", clap(about = "interact with litentry-parachain and teeracle", long_about = None))] #[cfg_attr(feature = "sidechain", clap(about = "interact with litentry-parachain and sidechain", long_about = None))] #[cfg_attr(feature = "offchain-worker", clap(about = "interact with litentry-parachain and offchain-worker", long_about = None))] #[clap(after_help = "stf subcommands depend on the stf crate this has been built against")] diff --git a/tee-worker/cli/src/oracle/commands/add_to_whitelist.rs b/tee-worker/cli/src/oracle/commands/add_to_whitelist.rs deleted file mode 100644 index 98afeb801d..0000000000 --- a/tee-worker/cli/src/oracle/commands/add_to_whitelist.rs +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - command_utils::{get_chain_api, get_pair_from_str, mrenclave_from_base58}, - Cli, -}; -use itp_node_api::api_client::{ADD_TO_WHITELIST, TEERACLE}; -use substrate_api_client::{ - ac_compose_macros::{compose_call, compose_extrinsic}, - SubmitAndWatch, XtStatus, -}; - -/// Add a trusted market data source to the on-chain whitelist. -#[derive(Debug, Clone, Parser)] -pub struct AddToWhitelistCmd { - /// Sender's on-chain AccountId in ss58check format. - /// - /// It has to be a sudo account. - from: String, - - /// Market data URL - source: String, - - /// MRENCLAVE of the oracle worker base58 encoded. - mrenclave: String, -} - -impl AddToWhitelistCmd { - pub fn run(&self, cli: &Cli) { - let mut api = get_chain_api(cli); - let mrenclave = mrenclave_from_base58(&self.mrenclave); - let from = get_pair_from_str(&self.from); - - let market_data_source = self.source.clone(); - - api.set_signer(from.into()); - - let call = compose_call!( - api.metadata(), - TEERACLE, - ADD_TO_WHITELIST, - market_data_source, - mrenclave - ); - - // compose the extrinsic - let xt = compose_extrinsic!(api, "Sudo", "sudo", call); - - let report = api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap(); - println!("[+] Add to whitelist got finalized. Hash: {:?}\n", report.extrinsic_hash); - } -} diff --git a/tee-worker/cli/src/oracle/commands/listen_to_exchange.rs b/tee-worker/cli/src/oracle/commands/listen_to_exchange.rs deleted file mode 100644 index 181be4febd..0000000000 --- a/tee-worker/cli/src/oracle/commands/listen_to_exchange.rs +++ /dev/null @@ -1,79 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{command_utils::get_chain_api, Cli}; -use itp_node_api::api_client::ParentchainApi; -use itp_time_utils::{duration_now, remaining_time}; -use log::{debug, info, trace}; -use my_node_runtime::{Hash, RuntimeEvent}; -use std::time::Duration; -use substrate_api_client::SubscribeEvents; - -/// Listen to exchange rate events. -#[derive(Debug, Clone, Parser)] -pub struct ListenToExchangeRateEventsCmd { - /// Listen for `duration` in seconds. - duration: u64, -} - -impl ListenToExchangeRateEventsCmd { - pub fn run(&self, cli: &Cli) { - let api = get_chain_api(cli); - let duration = Duration::from_secs(self.duration); - - let count = count_exchange_rate_update_events(&api, duration); - - println!("Number of ExchangeRateUpdated events received : "); - println!(" EVENTS_COUNT: {}", count); - } -} - -pub fn count_exchange_rate_update_events(api: &ParentchainApi, duration: Duration) -> u32 { - let stop = duration_now() + duration; - - //subscribe to events - let mut subscription = api.subscribe_events().unwrap(); - let mut count = 0; - - while remaining_time(stop).unwrap_or_default() > Duration::ZERO { - let events_result = subscription.next_events::().unwrap(); - if let Ok(events) = events_result { - for event_record in &events { - info!("received event {:?}", event_record.event); - if let RuntimeEvent::Teeracle(event) = &event_record.event { - match &event { - my_node_runtime::pallet_teeracle::Event::ExchangeRateUpdated( - data_source, - trading_pair, - exchange_rate, - ) => { - count += 1; - debug!("Received ExchangeRateUpdated event"); - println!( - "ExchangeRateUpdated: TRADING_PAIR : {}, SRC : {}, VALUE :{:?}", - trading_pair, data_source, exchange_rate - ); - }, - _ => trace!("ignoring teeracle event: {:?}", event), - } - } - } - } - } - debug!("Received {} ExchangeRateUpdated event(s) in total", count); - count -} diff --git a/tee-worker/cli/src/oracle/commands/listen_to_oracle.rs b/tee-worker/cli/src/oracle/commands/listen_to_oracle.rs deleted file mode 100644 index 87cc334040..0000000000 --- a/tee-worker/cli/src/oracle/commands/listen_to_oracle.rs +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{command_utils::get_chain_api, Cli}; -use itp_node_api::api_client::ParentchainApi; -use itp_time_utils::{duration_now, remaining_time}; -use log::{debug, info}; -use my_node_runtime::{Hash, RuntimeEvent}; -use std::time::Duration; -use substrate_api_client::{ac_node_api::EventRecord, SubscribeEvents}; - -/// Listen to exchange rate events. -#[derive(Debug, Clone, Parser)] -pub struct ListenToOracleEventsCmd { - /// Listen for `duration` in seconds. - duration: u64, -} - -type EventCount = u32; -type Event = EventRecord; - -impl ListenToOracleEventsCmd { - pub fn run(&self, cli: &Cli) { - let api = get_chain_api(cli); - let duration = Duration::from_secs(self.duration); - let count = count_oracle_update_events(&api, duration); - println!("Number of Oracle events received : "); - println!(" EVENTS_COUNT: {}", count); - } -} - -fn count_oracle_update_events(api: &ParentchainApi, duration: Duration) -> EventCount { - let stop = duration_now() + duration; - - //subscribe to events - let mut subscription = api.subscribe_events().unwrap(); - let mut count = 0; - - while remaining_time(stop).unwrap_or_default() > Duration::ZERO { - let events_result = subscription.next_events::(); - let event_count = match events_result { - Some(Ok(event_records)) => { - debug!("Could not successfully decode event_bytes {:?}", event_records); - report_event_count(event_records) - }, - _ => 0, - }; - count += event_count; - } - debug!("Received {} ExchangeRateUpdated event(s) in total", count); - count -} - -fn report_event_count(event_records: Vec) -> EventCount { - let mut count = 0; - event_records.iter().for_each(|event_record| { - info!("received event {:?}", event_record.event); - if let RuntimeEvent::Teeracle(event) = &event_record.event { - match &event { - my_node_runtime::pallet_teeracle::Event::OracleUpdated( - oracle_data_name, - data_source, - ) => { - count += 1; - debug!("Received OracleUpdated event"); - println!( - "OracleUpdated: ORACLE_NAME : {}, SRC : {}", - oracle_data_name, data_source - ); - }, - // Can just remove this and ignore handling this case - _ => debug!("ignoring teeracle event: {:?}", event), - } - } - }); - count -} diff --git a/tee-worker/cli/src/oracle/commands/mod.rs b/tee-worker/cli/src/oracle/commands/mod.rs deleted file mode 100644 index 22b0a326c6..0000000000 --- a/tee-worker/cli/src/oracle/commands/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -mod add_to_whitelist; -mod listen_to_exchange; -mod listen_to_oracle; - -pub use self::{ - add_to_whitelist::AddToWhitelistCmd, listen_to_exchange::ListenToExchangeRateEventsCmd, - listen_to_oracle::ListenToOracleEventsCmd, -}; diff --git a/tee-worker/cli/src/oracle/mod.rs b/tee-worker/cli/src/oracle/mod.rs deleted file mode 100644 index e12f117cd4..0000000000 --- a/tee-worker/cli/src/oracle/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Add cli commands for the oracle -//! -//! Todo: This shall be a standalone crate in app-libs/oracle. However, this needs: -//! https://github.com/integritee-network/worker/issues/852 - -use crate::Cli; -use commands::{AddToWhitelistCmd, ListenToExchangeRateEventsCmd, ListenToOracleEventsCmd}; - -mod commands; - -/// Oracle subcommands for the cli. -#[derive(Debug, clap::Subcommand)] -pub enum OracleCommand { - /// Add a market source to the teeracle's whitelist. - AddToWhitelist(AddToWhitelistCmd), - - /// Listen to exchange rate events - ListenToExchangeRateEvents(ListenToExchangeRateEventsCmd), - - /// Listen to all oracles event updates - ListenToOracleEvents(ListenToOracleEventsCmd), -} - -impl OracleCommand { - pub fn run(&self, cli: &Cli) { - match self { - OracleCommand::AddToWhitelist(cmd) => cmd.run(cli), - OracleCommand::ListenToExchangeRateEvents(cmd) => cmd.run(cli), - OracleCommand::ListenToOracleEvents(cmd) => cmd.run(cli), - } - } -} diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/mod.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/mod.rs index d582982aee..40ecceefaf 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/mod.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/mod.rs @@ -20,5 +20,4 @@ pub mod id_graph_stats; pub mod link_identity; pub mod remove_identity; pub mod request_vc; -pub mod request_vc_direct; pub mod send_erroneous_parentchain_call; diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs index 17158a882a..a8fcc74190 100644 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs +++ b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc.rs @@ -18,7 +18,7 @@ use crate::{ get_layer_two_nonce, trusted_cli::TrustedCli, trusted_command_utils::{get_identifiers, get_pair_from_str}, - trusted_operation::perform_trusted_operation, + trusted_operation::{perform_direct_operation, perform_trusted_operation}, Cli, CliResult, CliResultOk, }; use ita_stf::{trusted_call_result::RequestVCResult, Index, TrustedCall, TrustedCallSigning}; @@ -29,8 +29,9 @@ use litentry_primitives::{ AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableParams, AchainableToken, Assertion, BoundedWeb3Network, ContestType, EVMTokenType, - GenericDiscordRoleType, Identity, OneBlockCourseType, ParameterString, RequestAesKey, - SoraQuizType, VIP3MembershipCardLevel, Web3Network, Web3TokenType, REQUEST_AES_KEY_LEN, + GenericDiscordRoleType, Identity, OneBlockCourseType, ParameterString, PlatformUserType, + RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, Web3Network, Web3NftType, Web3TokenType, + REQUEST_AES_KEY_LEN, }; use sp_core::Pair; @@ -40,9 +41,9 @@ use sp_core::Pair; // ./bin/litentry-cli trusted -d request-vc \ // did:litentry:substrate:0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 a8 litentry,litmus // -// oneblock VC: +// OneBlock VC: // ./bin/litentry-cli trusted -d request-vc \ -// did:litentry:substrate:0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 oneblock completion +// did:litentry:substrate:0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 one-block completion // // achainable VC: // ./bin/litentry-cli trusted -d request-vc \ @@ -74,6 +75,9 @@ pub struct RequestVcCommand { /// subcommand to define the vc type requested #[clap(subcommand)] command: Command, + /// mode for the request-vc + #[clap(short = 's', long, default_value_t = false)] + stf: bool, } // see `assertion.rs` @@ -93,7 +97,7 @@ pub enum Command { A20, BnbDomainHolding, #[clap(subcommand)] - Oneblock(OneblockCommand), + OneBlock(OneblockCommand), #[clap(subcommand)] Achainable(AchainableCommand), #[clap(subcommand)] @@ -108,6 +112,10 @@ pub enum Command { BRC20AmountHolder, #[clap(subcommand)] TokenHoldingAmount(TokenHoldingAmountCommand), + #[clap(subcommand)] + PlatformUser(PlatformUserCommand), + #[clap(subcommand)] + NftHolder(NftHolderCommand), } #[derive(Args, Debug)] @@ -220,14 +228,15 @@ pub enum TokenHoldingAmountCommand { Trx, } -// I haven't found a good way to use common args for subcommands -#[derive(Args, Debug)] -pub struct AmountHoldingArg { - pub name: String, - pub chain: String, - pub amount: String, - pub date: String, - pub token: Option, +#[derive(Subcommand, Debug)] +pub enum PlatformUserCommand { + KaratDaoUser, +} + +#[derive(Subcommand, Debug)] +pub enum NftHolderCommand { + WeirdoGhostGang, + Club3Sbt, } // positional args (to vec) + required arg + optional arg is a nightmare combination for clap parser, @@ -236,85 +245,70 @@ pub struct AmountHoldingArg { // the best bet is to use a flag explicitly, be sure to use euqal form for `chain`, e.g.: // -- name -c=bsc,ethereum 10 // -- name -c=bsc,ethereum 10 token -#[derive(Args, Debug)] -pub struct AmountTokenArg { - pub name: String, - #[clap( - short, long, - num_args = 1.., - required = true, - value_delimiter = ',', - )] - pub chain: Vec, - pub amount: String, - pub token: Option, +macro_rules! AchainableCommandArgs { + ($type_name:ident, {$( $field_name:ident : $field_type:ty , )* }) => { + #[derive(Args, Debug)] + pub struct $type_name { + pub name: String, + #[clap( + short, long, + num_args = 1.., + required = true, + value_delimiter = ',', + )] + pub chain: Vec, + $( pub $field_name: $field_type ),* + } + }; } -#[derive(Args, Debug)] -pub struct AmountArg { - pub name: String, - pub chain: String, - pub amount: String, -} +AchainableCommandArgs!(AmountHoldingArg, { + amount: String, + date: String, + token: Option, +}); -#[derive(Args, Debug)] -pub struct AmountsArg { - pub name: String, - pub chain: String, - pub amount1: String, - pub amount2: String, -} +AchainableCommandArgs!(AmountTokenArg, { + amount: String, + token: Option, +}); -#[derive(Args, Debug)] -pub struct BasicArg { - pub name: String, - pub chain: String, -} +AchainableCommandArgs!(AmountArg, { + amount: String, +}); -#[derive(Args, Debug)] -pub struct BetweenPercentsArg { - pub name: String, - pub chain: String, - pub greater_than_or_equal_to: String, - pub less_than_or_equal_to: String, -} +AchainableCommandArgs!(AmountsArg, { + amount1: String, + amount2: String, +}); -#[derive(Args, Debug)] -pub struct ClassOfYearArg { - pub name: String, - pub chain: String, -} +AchainableCommandArgs!(BasicArg, {}); -#[derive(Args, Debug)] -pub struct DateIntervalArg { - pub name: String, - pub chain: String, - pub start_date: String, - pub end_date: String, -} +AchainableCommandArgs!(BetweenPercentsArg, { + greater_than_or_equal_to: String, + less_than_or_equal_to: String, +}); -#[derive(Args, Debug)] -pub struct DatePercentArg { - pub name: String, - pub chain: String, - pub token: String, - pub date: String, - pub percent: String, -} +AchainableCommandArgs!(ClassOfYearArg, {}); -#[derive(Args, Debug)] -pub struct DateArg { - pub name: String, - pub chain: String, - pub date: String, -} +AchainableCommandArgs!(DateIntervalArg, { + start_date: String, + end_date: String, +}); -#[derive(Args, Debug)] -pub struct TokenArg { - pub name: String, - pub chain: String, - pub token: String, -} +AchainableCommandArgs!(DatePercentArg, { + token: String, + date: String, + percent: String, +}); + +AchainableCommandArgs!(DateArg, { + date: String, +}); + +AchainableCommandArgs!(TokenArg, { + token: String, +}); impl RequestVcCommand { pub(crate) fn run(&self, cli: &Cli, trusted_cli: &TrustedCli) -> CliResult { @@ -349,23 +343,19 @@ impl RequestVcCommand { Command::A14 => Assertion::A14, Command::A20 => Assertion::A20, Command::BnbDomainHolding => Assertion::BnbDomainHolding, - Command::Oneblock(c) => match c { + Command::OneBlock(c) => match c { OneblockCommand::Completion => - Assertion::Oneblock(OneBlockCourseType::CourseCompletion), + Assertion::OneBlock(OneBlockCourseType::CourseCompletion), OneblockCommand::Outstanding => - Assertion::Oneblock(OneBlockCourseType::CourseOutstanding), + Assertion::OneBlock(OneBlockCourseType::CourseOutstanding), OneblockCommand::Participation => - Assertion::Oneblock(OneBlockCourseType::CourseParticipation), + Assertion::OneBlock(OneBlockCourseType::CourseParticipation), }, Command::Achainable(c) => match c { AchainableCommand::AmountHolding(arg) => Assertion::Achainable( AchainableParams::AmountHolding(AchainableAmountHolding { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), amount: to_para_str(&arg.amount), date: to_para_str(&arg.date), token: arg.token.as_ref().map(|s| to_para_str(s)), @@ -381,41 +371,25 @@ impl RequestVcCommand { AchainableCommand::Amount(arg) => Assertion::Achainable(AchainableParams::Amount(AchainableAmount { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), amount: to_para_str(&arg.amount), })), AchainableCommand::Amounts(arg) => Assertion::Achainable(AchainableParams::Amounts(AchainableAmounts { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), amount1: to_para_str(&arg.amount1), amount2: to_para_str(&arg.amount2), })), AchainableCommand::Basic(arg) => Assertion::Achainable(AchainableParams::Basic(AchainableBasic { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), })), AchainableCommand::BetweenPercents(arg) => Assertion::Achainable( AchainableParams::BetweenPercents(AchainableBetweenPercents { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), greater_than_or_equal_to: to_para_str(&arg.greater_than_or_equal_to), less_than_or_equal_to: to_para_str(&arg.less_than_or_equal_to), }), @@ -423,31 +397,19 @@ impl RequestVcCommand { AchainableCommand::ClassOfYear(arg) => Assertion::Achainable(AchainableParams::ClassOfYear(AchainableClassOfYear { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), })), AchainableCommand::DateInterval(arg) => Assertion::Achainable(AchainableParams::DateInterval(AchainableDateInterval { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), start_date: to_para_str(&arg.start_date), end_date: to_para_str(&arg.end_date), })), AchainableCommand::DatePercent(arg) => Assertion::Achainable(AchainableParams::DatePercent(AchainableDatePercent { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), date: to_para_str(&arg.date), percent: to_para_str(&arg.percent), token: to_para_str(&arg.token), @@ -455,21 +417,13 @@ impl RequestVcCommand { AchainableCommand::Date(arg) => Assertion::Achainable(AchainableParams::Date(AchainableDate { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), date: to_para_str(&arg.date), })), AchainableCommand::Token(arg) => Assertion::Achainable(AchainableParams::Token(AchainableToken { name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), + chain: to_chains(&arg.chain), token: to_para_str(&arg.token), })), }, @@ -544,6 +498,15 @@ impl RequestVcCommand { TokenHoldingAmountCommand::Ton => Assertion::TokenHoldingAmount(Web3TokenType::Ton), TokenHoldingAmountCommand::Trx => Assertion::TokenHoldingAmount(Web3TokenType::Trx), }, + Command::PlatformUser(arg) => match arg { + PlatformUserCommand::KaratDaoUser => + Assertion::PlatformUser(PlatformUserType::KaratDaoUser), + }, + Command::NftHolder(arg) => match arg { + NftHolderCommand::WeirdoGhostGang => + Assertion::NftHolder(Web3NftType::WeirdoGhostGang), + NftHolderCommand::Club3Sbt => Assertion::NftHolder(Web3NftType::Club3Sbt), + }, }; let key = Self::random_aes_key(); @@ -558,7 +521,13 @@ impl RequestVcCommand { .sign(&KeyPair::Sr25519(Box::new(alice)), nonce, &mrenclave, &shard) .into_trusted_operation(trusted_cli.direct); - match perform_trusted_operation::(cli, trusted_cli, &top) { + let maybe_vc = if self.stf { + perform_trusted_operation::(cli, trusted_cli, &top) + } else { + perform_direct_operation::(cli, trusted_cli, &top, key) + }; + + match maybe_vc { Ok(mut vc) => { let decrypted = aes_decrypt(&key, &mut vc.vc_payload).unwrap(); let credential_str = String::from_utf8(decrypted).expect("Found invalid UTF-8"); @@ -569,6 +538,7 @@ impl RequestVcCommand { println!("{:?}", e); }, } + Ok(CliResultOk::None) } diff --git a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs b/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs deleted file mode 100644 index 15e5153610..0000000000 --- a/tee-worker/cli/src/trusted_base_cli/commands/litentry/request_vc_direct.rs +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2020-2024 Trust Computing GmbH. -// This file is part of Litentry. -// -// Litentry is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Litentry is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Litentry. If not, see . - -use crate::{ - get_layer_two_nonce, - trusted_base_cli::commands::litentry::request_vc::*, - trusted_cli::TrustedCli, - trusted_command_utils::{get_identifiers, get_pair_from_str}, - trusted_operation::perform_direct_operation, - Cli, CliResult, CliResultOk, -}; -use ita_stf::{trusted_call_result::RequestVCResult, Index, TrustedCall, TrustedCallSigning}; -use itp_stf_primitives::types::KeyPair; -use litentry_hex_utils::decode_hex; -use litentry_primitives::{ - aes_decrypt, AchainableAmount, AchainableAmountHolding, AchainableAmountToken, - AchainableAmounts, AchainableBasic, AchainableBetweenPercents, AchainableClassOfYear, - AchainableDate, AchainableDateInterval, AchainableDatePercent, AchainableParams, - AchainableToken, Assertion, ContestType, EVMTokenType, GenericDiscordRoleType, Identity, - OneBlockCourseType, RequestAesKey, SoraQuizType, VIP3MembershipCardLevel, Web3Network, - Web3TokenType, REQUEST_AES_KEY_LEN, -}; -use sp_core::Pair; - -// usage example (you can always use --help on subcommands to see more details) -// -// a8: -// ./bin/litentry-cli trusted -d request-vc-direct \ -// did:litentry:substrate:0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 a8 litentry,litmus -// -// oneblock VC: -// ./bin/litentry-cli trusted -d request-vc-direct \ -// did:litentry:substrate:0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 oneblock completion -// -// achainable VC: -// ./bin/litentry-cli trusted -d request-vc-direct \ -// did:litentry:substrate:0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 achainable amount-holding a litentry 1 2014-05-01 -// -// vip3 VC: -// ./bin/litentry-cli trusted -d request-vc-direct \ -// did:litentry:substrate:0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 vip3-membership-card gold - -#[derive(Parser)] -pub struct RequestVcDirectCommand { - /// did account to whom the vc will be issued - did: String, - /// subcommand to define the vc type requested - #[clap(subcommand)] - command: Command, -} - -impl RequestVcDirectCommand { - pub(crate) fn run(&self, cli: &Cli, trusted_cli: &TrustedCli) -> CliResult { - let alice = get_pair_from_str(trusted_cli, "//Alice", cli); - let id: Identity = Identity::from_did(self.did.as_str()).unwrap(); - - let (mrenclave, shard) = get_identifiers(trusted_cli, cli); - let nonce = get_layer_two_nonce!(alice, cli, trusted_cli); - - let assertion = match &self.command { - Command::A1 => Assertion::A1, - Command::A2(arg) => Assertion::A2(to_para_str(&arg.guild_id)), - Command::A3(arg) => Assertion::A3( - to_para_str(&arg.guild_id), - to_para_str(&arg.channel_id), - to_para_str(&arg.role_id), - ), - Command::A4(arg) => Assertion::A4(to_para_str(&arg.minimum_amount)), - Command::A6 => Assertion::A6, - Command::A7(arg) => Assertion::A7(to_para_str(&arg.minimum_amount)), - Command::A8(arg) => { - let networks: Vec = arg - .networks - .iter() - .map(|n| n.as_str().try_into().expect("cannot convert to Web3Network")) - .collect(); - Assertion::A8(networks.try_into().unwrap()) - }, - Command::A10(arg) => Assertion::A10(to_para_str(&arg.minimum_amount)), - Command::A11(arg) => Assertion::A11(to_para_str(&arg.minimum_amount)), - Command::A13(arg) => { - let raw: [u8; 32] = decode_hex(&arg.account).unwrap().try_into().unwrap(); - Assertion::A13(raw.into()) - }, - Command::A14 => Assertion::A14, - Command::A20 => Assertion::A20, - Command::BnbDomainHolding => Assertion::BnbDomainHolding, - Command::Oneblock(c) => match c { - OneblockCommand::Completion => - Assertion::Oneblock(OneBlockCourseType::CourseCompletion), - OneblockCommand::Outstanding => - Assertion::Oneblock(OneBlockCourseType::CourseOutstanding), - OneblockCommand::Participation => - Assertion::Oneblock(OneBlockCourseType::CourseParticipation), - }, - Command::Achainable(c) => match c { - AchainableCommand::AmountHolding(arg) => Assertion::Achainable( - AchainableParams::AmountHolding(AchainableAmountHolding { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - amount: to_para_str(&arg.amount), - date: to_para_str(&arg.date), - token: arg.token.as_ref().map(|s| to_para_str(s)), - }), - ), - AchainableCommand::AmountToken(arg) => - Assertion::Achainable(AchainableParams::AmountToken(AchainableAmountToken { - name: to_para_str(&arg.name), - chain: to_chains(&arg.chain), - amount: to_para_str(&arg.amount), - token: arg.token.as_ref().map(|s| to_para_str(s)), - })), - AchainableCommand::Amount(arg) => - Assertion::Achainable(AchainableParams::Amount(AchainableAmount { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - amount: to_para_str(&arg.amount), - })), - AchainableCommand::Amounts(arg) => - Assertion::Achainable(AchainableParams::Amounts(AchainableAmounts { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - amount1: to_para_str(&arg.amount1), - amount2: to_para_str(&arg.amount2), - })), - AchainableCommand::Basic(arg) => - Assertion::Achainable(AchainableParams::Basic(AchainableBasic { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - })), - AchainableCommand::BetweenPercents(arg) => Assertion::Achainable( - AchainableParams::BetweenPercents(AchainableBetweenPercents { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - greater_than_or_equal_to: to_para_str(&arg.greater_than_or_equal_to), - less_than_or_equal_to: to_para_str(&arg.less_than_or_equal_to), - }), - ), - AchainableCommand::ClassOfYear(arg) => - Assertion::Achainable(AchainableParams::ClassOfYear(AchainableClassOfYear { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - })), - AchainableCommand::DateInterval(arg) => - Assertion::Achainable(AchainableParams::DateInterval(AchainableDateInterval { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - start_date: to_para_str(&arg.start_date), - end_date: to_para_str(&arg.end_date), - })), - AchainableCommand::DatePercent(arg) => - Assertion::Achainable(AchainableParams::DatePercent(AchainableDatePercent { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - date: to_para_str(&arg.date), - percent: to_para_str(&arg.percent), - token: to_para_str(&arg.token), - })), - AchainableCommand::Date(arg) => - Assertion::Achainable(AchainableParams::Date(AchainableDate { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - date: to_para_str(&arg.date), - })), - AchainableCommand::Token(arg) => - Assertion::Achainable(AchainableParams::Token(AchainableToken { - name: to_para_str(&arg.name), - chain: arg - .chain - .as_str() - .try_into() - .expect("cannot convert to Web3Network"), - token: to_para_str(&arg.token), - })), - }, - Command::GenericDiscordRole(c) => match c { - GenericDiscordRoleCommand::Contest(s) => match s { - ContestCommand::Legend => Assertion::GenericDiscordRole( - GenericDiscordRoleType::Contest(ContestType::Legend), - ), - ContestCommand::Popularity => Assertion::GenericDiscordRole( - GenericDiscordRoleType::Contest(ContestType::Popularity), - ), - ContestCommand::Participant => Assertion::GenericDiscordRole( - GenericDiscordRoleType::Contest(ContestType::Participant), - ), - }, - GenericDiscordRoleCommand::SoraQuiz(s) => match s { - SoraQuizCommand::Attendee => Assertion::GenericDiscordRole( - GenericDiscordRoleType::SoraQuiz(SoraQuizType::Attendee), - ), - SoraQuizCommand::Master => Assertion::GenericDiscordRole( - GenericDiscordRoleType::SoraQuiz(SoraQuizType::Master), - ), - }, - }, - Command::VIP3MembershipCard(arg) => match arg { - VIP3MembershipCardLevelCommand::Gold => - Assertion::VIP3MembershipCard(VIP3MembershipCardLevel::Gold), - VIP3MembershipCardLevelCommand::Silver => - Assertion::VIP3MembershipCard(VIP3MembershipCardLevel::Silver), - }, - Command::WeirdoGhostGangHolder => Assertion::WeirdoGhostGangHolder, - Command::EVMAmountHolding(c) => match c { - EVMAmountHoldingCommand::Ton => Assertion::EVMAmountHolding(EVMTokenType::Ton), - EVMAmountHoldingCommand::Trx => Assertion::EVMAmountHolding(EVMTokenType::Trx), - }, - Command::CryptoSummary => Assertion::CryptoSummary, - Command::LITStaking => Assertion::LITStaking, - Command::BRC20AmountHolder => Assertion::BRC20AmountHolder, - Command::TokenHoldingAmount(arg) => match arg { - TokenHoldingAmountCommand::Bnb => Assertion::TokenHoldingAmount(Web3TokenType::Bnb), - TokenHoldingAmountCommand::Eth => Assertion::TokenHoldingAmount(Web3TokenType::Eth), - TokenHoldingAmountCommand::SpaceId => - Assertion::TokenHoldingAmount(Web3TokenType::SpaceId), - TokenHoldingAmountCommand::Lit => Assertion::TokenHoldingAmount(Web3TokenType::Lit), - TokenHoldingAmountCommand::Wbtc => - Assertion::TokenHoldingAmount(Web3TokenType::Wbtc), - TokenHoldingAmountCommand::Usdc => - Assertion::TokenHoldingAmount(Web3TokenType::Usdc), - TokenHoldingAmountCommand::Usdt => - Assertion::TokenHoldingAmount(Web3TokenType::Usdt), - TokenHoldingAmountCommand::Crv => Assertion::TokenHoldingAmount(Web3TokenType::Crv), - TokenHoldingAmountCommand::Matic => - Assertion::TokenHoldingAmount(Web3TokenType::Matic), - TokenHoldingAmountCommand::Dydx => - Assertion::TokenHoldingAmount(Web3TokenType::Dydx), - TokenHoldingAmountCommand::Amp => Assertion::TokenHoldingAmount(Web3TokenType::Amp), - TokenHoldingAmountCommand::Cvx => Assertion::TokenHoldingAmount(Web3TokenType::Cvx), - TokenHoldingAmountCommand::Tusd => - Assertion::TokenHoldingAmount(Web3TokenType::Tusd), - TokenHoldingAmountCommand::Usdd => - Assertion::TokenHoldingAmount(Web3TokenType::Usdd), - TokenHoldingAmountCommand::Gusd => - Assertion::TokenHoldingAmount(Web3TokenType::Gusd), - TokenHoldingAmountCommand::Link => - Assertion::TokenHoldingAmount(Web3TokenType::Link), - TokenHoldingAmountCommand::Grt => Assertion::TokenHoldingAmount(Web3TokenType::Grt), - TokenHoldingAmountCommand::Comp => - Assertion::TokenHoldingAmount(Web3TokenType::Comp), - TokenHoldingAmountCommand::People => - Assertion::TokenHoldingAmount(Web3TokenType::People), - TokenHoldingAmountCommand::Gtc => Assertion::TokenHoldingAmount(Web3TokenType::Gtc), - TokenHoldingAmountCommand::Ton => Assertion::TokenHoldingAmount(Web3TokenType::Ton), - TokenHoldingAmountCommand::Trx => Assertion::TokenHoldingAmount(Web3TokenType::Trx), - }, - }; - - let key: [u8; 32] = Self::random_aes_key(); - - let top = TrustedCall::request_vc( - alice.public().into(), - id, - assertion, - Some(key), - Default::default(), - ) - .sign(&KeyPair::Sr25519(Box::new(alice)), nonce, &mrenclave, &shard) - .into_trusted_operation(trusted_cli.direct); - - // This should contain the AES Key for AESRequest - match perform_direct_operation::(cli, trusted_cli, &top, key) { - Ok(mut vc) => { - let decrypted = aes_decrypt(&key, &mut vc.vc_payload).unwrap(); - let credential_str = String::from_utf8(decrypted).expect("Found invalid UTF-8"); - println!("----Generated VC-----"); - println!("{}", credential_str); - }, - Err(e) => { - println!("{:?}", e); - }, - } - Ok(CliResultOk::None) - } - - fn random_aes_key() -> RequestAesKey { - let random: Vec = (0..REQUEST_AES_KEY_LEN).map(|_| rand::random::()).collect(); - random[0..REQUEST_AES_KEY_LEN].try_into().unwrap() - } -} diff --git a/tee-worker/cli/src/trusted_base_cli/mod.rs b/tee-worker/cli/src/trusted_base_cli/mod.rs index 878d3e5f2f..cc221ec281 100644 --- a/tee-worker/cli/src/trusted_base_cli/mod.rs +++ b/tee-worker/cli/src/trusted_base_cli/mod.rs @@ -23,7 +23,7 @@ use crate::{ litentry::{ get_storage::GetStorageCommand, id_graph_stats::IDGraphStats, link_identity::LinkIdentityCommand, remove_identity::RemoveIdentityCommand, - request_vc::RequestVcCommand, request_vc_direct::RequestVcDirectCommand, + request_vc::RequestVcCommand, send_erroneous_parentchain_call::SendErroneousParentchainCallCommand, }, nonce::NonceCommand, @@ -93,9 +93,6 @@ pub enum TrustedBaseCommand { /// Request VC RequestVc(RequestVcCommand), - /// Request VC isolated from Block Production - RequestVcDirect(RequestVcDirectCommand), - /// Remove Identity from the prime identity RemoveIdentity(RemoveIdentityCommand), } @@ -119,7 +116,6 @@ impl TrustedBaseCommand { TrustedBaseCommand::LinkIdentity(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::IDGraph(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::RequestVc(cmd) => cmd.run(cli, trusted_cli), - TrustedBaseCommand::RequestVcDirect(cmd) => cmd.run(cli, trusted_cli), TrustedBaseCommand::RemoveIdentity(cmd) => cmd.run(cli, trusted_cli), } } diff --git a/tee-worker/cli/src/trusted_operation.rs b/tee-worker/cli/src/trusted_operation.rs index 0404216d85..fbe783b184 100644 --- a/tee-worker/cli/src/trusted_operation.rs +++ b/tee-worker/cli/src/trusted_operation.rs @@ -25,7 +25,7 @@ use base58::{FromBase58, ToBase58}; use codec::{Decode, Encode, Input}; use ita_stf::{Getter, StfError, TrustedCall, TrustedCallSigned}; use itc_rpc_client::direct_client::{DirectApi, DirectClient}; -use itp_node_api::api_client::{ParentchainApi, TEEREX}; +use itp_node_api::api_client::{ParentchainApi, TEEBAG}; use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; use itp_sgx_crypto::ShieldingCryptoEncrypt; use itp_stf_primitives::types::{ShardIdentifier, TrustedOperation}; @@ -35,8 +35,7 @@ use litentry_primitives::{ aes_encrypt_default, AesRequest, ParentchainHash as Hash, RequestAesKey, }; use log::*; -use my_node_runtime::RuntimeEvent; -use pallet_teerex::Event as TeerexEvent; +use my_node_runtime::{pallet_teebag::Event as TeebagEvent, RuntimeEvent}; use sp_core::H256; use std::{ fmt::Debug, @@ -168,7 +167,7 @@ fn send_indirect_request( chain_api.set_signer(signer.into()); let request = RsaRequest::new(shard, call_encrypted); - let xt = compose_extrinsic!(&chain_api, TEEREX, "call_worker", request); + let xt = compose_extrinsic!(&chain_api, TEEBAG, "post_opaque_task", request); let block_hash = match chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) { Ok(xt_report) => { @@ -194,14 +193,14 @@ fn send_indirect_request( let event_result = subscription.next_events::(); if let Some(Ok(event_records)) = event_result { for event_record in event_records { - if let RuntimeEvent::Teerex(TeerexEvent::ProcessedParentchainBlock( - _signer, - confirmed_block_hash, - trusted_calls_merkle_root, - confirmed_block_number, - )) = event_record.event + if let RuntimeEvent::Teebag(TeebagEvent::ParentchainBlockProcessed { + who: _signer, + block_number: confirmed_block_number, + block_hash: confirmed_block_hash, + task_merkle_root: trusted_calls_merkle_root, + }) = event_record.event { - info!("Confirmation of ProcessedParentchainBlock received"); + info!("Confirmation of ParentchainBlockProcessed received"); debug!("shard: {:?}", shard); debug!("confirmed parentchain block Hash: {:?}", block_hash); debug!("trusted calls merkle root: {:?}", trusted_calls_merkle_root); @@ -212,9 +211,9 @@ fn send_indirect_request( confirmed_block_hash, confirmed_block_number, ) { - error!("ProcessedParentchainBlock event: {:?}", e); + error!("ParentchainBlockProcessed event: {:?}", e); return Err(TrustedOperationError::Default { - msg: format!("ProcessedParentchainBlock event: {:?}", e), + msg: format!("ParentchainBlockProcessed event: {:?}", e), }) }; diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts index 60ea972254..672d38917a 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/identity/definitions.ts @@ -49,6 +49,8 @@ export default { "BitcoinP2sh", "BitcoinP2wpkh", "BitcoinP2wsh", + "Polygon", + "Arbitrum", ], }, LitentryValidationData: { diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts index c111ab837b..86364ad00c 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/sidechain/definitions.ts @@ -79,7 +79,6 @@ export default { NoEligibleIdentity: "Null", }, }, - // teerex ShardIdentifier: "H256", }, }; diff --git a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts index 701fdf5377..ed0c0085b0 100644 --- a/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts +++ b/tee-worker/client-api/parachain-api/prepare-build/interfaces/vc/definitions.ts @@ -20,7 +20,7 @@ export default { A14: "Null", Achainable: "AchainableParams", A20: "Null", - Oneblock: "OneBlockCourseType", + OneBlock: "OneBlockCourseType", GenericDiscordRole: "GenericDiscordRoleType", __Unused15: "Null", BnbDomainHolding: "Null", @@ -32,6 +32,8 @@ export default { BRC20AmountHolder: "Null", CyptoSummary: "Null", TokenHoldingAmount: "Web3TokenType", + PlatformUser: "PlatformUserType", + NftHolder: "Web3NftType", }, }, AssertionSupportedNetwork: { @@ -58,66 +60,66 @@ export default { }, AchainableAmountHolding: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", amount: "Bytes", date: "Bytes", token: "Option", }, AchainableAmountToken: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", amount: "Bytes", token: "Option", }, AchainableAmount: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", amount: "Bytes", }, AchainableAmounts: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", amount1: "Bytes", amount2: "Bytes", }, AchainableBasic: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", }, AchainableBetweenPercents: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", greaterThanOrEqualTo: "Bytes", lessThanOrEqualTo: "Bytes", }, AchainableClassOfYear: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", }, AchainableDateInterval: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", startDate: "Bytes", endDate: "Bytes", }, AchainableDatePercent: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", token: "Bytes", date: "Bytes", percent: "Bytes", }, AchainableDate: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", date: "Bytes", }, AchainableToken: { name: "Bytes", - chain: "Web3Network", + chain: "Vec", token: "Bytes", }, - // Oneblock + // OneBlock OneBlockCourseType: { _enum: ["CourseCompletion", "CourseOutstanding", "CourseParticipation"], }, @@ -173,5 +175,13 @@ export default { "Trx", ], }, + // PlatformUserType + PlatformUserType: { + _enum: ["KaratDaoUser"], + }, + // Web3NftType + Web3NftType: { + _enum: ["WeirdoGhostGang", "Club3Sbt"], + }, }, }; diff --git a/tee-worker/core-primitives/enclave-api/Cargo.toml b/tee-worker/core-primitives/enclave-api/Cargo.toml index c9dfaa9dff..b0541b1136 100644 --- a/tee-worker/core-primitives/enclave-api/Cargo.toml +++ b/tee-worker/core-primitives/enclave-api/Cargo.toml @@ -26,7 +26,7 @@ itp-storage = { path = "../storage" } itp-types = { path = "../types" } # litentry -teerex-primitives = { path = "../../../primitives/teerex", default-features = false } +pallet-teebag = { path = "../../../pallets/teebag", default-features = false } [features] default = [] diff --git a/tee-worker/core-primitives/enclave-api/ffi/src/lib.rs b/tee-worker/core-primitives/enclave-api/ffi/src/lib.rs index 2dbb8fb016..f70a36d54b 100644 --- a/tee-worker/core-primitives/enclave-api/ffi/src/lib.rs +++ b/tee-worker/core-primitives/enclave-api/ffi/src/lib.rs @@ -215,30 +215,6 @@ extern "C" { response_len: u32, ) -> sgx_status_t; - pub fn update_market_data_xt( - eid: sgx_enclave_id_t, - retval: *mut sgx_status_t, - crypto_currency: *const u8, - crypto_currency_size: u32, - fiat_currency: *const u8, - fiat_currency_size: u32, - unchecked_extrinsic: *mut u8, - unchecked_extrinsic_max_size: u32, - unchecked_extrinsic_size: *mut u32, - ) -> sgx_status_t; - - pub fn update_weather_data_xt( - eid: sgx_enclave_id_t, - retval: *mut sgx_status_t, - weather_info_longitude: *const u8, - weather_info_longitude_size: u32, - weather_info_latitude: *const u8, - weather_info_latitude_size: u32, - unchecked_extrinsic: *mut u8, - unchecked_extrinsic_max_size: u32, - unchecked_extrinsic_size: *mut u32, - ) -> sgx_status_t; - pub fn run_state_provisioning_server( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, diff --git a/tee-worker/core-primitives/enclave-api/src/enclave_base.rs b/tee-worker/core-primitives/enclave-api/src/enclave_base.rs index 4e79a6f902..b0f9dcb047 100644 --- a/tee-worker/core-primitives/enclave-api/src/enclave_base.rs +++ b/tee-worker/core-primitives/enclave-api/src/enclave_base.rs @@ -21,9 +21,9 @@ use codec::Decode; use core::fmt::Debug; use itc_parentchain::primitives::{ParentchainId, ParentchainInitParams}; use itp_types::ShardIdentifier; +use pallet_teebag::EnclaveFingerprint; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::ed25519; -use teerex_primitives::EnclaveFingerprint; /// Trait for base/common Enclave API functions pub trait EnclaveBase: Send + Sync + 'static { @@ -97,10 +97,10 @@ mod impl_ffi { }; use itp_types::ShardIdentifier; use log::*; + use pallet_teebag::EnclaveFingerprint; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sgx_types::*; use sp_core::ed25519; - use teerex_primitives::EnclaveFingerprint; impl EnclaveBase for Enclave { fn init( diff --git a/tee-worker/core-primitives/enclave-api/src/lib.rs b/tee-worker/core-primitives/enclave-api/src/lib.rs index 38c810624f..463608e111 100644 --- a/tee-worker/core-primitives/enclave-api/src/lib.rs +++ b/tee-worker/core-primitives/enclave-api/src/lib.rs @@ -19,7 +19,6 @@ pub mod enclave_test; pub mod error; pub mod remote_attestation; pub mod sidechain; -pub mod teeracle_api; pub mod utils; #[cfg(feature = "implement-ffi")] diff --git a/tee-worker/core-primitives/enclave-api/src/remote_attestation.rs b/tee-worker/core-primitives/enclave-api/src/remote_attestation.rs index 9aa32cb631..30a765da32 100644 --- a/tee-worker/core-primitives/enclave-api/src/remote_attestation.rs +++ b/tee-worker/core-primitives/enclave-api/src/remote_attestation.rs @@ -18,8 +18,8 @@ use crate::EnclaveResult; use itp_types::ShardIdentifier; +use pallet_teebag::Fmspc; use sgx_types::*; -use teerex_primitives::Fmspc; /// Struct that unites all relevant data reported by the QVE pub struct QveReport { @@ -128,8 +128,8 @@ mod impl_ffi { use itp_settings::worker::EXTRINSIC_MAX_SIZE; use itp_types::ShardIdentifier; use log::*; + use pallet_teebag::Fmspc; use sgx_types::*; - use teerex_primitives::Fmspc; const OS_SYSTEM_PATH: &str = "/usr/lib/x86_64-linux-gnu/"; const C_STRING_ENDING: &str = "\0"; diff --git a/tee-worker/core-primitives/enclave-api/src/teeracle_api.rs b/tee-worker/core-primitives/enclave-api/src/teeracle_api.rs deleted file mode 100644 index 530e2ff127..0000000000 --- a/tee-worker/core-primitives/enclave-api/src/teeracle_api.rs +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::EnclaveResult; - -pub trait TeeracleApi: Send + Sync + 'static { - /// Update the currency market data for the token oracle. - fn update_market_data_xt( - &self, - crypto_currency: &str, - fiat_currency: &str, - ) -> EnclaveResult>; - - /// Update weather data for the corresponding coordinates. - fn update_weather_data_xt(&self, longitude: &str, latitude: &str) -> EnclaveResult>; -} - -#[cfg(feature = "implement-ffi")] -mod impl_ffi { - use super::TeeracleApi; - use crate::{error::Error, Enclave, EnclaveResult}; - use codec::Encode; - use frame_support::ensure; - use itp_enclave_api_ffi as ffi; - use log::*; - use sgx_types::*; - impl TeeracleApi for Enclave { - fn update_market_data_xt( - &self, - crypto_currency: &str, - fiat_currency: &str, - ) -> EnclaveResult> { - info!( - "TeeracleApi update_market_data_xt in with crypto {} and fiat {}", - crypto_currency, fiat_currency - ); - let mut retval = sgx_status_t::SGX_SUCCESS; - let response_max_len = 8192; - let mut response: Vec = vec![0u8; response_max_len as usize]; - let mut response_len: u32 = 0; - - let crypto_curr = crypto_currency.encode(); - let fiat_curr = fiat_currency.encode(); - - let res = unsafe { - ffi::update_market_data_xt( - self.eid, - &mut retval, - crypto_curr.as_ptr(), - crypto_curr.len() as u32, - fiat_curr.as_ptr(), - fiat_curr.len() as u32, - response.as_mut_ptr(), - response_max_len, - &mut response_len as *mut u32, - ) - }; - - ensure!(res == sgx_status_t::SGX_SUCCESS, Error::Sgx(res)); - ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); - - Ok(Vec::from(&response[..response_len as usize])) - } - fn update_weather_data_xt( - &self, - longitude: &str, - latitude: &str, - ) -> EnclaveResult> { - info!( - "TeeracleApi update_weather_data_xt in with latitude: {}, longitude: {}", - latitude, longitude - ); - let mut retval = sgx_status_t::SGX_SUCCESS; - let response_max_len = 8192; - let mut response: Vec = vec![0u8; response_max_len as usize]; - let mut response_len: u32 = 0; - - let longitude_encoded: Vec = longitude.encode(); - let latitude_encoded: Vec = latitude.encode(); - - let res = unsafe { - ffi::update_weather_data_xt( - self.eid, - &mut retval, - longitude_encoded.as_ptr(), - longitude_encoded.len() as u32, - latitude_encoded.as_ptr(), - latitude_encoded.len() as u32, - response.as_mut_ptr(), - response_max_len, - &mut response_len as *mut u32, - ) - }; - - ensure!(res == sgx_status_t::SGX_SUCCESS, Error::Sgx(res)); - ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); - Ok(Vec::from(&response[..response_len as usize])) - } - } -} diff --git a/tee-worker/core-primitives/enclave-bridge-storage/Cargo.toml b/tee-worker/core-primitives/enclave-bridge-storage/Cargo.toml deleted file mode 100644 index 8b191f3458..0000000000 --- a/tee-worker/core-primitives/enclave-bridge-storage/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "itp-enclave-bridge-storage" -version = "0.9.0" -authors = ["Integritee AG "] -edition = "2021" - -[dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -#local deps -itp-storage = { path = "../storage", default-features = false } - -[features] -default = ["std"] -std = [ - "codec/std", - "sp-std/std", - "itp-storage/std", -] diff --git a/tee-worker/core-primitives/enclave-bridge-storage/src/lib.rs b/tee-worker/core-primitives/enclave-bridge-storage/src/lib.rs deleted file mode 100644 index 9077d756b6..0000000000 --- a/tee-worker/core-primitives/enclave-bridge-storage/src/lib.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -use codec::Encode; -use itp_storage::{storage_map_key, StorageHasher}; -use sp_std::prelude::Vec; - -pub struct EnclaveBridgeStorage; - -// Separate the prefix from the rest because in our case we changed the storage prefix due to -// the rebranding. With the below implementation of the `TeerexStorageKeys`, we could simply -// define another struct `OtherStorage`, implement `StoragePrefix` for it, and get the -// `TeerexStorageKeys` implementation for free. -pub trait StoragePrefix { - fn prefix() -> &'static str; -} - -impl StoragePrefix for EnclaveBridgeStorage { - fn prefix() -> &'static str { - "EnclaveBridge" - } -} - -pub trait EnclaveBridgeStorageKeys { - fn shard_status(shard: T) -> Vec; -} - -impl EnclaveBridgeStorageKeys for S { - fn shard_status(shard: T) -> Vec { - storage_map_key(Self::prefix(), "ShardStatus", &shard, &StorageHasher::Blake2_128Concat) - } -} diff --git a/tee-worker/core-primitives/enclave-metrics/src/lib.rs b/tee-worker/core-primitives/enclave-metrics/src/lib.rs index 045c9f0c59..aab5638308 100644 --- a/tee-worker/core-primitives/enclave-metrics/src/lib.rs +++ b/tee-worker/core-primitives/enclave-metrics/src/lib.rs @@ -28,10 +28,6 @@ use codec::{Decode, Encode}; use core::time::Duration; use lc_stf_task_sender::RequestType; use std::{boxed::Box, string::String}; -use substrate_fixed::types::U32F32; - -// FIXME: Copied from ita-oracle because of cyclic deps. Should be removed after integritee-network/pallets#71 -pub type ExchangeRate = U32F32; #[derive(Encode, Decode, Debug)] pub enum EnclaveMetric { @@ -39,7 +35,6 @@ pub enum EnclaveMetric { TopPoolSizeSet(u64), TopPoolSizeIncrement, TopPoolSizeDecrement, - ExchangeRateOracle(ExchangeRateOracleMetric), StfTaskExecutionTime(Box, f64), SuccessfulTrustedOperationIncrement(String), FailedTrustedOperationIncrement(String), @@ -49,22 +44,7 @@ pub enum EnclaveMetric { SidechainSlotStfExecutionTime(Duration), SidechainSlotBlockCompositionTime(Duration), SidechainBlockBroadcastingTime(Duration), - // OracleMetric(OracleMetric), -} - -#[derive(Encode, Decode, Debug)] -pub enum ExchangeRateOracleMetric { - /// Exchange Rate from CoinGecko - (Source, TradingPair, ExchangeRate) - ExchangeRate(String, String, ExchangeRate), - /// Response time of the request in [ms]. (Source, ResponseTime) - ResponseTime(String, u128), - /// Increment the number of requests (Source) - NumberRequestsIncrement(String), -} - -#[derive(Encode, Decode, Debug)] -pub enum OracleMetric { - OracleSpecificMetric(MetricsInfo), - ResponseTime(String, u128), - NumberRequestsIncrement(String), + VCBuildTime(String, Duration), + SuccessfullVCIssuance, + FailedVCIssuance, } diff --git a/tee-worker/core-primitives/node-api/api-client-extensions/src/lib.rs b/tee-worker/core-primitives/node-api/api-client-extensions/src/lib.rs index 2829b53c1c..668cefd2ba 100644 --- a/tee-worker/core-primitives/node-api/api-client-extensions/src/lib.rs +++ b/tee-worker/core-primitives/node-api/api-client-extensions/src/lib.rs @@ -21,12 +21,10 @@ pub use substrate_api_client::{api::Error as ApiClientError, rpc::TungsteniteRpc pub mod account; pub mod chain; -pub mod pallet_teeracle; -pub mod pallet_teerex; +pub mod pallet_teebag; pub use account::*; pub use chain::*; -pub use pallet_teeracle::*; -pub use pallet_teerex::*; +pub use pallet_teebag::*; pub type ApiResult = Result; diff --git a/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teebag.rs b/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teebag.rs new file mode 100644 index 0000000000..e243091ca5 --- /dev/null +++ b/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teebag.rs @@ -0,0 +1,134 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::ApiResult; +use itp_api_client_types::{traits::GetStorage, Api, Config, Request}; +use itp_types::{AccountId, Enclave, ShardIdentifier, WorkerType}; + +pub const TEEBAG: &str = "Teebag"; + +/// ApiClient extension that enables communication with the `teebag` pallet. +pub trait PalletTeebagApi { + type Hash; + + fn enclave( + &self, + account: &AccountId, + at_block: Option, + ) -> ApiResult>; + fn enclave_count( + &self, + worker_type: WorkerType, + at_block: Option, + ) -> ApiResult; + fn primary_enclave_identifier_for_shard( + &self, + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult>; + fn primary_enclave_for_shard( + &self, + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult>; + fn all_enclaves( + &self, + worker_type: WorkerType, + at_block: Option, + ) -> ApiResult>; +} + +impl PalletTeebagApi for Api +where + RuntimeConfig: Config, + Client: Request, +{ + type Hash = RuntimeConfig::Hash; + + fn enclave( + &self, + account: &AccountId, + at_block: Option, + ) -> ApiResult> { + self.get_storage_map(TEEBAG, "EnclaveRegistry", account, at_block) + } + + fn enclave_count( + &self, + worker_type: WorkerType, + at_block: Option, + ) -> ApiResult { + // Vec<> and BoundedVec<> have the same encoding, thus they are used interchangeably + let identifiers: Vec = self + .get_storage_map(TEEBAG, "EnclaveIdentifier", worker_type, at_block)? + .unwrap_or_default(); + Ok(identifiers.len() as u64) + } + + // please note we don't use dedicated on-chain storage for this (like the upstream `WorkerForShard`) + // so this API will always return the "first" registered and qualified enclave. + // Wheter it meets our needs needs to be further evaluated + fn primary_enclave_identifier_for_shard( + &self, + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { + let identifiers: Vec = self + .get_storage_map(TEEBAG, "EnclaveIdentifier", worker_type, at_block)? + .unwrap_or_default(); + let mut maybe_account: Option = None; + for account in identifiers { + match self.enclave(&account, at_block)? { + Some(e) => + if e.mrenclave == shard.as_ref() { + maybe_account = Some(account.clone()); + break + }, + None => continue, + } + } + Ok(maybe_account) + } + + fn primary_enclave_for_shard( + &self, + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { + self.primary_enclave_identifier_for_shard(worker_type, shard, at_block)? + .map_or_else(|| Ok(None), |account| self.enclave(&account, at_block)) + } + + fn all_enclaves( + &self, + worker_type: WorkerType, + at_block: Option, + ) -> ApiResult> { + let identifiers: Vec = self + .get_storage_map(TEEBAG, "EnclaveIdentifier", worker_type, at_block)? + .unwrap_or_default(); + + let enclaves = identifiers + .into_iter() + .filter_map(|account| self.enclave(&account, at_block).ok()?) + .collect(); + Ok(enclaves) + } +} diff --git a/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs b/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs deleted file mode 100644 index 3f1ad2d198..0000000000 --- a/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs +++ /dev/null @@ -1,19 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pub const TEERACLE: &str = "Teeracle"; -pub const ADD_TO_WHITELIST: &str = "add_to_whitelist"; diff --git a/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs b/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs deleted file mode 100644 index 222e249402..0000000000 --- a/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs +++ /dev/null @@ -1,105 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::ApiResult; -use itp_api_client_types::{storage_key, traits::GetStorage, Api, Config, Request}; -use itp_types::{Enclave, IpfsHash, MrEnclave, ShardIdentifier}; -use sp_core::storage::StorageKey; - -pub const TEEREX: &str = "Teerex"; -pub const SIDECHAIN: &str = "Sidechain"; - -/// ApiClient extension that enables communication with the `teerex` pallet. -// Todo: make generic over `Config` type instead? -pub trait PalletTeerexApi { - type Hash; - - fn enclave(&self, index: u64, at_block: Option) -> ApiResult>; - fn enclave_count(&self, at_block: Option) -> ApiResult; - fn all_enclaves(&self, at_block: Option) -> ApiResult>; - fn worker_for_shard( - &self, - shard: &ShardIdentifier, - at_block: Option, - ) -> ApiResult>; - fn latest_ipfs_hash( - &self, - shard: &ShardIdentifier, - at_block: Option, - ) -> ApiResult>; - - // litentry - fn all_scheduled_mrenclaves(&self, at_block: Option) -> ApiResult>; -} - -impl PalletTeerexApi for Api -where - RuntimeConfig: Config, - Client: Request, -{ - type Hash = RuntimeConfig::Hash; - - fn enclave(&self, index: u64, at_block: Option) -> ApiResult> { - self.get_storage_map(TEEREX, "EnclaveRegistry", index, at_block) - } - - fn enclave_count(&self, at_block: Option) -> ApiResult { - Ok(self.get_storage(TEEREX, "EnclaveCount", at_block)?.unwrap_or(0u64)) - } - - fn all_enclaves(&self, at_block: Option) -> ApiResult> { - let count = self.enclave_count(at_block)?; - let mut enclaves = Vec::with_capacity(count as usize); - for n in 1..=count { - enclaves.push(self.enclave(n, at_block)?.expect("None enclave")) - } - Ok(enclaves) - } - - fn worker_for_shard( - &self, - shard: &ShardIdentifier, - at_block: Option, - ) -> ApiResult> { - self.get_storage_map(SIDECHAIN, "WorkerForShard", shard, at_block)? - .map_or_else(|| Ok(None), |w_index| self.enclave(w_index, at_block)) - } - - fn latest_ipfs_hash( - &self, - shard: &ShardIdentifier, - at_block: Option, - ) -> ApiResult> { - self.get_storage_map(TEEREX, "LatestIPFSHash", shard, at_block) - } - - fn all_scheduled_mrenclaves(&self, at_block: Option) -> ApiResult> { - let keys: Vec<_> = self - .get_keys(storage_key(TEEREX, "ScheduledEnclave"), at_block)? - .unwrap_or_default() - .iter() - .map(|key| { - let key = key.strip_prefix("0x").unwrap_or(key); - let raw_key = hex::decode(key).unwrap(); - self.get_storage_by_key::(StorageKey(raw_key).into(), at_block) - }) - .filter(|enclave| matches!(enclave, Ok(Some(_)))) - .map(|enclave| enclave.unwrap().unwrap()) - .collect(); - Ok(keys) - } -} diff --git a/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs b/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs deleted file mode 100644 index df5bf3646f..0000000000 --- a/tee-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{pallet_teerex::PalletTeerexApi, ApiResult}; -use itp_types::{parentchain::Hash, AccountId, IpfsHash, MrEnclave, MultiEnclave, ShardIdentifier}; -use std::collections::HashMap; - -#[derive(Default)] -pub struct PalletTeerexApiMock { - registered_enclaves: HashMap>>, -} - -impl PalletTeerexApiMock { - pub fn with_enclaves(mut self, enclaves: Vec>>) -> Self { - enclaves.iter().map(|enclave| self.registered_enclaves.insert(enclave)); - self - } -} - -impl PalletTeerexApi for PalletTeerexApiMock { - fn enclave( - &self, - account: AccountId, - _at_block: Option, - ) -> ApiResult>>> { - Ok(self.registered_enclaves.get(index as usize).cloned()) - } - - fn enclave_count(&self, _at_block: Option) -> ApiResult { - Ok(self.registered_enclaves.len() as u64) - } - - fn all_enclaves(&self, _at_block: Option) -> ApiResult>>> { - Ok(self.registered_enclaves.clone()) - } - - fn primary_worker_for_shard( - &self, - _shard: &ShardIdentifier, - _at_block: Option, - ) -> ApiResult>>> { - todo!() - } - - fn latest_ipfs_hash( - &self, - _shard: &ShardIdentifier, - _at_block: Option, - ) -> ApiResult> { - todo!() - } - - fn all_scheduled_mrenclaves(&self, _at_block: Option) -> ApiResult> { - Ok(self.registered_enclaves.iter().map(|k| k.mr_enclave).collect()) - } -} diff --git a/tee-worker/core-primitives/node-api/metadata/src/lib.rs b/tee-worker/core-primitives/node-api/metadata/src/lib.rs index 0a069c0277..956255578d 100644 --- a/tee-worker/core-primitives/node-api/metadata/src/lib.rs +++ b/tee-worker/core-primitives/node-api/metadata/src/lib.rs @@ -21,9 +21,9 @@ use crate::{ error::Result, pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, - pallet_proxy::ProxyCallIndexes, pallet_sidechain::SidechainCallIndexes, - pallet_system::SystemSs58Prefix, pallet_teerex::TeerexCallIndexes, - pallet_utility::UtilityCallIndexes, pallet_vcmp::VCMPCallIndexes, + pallet_proxy::ProxyCallIndexes, pallet_system::SystemSs58Prefix, + pallet_teebag::TeebagCallIndexes, pallet_utility::UtilityCallIndexes, + pallet_vcmp::VCMPCallIndexes, }; use codec::{Decode, Encode}; use sp_core::storage::StorageKey; @@ -35,10 +35,8 @@ pub mod error; pub mod pallet_balances; pub mod pallet_imp; pub mod pallet_proxy; -pub mod pallet_sidechain; pub mod pallet_system; -pub mod pallet_teeracle; -pub mod pallet_teerex; +pub mod pallet_teebag; pub mod pallet_utility; pub mod pallet_vcmp; pub mod runtime_call; @@ -47,8 +45,7 @@ pub mod runtime_call; pub mod metadata_mocks; pub trait NodeMetadataTrait: - TeerexCallIndexes - + SidechainCallIndexes + TeebagCallIndexes + IMPCallIndexes + VCMPCallIndexes + SystemSs58Prefix @@ -57,9 +54,9 @@ pub trait NodeMetadataTrait: + BalancesCallIndexes { } + impl< - T: TeerexCallIndexes - + SidechainCallIndexes + T: TeebagCallIndexes + IMPCallIndexes + VCMPCallIndexes + SystemSs58Prefix diff --git a/tee-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs b/tee-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs index cdf24e4fcc..d5b22c96b5 100644 --- a/tee-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs +++ b/tee-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -17,9 +17,9 @@ use crate::{ error::Result, pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, - pallet_proxy::ProxyCallIndexes, pallet_sidechain::SidechainCallIndexes, - pallet_system::SystemSs58Prefix, pallet_teerex::TeerexCallIndexes, - pallet_utility::UtilityCallIndexes, pallet_vcmp::VCMPCallIndexes, runtime_call::RuntimeCall, + pallet_proxy::ProxyCallIndexes, pallet_system::SystemSs58Prefix, + pallet_teebag::TeebagCallIndexes, pallet_utility::UtilityCallIndexes, + pallet_vcmp::VCMPCallIndexes, runtime_call::RuntimeCall, }; use codec::{Decode, Encode}; @@ -35,23 +35,18 @@ impl TryFrom for Metadata { #[derive(Default, Encode, Decode, Debug, Clone)] pub struct NodeMetadataMock { - teerex_module: u8, + // litentry + // teebag + teebag_module: u8, + set_scheduled_enclave: u8, + remove_scheduled_enclave: u8, register_enclave: u8, - unregister_sovereign_enclave: u8, - unregister_proxied_enclave: u8, + unregister_enclave: u8, register_quoting_enclave: u8, register_tcb_info: u8, - enclave_bridge_module: u8, - invoke: u8, - confirm_processed_parentchain_block: u8, - shield_funds: u8, - unshield_funds: u8, - publish_hash: u8, - update_shard_config: u8, - sidechain_module: u8, - // litentry - update_scheduled_enclave: u8, - remove_scheduled_enclave: u8, + post_opaque_task: u8, + parentchain_block_processed: u8, + sidechain_block_imported: u8, // IMP imp_module: u8, imp_link_identity: u8, @@ -76,7 +71,6 @@ pub struct NodeMetadataMock { utility_dispatch_as: u8, utility_force_batch: u8, - imported_sidechain_block: u8, proxy_module: u8, add_proxy: u8, proxy: u8, @@ -91,23 +85,17 @@ pub struct NodeMetadataMock { impl NodeMetadataMock { pub fn new() -> Self { NodeMetadataMock { - teerex_module: 50u8, - register_enclave: 0u8, - unregister_sovereign_enclave: 1u8, - unregister_proxied_enclave: 2u8, - register_quoting_enclave: 3, - register_tcb_info: 4, - enclave_bridge_module: 54u8, - invoke: 0u8, - confirm_processed_parentchain_block: 1u8, - shield_funds: 2u8, - unshield_funds: 3u8, - publish_hash: 4u8, - update_shard_config: 5u8, - sidechain_module: 53u8, // litentry - update_scheduled_enclave: 10u8, - remove_scheduled_enclave: 11u8, + teebag_module: 50u8, + set_scheduled_enclave: 0u8, + remove_scheduled_enclave: 1u8, + register_enclave: 2u8, + unregister_enclave: 3u8, + register_quoting_enclave: 4u8, + register_tcb_info: 5u8, + post_opaque_task: 6u8, + parentchain_block_processed: 7u8, + sidechain_block_imported: 8u8, imp_module: 64u8, imp_link_identity: 1u8, @@ -132,7 +120,6 @@ impl NodeMetadataMock { utility_dispatch_as: 3u8, utility_force_batch: 4u8, - imported_sidechain_block: 0u8, proxy_module: 7u8, add_proxy: 1u8, proxy: 0u8, @@ -146,63 +133,33 @@ impl NodeMetadataMock { } } -impl TeerexCallIndexes for NodeMetadataMock { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_enclave]) +impl TeebagCallIndexes for NodeMetadataMock { + fn set_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.set_scheduled_enclave]) } - - fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.unregister_sovereign_enclave]) + fn remove_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.remove_scheduled_enclave]) } - - fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.unregister_proxied_enclave]) + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.register_enclave]) + } + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.unregister_enclave]) } - fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_quoting_enclave]) + Ok([self.teebag_module, self.register_quoting_enclave]) } - fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_tcb_info]) - } - - fn invoke_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.invoke]) + Ok([self.teebag_module, self.register_tcb_info]) } - - fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.confirm_processed_parentchain_block]) - } - - fn shield_funds_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.shield_funds]) + fn post_opaque_task_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.post_opaque_task]) } - - fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.unshield_funds]) + fn parentchain_block_processed_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.parentchain_block_processed]) } - - fn publish_hash_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.publish_hash]) - } - - // fn update_shard_config_call_indexes(&self) -> Result<[u8; 2]> { - // Ok([self.teerex_module, self.update_shard_config]) - // } - - fn update_scheduled_enclave(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.update_scheduled_enclave]) - } - - fn remove_scheduled_enclave(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.remove_scheduled_enclave]) - } -} - -impl SidechainCallIndexes for NodeMetadataMock { - fn confirm_imported_sidechain_block_indexes(&self) -> Result<[u8; 2]> { - Ok([self.sidechain_module, self.imported_sidechain_block]) + fn sidechain_block_imported_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teebag_module, self.sidechain_block_imported]) } } diff --git a/tee-worker/core-primitives/node-api/metadata/src/pallet_teebag.rs b/tee-worker/core-primitives/node-api/metadata/src/pallet_teebag.rs new file mode 100644 index 0000000000..0dc73cfb25 --- /dev/null +++ b/tee-worker/core-primitives/node-api/metadata/src/pallet_teebag.rs @@ -0,0 +1,71 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +use crate::{error::Result, NodeMetadata}; + +/// Pallet' name: +pub const TEEBAG: &str = "Teebag"; + +// we only list the extrinsics that we care +pub trait TeebagCallIndexes { + fn set_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn remove_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]>; + + fn post_opaque_task_call_indexes(&self) -> Result<[u8; 2]>; + + fn parentchain_block_processed_call_indexes(&self) -> Result<[u8; 2]>; + + fn sidechain_block_imported_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl TeebagCallIndexes for NodeMetadata { + fn set_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "set_scheduled_enclave") + } + fn remove_scheduled_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "remove_scheduled_enclave") + } + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "register_enclave") + } + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "unregister_enclave") + } + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "register_quoting_enclave") + } + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "register_tcb_info") + } + fn post_opaque_task_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "post_opaque_task") + } + fn parentchain_block_processed_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "parentchain_block_processed") + } + fn sidechain_block_imported_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEBAG, "sidechain_block_imported") + } +} diff --git a/tee-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs b/tee-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs deleted file mode 100644 index 0d10003514..0000000000 --- a/tee-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{error::Result, NodeMetadata}; - -/// Pallet' name: -pub const TEERACLE: &str = "Teeracle"; - -pub trait TeeracleCallIndexes { - fn add_to_whitelist_call_indexes(&self) -> Result<[u8; 2]>; - fn remove_from_whitelist_call_indexes(&self) -> Result<[u8; 2]>; - fn update_exchange_rate_call_indexes(&self) -> Result<[u8; 2]>; - fn update_oracle_call_indexes(&self) -> Result<[u8; 2]>; -} - -impl TeeracleCallIndexes for NodeMetadata { - fn add_to_whitelist_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEERACLE, "add_to_whitelist") - } - - fn remove_from_whitelist_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEERACLE, "remove_from_whitelist") - } - - fn update_exchange_rate_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEERACLE, "update_exchange_rate") - } - - fn update_oracle_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEERACLE, "update_oracle") - } -} diff --git a/tee-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs b/tee-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs deleted file mode 100644 index d2cd618e80..0000000000 --- a/tee-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs +++ /dev/null @@ -1,114 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ -use crate::{error::Result, NodeMetadata}; -use sp_core::storage::StorageKey; - -/// Pallet' name: -pub const TEEREX: &str = "Teerex"; - -pub trait TeerexCallIndexes { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]>; - - fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]>; - - fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]>; - - fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]>; - - fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]>; - - fn invoke_call_indexes(&self) -> Result<[u8; 2]>; - - fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]>; - - fn shield_funds_call_indexes(&self) -> Result<[u8; 2]>; - - fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]>; - - fn publish_hash_call_indexes(&self) -> Result<[u8; 2]>; - - // litentry - fn update_scheduled_enclave(&self) -> Result<[u8; 2]>; - - fn remove_scheduled_enclave(&self) -> Result<[u8; 2]>; -} - -pub trait TeerexStorageKey { - fn sovereign_enclaves_storage_map_key(&self, index: u64) -> Result; - - fn proxied_enclaves_storage_map_key(&self, index: u64) -> Result; -} - -impl TeerexCallIndexes for NodeMetadata { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "register_enclave") - } - - fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "unregister_sovereign_enclave") - } - - fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "unregister_proxied_enclave") - } - - fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "register_quoting_enclave") - } - - fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "register_tcb_info") - } - - /* Keep parachain extrinsic name untouched. Keep alignment with upstream worker */ - fn invoke_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "call_worker") - } - - fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "confirm_processed_parentchain_block") - } - - fn shield_funds_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "shield_funds") - } - - fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "unshield_funds") - } - - fn publish_hash_call_indexes(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "publish_hash") - } - - fn update_scheduled_enclave(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "update_scheduled_enclave") - } - - fn remove_scheduled_enclave(&self) -> Result<[u8; 2]> { - self.call_indexes(TEEREX, "remove_scheduled_enclave") - } -} - -impl TeerexStorageKey for NodeMetadata { - fn sovereign_enclaves_storage_map_key(&self, index: u64) -> Result { - self.storage_map_key(TEEREX, "SovereignEnclaves", index) - } - fn proxied_enclaves_storage_map_key(&self, index: u64) -> Result { - self.storage_map_key(TEEREX, "ProxiedEnclaves", index) - } -} diff --git a/tee-worker/core-primitives/settings/Cargo.toml b/tee-worker/core-primitives/settings/Cargo.toml index bf48cd4ec2..3aadf1e5e5 100644 --- a/tee-worker/core-primitives/settings/Cargo.toml +++ b/tee-worker/core-primitives/settings/Cargo.toml @@ -5,10 +5,11 @@ authors = ['Trust Computing GmbH ', 'Integritee AG WorkerMode; @@ -36,13 +31,6 @@ impl ProvideWorkerMode for WorkerModeProvider { } } -#[cfg(feature = "teeracle")] -impl ProvideWorkerMode for WorkerModeProvider { - fn worker_mode() -> WorkerMode { - WorkerMode::Teeracle - } -} - #[cfg(feature = "sidechain")] impl ProvideWorkerMode for WorkerModeProvider { fn worker_mode() -> WorkerMode { @@ -51,7 +39,7 @@ impl ProvideWorkerMode for WorkerModeProvider { } // Default to `Sidechain` worker mode when no cargo features are set. -#[cfg(not(any(feature = "sidechain", feature = "teeracle", feature = "offchain-worker")))] +#[cfg(not(any(feature = "sidechain", feature = "offchain-worker")))] impl ProvideWorkerMode for WorkerModeProvider { fn worker_mode() -> WorkerMode { WorkerMode::Sidechain diff --git a/tee-worker/core-primitives/sgx-runtime-primitives/Cargo.toml b/tee-worker/core-primitives/sgx-runtime-primitives/Cargo.toml index 8ec87045fa..5290e8da32 100644 --- a/tee-worker/core-primitives/sgx-runtime-primitives/Cargo.toml +++ b/tee-worker/core-primitives/sgx-runtime-primitives/Cargo.toml @@ -12,9 +12,6 @@ pallet-balances = { default-features = false, git = "https://github.com/parityte sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -# litentry -litentry-primitives = { path = "../../litentry/primitives", default-features = false } - [features] default = ["std"] std = [ @@ -22,6 +19,4 @@ std = [ "pallet-balances/std", "sp-core/std", "sp-runtime/std", - # litentry - "litentry-primitives/std", ] diff --git a/tee-worker/core-primitives/sgx-runtime-primitives/src/types.rs b/tee-worker/core-primitives/sgx-runtime-primitives/src/types.rs index bad667791e..035ae982b8 100644 --- a/tee-worker/core-primitives/sgx-runtime-primitives/src/types.rs +++ b/tee-worker/core-primitives/sgx-runtime-primitives/src/types.rs @@ -21,8 +21,6 @@ use sp_runtime::{ MultiSignature, OpaqueExtrinsic, }; -use litentry_primitives::ParentchainAccountId; - /// The address format for describing accounts. pub type Address = sp_runtime::MultiAddress; /// Block header type as expected by this sgx-runtime. @@ -66,21 +64,3 @@ pub type Block = BlockG; pub type SignedBlock = SignedBlockG; pub type BlockHash = sp_core::H256; pub type ShardIdentifier = sp_core::H256; - -// litentry -pub trait ConvertAccountId { - type Input; - type Output; - fn convert(input: Self::Input) -> Self::Output; -} - -pub struct SgxParentchainTypeConverter; - -impl ConvertAccountId for SgxParentchainTypeConverter { - type Input = AccountId; - type Output = ParentchainAccountId; - fn convert(a: AccountId) -> ParentchainAccountId { - // it's an identity converter - a as ParentchainAccountId - } -} diff --git a/tee-worker/core-primitives/teerex-storage/Cargo.toml b/tee-worker/core-primitives/teerex-storage/Cargo.toml deleted file mode 100644 index ca9bafb791..0000000000 --- a/tee-worker/core-primitives/teerex-storage/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "itp-teerex-storage" -version = "0.9.0" -authors = ['Trust Computing GmbH ', 'Integritee AG '] -edition = "2021" - -[dependencies] -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } - -#local deps -itp-storage = { path = "../storage", default-features = false } - -[features] -default = ["std"] -std = [ - "sp-std/std", - "itp-storage/std", -] diff --git a/tee-worker/core-primitives/teerex-storage/src/lib.rs b/tee-worker/core-primitives/teerex-storage/src/lib.rs deleted file mode 100644 index 706d92fcb1..0000000000 --- a/tee-worker/core-primitives/teerex-storage/src/lib.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -use itp_storage::{storage_map_key, storage_value_key, StorageHasher}; -use sp_std::prelude::Vec; - -pub struct TeeRexStorage; - -// Separate the prefix from the rest because in our case we changed the storage prefix due to -// the rebranding. With the below implementation of the `TeerexStorageKeys`, we could simply -// define another struct `OtherStorage`, implement `StoragePrefix` for it, and get the -// `TeerexStorageKeys` implementation for free. -pub trait StoragePrefix { - fn prefix() -> &'static str; -} - -impl StoragePrefix for TeeRexStorage { - fn prefix() -> &'static str { - "Teerex" - } -} - -pub trait TeerexStorageKeys { - fn enclave_count() -> Vec; - fn enclave(index: u64) -> Vec; -} - -impl TeerexStorageKeys for S { - fn enclave_count() -> Vec { - storage_value_key(Self::prefix(), "EnclaveCount") - } - - fn enclave(index: u64) -> Vec { - storage_map_key(Self::prefix(), "EnclaveRegistry", &index, &StorageHasher::Blake2_128Concat) - } -} diff --git a/tee-worker/core-primitives/test/Cargo.toml b/tee-worker/core-primitives/test/Cargo.toml index ff82183e77..92466e8615 100644 --- a/tee-worker/core-primitives/test/Cargo.toml +++ b/tee-worker/core-primitives/test/Cargo.toml @@ -29,12 +29,12 @@ itp-stf-interface = { path = "../stf-interface", default-features = false } itp-stf-primitives = { path = "../stf-primitives", default-features = false } itp-stf-state-handler = { path = "../stf-state-handler", default-features = false } itp-storage = { path = "../storage", default-features = false } -itp-teerex-storage = { path = "../teerex-storage", default-features = false } itp-time-utils = { path = "../time-utils", default-features = false } itp-types = { path = "../types", default-features = false, features = ["test"] } # litentry hex = { version = "0.4.3", default-features = false } +lc-teebag-storage = { path = "../../litentry/core/teebag-storage", default-features = false } litentry-primitives = { path = "../../litentry/primitives", default-features = false } [features] @@ -50,7 +50,6 @@ std = [ "itp-stf-primitives/std", "itp-stf-state-handler/std", "itp-storage/std", - "itp-teerex-storage/std", "itp-time-utils/std", "itp-types/std", "log/std", @@ -59,6 +58,7 @@ std = [ "sp-runtime/std", "sp-std/std", "litentry-primitives/std", + "lc-teebag-storage/std", ] sgx = [ "itp-node-api/sgx", diff --git a/tee-worker/core-primitives/test/src/builders/enclave_gen_builder.rs b/tee-worker/core-primitives/test/src/builders/enclave_gen_builder.rs deleted file mode 100644 index 85e807c628..0000000000 --- a/tee-worker/core-primitives/test/src/builders/enclave_gen_builder.rs +++ /dev/null @@ -1,63 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use itp_time_utils::now_as_millis; -use itp_types::{Enclave, PalletString}; - -/// Builder for a generic enclave (`EnclaveGen`) struct. -pub struct EnclaveGenBuilder { - pubkey: AccountId, - mr_enclave: [u8; 32], - timestamp: u64, - url: PalletString, // utf8 encoded url -} - -impl Default for EnclaveGenBuilder -where - AccountId: Default, -{ - fn default() -> Self { - EnclaveGenBuilder { - pubkey: AccountId::default(), - mr_enclave: [0u8; 32], - timestamp: now_as_millis(), - url: PalletString::default(), - } - } -} - -impl EnclaveGenBuilder { - pub fn with_account(mut self, account: AccountId) -> Self { - self.pubkey = account; - self - } - - pub fn with_url(mut self, url: PalletString) -> Self { - self.url = url; - self - } - - pub fn build(self) -> EnclaveGen { - EnclaveGen { - pubkey: self.pubkey, - mr_enclave: self.mr_enclave, - timestamp: self.timestamp, - url: self.url, - } - } -} diff --git a/tee-worker/core-primitives/test/src/builders/mod.rs b/tee-worker/core-primitives/test/src/builders/mod.rs deleted file mode 100644 index 610066f015..0000000000 --- a/tee-worker/core-primitives/test/src/builders/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -//! Builder patterns for common structs used in tests. - -pub mod enclave_gen_builder; diff --git a/tee-worker/core-primitives/test/src/mock/onchain_mock.rs b/tee-worker/core-primitives/test/src/mock/onchain_mock.rs index 22744289b5..a0163f8df0 100644 --- a/tee-worker/core-primitives/test/src/mock/onchain_mock.rs +++ b/tee-worker/core-primitives/test/src/mock/onchain_mock.rs @@ -23,14 +23,14 @@ use itp_ocall_api::{ EnclaveSidechainOCallApi, }; use itp_storage::Error::StorageValueUnavailable; -use itp_teerex_storage::{TeeRexStorage, TeerexStorageKeys}; use itp_types::{ - parentchain::ParentchainId, storage::StorageEntryVerified, BlockHash, Enclave, ShardIdentifier, - WorkerRequest, WorkerResponse, + parentchain::ParentchainId, storage::StorageEntryVerified, AccountId, BlockHash, + ShardIdentifier, WorkerRequest, WorkerResponse, WorkerType, }; +use lc_teebag_storage::{TeebagStorage, TeebagStorageKeys}; use sgx_types::*; use sp_core::H256; -use sp_runtime::{traits::Header as HeaderTrait, AccountId32, OpaqueExtrinsic}; +use sp_runtime::{traits::Header as HeaderTrait, OpaqueExtrinsic}; use sp_std::prelude::*; use std::{collections::HashMap, string::String}; @@ -55,11 +55,15 @@ impl OnchainMock { pub fn add_validateer_set>( mut self, header: &Header, - set: Option>, + set: Option>, ) -> Self { - let set = set.unwrap_or_else(validateer_set); - self.insert_at_header(header, TeeRexStorage::enclave_count(), (set.len() as u64).encode()); - self.with_storage_entries_at_header(header, into_key_value_storage(set)) + let set: Vec = set.unwrap_or_else(validateer_set); + self.insert_at_header( + header, + TeebagStorage::enclave_identifier(WorkerType::Identity), + set.encode(), + ); + self } pub fn with_mr_enclave(mut self, mr_enclave: [u8; SGX_HASH_SIZE]) -> Self { @@ -224,20 +228,11 @@ impl EnclaveOnChainOCallApi for OnchainMock { } } -pub fn validateer_set() -> Vec { - let default_enclave = Enclave::new( - AccountId32::from([0; 32]), - Default::default(), - Default::default(), - Default::default(), - ); - vec![default_enclave.clone(), default_enclave.clone(), default_enclave.clone(), default_enclave] -} - -fn into_key_value_storage(validateers: Vec) -> Vec<(Vec, Enclave)> { - validateers - .into_iter() - .enumerate() - .map(|(i, e)| (TeeRexStorage::enclave(i as u64 + 1), e)) - .collect() +pub fn validateer_set() -> Vec { + vec![ + AccountId::from([0; 32]), + AccountId::from([1; 32]), + AccountId::from([2; 32]), + AccountId::from([3; 32]), + ] } diff --git a/tee-worker/core-primitives/top-pool-author/Cargo.toml b/tee-worker/core-primitives/top-pool-author/Cargo.toml index 191ae19ea0..b5f8d264e4 100644 --- a/tee-worker/core-primitives/top-pool-author/Cargo.toml +++ b/tee-worker/core-primitives/top-pool-author/Cargo.toml @@ -75,4 +75,3 @@ test = ["itp-test/sgx", "itp-top-pool/mocks"] mocks = ["lazy_static"] sidechain = [] offchain-worker = [] -teeracle = [] diff --git a/tee-worker/core-primitives/top-pool-author/src/author.rs b/tee-worker/core-primitives/top-pool-author/src/author.rs index 08cbd61ff7..a123d72491 100644 --- a/tee-worker/core-primitives/top-pool-author/src/author.rs +++ b/tee-worker/core-primitives/top-pool-author/src/author.rs @@ -68,15 +68,10 @@ pub type AuthorTopFilter = crate::top_filter::IndirectCallsOnlyFilter = crate::top_filter::DenyAllFilter; -#[cfg(feature = "teeracle")] // Teeracle currently does not process any trusted operations -pub type AuthorTopFilter = crate::top_filter::DenyAllFilter; -#[cfg(feature = "teeracle")] -pub type BroadcastedTopFilter = crate::top_filter::DenyAllFilter; - -#[cfg(not(any(feature = "sidechain", feature = "offchain-worker", feature = "teeracle")))] +#[cfg(not(any(feature = "sidechain", feature = "offchain-worker")))] pub type AuthorTopFilter = crate::top_filter::CallsOnlyFilter; -#[cfg(not(any(feature = "sidechain", feature = "offchain-worker", feature = "teeracle")))] +#[cfg(not(any(feature = "sidechain", feature = "offchain-worker")))] pub type BroadcastedTopFilter = crate::top_filter::DenyAllFilter; /// Currently we treat all RPC operations as externals. diff --git a/tee-worker/core-primitives/types/src/lib.rs b/tee-worker/core-primitives/types/src/lib.rs index 911282e427..882265fae2 100644 --- a/tee-worker/core-primitives/types/src/lib.rs +++ b/tee-worker/core-primitives/types/src/lib.rs @@ -21,53 +21,23 @@ use crate::storage::StorageEntry; use codec::{Decode, Encode}; use itp_sgx_crypto::ShieldingCryptoDecrypt; -use litentry_primitives::{decl_rsa_request, RequestAesKeyNonce}; +use litentry_primitives::decl_rsa_request; use sp_std::{boxed::Box, fmt::Debug, vec::Vec}; pub mod parentchain; pub mod storage; -/// Substrate runtimes provide no string type. Hence, for arbitrary data of varying length the -/// `Vec` is used. In the polkadot-js the typedef `Text` is used to automatically -/// utf8 decode bytes into a string. -#[cfg(not(feature = "std"))] -pub type PalletString = Vec; - -#[cfg(feature = "std")] -pub type PalletString = String; - pub use itp_sgx_runtime_primitives::types::*; -pub use litentry_primitives::{Assertion, DecryptableRequest}; +pub use litentry_primitives::{ + Assertion, AttestationType, DecryptableRequest, Enclave, EnclaveFingerprint, MrEnclave, + WorkerType, +}; pub use sp_core::{crypto::AccountId32 as AccountId, H256}; pub type IpfsHash = [u8; 46]; -pub type MrEnclave = [u8; 32]; - pub type CallIndex = [u8; 2]; -// pallet teerex -pub type ConfirmCallFn = (CallIndex, ShardIdentifier, H256, Vec); -pub type ShieldFundsFn = (CallIndex, Vec, Balance, ShardIdentifier); -pub type CallWorkerFn = (CallIndex, RsaRequest); - -pub type UpdateScheduledEnclaveFn = (CallIndex, SidechainBlockNumber, MrEnclave); -pub type RemoveScheduledEnclaveFn = (CallIndex, SidechainBlockNumber); - -// pallet IMP -pub type LinkIdentityParams = (ShardIdentifier, AccountId, Vec, Vec, RequestAesKeyNonce); -pub type LinkIdentityFn = (CallIndex, LinkIdentityParams); - -pub type DeactivateIdentityParams = (ShardIdentifier, Vec); -pub type DeactivateIdentityFn = (CallIndex, DeactivateIdentityParams); - -pub type ActivateIdentityParams = (ShardIdentifier, Vec); -pub type ActivateIdentityFn = (CallIndex, DeactivateIdentityParams); - -// pallet VCMP -pub type RequestVCParams = (ShardIdentifier, Assertion); -pub type RequestVCFn = (CallIndex, RequestVCParams); - -pub type Enclave = EnclaveGen; +pub type PostOpaqueTaskFn = (CallIndex, RsaRequest); /// Simple blob to hold an encoded call #[derive(Debug, PartialEq, Eq, Clone, Default)] @@ -108,23 +78,6 @@ impl DecryptableRequest for RsaRequest { } } -// Todo: move this improved enclave definition into a primitives crate in the pallet_teerex repo. -#[derive(Encode, Decode, Clone, PartialEq, sp_core::RuntimeDebug)] -pub struct EnclaveGen { - pub pubkey: AccountId, - // FIXME: this is redundant information - pub mr_enclave: [u8; 32], - pub timestamp: u64, - // unix epoch in milliseconds - pub url: PalletString, // utf8 encoded url -} - -impl EnclaveGen { - pub fn new(pubkey: AccountId, mr_enclave: [u8; 32], timestamp: u64, url: PalletString) -> Self { - Self { pubkey, mr_enclave, timestamp, url } - } -} - #[derive(Debug, Clone, PartialEq, Encode, Decode, Eq)] pub enum DirectRequestStatus { /// Direct request was successfully executed diff --git a/tee-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs b/tee-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs index 141ff21b54..461142f97c 100644 --- a/tee-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs +++ b/tee-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs @@ -78,7 +78,6 @@ pub mod tests { use crate::builders::{ rpc_response_builder::RpcResponseBuilder, rpc_return_value_builder::RpcReturnValueBuilder, }; - use codec::Encode; use itp_rpc::Id; use itp_types::{TrustedOperationStatus, H256}; diff --git a/tee-worker/core/parentchain/indirect-calls-executor/src/executor.rs b/tee-worker/core/parentchain/indirect-calls-executor/src/executor.rs index 0c2dbcf74c..aae0dcc240 100644 --- a/tee-worker/core/parentchain/indirect-calls-executor/src/executor.rs +++ b/tee-worker/core/parentchain/indirect-calls-executor/src/executor.rs @@ -29,7 +29,7 @@ use binary_merkle_tree::merkle_root; use codec::{Decode, Encode}; use core::marker::PhantomData; use itp_node_api::metadata::{ - pallet_teerex::TeerexCallIndexes, provider::AccessNodeMetadata, NodeMetadataTrait, + pallet_teebag::TeebagCallIndexes, provider::AccessNodeMetadata, NodeMetadataTrait, }; use itp_sgx_crypto::{key_repository::AccessKey, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}; use itp_stf_executor::traits::{StfEnclaveSigning, StfShardVaultQuery}; @@ -217,10 +217,10 @@ impl< ParentchainBlock: ParentchainBlockTrait, { let call = self.node_meta_data_provider.get_from_metadata(|meta_data| { - meta_data.confirm_processed_parentchain_block_call_indexes() + meta_data.parentchain_block_processed_call_indexes() })??; let root: H256 = merkle_root::(extrinsics); - trace!("prepared confirm_processed_parentchain_block() call for block {:?} with index {:?} and merkle root {}", block_number, call, root); + trace!("prepared parentchain_block_processed() call for block {:?} with index {:?} and merkle root {}", block_number, call, root); // Litentry: we don't include `shard` in the extrinsic parameter to be backwards compatible, // however, we should not forget it in case we need it later Ok(OpaqueCall::from_tuple(&(call, block_hash, block_number, root))) @@ -320,7 +320,7 @@ mod test { stf_mock::{GetterMock, TrustedCallSignedMock}, }; use itp_top_pool_author::mocks::AuthorApiMock; - use itp_types::{Block, CallWorkerFn, RsaRequest, ShardIdentifier, ShieldFundsFn}; + use itp_types::{Block, PostOpaqueTaskFn, RsaRequest, ShardIdentifier}; use sp_core::{ed25519, Pair}; use sp_runtime::{MultiAddress, MultiSignature, OpaqueExtrinsic}; use std::assert_matches::assert_matches; @@ -366,41 +366,6 @@ mod test { assert_eq!(1, top_pool_author.pending_tops(shard_id()).unwrap().len()); } - #[test] - fn shielding_call_can_be_added_to_pool_successfully() { - let _ = env_logger::builder().is_test(true).try_init(); - - let mr_enclave = [33u8; 32]; - let (indirect_calls_executor, top_pool_author, shielding_key_repo) = - test_fixtures(mr_enclave.clone(), NodeMetadataMock::new()); - let shielding_key = shielding_key_repo.retrieve_key().unwrap(); - - let opaque_extrinsic = OpaqueExtrinsic::from_bytes( - shield_funds_unchecked_extrinsic(&shielding_key).encode().as_slice(), - ) - .unwrap(); - - let parentchain_block = ParentchainBlockBuilder::default() - .with_extrinsics(vec![opaque_extrinsic]) - .build(); - - indirect_calls_executor - .execute_indirect_calls_in_extrinsics(&parentchain_block, &Vec::new()) - .unwrap(); - - assert_eq!(1, top_pool_author.pending_tops(shard_id()).unwrap().len()); - let submitted_extrinsic = - top_pool_author.pending_tops(shard_id()).unwrap().first().cloned().unwrap(); - let decrypted_extrinsic = shielding_key.decrypt(&submitted_extrinsic).unwrap(); - let decoded_operation = TrustedOperation::::decode( - &mut decrypted_extrinsic.as_slice(), - ) - .unwrap(); - assert_matches!(decoded_operation, TrustedOperation::indirect_call(_)); - let trusted_call_signed = decoded_operation.to_call().unwrap(); - assert!(trusted_call_signed.verify_signature(&mr_enclave, &shard_id())); - } - #[test] fn ensure_empty_extrinsic_vec_triggers_zero_filled_merkle_root() { // given @@ -409,11 +374,10 @@ mod test { let block_hash = H256::from([1; 32]); let extrinsics = Vec::new(); - let confirm_processed_parentchain_block_indexes = - dummy_metadata.confirm_processed_parentchain_block_call_indexes().unwrap(); + let parentchain_block_processed_call_indexes = + dummy_metadata.parentchain_block_processed_call_indexes().unwrap(); let expected_call = - (confirm_processed_parentchain_block_indexes, block_hash, 1u32, H256::default()) - .encode(); + (parentchain_block_processed_call_indexes, block_hash, 1u32, H256::default()).encode(); // when let call = indirect_calls_executor @@ -432,12 +396,11 @@ mod test { let block_hash = H256::from([1; 32]); let extrinsics = vec![H256::from([4; 32]), H256::from([9; 32])]; - let confirm_processed_parentchain_block_indexes = - dummy_metadata.confirm_processed_parentchain_block_call_indexes().unwrap(); + let parentchain_block_processed_call_indexes = + dummy_metadata.parentchain_block_processed_call_indexes().unwrap(); let zero_root_call = - (confirm_processed_parentchain_block_indexes, block_hash, 1u32, H256::default()) - .encode(); + (parentchain_block_processed_call_indexes, block_hash, 1u32, H256::default()).encode(); // when let call = indirect_calls_executor @@ -448,27 +411,12 @@ mod test { assert_ne!(call.0, zero_root_call); } - fn shield_funds_unchecked_extrinsic( - shielding_key: &ShieldingCryptoMock, - ) -> ParentchainUncheckedExtrinsic { - let target_account = shielding_key.encrypt(&AccountId::new([2u8; 32]).encode()).unwrap(); - let dummy_metadata = NodeMetadataMock::new(); - - let shield_funds_indexes = dummy_metadata.shield_funds_call_indexes().unwrap(); - ParentchainUncheckedExtrinsic::::new_signed( - (shield_funds_indexes, target_account, 1000u128, shard_id()), - MultiAddress::Address32([1u8; 32]), - MultiSignature::Ed25519(default_signature()), - default_extrinsic_params().signed_extra(), - ) - } - - fn invoke_unchecked_extrinsic() -> ParentchainUncheckedExtrinsic { + fn invoke_unchecked_extrinsic() -> ParentchainUncheckedExtrinsic { let request = RsaRequest::new(shard_id(), vec![1u8, 2u8]); let dummy_metadata = NodeMetadataMock::new(); - let call_worker_indexes = dummy_metadata.invoke_call_indexes().unwrap(); + let call_worker_indexes = dummy_metadata.post_opaque_task_call_indexes().unwrap(); - ParentchainUncheckedExtrinsic::::new_signed( + ParentchainUncheckedExtrinsic::::new_signed( (call_worker_indexes, request), MultiAddress::Address32([1u8; 32]), MultiSignature::Ed25519(default_signature()), diff --git a/tee-worker/core/parentchain/indirect-calls-executor/src/mock.rs b/tee-worker/core/parentchain/indirect-calls-executor/src/mock.rs index 38189f44d8..57c1645cc2 100644 --- a/tee-worker/core/parentchain/indirect-calls-executor/src/mock.rs +++ b/tee-worker/core/parentchain/indirect-calls-executor/src/mock.rs @@ -58,11 +58,7 @@ where "[ShieldFundsAndInvokeFilter] attempting to execute indirect call with index {:?}", index ); - if index == metadata.shield_funds_call_indexes().ok()? { - log::debug!("executing shield funds call"); - let args = ShieldFundsArgs::decode(call_args).unwrap(); - Some(IndirectCall::ShieldFunds(args)) - } else if index == metadata.invoke_call_indexes().ok()? { + if index == metadata.post_opaque_task_call_indexes().ok()? { log::debug!("executing invoke call"); let args = InvokeArgs::decode(call_args).unwrap(); Some(IndirectCall::Invoke(args)) diff --git a/tee-worker/core/rpc-client/Cargo.toml b/tee-worker/core/rpc-client/Cargo.toml index fc06593ed3..1f2b3ff104 100644 --- a/tee-worker/core/rpc-client/Cargo.toml +++ b/tee-worker/core/rpc-client/Cargo.toml @@ -31,7 +31,6 @@ itp-utils = { path = "../../core-primitives/utils" } ita-stf = { path = "../../app-libs/stf" } itp-stf-primitives = { path = "../../core-primitives/stf-primitives" } litentry-primitives = { path = "../../litentry/primitives", default-features = false } -teerex-primitives = { path = "../../../primitives/teerex", default-features = false } [dev-dependencies] env_logger = "0.9.0" diff --git a/tee-worker/core/rpc-client/src/direct_client.rs b/tee-worker/core/rpc-client/src/direct_client.rs index 7814b0e7e3..f5fad98dc2 100644 --- a/tee-worker/core/rpc-client/src/direct_client.rs +++ b/tee-worker/core/rpc-client/src/direct_client.rs @@ -17,6 +17,7 @@ //! Interface for direct access to a workers rpc. +pub use crate::error::{Error, Result}; use crate::ws_client::{WsClient, WsClientControl}; use base58::ToBase58; use codec::{Decode, Encode}; @@ -25,7 +26,7 @@ use ita_stf::{Getter, PublicGetter}; use itp_api_client_types::Metadata; use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; use itp_stf_primitives::types::{AccountId, ShardIdentifier}; -use itp_types::{DirectRequestStatus, RsaRequest}; +use itp_types::{DirectRequestStatus, MrEnclave, RsaRequest}; use itp_utils::{FromHexPrefixed, ToHexPrefixed}; use litentry_primitives::Identity; use log::*; @@ -39,9 +40,6 @@ use std::{ thread, thread::JoinHandle, }; -use teerex_primitives::MrEnclave; - -pub use crate::error::{Error, Result}; #[derive(Clone)] pub struct DirectClient { diff --git a/tee-worker/core/rpc-client/src/mock.rs b/tee-worker/core/rpc-client/src/mock.rs index 8f582ecc27..bffb003e65 100644 --- a/tee-worker/core/rpc-client/src/mock.rs +++ b/tee-worker/core/rpc-client/src/mock.rs @@ -23,10 +23,10 @@ use frame_metadata::RuntimeMetadataPrefixed; use ita_stf::H256; use itp_api_client_types::Metadata; use itp_stf_primitives::types::{AccountId, ShardIdentifier}; +use itp_types::MrEnclave; use litentry_primitives::Identity; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use std::{sync::mpsc::Sender as MpscSender, thread::JoinHandle}; -use teerex_primitives::MrEnclave; #[derive(Clone, Default)] pub struct DirectClientMock { diff --git a/tee-worker/docker/docker-compose.yml b/tee-worker/docker/docker-compose.yml index 707588493d..938565778b 100644 --- a/tee-worker/docker/docker-compose.yml +++ b/tee-worker/docker/docker-compose.yml @@ -118,10 +118,9 @@ services: environment: - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, - TWITTER_OFFICIAL_URL=http://localhost:19527 - - TWITTER_LITENTRY_URL=http://localhost:19527 - TWITTER_AUTH_TOKEN_V2= - DISCORD_OFFICIAL_URL=http://localhost:19527 - - DISCORD_LITENTRY_URL=http://localhost:19527 + - LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 - DISCORD_AUTH_TOKEN= - ACHAINABLE_URL=http://localhost:19527 - ACHAINABLE_AUTH_KEY= @@ -135,6 +134,8 @@ services: - CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID - CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID - CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID + - LITENTRY_ARCHIVE_URL=http://localhost:19527 + - VIP3_URL=http://localhost:19527 networks: - litentry-test-network healthcheck: diff --git a/tee-worker/docker/lit-data-providers-test.yml b/tee-worker/docker/lit-data-provider-test.yml similarity index 84% rename from tee-worker/docker/lit-data-providers-test.yml rename to tee-worker/docker/lit-data-provider-test.yml index be0ee66ed4..469f617193 100644 --- a/tee-worker/docker/lit-data-providers-test.yml +++ b/tee-worker/docker/lit-data-provider-test.yml @@ -1,7 +1,7 @@ services: - lit-data-providers-test: + lit-data-provider-test: image: litentry/litentry-cli:latest - container_name: litentry-data-providers-test + container_name: litentry-data-provider-test volumes: - ../ts-tests:/ts-tests - ../client-api:/client-api @@ -17,7 +17,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-data-providers 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh data-provider.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-di-bitcoin-identity-test.yml b/tee-worker/docker/lit-di-bitcoin-identity-test.yml index 9cc7e41c35..22a1e0473c 100644 --- a/tee-worker/docker/lit-di-bitcoin-identity-test.yml +++ b/tee-worker/docker/lit-di-bitcoin-identity-test.yml @@ -17,7 +17,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-di-bitcoin-identity 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh di_bitcoin_identity.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-di-evm-identity-multiworker-test.yml b/tee-worker/docker/lit-di-evm-identity-multiworker-test.yml index 4649e93fdb..f5bb805edc 100644 --- a/tee-worker/docker/lit-di-evm-identity-multiworker-test.yml +++ b/tee-worker/docker/lit-di-evm-identity-multiworker-test.yml @@ -21,7 +21,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-di-evm-identity 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh di_evm_identity.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-di-evm-identity-test.yml b/tee-worker/docker/lit-di-evm-identity-test.yml index 7938ca67a8..b0c0152f79 100644 --- a/tee-worker/docker/lit-di-evm-identity-test.yml +++ b/tee-worker/docker/lit-di-evm-identity-test.yml @@ -17,7 +17,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-di-evm-identity 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh di_evm_identity.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-di-substrate-identity-multiworker-test.yml b/tee-worker/docker/lit-di-substrate-identity-multiworker-test.yml index f5647624b9..e0bb7320b6 100644 --- a/tee-worker/docker/lit-di-substrate-identity-multiworker-test.yml +++ b/tee-worker/docker/lit-di-substrate-identity-multiworker-test.yml @@ -21,7 +21,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-di-substrate-identity 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh di_substrate_identity.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-di-substrate-identity-test.yml b/tee-worker/docker/lit-di-substrate-identity-test.yml index 3f1c8250c7..9c194728d8 100644 --- a/tee-worker/docker/lit-di-substrate-identity-test.yml +++ b/tee-worker/docker/lit-di-substrate-identity-test.yml @@ -17,7 +17,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-di-substrate-identity 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh di_substrate_identity.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-di-vc-multiworker-test.yml b/tee-worker/docker/lit-di-vc-multiworker-test.yml index 08bb708212..fc0eebca3b 100644 --- a/tee-worker/docker/lit-di-vc-multiworker-test.yml +++ b/tee-worker/docker/lit-di-vc-multiworker-test.yml @@ -21,7 +21,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-di-vc 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh di_vc.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-di-vc-test.yml b/tee-worker/docker/lit-di-vc-test.yml index a41ebfc457..532e856b40 100644 --- a/tee-worker/docker/lit-di-vc-test.yml +++ b/tee-worker/docker/lit-di-vc-test.yml @@ -17,7 +17,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-di-vc 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh di_vc.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-dr-vc-multiworker-test.yml b/tee-worker/docker/lit-dr-vc-multiworker-test.yml new file mode 100644 index 0000000000..8bafe6680a --- /dev/null +++ b/tee-worker/docker/lit-dr-vc-multiworker-test.yml @@ -0,0 +1,28 @@ +services: + lit-dr-vc-multiworker-test: + image: litentry/litentry-cli:latest + container_name: litentry-dr-vc-test + volumes: + - ../ts-tests:/ts-tests + - ../client-api:/client-api + - ../cli:/usr/local/worker-cli + build: + context: .. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + litentry-worker-1: + condition: service_healthy + litentry-worker-2: + condition: service_healthy + litentry-worker-3: + condition: service_healthy + networks: + - litentry-test-network + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh dr_vc.test.ts 2>&1' " + restart: "no" +networks: + litentry-test-network: + driver: bridge diff --git a/tee-worker/docker/lit-dr-vc-test.yml b/tee-worker/docker/lit-dr-vc-test.yml new file mode 100644 index 0000000000..40624dbb40 --- /dev/null +++ b/tee-worker/docker/lit-dr-vc-test.yml @@ -0,0 +1,24 @@ +services: + lit-dr-vc-test: + image: litentry/litentry-cli:latest + container_name: litentry-dr-vc-test + volumes: + - ../ts-tests:/ts-tests + - ../client-api:/client-api + - ../cli:/usr/local/worker-cli + build: + context: .. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + litentry-worker-1: + condition: service_healthy + networks: + - litentry-test-network + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh dr_vc.test.ts 2>&1' " + restart: "no" +networks: + litentry-test-network: + driver: bridge diff --git a/tee-worker/docker/lit-ii-batch-test-multiworker.yml b/tee-worker/docker/lit-ii-batch-test-multiworker.yml index 6d26ecea5d..7b6ce161db 100644 --- a/tee-worker/docker/lit-ii-batch-test-multiworker.yml +++ b/tee-worker/docker/lit-ii-batch-test-multiworker.yml @@ -21,7 +21,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-ii-batch 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh ii_batch.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-ii-batch-test.yml b/tee-worker/docker/lit-ii-batch-test.yml index f0a6ee9fbf..cb8225857b 100644 --- a/tee-worker/docker/lit-ii-batch-test.yml +++ b/tee-worker/docker/lit-ii-batch-test.yml @@ -17,7 +17,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-ii-batch 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh ii_batch.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-ii-identity-multiworker-test.yml b/tee-worker/docker/lit-ii-identity-multiworker-test.yml index 684f832367..bdcb0d9e28 100644 --- a/tee-worker/docker/lit-ii-identity-multiworker-test.yml +++ b/tee-worker/docker/lit-ii-identity-multiworker-test.yml @@ -21,7 +21,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-ii-identity 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh ii_identity.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-ii-identity-test.yml b/tee-worker/docker/lit-ii-identity-test.yml index 874b3dad67..66055f0280 100644 --- a/tee-worker/docker/lit-ii-identity-test.yml +++ b/tee-worker/docker/lit-ii-identity-test.yml @@ -17,7 +17,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-ii-identity 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh ii_identity.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-ii-vc-multiworker-test.yml b/tee-worker/docker/lit-ii-vc-multiworker-test.yml index f84a6e52a2..60a3ee7fcf 100644 --- a/tee-worker/docker/lit-ii-vc-multiworker-test.yml +++ b/tee-worker/docker/lit-ii-vc-multiworker-test.yml @@ -21,7 +21,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-ii-vc 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh ii_vc.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-ii-vc-test.yml b/tee-worker/docker/lit-ii-vc-test.yml index f530e499f8..d72f80d719 100644 --- a/tee-worker/docker/lit-ii-vc-test.yml +++ b/tee-worker/docker/lit-ii-vc-test.yml @@ -17,7 +17,7 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-ii-vc 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh ii_vc.test.ts 2>&1' " restart: "no" networks: litentry-test-network: diff --git a/tee-worker/docker/lit-resume-worker.yml b/tee-worker/docker/lit-resume-worker.yml index 319d426d2f..2ee8532ab2 100644 --- a/tee-worker/docker/lit-resume-worker.yml +++ b/tee-worker/docker/lit-resume-worker.yml @@ -15,8 +15,8 @@ services: condition: service_healthy networks: - litentry-test-network - entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_worker_test.sh test-resuming-worker 2>&1' " + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_worker_test.sh resuming_worker.test.ts 2>&1' " restart: "no" networks: litentry-test-network: - driver: bridge \ No newline at end of file + driver: bridge diff --git a/tee-worker/docker/lit-set-heartbeat-timeout.yml b/tee-worker/docker/lit-set-heartbeat-timeout.yml deleted file mode 100644 index 2dc293fbc8..0000000000 --- a/tee-worker/docker/lit-set-heartbeat-timeout.yml +++ /dev/null @@ -1,24 +0,0 @@ -services: - lit-set-heartbeat-timeout: - image: litentry/litentry-cli:latest - container_name: litentry-set-heartbeat-timeout - volumes: - - ../cli:/usr/local/worker-cli - build: - context: .. - dockerfile: build.Dockerfile - target: deployed-client - depends_on: - litentry-node: - condition: service_healthy - litentry-worker-1: - condition: service_healthy - networks: - - litentry-test-network - entrypoint: - "/usr/local/worker-cli/lit_set_heartbeat_timeout.sh -p 9912 -u ws://litentry-node - -V wss://litentry-worker-1 -A 2011 -W wss://litentry-worker-2 -B 2012 -C /usr/local/bin/litentry-cli 2>&1" - restart: "no" -networks: - litentry-test-network: - driver: bridge \ No newline at end of file diff --git a/tee-worker/docker/multiworker-docker-compose.yml b/tee-worker/docker/multiworker-docker-compose.yml index 70225a3d47..ce3688afe1 100644 --- a/tee-worker/docker/multiworker-docker-compose.yml +++ b/tee-worker/docker/multiworker-docker-compose.yml @@ -119,10 +119,9 @@ services: environment: - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, - TWITTER_OFFICIAL_URL=http://localhost:19527 - - TWITTER_LITENTRY_URL=http://localhost:19527 - TWITTER_AUTH_TOKEN_V2= - DISCORD_OFFICIAL_URL=http://localhost:19527 - - DISCORD_LITENTRY_URL=http://localhost:19527 + - LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 - DISCORD_AUTH_TOKEN= - ACHAINABLE_URL=http://localhost:19527 - ACHAINABLE_AUTH_KEY= @@ -136,6 +135,8 @@ services: - CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID - CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID - CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID + - LITENTRY_ARCHIVE_URL=http://localhost:19527 + - VIP3_URL=http://localhost:19527 networks: - litentry-test-network healthcheck: @@ -169,10 +170,9 @@ services: environment: - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, - TWITTER_OFFICIAL_URL=http://localhost:19527 - - TWITTER_LITENTRY_URL=http://localhost:19527 - TWITTER_AUTH_TOKEN_V2= - DISCORD_OFFICIAL_URL=http://localhost:19527 - - DISCORD_LITENTRY_URL=http://localhost:19527 + - LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 - DISCORD_AUTH_TOKEN= - ACHAINABLE_URL=http://localhost:19527 - ACHAINABLE_AUTH_KEY= @@ -186,6 +186,8 @@ services: - CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID - CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID - CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID + - LITENTRY_ARCHIVE_URL=http://localhost:19527 + - VIP3_URL=http://localhost:19527 networks: - litentry-test-network healthcheck: @@ -219,10 +221,9 @@ services: environment: - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, - TWITTER_OFFICIAL_URL=http://localhost:19527 - - TWITTER_LITENTRY_URL=http://localhost:19527 - TWITTER_AUTH_TOKEN_V2= - DISCORD_OFFICIAL_URL=http://localhost:19527 - - DISCORD_LITENTRY_URL=http://localhost:19527 + - LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 - DISCORD_AUTH_TOKEN= - ACHAINABLE_URL=http://localhost:19527 - ACHAINABLE_AUTH_KEY= @@ -236,6 +237,8 @@ services: - CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID - CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID - CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID + - LITENTRY_ARCHIVE_URL=http://localhost:19527 + - VIP3_URL=http://localhost:19527 networks: - litentry-test-network healthcheck: diff --git a/tee-worker/enclave-runtime/Cargo.lock b/tee-worker/enclave-runtime/Cargo.lock index 136db05d22..67e0bbaca8 100644 --- a/tee-worker/enclave-runtime/Cargo.lock +++ b/tee-worker/enclave-runtime/Cargo.lock @@ -545,6 +545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "num-traits 0.2.16", + "serde 1.0.193", ] [[package]] @@ -566,19 +567,6 @@ dependencies = [ "generic-array 0.14.7", ] -[[package]] -name = "common-primitives" -version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" -dependencies = [ - "derive_more", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "const-oid" version = "0.9.5" @@ -737,6 +725,17 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "der_derive", + "flagset", +] + [[package]] name = "der" version = "0.7.8" @@ -747,6 +746,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef71ddb5b3a1f53dee24817c8f70dfa1cb29e804c18d88c228d4bc9c86ee3b9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + [[package]] name = "derive-syn-parse" version = "0.1.5" @@ -807,7 +818,7 @@ version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ - "der", + "der 0.7.8", "digest 0.10.7", "elliptic-curve", "rfc6979", @@ -864,7 +875,6 @@ dependencies = [ "frame-system", "hex 0.4.3", "ipfs-unixfs", - "ita-oracle", "ita-parentchain-interface", "ita-sgx-runtime", "ita-stf", @@ -937,7 +947,6 @@ dependencies = [ "sgx_types", "sp-core", "sp-runtime", - "teerex-primitives 0.1.0 (git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42)", "webpki", ] @@ -1173,6 +1182,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flagset" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a7e408202050813e6f1d9addadcaafef3dca7530c7ddfb005d4081cce6779" + [[package]] name = "fnv" version = "1.0.6" @@ -1841,23 +1856,6 @@ dependencies = [ "sha2 0.9.9", ] -[[package]] -name = "ita-oracle" -version = "0.9.0" -dependencies = [ - "itc-rest-client", - "itp-enclave-metrics", - "itp-ocall-api", - "lazy_static", - "log", - "parity-scale-codec", - "serde 1.0.193", - "sgx_tstd", - "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", - "thiserror", - "url", -] - [[package]] name = "ita-parentchain-interface" version = "0.9.0" @@ -2349,6 +2347,9 @@ dependencies = [ [[package]] name = "itp-settings" version = "0.9.0" +dependencies = [ + "litentry-primitives", +] [[package]] name = "itp-sgx-crypto" @@ -2396,7 +2397,6 @@ name = "itp-sgx-runtime-primitives" version = "0.9.0" dependencies = [ "frame-system", - "litentry-primitives", "pallet-balances", "sp-core", "sp-runtime", @@ -2514,14 +2514,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "itp-teerex-storage" -version = "0.9.0" -dependencies = [ - "itp-storage", - "sp-std", -] - [[package]] name = "itp-test" version = "0.9.0" @@ -2536,10 +2528,10 @@ dependencies = [ "itp-stf-primitives", "itp-stf-state-handler", "itp-storage", - "itp-teerex-storage", "itp-time-utils", "itp-types", "jsonrpc-core", + "lc-teebag-storage", "litentry-primitives", "log", "parity-scale-codec", @@ -2825,10 +2817,9 @@ name = "its-validateer-fetch" version = "0.9.0" dependencies = [ "derive_more", - "frame-support", "itp-ocall-api", - "itp-teerex-storage", "itp-types", + "lc-teebag-storage", "parity-scale-codec", "sp-core", "sp-runtime", @@ -2837,9 +2828,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -3122,6 +3113,15 @@ dependencies = [ "url", ] +[[package]] +name = "lc-teebag-storage" +version = "0.1.0" +dependencies = [ + "itp-storage", + "itp-types", + "sp-std", +] + [[package]] name = "lc-vc-task-receiver" version = "0.1.0" @@ -3257,6 +3257,7 @@ dependencies = [ "litentry-hex-utils", "log", "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "pallet-teebag", "parity-scale-codec", "rand 0.7.3", "ring 0.16.20", @@ -3270,7 +3271,6 @@ dependencies = [ "sp-std", "strum", "strum_macros", - "teerex-primitives 0.1.0", ] [[package]] @@ -3687,6 +3687,31 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-teebag" +version = "0.1.0" +dependencies = [ + "base64 0.13.1", + "chrono 0.4.31", + "der 0.6.1", + "frame-support", + "frame-system", + "hex 0.4.3", + "log", + "pallet-timestamp", + "parity-scale-codec", + "ring 0.16.20", + "rustls-webpki", + "scale-info", + "serde 1.0.193", + "serde_json 1.0.107", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "x509-cert", +] + [[package]] name = "pallet-timestamp" version = "4.0.0-dev" @@ -4065,7 +4090,7 @@ dependencies = [ "cc", "sgx_tstd", "spin", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -4078,7 +4103,7 @@ dependencies = [ "libc", "once_cell 1.18.0", "spin", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] @@ -4177,6 +4202,22 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-pki-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47003264dea418db67060fa420ad16d0d2f8f0a0360d825c00e177ac52cb5d8" + +[[package]] +name = "rustls-webpki" +version = "0.102.0-alpha.3" +source = "git+https://github.com/rustls/webpki?rev=da923ed#da923edaab56f599971e58773617fb574cd019dc" +dependencies = [ + "ring 0.16.20", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -4303,7 +4344,7 @@ source = "git+https://github.com/mesalock-linux/sct.rs?branch=mesalock_sgx#c4d85 dependencies = [ "ring 0.16.19", "sgx_tstd", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -4313,7 +4354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", - "der", + "der 0.7.8", "generic-array 0.14.7", "subtle", "zeroize", @@ -5131,6 +5172,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "der 0.6.1", +] + [[package]] name = "ss58-registry" version = "1.43.0" @@ -5282,32 +5332,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "teerex-primitives" -version = "0.1.0" -dependencies = [ - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-std", -] - -[[package]] -name = "teerex-primitives" -version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" -dependencies = [ - "common-primitives", - "derive_more", - "log", - "parity-scale-codec", - "scale-info", - "serde 1.0.193", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "termcolor" version = "1.0.5" @@ -5576,6 +5600,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.1.1" @@ -5609,9 +5639,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -5619,9 +5649,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", @@ -5634,9 +5664,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote 1.0.33", "wasm-bindgen-macro-support", @@ -5644,9 +5674,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote 1.0.33", @@ -5657,15 +5687,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", @@ -5678,7 +5708,7 @@ source = "git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx#8dbe6 dependencies = [ "ring 0.16.19", "sgx_tstd", - "untrusted", + "untrusted 0.7.1", ] [[package]] @@ -5739,6 +5769,18 @@ dependencies = [ "tap", ] +[[package]] +name = "x509-cert" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d224a125dec5adda27d0346b9cae9794830279c4f9c27e4ab0b6c408d54012" +dependencies = [ + "const-oid", + "der 0.6.1", + "flagset", + "spki", +] + [[package]] name = "yasna" version = "0.3.1" diff --git a/tee-worker/enclave-runtime/Cargo.toml b/tee-worker/enclave-runtime/Cargo.toml index 6ac3c843b0..ffe4a27b10 100644 --- a/tee-worker/enclave-runtime/Cargo.toml +++ b/tee-worker/enclave-runtime/Cargo.toml @@ -31,11 +31,6 @@ offchain-worker = [ "itp-settings/offchain-worker", "itp-top-pool-author/offchain-worker", ] -teeracle = [ - "ita-oracle", - "itp-settings/teeracle", - "itp-top-pool-author/teeracle", -] test = [ "ita-stf/test", "itc-parentchain/test", @@ -95,10 +90,8 @@ base58 = { rev = "sgx_1.1.3", package = "rust-base58", default-features = false, cid = { default-features = false, git = "https://github.com/whalelephant/rust-cid", branch = "nstd" } multibase = { default-features = false, git = "https://github.com/whalelephant/rust-multibase", branch = "nstd" } -teerex-primitives = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } # local deps -ita-oracle = { path = "../app-libs/oracle", default-features = false, optional = true, features = ["sgx"] } ita-parentchain-interface = { path = "../app-libs/parentchain-interface", default-features = false, features = ["sgx"] } ita-sgx-runtime = { path = "../app-libs/sgx-runtime", default-features = false } ita-stf = { path = "../app-libs/stf", default-features = false, features = ["sgx"] } diff --git a/tee-worker/enclave-runtime/Enclave.edl b/tee-worker/enclave-runtime/Enclave.edl index 04c02fea61..80d878511b 100644 --- a/tee-worker/enclave-runtime/Enclave.edl +++ b/tee-worker/enclave-runtime/Enclave.edl @@ -140,20 +140,6 @@ enclave { [out] uint32_t* unchecked_extrinsic_size ); - public sgx_status_t update_market_data_xt( - [in, size=crypto_currency_size] uint8_t* crypto_currency, uint32_t crypto_currency_size, - [in, size=fiat_currency_size] uint8_t* fiat_currency, uint32_t fiat_currency_size, - [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, - [out] uint32_t* unchecked_extrinsic_size - ); - - public sgx_status_t update_weather_data_xt( - [in, size=weather_info_logitude_size] uint8_t* weather_info_logitude, uint32_t weather_info_logitude_size, - [in, size=weather_info_latitude_size] uint8_t* weather_info_latitude, uint32_t weather_info_latitude_size, - [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, - [out] uint32_t* unchecked_extrinsic_size - ); - public sgx_status_t dump_ias_ra_cert_to_disk(); public sgx_status_t dump_dcap_ra_cert_to_disk([in] const sgx_target_info_t* quoting_enclave_target_info, uint32_t quote_size); diff --git a/tee-worker/enclave-runtime/src/attestation.rs b/tee-worker/enclave-runtime/src/attestation.rs index 5b7f7ded3a..933ba536a9 100644 --- a/tee-worker/enclave-runtime/src/attestation.rs +++ b/tee-worker/enclave-runtime/src/attestation.rs @@ -42,20 +42,23 @@ use itp_attestation_handler::{AttestationHandler, RemoteAttestationType, SgxQlQv use itp_component_container::ComponentGetter; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::metadata::{ - pallet_teerex::TeerexCallIndexes, + pallet_teebag::TeebagCallIndexes, provider::{AccessNodeMetadata, Error as MetadataProviderError}, Error as MetadataError, }; use itp_node_api_metadata::NodeMetadata; -use itp_settings::worker::MR_ENCLAVE_SIZE; +use itp_settings::{ + worker::MR_ENCLAVE_SIZE, + worker_mode::{ProvideWorkerMode, WorkerModeProvider}, +}; use itp_sgx_crypto::{ ed25519_derivation::DeriveEd25519, key_repository::AccessKey, Error as SgxCryptoError, }; -use itp_types::OpaqueCall; +use itp_types::{AttestationType, OpaqueCall, WorkerType}; use itp_utils::write_slice_and_whitespace_pad; use log::*; use sgx_types::*; -use sp_core::Pair; +use sp_core::{ed25519::Public as Ed25519Public, Pair}; use sp_runtime::OpaqueExtrinsic; use std::{prelude::v1::*, slice, vec::Vec}; @@ -142,7 +145,8 @@ pub unsafe extern "C" fn generate_ias_ra_extrinsic( } let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); let url = match String::decode(&mut url_slice) { - Ok(url) => url, + // Litentry: the teebag extrinsic expects an URL with plain utf8 encoded Vec, not string scale-encoded + Ok(url) => url.as_bytes().to_vec(), Err(_) => return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), }; @@ -178,7 +182,8 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( } let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); let url = match String::decode(&mut url_slice) { - Ok(url) => url, + // Litentry: the teebag extrinsic expects an URL with plain utf8 encoded Vec, not string scale-encoded + Ok(url) => url.as_bytes().to_vec(), Err(_) => return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), }; @@ -204,7 +209,7 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( } pub fn generate_dcap_ra_extrinsic_internal( - url: String, + url: Vec, skip_ra: bool, quoting_enclave_target_info: Option<&sgx_target_info_t>, quote_size: Option<&u32>, @@ -287,7 +292,8 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic_from_quote( } let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); let url = match String::decode(&mut url_slice) { - Ok(url) => url, + // Litentry: the teebag extrinsic expects an URL with plain utf8 encoded Vec, not string scale-encoded + Ok(url) => url.as_bytes().to_vec(), Err(_) => return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), }; @@ -311,7 +317,7 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic_from_quote( } pub fn generate_dcap_ra_extrinsic_from_quote_internal( - url: String, + url: Vec, quote: &[u8], ) -> EnclaveResult { let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; @@ -324,15 +330,25 @@ pub fn generate_dcap_ra_extrinsic_from_quote_internal( let shielding_pubkey = get_shielding_pubkey()?; let vc_pubkey = get_vc_pubkey()?; + let attestation_type = AttestationType::Dcap(Default::default()); // skip_ra should be false here already - let call = OpaqueCall::from_tuple(&(call_ids, quote, url, shielding_pubkey, vc_pubkey)); + let call = OpaqueCall::from_tuple(&( + call_ids, + WorkerType::Identity, + WorkerModeProvider::worker_mode(), + quote, + url, + shielding_pubkey, + vc_pubkey, + attestation_type, + )); info!(" [Enclave] Compose register enclave got extrinsic, returning"); create_extrinsics(call) } pub fn generate_dcap_skip_ra_extrinsic_from_mr_enclave( - url: String, + url: Vec, quote: &[u8], ) -> EnclaveResult { let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; @@ -346,25 +362,35 @@ pub fn generate_dcap_skip_ra_extrinsic_from_mr_enclave( let shielding_pubkey = get_shielding_pubkey()?; let vc_pubkey = get_vc_pubkey()?; - let call = OpaqueCall::from_tuple(&(call_ids, quote, url, shielding_pubkey, vc_pubkey)); + let call = OpaqueCall::from_tuple(&( + call_ids, + WorkerType::Identity, + WorkerModeProvider::worker_mode(), + quote, + url, + shielding_pubkey, + vc_pubkey, + AttestationType::Ignore, + )); info!(" [Enclave] Compose register enclave (skip-ra) got extrinsic, returning"); create_extrinsics(call) } fn generate_ias_ra_extrinsic_internal( - url: String, + url: Vec, skip_ra: bool, ) -> EnclaveResult { let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; let cert_der = attestation_handler.generate_ias_ra_cert(skip_ra)?; - generate_ias_ra_extrinsic_from_der_cert_internal(url, &cert_der) + generate_ias_ra_extrinsic_from_der_cert_internal(url, &cert_der, skip_ra) } pub fn generate_ias_ra_extrinsic_from_der_cert_internal( - url: String, + url: Vec, cert_der: &[u8], + skip_ra: bool, ) -> EnclaveResult { let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; @@ -375,8 +401,18 @@ pub fn generate_ias_ra_extrinsic_from_der_cert_internal( let shielding_pubkey = get_shielding_pubkey()?; let vc_pubkey = get_vc_pubkey()?; + let attestation_type = if skip_ra { AttestationType::Ignore } else { AttestationType::Ias }; - let call = OpaqueCall::from_tuple(&(call_ids, cert_der, url, shielding_pubkey, vc_pubkey)); + let call = OpaqueCall::from_tuple(&( + call_ids, + WorkerType::Identity, + WorkerModeProvider::worker_mode(), + cert_der, + url, + shielding_pubkey, + vc_pubkey, + attestation_type, + )); create_extrinsics(call) } @@ -533,18 +569,16 @@ fn get_shielding_pubkey() -> EnclaveResult>> { }) .ok(); - debug!("[Enclave] shielding_pubkey size: {:?}", shielding_pubkey.clone().map(|key| key.len())); - Ok(shielding_pubkey) } -fn get_vc_pubkey() -> EnclaveResult>> { +fn get_vc_pubkey() -> EnclaveResult> { let vc_pubkey = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT .get()? .retrieve_key() .and_then(|keypair| { // vc signing pubkey - keypair.derive_ed25519().map(|keypair| keypair.public().to_vec()) + keypair.derive_ed25519().map(|keypair| keypair.public()) }) .ok(); diff --git a/tee-worker/enclave-runtime/src/empty_impls.rs b/tee-worker/enclave-runtime/src/empty_impls.rs index e401fa8d05..e011e4d19c 100644 --- a/tee-worker/enclave-runtime/src/empty_impls.rs +++ b/tee-worker/enclave-runtime/src/empty_impls.rs @@ -22,35 +22,3 @@ pub extern "C" fn test_main_entrance() -> sgx_types::size_t { unreachable!("Tests are not available when compiled in production mode.") } - -/// Empty Teeracle market data implementation. -#[cfg(not(feature = "teeracle"))] -#[no_mangle] -#[allow(clippy::unreachable)] -pub unsafe extern "C" fn update_market_data_xt( - _crypto_currency_ptr: *const u8, - _crypto_currency_size: u32, - _fiat_currency_ptr: *const u8, - _fiat_currency_size: u32, - _unchecked_extrinsic: *mut u8, - _unchecked_extrinsic_max_size: u32, - _unchecked_extrinsic_size: *mut u32, -) -> sgx_types::sgx_status_t { - unreachable!("Cannot update market data, teeracle feature is not enabled.") -} - -/// Empty Teeracle Weather data implementation. -#[cfg(not(feature = "teeracle"))] -#[no_mangle] -#[allow(clippy::unreachable)] -pub unsafe extern "C" fn update_weather_data_xt( - _weather_info_longitude: *const u8, - _weather_info_longitude_size: u32, - _weather_info_latitude: *const u8, - _weather_info_latitude_size: u32, - _unchecked_extrinsic: *mut u8, - _unchecked_extrinsic_max_size: u32, - _unchecked_extrinsic_size: *mut u32, -) -> sgx_types::sgx_status_t { - unreachable!("Cannot update weather data, teeracle feature is not enabled.") -} diff --git a/tee-worker/enclave-runtime/src/initialization/mod.rs b/tee-worker/enclave-runtime/src/initialization/mod.rs index 5f50cdb42d..a0edccab0b 100644 --- a/tee-worker/enclave-runtime/src/initialization/mod.rs +++ b/tee-worker/enclave-runtime/src/initialization/mod.rs @@ -216,8 +216,11 @@ pub(crate) fn init_enclave( Arc::new(IntelAttestationHandler::new(ocall_api, signing_key_repository)); GLOBAL_ATTESTATION_HANDLER_COMPONENT.initialize(attestation_handler); - let data_provider_config = DataProviderConfig::new(); - GLOBAL_DATA_PROVIDER_CONFIG.initialize(data_provider_config.into()); + if let Ok(data_provider_config) = DataProviderConfig::new() { + GLOBAL_DATA_PROVIDER_CONFIG.initialize(data_provider_config.into()); + } else { + return Err(Error::Other("data provider initialize error".into())) + } Ok(()) } diff --git a/tee-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs b/tee-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs index f297c4960e..aeeec12a5b 100644 --- a/tee-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs +++ b/tee-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs @@ -100,8 +100,6 @@ impl IntegriteeParachainHandler { extrinsics_factory.clone(), )?, WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher(block_importer), - WorkerMode::Teeracle => - Arc::new(IntegriteeParentchainBlockImportDispatcher::new_empty_dispatcher()), }; let parachain_handler = Self { diff --git a/tee-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs b/tee-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs index b5ae349479..207115d47f 100644 --- a/tee-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs +++ b/tee-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs @@ -99,8 +99,6 @@ impl IntegriteeSolochainHandler { extrinsics_factory.clone(), )?, WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher(block_importer), - WorkerMode::Teeracle => - Arc::new(IntegriteeParentchainBlockImportDispatcher::new_empty_dispatcher()), }; let solochain_handler = Self { diff --git a/tee-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs b/tee-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs index bf24f6fdd4..e4a08cce6d 100644 --- a/tee-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs +++ b/tee-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs @@ -104,8 +104,6 @@ impl TargetAParachainHandler { )?, WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher_for_target_a(block_importer), - WorkerMode::Teeracle => - Arc::new(TargetAParentchainBlockImportDispatcher::new_empty_dispatcher()), }; let parachain_handler = Self { diff --git a/tee-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs b/tee-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs index f5cf2ae8ff..e26ce6833d 100644 --- a/tee-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs +++ b/tee-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs @@ -97,8 +97,6 @@ impl TargetASolochainHandler { )?, WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher_for_target_a(block_importer), - WorkerMode::Teeracle => - Arc::new(TargetAParentchainBlockImportDispatcher::new_empty_dispatcher()), }; let solochain_handler = Self { diff --git a/tee-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs b/tee-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs index be44224c65..36d83a0e06 100644 --- a/tee-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs +++ b/tee-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs @@ -104,8 +104,6 @@ impl TargetBParachainHandler { )?, WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher_for_target_b(block_importer), - WorkerMode::Teeracle => - Arc::new(TargetBParentchainBlockImportDispatcher::new_empty_dispatcher()), }; let parachain_handler = Self { diff --git a/tee-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs b/tee-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs index 842baa8129..015ff2cea6 100644 --- a/tee-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs +++ b/tee-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs @@ -97,8 +97,6 @@ impl TargetBSolochainHandler { )?, WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher_for_target_b(block_importer), - WorkerMode::Teeracle => - Arc::new(TargetBParentchainBlockImportDispatcher::new_empty_dispatcher()), }; let solochain_handler = Self { diff --git a/tee-worker/enclave-runtime/src/lib.rs b/tee-worker/enclave-runtime/src/lib.rs index 208dcb50f5..c87c3e3b22 100644 --- a/tee-worker/enclave-runtime/src/lib.rs +++ b/tee-worker/enclave-runtime/src/lib.rs @@ -71,7 +71,7 @@ use itp_component_container::ComponentGetter; use itp_import_queue::PushToQueue; use itp_node_api::metadata::NodeMetadata; use itp_nonce_cache::{MutateNonce, Nonce}; -use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerModeProvider}; use itp_sgx_crypto::key_repository::AccessPubkey; use itp_storage::{StorageProof, StorageProofChecker}; use itp_types::{ShardIdentifier, SignedBlock}; @@ -102,9 +102,6 @@ mod sync; mod tls_ra; pub mod top_pool_execution; -#[cfg(feature = "teeracle")] -pub mod teeracle; - #[cfg(feature = "test")] pub mod test; @@ -590,10 +587,6 @@ fn dispatch_parentchain_blocks_for_import id: &ParentchainId, is_syncing: bool, ) -> Result<()> { - if WorkerModeProvider::worker_mode() == WorkerMode::Teeracle { - trace!("Not importing any parentchain blocks"); - return Ok(()) - } trace!( "[{:?}] Dispatching Import of {} blocks and {} events", id, diff --git a/tee-worker/enclave-runtime/src/rpc/worker_api_direct.rs b/tee-worker/enclave-runtime/src/rpc/worker_api_direct.rs index 93b9370d57..e02f775f0d 100644 --- a/tee-worker/enclave-runtime/src/rpc/worker_api_direct.rs +++ b/tee-worker/enclave-runtime/src/rpc/worker_api_direct.rs @@ -339,8 +339,8 @@ where if_not_production!({ use itp_types::{MrEnclave, SidechainBlockNumber}; - // state_updateScheduledEnclave, params: sidechainBlockNumber, hex encoded mrenclave - io.add_sync_method("state_updateScheduledEnclave", move |params: Params| { + // state_setScheduledEnclave, params: sidechainBlockNumber, hex encoded mrenclave + io.add_sync_method("state_setScheduledEnclave", move |params: Params| { match params.parse::<(SidechainBlockNumber, String)>() { Ok((bn, mrenclave)) => return match hex::decode(&mrenclave) { @@ -492,8 +492,11 @@ fn forward_dcap_quote_inner(params: Params) -> Result { litentry_hex_utils::decode_hex(param).map_err(|e| format!("{:?}", e))?; let url = String::new(); - let ext = generate_dcap_ra_extrinsic_from_quote_internal(url, &encoded_quote_to_forward) - .map_err(|e| format!("{:?}", e))?; + let ext = generate_dcap_ra_extrinsic_from_quote_internal( + url.as_bytes().to_vec(), + &encoded_quote_to_forward, + ) + .map_err(|e| format!("{:?}", e))?; let validator_access = get_validator_accessor_from_integritee_solo_or_parachain() .map_err(|e| format!("{:?}", e))?; @@ -522,8 +525,12 @@ fn attesteer_forward_ias_attestation_report_inner( litentry_hex_utils::decode_hex(param).map_err(|e| format!("{:?}", e))?; let url = String::new(); - let ext = generate_ias_ra_extrinsic_from_der_cert_internal(url, &ias_attestation_report) - .map_err(|e| format!("{:?}", e))?; + let ext = generate_ias_ra_extrinsic_from_der_cert_internal( + url.as_bytes().to_vec(), + &ias_attestation_report, + false, + ) + .map_err(|e| format!("{:?}", e))?; let validator_access = get_validator_accessor_from_integritee_solo_or_parachain() .map_err(|e| format!("{:?}", e))?; diff --git a/tee-worker/enclave-runtime/src/teeracle/mod.rs b/tee-worker/enclave-runtime/src/teeracle/mod.rs deleted file mode 100644 index c38dd27c2e..0000000000 --- a/tee-worker/enclave-runtime/src/teeracle/mod.rs +++ /dev/null @@ -1,279 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{ - error::{Error, Result}, - initialization::global_components::GLOBAL_OCALL_API_COMPONENT, - utils::{ - get_extrinsic_factory_from_integritee_solo_or_parachain, - get_node_metadata_repository_from_integritee_solo_or_parachain, - }, -}; -use codec::{Decode, Encode}; -use core::slice; -use ita_oracle::{ - create_coin_gecko_oracle, create_coin_market_cap_oracle, create_open_meteo_weather_oracle, - metrics_exporter::ExportMetrics, - oracles::{ - exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, - weather_oracle::{GetLongitude, WeatherOracle}, - }, - traits::OracleSource, - types::{TradingInfo, TradingPair, WeatherInfo, WeatherQuery}, -}; -use itp_component_container::ComponentGetter; -use itp_extrinsics_factory::CreateExtrinsics; -use itp_node_api::metadata::{pallet_teeracle::TeeracleCallIndexes, provider::AccessNodeMetadata}; -use itp_types::OpaqueCall; -use itp_utils::write_slice_and_whitespace_pad; -use log::*; -use sgx_types::sgx_status_t; -use sp_runtime::OpaqueExtrinsic; -use std::{string::String, vec::Vec}; - -fn update_weather_data_internal(weather_info: WeatherInfo) -> Result> { - let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; - let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; - - let mut extrinsic_calls: Vec = Vec::new(); - - let open_meteo_weather_oracle = create_open_meteo_weather_oracle(ocall_api); - - match get_longitude(weather_info, open_meteo_weather_oracle) { - Ok(opaque_call) => extrinsic_calls.push(opaque_call), - Err(e) => { - error!("[-] Failed to get the newest longitude from OpenMeteo. {:?}", e); - }, - }; - let extrinsics = extrinsics_factory.create_extrinsics(extrinsic_calls.as_slice(), None)?; - Ok(extrinsics) -} - -fn get_longitude( - weather_info: WeatherInfo, - oracle: WeatherOracle, -) -> Result -where - OracleSourceType: OracleSource< - WeatherInfo, - OracleRequestResult = std::result::Result, - >, - MetricsExporter: ExportMetrics, -{ - let longitude = - oracle.get_longitude(weather_info.clone()).map_err(|e| Error::Other(e.into()))?; - - let base_url = oracle.get_base_url().map_err(|e| Error::Other(e.into()))?; - let source_base_url = base_url.as_str(); - - println!("Update the longitude: {}, for source {}", longitude, source_base_url); - - let node_metadata_repository = - get_node_metadata_repository_from_integritee_solo_or_parachain()?; - - let call_ids = node_metadata_repository - .get_from_metadata(|m| m.update_oracle_call_indexes()) - .map_err(Error::NodeMetadataProvider)? - .map_err(|e| Error::Other(format!("{:?}", e).into()))?; - - let call = OpaqueCall::from_tuple(&( - call_ids, - weather_info.weather_query.key().as_bytes().to_vec(), - source_base_url.as_bytes().to_vec(), - longitude.encode(), - )); - - Ok(call) -} - -#[no_mangle] -pub unsafe extern "C" fn update_weather_data_xt( - weather_info_longitude: *const u8, - weather_info_longitude_size: u32, - weather_info_latitude: *const u8, - weather_info_latitude_size: u32, - unchecked_extrinsic: *mut u8, - unchecked_extrinsic_max_size: u32, - unchecked_extrinsic_size: *mut u32, -) -> sgx_status_t { - let mut weather_info_longitude_slice = - slice::from_raw_parts(weather_info_longitude, weather_info_longitude_size as usize); - let longitude = match String::decode(&mut weather_info_longitude_slice) { - Ok(val) => val, - Err(e) => { - error!("Could not decode longitude: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let mut weather_info_latitude_slice = - slice::from_raw_parts(weather_info_latitude, weather_info_latitude_size as usize); - let latitude = match String::decode(&mut weather_info_latitude_slice) { - Ok(val) => val, - Err(e) => { - error!("Could not decode latitude: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let weather_query = WeatherQuery { longitude, latitude, hourly: " ".into() }; - let weather_info = WeatherInfo { weather_query }; - - let extrinsics = match update_weather_data_internal(weather_info) { - Ok(xts) => xts, - Err(e) => { - error!("Updating weather info failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - let extrinsic_slice = - slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); - - // Save created extrinsic as slice in the return value unchecked_extrinsic. - *unchecked_extrinsic_size = - match write_slice_and_whitespace_pad(extrinsic_slice, extrinsics.encode()) { - Ok(l) => l as u32, - Err(e) => { - error!("Copying encoded extrinsics into return slice failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - sgx_status_t::SGX_SUCCESS -} - -/// For now get the crypto/fiat currency exchange rate from coingecko and CoinMarketCap. -#[no_mangle] -pub unsafe extern "C" fn update_market_data_xt( - crypto_currency_ptr: *const u8, - crypto_currency_size: u32, - fiat_currency_ptr: *const u8, - fiat_currency_size: u32, - unchecked_extrinsic: *mut u8, - unchecked_extrinsic_max_size: u32, - unchecked_extrinsic_size: *mut u32, -) -> sgx_status_t { - let mut crypto_currency_slice = - slice::from_raw_parts(crypto_currency_ptr, crypto_currency_size as usize); - #[allow(clippy::unwrap_used)] - let crypto_currency: String = Decode::decode(&mut crypto_currency_slice).unwrap(); - - let mut fiat_currency_slice = - slice::from_raw_parts(fiat_currency_ptr, fiat_currency_size as usize); - #[allow(clippy::unwrap_used)] - let fiat_currency: String = Decode::decode(&mut fiat_currency_slice).unwrap(); - - let extrinsics = match update_market_data_internal(crypto_currency, fiat_currency) { - Ok(xts) => xts, - Err(e) => { - error!("Update market data failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - if extrinsics.is_empty() { - error!("Updating market data yielded no extrinsics"); - return sgx_status_t::SGX_ERROR_UNEXPECTED - } - let extrinsic_slice = - slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); - - // Save created extrinsic as slice in the return value unchecked_extrinsic. - *unchecked_extrinsic_size = - match write_slice_and_whitespace_pad(extrinsic_slice, extrinsics.encode()) { - Ok(l) => l as u32, - Err(e) => { - error!("Copying encoded extrinsics into return slice failed: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - - sgx_status_t::SGX_SUCCESS -} - -fn update_market_data_internal( - crypto_currency: String, - fiat_currency: String, -) -> Result> { - let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; - let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; - - let mut extrinsic_calls: Vec = Vec::new(); - - // Get the exchange rate - let trading_pair = TradingPair { crypto_currency, fiat_currency }; - - let coin_gecko_oracle = create_coin_gecko_oracle(ocall_api.clone()); - - match get_exchange_rate(trading_pair.clone(), coin_gecko_oracle) { - Ok(opaque_call) => extrinsic_calls.push(opaque_call), - Err(e) => { - error!("[-] Failed to get the newest exchange rate from CoinGecko. {:?}", e); - }, - }; - - let coin_market_cap_oracle = create_coin_market_cap_oracle(ocall_api); - match get_exchange_rate(trading_pair, coin_market_cap_oracle) { - Ok(oc) => extrinsic_calls.push(oc), - Err(e) => { - error!("[-] Failed to get the newest exchange rate from CoinMarketCap. {:?}", e); - }, - }; - - let extrinsics = extrinsics_factory.create_extrinsics(extrinsic_calls.as_slice(), None)?; - Ok(extrinsics) -} - -fn get_exchange_rate( - trading_pair: TradingPair, - oracle: ExchangeRateOracle, -) -> Result -where - OracleSourceType: OracleSource, - MetricsExporter: ExportMetrics, -{ - let (rate, base_url) = oracle - .get_exchange_rate(trading_pair.clone()) - .map_err(|e| Error::Other(e.into()))?; - - let source_base_url = base_url.as_str(); - - println!( - "Update the exchange rate: {} = {:?} for source {}", - trading_pair.clone().key(), - rate, - source_base_url, - ); - - let node_metadata_repository = - get_node_metadata_repository_from_integritee_solo_or_parachain()?; - - let call_ids = node_metadata_repository - .get_from_metadata(|m| m.update_exchange_rate_call_indexes()) - .map_err(Error::NodeMetadataProvider)? - .map_err(|e| Error::Other(format!("{:?}", e).into()))?; - - let call = OpaqueCall::from_tuple(&( - call_ids, - source_base_url.as_bytes().to_vec(), - trading_pair.key().as_bytes().to_vec(), - Some(rate), - )); - - Ok(call) -} diff --git a/tee-worker/enclave-runtime/src/test/fixtures/components.rs b/tee-worker/enclave-runtime/src/test/fixtures/components.rs index dd1237672d..34f3606010 100644 --- a/tee-worker/enclave-runtime/src/test/fixtures/components.rs +++ b/tee-worker/enclave-runtime/src/test/fixtures/components.rs @@ -27,7 +27,7 @@ use itp_stf_primitives::{ }; use itp_top_pool::pool::Options as PoolOptions; use itp_top_pool_author::api::SidechainApi; -use itp_types::{Block as ParentchainBlock, Enclave, ShardIdentifier}; +use itp_types::{Block as ParentchainBlock, ShardIdentifier}; use sp_core::{ed25519, Pair, H256}; use sp_runtime::traits::Header as HeaderTrait; use std::{boxed::Box, sync::Arc, vec::Vec}; @@ -41,13 +41,7 @@ pub(crate) fn create_ocall_api>( header: &Header, signer: &TestSigner, ) -> Arc { - let enclave_validateer = Enclave::new( - signer.public().into(), - Default::default(), - Default::default(), - Default::default(), - ); - Arc::new(TestOCallApi::default().add_validateer_set(header, Some(vec![enclave_validateer]))) + Arc::new(TestOCallApi::default().add_validateer_set(header, Some(vec![signer.public().into()]))) } pub(crate) fn encrypt_trusted_operation( diff --git a/tee-worker/enclave-runtime/src/test/mod.rs b/tee-worker/enclave-runtime/src/test/mod.rs index 6f3d7a252e..b3a25415a3 100644 --- a/tee-worker/enclave-runtime/src/test/mod.rs +++ b/tee-worker/enclave-runtime/src/test/mod.rs @@ -29,6 +29,3 @@ pub mod sidechain_event_tests; mod state_getter_tests; pub mod tests_main; pub mod top_pool_tests; - -#[cfg(feature = "teeracle")] -pub mod teeracle_tests; diff --git a/tee-worker/enclave-runtime/src/test/teeracle_tests.rs b/tee-worker/enclave-runtime/src/test/teeracle_tests.rs deleted file mode 100644 index bd9a4c8391..0000000000 --- a/tee-worker/enclave-runtime/src/test/teeracle_tests.rs +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use codec::alloc::string::ToString; -use ita_oracle::{ - create_coin_gecko_oracle, create_coin_market_cap_oracle, - oracles::exchange_rate_oracle::GetExchangeRate, types::TradingPair, -}; -use itp_test::mock::metrics_ocall_mock::MetricsOCallMock; -use std::sync::Arc; - -pub(super) fn test_verify_get_exchange_rate_from_coin_gecko_works() { - // Get the exchange rate - let trading_pair = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; - - let coin_gecko_oracle = create_coin_gecko_oracle(Arc::new(MetricsOCallMock::default())); - - let result = coin_gecko_oracle.get_exchange_rate(trading_pair.clone()); - assert!(result.is_ok()); -} - -/// Get exchange rate from coin market cap. Requires API key (therefore not suited for unit testing). -#[allow(unused)] -pub(super) fn test_verify_get_exchange_rate_from_coin_market_cap_works() { - // Get the exchange rate - let trading_pair = - TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; - - let coin_market_cap_oracle = - create_coin_market_cap_oracle(Arc::new(MetricsOCallMock::default())); - - let result = coin_market_cap_oracle.get_exchange_rate(trading_pair.clone()); - assert!(result.is_ok()); -} diff --git a/tee-worker/enclave-runtime/src/test/tests_main.rs b/tee-worker/enclave-runtime/src/test/tests_main.rs index 64416fb0dd..1cedf32c1f 100644 --- a/tee-worker/enclave-runtime/src/test/tests_main.rs +++ b/tee-worker/enclave-runtime/src/test/tests_main.rs @@ -143,7 +143,8 @@ pub extern "C" fn test_main_entrance() -> size_t { sidechain_aura_tests::produce_sidechain_block_and_import_it, sidechain_event_tests::ensure_events_get_reset_upon_block_proposal, top_pool_tests::process_indirect_call_in_top_pool, - top_pool_tests::submit_shielding_call_to_top_pool, + // TODO: Litentry disables it for now (P-494) + // top_pool_tests::submit_shielding_call_to_top_pool, // tls_ra unit tests tls_ra::seal_handler::test::seal_shielding_key_works, tls_ra::seal_handler::test::seal_shielding_key_fails_for_invalid_key, @@ -171,23 +172,9 @@ pub extern "C" fn test_main_entrance() -> size_t { // ipfs::test_verification_ok_for_correct_content, // ipfs::test_verification_fails_for_incorrect_content, // test_ocall_read_write_ipfs, - - // Teeracle tests - run_teeracle_tests, ) } -#[cfg(feature = "teeracle")] -fn run_teeracle_tests() { - use super::teeracle_tests::*; - test_verify_get_exchange_rate_from_coin_gecko_works(); - // Disabled - requires API key, cannot run locally - //test_verify_get_exchange_rate_from_coin_market_cap_works(); -} - -#[cfg(not(feature = "teeracle"))] -fn run_teeracle_tests() {} - #[cfg(feature = "evm")] fn run_evm_tests() { evm_pallet_tests::test_evm_call(); diff --git a/tee-worker/enclave-runtime/src/test/top_pool_tests.rs b/tee-worker/enclave-runtime/src/test/top_pool_tests.rs index 22776fbd39..f7ecff84b7 100644 --- a/tee-worker/enclave-runtime/src/test/top_pool_tests.rs +++ b/tee-worker/enclave-runtime/src/test/top_pool_tests.rs @@ -48,7 +48,7 @@ use itp_node_api::{ }, metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}, }; -use itp_node_api_metadata::pallet_teerex::TeerexCallIndexes; +use itp_node_api_metadata::pallet_teebag::TeebagCallIndexes; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_sgx_crypto::ShieldingCryptoEncrypt; use itp_stf_executor::enclave_signer::StfEnclaveSigner; @@ -59,9 +59,7 @@ use itp_top_pool_author::{ top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}, traits::AuthorApi, }; -use itp_types::{ - parentchain::Address, AccountId, Block, RsaRequest, ShardIdentifier, ShieldFundsFn, H256, -}; +use itp_types::{parentchain::Address, Block, RsaRequest, ShardIdentifier, H256}; use jsonrpc_core::futures::executor; use litentry_primitives::Identity; use log::*; @@ -107,6 +105,10 @@ pub fn process_indirect_call_in_top_pool() { assert_eq!(1, top_pool_author.get_pending_trusted_calls(shard_id).len()); } +/* + +// TODO: use our trusted call for testing - see P-494 + pub fn submit_shielding_call_to_top_pool() { let _ = env_logger::builder().is_test(true).try_init(); @@ -159,7 +161,7 @@ pub fn submit_shielding_call_to_top_pool() { shielding_key_repo, enclave_signer, top_pool_author.clone(), node_meta_data_repository ); - let block_with_shielding_call = create_shielding_call_extrinsic(shard_id, &shielding_key); + let block_with_shielding_call = create_opaque_call_extrinsic(shard_id, &shielding_key); let _ = indirect_calls_executor .execute_indirect_calls_in_extrinsics(&block_with_shielding_call, &Vec::new()) @@ -171,6 +173,7 @@ pub fn submit_shielding_call_to_top_pool() { let trusted_call = trusted_operation.to_call().unwrap(); assert!(trusted_call.verify_signature(&mr_enclave.m, &shard_id)); } +*/ fn encrypted_indirect_call< AttestationApi: EnclaveAttestationOCallApi, @@ -194,11 +197,11 @@ fn encrypted_indirect_call< encrypt_trusted_operation(shielding_key, &trusted_operation) } -fn create_shielding_call_extrinsic( - shard: ShardIdentifier, - shielding_key: &ShieldingKey, +/* +fn create_opaque_call_extrinsic( + _shard: ShardIdentifier, + _shielding_key: &ShieldingKey, ) -> Block { - let target_account = shielding_key.encrypt(&AccountId::new([2u8; 32]).encode()).unwrap(); let test_signer = ed25519::Pair::from_seed(b"33345678901234567890123456789012"); let signature = test_signer.sign(&[0u8]); @@ -212,15 +215,10 @@ fn create_shielding_call_extrinsic( let dummy_node_metadata = NodeMetadataMock::new(); - let shield_funds_indexes = dummy_node_metadata.shield_funds_call_indexes().unwrap(); + let call_index = dummy_node_metadata.post_opaque_task_call_indexes().unwrap(); let opaque_extrinsic = OpaqueExtrinsic::from_bytes( - ParentchainUncheckedExtrinsic::::new_signed( - ( - shield_funds_indexes, - target_account, - ita_stf::test_genesis::SECOND_ENDOWED_ACC_FUNDS, - shard, - ), + ParentchainUncheckedExtrinsic::::new_signed( + (call_index, RsaRequest::default()), Address::Address32([1u8; 32]), MultiSignature::Ed25519(signature), default_extra_for_test.signed_extra(), @@ -234,3 +232,5 @@ fn create_shielding_call_extrinsic( .with_extrinsics(vec![opaque_extrinsic]) .build() } + +*/ diff --git a/tee-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs b/tee-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs index 33f72e9095..e5fbed0a09 100644 --- a/tee-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/tee-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -55,8 +55,7 @@ enum ProvisioningPayload { impl From for ProvisioningPayload { fn from(m: WorkerMode) -> Self { match m { - WorkerMode::OffChainWorker | WorkerMode::Teeracle => - ProvisioningPayload::ShieldingKeyAndLightClient, + WorkerMode::OffChainWorker => ProvisioningPayload::ShieldingKeyAndLightClient, WorkerMode::Sidechain => ProvisioningPayload::Everything, } } diff --git a/tee-worker/enclave-runtime/src/top_pool_execution.rs b/tee-worker/enclave-runtime/src/top_pool_execution.rs index e80611707b..3f45673f81 100644 --- a/tee-worker/enclave-runtime/src/top_pool_execution.rs +++ b/tee-worker/enclave-runtime/src/top_pool_execution.rs @@ -99,8 +99,8 @@ pub unsafe extern "C" fn execute_trusted_calls() -> sgx_status_t { fn execute_top_pool_trusted_calls_internal() -> Result<()> { let start_time = Instant::now(); - debug!("----------------------------------------"); - debug!("Start sidechain block production cycle"); + info!("----------------------------------------"); + info!("Start sidechain block production cycle"); // We acquire lock explicitly (variable binding), since '_' will drop the lock after the statement. // See https://medium.com/codechain/rust-underscore-does-not-bind-fec6a18115a8 diff --git a/tee-worker/litentry/core/assertion-build-v2/src/lib.rs b/tee-worker/litentry/core/assertion-build-v2/src/lib.rs index 4d4e798eac..ef5b56095d 100644 --- a/tee-worker/litentry/core/assertion-build-v2/src/lib.rs +++ b/tee-worker/litentry/core/assertion-build-v2/src/lib.rs @@ -41,4 +41,6 @@ use lc_assertion_build::{transpose_identity, Result}; use lc_service::DataProviderConfig; use log::*; +pub mod nft_holder; +pub mod platform_user; pub mod token_holding_amount; diff --git a/tee-worker/litentry/core/assertion-build-v2/src/nft_holder/mod.rs b/tee-worker/litentry/core/assertion-build-v2/src/nft_holder/mod.rs new file mode 100644 index 0000000000..bb4e1ed443 --- /dev/null +++ b/tee-worker/litentry/core/assertion-build-v2/src/nft_holder/mod.rs @@ -0,0 +1,296 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use lc_credentials_v2::{nft_holder::NFTHolderAssertionUpdate, Credential}; +use lc_service::web3_nft::nft_holder::has_nft; +use lc_stf_task_sender::AssertionBuildRequest; +use litentry_primitives::{Web3Network, Web3NftType}; +use log::debug; + +use crate::*; + +pub fn build( + req: &AssertionBuildRequest, + nft_type: Web3NftType, + data_provider_config: &DataProviderConfig, +) -> Result { + debug!("nft holder: {:?}", nft_type); + + let identities: Vec<(Web3Network, Vec)> = transpose_identity(&req.identities); + let addresses = identities + .into_iter() + .flat_map(|(network_type, addresses)| { + addresses.into_iter().map(move |address| (network_type, address)) + }) + .collect::>(); + + let result = has_nft(nft_type.clone(), addresses, data_provider_config).map_err(|e| { + Error::RequestVCFailed( + Assertion::NftHolder(nft_type.clone()), + ErrorDetail::DataProviderError(ErrorString::truncate_from( + format!("{e:?}").as_bytes().to_vec(), + )), + ) + }); + + match result { + Ok(has_nft) => match Credential::new(&req.who, &req.shard) { + Ok(mut credential_unsigned) => { + credential_unsigned.update_nft_holder_assertion(nft_type, has_nft); + Ok(credential_unsigned) + }, + Err(e) => { + error!("Generate unsigned credential failed {:?}", e); + Err(Error::RequestVCFailed(Assertion::NftHolder(nft_type), e.into_error_detail())) + }, + }, + Err(e) => Err(e), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use itp_stf_primitives::types::ShardIdentifier; + use itp_types::AccountId; + use lc_common::web3_nft::{NftAddress, NftName}; + use lc_credentials_v2::assertion_logic::{AssertionLogic, Op}; + use lc_mock_server::run; + use litentry_hex_utils::decode_hex; + use litentry_primitives::{Identity, IdentityNetworkTuple}; + + fn crate_assertion_build_request( + nft_type: Web3NftType, + identities: Vec, + ) -> AssertionBuildRequest { + AssertionBuildRequest { + shard: ShardIdentifier::default(), + signer: AccountId::from([0; 32]), + who: AccountId::from([0; 32]).into(), + assertion: Assertion::NftHolder(nft_type), + identities, + top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, + maybe_key: None, + should_create_id_graph: false, + req_ext_hash: Default::default(), + } + } + + fn create_token_assertion_logic(nft_type: Web3NftType) -> Box { + Box::new(AssertionLogic::Item { + src: "$nft".into(), + op: Op::Equal, + dst: nft_type.get_nft_name().into(), + }) + } + + fn create_werido_ghost_gang_assertion_logic() -> Box { + Box::new(AssertionLogic::Or { + items: vec![Box::new(AssertionLogic::And { + items: vec![ + Box::new(AssertionLogic::Item { + src: "$network".into(), + op: Op::Equal, + dst: "ethereum".into(), + }), + Box::new(AssertionLogic::Item { + src: "$address".into(), + op: Op::Equal, + dst: Web3NftType::WeirdoGhostGang + .get_nft_address(Web3Network::Ethereum) + .unwrap() + .into(), + }), + ], + })], + }) + } + + fn create_club3_sbt_assertion_logic() -> Box { + Box::new(AssertionLogic::Or { + items: vec![ + Box::new(AssertionLogic::And { + items: vec![ + Box::new(AssertionLogic::Item { + src: "$network".into(), + op: Op::Equal, + dst: "bsc".into(), + }), + Box::new(AssertionLogic::Item { + src: "$address".into(), + op: Op::Equal, + dst: Web3NftType::Club3Sbt + .get_nft_address(Web3Network::Bsc) + .unwrap() + .into(), + }), + ], + }), + Box::new(AssertionLogic::And { + items: vec![ + Box::new(AssertionLogic::Item { + src: "$network".into(), + op: Op::Equal, + dst: "polygon".into(), + }), + Box::new(AssertionLogic::Item { + src: "$address".into(), + op: Op::Equal, + dst: Web3NftType::Club3Sbt + .get_nft_address(Web3Network::Polygon) + .unwrap() + .into(), + }), + ], + }), + Box::new(AssertionLogic::And { + items: vec![ + Box::new(AssertionLogic::Item { + src: "$network".into(), + op: Op::Equal, + dst: "arbitrum".into(), + }), + Box::new(AssertionLogic::Item { + src: "$address".into(), + op: Op::Equal, + dst: Web3NftType::Club3Sbt + .get_nft_address(Web3Network::Arbitrum) + .unwrap() + .into(), + }), + ], + }), + ], + }) + } + + fn init() -> DataProviderConfig { + let _ = env_logger::builder().is_test(true).try_init(); + let url = run(0).unwrap(); + + let mut data_provider_config = DataProviderConfig::new().unwrap(); + + data_provider_config.set_nodereal_api_key("d416f55179dbd0e45b1a8ed030e3".into()); + data_provider_config.set_nodereal_api_chain_network_url(url.clone() + "/nodereal_jsonrpc/"); + data_provider_config.set_moralis_api_key("d416f55179dbd0e45b1a8ed030e3".into()); + data_provider_config.set_moralis_api_url(url.clone() + "/moralis/"); + data_provider_config + } + + #[test] + fn build_werido_ghost_gang_holder_works() { + let data_provider_config = init(); + let address = decode_hex("0x45cdb67696802b9d01ed156b883269dbdb9c6239".as_bytes().to_vec()) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + let identities: Vec = + vec![(Identity::Evm(address), vec![Web3Network::Ethereum])]; + + let req = crate_assertion_build_request(Web3NftType::WeirdoGhostGang, identities); + + match build(&req, Web3NftType::WeirdoGhostGang, &data_provider_config) { + Ok(credential) => { + log::info!("build WeirdoGhostGang holder done"); + assert_eq!( + *(credential.credential_subject.assertions.first().unwrap()), + AssertionLogic::And { + items: vec![ + create_token_assertion_logic(Web3NftType::WeirdoGhostGang), + create_werido_ghost_gang_assertion_logic(), + ] + } + ); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), true); + }, + Err(e) => { + panic!("build WeirdoGhostGang holder failed with error {:?}", e); + }, + } + } + + #[test] + fn build_club3_sbt_holder_works() { + let data_provider_config = init(); + let mut address = + decode_hex("0x49ad262c49c7aa708cc2df262ed53b64a17dd5ee".as_bytes().to_vec()) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + let mut identities: Vec = + vec![(Identity::Evm(address), vec![Web3Network::Bsc, Web3Network::Polygon])]; + + let mut req = crate_assertion_build_request(Web3NftType::Club3Sbt, identities); + match build(&req, Web3NftType::Club3Sbt, &data_provider_config) { + Ok(credential) => { + log::info!("build Club3Sbt holder done"); + assert_eq!( + *(credential.credential_subject.assertions.first().unwrap()), + AssertionLogic::And { + items: vec![ + create_token_assertion_logic(Web3NftType::Club3Sbt), + create_club3_sbt_assertion_logic(), + ] + } + ); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), true); + }, + Err(e) => { + panic!("build Club3Sbt holder failed with error {:?}", e); + }, + } + + address = decode_hex("0x45cdb67696802b9d01ed156b883269dbdb9c6239".as_bytes().to_vec()) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + identities = vec![( + Identity::Evm(address), + vec![Web3Network::Bsc, Web3Network::Polygon, Web3Network::Arbitrum], + )]; + + req = crate_assertion_build_request(Web3NftType::Club3Sbt, identities); + match build(&req, Web3NftType::Club3Sbt, &data_provider_config) { + Ok(credential) => { + log::info!("build Club3Sbt holder done"); + assert_eq!( + *(credential.credential_subject.assertions.first().unwrap()), + AssertionLogic::And { + items: vec![ + create_token_assertion_logic(Web3NftType::Club3Sbt), + create_club3_sbt_assertion_logic(), + ] + } + ); + assert_eq!(*(credential.credential_subject.values.first().unwrap()), false); + }, + Err(e) => { + panic!("build Club3Sbt holder failed with error {:?}", e); + }, + } + } +} diff --git a/tee-worker/litentry/core/assertion-build-v2/src/platform_user/mod.rs b/tee-worker/litentry/core/assertion-build-v2/src/platform_user/mod.rs new file mode 100644 index 0000000000..5c261f8f92 --- /dev/null +++ b/tee-worker/litentry/core/assertion-build-v2/src/platform_user/mod.rs @@ -0,0 +1,180 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use std::collections::HashSet; + +use lc_credentials_v2::{platform_user::PlatformUserAssertionUpdate, Credential}; +use lc_service::platform_user::is_user; +use lc_stf_task_sender::AssertionBuildRequest; +use litentry_primitives::{PlatformUserType, Web3Network}; +use log::debug; + +use crate::*; + +pub fn build( + req: &AssertionBuildRequest, + platform_user_type: PlatformUserType, + data_provider_config: &DataProviderConfig, +) -> Result { + debug!("platform user: {:?}", platform_user_type); + + let identities: Vec<(Web3Network, Vec)> = transpose_identity(&req.identities); + let addresses: Vec = identities + .into_iter() + .flat_map(|(_, addresses)| addresses.into_iter()) + .collect::>() + .into_iter() + .collect(); + + let result = + is_user(platform_user_type.clone(), addresses, data_provider_config).map_err(|e| { + Error::RequestVCFailed( + Assertion::PlatformUser(platform_user_type.clone()), + ErrorDetail::DataProviderError(ErrorString::truncate_from( + format!("{e:?}").as_bytes().to_vec(), + )), + ) + }); + + match result { + Ok(value) => match Credential::new(&req.who, &req.shard) { + Ok(mut credential_unsigned) => { + credential_unsigned.update_platform_user_assertion(platform_user_type, value); + Ok(credential_unsigned) + }, + Err(e) => { + error!("Generate unsigned credential failed {:?}", e); + Err(Error::RequestVCFailed( + Assertion::PlatformUser(platform_user_type), + e.into_error_detail(), + )) + }, + }, + Err(e) => Err(e), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use itp_stf_primitives::types::ShardIdentifier; + use itp_types::AccountId; + use lc_common::platform_user::PlatformName; + use lc_credentials_v2::assertion_logic::{AssertionLogic, Op}; + use lc_mock_server::run; + use litentry_hex_utils::decode_hex; + use litentry_primitives::{Identity, IdentityNetworkTuple}; + + fn init() -> DataProviderConfig { + let _ = env_logger::builder().is_test(true).try_init(); + let url = run(0).unwrap() + "/karat_dao/"; + + let mut config = DataProviderConfig::new().unwrap(); + config.set_karat_dao_api_url(url); + config + } + + fn crate_assertion_build_request( + platform_user_type: PlatformUserType, + identities: Vec, + ) -> AssertionBuildRequest { + AssertionBuildRequest { + shard: ShardIdentifier::default(), + signer: AccountId::from([0; 32]), + who: AccountId::from([0; 32]).into(), + assertion: Assertion::PlatformUser(platform_user_type), + identities, + top_hash: Default::default(), + parachain_block_number: 0u32, + sidechain_block_number: 0u32, + maybe_key: None, + should_create_id_graph: false, + req_ext_hash: Default::default(), + } + } + + fn build_and_assert_result( + identities: Vec, + platform_user_type: PlatformUserType, + assertion_value: bool, + data_provider_config: &DataProviderConfig, + ) { + let req = crate_assertion_build_request(PlatformUserType::KaratDaoUser, identities); + + match build(&req, platform_user_type.clone(), &data_provider_config) { + Ok(credential) => { + log::info!("build karat dao user done"); + assert_eq!( + *(credential.credential_subject.assertions.first().unwrap()), + AssertionLogic::And { + items: vec![Box::new(AssertionLogic::Item { + src: "$platform".into(), + op: Op::Equal, + dst: platform_user_type.get_platform_name().into() + })] + } + ); + assert_eq!( + *(credential.credential_subject.values.first().unwrap()), + assertion_value + ); + }, + Err(e) => { + panic!("build karat dao user failed with error {:?}", e); + }, + } + } + + #[test] + fn build_karat_dao_user_works() { + let data_provider_config = init(); + let mut address = + decode_hex("0x49ad262c49c7aa708cc2df262ed53b64a17dd5ee".as_bytes().to_vec()) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + let mut identities: Vec = + vec![(Identity::Evm(address), vec![Web3Network::Ethereum])]; + + build_and_assert_result( + identities, + PlatformUserType::KaratDaoUser, + true, + &data_provider_config, + ); + + address = decode_hex("0x75438d34c9125839c8b08d21b7f3167281659e7c".as_bytes().to_vec()) + .unwrap() + .as_slice() + .try_into() + .unwrap(); + identities = vec![(Identity::Evm(address), vec![Web3Network::Bsc, Web3Network::Ethereum])]; + + build_and_assert_result( + identities, + PlatformUserType::KaratDaoUser, + false, + &data_provider_config, + ); + } +} diff --git a/tee-worker/litentry/core/assertion-build-v2/src/token_holding_amount/mod.rs b/tee-worker/litentry/core/assertion-build-v2/src/token_holding_amount/mod.rs index 4973ce5ecf..50ca6477e1 100644 --- a/tee-worker/litentry/core/assertion-build-v2/src/token_holding_amount/mod.rs +++ b/tee-worker/litentry/core/assertion-build-v2/src/token_holding_amount/mod.rs @@ -38,8 +38,8 @@ pub fn build( let identities: Vec<(Web3Network, Vec)> = transpose_identity(&req.identities); let addresses = identities .into_iter() - .flat_map(|(newtwork_type, addresses)| { - addresses.into_iter().map(move |address| (newtwork_type, address)) + .flat_map(|(network_type, addresses)| { + addresses.into_iter().map(move |address| (network_type, address)) }) .collect::>(); @@ -287,7 +287,7 @@ mod tests { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap(); - let mut data_provider_config = DataProviderConfig::default(); + let mut data_provider_config = DataProviderConfig::new().unwrap(); data_provider_config.set_nodereal_api_key("d416f55179dbd0e45b1a8ed030e3".into()); data_provider_config.set_nodereal_api_chain_network_url(url.clone() + "/nodereal_jsonrpc/"); diff --git a/tee-worker/litentry/core/assertion-build/src/a14.rs b/tee-worker/litentry/core/assertion-build/src/a14.rs index bde9bef807..91de2a1a3c 100644 --- a/tee-worker/litentry/core/assertion-build/src/a14.rs +++ b/tee-worker/litentry/core/assertion-build/src/a14.rs @@ -28,11 +28,11 @@ use http::header::{AUTHORIZATION, CONNECTION}; use http_req::response::Headers; use itc_rest_client::{ error::Error as RestClientError, - http_client::{DefaultSend, HttpClient}, + http_client::{HttpClient, SendWithCertificateVerification}, rest_client::RestClient, RestPath, RestPost, }; -use lc_data_providers::{build_client, DataProviderConfig}; +use lc_data_providers::{build_client_with_cert, DataProviderConfig}; use serde::{Deserialize, Serialize}; const VC_A14_SUBJECT_DESCRIPTION: &str = @@ -67,7 +67,7 @@ pub struct A14Response { // TODO: merge it to new achainable API client once the migration is done pub struct A14Client { - client: RestClient>, + client: RestClient>, } impl A14Client { @@ -79,7 +79,7 @@ impl A14Client { data_provider_config.achainable_auth_key.clone().as_str(), ); let client = - build_client("https://label-production.graph.tdf-labs.io/v1/run/labels/a719e99c-1f9b-432e-8f1d-cb3de0f14dde", headers); + build_client_with_cert("https://label-production.graph.tdf-labs.io/v1/run/labels/a719e99c-1f9b-432e-8f1d-cb3de0f14dde", headers); A14Client { client } } diff --git a/tee-worker/litentry/core/assertion-build/src/a2.rs b/tee-worker/litentry/core/assertion-build/src/a2.rs index 191777cb49..b351f1aea1 100644 --- a/tee-worker/litentry/core/assertion-build/src/a2.rs +++ b/tee-worker/litentry/core/assertion-build/src/a2.rs @@ -25,7 +25,7 @@ use lc_data_providers::{ discord_litentry::DiscordLitentryClient, vec_to_string, DataProviderConfig, }; -const VC_A2_SUBJECT_DESCRIPTION: &str = "The user is a member of Litentry Discord. +const VC_A2_SUBJECT_DESCRIPTION: &str = "The user is a member of Litentry Discord. Server link: https://discord.gg/phBSa3eMX9 Guild ID: 807161594245152800."; const VC_A2_SUBJECT_TYPE: &str = "Litentry Discord Member"; @@ -44,7 +44,8 @@ pub fn build( Error::RequestVCFailed(Assertion::A2(guild_id.clone()), ErrorDetail::ParseError) })?; - let mut client = DiscordLitentryClient::new(&data_provider_config.discord_litentry_url); + let mut client = + DiscordLitentryClient::new(&data_provider_config.litentry_discord_microservice_url); for identity in &req.identities { if let Identity::Discord(address) = &identity.0 { discord_cnt += 1; @@ -93,8 +94,9 @@ mod tests { #[test] fn build_a2_works() { - let mut data_provider_config = DataProviderConfig::new(); - data_provider_config.set_discord_litentry_url("http://localhost:19527".to_string()); + let mut data_provider_config = DataProviderConfig::new().unwrap(); + data_provider_config + .set_litentry_discord_microservice_url("http://localhost:19527".to_string()); let guild_id_u: u64 = 919848390156767232; let guild_id_vec: Vec = format!("{}", guild_id_u).as_bytes().to_vec(); diff --git a/tee-worker/litentry/core/assertion-build/src/a20.rs b/tee-worker/litentry/core/assertion-build/src/a20.rs index 40fa7e72b5..822bcebabb 100644 --- a/tee-worker/litentry/core/assertion-build/src/a20.rs +++ b/tee-worker/litentry/core/assertion-build/src/a20.rs @@ -23,7 +23,7 @@ extern crate sgx_tstd as std; use http::header::CONNECTION; use http_req::response::Headers; use itc_rest_client::{error::Error as RestClientError, RestGet, RestPath}; -use lc_data_providers::build_client; +use lc_data_providers::{build_client_with_cert, DataProviderConfig}; use serde::{Deserialize, Serialize}; #[cfg(all(not(feature = "std"), feature = "sgx"))] @@ -42,12 +42,15 @@ pub struct EarlyBirdResponse { has_joined: bool, } impl RestPath for EarlyBirdResponse { - fn get_path(path: String) -> core::result::Result { - Ok(path) + fn get_path(_path: String) -> core::result::Result { + Ok("events/does-user-joined-evm-campaign".to_string()) } } -pub fn build(req: &AssertionBuildRequest) -> Result { +pub fn build( + req: &AssertionBuildRequest, + data_provider_config: &DataProviderConfig, +) -> Result { // Note: it's not perfectly implemented here // it only attests if the main address meets the criteria, but we should have implemented // the supported web3networks and attested the linked identities. @@ -62,10 +65,7 @@ pub fn build(req: &AssertionBuildRequest) -> Result { let mut headers = Headers::new(); headers.insert(CONNECTION.as_str(), "close"); - let mut client = build_client( - "https://archive-test.litentry.io/events/does-user-joined-evm-campaign", - headers, - ); + let mut client = build_client_with_cert(&data_provider_config.litentry_archive_url, headers); let query = vec![("account", who.as_str())]; let value = client .get_with::("".to_string(), query.as_slice()) diff --git a/tee-worker/litentry/core/assertion-build/src/a3.rs b/tee-worker/litentry/core/assertion-build/src/a3.rs index 9e43923fba..c0dc6f5a5d 100644 --- a/tee-worker/litentry/core/assertion-build/src/a3.rs +++ b/tee-worker/litentry/core/assertion-build/src/a3.rs @@ -59,7 +59,8 @@ pub fn build( ) })?; - let mut client = DiscordLitentryClient::new(&data_provider_config.discord_litentry_url); + let mut client = + DiscordLitentryClient::new(&data_provider_config.litentry_discord_microservice_url); for identity in &req.identities { if let Identity::Discord(address) = &identity.0 { let resp = client @@ -116,8 +117,9 @@ mod tests { #[test] fn build_a3_works() { - let mut data_provider_config = DataProviderConfig::new(); - data_provider_config.set_discord_litentry_url("http://localhost:19527".to_string()); + let mut data_provider_config = DataProviderConfig::new().unwrap(); + data_provider_config + .set_litentry_discord_microservice_url("http://localhost:19527".to_string()); let guild_id_u: u64 = 919848390156767232; let channel_id_u: u64 = 919848392035794945; let role_id_u: u64 = 1034083718425493544; diff --git a/tee-worker/litentry/core/assertion-build/src/achainable/amount.rs b/tee-worker/litentry/core/assertion-build/src/achainable/amount.rs index af9245bb9d..d1a75b3169 100644 --- a/tee-worker/litentry/core/assertion-build/src/achainable/amount.rs +++ b/tee-worker/litentry/core/assertion-build/src/achainable/amount.rs @@ -140,8 +140,10 @@ pub fn build_amount( if bname == AchainableNameAmount::BalanceUnderAmount { credential_unsigned.update_eth_holding_amount(balance); } else { - let (desc, subtype, content) = - get_assertion_content(&achainable_param.to_string(¶m.name)?, ¶m.chain); + let (desc, subtype, content) = get_assertion_content( + &achainable_param.to_string(¶m.name)?, + ¶m.chain[0], + ); credential_unsigned.add_subject_info(desc, subtype); credential_unsigned.update_content(flag, content); } diff --git a/tee-worker/litentry/core/assertion-build/src/generic_discord_role.rs b/tee-worker/litentry/core/assertion-build/src/generic_discord_role.rs index cadb2ef9e2..9f82b9ba19 100644 --- a/tee-worker/litentry/core/assertion-build/src/generic_discord_role.rs +++ b/tee-worker/litentry/core/assertion-build/src/generic_discord_role.rs @@ -38,7 +38,8 @@ pub fn build( })?; let mut has_role_value = false; - let mut client = DiscordLitentryClient::new(&data_provider_config.discord_litentry_url); + let mut client = + DiscordLitentryClient::new(&data_provider_config.litentry_discord_microservice_url); for identity in &req.identities { if let Identity::Discord(address) = &identity.0 { let resp = @@ -108,9 +109,9 @@ mod tests { fn init() -> DataProviderConfig { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap(); - let mut data_provider_conifg = DataProviderConfig::new(); + let mut data_provider_conifg = DataProviderConfig::new().unwrap(); - data_provider_conifg.set_discord_litentry_url(url); + data_provider_conifg.set_litentry_discord_microservice_url(url); data_provider_conifg.set_contest_legend_discord_role_id("1034083718425493544".to_string()); data_provider_conifg.set_sora_quiz_attendee_id("1034083718425493544".to_string()); data_provider_conifg diff --git a/tee-worker/litentry/core/assertion-build/src/holding_time.rs b/tee-worker/litentry/core/assertion-build/src/holding_time.rs index a6744d6eb0..c46fceafa4 100644 --- a/tee-worker/litentry/core/assertion-build/src/holding_time.rs +++ b/tee-worker/litentry/core/assertion-build/src/holding_time.rs @@ -345,7 +345,7 @@ mod tests { fn init() -> DataProviderConfig { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap(); - let mut data_provider_config = DataProviderConfig::new(); + let mut data_provider_config = DataProviderConfig::new().unwrap(); data_provider_config.set_achainable_url(url); data_provider_config } diff --git a/tee-worker/litentry/core/assertion-build/src/lib.rs b/tee-worker/litentry/core/assertion-build/src/lib.rs index 6f2f1a124b..bf093be0a1 100644 --- a/tee-worker/litentry/core/assertion-build/src/lib.rs +++ b/tee-worker/litentry/core/assertion-build/src/lib.rs @@ -179,7 +179,9 @@ fn pubkey_to_address(network: &Web3Network, pubkey: &str) -> String { | Web3Network::Khala | Web3Network::SubstrateTestnet | Web3Network::Ethereum - | Web3Network::Bsc => "".to_string(), + | Web3Network::Bsc + | Web3Network::Polygon + | Web3Network::Arbitrum => "".to_string(), } } diff --git a/tee-worker/litentry/core/assertion-build/src/lit_staking.rs b/tee-worker/litentry/core/assertion-build/src/lit_staking.rs index c24ef05256..2b1c1c5670 100644 --- a/tee-worker/litentry/core/assertion-build/src/lit_staking.rs +++ b/tee-worker/litentry/core/assertion-build/src/lit_staking.rs @@ -20,14 +20,14 @@ use frame_support::{StorageHasher, Twox64Concat}; use http::header::CONNECTION; use itc_rest_client::{ error::Error as RestClientError, - http_client::{DefaultSend, HttpClient}, + http_client::{HttpClient, SendWithCertificateVerification}, rest_client::{Headers, RestClient}, RestPath, RestPost, }; use itp_stf_primitives::types::AccountId; use itp_utils::hex_display::AsBytesRef; use lc_credentials::litentry_profile::lit_staking::UpdateLITStakingAmountCredential; -use lc_data_providers::build_client; +use lc_data_providers::build_client_with_cert; use litentry_primitives::ParentchainBalance; use pallet_parachain_staking::types::Delegator; use serde::{Deserialize, Serialize}; @@ -70,7 +70,7 @@ pub struct JsonRPCResponse { } pub struct LitentryStakingClient { - client: RestClient>, + client: RestClient>, } impl Default for LitentryStakingClient { @@ -83,7 +83,7 @@ impl LitentryStakingClient { pub fn new() -> Self { let mut headers = Headers::new(); headers.insert(CONNECTION.as_str(), "close"); - let client = build_client("https://litentry-rpc.dwellir.com:443", headers); + let client = build_client_with_cert("https://litentry-rpc.dwellir.com:443", headers); LitentryStakingClient { client } } diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs index 70715e0770..a547680733 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/amount_holding/evm_amount_holding.rs @@ -55,13 +55,13 @@ fn get_holding_balance( block_number: "latest".into(), }; match address.0 { - Web3Network::Bsc => match bsc_client.get_token_balance_20(¶m) { + Web3Network::Bsc => match bsc_client.get_token_balance_20(¶m, false) { Ok(balance) => { total_balance += balance; }, Err(err) => return Err(err), }, - Web3Network::Ethereum => match eth_client.get_token_balance_20(¶m) { + Web3Network::Ethereum => match eth_client.get_token_balance_20(¶m, false) { Ok(balance) => { total_balance += balance; }, @@ -169,7 +169,7 @@ mod tests { fn init() -> DataProviderConfig { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap() + "/nodereal_jsonrpc/"; - let mut data_provider_config = DataProviderConfig::default(); + let mut data_provider_config = DataProviderConfig::new().unwrap(); data_provider_config.set_nodereal_api_key("d416f55179dbd0e45b1a8ed030e3".into()); data_provider_config.set_nodereal_api_chain_network_url(url); diff --git a/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs b/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs index b06474ca12..df358ef0a6 100644 --- a/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs +++ b/tee-worker/litentry/core/assertion-build/src/nodereal/nft_holder/weirdo_ghost_gang_holder.rs @@ -42,7 +42,7 @@ fn check_has_nft( block_number: "latest".into(), }; - match client.get_token_balance_721(¶m) { + match client.get_token_balance_721(¶m, false) { Ok(res) => { debug!("Get token balance 721 response: {:?}", res); Ok(res > 0) @@ -120,7 +120,7 @@ mod tests { fn init() -> DataProviderConfig { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap() + "/nodereal_jsonrpc/"; - let mut config = DataProviderConfig::new(); + let mut config = DataProviderConfig::new().unwrap(); config.set_nodereal_api_key("d416f55179dbd0e45b1a8ed030e3".to_string()); config.set_nodereal_api_chain_network_url(url); diff --git a/tee-worker/litentry/core/assertion-build/src/oneblock/course.rs b/tee-worker/litentry/core/assertion-build/src/oneblock/course.rs index 42da6bd72a..e913f7689e 100644 --- a/tee-worker/litentry/core/assertion-build/src/oneblock/course.rs +++ b/tee-worker/litentry/core/assertion-build/src/oneblock/course.rs @@ -43,7 +43,7 @@ pub fn build( }, Err(e) => { error!("Generate unsigned credential failed {:?}", e); - Err(Error::RequestVCFailed(Assertion::Oneblock(course_type), e.into_error_detail())) + Err(Error::RequestVCFailed(Assertion::OneBlock(course_type), e.into_error_detail())) }, } } diff --git a/tee-worker/litentry/core/assertion-build/src/oneblock/mod.rs b/tee-worker/litentry/core/assertion-build/src/oneblock/mod.rs index 545e21ebfe..24e514cb28 100644 --- a/tee-worker/litentry/core/assertion-build/src/oneblock/mod.rs +++ b/tee-worker/litentry/core/assertion-build/src/oneblock/mod.rs @@ -26,7 +26,7 @@ use crate::*; use http::header::{AUTHORIZATION, CONNECTION}; use http_req::response::Headers; use itc_rest_client::{error::Error as RestClientError, RestGet, RestPath}; -use lc_data_providers::{build_client, DataProviderConfig}; +use lc_data_providers::{build_client_with_cert, DataProviderConfig}; use serde::{Deserialize, Serialize}; use std::string::ToString; @@ -55,11 +55,11 @@ fn fetch_data_from_notion( headers.insert("Notion-Version", "2022-06-28"); headers.insert(AUTHORIZATION.as_str(), oneblock_notion_key.as_str()); - let mut client = build_client(oneblock_notion_url.as_str(), headers); + let mut client = build_client_with_cert(oneblock_notion_url.as_str(), headers); client.get::(String::default()).map_err(|e| { Error::RequestVCFailed( - Assertion::Oneblock(course_type.clone()), + Assertion::OneBlock(course_type.clone()), ErrorDetail::DataProviderError(ErrorString::truncate_from( format!("{e:?}").as_bytes().to_vec(), )), diff --git a/tee-worker/litentry/core/common/src/lib.rs b/tee-worker/litentry/core/common/src/lib.rs index bb84990a23..655f1de648 100644 --- a/tee-worker/litentry/core/common/src/lib.rs +++ b/tee-worker/litentry/core/common/src/lib.rs @@ -24,6 +24,8 @@ extern crate sgx_tstd as std; use litentry_primitives::Web3Network; +pub mod platform_user; +pub mod web3_nft; pub mod web3_token; pub fn web3_network_to_chain(network: &Web3Network) -> &'static str { @@ -42,5 +44,7 @@ pub fn web3_network_to_chain(network: &Web3Network) -> &'static str { Web3Network::BitcoinP2sh => "bitcoin_p2sh", Web3Network::BitcoinP2wpkh => "bitcoin_p2wpkh", Web3Network::BitcoinP2wsh => "bitcoin_p2wsh", + Web3Network::Polygon => "polygon", + Web3Network::Arbitrum => "arbitrum", } } diff --git a/tee-worker/litentry/core/common/src/platform_user/mod.rs b/tee-worker/litentry/core/common/src/platform_user/mod.rs new file mode 100644 index 0000000000..8cb8b9c21a --- /dev/null +++ b/tee-worker/litentry/core/common/src/platform_user/mod.rs @@ -0,0 +1,35 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use litentry_primitives::PlatformUserType; + +pub trait PlatformName { + fn get_platform_name(&self) -> &'static str; +} + +impl PlatformName for PlatformUserType { + fn get_platform_name(&self) -> &'static str { + match self { + Self::KaratDaoUser => "KaratDao", + } + } +} diff --git a/tee-worker/litentry/core/common/src/web3_nft/mod.rs b/tee-worker/litentry/core/common/src/web3_nft/mod.rs new file mode 100644 index 0000000000..3d48ae84e4 --- /dev/null +++ b/tee-worker/litentry/core/common/src/web3_nft/mod.rs @@ -0,0 +1,60 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use litentry_primitives::Web3NftType; + +use crate::Web3Network; + +pub trait NftName { + fn get_nft_name(&self) -> &'static str; +} + +impl NftName for Web3NftType { + fn get_nft_name(&self) -> &'static str { + match self { + Self::WeirdoGhostGang => "Weirdo Ghost Gang", + Self::Club3Sbt => "Club3 SBT", + } + } +} + +pub trait NftAddress { + fn get_nft_address(&self, network: Web3Network) -> Option<&'static str>; +} + +impl NftAddress for Web3NftType { + fn get_nft_address(&self, network: Web3Network) -> Option<&'static str> { + match (self, network) { + // WeirdoGhostGang + (Self::WeirdoGhostGang, Web3Network::Ethereum) => + Some("0x9401518f4EBBA857BAA879D9f76E1Cc8b31ed197"), + // Club3Sbt + (Self::Club3Sbt, Web3Network::Bsc) => + Some("0x9f488C0dafb1B3bFeeD3e886e0E6E5f3f4517925"), + (Self::Club3Sbt, Web3Network::Polygon) => + Some("0xAc2e4e67cffa5E82bfA1e169e5F9aa405114C982"), + (Self::Club3Sbt, Web3Network::Arbitrum) => + Some("0xcccFF19FB8a4a2A206d07842b8F8c8c0A11904C2"), + _ => None, + } + } +} diff --git a/tee-worker/litentry/core/credentials-v2/src/lib.rs b/tee-worker/litentry/core/credentials-v2/src/lib.rs index 4bdd90bb13..258a408f5e 100644 --- a/tee-worker/litentry/core/credentials-v2/src/lib.rs +++ b/tee-worker/litentry/core/credentials-v2/src/lib.rs @@ -36,4 +36,6 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam // TODO migration to v2 in the future pub use lc_credentials::{assertion_logic, Credential}; +pub mod nft_holder; +pub mod platform_user; pub mod token_holding_amount; diff --git a/tee-worker/litentry/core/credentials-v2/src/nft_holder/mod.rs b/tee-worker/litentry/core/credentials-v2/src/nft_holder/mod.rs new file mode 100644 index 0000000000..2cd754c6a8 --- /dev/null +++ b/tee-worker/litentry/core/credentials-v2/src/nft_holder/mod.rs @@ -0,0 +1,90 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use lc_common::{ + web3_network_to_chain, + web3_nft::{NftAddress, NftName}, +}; +use litentry_primitives::{Web3Network, Web3NftType}; + +// TODO migration to v2 in the future +use lc_credentials::{ + assertion_logic::{AssertionLogic, Op}, + Credential, +}; + +const TYPE: &str = "Generic NFT Holder"; +const DESCRIPTION: &str = "You are a holder of a certain kind of NFT"; + +struct AssertionKeys { + nft: &'static str, + network: &'static str, + address: &'static str, +} + +const ASSERTION_KEYS: AssertionKeys = + AssertionKeys { nft: "$nft", network: "$network", address: "$address" }; + +pub trait NFTHolderAssertionUpdate { + fn update_nft_holder_assertion(&mut self, nft_type: Web3NftType, has_nft: bool); +} + +impl NFTHolderAssertionUpdate for Credential { + fn update_nft_holder_assertion(&mut self, nft_type: Web3NftType, has_nft: bool) { + self.add_subject_info(DESCRIPTION, TYPE); + + let mut assertion = AssertionLogic::new_and(); + + assertion = assertion.add_item(AssertionLogic::new_item( + ASSERTION_KEYS.nft, + Op::Equal, + nft_type.get_nft_name(), + )); + + let mut network_assertion: AssertionLogic = AssertionLogic::new_or(); + for network in nft_type.get_supported_networks() { + network_assertion = network_assertion + .add_item(create_network_assertion_logic(network, nft_type.clone())); + } + + assertion = assertion.add_item(network_assertion); + self.credential_subject.assertions.push(assertion); + self.credential_subject.values.push(has_nft); + } +} + +fn create_network_assertion_logic(network: Web3Network, nft_type: Web3NftType) -> AssertionLogic { + let mut assertion = AssertionLogic::new_and(); + assertion = assertion.add_item(AssertionLogic::new_item( + ASSERTION_KEYS.network, + Op::Equal, + web3_network_to_chain(&network), + )); + if let Some(address) = nft_type.get_nft_address(network) { + assertion = assertion.add_item(AssertionLogic::new_item( + ASSERTION_KEYS.address, + Op::Equal, + address, + )); + } + assertion +} diff --git a/tee-worker/litentry/core/credentials-v2/src/platform_user/mod.rs b/tee-worker/litentry/core/credentials-v2/src/platform_user/mod.rs new file mode 100644 index 0000000000..82c1ea7a76 --- /dev/null +++ b/tee-worker/litentry/core/credentials-v2/src/platform_user/mod.rs @@ -0,0 +1,61 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use lc_common::platform_user::PlatformName; +use litentry_primitives::PlatformUserType; + +// TODO migration to v2 in the future +use lc_credentials::{ + assertion_logic::{AssertionLogic, Op}, + Credential, +}; + +const TYPE: &str = "Platform user"; +const DESCRIPTION: &str = "You are a user of a certain platform"; + +pub trait PlatformUserAssertionUpdate { + fn update_platform_user_assertion( + &mut self, + platform_user_type: PlatformUserType, + is_user: bool, + ); +} + +impl PlatformUserAssertionUpdate for Credential { + fn update_platform_user_assertion( + &mut self, + platform_user_type: PlatformUserType, + is_user: bool, + ) { + self.add_subject_info(DESCRIPTION, TYPE); + + let mut assertion = AssertionLogic::new_and(); + assertion = assertion.add_item(AssertionLogic::new_item( + "$platform", + Op::Equal, + platform_user_type.get_platform_name(), + )); + + self.credential_subject.assertions.push(assertion); + self.credential_subject.values.push(is_user); + } +} diff --git a/tee-worker/litentry/core/credentials-v2/src/token_holding_amount/mod.rs b/tee-worker/litentry/core/credentials-v2/src/token_holding_amount/mod.rs index b2d95dbe2a..2cd05e903f 100644 --- a/tee-worker/litentry/core/credentials-v2/src/token_holding_amount/mod.rs +++ b/tee-worker/litentry/core/credentials-v2/src/token_holding_amount/mod.rs @@ -75,9 +75,9 @@ fn update_assertion(token_type: Web3TokenType, balance: f64, credential: &mut Cr )); let mut network_assertion: AssertionLogic = AssertionLogic::new_or(); - for newtork in token_type.get_supported_networks() { + for network in token_type.get_supported_networks() { network_assertion = - network_assertion.add_item(create_network_assertion_logic(newtork, token_type.clone())); + network_assertion.add_item(create_network_assertion_logic(network, token_type.clone())); } assertion = assertion.add_item(network_assertion); diff --git a/tee-worker/litentry/core/credentials/src/achainable/bab_holder.rs b/tee-worker/litentry/core/credentials/src/achainable/bab_holder.rs index 997d7bfa23..510ea0a1e0 100644 --- a/tee-worker/litentry/core/credentials/src/achainable/bab_holder.rs +++ b/tee-worker/litentry/core/credentials/src/achainable/bab_holder.rs @@ -21,7 +21,7 @@ use crate::{ const BAB_HOLDER_DESCRIPTIONS: &str = "You are a holder of a certain kind of NFT"; const BAB_HOLDER_TYPE: &str = "NFT Holder"; -const BAB_HOLDER_BREAKDOWN: &str = "is_bab_holder"; +const BAB_HOLDER_BREAKDOWN: &str = "$is_bab_holder"; pub trait UpdateBABHolder { fn update_bab_holder(&mut self, is_bab_holder: bool); diff --git a/tee-worker/litentry/core/credentials/src/achainable/lit_holding_amount.rs b/tee-worker/litentry/core/credentials/src/achainable/lit_holding_amount.rs index c311641c9c..18b5f23b2f 100644 --- a/tee-worker/litentry/core/credentials/src/achainable/lit_holding_amount.rs +++ b/tee-worker/litentry/core/credentials/src/achainable/lit_holding_amount.rs @@ -22,7 +22,7 @@ use std::vec::Vec; // Type / Info const LIT_HOLDING_AMOUNT_INFO: (&str, &str) = ("Token holding amount", "The amount of a particular token you are holding"); -const LIT_HOLDING_AMOUNT_BREAKDOWN: &str = "lit_holding_amount"; +const LIT_HOLDING_AMOUNT_BREAKDOWN: &str = "$lit_holding_amount"; const LIT_BALANCE_RANGE: [usize; 10] = [0, 1, 50, 100, 200, 500, 800, 1200, 1600, 3000]; pub struct LitHoldingAmount { diff --git a/tee-worker/litentry/core/credentials/src/achainable/uniswap_user.rs b/tee-worker/litentry/core/credentials/src/achainable/uniswap_user.rs index c34ef97db0..590c3e5a4e 100644 --- a/tee-worker/litentry/core/credentials/src/achainable/uniswap_user.rs +++ b/tee-worker/litentry/core/credentials/src/achainable/uniswap_user.rs @@ -21,8 +21,8 @@ use crate::{ use std::string::ToString; const UNISWAP_USER_DESCRIPTIONS: &str = - "You are a trader or liquidity provider of Uniswap V2 or V3. -Uniswap V2 Factory Contract: 0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f. + "You are a trader or liquidity provider of Uniswap V2 or V3. +Uniswap V2 Factory Contract: 0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f. Uniswap V3 Factory Contract: 0x1f98431c8ad98523631ae4a59f267346ea31f984."; const UNISWAP_USER_TYPE: &str = "Uniswap V2/V3 User"; diff --git a/tee-worker/litentry/core/credentials/src/credential_schema.rs b/tee-worker/litentry/core/credentials/src/credential_schema.rs new file mode 100644 index 0000000000..edac8f692e --- /dev/null +++ b/tee-worker/litentry/core/credentials/src/credential_schema.rs @@ -0,0 +1,109 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use litentry_primitives::{AchainableParams, Assertion}; +use std::string::{String, ToString}; + +const BASE_URL: &str = "https://raw.githubusercontent.com/litentry/vc-jsonschema/main/dist/schemas"; +const NOT_IMPLEMENTED: &str = + "https://raw.githubusercontent.com/litentry/vc-jsonschema/main/dist/schemas/0-base.json"; + +/// Returns the respective JSON Schema for the given assertion and its credential. +/// JSON Schemas can be found at https://github.com/litentry/vc-jsonschema +pub fn get_schema_url(assertion: &Assertion) -> String { + match assertion { + Assertion::A1 => format!("{BASE_URL}/1-basic-identity-verification/1-0-0.json"), + + Assertion::A2(_) => format!("{BASE_URL}/2-litentry-discord-member/1-0-0.json"), + + Assertion::A3(_, _, _) => format!("{BASE_URL}/3-active-discord-id-hubber/1-0-0.json"), + + Assertion::A4(_) => format!("{BASE_URL}/4-token-holding-time/1-0-0.json"), + + Assertion::A6 => format!("{BASE_URL}/6-twitter-follower-amount/1-0-0.json"), + + Assertion::A7(_) => format!("{BASE_URL}/4-token-holding-time/1-0-0.json"), + + Assertion::A8(_) => format!("{BASE_URL}/7-evm-substrate-transaction-count/1-0-0.json"), + + Assertion::A10(_) => format!("{BASE_URL}/4-token-holding-time/1-0-0.json"), + + Assertion::A11(_) => format!("{BASE_URL}/4-token-holding-time/1-0-0.json"), + + Assertion::A13(_) => format!("{BASE_URL}/8-decoded-2023-basic-special-badge/1-0-0.json"), + + Assertion::A14 => + format!("{BASE_URL}/9-polkadot-governance-participation-proof/1-0-0.json"), + + Assertion::Achainable(params) => match params { + AchainableParams::AmountHolding(_) => + format!("{BASE_URL}/17-token-holding-amount/1-0-0.json"), + + AchainableParams::AmountToken(_) => + format!("{BASE_URL}/17-token-holding-amount/1-0-0.json"), + + AchainableParams::Amount(_) => format!("{BASE_URL}/11-token-holder/1-0-0.json"), + + AchainableParams::Basic(_) => format!("{BASE_URL}/11-token-holder/1-0-0.json"), + + AchainableParams::ClassOfYear(_) => + format!("{BASE_URL}/10-account-class-of-year/1-0-0.json"), + + AchainableParams::Mirror(_) => format!("{BASE_URL}/22-mirror-contributor/1-0-0.json"), + + // The following assertions are Unused and produce no specific claims. They Generates + // generic JSON Credentials + AchainableParams::Amounts(_) => NOT_IMPLEMENTED.to_string(), + AchainableParams::BetweenPercents(_) => NOT_IMPLEMENTED.to_string(), + AchainableParams::Date(_) => NOT_IMPLEMENTED.to_string(), + AchainableParams::DateInterval(_) => NOT_IMPLEMENTED.to_string(), + AchainableParams::DatePercent(_) => NOT_IMPLEMENTED.to_string(), + AchainableParams::Token(_) => NOT_IMPLEMENTED.to_string(), + }, + + Assertion::A20 => format!("{BASE_URL}/12-idhub-evm-version-early-bird/1-0-0.json"), + + Assertion::OneBlock(_) => format!("{BASE_URL}/13-oneblock-student-phase-12/1-0-0.json"), + + Assertion::GenericDiscordRole(_) => + format!("{BASE_URL}/14-generic-discord-role/1-0-0.json"), + + Assertion::BnbDomainHolding => + format!("{BASE_URL}/15-bnb-domain-holding-amount/1-0-0.json"), + + Assertion::BnbDigitDomainClub(_) => + format!("{BASE_URL}/16-bnb-3d-4d-club-domain-holding-amount/1-0-0.json"), + + Assertion::VIP3MembershipCard(_) => format!("{BASE_URL}/19-vip3-card-holder/1-0-0.json"), + + Assertion::WeirdoGhostGangHolder => + format!("{BASE_URL}/18-weirdoghostgang-holder/1-0-0.json"), + + Assertion::LITStaking => format!("{BASE_URL}/17-token-holding-amount/1-0-0.json"), + + Assertion::TokenHoldingAmount(_) | Assertion::EVMAmountHolding(_) => + format!("{BASE_URL}/21-evm-holding-amount/1-0-0.json"), + + Assertion::BRC20AmountHolder => + format!("{BASE_URL}/20-token-holding-amount-list/1-0-0.json"), + + Assertion::CryptoSummary => format!("{BASE_URL}/23-crypto-summary/1-0-0.json"), + + Assertion::PlatformUser(_) => format!("{BASE_URL}/24-platform-user/1-0-0.json"), + + Assertion::NftHolder(_) => format!("{BASE_URL}/26-nft-holder/1-0-0.json"), + } +} diff --git a/tee-worker/litentry/core/credentials/src/lib.rs b/tee-worker/litentry/core/credentials/src/lib.rs index b35050ff72..d28b66c9b3 100644 --- a/tee-worker/litentry/core/credentials/src/lib.rs +++ b/tee-worker/litentry/core/credentials/src/lib.rs @@ -82,6 +82,7 @@ pub mod oneblock; pub mod schema; use assertion_logic::{AssertionLogic, Op}; pub mod brc20; +pub mod credential_schema; pub mod generic_discord_role; pub mod nodereal; pub mod vip3; @@ -166,9 +167,9 @@ impl CredentialSubject { #[derive(Serialize, Deserialize, Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo)] #[serde(rename_all = "camelCase")] pub struct CredentialSchema { - /// Schema ID that is maintained by Parentchain VCMP + /// Schema ID that is maintained in https://github.com/litentry/vc-jsonschema pub id: String, - /// The schema type, generally it is + /// The schema type, generally it is JSON Schema Draft 7 (JSONSchema7/JSONSchema2018) #[serde(rename = "type")] pub types: String, } @@ -227,9 +228,8 @@ pub struct Credential { /// Digital proof with the signature of Issuer #[serde(skip_serializing_if = "Option::is_none")] pub proof: Option, - #[serde(skip_deserializing)] - #[serde(skip_serializing_if = "Option::is_none")] - pub credential_schema: Option, + /// The JSON Schema information the credential follows + pub credential_schema: CredentialSchema, } impl Credential { @@ -253,7 +253,6 @@ impl Credential { vc.credential_subject.id = subject.to_did().map_err(|err| Error::ParseError(err.to_string()))?; vc.issuance_date = now_as_iso8601(); - vc.credential_schema = None; vc.proof = None; vc.generate_id(); diff --git a/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/mod.rs b/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/mod.rs index 1c587c060a..f39ca0a98b 100644 --- a/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/mod.rs +++ b/tee-worker/litentry/core/credentials/src/nodereal/crypto_summary/mod.rs @@ -243,7 +243,7 @@ impl CryptoSummaryClient { for address in addresses { let res = self .bsc_client - .get_token_holdings(address) + .get_token_holdings(address, false) .map_err(|e| e.into_error_detail())?; let result: ResponseTokenResult = @@ -272,7 +272,7 @@ impl CryptoSummaryClient { // Total txs on BSC let tx = self .bsc_client - .get_transaction_count(address) + .get_transaction_count(address, false) .map_err(|e| e.into_error_detail())?; total_txs += tx; } @@ -283,7 +283,7 @@ impl CryptoSummaryClient { // Query Token let res_token = self .eth_client - .get_token_holdings(address) + .get_token_holdings(address, false) .map_err(|e| e.into_error_detail())?; let result: ResponseTokenResult = serde_json::from_value(res_token.result) .map_err(|_| ErrorDetail::ParseError)?; @@ -319,7 +319,7 @@ impl CryptoSummaryClient { let res_nft = self .eth_client - .get_nft_holdings(¶m) + .get_nft_holdings(¶m, false) .map_err(|e| e.into_error_detail())?; let details = res_nft.details; @@ -338,7 +338,7 @@ impl CryptoSummaryClient { // Total txs on Ethereum let tx = self .eth_client - .get_transaction_count(address) + .get_transaction_count(address, false) .map_err(|e| e.into_error_detail())?; total_txs += tx; } diff --git a/tee-worker/litentry/core/credentials/src/templates/credential.json b/tee-worker/litentry/core/credentials/src/templates/credential.json index c26af00bf1..effeba0b14 100644 --- a/tee-worker/litentry/core/credentials/src/templates/credential.json +++ b/tee-worker/litentry/core/credentials/src/templates/credential.json @@ -37,7 +37,7 @@ "verificationMethod":"" }, "credentialSchema":{ - "id":"http://apps.litentry.com/credential/schemas/2023", + "id":"https://github.com/litentry/vc-jsonschema/", "type":"JsonSchemaValidator2018" } -} \ No newline at end of file +} diff --git a/tee-worker/litentry/core/data-providers/src/achainable.rs b/tee-worker/litentry/core/data-providers/src/achainable.rs index 16636ca8b5..733b2261c7 100644 --- a/tee-worker/litentry/core/data-providers/src/achainable.rs +++ b/tee-worker/litentry/core/data-providers/src/achainable.rs @@ -184,6 +184,8 @@ pub fn web3_network_to_chain(network: &Web3Network) -> String { Web3Network::BitcoinP2sh => "bitcoin_p2sh".into(), Web3Network::BitcoinP2wpkh => "bitcoin_p2wpkh".into(), Web3Network::BitcoinP2wsh => "bitcoin_p2wsh".into(), + Web3Network::Polygon => "polygon".into(), + Web3Network::Arbitrum => "arbitrum".into(), } } @@ -235,7 +237,8 @@ impl TryFrom for Params { let token = if p.token.is_some() { Some(ap.to_string(&p.token.unwrap())?) } else { None }; - let p = ParamsBasicTypeWithAmountHolding::one(name, network, amount, date, token); + let p = + ParamsBasicTypeWithAmountHolding::one(name, &network[0], amount, date, token); Ok(Params::ParamsBasicTypeWithAmountHolding(p)) }, AchainableParams::AmountToken(p) => { @@ -255,7 +258,7 @@ impl TryFrom for Params { let network = &p.chain; let amount = ap.to_string(&p.amount)?; - let p = ParamsBasicTypeWithAmount::new(name, network, amount); + let p = ParamsBasicTypeWithAmount::new(name, &network[0], amount); Ok(Params::ParamsBasicTypeWithAmount(p)) }, AchainableParams::Amounts(p) => { @@ -264,14 +267,14 @@ impl TryFrom for Params { let amount1 = ap.to_string(&p.amount1)?; let amount2 = ap.to_string(&p.amount2)?; - let p = ParamsBasicTypeWithAmounts::new(name, network, amount1, amount2); + let p = ParamsBasicTypeWithAmounts::new(name, &network[0], amount1, amount2); Ok(Params::ParamsBasicTypeWithAmounts(p)) }, AchainableParams::Basic(p) => { let name = ap.to_string(&p.name)?; let network = &p.chain; - let p = ParamsBasicType::new(name, network); + let p = ParamsBasicType::new(name, &network[0]); Ok(Params::ParamsBasicType(p)) }, AchainableParams::BetweenPercents(p) => { @@ -282,7 +285,7 @@ impl TryFrom for Params { let p = ParamsBasicTypeWithBetweenPercents::new( name, - network, + &network[0], greater_than_or_equal_to, less_than_or_equal_to, ); @@ -299,7 +302,7 @@ impl TryFrom for Params { let date1 = "2015-01-01".into(); let date2 = "2023-01-01".into(); - let p = ParamsBasicTypeWithClassOfYear::new(name, network, date1, date2); + let p = ParamsBasicTypeWithClassOfYear::new(name, &network[0], date1, date2); Ok(Params::ParamsBasicTypeWithClassOfYear(p)) }, AchainableParams::DateInterval(p) => { @@ -308,7 +311,8 @@ impl TryFrom for Params { let start_date = ap.to_string(&p.start_date)?; let end_date = ap.to_string(&p.end_date)?; - let p = ParamsBasicTypeWithDateInterval::new(name, network, start_date, end_date); + let p = + ParamsBasicTypeWithDateInterval::new(name, &network[0], start_date, end_date); Ok(Params::ParamsBasicTypeWithDateInterval(p)) }, AchainableParams::DatePercent(p) => { @@ -318,7 +322,8 @@ impl TryFrom for Params { let date = ap.to_string(&p.date)?; let percent = ap.to_string(&p.percent)?; - let p = ParamsBasicTypeWithDatePercent::new(name, network, token, date, percent); + let p = + ParamsBasicTypeWithDatePercent::new(name, &network[0], token, date, percent); Ok(Params::ParamsBasicTypeWithDatePercent(p)) }, AchainableParams::Date(p) => { @@ -326,7 +331,7 @@ impl TryFrom for Params { let network = &p.chain; let date = ap.to_string(&p.date)?; - let p = ParamsBasicTypeWithDate::new(name, network, date); + let p = ParamsBasicTypeWithDate::new(name, &network[0], date); Ok(Params::ParamsBasicTypeWithDate(p)) }, AchainableParams::Token(p) => { @@ -334,7 +339,7 @@ impl TryFrom for Params { let network = &p.chain; let token = ap.to_string(&p.token)?; - let p = ParamsBasicTypeWithToken::new(name, network, token); + let p = ParamsBasicTypeWithToken::new(name, &network[0], token); Ok(Params::ParamsBasicTypeWithToken(p)) }, AchainableParams::Mirror(p) => { @@ -348,7 +353,7 @@ impl TryFrom for Params { None }; - let p = ParamsBasicTypeWithMirror::new(name, network, post_quantity); + let p = ParamsBasicTypeWithMirror::new(name, &network[0], post_quantity); Ok(Params::ParamsBasicTypeWithMirror(p)) }, } @@ -1436,7 +1441,7 @@ mod tests { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap(); - let mut data_provider_config = DataProviderConfig::new(); + let mut data_provider_config = DataProviderConfig::new().unwrap(); data_provider_config.set_achainable_url(url); AchainableClient::new(&data_provider_config) } diff --git a/tee-worker/litentry/core/data-providers/src/discord_litentry.rs b/tee-worker/litentry/core/data-providers/src/discord_litentry.rs index 129f5ce55e..7ae93687de 100644 --- a/tee-worker/litentry/core/data-providers/src/discord_litentry.rs +++ b/tee-worker/litentry/core/data-providers/src/discord_litentry.rs @@ -17,11 +17,11 @@ #[cfg(all(not(feature = "std"), feature = "sgx"))] use crate::sgx_reexport_prelude::*; -use crate::{build_client, vec_to_string, Error, HttpError}; +use crate::{build_client_with_cert, vec_to_string, Error, HttpError}; use http::header::CONNECTION; use http_req::response::Headers; use itc_rest_client::{ - http_client::{DefaultSend, HttpClient}, + http_client::{HttpClient, SendWithCertificateVerification}, rest_client::RestClient, RestGet, RestPath, }; @@ -50,14 +50,14 @@ impl RestPath for DiscordResponse { } pub struct DiscordLitentryClient { - client: RestClient>, + client: RestClient>, } impl DiscordLitentryClient { pub fn new(url: &str) -> Self { let mut headers = Headers::new(); headers.insert(CONNECTION.as_str(), "close"); - let client = build_client(url, headers); + let client = build_client_with_cert(url, headers); DiscordLitentryClient { client } } @@ -161,8 +161,8 @@ mod tests { fn init() -> DataProviderConfig { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap(); - let mut data_provider_config = DataProviderConfig::new(); - data_provider_config.set_discord_litentry_url(url); + let mut data_provider_config = DataProviderConfig::new().unwrap(); + data_provider_config.set_litentry_discord_microservice_url(url); data_provider_config } @@ -171,7 +171,8 @@ mod tests { let data_provider_config = init(); let guild_id = "919848390156767232".as_bytes().to_vec(); let handler = "againstwar".as_bytes().to_vec(); - let mut client = DiscordLitentryClient::new(&data_provider_config.discord_litentry_url); + let mut client = + DiscordLitentryClient::new(&data_provider_config.litentry_discord_microservice_url); let response = client.check_join(guild_id, handler); assert!(response.is_ok(), "check join discord error: {:?}", response); } @@ -183,7 +184,8 @@ mod tests { let channel_id = "919848392035794945".as_bytes().to_vec(); let role_id = "1034083718425493544".as_bytes().to_vec(); let handler = "ericzhang.eth".as_bytes().to_vec(); - let mut client = DiscordLitentryClient::new(&data_provider_config.discord_litentry_url); + let mut client = + DiscordLitentryClient::new(&data_provider_config.litentry_discord_microservice_url); let response = client.check_id_hubber(guild_id, channel_id, role_id, handler); assert!(response.is_ok(), "check discord id hubber error: {:?}", response); } diff --git a/tee-worker/litentry/core/data-providers/src/discord_official.rs b/tee-worker/litentry/core/data-providers/src/discord_official.rs index 938b996133..7ee9d08617 100644 --- a/tee-worker/litentry/core/data-providers/src/discord_official.rs +++ b/tee-worker/litentry/core/data-providers/src/discord_official.rs @@ -125,7 +125,7 @@ mod tests { fn init() -> DataProviderConfig { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap(); - let mut data_provider_config = DataProviderConfig::new(); + let mut data_provider_config = DataProviderConfig::new().unwrap(); data_provider_config.set_discord_official_url(url); data_provider_config } diff --git a/tee-worker/litentry/core/data-providers/src/karat_dao.rs b/tee-worker/litentry/core/data-providers/src/karat_dao.rs new file mode 100644 index 0000000000..169ed48909 --- /dev/null +++ b/tee-worker/litentry/core/data-providers/src/karat_dao.rs @@ -0,0 +1,169 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use crate::{ + build_client_with_cert, DataProviderConfig, Error, HttpError, ReqPath, RetryOption, + RetryableRestGet, +}; +use http::header::CONNECTION; +use http_req::response::Headers; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, + RestPath, +}; +use log::debug; +use serde::{Deserialize, Serialize}; +use std::{ + str, + string::{String, ToString}, + vec, + vec::Vec, +}; + +pub struct KaratDaoClient { + retry_option: RetryOption, + client: RestClient>, +} + +#[derive(Debug)] +pub struct KaraDaoRequest { + path: String, + query: Option>, +} + +impl KaratDaoClient { + pub fn new(data_provider_config: &DataProviderConfig) -> Self { + let api_retry_delay = data_provider_config.karat_dao_api_retry_delay; + let api_retry_times = data_provider_config.karat_dao_api_retry_times; + let api_url = data_provider_config.karat_dao_api_url.clone(); + let retry_option = + RetryOption { retry_delay: Some(api_retry_delay), retry_times: Some(api_retry_times) }; + + let mut headers = Headers::new(); + headers.insert(CONNECTION.as_str(), "close"); + let client = build_client_with_cert(api_url.as_str(), headers); + + KaratDaoClient { retry_option, client } + } + + fn get(&mut self, params: KaraDaoRequest, fast_fail: bool) -> Result + where + T: serde::de::DeserializeOwned + for<'a> RestPath>, + { + let retry_option: Option = + if fast_fail { None } else { Some(self.retry_option.clone()) }; + if let Some(query) = params.query { + let transformed_query: Vec<(&str, &str)> = + query.iter().map(|(k, v)| (k.as_str(), v.as_str())).collect(); + self.client.get_with_retry::( + ReqPath::new(params.path.as_str()), + &transformed_query, + retry_option, + ) + } else { + self.client + .get_retry::(ReqPath::new(params.path.as_str()), retry_option) + } + } +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct UserVerificationResponse { + pub result: UserVerificationResult, +} + +impl<'a> RestPath> for UserVerificationResponse { + fn get_path(path: ReqPath) -> Result { + Ok(path.path.into()) + } +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct UserVerificationResult { + pub is_valid: bool, +} + +pub trait KaraDaoApi { + fn user_verification( + &mut self, + address: String, + fail_fast: bool, + ) -> Result; +} + +impl KaraDaoApi for KaratDaoClient { + fn user_verification( + &mut self, + address: String, + fail_fast: bool, + ) -> Result { + let query: Vec<(String, String)> = vec![("address".to_string(), address)]; + + let params = KaraDaoRequest { path: "user/verification".into(), query: Some(query) }; + + debug!("user_verification, params: {:?}", params); + + match self.get::(params, fail_fast) { + Ok(resp) => { + debug!("user_verification, response: {:?}", resp); + Ok(resp) + }, + Err(e) => { + debug!("user_verification, error: {:?}", e); + Err(e) + }, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use lc_mock_server::run; + + fn init() -> DataProviderConfig { + let _ = env_logger::builder().is_test(true).try_init(); + let url = run(0).unwrap() + "/karat_dao/"; + + let mut config = DataProviderConfig::new().unwrap(); + config.set_karat_dao_api_url(url); + config + } + + #[test] + fn does_user_verification_works() { + let config = init(); + let mut client = KaratDaoClient::new(&config); + let mut response = client + .user_verification("0x49ad262c49c7aa708cc2df262ed53b64a17dd5ee".into(), true) + .unwrap(); + assert_eq!(response.result.is_valid, true); + + response = client + .user_verification("0x9401518f4ebba857baa879d9f76e1cc8b31ed197".into(), false) + .unwrap(); + assert_eq!(response.result.is_valid, false); + } +} diff --git a/tee-worker/litentry/core/data-providers/src/lib.rs b/tee-worker/litentry/core/data-providers/src/lib.rs index 973da9c4ff..908019f57d 100644 --- a/tee-worker/litentry/core/data-providers/src/lib.rs +++ b/tee-worker/litentry/core/data-providers/src/lib.rs @@ -41,15 +41,15 @@ use core::time::Duration; use http_req::response::Headers; use itc_rest_client::{ error::Error as HttpError, - http_client::{DefaultSend, HttpClient}, + http_client::{HttpClient, Send, SendWithCertificateVerification}, rest_client::RestClient, + Query, RestGet, RestPath, RestPost, }; use litentry_macros::if_not_production; use log::debug; use serde::{Deserialize, Serialize}; -use std::vec; +use std::{thread, vec}; -use itc_rest_client::http_client::SendWithCertificateVerification; use litentry_primitives::{ AchainableParams, Assertion, ErrorDetail, ErrorString, IntoErrorDetail, ParameterString, VCMPError, @@ -69,6 +69,8 @@ pub mod achainable_names; pub mod discord_litentry; pub mod discord_official; pub mod geniidata; +pub mod karat_dao; +pub mod moralis; pub mod nodereal; pub mod nodereal_jsonrpc; pub mod twitter_official; @@ -166,10 +168,9 @@ impl TokenFromString for ETokenAddress { #[derive(PartialEq, Eq, Clone, Encode, Decode, Serialize, Deserialize, Debug)] pub struct DataProviderConfig { pub twitter_official_url: String, - pub twitter_litentry_url: String, pub twitter_auth_token_v2: String, pub discord_official_url: String, - pub discord_litentry_url: String, + pub litentry_discord_microservice_url: String, pub discord_auth_token: String, pub achainable_url: String, pub achainable_auth_key: String, @@ -189,25 +190,27 @@ pub struct DataProviderConfig { pub vip3_url: String, pub geniidata_url: String, pub geniidata_api_key: String, -} - -impl Default for DataProviderConfig { - fn default() -> Self { - Self::new() - } + pub litentry_archive_url: String, + pub karat_dao_api_retry_delay: u64, + pub karat_dao_api_retry_times: u16, + pub karat_dao_api_url: String, + pub moralis_api_url: String, + pub moralis_api_retry_delay: u64, + pub moralis_api_retry_times: u16, + pub moralis_api_key: String, } impl DataProviderConfig { - pub fn new() -> Self { + pub fn new() -> Result { log::debug!("Initializing data providers config"); // default prod config let mut config = DataProviderConfig { twitter_official_url: "https://api.twitter.com".to_string(), - twitter_litentry_url: "http://127.0.0.1:9527”".to_string(), twitter_auth_token_v2: "".to_string(), discord_official_url: "https://discordapp.com".to_string(), - discord_litentry_url: "http://127.0.0.1:9527”".to_string(), + litentry_discord_microservice_url: "https://tee-microservice.litentry.io:9528" + .to_string(), discord_auth_token: "".to_string(), achainable_url: "https://label-production.graph.tdf-labs.io/".to_string(), achainable_auth_key: "".to_string(), @@ -229,30 +232,35 @@ impl DataProviderConfig { vip3_url: "https://dappapi.vip3.io/".to_string(), geniidata_url: "https://api.geniidata.com/api/1/brc20/balance?".to_string(), geniidata_api_key: "".to_string(), + litentry_archive_url: "https://archive-test.litentry.io".to_string(), + karat_dao_api_retry_delay: 5000, + karat_dao_api_retry_times: 2, + karat_dao_api_url: "https://api.karatdao.com/".to_string(), + moralis_api_key: "".to_string(), + moralis_api_retry_delay: 5000, + moralis_api_retry_times: 2, + moralis_api_url: "https://deep-index.moralis.io/api/v2.2/".to_string(), }; // we allow to override following config properties for non prod dev if_not_production!({ if let Ok(v) = env::var("TWITTER_OFFICIAL_URL") { - config.set_twitter_official_url(v); - } - if let Ok(v) = env::var("TWITTER_LITENTRY_URL") { - config.set_twitter_litentry_url(v); + config.set_twitter_official_url(v)?; } if let Ok(v) = env::var("DISCORD_OFFICIAL_URL") { - config.set_discord_official_url(v); + config.set_discord_official_url(v)?; } - if let Ok(v) = env::var("DISCORD_LITENTRY_URL") { - config.set_discord_litentry_url(v); + if let Ok(v) = env::var("LITENTRY_DISCORD_MICROSERVICE_URL") { + config.set_litentry_discord_microservice_url(v)?; } if let Ok(v) = env::var("ACHAINABLE_URL") { - config.set_achainable_url(v); + config.set_achainable_url(v)?; } if let Ok(v) = env::var("CREDENTIAL_ENDPOINT") { config.set_credential_endpoint(v); } if let Ok(v) = env::var("ONEBLOCK_NOTION_URL") { - config.set_oneblock_notion_url(v); + config.set_oneblock_notion_url(v)?; } if let Ok(v) = env::var("SORA_QUIZ_MASTER_ID") { config.set_sora_quiz_master_id(v); @@ -261,7 +269,7 @@ impl DataProviderConfig { config.set_sora_quiz_attendee_id(v); } if let Ok(v) = env::var("NODEREAL_API_URL") { - config.set_nodereal_api_url(v); + config.set_nodereal_api_url(v)?; } if let Ok(v) = env::var("NODEREAL_API_RETRY_DELAY") { config.set_nodereal_api_retry_delay(v.parse::().unwrap()); @@ -270,7 +278,7 @@ impl DataProviderConfig { config.set_nodereal_api_retry_times(v.parse::().unwrap()); } if let Ok(v) = env::var("NODEREAL_API_CHAIN_NETWORK_URL") { - config.set_nodereal_api_chain_network_url(v); + config.set_nodereal_api_chain_network_url(v)?; } if let Ok(v) = env::var("CONTEST_LEGEND_DISCORD_ROLE_ID") { config.set_contest_legend_discord_role_id(v); @@ -282,10 +290,31 @@ impl DataProviderConfig { config.set_contest_participant_discord_role_id(v); } if let Ok(v) = env::var("VIP3_URL") { - config.set_vip3_url(v); + config.set_vip3_url(v)?; } if let Ok(v) = env::var("GENIIDATA_URL") { - config.set_geniidata_url(v); + config.set_geniidata_url(v)?; + } + if let Ok(v) = env::var("LITENTRY_ARCHIVE_URL") { + config.set_litentry_archive_url(v)?; + } + if let Ok(v) = env::var("KARAT_DAO_API_RETRY_DELAY") { + config.set_karat_dao_api_retry_delay(v.parse::().unwrap()); + } + if let Ok(v) = env::var("KARAT_DAO_API_RETRY_TIME") { + config.set_karat_dao_api_retry_times(v.parse::().unwrap()); + } + if let Ok(v) = env::var("KARAT_DAO_API_URL") { + config.set_karat_dao_api_url(v)?; + } + if let Ok(v) = env::var("MORALIS_API_URL") { + config.set_moralis_api_url(v)?; + } + if let Ok(v) = env::var("MORALIS_API_RETRY_DELAY") { + config.set_moralis_api_retry_delay(v.parse::().unwrap()); + } + if let Ok(v) = env::var("MORALIS_API_RETRY_TIME") { + config.set_moralis_api_retry_times(v.parse::().unwrap()); } }); // set secrets from env variables @@ -307,35 +336,42 @@ impl DataProviderConfig { if let Ok(v) = env::var("GENIIDATA_API_KEY") { config.set_geniidata_api_key(v); } - config + if let Ok(v) = env::var("MORALIS_API_KEY") { + config.set_moralis_api_key(v); + } + Ok(config) } - pub fn set_twitter_official_url(&mut self, v: String) { + pub fn set_twitter_official_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; debug!("set_twitter_official_url: {:?}", v); self.twitter_official_url = v; - } - pub fn set_twitter_litentry_url(&mut self, v: String) { - debug!("set_twitter_litentry_url: {:?}", v); - self.twitter_litentry_url = v; + Ok(()) } pub fn set_twitter_auth_token_v2(&mut self, v: String) { debug!("set_twitter_auth_token_v2: {:?}", v); self.twitter_auth_token_v2 = v; } - pub fn set_discord_official_url(&mut self, v: String) { + pub fn set_discord_official_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; debug!("set_discord_official_url: {:?}", v); self.discord_official_url = v; + Ok(()) } - pub fn set_discord_litentry_url(&mut self, v: String) { - debug!("set_discord_litentry_url: {:?}", v); - self.discord_litentry_url = v; + pub fn set_litentry_discord_microservice_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; + debug!("set_litentry_discord_microservice_url: {:?}", v); + self.litentry_discord_microservice_url = v; + Ok(()) } pub fn set_discord_auth_token(&mut self, v: String) { debug!("set_discord_auth_token: {:?}", v); self.discord_auth_token = v; } - pub fn set_achainable_url(&mut self, v: String) { + pub fn set_achainable_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; debug!("set_achainable_url: {:?}", v); self.achainable_url = v; + Ok(()) } pub fn set_achainable_auth_key(&mut self, v: String) { debug!("set_achainable_auth_key: {:?}", v); @@ -349,9 +385,11 @@ impl DataProviderConfig { debug!("set_oneblock_notion_key: {:?}", v); self.oneblock_notion_key = v; } - pub fn set_oneblock_notion_url(&mut self, v: String) { + pub fn set_oneblock_notion_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; debug!("set_oneblock_notion_url: {:?}", v); self.oneblock_notion_url = v; + Ok(()) } pub fn set_sora_quiz_master_id(&mut self, v: String) { debug!("set_sora_quiz_master_id: {:?}", v); @@ -373,13 +411,17 @@ impl DataProviderConfig { debug!("set_nodereal_api_retry_times: {:?}", v); self.nodereal_api_retry_times = v; } - pub fn set_nodereal_api_url(&mut self, v: String) { + pub fn set_nodereal_api_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; debug!("set_nodereal_api_url: {:?}", v); self.nodereal_api_url = v; + Ok(()) } - pub fn set_nodereal_api_chain_network_url(&mut self, v: String) { + pub fn set_nodereal_api_chain_network_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; debug!("set_nodereal_api_chain_network_url: {:?}", v); self.nodereal_api_chain_network_url = v; + Ok(()) } pub fn set_contest_legend_discord_role_id(&mut self, v: String) { debug!("set_contest_legend_discord_role_id: {:?}", v); @@ -393,18 +435,67 @@ impl DataProviderConfig { debug!("set_contest_participant_discord_role_id: {:?}", v); self.contest_participant_discord_role_id = v; } - pub fn set_vip3_url(&mut self, v: String) { + pub fn set_vip3_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; debug!("set_vip3_url: {:?}", v); self.vip3_url = v; + Ok(()) } - pub fn set_geniidata_url(&mut self, v: String) { + pub fn set_geniidata_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; debug!("set_geniidata_url: {:?}", v); self.geniidata_url = v; + Ok(()) } pub fn set_geniidata_api_key(&mut self, v: String) { debug!("set_geniidata_api_key: {:?}", v); self.geniidata_api_key = v; } + pub fn set_litentry_archive_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; + debug!("set_litentry_archive_url: {:?}", v); + self.litentry_archive_url = v; + Ok(()) + } + pub fn set_karat_dao_api_retry_delay(&mut self, v: u64) { + debug!("set_karat_dao_api_retry_delay: {:?}", v); + self.karat_dao_api_retry_delay = v; + } + pub fn set_karat_dao_api_retry_times(&mut self, v: u16) { + debug!("set_karat_dao_api_retry_times: {:?}", v); + self.karat_dao_api_retry_times = v; + } + pub fn set_karat_dao_api_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; + debug!("set_karat_dao_api_url: {:?}", v); + self.karat_dao_api_url = v; + Ok(()) + } + pub fn set_moralis_api_key(&mut self, v: String) { + debug!("set_moralis_api_key: {:?}", v); + self.moralis_api_key = v; + } + pub fn set_moralis_api_retry_delay(&mut self, v: u64) { + debug!("set_moralis_api_retry_delay: {:?}", v); + self.moralis_api_retry_delay = v; + } + pub fn set_moralis_api_retry_times(&mut self, v: u16) { + debug!("set_moralis_api_retry_times: {:?}", v); + self.moralis_api_retry_times = v; + } + pub fn set_moralis_api_url(&mut self, v: String) -> Result<(), Error> { + check_url(&v)?; + debug!("set_moralis_api_url: {:?}", v); + self.moralis_api_url = v; + Ok(()) + } +} + +fn check_url(v: &String) -> Result<(), Error> { + match Url::parse(v) { + Ok(_) => Ok(()), + Err(err) => Err(Error::Utf8Error(format!("Input url: {:?}, parse error: {:?}", v, err))), + } } #[derive(Debug, thiserror::Error, Clone)] @@ -423,6 +514,9 @@ pub enum Error { #[error("GeniiData error: {0}")] GeniiDataError(String), + + #[error("Retryable error: {0}")] + RetryableError(String), } impl IntoErrorDetail for Error { @@ -446,13 +540,6 @@ pub fn vec_to_string(vec: Vec) -> Result { Ok(tmp.to_string()) } -pub fn build_client(base_url: &str, headers: Headers) -> RestClient> { - debug!("base_url: {}", base_url); - let base_url = Url::parse(base_url).unwrap(); - let http_client = HttpClient::new(DefaultSend {}, true, Some(TIMEOUT), Some(headers), None); - RestClient::new(http_client, base_url) -} - pub fn build_client_with_cert( base_url: &str, headers: Headers, @@ -469,6 +556,161 @@ pub fn build_client_with_cert( RestClient::new(http_client, base_url) } +#[derive(Serialize, Debug, Clone, Copy)] +#[serde(rename_all = "camelCase")] +pub struct ReqPath<'a> { + path: &'a str, +} + +impl<'a> ReqPath<'a> { + pub fn new(path: &'a str) -> Self { + Self { path } + } +} + +#[derive(Debug, Clone)] +pub struct RetryOption { + // default delay is 0 + retry_delay: Option, + // set retry_times to 0 or None for fail fast + retry_times: Option, +} + +const DEFAULT_RETRY_OPTION: RetryOption = RetryOption { retry_delay: None, retry_times: None }; + +pub type RestHttpClient = RestClient>; + +pub trait RetryableRestClient { + fn retry(&mut self, action: A, retry_option: RetryOption) -> Result + where + A: Fn(&mut RestHttpClient) -> Result; +} + +impl RetryableRestClient for RestHttpClient +where + T: Send, +{ + fn retry(&mut self, action: A, retry_option: RetryOption) -> Result + where + A: Fn(&mut RestHttpClient) -> Result, + { + let mut retries = 0; + let base_delay = Duration::from_millis(retry_option.retry_delay.unwrap_or_default()); + let maximum_retries = retry_option.retry_times.unwrap_or_default(); + + loop { + if retries > 0 { + debug!("Fail to call rest api, begin retry: {}", retries); + } + + if retries > maximum_retries { + return Err(Error::RetryableError(format!( + "Fail to call rest api within {} retries", + maximum_retries + ))) + } + + match action(self) { + Ok(response) => return Ok(response), + Err(err) => { + let req_err: Error = + Error::RequestError(format!("call rest api error: {}", err)); + match err { + HttpError::HttpError(code, _) => + if code == 429 { + // Too Many Requests + // exponential back off + thread::sleep(base_delay * 2u32.pow(retries as u32)); + retries += 1; + } else { + return Err(req_err) + }, + _ => return Err(req_err), + } + }, + } + } + } +} + +pub trait RetryableRestGet { + // set retry_option to None for fail fast + fn get_retry(&mut self, params: U, retry_option: Option) -> Result + where + U: Copy, + R: serde::de::DeserializeOwned + RestPath; + + // set retry_option to None for fail fast + fn get_with_retry( + &mut self, + params: U, + query: &Query<'_>, + retry_option: Option, + ) -> Result + where + U: Copy, + R: serde::de::DeserializeOwned + RestPath; +} + +impl RetryableRestGet for RestHttpClient +where + T: Send, +{ + fn get_retry(&mut self, params: U, retry_option: Option) -> Result + where + U: Copy, + R: serde::de::DeserializeOwned + RestPath, + { + self.retry(|c| c.get(params), retry_option.unwrap_or(DEFAULT_RETRY_OPTION)) + } + + fn get_with_retry( + &mut self, + params: U, + query: &Query<'_>, + retry_option: Option, + ) -> Result + where + U: Copy, + R: serde::de::DeserializeOwned + RestPath, + { + self.retry(|c| c.get_with(params, query), retry_option.unwrap_or(DEFAULT_RETRY_OPTION)) + } +} + +pub trait RetryableRestPost { + // set retry_option to None for fail fast + fn post_capture_retry( + &mut self, + params: U, + data: &D, + retry_option: Option, + ) -> Result + where + U: Copy, + D: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned; +} + +impl RetryableRestPost for RestHttpClient +where + T: Send, +{ + fn post_capture_retry( + &mut self, + params: U, + data: &D, + retry_option: Option, + ) -> Result + where + U: Copy, + D: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned, + { + self.retry(|c| c.post_capture(params, data), retry_option.unwrap_or(DEFAULT_RETRY_OPTION)) + } +} + pub trait ConvertParameterString { fn to_string(&self, field: &ParameterString) -> Result; } @@ -481,13 +723,20 @@ impl ConvertParameterString for AchainableParams { } } -pub fn convert_balance_hex_to_u128(result: serde_json::Value) -> Result { - match result.as_str() { - Some(result) => match u128::from_str_radix(&result[2..], 16) { +pub fn convert_balance_hex_to_u128(hex: &str) -> Result { + match u128::from_str_radix(&hex[2..], 16) { + Ok(balance) => Ok(balance), + Err(_) => Err(format!("Cannot parse hex {:?} to u128", hex)), + } +} + +pub fn convert_balance_hex_json_value_to_u128(value: serde_json::Value) -> Result { + match value.as_str() { + Some(str) => match convert_balance_hex_to_u128(str) { Ok(balance) => Ok(balance), - Err(_) => Err(Error::RequestError(format!("Cannot parse result {:?} to u128", result))), + Err(err) => Err(Error::RequestError(err)), }, - None => Err(Error::RequestError(format!("Cannot tansform result {:?} to &str", result))), + None => Err(Error::RequestError(format!("Cannot transform value {:?} to &str", value))), } } @@ -498,39 +747,43 @@ mod tests { #[test] fn should_return_correct_value_when_param_is_valid() { assert_eq!( - convert_balance_hex_to_u128(serde_json::Value::String("0x0".into())).unwrap(), + convert_balance_hex_json_value_to_u128(serde_json::Value::String("0x0".into())) + .unwrap(), 0_u128 ); assert_eq!( - convert_balance_hex_to_u128(serde_json::Value::String("0x320".into())).unwrap(), + convert_balance_hex_json_value_to_u128(serde_json::Value::String("0x320".into())) + .unwrap(), 800_u128 ); assert_eq!( - convert_balance_hex_to_u128(serde_json::Value::String("0x2b5e3af16b1880000".into())) - .unwrap(), + convert_balance_hex_json_value_to_u128(serde_json::Value::String( + "0x2b5e3af16b1880000".into() + )) + .unwrap(), 50_000_000_000_000_000_000_u128 ); } #[test] - fn shoud_return_error_when_param_is_not_a_str() { - match convert_balance_hex_to_u128(serde_json::Value::Bool(true)) { + fn should_return_error_when_param_is_not_a_str() { + match convert_balance_hex_json_value_to_u128(serde_json::Value::Bool(true)) { Ok(_) => panic!("Expected an error, but got Ok"), Err(err) => assert_eq!( err.to_string(), - "Request error: Cannot tansform result Bool(true) to &str" + "Request error: Cannot transform value Bool(true) to &str" ), } } #[test] - fn shoud_return_error_when_param_is_not_a_hex_str() { - match convert_balance_hex_to_u128(serde_json::Value::String("qwexyz".into())) { + fn should_return_error_when_param_is_not_a_hex_str() { + match convert_balance_hex_json_value_to_u128(serde_json::Value::String("qwexyz".into())) { Ok(_) => panic!("Expected an error, but got Ok"), Err(err) => - assert_eq!(err.to_string(), "Request error: Cannot parse result \"qwexyz\" to u128"), + assert_eq!(err.to_string(), "Request error: Cannot parse hex \"qwexyz\" to u128"), } } } diff --git a/tee-worker/litentry/core/data-providers/src/moralis.rs b/tee-worker/litentry/core/data-providers/src/moralis.rs new file mode 100644 index 0000000000..8adefdad13 --- /dev/null +++ b/tee-worker/litentry/core/data-providers/src/moralis.rs @@ -0,0 +1,238 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + build_client_with_cert, DataProviderConfig, Error, HttpError, ReqPath, RetryOption, + RetryableRestGet, +}; +use http::header::CONNECTION; +use http_req::response::Headers; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, + RestPath, +}; +use litentry_primitives::Web3Network; +use log::debug; +use serde::{Deserialize, Serialize}; +use std::{ + format, str, + string::{String, ToString}, + vec, + vec::Vec, +}; + +#[derive(Debug)] +pub struct MoralisRequest { + path: String, + query: Option>, +} + +pub struct MoralisClient { + retry_option: RetryOption, + client: RestClient>, +} + +impl MoralisClient { + pub fn new(data_provider_config: &DataProviderConfig) -> Self { + let api_key = data_provider_config.moralis_api_key.clone(); + let api_retry_delay = data_provider_config.moralis_api_retry_delay; + let api_retry_times = data_provider_config.moralis_api_retry_times; + let api_url = data_provider_config.moralis_api_url.clone(); + let retry_option = + RetryOption { retry_delay: Some(api_retry_delay), retry_times: Some(api_retry_times) }; + + let mut headers = Headers::new(); + headers.insert(CONNECTION.as_str(), "close"); + headers.insert("X-API-Key", api_key.as_str()); + let client = build_client_with_cert(api_url.as_str(), headers); + + MoralisClient { retry_option, client } + } + + fn get(&mut self, params: MoralisRequest, fast_fail: bool) -> Result + where + T: serde::de::DeserializeOwned + for<'a> RestPath>, + { + let retry_option: Option = + if fast_fail { None } else { Some(self.retry_option.clone()) }; + if let Some(query) = params.query { + let transformed_query: Vec<(&str, &str)> = + query.iter().map(|(k, v)| (k.as_str(), v.as_str())).collect(); + self.client.get_with_retry::( + ReqPath::new(params.path.as_str()), + &transformed_query, + retry_option, + ) + } else { + self.client + .get_retry::(ReqPath::new(params.path.as_str()), retry_option) + } + } +} + +trait MoralisChain { + fn get_chain(&self) -> String; +} + +impl MoralisChain for Web3Network { + fn get_chain(&self) -> String { + match self { + Self::Ethereum => "eth".into(), + Self::Bsc => "bsc".into(), + Self::Polygon => "polygon".into(), + Self::Arbitrum => "arbitrum".into(), + _ => "".into(), + } + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct MoralisChainParam { + value: String, +} + +impl MoralisChainParam { + pub fn new(network: &Web3Network) -> Self { + Self { value: network.get_chain() } + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct MoralisPageResponse { + pub status: String, + pub page: usize, + pub page_size: usize, + pub cursor: Option, + pub result: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct GetNftsByWalletParam { + pub address: String, + pub chain: MoralisChainParam, + pub token_addresses: Option>, + // max: 100, default: 100 + pub limit: Option, + pub cursor: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct GetNftsByWalletResult { + pub amount: String, + pub token_id: String, + pub token_address: String, + pub contract_type: String, + pub owner_of: String, +} + +pub type GetNftsByWalletResponse = MoralisPageResponse; + +impl<'a> RestPath> for GetNftsByWalletResponse { + fn get_path(path: ReqPath) -> Result { + Ok(path.path.into()) + } +} + +pub trait NftApiList { + fn get_nfts_by_wallet( + &mut self, + param: &GetNftsByWalletParam, + fast_fail: bool, + ) -> Result; +} + +impl NftApiList for MoralisClient { + // https://docs.moralis.io/web3-data-api/evm/reference/get-wallet-nfts + fn get_nfts_by_wallet( + &mut self, + param: &GetNftsByWalletParam, + fast_fail: bool, + ) -> Result { + let mut query: Vec<(String, String)> = + vec![("chain".to_string(), param.chain.value.clone())]; + if let Some(token_addresses) = param.token_addresses.clone() { + for (index, address) in token_addresses.iter().enumerate() { + query.push((format!("token_addresses[{}]", index), address.clone())); + } + } + + if let Some(limit) = param.limit { + query.push(("limit".to_string(), limit.to_string())); + } + + if let Some(cursor) = param.cursor.clone() { + query.push(("cursor".to_string(), cursor)); + } + + let params = MoralisRequest { path: format!("{}/nft", param.address), query: Some(query) }; + + debug!("get_nfts_by_wallet, params: {:?}", params); + + match self.get::(params, fast_fail) { + Ok(resp) => { + debug!("get_nfts_by_wallet, response: {:?}", resp); + Ok(resp) + }, + Err(e) => { + debug!("get_nfts_by_wallet, error: {:?}", e); + Err(e) + }, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use lc_mock_server::run; + + fn init() -> DataProviderConfig { + let _ = env_logger::builder().is_test(true).try_init(); + let url = run(0).unwrap() + "/moralis/"; + + let mut config = DataProviderConfig::new().unwrap(); + config.set_moralis_api_key("d416f55179dbd0e45b1a8ed030e3".to_string()); + config.set_moralis_api_url(url); + config + } + + #[test] + fn does_get_nfts_by_wallet_works() { + let config = init(); + let mut client = MoralisClient::new(&config); + let param = GetNftsByWalletParam { + address: "0x49ad262c49c7aa708cc2df262ed53b64a17dd5ee".into(), + chain: MoralisChainParam::new(&Web3Network::Ethereum), + token_addresses: Some(vec!["0x9401518f4ebba857baa879d9f76e1cc8b31ed197".into()]), + limit: None, + cursor: None, + }; + let result = client.get_nfts_by_wallet(¶m, true).unwrap(); + assert_eq!(result.cursor.unwrap(), "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"); + assert_eq!(result.page, 1); + assert_eq!(result.page_size, 100); + assert_eq!(result.result.len(), 1); + assert_eq!(result.result[0].amount, "1"); + assert_eq!(result.result[0].token_id, "5021"); + assert_eq!(result.result[0].token_address, "0xfff54e6fe44fd47c8814c4b1d62c924c54364ad3"); + assert_eq!(result.result[0].contract_type, "ERC721"); + assert_eq!(result.result[0].owner_of, "0xff3879b8a363aed92a6eaba8f61f1a96a9ec3c1e"); + } +} diff --git a/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs b/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs index ff9cf7b52f..713535d2bc 100644 --- a/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs +++ b/tee-worker/litentry/core/data-providers/src/nodereal_jsonrpc.rs @@ -17,13 +17,16 @@ #[cfg(all(not(feature = "std"), feature = "sgx"))] use crate::sgx_reexport_prelude::*; -use crate::{build_client, convert_balance_hex_to_u128, DataProviderConfig, Error, HttpError}; +use crate::{ + build_client_with_cert, convert_balance_hex_json_value_to_u128, DataProviderConfig, Error, + HttpError, ReqPath, RetryOption, RetryableRestPost, +}; use http::header::CONNECTION; use http_req::response::Headers; use itc_rest_client::{ - http_client::{DefaultSend, HttpClient}, + http_client::{HttpClient, SendWithCertificateVerification}, rest_client::RestClient, - RestPath, RestPost, + RestPath, }; use itp_rpc::{Id, RpcRequest}; use litentry_primitives::Web3Network; @@ -32,7 +35,7 @@ use serde::{Deserialize, Serialize}; use std::{ format, str, string::{String, ToString}, - thread, time, vec, + vec, vec::Vec, }; @@ -53,6 +56,8 @@ impl Web3NetworkNoderealJsonrpcClient for Web3Network { Some(NoderealJsonrpcClient::new(NoderealChain::Bsc, data_provider_config)), Web3Network::Ethereum => Some(NoderealJsonrpcClient::new(NoderealChain::Eth, data_provider_config)), + Web3Network::Polygon => + Some(NoderealJsonrpcClient::new(NoderealChain::Polygon, data_provider_config)), _ => None, } } @@ -90,21 +95,9 @@ impl NoderealChain { } } -#[derive(Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct ReqPath { - path: String, -} - -impl ReqPath { - pub fn new(api_key: &str) -> Self { - Self { path: "v1/".to_string() + api_key } - } -} - -impl RestPath for RpcRequest { +impl<'a> RestPath> for RpcRequest { fn get_path(req: ReqPath) -> core::result::Result { - Ok(req.path) + Ok(req.path.into()) } } @@ -116,10 +109,9 @@ pub struct RpcResponse { } pub struct NoderealJsonrpcClient { - api_key: String, - api_retry_delay: u64, - api_retry_times: u16, - client: RestClient>, + path: String, + retry_option: RetryOption, + client: RestClient>, } impl NoderealJsonrpcClient { @@ -129,67 +121,22 @@ impl NoderealJsonrpcClient { let api_retry_times = data_provider_config.nodereal_api_retry_times; let api_url = data_provider_config.nodereal_api_chain_network_url.clone(); let base_url = api_url.replace("{chain}", chain.to_string()); + let retry_option = + RetryOption { retry_delay: Some(api_retry_delay), retry_times: Some(api_retry_times) }; + let path = format!("v1/{}", api_key); let mut headers = Headers::new(); headers.insert(CONNECTION.as_str(), "close"); - let client = build_client(base_url.as_str(), headers); + let client = build_client_with_cert(base_url.as_str(), headers); - NoderealJsonrpcClient { api_key, api_retry_delay, api_retry_times, client } + NoderealJsonrpcClient { path, retry_option, client } } - // https://docs.nodereal.io/docs/cups-rate-limit - // add retry functionality to handle situations where requests may surpass predefined constraints. - fn retry(&mut self, action: A) -> Result - where - A: Fn(&mut NoderealJsonrpcClient) -> Result, - { - let mut retries = 0; - // retry delay 1 second - let base_delay = time::Duration::from_millis(self.api_retry_delay); - // maximum 5 retry times - let maximum_retries = self.api_retry_times; - - loop { - if retries > 0 { - debug!("Fail to call nodereal enhanced api, begin retry: {}", retries); - } - - if retries > maximum_retries { - return Err(Error::RequestError(format!( - "Fail to call call nodereal enhanced api within {} retries", - maximum_retries - ))) - } - - match action(self) { - Ok(response) => return Ok(response), - Err(err) => { - let req_err: Error = - Error::RequestError(format!("Nodereal enhanced api error: {}", err)); - match err { - HttpError::HttpError(code, _) => - if code == 429 { - // Too Many Requests - // exponential back off - thread::sleep(base_delay * 2u32.pow(retries as u32)); - retries += 1; - } else { - return Err(req_err) - }, - _ => return Err(req_err), - } - }, - } - } - } - - fn post(&mut self, body: &RpcRequest) -> Result { - self.retry(|c| { - c.client.post_capture::( - ReqPath::new(c.api_key.as_str()), - body, - ) - }) + fn post(&mut self, body: &RpcRequest, fast_fail: bool) -> Result { + let path = ReqPath::new(self.path.as_str()); + let retry_option = if fast_fail { None } else { Some(self.retry_option.clone()) }; + self.client + .post_capture_retry::(path, body, retry_option) } } @@ -236,13 +183,73 @@ pub struct GetTokenBalance721Param { pub block_number: String, } +#[derive(Serialize, Debug)] +pub struct GetTokenBalance1155Param { + // The address of the ERC1155/BEP1155 token + pub token_address: String, + // Account address whose balance will be checked + pub account_address: String, + // The block number in hex format or the string 'latest' or 'earliest' on which the balance will be checked + pub block_number: String, + // The tokenId in hex format of the ERC1155/BEP1155 token + pub token_id: String, +} + +#[derive(Serialize, Debug)] +pub struct GetNFTInventoryParam { + // The address of the account in hex format + pub account_address: String, + // The address of the contract + pub contract_address: String, + // pageSize is hex encoded and should be less equal than 100 (each page return at most pageSize items) + pub page_size: String, + // It should be empty for the first page. If more results are available, a pageKey will be returned in the response. Pass the pageKey to fetch the next pageSize items. + pub page_key: String, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct GetNFTInventoryResult { + // example: 100_342 + pub page_key: String, + pub details: Vec, +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct GetNFTInventoryResultDetail { + // the address of the token + pub token_address: String, + // the id of the token + pub token_id: String, + // the balance of the token + pub balance: String, +} + pub trait NftApiList { fn get_nft_holdings( &mut self, param: &GetNFTHoldingsParam, + fast_fail: bool, ) -> Result; - fn get_token_balance_721(&mut self, param: &GetTokenBalance721Param) -> Result; + fn get_token_balance_721( + &mut self, + param: &GetTokenBalance721Param, + fast_fail: bool, + ) -> Result; + + fn get_token_balance_1155( + &mut self, + param: &GetTokenBalance1155Param, + fast_fail: bool, + ) -> Result; + + fn get_token_nft_inventory( + &mut self, + param: &GetNFTInventoryParam, + fast_fail: bool, + ) -> Result; } // NFT API @@ -251,6 +258,7 @@ impl NftApiList for NoderealJsonrpcClient { fn get_nft_holdings( &mut self, param: &GetNFTHoldingsParam, + fast_fail: bool, ) -> Result { let params: Vec = vec![ param.account_address.clone(), @@ -265,16 +273,23 @@ impl NftApiList for NoderealJsonrpcClient { params, id: Id::Number(1), }; - self.post(&req_body).map_err(|e| Error::RequestError(format!("{:?}", e))).map( - |resp: RpcResponse| { + self.post(&req_body, fast_fail) + .map_err(|e| { + debug!("get_nft_holdings, error: {:?}", e); + e + }) + .map(|resp: RpcResponse| { debug!("get_nft_holdings, response: {:?}", resp); serde_json::from_value(resp.result).unwrap() - }, - ) + }) } // https://docs.nodereal.io/reference/nr_gettokenbalance721 - fn get_token_balance_721(&mut self, param: &GetTokenBalance721Param) -> Result { + fn get_token_balance_721( + &mut self, + param: &GetTokenBalance721Param, + fast_fail: bool, + ) -> Result { let params: Vec = vec![ param.token_address.clone(), param.account_address.clone(), @@ -288,13 +303,84 @@ impl NftApiList for NoderealJsonrpcClient { id: Id::Number(1), }; - match self.post(&req_body) { + match self.post(&req_body, fast_fail) { Ok(resp) => { // result example: '0x', '0x8' debug!("get_token_balance_721, response: {:?}", resp); - convert_balance_hex_to_u128(resp.result) + convert_balance_hex_json_value_to_u128(resp.result) + }, + Err(e) => { + debug!("get_token_balance_721, error: {:?}", e); + Err(e) + }, + } + } + + // https://docs.nodereal.io/reference/nr_gettokenbalance1155 + fn get_token_balance_1155( + &mut self, + param: &GetTokenBalance1155Param, + fast_fail: bool, + ) -> Result { + let params: Vec = vec![ + param.token_address.clone(), + param.account_address.clone(), + param.block_number.clone(), + param.token_id.clone(), + ]; + debug!("get_token_balance_1155: {:?}", param); + let req_body = RpcRequest { + jsonrpc: "2.0".to_string(), + method: "nr_getTokenBalance1155".to_string(), + params, + id: Id::Number(1), + }; + + match self.post(&req_body, fast_fail) { + Ok(resp) => { + // result example: '0x', '0x8' + debug!("get_token_balance_1155, response: {:?}", resp); + convert_balance_hex_json_value_to_u128(resp.result) + }, + Err(e) => { + debug!("get_token_balance_1155, error: {:?}", e); + Err(e) + }, + } + } + + // https://docs.nodereal.io/reference/nr_getnftinventory + fn get_token_nft_inventory( + &mut self, + param: &GetNFTInventoryParam, + fast_fail: bool, + ) -> Result { + let params: Vec = vec![ + param.account_address.clone(), + param.contract_address.clone(), + param.page_size.clone(), + param.page_key.clone(), + ]; + debug!("get_token_nft_inventory: {:?}", param); + let req_body = RpcRequest { + jsonrpc: "2.0".to_string(), + method: "nr_getNFTInventory".to_string(), + params, + id: Id::Number(1), + }; + + match self.post(&req_body, fast_fail) { + Ok(resp) => { + debug!("get_token_nft_inventory, response: {:?}", resp); + match serde_json::from_value::(resp.result) { + Ok(result) => Ok(result), + Err(e) => Err(Error::RequestError(format!("{:?}", e))), + } + }, + Err(e) => { + debug!("get_token_nft_inventory, error: {:?}", e); + Err(e) }, - Err(e) => Err(Error::RequestError(format!("{:?}", e))), } } } @@ -311,13 +397,21 @@ pub struct GetTokenBalance20Param { // Fungible Tokens API pub trait FungibleApiList { - fn get_token_balance_20(&mut self, param: &GetTokenBalance20Param) -> Result; - fn get_token_holdings(&mut self, address: &str) -> Result; + fn get_token_balance_20( + &mut self, + param: &GetTokenBalance20Param, + fast_fail: bool, + ) -> Result; + fn get_token_holdings(&mut self, address: &str, fast_fail: bool) -> Result; } impl FungibleApiList for NoderealJsonrpcClient { // https://docs.nodereal.io/reference/nr_gettokenbalance20 - fn get_token_balance_20(&mut self, param: &GetTokenBalance20Param) -> Result { + fn get_token_balance_20( + &mut self, + param: &GetTokenBalance20Param, + fast_fail: bool, + ) -> Result { let params: Vec = vec![param.contract_address.clone(), param.address.clone(), param.block_number.clone()]; debug!("get_token_balance_20: {:?}", param); @@ -328,17 +422,20 @@ impl FungibleApiList for NoderealJsonrpcClient { id: Id::Number(1), }; - match self.post(&req_body) { + match self.post(&req_body, fast_fail) { Ok(resp) => { // result example: '0x', '0x8' debug!("get_token_balance_20, response: {:?}", resp); - convert_balance_hex_to_u128(resp.result) + convert_balance_hex_json_value_to_u128(resp.result) + }, + Err(e) => { + debug!("get_token_balance_20, error: {:?}", e); + Err(e) }, - Err(e) => Err(Error::RequestError(format!("{:?}", e))), } } - fn get_token_holdings(&mut self, address: &str) -> Result { + fn get_token_holdings(&mut self, address: &str, fast_fail: bool) -> Result { let params: Vec = vec![address.to_string(), "0x1".to_string(), "0x64".to_string()]; debug!("get_token_holdings: {:?}", params); @@ -349,16 +446,16 @@ impl FungibleApiList for NoderealJsonrpcClient { id: Id::Number(1), }; - self.post(&req_body) + self.post(&req_body, fast_fail) } } pub trait EthBalance { - fn get_balance(&mut self, address: &str) -> Result; + fn get_balance(&mut self, address: &str, fast_fail: bool) -> Result; } impl EthBalance for NoderealJsonrpcClient { - fn get_balance(&mut self, address: &str) -> Result { + fn get_balance(&mut self, address: &str, fast_fail: bool) -> Result { let params = vec![address.to_string(), "latest".to_string()]; let req_body = RpcRequest { @@ -368,23 +465,26 @@ impl EthBalance for NoderealJsonrpcClient { id: Id::Number(1), }; - match self.post(&req_body) { + match self.post(&req_body, fast_fail) { Ok(resp) => { // result example: '0x', '0x8' debug!("eth_getBalance, response: {:?}", resp); - convert_balance_hex_to_u128(resp.result) + convert_balance_hex_json_value_to_u128(resp.result) + }, + Err(e) => { + debug!("eth_getBalance, error: {:?}", e); + Err(e) }, - Err(e) => Err(Error::RequestError(format!("{:?}", e))), } } } pub trait TransactionCount { - fn get_transaction_count(&mut self, address: &str) -> Result; + fn get_transaction_count(&mut self, address: &str, fast_fail: bool) -> Result; } impl TransactionCount for NoderealJsonrpcClient { - fn get_transaction_count(&mut self, address: &str) -> Result { + fn get_transaction_count(&mut self, address: &str, fast_fail: bool) -> Result { let params = vec![address.to_string(), "latest".to_string()]; let req_body = RpcRequest { @@ -394,7 +494,7 @@ impl TransactionCount for NoderealJsonrpcClient { id: Id::Number(1), }; - match self.post(&req_body) { + match self.post(&req_body, fast_fail) { Ok(resp) => { // result example: '0x', '0x8' debug!("eth_getTransactionCount, response: {:?}", resp); @@ -407,12 +507,15 @@ impl TransactionCount for NoderealJsonrpcClient { ))), }, None => Err(Error::RequestError(format!( - "Cannot tansform response result {:?} to &str", + "Cannot transform response result {:?} to &str", resp.result ))), } }, - Err(e) => Err(Error::RequestError(format!("{:?}", e))), + Err(e) => { + debug!("get_transaction_count, error: {:?}", e); + Err(e) + }, } } } @@ -426,7 +529,7 @@ mod tests { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap() + "/nodereal_jsonrpc/"; - let mut config = DataProviderConfig::new(); + let mut config = DataProviderConfig::new().unwrap(); config.set_nodereal_api_key("d416f55179dbd0e45b1a8ed030e3".to_string()); config.set_nodereal_api_chain_network_url(url); config @@ -442,7 +545,7 @@ mod tests { page: 1, page_size: 2, }; - let result = client.get_nft_holdings(¶m).unwrap(); + let result = client.get_nft_holdings(¶m, false).unwrap(); assert_eq!(result.total_count, "0x1"); assert_eq!(result.details.len(), 1); assert_eq!(result.details[0].token_address, "0x9401518f4EBBA857BAA879D9f76E1Cc8b31ed197"); @@ -460,7 +563,7 @@ mod tests { account_address: "0x49AD262C49C7aA708Cc2DF262eD53B64A17Dd5EE".into(), block_number: "latest".into(), }; - let result = client.get_token_balance_721(¶m).unwrap(); + let result = client.get_token_balance_721(¶m, false).unwrap(); assert_eq!(result, 1); } @@ -473,7 +576,39 @@ mod tests { address: "0x85Be4e2ccc9c85BE8783798B6e8A101BDaC6467F".into(), block_number: "latest".into(), }; - let result = client.get_token_balance_20(¶m).unwrap(); + let result = client.get_token_balance_20(¶m, false).unwrap(); assert_eq!(result, 800); } + + #[test] + fn does_get_token_balance_1155_works() { + let config = init(); + let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth, &config); + let param = GetTokenBalance1155Param { + token_address: "0x07D971C03553011a48E951a53F48632D37652Ba1".into(), + account_address: "0x49AD262C49C7aA708Cc2DF262eD53B64A17Dd5EE".into(), + block_number: "latest".into(), + token_id: "0x0000000000000000000000000000000000000000f".into(), + }; + let result = client.get_token_balance_1155(¶m, false).unwrap(); + assert_eq!(result, 1); + } + + #[test] + fn does_get_token_nft_inventory_works() { + let config = init(); + let mut client = NoderealJsonrpcClient::new(NoderealChain::Eth, &config); + let param = GetNFTInventoryParam { + account_address: "0x0042f9b78c67eb30c020a56d07f9a2fc83bc2514".into(), + contract_address: "0x64aF96778bA83b7d4509123146E2B3b07F7deF52".into(), + page_size: "0x14".into(), + page_key: "".into(), + }; + let result = client.get_token_nft_inventory(¶m, false).unwrap(); + assert_eq!(result.page_key, "100_342"); + assert_eq!(result.details.len(), 1); + assert_eq!(result.details[0].token_address, "0x5e74094cd416f55179dbd0e45b1a8ed030e396a1"); + assert_eq!(result.details[0].token_id, "0x0000000000000000000000000000000000000000f"); + assert_eq!(result.details[0].balance, "0x00000000000000000000000000000000000000001"); + } } diff --git a/tee-worker/litentry/core/data-providers/src/twitter_official.rs b/tee-worker/litentry/core/data-providers/src/twitter_official.rs index 09404f862a..43d6b7d618 100644 --- a/tee-worker/litentry/core/data-providers/src/twitter_official.rs +++ b/tee-worker/litentry/core/data-providers/src/twitter_official.rs @@ -255,7 +255,7 @@ mod tests { fn init() -> DataProviderConfig { let _ = env_logger::builder().is_test(true).try_init(); let url = run(0).unwrap(); - let mut data_provider_config = DataProviderConfig::new(); + let mut data_provider_config = DataProviderConfig::new().unwrap(); data_provider_config.set_twitter_official_url(url); data_provider_config } diff --git a/tee-worker/litentry/core/mock-server/src/karat_dao.rs b/tee-worker/litentry/core/mock-server/src/karat_dao.rs new file mode 100644 index 0000000000..3178d750d8 --- /dev/null +++ b/tee-worker/litentry/core/mock-server/src/karat_dao.rs @@ -0,0 +1,42 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . +#![allow(opaque_hidden_inferred_bound)] + +use std::collections::HashMap; + +use lc_data_providers::karat_dao::{UserVerificationResponse, UserVerificationResult}; + +use warp::{http::Response, Filter}; + +pub(crate) fn query() -> impl Filter + Clone { + warp::get() + .and(warp::path!("karat_dao" / "user" / "verification")) + .and(warp::query::>()) + .map(move |p: HashMap| { + let default = String::default(); + let address = p.get("address").unwrap_or(&default); + + if address == "0x49ad262c49c7aa708cc2df262ed53b64a17dd5ee" { + let body = + UserVerificationResponse { result: UserVerificationResult { is_valid: true } }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + } else { + let body = + UserVerificationResponse { result: UserVerificationResult { is_valid: false } }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + } + }) +} diff --git a/tee-worker/litentry/core/mock-server/src/lib.rs b/tee-worker/litentry/core/mock-server/src/lib.rs index ebe5f3245b..d725b79ed5 100644 --- a/tee-worker/litentry/core/mock-server/src/lib.rs +++ b/tee-worker/litentry/core/mock-server/src/lib.rs @@ -24,9 +24,12 @@ use warp::Filter; pub mod achainable; pub mod discord_litentry; pub mod discord_official; +pub mod karat_dao; +pub mod litentry_archive; +pub mod moralis; pub mod nodereal_jsonrpc; -pub mod twitter_litentry; pub mod twitter_official; +pub mod vip3; // It should only works on UNIX. async fn shutdown_signal() { @@ -56,13 +59,16 @@ pub fn run(port: u16) -> Result { .or(twitter_official::query_retweeted_by()) .or(twitter_official::query_user_by_name()) .or(twitter_official::query_user_by_id()) - .or(twitter_litentry::check_follow()) .or(discord_official::query_message()) .or(discord_litentry::check_id_hubber()) .or(discord_litentry::check_join()) .or(discord_litentry::has_role()) .or(nodereal_jsonrpc::query()) + .or(karat_dao::query()) + .or(moralis::query()) .or(achainable::query()) + .or(litentry_archive::query_user_joined_evm_campaign()) + .or(vip3::query_user_sbt_level()) .boxed(), ) .bind_with_graceful_shutdown(([127, 0, 0, 1], port), shutdown_signal()); diff --git a/tee-worker/litentry/core/mock-server/src/twitter_litentry.rs b/tee-worker/litentry/core/mock-server/src/litentry_archive.rs similarity index 74% rename from tee-worker/litentry/core/mock-server/src/twitter_litentry.rs rename to tee-worker/litentry/core/mock-server/src/litentry_archive.rs index 00443af0eb..65f98b3b90 100644 --- a/tee-worker/litentry/core/mock-server/src/twitter_litentry.rs +++ b/tee-worker/litentry/core/mock-server/src/litentry_archive.rs @@ -18,21 +18,20 @@ use std::collections::HashMap; use warp::{http::Response, Filter}; -pub(crate) fn check_follow( +pub(crate) fn query_user_joined_evm_campaign( ) -> impl Filter + Clone { warp::get() - .and(warp::path!("twitter" / "followers" / "verification")) + .and(warp::path!("events" / "does-user-joined-evm-campaign")) .and(warp::query::>()) .map(move |p: HashMap| { let default = String::default(); - let handler1 = p.get("handler1").unwrap_or(&default); - let handler2 = p.get("handler2").unwrap_or(&default); - - let body = r#"{ "data": false }"#; - if handler1.as_str() == "litentry" && handler2 == "paritytech" { + let account = p.get("account").unwrap_or(&default); + if account == "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d" { + let body = r#"{ "hasJoined": true }"#; Response::builder().body(body.to_string()) } else { - Response::builder().status(400).body(String::from("Error query")) + let body = r#"{ "hasJoined": false }"#; + Response::builder().body(body.to_string()) } }) } diff --git a/tee-worker/litentry/core/mock-server/src/moralis.rs b/tee-worker/litentry/core/mock-server/src/moralis.rs new file mode 100644 index 0000000000..ae49497c86 --- /dev/null +++ b/tee-worker/litentry/core/mock-server/src/moralis.rs @@ -0,0 +1,55 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . +#![allow(opaque_hidden_inferred_bound)] + +use std::collections::HashMap; + +use lc_data_providers::moralis::{GetNftsByWalletResult, MoralisPageResponse}; + +use warp::{http::Response, Filter}; + +pub(crate) fn query() -> impl Filter + Clone { + warp::get() + .and(warp::path!("moralis" / String / "nft")) + .and(warp::query::>()) + .map(move |address, _| { + if address == "0x49ad262c49c7aa708cc2df262ed53b64a17dd5ee" { + let body = MoralisPageResponse:: { + status: "SYNCED".into(), + cursor: Some("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9".into()), + page: 1, + page_size: 100, + result: vec![GetNftsByWalletResult { + amount: "1".into(), + token_id: "5021".into(), + token_address: "0xfff54e6fe44fd47c8814c4b1d62c924c54364ad3".into(), + contract_type: "ERC721".into(), + owner_of: "0xff3879b8a363aed92a6eaba8f61f1a96a9ec3c1e".into(), + }], + }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + } else { + let body = MoralisPageResponse:: { + status: "SYNCED".into(), + cursor: None, + page: 1, + page_size: 100, + result: vec![], + }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + } + }) +} diff --git a/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs b/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs index 43d97de947..6d85c6a10a 100644 --- a/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs +++ b/tee-worker/litentry/core/mock-server/src/nodereal_jsonrpc.rs @@ -17,7 +17,8 @@ use itp_rpc::Id; use lc_data_providers::nodereal_jsonrpc::{ - GetNFTHoldingsResult, GetNFTHoldingsResultDetail, RpcResponse, + GetNFTHoldingsResult, GetNFTHoldingsResultDetail, GetNFTInventoryResult, + GetNFTInventoryResultDetail, RpcResponse, }; use warp::{http::Response, hyper::body::Bytes, Filter}; @@ -62,6 +63,14 @@ pub(crate) fn query() -> impl Filter { + let body = RpcResponse { + jsonrpc: "2.0".into(), + id: Id::Number(1), + result: serde_json::to_value("0x1").unwrap(), + }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + }, "nr_getTokenBalance20" => { let value = match params[1].as_str() { // 100_000_000_000 @@ -84,6 +93,22 @@ pub(crate) fn query() -> impl Filter { + let result = GetNFTInventoryResult { + page_key: "100_342".into(), + details: vec![GetNFTInventoryResultDetail { + token_address: "0x5e74094cd416f55179dbd0e45b1a8ed030e396a1".into(), + token_id: "0x0000000000000000000000000000000000000000f".into(), + balance: "0x00000000000000000000000000000000000000001".into(), + }], + }; + let body = RpcResponse { + jsonrpc: "2.0".into(), + id: Id::Number(1), + result: serde_json::to_value(result).unwrap(), + }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + }, "eth_getBalance" => { let body = RpcResponse { jsonrpc: "2.0".into(), diff --git a/tee-worker/litentry/core/mock-server/src/vip3.rs b/tee-worker/litentry/core/mock-server/src/vip3.rs new file mode 100644 index 0000000000..0557ee56c0 --- /dev/null +++ b/tee-worker/litentry/core/mock-server/src/vip3.rs @@ -0,0 +1,47 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![allow(opaque_hidden_inferred_bound)] + +use lc_data_providers::vip3::{LevelEntity, VIP3SBTInfoResponse}; +use std::collections::HashMap; +use warp::{http::Response, Filter}; + +pub(crate) fn query_user_sbt_level( +) -> impl Filter + Clone { + warp::get() + .and(warp::path!("api" / "v1" / "sbt" / "info")) + .and(warp::query::>()) + .map(move |p: HashMap| { + let default = String::default(); + let account = p.get("addr").unwrap_or(&default); + if account == "0xff93b45308fd417df303d6515ab04d9e89a750ca" { + let body = VIP3SBTInfoResponse { + code: 0, + msg: "success".to_string(), + data: LevelEntity { level: 1 }, + }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + } else { + let body = VIP3SBTInfoResponse { + code: 0, + msg: "success".to_string(), + data: LevelEntity { level: 0 }, + }; + Response::builder().body(serde_json::to_string(&body).unwrap()) + } + }) +} diff --git a/tee-worker/litentry/core/service/src/lib.rs b/tee-worker/litentry/core/service/src/lib.rs index e1773ead74..282f25ca30 100644 --- a/tee-worker/litentry/core/service/src/lib.rs +++ b/tee-worker/litentry/core/service/src/lib.rs @@ -28,10 +28,14 @@ pub mod sgx_reexport_prelude { #[cfg(all(feature = "std", feature = "sgx"))] compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); -use std::{string::String, vec::Vec}; +use std::{string::String, vec, vec::Vec}; -use litentry_primitives::{ErrorDetail as Error, IntoErrorDetail, Web3Network, Web3TokenType}; +use litentry_primitives::{ + ErrorDetail as Error, IntoErrorDetail, Web3Network, Web3NftType, Web3TokenType, +}; pub use lc_data_providers::DataProviderConfig; +pub mod platform_user; +pub mod web3_nft; pub mod web3_token; diff --git a/tee-worker/litentry/core/service/src/platform_user/karat_dao_user.rs b/tee-worker/litentry/core/service/src/platform_user/karat_dao_user.rs new file mode 100644 index 0000000000..055fd7d3ea --- /dev/null +++ b/tee-worker/litentry/core/service/src/platform_user/karat_dao_user.rs @@ -0,0 +1,50 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use core::result::Result; + +use lc_data_providers::{ + karat_dao::{KaraDaoApi, KaratDaoClient}, + DataProviderConfig, +}; + +use crate::*; + +pub fn is_user( + addresses: Vec, + data_provider_config: &DataProviderConfig, +) -> Result { + let mut is_user = false; + let mut client = KaratDaoClient::new(data_provider_config); + for address in addresses { + match client.user_verification(address, true) { + Ok(response) => { + is_user = response.result.is_valid; + if is_user { + break + } + }, + Err(err) => return Err(err.into_error_detail()), + } + } + Ok(is_user) +} diff --git a/tee-worker/litentry/core/service/src/platform_user/mod.rs b/tee-worker/litentry/core/service/src/platform_user/mod.rs new file mode 100644 index 0000000000..5eac7fdd53 --- /dev/null +++ b/tee-worker/litentry/core/service/src/platform_user/mod.rs @@ -0,0 +1,40 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use core::result::Result; + +use lc_data_providers::DataProviderConfig; +use litentry_primitives::PlatformUserType; + +use crate::*; + +mod karat_dao_user; + +pub fn is_user( + platform_user_type: PlatformUserType, + addresses: Vec, + data_provider_config: &DataProviderConfig, +) -> Result { + match platform_user_type { + PlatformUserType::KaratDaoUser => karat_dao_user::is_user(addresses, data_provider_config), + } +} diff --git a/tee-worker/litentry/core/service/src/web3_nft/mod.rs b/tee-worker/litentry/core/service/src/web3_nft/mod.rs new file mode 100644 index 0000000000..0ad2e33690 --- /dev/null +++ b/tee-worker/litentry/core/service/src/web3_nft/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +pub mod nft_holder; diff --git a/tee-worker/litentry/core/service/src/web3_nft/nft_holder/common.rs b/tee-worker/litentry/core/service/src/web3_nft/nft_holder/common.rs new file mode 100644 index 0000000000..4cf51238b8 --- /dev/null +++ b/tee-worker/litentry/core/service/src/web3_nft/nft_holder/common.rs @@ -0,0 +1,124 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use core::result::Result; + +use lc_common::web3_nft::NftAddress; +use lc_data_providers::{ + moralis::{ + GetNftsByWalletParam, MoralisChainParam, MoralisClient, NftApiList as MoralisNftApiList, + }, + nodereal_jsonrpc::{ + GetTokenBalance721Param, NftApiList as NoderealNftApiList, Web3NetworkNoderealJsonrpcClient, + }, +}; +use litentry_primitives::ErrorDetail; + +use crate::*; + +// support ERC721/BEP721 nft token +pub fn has_nft_721( + addresses: Vec<(Web3Network, String)>, + nft_type: Web3NftType, + data_provider_config: &DataProviderConfig, +) -> Result { + for address in addresses.iter() { + let network = address.0; + let token_address = nft_type.get_nft_address(network).unwrap_or_default(); + + match network { + Web3Network::Bsc | Web3Network::Ethereum => { + if let Some(mut client) = + network.create_nodereal_jsonrpc_client(data_provider_config) + { + let param = GetTokenBalance721Param { + token_address: token_address.into(), + account_address: address.1.clone(), + block_number: "latest".into(), + }; + match client.get_token_balance_721(¶m, false) { + Ok(balance) => + if balance > 0 { + return Ok(true) + }, + Err(err) => return Err(err.into_error_detail()), + } + } + }, + _ => {}, + } + } + + Ok(false) +} + +// support ERC1155/BEP1155 nft token +pub fn has_nft_1155( + addresses: Vec<(Web3Network, String)>, + nft_type: Web3NftType, + data_provider_config: &DataProviderConfig, +) -> Result { + let mut client = MoralisClient::new(data_provider_config); + for address in addresses.iter() { + let network = address.0; + let token_address = nft_type.get_nft_address(network).unwrap_or_default(); + + match network { + Web3Network::Bsc + | Web3Network::Ethereum + | Web3Network::Polygon + | Web3Network::Arbitrum => { + let mut cursor: Option = None; + 'inner: loop { + let param = GetNftsByWalletParam { + address: address.1.clone(), + chain: MoralisChainParam::new(&network), + token_addresses: Some(vec![token_address.into()]), + limit: None, + cursor, + }; + match client.get_nfts_by_wallet(¶m, false) { + Ok(resp) => { + cursor = resp.cursor; + for item in &resp.result { + match item.amount.parse::() { + Ok(balance) => + if balance > 0 { + return Ok(true) + }, + Err(_) => return Err(ErrorDetail::ParseError), + } + } + }, + Err(err) => return Err(err.into_error_detail()), + } + if cursor.is_none() { + break 'inner + } + } + }, + _ => {}, + } + } + + Ok(false) +} diff --git a/tee-worker/litentry/core/service/src/web3_nft/nft_holder/mod.rs b/tee-worker/litentry/core/service/src/web3_nft/nft_holder/mod.rs new file mode 100644 index 0000000000..8f24d928ef --- /dev/null +++ b/tee-worker/litentry/core/service/src/web3_nft/nft_holder/mod.rs @@ -0,0 +1,39 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use core::result::Result; + +use crate::*; + +mod common; + +pub fn has_nft( + nft_type: Web3NftType, + addresses: Vec<(Web3Network, String)>, + data_provider_config: &DataProviderConfig, +) -> Result { + match nft_type { + Web3NftType::WeirdoGhostGang => + common::has_nft_721(addresses, nft_type, data_provider_config), + Web3NftType::Club3Sbt => common::has_nft_1155(addresses, nft_type, data_provider_config), + } +} diff --git a/tee-worker/litentry/core/service/src/web3_token/token_balance/bnb_balance.rs b/tee-worker/litentry/core/service/src/web3_token/token_balance/bnb_balance.rs index 2b8f19874b..157a7ecf3c 100644 --- a/tee-worker/litentry/core/service/src/web3_token/token_balance/bnb_balance.rs +++ b/tee-worker/litentry/core/service/src/web3_token/token_balance/bnb_balance.rs @@ -47,7 +47,7 @@ pub fn get_balance( network.create_nodereal_jsonrpc_client(data_provider_config) { let result = if network == Web3Network::Bsc { - client.get_balance(address.1.as_str()) + client.get_balance(address.1.as_str(), false) } else { let param = GetTokenBalance20Param { contract_address: Web3TokenType::Bnb @@ -57,7 +57,7 @@ pub fn get_balance( address: address.1.clone(), block_number: "latest".into(), }; - client.get_token_balance_20(¶m) + client.get_token_balance_20(¶m, false) }; match result { diff --git a/tee-worker/litentry/core/service/src/web3_token/token_balance/common.rs b/tee-worker/litentry/core/service/src/web3_token/token_balance/common.rs index 4f4cf1bcf6..21a8244e71 100644 --- a/tee-worker/litentry/core/service/src/web3_token/token_balance/common.rs +++ b/tee-worker/litentry/core/service/src/web3_token/token_balance/common.rs @@ -51,7 +51,7 @@ pub fn get_balance_from_evm( if let Some(mut client) = network.create_nodereal_jsonrpc_client(data_provider_config) { - match client.get_token_balance_20(¶m) { + match client.get_token_balance_20(¶m, false) { Ok(balance) => { total_balance += calculate_balance_with_decimals(balance, decimals); }, diff --git a/tee-worker/litentry/core/service/src/web3_token/token_balance/eth_balance.rs b/tee-worker/litentry/core/service/src/web3_token/token_balance/eth_balance.rs index 63140ce609..b2d9b82357 100644 --- a/tee-worker/litentry/core/service/src/web3_token/token_balance/eth_balance.rs +++ b/tee-worker/litentry/core/service/src/web3_token/token_balance/eth_balance.rs @@ -47,7 +47,7 @@ pub fn get_balance( network.create_nodereal_jsonrpc_client(data_provider_config) { let result = if network == Web3Network::Ethereum { - client.get_balance(address.1.as_str()) + client.get_balance(address.1.as_str(), false) } else { let param = GetTokenBalance20Param { contract_address: Web3TokenType::Eth @@ -57,7 +57,7 @@ pub fn get_balance( address: address.1.clone(), block_number: "latest".into(), }; - client.get_token_balance_20(¶m) + client.get_token_balance_20(¶m, false) }; match result { diff --git a/tee-worker/litentry/core/service/src/web3_token/token_balance/lit_balance.rs b/tee-worker/litentry/core/service/src/web3_token/token_balance/lit_balance.rs index 3dd70bab55..fd43092991 100644 --- a/tee-worker/litentry/core/service/src/web3_token/token_balance/lit_balance.rs +++ b/tee-worker/litentry/core/service/src/web3_token/token_balance/lit_balance.rs @@ -58,7 +58,7 @@ pub fn get_balance( if let Some(mut client) = network.create_nodereal_jsonrpc_client(data_provider_config) { - match client.get_token_balance_20(¶m) { + match client.get_token_balance_20(¶m, false) { Ok(balance) => { total_balance += calculate_balance_with_decimals(balance, decimals); }, diff --git a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs index dc9c355e85..88bc40efd5 100644 --- a/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs +++ b/tee-worker/litentry/core/stf-task/receiver/src/handler/assertion.rs @@ -25,6 +25,7 @@ use itp_stf_executor::traits::StfEnclaveSigning; use itp_stf_state_handler::handle_state::HandleState; use itp_top_pool_author::traits::AuthorApi; use itp_types::ShardIdentifier; +use lc_credentials::credential_schema; use lc_data_providers::DataProviderConfig; use lc_stf_task_sender::AssertionBuildRequest; use litentry_primitives::{ @@ -65,192 +66,7 @@ where fn on_process(&self) -> Result { // create the initial credential // TODO: maybe we can further simplify this - let mut credential = match self.req.assertion.clone() { - Assertion::A1 => { - #[cfg(test)] - { - std::thread::sleep(core::time::Duration::from_secs(5)); - } - lc_assertion_build::a1::build(&self.req) - }, - Assertion::A2(guild_id) => lc_assertion_build::a2::build( - &self.req, - guild_id, - &self.context.data_provider_config, - ), - - Assertion::A3(guild_id, channel_id, role_id) => lc_assertion_build::a3::build( - &self.req, - guild_id, - channel_id, - role_id, - &self.context.data_provider_config, - ), - - Assertion::A4(min_balance) => build_holding_time( - &self.req, - AmountHoldingTimeType::LIT, - min_balance, - &self.context.data_provider_config, - ), - - Assertion::A6 => - lc_assertion_build::a6::build(&self.req, &self.context.data_provider_config), - - Assertion::A7(min_balance) => build_holding_time( - &self.req, - AmountHoldingTimeType::DOT, - min_balance, - &self.context.data_provider_config, - ), - - // no need to pass `networks` again because it's the same as the `get_supported_web3networks` - Assertion::A8(_networks) => - lc_assertion_build::a8::build(&self.req, &self.context.data_provider_config), - - Assertion::A10(min_balance) => build_holding_time( - &self.req, - AmountHoldingTimeType::WBTC, - min_balance, - &self.context.data_provider_config, - ), - - Assertion::A11(min_balance) => build_holding_time( - &self.req, - AmountHoldingTimeType::ETH, - min_balance, - &self.context.data_provider_config, - ), - - Assertion::A13(owner) => - lc_assertion_build::a13::build(&self.req, self.context.ocall_api.clone(), &owner), - - Assertion::A14 => - lc_assertion_build::a14::build(&self.req, &self.context.data_provider_config), - - Assertion::Achainable(param) => lc_assertion_build::achainable::build( - &self.req, - param, - &self.context.data_provider_config, - ), - - Assertion::A20 => lc_assertion_build::a20::build(&self.req), - - Assertion::Oneblock(course_type) => lc_assertion_build::oneblock::course::build( - &self.req, - course_type, - &self.context.data_provider_config, - ), - - Assertion::GenericDiscordRole(role_type) => - lc_assertion_build::generic_discord_role::build( - &self.req, - role_type, - &self.context.data_provider_config, - ), - - Assertion::BnbDomainHolding => - lc_assertion_build::nodereal::bnb_domain::bnb_domain_holding_amount::build( - &self.req, - &self.context.data_provider_config, - ), - - Assertion::BnbDigitDomainClub(digit_domain_type) => - lc_assertion_build::nodereal::bnb_domain::bnb_digit_domain_club_amount::build( - &self.req, - digit_domain_type, - &self.context.data_provider_config, - ), - - Assertion::VIP3MembershipCard(level) => lc_assertion_build::vip3::card::build( - &self.req, - level, - &self.context.data_provider_config, - ), - - Assertion::WeirdoGhostGangHolder => - lc_assertion_build::nodereal::nft_holder::weirdo_ghost_gang_holder::build( - &self.req, - &self.context.data_provider_config, - ), - - Assertion::LITStaking => lc_assertion_build::lit_staking::build(&self.req), - - Assertion::EVMAmountHolding(token_type) => - lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( - &self.req, - token_type, - &self.context.data_provider_config, - ), - - Assertion::BRC20AmountHolder => lc_assertion_build::brc20::amount_holder::build( - &self.req, - &self.context.data_provider_config, - ), - - Assertion::CryptoSummary => lc_assertion_build::nodereal::crypto_summary::build( - &self.req, - &self.context.data_provider_config, - ), - - Assertion::TokenHoldingAmount(token_type) => - lc_assertion_build_v2::token_holding_amount::build( - &self.req, - token_type, - &self.context.data_provider_config, - ), - }?; - - // post-process the credential - let signer = self.context.enclave_signer.as_ref(); - let enclave_account = signer.get_enclave_account().map_err(|e| { - VCMPError::RequestVCFailed( - self.req.assertion.clone(), - ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), - ) - })?; - - credential.parachain_block_number = self.req.parachain_block_number; - credential.sidechain_block_number = self.req.sidechain_block_number; - - credential.credential_subject.endpoint = - self.context.data_provider_config.credential_endpoint.to_string(); - - credential.credential_subject.assertion_text = format!("{:?}", self.req.assertion); - - credential.issuer.id = - Identity::Substrate(enclave_account.into()).to_did().map_err(|e| { - VCMPError::RequestVCFailed( - self.req.assertion.clone(), - ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), - ) - })?; - - let json_string = credential.to_json().map_err(|_| { - VCMPError::RequestVCFailed(self.req.assertion.clone(), ErrorDetail::ParseError) - })?; - let payload = json_string.as_bytes(); - let (enclave_account, sig) = signer.sign(payload).map_err(|e| { - VCMPError::RequestVCFailed( - self.req.assertion.clone(), - ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), - ) - })?; - debug!("Credential Payload signature: {:?}", sig); - - credential.add_proof(&sig, &enclave_account); - credential.validate().map_err(|e| { - VCMPError::RequestVCFailed( - self.req.assertion.clone(), - ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), - ) - })?; - - let credential_str = credential.to_json().map_err(|_| { - VCMPError::RequestVCFailed(self.req.assertion.clone(), ErrorDetail::ParseError) - })?; - debug!("Credential: {}, length: {}", credential_str, credential_str.len()); - Ok(credential_str.as_bytes().to_vec()) + create_credential_str(&self.req, &self.context) } fn on_success( @@ -310,3 +126,200 @@ fn build_holding_time( ) -> Result { lc_assertion_build::holding_time::build(req, htype, min_balance, data_provider_config) } + +pub fn create_credential_str< + ShieldingKeyRepository, + A: AuthorApi, + S: StfEnclaveSigning, + H: HandleState, + O: EnclaveOnChainOCallApi, +>( + req: &AssertionBuildRequest, + context: &Arc>, +) -> Result, VCMPError> +where + ShieldingKeyRepository: AccessKey, + ::KeyType: ShieldingCryptoEncrypt + 'static, +{ + let mut credential = match req.assertion.clone() { + Assertion::A1 => { + #[cfg(test)] + { + std::thread::sleep(core::time::Duration::from_secs(5)); + } + lc_assertion_build::a1::build(req) + }, + Assertion::A2(guild_id) => + lc_assertion_build::a2::build(req, guild_id, &context.data_provider_config), + + Assertion::A3(guild_id, channel_id, role_id) => lc_assertion_build::a3::build( + req, + guild_id, + channel_id, + role_id, + &context.data_provider_config, + ), + + Assertion::A4(min_balance) => build_holding_time( + req, + AmountHoldingTimeType::LIT, + min_balance, + &context.data_provider_config, + ), + + Assertion::A6 => lc_assertion_build::a6::build(req, &context.data_provider_config), + + Assertion::A7(min_balance) => build_holding_time( + req, + AmountHoldingTimeType::DOT, + min_balance, + &context.data_provider_config, + ), + + // no need to pass `networks` again because it's the same as the `get_supported_web3networks` + Assertion::A8(_networks) => + lc_assertion_build::a8::build(req, &context.data_provider_config), + + Assertion::A10(min_balance) => build_holding_time( + req, + AmountHoldingTimeType::WBTC, + min_balance, + &context.data_provider_config, + ), + + Assertion::A11(min_balance) => build_holding_time( + req, + AmountHoldingTimeType::ETH, + min_balance, + &context.data_provider_config, + ), + + Assertion::A13(owner) => + lc_assertion_build::a13::build(req, context.ocall_api.clone(), &owner), + + Assertion::A14 => lc_assertion_build::a14::build(req, &context.data_provider_config), + + Assertion::Achainable(param) => + lc_assertion_build::achainable::build(req, param, &context.data_provider_config), + + Assertion::A20 => lc_assertion_build::a20::build(req, &context.data_provider_config), + + Assertion::OneBlock(course_type) => lc_assertion_build::oneblock::course::build( + req, + course_type, + &context.data_provider_config, + ), + + Assertion::GenericDiscordRole(role_type) => + lc_assertion_build::generic_discord_role::build( + req, + role_type, + &context.data_provider_config, + ), + + Assertion::BnbDomainHolding => + lc_assertion_build::nodereal::bnb_domain::bnb_domain_holding_amount::build( + req, + &context.data_provider_config, + ), + + Assertion::BnbDigitDomainClub(digit_domain_type) => + lc_assertion_build::nodereal::bnb_domain::bnb_digit_domain_club_amount::build( + req, + digit_domain_type, + &context.data_provider_config, + ), + + Assertion::VIP3MembershipCard(level) => + lc_assertion_build::vip3::card::build(req, level, &context.data_provider_config), + + Assertion::WeirdoGhostGangHolder => + lc_assertion_build::nodereal::nft_holder::weirdo_ghost_gang_holder::build( + req, + &context.data_provider_config, + ), + + Assertion::LITStaking => lc_assertion_build::lit_staking::build(req), + + Assertion::EVMAmountHolding(token_type) => + lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( + req, + token_type, + &context.data_provider_config, + ), + + Assertion::BRC20AmountHolder => + lc_assertion_build::brc20::amount_holder::build(req, &context.data_provider_config), + + Assertion::CryptoSummary => + lc_assertion_build::nodereal::crypto_summary::build(req, &context.data_provider_config), + + Assertion::TokenHoldingAmount(token_type) => + lc_assertion_build_v2::token_holding_amount::build( + req, + token_type, + &context.data_provider_config, + ), + + Assertion::PlatformUser(platform_user_type) => lc_assertion_build_v2::platform_user::build( + req, + platform_user_type, + &context.data_provider_config, + ), + + Assertion::NftHolder(nft_type) => + lc_assertion_build_v2::nft_holder::build(req, nft_type, &context.data_provider_config), + }?; + + // post-process the credential + let signer = context.enclave_signer.as_ref(); + let enclave_account = signer.get_enclave_account().map_err(|e| { + VCMPError::RequestVCFailed( + req.assertion.clone(), + ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), + ) + })?; + + credential.parachain_block_number = req.parachain_block_number; + credential.sidechain_block_number = req.sidechain_block_number; + + credential.credential_subject.endpoint = + context.data_provider_config.credential_endpoint.to_string(); + + credential.credential_subject.assertion_text = format!("{:?}", req.assertion); + + credential.credential_schema.id = credential_schema::get_schema_url(&req.assertion); + + credential.issuer.id = Identity::Substrate(enclave_account.into()).to_did().map_err(|e| { + VCMPError::RequestVCFailed( + req.assertion.clone(), + ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), + ) + })?; + + let json_string = credential + .to_json() + .map_err(|_| VCMPError::RequestVCFailed(req.assertion.clone(), ErrorDetail::ParseError))?; + let payload = json_string.as_bytes(); + let (enclave_account, sig) = signer.sign(payload).map_err(|e| { + VCMPError::RequestVCFailed( + req.assertion.clone(), + ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), + ) + })?; + debug!("Credential Payload signature: {:?}", sig); + + credential.add_proof(&sig, &enclave_account); + credential.validate().map_err(|e| { + VCMPError::RequestVCFailed( + req.assertion.clone(), + ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), + ) + })?; + + let credential_str = credential + .to_json() + .map_err(|_| VCMPError::RequestVCFailed(req.assertion.clone(), ErrorDetail::ParseError))?; + debug!("Credential: {}, length: {}", credential_str, credential_str.len()); + Ok(credential_str.as_bytes().to_vec()) +} diff --git a/tee-worker/litentry/core/stf-task/receiver/src/test.rs b/tee-worker/litentry/core/stf-task/receiver/src/test.rs index 61a9048590..1e55e37c90 100644 --- a/tee-worker/litentry/core/stf-task/receiver/src/test.rs +++ b/tee-worker/litentry/core/stf-task/receiver/src/test.rs @@ -21,7 +21,7 @@ fn test_threadpool_behaviour() { let stf_enclave_signer_mock = StfEnclaveSignerMock::default(); let handle_state_mock = HandleStateMock::default(); let onchain_mock = OnchainMock::default(); - let data_provider_conifg = DataProviderConfig::new(); + let data_provider_conifg = DataProviderConfig::new().unwrap(); let context = StfTaskContext::new( Arc::new(shielding_key_repository_mock), author_mock.into(), diff --git a/tee-worker/litentry/core/teebag-storage/Cargo.toml b/tee-worker/litentry/core/teebag-storage/Cargo.toml new file mode 100644 index 0000000000..c68b9e0d5e --- /dev/null +++ b/tee-worker/litentry/core/teebag-storage/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "lc-teebag-storage" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition = "2021" + +[dependencies] +itp-storage = { path = "../../../core-primitives/storage", default-features = false } +itp-types = { path = "../../../core-primitives/types", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", default-features = false } + +[features] +default = ["std"] +std = [ + "sp-std/std", + "itp-storage/std", + "itp-types/std", +] diff --git a/tee-worker/litentry/core/teebag-storage/src/lib.rs b/tee-worker/litentry/core/teebag-storage/src/lib.rs new file mode 100644 index 0000000000..3f931d9f7e --- /dev/null +++ b/tee-worker/litentry/core/teebag-storage/src/lib.rs @@ -0,0 +1,48 @@ +// Copyright 2020-2024 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use itp_storage::{storage_map_key, StorageHasher}; +use itp_types::WorkerType; +use sp_std::prelude::Vec; + +pub struct TeebagStorage; + +pub trait StoragePrefix { + fn prefix() -> &'static str; +} + +impl StoragePrefix for TeebagStorage { + fn prefix() -> &'static str { + "Teebag" + } +} + +pub trait TeebagStorageKeys { + fn enclave_identifier(worker_type: WorkerType) -> Vec; +} + +impl TeebagStorageKeys for S { + fn enclave_identifier(worker_type: WorkerType) -> Vec { + storage_map_key( + Self::prefix(), + "EnclaveIdentifier", + &worker_type, + &StorageHasher::Blake2_128Concat, + ) + } +} diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs index 0c48bda55f..91901c4e91 100644 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs +++ b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/lib.rs @@ -16,7 +16,6 @@ compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the sam #[cfg(all(not(feature = "std"), feature = "sgx"))] pub use crate::sgx_reexport_prelude::*; -use crate::vc_handling::VCRequestHandler; use codec::{Decode, Encode}; use frame_support::{ensure, sp_runtime::traits::One}; use ita_sgx_runtime::{pallet_imt::get_eligible_identities, BlockNumber, Hash, Runtime}; @@ -26,6 +25,7 @@ use ita_stf::{ aes_encrypt_default, helpers::ensure_self, trusted_call_result::RequestVCResult, Getter, OpaqueCall, TrustedCall, TrustedCallSigned, TrustedCallVerification, TrustedOperation, H256, }; +use itp_enclave_metrics::EnclaveMetric; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::metadata::{ pallet_vcmp::VCMPCallIndexes, provider::AccessNodeMetadata, NodeMetadataTrait, @@ -40,9 +40,9 @@ use itp_top_pool_author::traits::AuthorApi; use itp_types::{ parentchain::ParentchainId, AccountId, BlockNumber as SidechainBlockNumber, ShardIdentifier, }; -use lc_stf_task_receiver::StfTaskContext; +use lc_stf_task_receiver::{handler::assertion::create_credential_str, StfTaskContext}; use lc_stf_task_sender::AssertionBuildRequest; -use lc_vc_task_sender::init_vc_task_sender_storage; +use lc_vc_task_sender::{init_vc_task_sender_storage, VCResponse}; use litentry_macros::if_production_or; use litentry_primitives::{ AesRequest, Assertion, DecryptableRequest, Identity, ParentchainBlockNumber, @@ -59,12 +59,11 @@ use std::{ Arc, }, thread, + time::Instant, vec::Vec, }; use threadpool::ThreadPool; -mod vc_handling; - pub fn run_vc_handler_runner( context: Arc>, extrinsic_factory: Arc, @@ -107,15 +106,27 @@ pub fn run_vc_handler_runner( let sender_pool = sender.clone(); pool.execute(move || { - if let Err(e) = req.sender.send(handle_request( + let response = handle_request( &mut req.request, - context_pool, + context_pool.clone(), extrinsic_factory_pool, node_metadata_repo_pool, sender_pool, - )) { + ); + if let Err(e) = req.sender.send(response.clone()) { warn!("Unable to submit response back to the handler: {:?}", e); } + if response.is_err() { + if let Err(e) = + context_pool.ocall_api.update_metric(EnclaveMetric::FailedVCIssuance) + { + warn!("Failed to update metric for VC Issuance: {:?}", e); + } + } else if let Err(e) = + context_pool.ocall_api.update_metric(EnclaveMetric::SuccessfullVCIssuance) + { + warn!("Failed to update metric for VC Issuance: {:?}", e); + } }); } @@ -143,6 +154,7 @@ where N: AccessNodeMetadata + Send + Sync + 'static, N::MetadataType: NodeMetadataTrait, { + let start_time = Instant::now(); let enclave_shielding_key = context .shielding_key .retrieve_key() @@ -278,10 +290,9 @@ where req_ext_hash, }; - let vc_request_handler = VCRequestHandler { req, context: context.clone() }; - let res = vc_request_handler - .process() + let credential_str = create_credential_str(&req, &context) .map_err(|e| format!("Failed to build assertion due to: {:?}", e))?; + let res = VCResponse { vc_payload: credential_str }; let call_index = node_metadata_repo .get_from_metadata(|m| m.vc_issued_call_indexes()) @@ -292,7 +303,7 @@ where let call = OpaqueCall::from_tuple(&( call_index, who.clone(), - assertion, + assertion.clone(), id_graph_hash, req_ext_hash, )); @@ -325,6 +336,13 @@ where .send_to_parentchain(xt, &ParentchainId::Litentry, false) .map_err(|e| format!("Unable to send extrinsic to parentchain: {:?}", e))?; + if let Err(e) = context.ocall_api.update_metric(EnclaveMetric::VCBuildTime( + format!("{:?}", assertion), + start_time.elapsed(), + )) { + warn!("Failed to update metric for vc build time: {:?}", e); + } + Ok(res.encode()) } else { Err("Expect request_vc trusted call".to_string()) diff --git a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs b/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs deleted file mode 100644 index d21759f4a9..0000000000 --- a/tee-worker/litentry/core/vc-issuance/lc-vc-task-receiver/src/vc_handling.rs +++ /dev/null @@ -1,235 +0,0 @@ -#![allow(clippy::result_large_err)] - -use crate::{Getter, TrustedCallSigned}; -use ita_sgx_runtime::Hash; -pub use ita_stf::aes_encrypt_default; -use itp_ocall_api::EnclaveOnChainOCallApi; -use itp_sgx_crypto::{key_repository::AccessKey, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}; -use itp_sgx_externalities::SgxExternalitiesTrait; -use itp_stf_executor::traits::StfEnclaveSigning; -use itp_stf_state_handler::handle_state::HandleState; -use itp_top_pool_author::traits::AuthorApi; -use lc_data_providers::DataProviderConfig; -use lc_stf_task_receiver::StfTaskContext; -use lc_stf_task_sender::AssertionBuildRequest; -use lc_vc_task_sender::VCResponse; -use litentry_primitives::{ - AmountHoldingTimeType, Assertion, ErrorDetail, ErrorString, Identity, ParameterString, - VCMPError, -}; -use std::{format, string::ToString, sync::Arc}; - -pub(crate) struct VCRequestHandler< - ShieldingKeyRepository, - A: AuthorApi, - S: StfEnclaveSigning, - H: HandleState, - O: EnclaveOnChainOCallApi, -> where - ShieldingKeyRepository: AccessKey, - ::KeyType: - ShieldingCryptoDecrypt + ShieldingCryptoEncrypt + 'static, -{ - pub(crate) req: AssertionBuildRequest, - pub(crate) context: Arc>, -} - -impl VCRequestHandler -where - ShieldingKeyRepository: AccessKey, - ::KeyType: - ShieldingCryptoDecrypt + ShieldingCryptoEncrypt + 'static, - A: AuthorApi, - S: StfEnclaveSigning, - H: HandleState, - H::StateT: SgxExternalitiesTrait, - O: EnclaveOnChainOCallApi, -{ - pub fn process(self) -> Result { - let mut credential = match self.req.assertion.clone() { - Assertion::A1 => lc_assertion_build::a1::build(&self.req), - - Assertion::A2(guild_id) => lc_assertion_build::a2::build( - &self.req, - guild_id, - &self.context.data_provider_config, - ), - - Assertion::A3(guild_id, channel_id, role_id) => lc_assertion_build::a3::build( - &self.req, - guild_id, - channel_id, - role_id, - &self.context.data_provider_config, - ), - - Assertion::A4(min_balance) => build_holding_time( - &self.req, - AmountHoldingTimeType::LIT, - min_balance, - &self.context.data_provider_config, - ), - - Assertion::A6 => - lc_assertion_build::a6::build(&self.req, &self.context.data_provider_config), - - Assertion::A7(min_balance) => build_holding_time( - &self.req, - AmountHoldingTimeType::DOT, - min_balance, - &self.context.data_provider_config, - ), - - // no need to pass `networks` again because it's the same as the `get_supported_web3networks` - Assertion::A8(_networks) => - lc_assertion_build::a8::build(&self.req, &self.context.data_provider_config), - - Assertion::A10(min_balance) => build_holding_time( - &self.req, - AmountHoldingTimeType::WBTC, - min_balance, - &self.context.data_provider_config, - ), - - Assertion::A11(min_balance) => build_holding_time( - &self.req, - AmountHoldingTimeType::ETH, - min_balance, - &self.context.data_provider_config, - ), - - Assertion::A13(owner) => - lc_assertion_build::a13::build(&self.req, self.context.ocall_api.clone(), &owner), - - Assertion::A14 => - lc_assertion_build::a14::build(&self.req, &self.context.data_provider_config), - - Assertion::Achainable(param) => lc_assertion_build::achainable::build( - &self.req, - param, - &self.context.data_provider_config, - ), - - Assertion::A20 => lc_assertion_build::a20::build(&self.req), - - Assertion::Oneblock(course_type) => lc_assertion_build::oneblock::course::build( - &self.req, - course_type, - &self.context.data_provider_config, - ), - - Assertion::GenericDiscordRole(role_type) => - lc_assertion_build::generic_discord_role::build( - &self.req, - role_type, - &self.context.data_provider_config, - ), - - Assertion::BnbDomainHolding => - lc_assertion_build::nodereal::bnb_domain::bnb_domain_holding_amount::build( - &self.req, - &self.context.data_provider_config, - ), - - Assertion::BnbDigitDomainClub(digit_domain_type) => - lc_assertion_build::nodereal::bnb_domain::bnb_digit_domain_club_amount::build( - &self.req, - digit_domain_type, - &self.context.data_provider_config, - ), - - Assertion::VIP3MembershipCard(level) => lc_assertion_build::vip3::card::build( - &self.req, - level, - &self.context.data_provider_config, - ), - - Assertion::WeirdoGhostGangHolder => - lc_assertion_build::nodereal::nft_holder::weirdo_ghost_gang_holder::build( - &self.req, - &self.context.data_provider_config, - ), - - Assertion::LITStaking => lc_assertion_build::lit_staking::build(&self.req), - - Assertion::EVMAmountHolding(token_type) => - lc_assertion_build::nodereal::amount_holding::evm_amount_holding::build( - &self.req, - token_type, - &self.context.data_provider_config, - ), - - Assertion::BRC20AmountHolder => lc_assertion_build::brc20::amount_holder::build( - &self.req, - &self.context.data_provider_config, - ), - - Assertion::CryptoSummary => lc_assertion_build::nodereal::crypto_summary::build( - &self.req, - &self.context.data_provider_config, - ), - - Assertion::TokenHoldingAmount(token_type) => - lc_assertion_build_v2::token_holding_amount::build( - &self.req, - token_type, - &self.context.data_provider_config, - ), - }?; - - // post-process the credential - let signer = self.context.enclave_signer.as_ref(); - let enclave_account = signer.get_enclave_account().map_err(|e| { - VCMPError::RequestVCFailed( - self.req.assertion.clone(), - ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), - ) - })?; - - credential.credential_subject.endpoint = - self.context.data_provider_config.credential_endpoint.to_string(); - - credential.issuer.id = - Identity::Substrate(enclave_account.into()).to_did().map_err(|e| { - VCMPError::RequestVCFailed( - self.req.assertion.clone(), - ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), - ) - })?; - let json_string = credential.to_json().map_err(|_| { - VCMPError::RequestVCFailed(self.req.assertion.clone(), ErrorDetail::ParseError) - })?; - let payload = json_string.as_bytes(); - let (enclave_account, sig) = signer.sign(payload).map_err(|e| { - VCMPError::RequestVCFailed( - self.req.assertion.clone(), - ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), - ) - })?; - - credential.add_proof(&sig, &enclave_account); - credential.validate().map_err(|e| { - VCMPError::RequestVCFailed( - self.req.assertion.clone(), - ErrorDetail::StfError(ErrorString::truncate_from(format!("{e:?}").into())), - ) - })?; - - let credential_str = credential.to_json().map_err(|_| { - VCMPError::RequestVCFailed(self.req.assertion.clone(), ErrorDetail::ParseError) - })?; - - let vc_response = VCResponse { vc_payload: credential_str.as_bytes().to_vec() }; - - Ok(vc_response) - } -} - -fn build_holding_time( - req: &AssertionBuildRequest, - htype: AmountHoldingTimeType, - min_balance: ParameterString, - data_provider_config: &DataProviderConfig, -) -> Result { - lc_assertion_build::holding_time::build(req, htype, min_balance, data_provider_config) -} diff --git a/tee-worker/litentry/primitives/Cargo.toml b/tee-worker/litentry/primitives/Cargo.toml index 076b5aab29..14c1d6da3e 100644 --- a/tee-worker/litentry/primitives/Cargo.toml +++ b/tee-worker/litentry/primitives/Cargo.toml @@ -31,8 +31,8 @@ sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "m itp-sgx-crypto = { path = "../../core-primitives/sgx/crypto", default-features = false } itp-utils = { path = "../../core-primitives/utils", default-features = false } litentry-hex-utils = { path = "../../../primitives/hex", default-features = false } +pallet-teebag = { path = "../../../pallets/teebag", default-features = false } parentchain-primitives = { package = "core-primitives", path = "../../../primitives/core", default-features = false } -teerex-primitives = { path = "../../../primitives/teerex", default-features = false } [dev-dependencies] base64 = { version = "0.13", features = ["alloc"] } @@ -59,7 +59,7 @@ std = [ "sp-runtime/std", "ring/std", "parentchain-primitives/std", - "teerex-primitives/std", + "pallet-teebag/std", "rand", "log/std", "bitcoin/std", diff --git a/tee-worker/litentry/primitives/src/aes_request.rs b/tee-worker/litentry/primitives/src/aes_request.rs index 998d642837..e15c88e40b 100644 --- a/tee-worker/litentry/primitives/src/aes_request.rs +++ b/tee-worker/litentry/primitives/src/aes_request.rs @@ -17,7 +17,7 @@ #[cfg(all(not(feature = "std"), feature = "sgx"))] extern crate sgx_tstd as std; -/// A morphling of itp_types::RsaRequest which stems from teerex_primitives::RsaRequest +/// A morphling of itp_types::RsaRequest which stems from teebag::RsaRequest /// /// Instead of encrypting the TrustedCallSigned with the TEE's shielding key, we encrypt /// it with a 32-byte ephemeral AES key which is generated from the client's side, and diff --git a/tee-worker/litentry/primitives/src/lib.rs b/tee-worker/litentry/primitives/src/lib.rs index ef643d7c19..b9310fb34d 100644 --- a/tee-worker/litentry/primitives/src/lib.rs +++ b/tee-worker/litentry/primitives/src/lib.rs @@ -43,6 +43,10 @@ use codec::{Decode, Encode, MaxEncodedLen}; use itp_sgx_crypto::ShieldingCryptoDecrypt; use litentry_hex_utils::hex_encode; use log::error; +pub use pallet_teebag::{ + decl_rsa_request, extract_tcb_info_from_raw_dcap_quote, AttestationType, Enclave, + EnclaveFingerprint, MrEnclave, ShardIdentifier, SidechainBlockNumber, WorkerMode, WorkerType, +}; pub use parentchain_primitives::{ all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks, all_web3networks, identity::*, AccountId as ParentchainAccountId, AchainableAmount, AchainableAmountHolding, @@ -53,8 +57,9 @@ pub use parentchain_primitives::{ BoundedWeb3Network, ContestType, EVMTokenType, ErrorDetail, ErrorString, GenericDiscordRoleType, Hash as ParentchainHash, Header as ParentchainHeader, IMPError, Index as ParentchainIndex, IntoErrorDetail, OneBlockCourseType, ParameterString, - SchemaContentString, SchemaIdString, Signature as ParentchainSignature, SoraQuizType, - VCMPError, VIP3MembershipCardLevel, Web3Network, Web3TokenType, MINUTES, + PlatformUserType, SchemaContentString, SchemaIdString, Signature as ParentchainSignature, + SoraQuizType, VCMPError, VIP3MembershipCardLevel, Web3Network, Web3NftType, Web3TokenType, + MINUTES, }; use scale_info::TypeInfo; use sp_core::{ecdsa, ed25519, sr25519, ByteArray}; @@ -64,7 +69,6 @@ use sp_io::{ }; use sp_runtime::traits::Verify; use std::string::{String, ToString}; -pub use teerex_primitives::{decl_rsa_request, ShardIdentifier, SidechainBlockNumber}; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; diff --git a/tee-worker/local-setup/.env.dev b/tee-worker/local-setup/.env.dev index 7c9cf8f7bb..5f9c5dbec7 100644 --- a/tee-worker/local-setup/.env.dev +++ b/tee-worker/local-setup/.env.dev @@ -30,23 +30,25 @@ DISCORD_AUTH_TOKEN= ACHAINABLE_AUTH_KEY= ONEBLOCK_NOTION_KEY= NODEREAL_API_KEY= -GENIIDATA_API_KEY=142cf1b0-1ca7-11ee-bb5e-9d74c2e854ac +GENIIDATA_API_KEY= +MORALIS_API_KEY= # The followings are default value. # Can be skipped; or overwrite within non-production mode. -TWITTER_OFFICIAL_URL=https://api.twitter.com -TWITTER_LITENTRY_URL=http://localhost:19527 -DISCORD_OFFICIAL_URL=https://discordapp.com -DISCORD_LITENTRY_URL=http://localhost:19527 -ACHAINABLE_URL=https://label-production.graph.tdf-labs.io/ -CREDENTIAL_ENDPOINT=wss://rpc.rococo-parachain.litentry.io -ONEBLOCK_NOTION_URL=https://api.notion.com/v1/blocks/e4068e6a326243468f35dcdc0c43f686/children -SORA_QUIZ_MASTER_ID=1164463721989554218 -SORA_QUIZ_ATTENDEE_ID=1166941149219532800 -NODEREAL_API_URL=https://open-platform.nodereal.io/ +TWITTER_OFFICIAL_URL=http://localhost:19527 +DISCORD_OFFICIAL_URL=http://localhost:19527 +LITENTRY_DISCORD_MICROSERVICE_URL=http://localhost:19527 +ACHAINABLE_URL=http://localhost:19527 +CREDENTIAL_ENDPOINT=http://localhost:9933 +ONEBLOCK_NOTION_URL=https://abc.com +SORA_QUIZ_MASTER_ID=SORA_QUIZ_MASTER_ID +SORA_QUIZ_ATTENDEE_ID=SORA_QUIZ_ATTENDEE_ID +NODEREAL_API_URL=http://localhost:19527 NODEREAL_API_CHAIN_NETWORK_URL=https://{chain}-mainnet.nodereal.io/ -CONTEST_LEGEND_DISCORD_ROLE_ID=1172576273063739462 -CONTEST_POPULARITY_DISCORD_ROLE_ID=1172576681119195208 -CONTEST_PARTICIPANT_DISCORD_ROLE_ID=1172576734135210104 -VIP3_URL=https://dappapi.vip3.io/ -GENIIDATA_URL=https://api.geniidata.com/api/1/brc20/balance? \ No newline at end of file +CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID +CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID +CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID +VIP3_URL=http://localhost:19527 +GENIIDATA_URL=https://api.geniidata.com/api/1/brc20/balance? +LITENTRY_ARCHIVE_URL=http://localhost:19527 +MORALIS_API_URL=https://deep-index.moralis.io/api/v2.2/ diff --git a/tee-worker/local-setup/launch.py b/tee-worker/local-setup/launch.py index 3c15bd1e46..d89694e33e 100755 --- a/tee-worker/local-setup/launch.py +++ b/tee-worker/local-setup/launch.py @@ -12,6 +12,7 @@ import signal from subprocess import Popen, PIPE, STDOUT, run import os +import shutil import sys from time import sleep from typing import Union, IO @@ -156,10 +157,16 @@ def offset_port(offset): def setup_environment(offset, config, parachain_dir): - load_dotenv("./local-setup/.env.dev") + if not os.path.isfile("./local-setup/.env"): + shutil.copy("./local-setup/.env.dev", "./local-setup/.env") + + load_dotenv("./local-setup/.env") offset_port(offset) check_all_ports_and_reallocate() - generate_config_local_json(parachain_dir) + + if parachain_dir != "": + generate_config_local_json(parachain_dir) + generate_env_local() # TODO: only works for single worker for now @@ -219,6 +226,7 @@ def main(processes, config_path, parachain_type, log_config_path, offset, parach setup_environment(offset, config, parachain_dir) run(["../scripts/launch-local-binary.sh", "rococo"], check=True) elif parachain_type == "remote": + setup_environment(offset, config, "") print("Litentry parachain should be started remotely") else: sys.exit("Unsupported parachain_type") diff --git a/tee-worker/scripts/litentry/release/config.json.eg b/tee-worker/scripts/litentry/release/config.json.eg deleted file mode 100644 index acfdbc872a..0000000000 --- a/tee-worker/scripts/litentry/release/config.json.eg +++ /dev/null @@ -1,11 +0,0 @@ -{ - "twitter_official_url": "https://api.twitter.com", - "twitter_litentry_url": "", - "twitter_auth_token_v2": "abcdefghijklmnopqrstuvwxyz", - "discord_official_url": "https://discordapp.com", - "discord_litentry_url": "", - "discord_auth_token": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "achainable_url": "https://graph.tdf-labs.io/", - "achainable_auth_key": "88888888-4444-4444-4444-1234567890ab", - "credential_endpoint": "" -} \ No newline at end of file diff --git a/tee-worker/scripts/litentry/release/deploy.sh b/tee-worker/scripts/litentry/release/deploy.sh deleted file mode 100755 index 72c7060dfa..0000000000 --- a/tee-worker/scripts/litentry/release/deploy.sh +++ /dev/null @@ -1,555 +0,0 @@ -#!/bin/bash - -set -eo pipefail - -# This script is used to perform actions on the target host, including: -# - generate: generate the systemd service files from the template -# - restart: restart the parachain, or the worker, or both -# - upgrade-worker: uprade the worker0 to the rev in local repo -# -# TODO: -# the combinations of flags are not yet well verified/organised, especially the following: -# --only-worker -# --build -# --discard - -# ------------------------------ -# path setting -# ------------------------------ - -ROOTDIR=$(git rev-parse --show-toplevel) -BASEDIR=/opt/litentry -PARACHAIN_BASEDIR="$BASEDIR/parachain" -WORKER_BASEDIR="$BASEDIR/worker" -BACKUP_BASEDIR="$BASEDIR/backup" -LOG_BACKUP_BASEDIR="$BACKUP_BASEDIR/log" -WORKER_BACKUP_BASEDIR="$BACKUP_BASEDIR/worker" -RELAYCHAIN_ALICE_BASEDIR="$PARACHAIN_BASEDIR/relay-alice" -RELAYCHAIN_BOB_BASEDIR="$PARACHAIN_BASEDIR/relay-bob" -PARACHAIN_ALICE_BASEDIR="$PARACHAIN_BASEDIR/para-alice" - -# ------------------------------ -# default arg setting -# ------------------------------ - -BUILD=false -DISCARD=false -WORKER_CONFIG= -CHAIN=rococo -ONLY_WORKER=false -PARACHAIN_HOST=localhost -PARACHAIN_PORT=9944 -DOCKER_IMAGE=litentry/litentry-parachain:tee-prod -COPY_FROM_DOCKER=false -PRODUCTION=false -ACTION= - -# ------------------------------ -# Some global setting -# ------------------------------ - -WORKER_COUNT= -PARACHAIN_ID= -OLD_MRENCLAVE= -NEW_MRENCLAVE= -OLD_SHARD= -LATEST_FINALIZED_BLOCK= - -SGX_SDK=/opt/intel/sgxsdk -SGX_ENCLAVE_SIGNER=$SGX_SDK/bin/x64/sgx_sign - -# ------------------------------ -# main() -# ------------------------------ - -function main { - # 0/ check if $USER has sudo - if sudo -l -U $USER 2>/dev/null | grep -q 'may run the following'; then - source "$SGX_SDK/environment" - else - echo "$USER doesn't have sudo permission" - exit 1 - fi - - # 1/ create folders if missing - sudo mkdir -p "$BASEDIR" - sudo chown $USER:$GROUPS "$BASEDIR" - for d in "$LOG_BACKUP_BASEDIR" "$WORKER_BACKUP_BASEDIR" "$RELAYCHAIN_ALICE_BASEDIR" "$RELAYCHAIN_BOB_BASEDIR" \ - "$PARACHAIN_ALICE_BASEDIR" "$WORKER_BASEDIR"; do - mkdir -p "$d" - done - - # 2/ parse command lines - echo "Parsing command line ..." - while [ $# -gt 0 ]; do - case "$1" in - -h|--help) - display_help - exit 0 - ;; - -b|--build) - BUILD=true - shift - ;; - -d|--discard) - DISCARD=true - shift - ;; - -c|--config) - WORKER_CONFIG="$(realpath -s $2)" - shift 2 - ;; - -a|--only-worker) - ONLY_WORKER=true - shift - ;; - -x|--chain) - CHAIN="$2" - shift 2 - ;; - -p|--parachain-port) - PARACHAIN_PORT="$2" - shift 2 - ;; - -z|--parachain-host) - PARACHAIN_HOST="$2" - shift 2 - ;; - -v|--copy-from-docker) - COPY_FROM_DOCKER=true - DOCKER_IMAGE="$2" - shift 2 - ;; - --prod) - PRODUCTION=true - shift - ;; - generate|restart|upgrade-worker) - ACTION="$1" - shift - ;; - *) - echo "Error: unknown option or subcommand $1" - display_help - exit 1 - ;; - esac - done - - # 3/ sanity checks - if [ ! -f "$WORKER_CONFIG" ]; then - echo "Worker config not found: $WORKER_CONFIG" - exit 1 - fi - - WORKER_COUNT=$(cat "$WORKER_CONFIG" | jq '.workers | length') - echo "Worker count: $WORKER_COUNT" - - # TODO: check flags conflict, e.g. - # - having `--discard` together with `upgrade-worker` doesn't make sense - # - `upgrade-worker` should ignore the `--only-worker` flag - - # 4/ main business logic - case "$ACTION" in - generate) - backup_services - generate_services - exit - ;; - restart) - backup_logs - backup_workers - stop_services - prune - build - setup_working_dir - if [ "$ONLY_WORKER" = true ]; then - remove_clean_reset - fi - restart_services - exit - ;; - upgrade-worker) - # build the new worker, the code must be under $ROOTDIR/tee-worker already - build_worker - # update the schedule - set_scheduled_enclave - - # wait until sidechain stalls - wait_for_sidechain - backup_workers - stop_worker_services - get_old_mrenclave - # TODO: actually we only need the copy-up - setup_working_dir - migrate_shard - remove_clean_reset - restart_services - exit - ;; - *) - echo "Unknown action: $ACTION" - exit 1 ;; - esac -} - -# ------------------------------ -# helper functions -# ------------------------------ - -function print_divider { - echo "------------------------------------------------------------" -} - -function display_help { - echo "usage: ./deploy.sh [options]" - echo "" - echo "subcommands:" - echo " generate Generate the parachain and worker systemd files" - echo " restart Restart the services" - echo " upgrade-worker Upgrade the worker" - echo "" - echo "options:" - echo " -h, --help Display this help message and exit" - echo " -b, --build Build the parachain and worker binaries (default: false)" - echo " -d, --discard Clean the existing state for parachain and worker (default: false)" - echo " -c, --config Config file for the worker" - echo " -a, --only-worker Start only the worker (default: false)" - echo " -x, --chain Chain type for launching the parachain network (default: rococo)" - echo " -h, --parachain-host Parachain ws URL (default: localhost)" - echo " -p, --parachain-port Parachain ws port (default: 9944)" - echo " -v, --copy-from-docker Copy the parachain binary from a docker image (default: litentry/litentry-parachain:tee-prod)" - echo " --prod Use a prod configuration to build and run the worker (default: false)" - echo "" - echo "examples:" - echo " ./deploy.sh generate --config tmp.json" - echo " ./deploy.sh restart --config tmp.json --discard --build" - echo " ./deploy.sh restart --config tmp.json --only-worker" - echo " ./deploy.sh upgrade-worker --config tmp.json --only-worker" - echo "" - echo "notes:" - echo " - This script requires an OS that supports systemd." - echo " - It is mandatory to provide a JSON config file for the worker." - echo " - jq is required to be installed on the system " - echo "" - echo "For more information or assistance, please contact Litentry parachain team." -} - -# TODO: in fact, this function only backs up the parachain logs -# maybe we want to remove it as it's not so critical anyway -function backup_logs { - echo "Backing up logs ..." - now=$(date +"%Y%m%d-%H%M%S") - outdir="$LOG_BACKUP_BASEDIR/log-$now" - mkdir -p "$outdir" - cp "$PARACHAIN_BASEDIR"/*.log "$outdir" || true - echo "Logs backed up into $outdir" -} - -function backup_workers { - echo "Backing up workers ..." - now=$(date +"%Y%m%d-%H%M%S") - cd "$WORKER_BASEDIR" || exit - for i in $(ls -d * 2>/dev/null); do - outdir="$WORKER_BACKUP_BASEDIR/$i-$now" - cp -rf "$i" "$outdir" - echo "Worker backed up into $outdir" - done -} - -function backup_services { - echo "Backing up services ..." - now=$(date +"%Y%m%d-%H%M%S") - cd /etc/systemd/system || exit - outdir="$WORKER_BACKUP_BASEDIR/service-$now" - mkdir -p "$outdir" - for f in para-alice.service relay-alice.service relay-bob.service $(ls worker*.service 2>/dev/null); do - cp "$f" "$outdir" || true - done -} - -function prune { - if [ "$DISCARD" = true ]; then - echo "Pruning the existing state ..." - rm -rf "$PARACHAIN_BASEDIR"/* - rm -rf "$WORKER_BASEDIR"/* - fi -} - -function generate_services { - echo "Generating systemd service files ..." - cd "$ROOTDIR/tee-worker/scripts/litentry/release" - cp template/* . - sed -i "s/CHAIN/$CHAIN/g" *.service - sed -i "s/USER/$USER/g" *.service - for ((i = 0; i < WORKER_COUNT; i++)); do - cp worker.service worker$i.service - sed -i "s/NUMBER/$i/g" worker$i.service - # populate args - flags=$(cat "$WORKER_CONFIG" | jq -r ".workers[$i].flags[]") - subcommand_flags=$(cat "$WORKER_CONFIG" | jq -r ".workers[$i].subcommand_flags[]") - args= - for flag in $flags; do - args+=" $flag" - done - args+=" run" - for subcommand_flag in $subcommand_flags; do - args+=" $subcommand_flag" - done - sed -i "s;ARGS;$args;" worker$i.service - done - rm worker.service - sudo cp *.service -f /etc/systemd/system/ - rm *.service - sudo systemctl daemon-reload - echo "Done, please check files under /etc/systemd/system/" - echo "Restart the services to take effect" -} - -function build_worker { - echo "Building worker ..." - cd $ROOTDIR/tee-worker/ || exit - if [ "$PRODUCTION" = true ]; then - # we will get an error if SGX_COMMERCIAL_KEY is not set for prod - SGX_PRODUCTION=1 make - else - # use SW mode for dev - SGX_MODE=SW make - fi -} - -# TODO: take github rev into consideration -function build { - if [ "$BUILD" = true ]; then - echo "Building the parachain and worker binaries ..." - - # download polkadot - echo "Downloading polkadot binary ..." - url="https://github.com/paritytech/polkadot/releases/download/v0.9.42/polkadot" - polkadot_bin="$PARACHAIN_BASEDIR/polkadot" - wget -O "$polkadot_bin" -q "$url" - chmod a+x "$polkadot_bin" - if [ ! -s "$polkadot_bin" ]; then - echo "$polkadot_bin is 0 bytes, download URL: $url" && exit 1 - fi - if ! "$polkadot_bin" --version &> /dev/null; then - echo "Cannot execute $polkadot_bin, wrong executable?" && exit 1 - fi - - # pull or build parachain - if [ "$COPY_FROM_DOCKER" = true ]; then - echo "Pulling binary from $DOCKER_IMAGE ..." - docker pull "$DOCKER_IMAGE" - docker cp "$(docker create --rm $DOCKER_IMAGE):/usr/local/bin/litentry-collator" "$PARACHAIN_BASEDIR" - else - echo "Building parachain binary ..." - cd "$ROOTDIR" || exit - if [ "$PRODUCTION" = true ]; then - cargo build --locked --profile production - else - pwd - make build-node - fi - cp "$ROOTDIR/target/release/litentry-collator" "$PARACHAIN_BASEDIR" - fi - chmod a+x "$PARACHAIN_BASEDIR/litentry-collator" - fi -} - -function restart_services { - sudo systemctl daemon-reload - if [ "$ONLY_WORKER" = false ]; then - echo "Restarting parachain services ..." - - cd "$PARACHAIN_BASEDIR" || exit - ./polkadot build-spec --chain rococo-local --disable-default-bootnode --raw > rococo-local-chain-spec.json - ./litentry-collator export-genesis-state --chain $CHAIN-dev > genesis-state - ./litentry-collator export-genesis-wasm --chain $CHAIN-dev > genesis-wasm - - sudo systemctl restart relay-alice.service - sleep 5 - sudo systemctl restart relay-bob.service - sleep 5 - sudo systemctl restart para-alice.service - sleep 5 - register_parachain - fi - - echo "Restarting worker services ..." - for ((i = 0; i < WORKER_COUNT; i++)); do - sudo systemctl restart "worker$i.service" - sleep 5 - done - echo "Done" -} - -function stop_worker_services { - echo "Stopping worker services ..." - for ((i = 0; i < WORKER_COUNT; i++)); do - sudo systemctl stop "worker$i.service" - sleep 5 - done -} - -function stop_parachain_services { - echo "Stopping parachain services ..." - sudo systemctl stop para-alice.service relay-alice.service relay-bob.service -} - -function stop_services { - stop_worker_services - - # TODO: it means we can't stop parachain service alone - # this needs to be done directly via `systemctl` - if [ "$ONLY_WORKER" = false ]; then - stop_parachain_services - fi -} - -function register_parachain { - echo "Register parathread now ..." - cd "$ROOTDIR" || exit - export PARACHAIN_ID=$(grep DEFAULT_PARA_ID node/src/chain_specs/$CHAIN.rs | grep u32 | sed 's/.* = //;s/\;//') - cd "$ROOTDIR/ts-tests" || exit - if [[ -z "$NODE_ENV" ]]; then - echo "NODE_ENV=ci" > .env - else - echo "NODE_ENV=$NODE_ENV" > .env - fi - # The genesis state path file needs to be updated as it is hardcoded to be /tmp/parachain_dev - jq --arg genesis_state "$PARACHAIN_BASEDIR/genesis-state" --arg genesis_wasm "$PARACHAIN_BASEDIR/genesis-wasm" '.genesis_state_path = $genesis_state | .genesis_wasm_path = $genesis_wasm' config.ci.json > config.ci.json.1 - mv config.ci.json.1 config.ci.json - pnpm install - pnpm run register-parathread 2>&1 | tee "$PARACHAIN_BASEDIR/register-parathread.log" - print_divider - - echo "Upgrade parathread to parachain now ..." - # Wait for 90s to allow onboarding finish, after that we do the upgrade - sleep 90 - pnpm run upgrade-parathread 2>&1 | tee "$PARACHAIN_BASEDIR/upgrade-parathread.log" - print_divider - - echo "done. please check $PARACHAIN_BASEDIR for generated files if need" - print_divider - git restore config.ci.json -} - -function setup_working_dir { - echo "Setting up working dir ..." - cd "$ROOTDIR/tee-worker/bin" || exit - - if [ "$PRODUCTION" = false ]; then - for f in 'key.txt' 'spid.txt'; do - [ -f "$f" ] || touch "$f" - done - fi - - for ((i = 0; i < WORKER_COUNT; i++)); do - worker_dir="$WORKER_BASEDIR/w$i" - mkdir -p "$worker_dir" - for f in 'key.txt' 'spid.txt' 'enclave.signed.so' 'litentry-worker'; do - [ -f "$f" ] && cp -f "$f" "$worker_dir" - done - - cd "$worker_dir" - [ -f light_client_db.bin/db.bin.backup ] && cp -f light_client_db.bin/db.bin.backup light_client_db.bin/db.bin - - enclave_account=$(./litentry-worker signing-key | grep -oP '^Enclave account: \K.*$$') - - if [ "$PRODUCTION" = true ]; then - echo "Transferring balance to the enclave account $enclave_account ..." - cd $ROOTDIR/scripts/ts-utils/ || exit - pnpm install - pnpm exec ts-node transfer.ts $enclave_account - fi - done -} - -function get_old_mrenclave { - cd "$WORKER_BASEDIR/w0" || exit - OLD_SHARD=$(./litentry-worker mrenclave) - $SGX_ENCLAVE_SIGNER dump -enclave ./enclave.signed.so -dumpfile df.out - OLD_MRENCLAVE=$($ROOTDIR/tee-worker/extract_identity < df.out | awk '{print $2}') - rm df.out - echo "old shard: $OLD_SHARD" - echo "old mrenclave: $OLD_MRENCLAVE" -} - -function set_scheduled_enclave { - echo "Setting scheduled enclave ..." - cd $ROOTDIR/tee-worker || exit - NEW_MRENCLAVE=$(make mrenclave 2>&1 | grep MRENCLAVE | awk '{print $2}') - echo "new mrenclave: $NEW_MRENCLAVE" - - latest_sidechain_block - - echo "Setting up the new worker on chain ..." - cd $ROOTDIR/ts-tests/ || exit - pnpm install - pnpm run setup-enclave $NEW_MRENCLAVE $SCHEDULED_UPDATE_BLOCK -} - -function wait_for_sidechain { - echo "Waiting for sidechain to reach block $SCHEDULED_UPDATE_BLOCK ..." - found=false - for _ in $(seq 1 30); do - sleep 20 - block_number=$(grep -F 'Enclave produced sidechain blocks' $WORKER_BASEDIR/w0/worker.log | tail -n 1 | sed 's/.*\[//;s/]//') - echo "current sidechain block: $block_number" - if [ $((block_number+1)) -eq $SCHEDULED_UPDATE_BLOCK ]; then - echo "we should stall soon ..." - fi - if tail -n 50 $WORKER_BASEDIR/w0/worker.log | grep -q "Skipping sidechain block $SCHEDULED_UPDATE_BLOCK due to mismatch MRENCLAVE"; then - echo "we reach $SCHEDULED_UPDATE_BLOCK now" - found=true - break - fi - done - if [ $found = false ]; then - echo "not reached, timeout" - exit 1 - fi -} - -function migrate_shard { - echo "Migrating shards for workers ..." - for ((i = 0; i < WORKER_COUNT; i++)); do - cd "$WORKER_BASEDIR/w$i" || exit - echo "old MRENCLAVE: $OLD_MRENCLAVE" - echo "new MRENCLAVE: $NEW_MRENCLAVE" - ./litentry-worker migrate-shard --old-shard $OLD_MRENCLAVE --new-shard $NEW_MRENCLAVE - - cd shards || exit - rm -rf $OLD_SHARD - done - echo "Done" -} - -function remove_clean_reset { - echo "Removing --clean-reset flag for workers ..." - for ((i = 0; i < WORKER_COUNT; i++)); do - sudo sed -i 's/--clean-reset//' /etc/systemd/system/worker$i.service - done - echo "Done" -} - -# TODO: here we only read worker0 logs here -function latest_sidechain_block { - block_number=$(grep -F 'Enclave produced sidechain blocks' $WORKER_BASEDIR/w0/worker.log | tail -n 1 | sed 's/.*\[//;s/]//') - SCHEDULED_UPDATE_BLOCK=$((block_number + 30)) - echo "Current sidechain block: $block_number, scheduled update block: $SCHEDULED_UPDATE_BLOCK" -} - -# TODO: unused -function _latest_parentchain_block { - # JSON-RPC request payload - request='{"jsonrpc":"2.0","id":1,"method":"chain_getHeader","params":[]}' - - # Make the JSON-RPC request and retrieve the latest finalized block - response=$(curl -s -H "Content-Type: application/json" -d "$request" http://$PARACHAIN_HOST:$PARACHAIN_PORT) - hex_number=$(echo "$response" | grep -oP '(?<="number":")[^"]+') - LATEST_FINALIZED_BLOCK=$(printf "%d" "$hex_number") - echo "Current parachain block: $LATEST_FINALIZED_BLOCK" -} - -main "$@" diff --git a/tee-worker/scripts/litentry/release/prepare.sh b/tee-worker/scripts/litentry/release/prepare.sh deleted file mode 100755 index e9817e8d71..0000000000 --- a/tee-worker/scripts/litentry/release/prepare.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -set -euo pipefail - - -# This WORKER_DIR is the directory where worker will start from. -WORKER_DIR=/opt/worker/ - -# CONFIG_DIR provides all the necessary private secret files. -# They should only exist on the running machine. -CONFIG_DIR=/opt/configs/ -CONFIG=$CONFIG_DIR/config.json -ACCOUNT=$CONFIG_DIR/private_account.json -INTEL_KEY=$CONFIG_DIR/key_production.txt -INTEL_SPID=$CONFIG_DIR/spid_production.txt - -############################################################################## -# Don't edit anything from here -if [[ ! -e "$WORKER_DIR" ]]; then - mkdir -p $WORKER_DIR -fi - -for Item in $CONFIG $ACCOUNT $INTEL_KEY $INTEL_SPID; do - if [[ ! -e "$Item" ]]; then - echo "Error: $Item is not a valid path." - exit 1 - fi -done - -# Generate keys and copy around. -SRC_DIR=$(dirname "$0") -cd $SRC_DIR - -./litentry-worker signing-key | grep -oP '^Enclave account: \K.*$$' > enclave_account.txt -echo "Enclave account is prepared inside enclave_account.txt" - -./litentry-worker shielding-key - -for Item in 'enclave.signed.so' 'litentry-worker' 'aes_key_sealed.bin' 'ed25519_key_sealed.bin' 'enclave-shielding-pubkey.json' 'enclave-signing-pubkey.bin' 'rsa3072_key_sealed.bin' 'sidechain_db'; do - cp -r "${Item}" "${WORKER_DIR}" -done - -cp $CONFIG "${WORKER_DIR}/config.json" -cp $INTEL_KEY "${WORKER_DIR}/key_production.txt" -cp $INTEL_SPID "${WORKER_DIR}/spid_production.txt" - -# Comment out for the moment. Need to adapt together with PR-1587 ts-utils. -cp $ACCOUNT "${WORKER_DIR}/ts-utils/private_account.json" -cp "enclave_account.txt" "${WORKER_DIR}/ts-utils/enclave_account.txt" -cp "mrenclave.txt" "${WORKER_DIR}/ts-utils/mrenclave.txt" - diff --git a/tee-worker/scripts/litentry/release/template/worker.service b/tee-worker/scripts/litentry/release/template/worker.service index e218d60278..d2a6edb24d 100644 --- a/tee-worker/scripts/litentry/release/template/worker.service +++ b/tee-worker/scripts/litentry/release/template/worker.service @@ -6,9 +6,9 @@ Type=simple User=USER Environment='RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug' WorkingDirectory=/opt/litentry/worker/wNUMBER -ExecStart=/bin/bash -c 'cd /opt/litentry/worker/wNUMBER && source /opt/intel/sgxsdk/environment && ./litentry-worker ARGS' +ExecStart=/bin/bash -c 'cd /opt/litentry/worker/wNUMBER && source /opt/intel/sgxsdk/environment && source /opt/worker_configs/worker_env && ./litentry-worker ARGS' StandardOutput=append:/opt/litentry/worker/wNUMBER/worker.log StandardError=inherit [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target diff --git a/tee-worker/service/Cargo.toml b/tee-worker/service/Cargo.toml index 8363903079..62d93b85a5 100644 --- a/tee-worker/service/Cargo.toml +++ b/tee-worker/service/Cargo.toml @@ -78,8 +78,6 @@ litentry-hex-utils = { path = "../../primitives/hex", default-features = false } litentry-macros = { path = "../../primitives/core/macros", default-features = false } litentry-primitives = { path = "../litentry/primitives" } my-node-runtime = { package = "rococo-parachain-runtime", path = "../../runtime/rococo" } -sgx-verify = { path = "../../pallets/teerex/sgx-verify", default-features = false } -teerex-primitives = { path = "../../primitives/teerex", default-features = false } [features] default = [] @@ -93,7 +91,6 @@ production = [ "litentry-macros/production", "litentry-primitives/production", ] -teeracle = ["itp-settings/teeracle"] dcap = [] attesteer = ["dcap"] # Must be enabled to build a binary and link it with the enclave successfully. diff --git a/tee-worker/service/src/cli.yml b/tee-worker/service/src/cli.yml index db53ab0174..9ffc3d55b0 100644 --- a/tee-worker/service/src/cli.yml +++ b/tee-worker/service/src/cli.yml @@ -13,11 +13,11 @@ settings: # part of a Hash args: - node-url: - short: u - long: node-url - help: Set the url and the protocol of the RPC endpoint. - takes_value: true - default_value: "ws://127.0.0.1" + short: u + long: node-url + help: Set the url and the protocol of the RPC endpoint. + takes_value: true + default_value: "ws://127.0.0.1" - node-port: short: p long: node-port @@ -50,188 +50,185 @@ args: help: Data dir where the worker stores it's keys and other data. takes_value: true - ws-external: - long: ws-external - help: Set this flag in case the worker should listen to external requests. + long: ws-external + help: Set this flag in case the worker should listen to external requests. - mu-ra-port: - short: r - long: mu-ra-port - help: Set the websocket port to listen for mu-ra requests - takes_value: true - default_value: "3443" + short: r + long: mu-ra-port + help: Set the websocket port to listen for mu-ra requests + takes_value: true + default_value: "3443" - trusted-worker-port: - short: P - long: trusted-worker-port - help: Set the trusted websocket port of the worker, running directly in the enclave. - takes_value: true - default_value: "2000" + short: P + long: trusted-worker-port + help: Set the trusted websocket port of the worker, running directly in the enclave. + takes_value: true + default_value: "2000" - untrusted-worker-port: - short: w - long: untrusted-worker-port - help: Set the untrusted websocket port of the worker - takes_value: true - default_value: "2001" + short: w + long: untrusted-worker-port + help: Set the untrusted websocket port of the worker + takes_value: true + default_value: "2001" - trusted-external-address: - short: T - long: trusted-external-address - help: Set the trusted worker address to be advertised on the parentchain. If no port is given, the same as in `trusted-worker-port` will be used. - takes_value: true - required: false + short: T + long: trusted-external-address + help: Set the trusted worker address to be advertised on the parentchain. If no port is given, the same as in `trusted-worker-port` will be used. + takes_value: true + required: false - untrusted-external-address: - short: U - long: untrusted-external-address - help: Set the untrusted worker address to be retrieved by a trusted rpc call. If no port is given, the same as in `untrusted-worker-port` will be used. - takes_value: true - required: false + short: U + long: untrusted-external-address + help: Set the untrusted worker address to be retrieved by a trusted rpc call. If no port is given, the same as in `untrusted-worker-port` will be used. + takes_value: true + required: false - mu-ra-external-address: - short: M - long: mu-ra-external-address - help: Set the mutual remote attestation worker address to be retrieved by a trusted rpc call. If no port is given, the same as in `mu-ra-port` will be used. - takes_value: true - required: false + short: M + long: mu-ra-external-address + help: Set the mutual remote attestation worker address to be retrieved by a trusted rpc call. If no port is given, the same as in `mu-ra-port` will be used. + takes_value: true + required: false - enable-metrics: - long: enable-metrics - help: Enable the metrics HTTP server to serve metrics + long: enable-metrics + help: Enable the metrics HTTP server to serve metrics - metrics-port: - short: i - long: metrics-port - help: Set the port on which the metrics are served. - takes_value: true - default_value: "8787" - required: false + short: i + long: metrics-port + help: Set the port on which the metrics are served. + takes_value: true + default_value: "8787" + required: false - untrusted-http-port: - short: h - long: untrusted-http-port - help: Set the port for the untrusted HTTP server - takes_value: true - required: false + short: h + long: untrusted-http-port + help: Set the port for the untrusted HTTP server + takes_value: true + required: false - clean-reset: - long: clean-reset - short: c - help: Cleans and purges any previous state and key files and generates them anew before starting. + long: clean-reset + short: c + help: Cleans and purges any previous state and key files and generates them anew before starting. - enable-mock-server: - long: enable-mock-server - takes_value: false - help: Set this flag to enable the HTTP mock server for testing + long: enable-mock-server + takes_value: false + help: Set this flag to enable the HTTP mock server for testing - mock-server-port: - long: mock-server-port - help: Set the port for HTTP mock server - takes_value: true - required: false - default_value: "19527" + long: mock-server-port + help: Set the port for HTTP mock server + takes_value: true + required: false + default_value: "19527" - parentchain-start-block: - long: parentchain-start-block - help: Set the parentchain block number to start syncing with - takes_value: true - required: false - default_value: "0" + long: parentchain-start-block + help: Set the parentchain block number to start syncing with + takes_value: true + required: false + default_value: "0" - fail-slot-mode: - long: fail-slot-mode - help: Set the mode of failing a slot, values [BeforeOnSlot, AfterOnSlot] - takes_value: true - required: false + long: fail-slot-mode + help: Set the mode of failing a slot, values [BeforeOnSlot, AfterOnSlot] + takes_value: true + required: false - fail-at: - long: fail-at - help: Set the slot to fail on - takes_value: true - required: false - default_value: "0" + long: fail-at + help: Set the slot to fail on + takes_value: true + required: false + default_value: "0" subcommands: - run: - about: Start the litentry-worker - args: - - skip-ra: - long: skip-ra - help: skip remote attestation. Set this flag if running enclave in SW mode - - shard: - required: false - index: 1 - help: shard identifier base58 encoded. Defines the state that this worker shall operate on. Default is mrenclave - - dev: - long: dev - short: d - help: Set this flag if running in development mode to bootstrap enclave account on parentchain via //Alice. - - request-state: - long: request-state - short: r - help: Run the worker and request key and state provisioning from another worker. - - teeracle-interval: - required: false - long: teeracle-interval - short: i - help: Set the teeracle exchange rate update interval. Example of accepted syntax <5 seconds 15 minutes 2 hours 1 days> or short <5s15m2h1d> - takes_value: true - - reregister-teeracle-interval: - required: false - long: reregister - help: Set the teeracle reregistration interval. Example of accepted syntax <5 seconds 15 minutes 2 hours 1 days> or short <5s15m2h1d> - takes_value: true + about: Start the litentry-worker + args: + - skip-ra: + long: skip-ra + help: skip remote attestation. Set this flag if running enclave in SW mode + - shard: + required: false + index: 1 + help: shard identifier base58 encoded. Defines the state that this worker shall operate on. Default is mrenclave + - dev: + long: dev + short: d + help: Set this flag if running in development mode to bootstrap enclave account on parentchain via //Alice. + - request-state: + long: request-state + short: r + help: Run the worker and request key and state provisioning from another worker. + - marblerun-url: + required: false + long: marblerun-url + help: Set the URL for prometheus metrics. Probably put some meaningful description + takes_value: true - request-state: - about: join a shard by requesting key provisioning from another worker - args: - - shard: - long: shard - required: false - help: shard identifier base58 encoded. Defines the state that this worker shall operate on. Default is mrenclave - - skip-ra: - long: skip-ra - help: skip remote attestation. Set this flag if running enclave in SW mode + about: join a shard by requesting key provisioning from another worker + args: + - shard: + long: shard + required: false + help: shard identifier base58 encoded. Defines the state that this worker shall operate on. Default is mrenclave + - skip-ra: + long: skip-ra + help: skip remote attestation. Set this flag if running enclave in SW mode - shielding-key: - about: Get the public RSA3072 key from the TEE to be used to encrypt requests + about: Get the public RSA3072 key from the TEE to be used to encrypt requests - signing-key: - about: Get the public ed25519 key the TEE uses to sign messages and extrinsics + about: Get the public ed25519 key the TEE uses to sign messages and extrinsics - dump-ra: - about: Perform RA and dump cert to disk + about: Perform RA and dump cert to disk - mrenclave: - about: Dump mrenclave to stdout. base58 encoded. + about: Dump mrenclave to stdout. base58 encoded. - init-shard: - about: Initialize new shard (do this only if you run the first worker for that shard). if shard is not specified, the MRENCLAVE is used instead - args: - - shard: - required: false - multiple: true - index: 1 - help: shard identifier base58 encoded + about: Initialize new shard (do this only if you run the first worker for that shard). if shard is not specified, the MRENCLAVE is used instead + args: + - shard: + required: false + multiple: true + index: 1 + help: shard identifier base58 encoded - migrate-shard: - about: Migrate shard - args: - - old-shard: - long: old-shard - help: shard identifier hex encoded - takes_value: true - - new-shard: - long: new-shard - help: shard identifier hex encoded - takes_value: true + about: Migrate shard + args: + - old-shard: + long: old-shard + help: shard identifier hex encoded + takes_value: true + - new-shard: + long: new-shard + help: shard identifier hex encoded + takes_value: true - test: about: Run tests involving the enclave takes_value: true args: - - all: + - all: short: a long: all help: Run all tests (beware, all corrupts the counter state for some whatever reason...) takes_value: false - - unit: + - unit: short: u long: unit help: Run unit tests takes_value: false - - ecall: + - ecall: short: e long: ecall help: Run enclave ecall tests takes_value: false - - integration: + - integration: short: i long: integration help: Run integration tests takes_value: false - - provisioning-server: + - provisioning-server: long: provisioning-server help: Run TEE server for MU-RA key provisioning takes_value: false - - provisioning-client: + - provisioning-client: long: provisioning-client help: Run TEE client for MU-RA key provisioning takes_value: false + - skip-ra: + long: skip-ra + help: skip remote attestation. Set this flag if running enclave in SW mode diff --git a/tee-worker/service/src/config.rs b/tee-worker/service/src/config.rs index 5c7b569d21..6232af4a79 100644 --- a/tee-worker/service/src/config.rs +++ b/tee-worker/service/src/config.rs @@ -17,7 +17,6 @@ use clap::ArgMatches; use itc_rest_client::rest_client::Url; -use itp_settings::teeracle::{DEFAULT_MARKET_DATA_UPDATE_INTERVAL, ONE_DAY, THIRTY_MINUTES}; use parse_duration::parse; use serde::{Deserialize, Serialize}; use std::{ @@ -312,10 +311,6 @@ pub struct RunConfig { request_state: bool, /// Shard identifier base58 encoded. Defines the shard that this worker operates on. Default is mrenclave. shard: Option, - /// Optional teeracle update interval - teeracle_update_interval: Option, - /// Optional teeracle reregistration interval - reregister_teeracle_interval: Option, /// Marblerun's Prometheus endpoint base URL marblerun_base_url: Option, } @@ -337,19 +332,6 @@ impl RunConfig { self.shard.as_deref() } - pub fn teeracle_update_interval(&self) -> Duration { - self.teeracle_update_interval.unwrap_or(DEFAULT_MARKET_DATA_UPDATE_INTERVAL) - } - - /// The periodic registration period of the teeracle. - /// - /// Defaults to 23h30m, as this is slightly below the currently configured automatic - /// deregistration period on the Integritee chains. - pub fn reregister_teeracle_interval(&self) -> Duration { - // Todo: Derive this from chain https://github.com/integritee-network/worker/issues/1351 - self.reregister_teeracle_interval.unwrap_or(ONE_DAY - THIRTY_MINUTES) - } - pub fn marblerun_base_url(&self) -> &str { // This conflicts with the default port of a substrate node, but it is indeed the // default port of marblerun too: @@ -364,12 +346,6 @@ impl From<&ArgMatches<'_>> for RunConfig { let dev = m.is_present("dev"); let request_state = m.is_present("request-state"); let shard = m.value_of("shard").map(|s| s.to_string()); - let teeracle_update_interval = m.value_of("teeracle-interval").map(|i| { - parse(i).unwrap_or_else(|e| panic!("teeracle-interval parsing error {:?}", e)) - }); - let reregister_teeracle_interval = m.value_of("reregister-teeracle-interval").map(|i| { - parse(i).unwrap_or_else(|e| panic!("teeracle-interval parsing error {:?}", e)) - }); let marblerun_base_url = m.value_of("marblerun-url").map(|i| { Url::parse(i) @@ -377,15 +353,7 @@ impl From<&ArgMatches<'_>> for RunConfig { .to_string() }); - Self { - skip_ra, - dev, - request_state, - shard, - teeracle_update_interval, - reregister_teeracle_interval, - marblerun_base_url, - } + Self { skip_ra, dev, request_state, shard, marblerun_base_url } } } @@ -525,7 +493,6 @@ mod test { assert_eq!(run_config.dev, false); assert_eq!(run_config.skip_ra, false); assert!(run_config.shard.is_none()); - assert!(run_config.teeracle_update_interval.is_none()); } #[test] @@ -538,11 +505,9 @@ mod test { ("dev", Default::default()), ("skip-ra", Default::default()), ("shard", Default::default()), - ("teeracle-interval", Default::default()), ]); // Workaround because MatchedArg is private. args.args.get_mut("shard").unwrap().vals = vec![shard_identifier.into()]; - args.args.get_mut("teeracle-interval").unwrap().vals = vec!["42s".into()]; let run_config = RunConfig::from(&args); @@ -550,7 +515,6 @@ mod test { assert_eq!(run_config.dev, true); assert_eq!(run_config.skip_ra, true); assert_eq!(run_config.shard.unwrap(), shard_identifier.to_string()); - assert_eq!(run_config.teeracle_update_interval.unwrap(), Duration::from_secs(42)); } #[test] @@ -584,17 +548,6 @@ mod test { assert_eq!(config.mu_ra_url_external(), format!("{}:{}", expected_worker_ip, mu_ra_port)); } - #[test] - fn teeracle_interval_parsing_panics_if_format_is_invalid() { - let teeracle_interval = "24s_invalid-format"; - let mut args = ArgMatches::default(); - args.args = HashMap::from([("teeracle-interval", Default::default())]); - args.args.get_mut("teeracle-interval").unwrap().vals = vec![teeracle_interval.into()]; - - let result = std::panic::catch_unwind(|| RunConfig::from(&args)); - assert!(result.is_err()); - } - #[test] fn external_addresses_are_returned_correctly_if_set() { let trusted_ext_addr = "wss://1.1.1.2:700"; diff --git a/tee-worker/service/src/main.rs b/tee-worker/service/src/main.rs index 6c5a888eee..feab3398ea 100644 --- a/tee-worker/service/src/main.rs +++ b/tee-worker/service/src/main.rs @@ -31,8 +31,6 @@ mod setup; mod sidechain_setup; mod sync_block_broadcaster; mod sync_state; -#[cfg(feature = "teeracle")] -mod teeracle; mod tests; mod utils; mod worker; diff --git a/tee-worker/service/src/main_impl.rs b/tee-worker/service/src/main_impl.rs index 3e660cefc2..603ba62bf0 100644 --- a/tee-worker/service/src/main_impl.rs +++ b/tee-worker/service/src/main_impl.rs @@ -1,6 +1,3 @@ -#[cfg(feature = "teeracle")] -use crate::teeracle::{schedule_periodic_reregistration_thread, start_periodic_market_update}; - #[cfg(not(feature = "dcap"))] use crate::utils::check_files; use crate::{ @@ -36,10 +33,9 @@ use itp_enclave_api::{ enclave_base::EnclaveBase, remote_attestation::{RemoteAttestation, TlsRemoteAttestation}, sidechain::Sidechain, - teeracle_api::TeeracleApi, }; use itp_node_api::{ - api_client::{AccountApi, PalletTeerexApi, ParentchainApi}, + api_client::{AccountApi, PalletTeebagApi, ParentchainApi}, metadata::NodeMetadata, node_api_factory::{CreateNodeApi, NodeApiFactory}, }; @@ -51,6 +47,7 @@ use its_primitives::types::block::SignedBlock as SignedSidechainBlock; use its_storage::{interface::FetchBlocks, BlockPruner, SidechainStorageLock}; use lc_data_providers::DataProviderConfig; use litentry_macros::if_production_or; +use litentry_primitives::{Enclave as TeebagEnclave, ShardIdentifier, WorkerType}; use log::*; use my_node_runtime::{Hash, Header, RuntimeEvent}; use regex::Regex; @@ -61,10 +58,9 @@ use substrate_api_client::{ ac_primitives::serde_impls::StorageKey, api::XtStatus, rpc::HandleSubscription, storage_key, GetChainInfo, GetStorage, SubmitAndWatch, SubscribeChain, SubscribeEvents, }; -use teerex_primitives::{Enclave as TeerexEnclave, ShardIdentifier}; #[cfg(feature = "dcap")] -use sgx_verify::extract_tcb_info_from_raw_dcap_quote; +use litentry_primitives::extract_tcb_info_from_raw_dcap_quote; use itc_parentchain::primitives::ParentchainId; use itp_enclave_api::Enclave; @@ -336,13 +332,7 @@ fn start_worker( quote_size: Option, ) where T: GetTokioHandle, - E: EnclaveBase - + DirectRequest - + Sidechain - + RemoteAttestation - + TlsRemoteAttestation - + TeeracleApi - + Clone, + E: EnclaveBase + DirectRequest + Sidechain + RemoteAttestation + TlsRemoteAttestation + Clone, D: BlockPruner + FetchBlocks + Sync + Send + 'static, InitializationHandler: TrackInitialization + IsInitialized + Sync + Send + 'static, WorkerModeProvider: ProvideWorkerMode, @@ -350,13 +340,11 @@ fn start_worker( let run_config = config.run_config().clone().expect("Run config missing"); let skip_ra = run_config.skip_ra(); - #[cfg(feature = "teeracle")] - let flavor_str = "teeracle"; #[cfg(feature = "sidechain")] let flavor_str = "sidechain"; #[cfg(feature = "offchain-worker")] let flavor_str = "offchain-worker"; - #[cfg(not(any(feature = "offchain-worker", feature = "sidechain", feature = "teeracle")))] + #[cfg(not(any(feature = "offchain-worker", feature = "sidechain")))] let flavor_str = "offchain-worker"; println!("Litentry Worker for {} v{}", flavor_str, VERSION); @@ -521,108 +509,56 @@ fn start_worker( #[cfg(feature = "dcap")] let register_xt = move || enclave2.generate_dcap_ra_extrinsic(&trusted_url2, skip_ra).unwrap(); - let mut register_enclave_xt_header: Option

= None; - let mut we_are_primary_validateer: bool = false; - let send_register_xt = move || { println!("[+] Send register enclave extrinsic"); send_extrinsic(register_xt(), &node_api2, &tee_accountid2, is_development_mode) }; - // litentry: check if the enclave is already registered - // TODO: revisit the registration process (P-10) - match litentry_rpc_api.get_keys(storage_key("Teerex", "EnclaveRegistry"), None) { - Ok(Some(keys)) => { - let trusted_url = trusted_url.as_bytes().to_vec(); - let mrenclave = mrenclave.0.to_vec(); - let mut found = false; - for key in keys { - let key = if key.starts_with("0x") { - let bytes = &key.as_bytes()[b"0x".len()..]; - hex::decode(bytes).unwrap() - } else { - hex::decode(key.as_bytes()).unwrap() - }; - match litentry_rpc_api.get_storage_by_key::>>( - StorageKey(key.clone()), - None, - ) { - Ok(Some(value)) => { - if value.mr_enclave.to_vec() == mrenclave && value.url == trusted_url { - // After calling the perform_ra function, the nonce will be incremented by 1, - // so enclave is already registered, we should reset the nonce_cache - let nonce = - litentry_rpc_api.get_account_next_index(&tee_accountid).unwrap(); - enclave - .set_nonce(nonce, ParentchainId::Litentry) - .expect("Could not set nonce of enclave. Returning here..."); - found = true; - info!("fond enclave: {:?}", value); - break - } - }, - Ok(None) => { - warn!("not found from key: {:?}", key); - }, - Err(_) => {}, - } - } - if !found { - // Todo: Can't unwrap here because the extrinsic is for some reason not found in the block - // even if it was successful: https://github.com/scs/substrate-api-client/issues/624. - let register_enclave_block_hash = send_register_xt(); - let api_register_enclave_xt_header = - litentry_rpc_api.get_header(register_enclave_block_hash).unwrap().unwrap(); - - // TODO: #1451: Fix api-client type hacks - // TODO(Litentry): keep an eye on it - it's a hacky way to convert `SubstrateHeader` to `Header` - let header = - Header::decode(&mut api_register_enclave_xt_header.encode().as_slice()) - .expect("Can decode previously encoded header; qed"); - - println!( - "[+] Enclave registered at block number: {:?}, hash: {:?}", - header.number(), - header.hash() - ); + // Litentry: send the registration extrinsic regardless of being registered or not, + // the reason is the mrenclave could change in between, so we rely on the + // on-chain logic to handle everything. + // this is the same behavior as upstream + let register_enclave_block_hash = + send_register_xt().expect("enclave RA registration must be successful to continue"); + + let api_register_enclave_xt_header = + litentry_rpc_api.get_header(Some(register_enclave_block_hash)).unwrap().unwrap(); + + // TODO: #1451: Fix api-client type hacks + let register_enclave_xt_header = + Header::decode(&mut api_register_enclave_xt_header.encode().as_slice()) + .expect("Can decode previously encoded header; qed"); + + println!( + "[+] Enclave registered at block number: {:?}, hash: {:?}", + register_enclave_xt_header.number(), + register_enclave_xt_header.hash() + ); - register_enclave_xt_header = Some(header); - } - }, - _ => panic!("unknown error"), - } + // double-check + let my_enclave = litentry_rpc_api + .enclave(&tee_accountid, None) + .unwrap() + .expect("our enclave should be registered at this point"); + trace!("verified that our enclave is registered: {:?}", my_enclave); - if let Some(register_enclave_xt_header) = register_enclave_xt_header.clone() { - we_are_primary_validateer = - we_are_primary_worker(&litentry_rpc_api, ®ister_enclave_xt_header).unwrap(); - } + let is_primary_enclave = match litentry_rpc_api + .primary_enclave_identifier_for_shard(WorkerType::Identity, shard, None) + .unwrap() + { + Some(account) => account == tee_accountid, + None => false, + }; - if we_are_primary_validateer { - println!("[+] We are the primary worker"); + if is_primary_enclave { + println!("[+] We are the primary enclave"); } else { - println!("[+] We are NOT the primary worker"); + println!("[+] We are NOT the primary enclave"); } initialization_handler.registered_on_parentchain(); match WorkerModeProvider::worker_mode() { - WorkerMode::Teeracle => { - // ------------------------------------------------------------------------ - // initialize teeracle interval - #[cfg(feature = "teeracle")] - schedule_periodic_reregistration_thread( - send_register_xt, - run_config.reregister_teeracle_interval(), - ); - - #[cfg(feature = "teeracle")] - start_periodic_market_update( - &litentry_rpc_api, - run_config.teeracle_update_interval(), - enclave.as_ref(), - &tokio_handle, - ); - }, WorkerMode::OffChainWorker => { println!("*** [+] Finished initializing light client, syncing parentchain..."); @@ -652,7 +588,7 @@ fn start_worker( let last_synced_header = sidechain_init_block_production( enclave.clone(), register_enclave_xt_header, - we_are_primary_validateer, + is_primary_enclave, parentchain_handler.clone(), sidechain_storage, &last_synced_header, @@ -664,7 +600,7 @@ fn start_worker( start_parentchain_header_subscription_thread(parentchain_handler, last_synced_header); - init_provided_shard_vault(shard, &enclave, we_are_primary_validateer); + init_provided_shard_vault(shard, &enclave, is_primary_enclave); spawn_worker_for_shard_polling(shard, litentry_rpc_api.clone(), initialization_handler); }, @@ -707,14 +643,14 @@ fn start_worker( fn init_provided_shard_vault( shard: &ShardIdentifier, enclave: &Arc, - we_are_primary_validateer: bool, + is_primary_enclave: bool, ) { if let Ok(shard_vault) = enclave.get_ecc_vault_pubkey(shard) { println!( "[Litentry] shard vault account is already initialized in state: {}", shard_vault.to_ss58check() ); - } else if we_are_primary_validateer { + } else if is_primary_enclave { println!("[Litentry] initializing proxied shard vault account now"); enclave.init_proxied_shard_vault(shard, &ParentchainId::Litentry).unwrap(); println!( @@ -752,18 +688,17 @@ fn init_target_parentchain( let (parentchain_handler, last_synched_header) = init_parentchain(enclave, &node_api, tee_account_id, parentchain_id); - if WorkerModeProvider::worker_mode() != WorkerMode::Teeracle { - println!( - "*** [+] [{:?}] Finished initializing light client, syncing parentchain...", - parentchain_id - ); + println!( + "*** [+] [{:?}] Finished initializing light client, syncing parentchain...", + parentchain_id + ); - // Syncing all parentchain blocks, this might take a while.. - let last_synched_header = - parentchain_handler.sync_parentchain(last_synched_header, 0, true).unwrap(); + // Syncing all parentchain blocks, this might take a while.. + let last_synched_header = + parentchain_handler.sync_parentchain(last_synched_header, 0, true).unwrap(); + + start_parentchain_header_subscription_thread(parentchain_handler, last_synched_header); - start_parentchain_header_subscription_thread(parentchain_handler, last_synched_header) - } println!("[{:?}] initializing proxied shard vault account now", parentchain_id); enclave.init_proxied_shard_vault(shard, &parentchain_id).unwrap(); @@ -802,7 +737,7 @@ where let last_synced_header = parentchain_handler.init_parentchain_components().unwrap(); println!("[{:?}] last synced parentchain block: {}", parentchain_id, last_synced_header.number); - let nonce = node_api.get_nonce_of(tee_account_id).unwrap(); + let nonce = node_api.get_account_next_index(tee_account_id).unwrap(); info!("[{:?}] Enclave nonce = {:?}", parentchain_id, nonce); enclave.set_nonce(nonce, parentchain_id).unwrap_or_else(|_| { panic!("[{:?}] Could not set nonce of enclave. Returning here...", parentchain_id) @@ -824,9 +759,8 @@ where } /// Start polling loop to wait until we have a worker for a shard registered on -/// the parentchain (TEEREX WorkerForShard). This is the pre-requisite to be +/// the parentchain (TEEBAG EnclaveIdentifier). This is the pre-requisite to be /// considered initialized and ready for the next worker to start (in sidechain mode only). -/// considered initialized and ready for the next worker to start. fn spawn_worker_for_shard_polling( shard: &ShardIdentifier, node_api: ParentchainApi, @@ -840,7 +774,11 @@ fn spawn_worker_for_shard_polling( loop { info!("Polling for worker for shard ({} seconds interval)", POLL_INTERVAL_SECS); - if let Ok(Some(_enclave)) = node_api.worker_for_shard(&shard_for_initialized, None) { + if let Ok(Some(_account)) = node_api.primary_enclave_identifier_for_shard( + WorkerType::Identity, + &shard_for_initialized, + None, + ) { // Set that the service is initialized. initialization_handler.worker_for_shard_registered(); println!("[+] Found `WorkerForShard` on parentchain state",); @@ -1030,7 +968,7 @@ fn subscribe_to_parentchain_new_headers( // - we might have multiple `sync_parentchain` running concurrently, which causes chaos in enclave side // - I still feel it's only a workaround, not a perfect solution // - // TODO: now the sync will panic if disconnected - it heavily relys on the worker-restart to work (even manually) + // TODO: now the sync will panic if disconnected - it heavily relies on the worker-restart to work (even manually) let parentchain_id = parentchain_handler.parentchain_id(); loop { let new_header = subscription @@ -1053,13 +991,3 @@ pub fn enclave_account(enclave_api: &E) -> AccountId32 { trace!("[+] Got ed25519 account of TEE = {}", tee_public.to_ss58check()); AccountId32::from(*tee_public.as_array_ref()) } - -/// Checks if we are the first validateer to register on the parentchain. -fn we_are_primary_worker( - node_api: &ParentchainApi, - register_enclave_xt_header: &Header, -) -> Result { - let enclave_count_of_previous_block = - node_api.enclave_count(Some(*register_enclave_xt_header.parent_hash()))?; - Ok(enclave_count_of_previous_block == 0) -} diff --git a/tee-worker/service/src/prometheus_metrics.rs b/tee-worker/service/src/prometheus_metrics.rs index c998261561..4e99f4e7d4 100644 --- a/tee-worker/service/src/prometheus_metrics.rs +++ b/tee-worker/service/src/prometheus_metrics.rs @@ -17,9 +17,6 @@ //! Service for prometheus metrics, hosted on a http server. -#[cfg(feature = "teeracle")] -use crate::teeracle::teeracle_metrics::update_teeracle_metrics; - use crate::{ account_funding::EnclaveAccountInfo, error::{Error, ServiceResult}, @@ -41,9 +38,9 @@ use lc_stf_task_sender::RequestType; use litentry_primitives::{Assertion, Identity}; use log::*; use prometheus::{ - proto::MetricFamily, register_counter_vec, register_histogram, register_histogram_vec, - register_int_gauge, register_int_gauge_vec, CounterVec, Histogram, HistogramVec, IntGauge, - IntGaugeVec, + proto::MetricFamily, register_counter, register_counter_vec, register_histogram, + register_histogram_vec, register_int_gauge, register_int_gauge_vec, Counter, CounterVec, + Histogram, HistogramVec, IntGauge, IntGaugeVec, }; use serde::{Deserialize, Serialize}; use std::{net::SocketAddr, sync::Arc}; @@ -91,6 +88,15 @@ lazy_static! { static ref ENCLAVE_SIDECHAIN_BLOCK_BROADCASTING_TIME: Histogram = register_histogram!("litentry_worker_enclave_sidechain_block_broadcasting_time", "Time taken to broadcast sidechain block") .unwrap(); + static ref VC_BUILD_TIME: HistogramVec = + register_histogram_vec!("litentry_worker_vc_build_time", "Time taken to build a vc", &["variant"]) + .unwrap(); + static ref SUCCESSFULL_VC_ISSUANCE_TASKS: Counter = + register_counter!("litentry_worker_vc_successfull_issuances_tasks", "Succesfull VC Issuance tasks") + .unwrap(); + static ref FAILED_VC_ISSUANCE_TASKS: Counter = + register_counter!("litentry_worker_vc_failed_issuances_tasks", "Failed VC Issuance tasks") + .unwrap(); } @@ -229,11 +235,13 @@ impl ReceiveEnclaveMetrics for EnclaveMetricsReceiver { ENCLAVE_SIDECHAIN_SLOT_BLOCK_COMPOSITION_TIME.observe(time.as_secs_f64()), EnclaveMetric::SidechainBlockBroadcastingTime(time) => ENCLAVE_SIDECHAIN_BLOCK_BROADCASTING_TIME.observe(time.as_secs_f64()), - #[cfg(feature = "teeracle")] - EnclaveMetric::ExchangeRateOracle(m) => update_teeracle_metrics(m)?, - #[cfg(not(feature = "teeracle"))] - EnclaveMetric::ExchangeRateOracle(_) => { - error!("Received Teeracle metric, but Teeracle feature is not enabled, ignoring metric item.") + EnclaveMetric::VCBuildTime(assertion, time) => + VC_BUILD_TIME.with_label_values(&[&assertion]).observe(time.as_secs_f64()), + EnclaveMetric::SuccessfullVCIssuance => { + SUCCESSFULL_VC_ISSUANCE_TASKS.inc(); + }, + EnclaveMetric::FailedVCIssuance => { + FAILED_VC_ISSUANCE_TASKS.inc(); }, } Ok(()) @@ -281,7 +289,7 @@ fn handle_stf_call_request(req: RequestType, time: f64) { Assertion::A14 => "A14", Assertion::A20 => "A20", Assertion::Achainable(..) => "Achainable", - Assertion::Oneblock(..) => "Oneblock", + Assertion::OneBlock(..) => "OneBlock", Assertion::BnbDomainHolding => "BnbDomainHolding", Assertion::BnbDigitDomainClub(..) => "BnbDigitDomainClub", Assertion::GenericDiscordRole(_) => "GenericDiscordRole", @@ -292,6 +300,8 @@ fn handle_stf_call_request(req: RequestType, time: f64) { Assertion::BRC20AmountHolder => "BRC20AmountHolder", Assertion::CryptoSummary => "CryptoSummary", Assertion::TokenHoldingAmount(_) => "TokenHoldingAmount", + Assertion::PlatformUser(_) => "PlatformUser", + Assertion::NftHolder(_) => "NftHolder", }, }; inc_stf_calls(category, label); diff --git a/tee-worker/service/src/sidechain_setup.rs b/tee-worker/service/src/sidechain_setup.rs index a499c85fed..55a17cdbe1 100644 --- a/tee-worker/service/src/sidechain_setup.rs +++ b/tee-worker/service/src/sidechain_setup.rs @@ -57,7 +57,7 @@ pub(crate) fn sidechain_start_untrusted_rpc_server( #[allow(clippy::too_many_arguments)] pub(crate) fn sidechain_init_block_production( enclave: Arc, - register_enclave_xt_header: Option
, + register_enclave_xt_header: Header, we_are_primary_validateer: bool, parentchain_handler: Arc, sidechain_storage: Arc, @@ -80,7 +80,7 @@ where ); updated_header = Some(parentchain_handler.sync_and_import_parentchain_until( last_synced_header, - ®ister_enclave_xt_header.unwrap(), + ®ister_enclave_xt_header, overriden_start_block, )?); } diff --git a/tee-worker/service/src/sync_state.rs b/tee-worker/service/src/sync_state.rs index 21d2d4d7e0..29bb91fd5b 100644 --- a/tee-worker/service/src/sync_state.rs +++ b/tee-worker/service/src/sync_state.rs @@ -26,15 +26,15 @@ use itp_enclave_api::{ enclave_base::EnclaveBase, remote_attestation::{RemoteAttestation, TlsRemoteAttestation}, }; -use itp_node_api::api_client::PalletTeerexApi; +use itp_node_api::api_client::PalletTeebagApi; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; -use itp_types::ShardIdentifier; +use itp_types::{ShardIdentifier, WorkerType}; use sgx_types::sgx_quote_sign_type_t; use std::string::String; pub(crate) fn sync_state< E: TlsRemoteAttestation + EnclaveBase + RemoteAttestation, - NodeApi: PalletTeerexApi, + NodeApi: PalletTeebagApi, WorkerModeProvider: ProvideWorkerMode, >( node_api: &NodeApi, @@ -70,30 +70,32 @@ pub(crate) fn sync_state< /// Note: The sidechainblock author will only change whenever a new parentchain block is /// produced. And even then, it might be the same as the last block. So if several workers /// are started in a timely manner, they will all get the same url. -async fn get_author_url_of_last_finalized_sidechain_block( +async fn get_author_url_of_last_finalized_sidechain_block( node_api: &NodeApi, shard: &ShardIdentifier, ) -> Result { let enclave = node_api - .worker_for_shard(shard, None)? + .primary_enclave_for_shard(WorkerType::Identity, shard, None)? .ok_or_else(|| Error::NoWorkerForShardFound(*shard))?; - let worker_api_direct = DirectWorkerApi::new(enclave.url); + let worker_api_direct = + DirectWorkerApi::new(String::from_utf8_lossy(enclave.url.as_slice()).to_string()); Ok(worker_api_direct.get_mu_ra_url()?) } /// Returns the url of the first Enclave that matches our own MRENCLAVE. /// /// This should be run before we register ourselves as enclave, to ensure we don't get our own url. -async fn get_enclave_url_of_first_registered( +async fn get_enclave_url_of_first_registered( node_api: &NodeApi, enclave_api: &EnclaveApi, ) -> Result { - let self_mr_enclave = enclave_api.get_fingerprint()?; + let self_mrenclave = enclave_api.get_fingerprint()?; let first_enclave = node_api - .all_enclaves(None)? + .all_enclaves(WorkerType::Identity, None)? .into_iter() - .find(|e| e.mr_enclave == self_mr_enclave.to_fixed_bytes()) + .find(|e| e.mrenclave == self_mrenclave.to_fixed_bytes()) .ok_or(Error::NoPeerWorkerFound)?; - let worker_api_direct = DirectWorkerApi::new(first_enclave.url); + let worker_api_direct = + DirectWorkerApi::new(String::from_utf8_lossy(first_enclave.url.as_slice()).to_string()); Ok(worker_api_direct.get_mu_ra_url()?) } diff --git a/tee-worker/service/src/teeracle/mod.rs b/tee-worker/service/src/teeracle/mod.rs deleted file mode 100644 index 415f7c461d..0000000000 --- a/tee-worker/service/src/teeracle/mod.rs +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::{error::ServiceResult, teeracle::schedule_periodic::schedule_periodic}; -use codec::{Decode, Encode}; -use itp_enclave_api::teeracle_api::TeeracleApi; -use itp_node_api::api_client::ParentchainApi; -use itp_types::parentchain::Hash; -use litentry_hex_utils::hex_encode; -use log::*; -use sp_runtime::OpaqueExtrinsic; -use std::time::Duration; -use substrate_api_client::{SubmitAndWatch, XtStatus}; -use teeracle_metrics::{increment_number_of_request_failures, set_extrinsics_inclusion_success}; -use tokio::runtime::Handle; - -pub(crate) mod schedule_periodic; -pub(crate) mod teeracle_metrics; - -/// Schedule periodic reregistration of the enclave. -/// -/// The `send_register_xt` needs to create a fresh registration extrinsic every time it is called -/// (updated nonce, fresh IAS-RA or DCAP-Quote). -/// -/// Currently, this is only used for the teeracle, but could also be used for other flavors in the -/// future. -pub(crate) fn schedule_periodic_reregistration_thread( - send_register_xt: impl Fn() -> Option + std::marker::Send + 'static, - period: Duration, -) { - println!("Schedule periodic enclave reregistration every: {:?}", period); - - std::thread::Builder::new() - .name("enclave_reregistration_thread".to_owned()) - .spawn(move || { - schedule_periodic( - || { - trace!("Reregistering the enclave."); - if let Some(block_hash) = send_register_xt() { - println!( - "✅ Successfully reregistered the enclave. Block hash: {}.", - block_hash - ) - } else { - error!("❌ Could not reregister the enclave.") - } - }, - period, - ); - }) - .unwrap(); -} - -/// Executes a periodic teeracle data update and sends the new data to the parentchain. -/// -/// Note: Puts the current thread to sleep for `period`. -pub(crate) fn start_periodic_market_update( - api: &ParentchainApi, - period: Duration, - enclave_api: &E, - tokio_handle: &Handle, -) { - let updates_to_run = || { - if let Err(e) = execute_oracle_update(api, tokio_handle, || { - // Get market data for usd (hardcoded) - enclave_api.update_market_data_xt("TEER", "USD") - }) { - error!("Error running market update {:?}", e) - } - - // TODO: Refactor and add this back according to ISSUE: https://github.com/integritee-network/worker/issues/1300 - // if let Err(e) = execute_oracle_update(api, tokio_handle, || { - // enclave_api.update_weather_data_xt("54.32", "15.37") - // }) { - // error!("Error running weather update {:?}", e) - // } - }; - info!("Teeracle will update now"); - updates_to_run(); - - info!("Schedule teeracle updates every {:?}", period); - schedule_periodic(updates_to_run, period); -} - -fn execute_oracle_update( - node_api: &ParentchainApi, - tokio_handle: &Handle, - get_oracle_xt: F, -) -> ServiceResult<()> -where - F: Fn() -> Result, itp_enclave_api::error::Error>, -{ - let oracle_xt = get_oracle_xt().map_err(|e| { - increment_number_of_request_failures(); - e - })?; - - let extrinsics = >::decode(&mut oracle_xt.as_slice())?; - - // Send the extrinsics to the parentchain and wait for InBlock confirmation. - for call in extrinsics.into_iter() { - let node_api_clone = node_api.clone(); - tokio_handle.spawn(async move { - let encoded_extrinsic = call.encode(); - debug!("Hex encoded extrinsic to be sent: {}", hex_encode(&encoded_extrinsic)); - - println!("[>] Update oracle data (send the extrinsic)"); - let extrinsic_hash = match node_api_clone.submit_and_watch_opaque_extrinsic_until( - &encoded_extrinsic.into(), - XtStatus::InBlock, - ) { - Err(e) => { - error!("Failed to send extrinsic: {:?}", e); - set_extrinsics_inclusion_success(false); - return - }, - Ok(report) => { - set_extrinsics_inclusion_success(true); - report.extrinsic_hash - }, - }; - - println!("[<] Extrinsic got included into a block. Hash: {:?}\n", extrinsic_hash); - }); - } - - Ok(()) -} diff --git a/tee-worker/service/src/teeracle/schedule_periodic.rs b/tee-worker/service/src/teeracle/schedule_periodic.rs deleted file mode 100644 index cde09af452..0000000000 --- a/tee-worker/service/src/teeracle/schedule_periodic.rs +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use std::{ - thread, - time::{Duration, Instant}, -}; - -/// Schedules a periodic task in the current thread. -/// -/// In case the task takes longer than is scheduled by the interval duration, -/// the interval timing will drift. The task is responsible for -/// ensuring it does not use up more time than is scheduled. -pub(super) fn schedule_periodic(task: T, period: Duration) -where - T: Fn(), -{ - let mut interval_start = Instant::now(); - loop { - let elapsed = interval_start.elapsed(); - - if elapsed >= period { - // update interval time - interval_start = Instant::now(); - task(); - } else { - // sleep for the rest of the interval - let sleep_time = period - elapsed; - thread::sleep(sleep_time); - } - } -} diff --git a/tee-worker/service/src/teeracle/teeracle_metrics.rs b/tee-worker/service/src/teeracle/teeracle_metrics.rs deleted file mode 100644 index 8fe62c2092..0000000000 --- a/tee-worker/service/src/teeracle/teeracle_metrics.rs +++ /dev/null @@ -1,76 +0,0 @@ -/* - Copyright 2021 Integritee AG and Supercomputing Systems AG - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -use crate::error::{Error, ServiceResult}; -use itp_enclave_metrics::ExchangeRateOracleMetric; -use lazy_static::lazy_static; -use prometheus::{ - register_gauge_vec, register_int_counter, register_int_counter_vec, register_int_gauge, - register_int_gauge_vec, GaugeVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, -}; - -lazy_static! { - /// Register Teeracle specific metrics - - static ref EXCHANGE_RATE: GaugeVec = - register_gauge_vec!("integritee_teeracle_exchange_rate", "Exchange rates partitioned into source and trading pair", &["source", "trading_pair"]) - .unwrap(); - static ref RESPONSE_TIME: IntGaugeVec = - register_int_gauge_vec!("integritee_teeracle_response_times", "Response times in ms for requests that the oracle makes", &["source"]) - .unwrap(); - static ref NUMBER_OF_REQUESTS: IntCounterVec = - register_int_counter_vec!("integritee_teeracle_number_of_requests", "Number of requests made per source", &["source"]) - .unwrap(); - - static ref NUMBER_OF_REQUEST_FAILURES: IntCounter = - register_int_counter!("integritee_teeracle_request_failures", "Number of requests that failed") - .unwrap(); - - static ref EXTRINSIC_INCLUSION_SUCCESS: IntGauge = - register_int_gauge!("integritee_teeracle_extrinsic_inclusion_success", "1 if extrinsics was successfully finalized, 0 if not") - .unwrap(); -} - -pub(super) fn increment_number_of_request_failures() { - NUMBER_OF_REQUEST_FAILURES.inc(); -} - -pub(super) fn set_extrinsics_inclusion_success(is_successful: bool) { - let success_values = i64::from(is_successful); - EXTRINSIC_INCLUSION_SUCCESS.set(success_values); -} - -pub fn update_teeracle_metrics(metric: ExchangeRateOracleMetric) -> ServiceResult<()> { - match metric { - ExchangeRateOracleMetric::ExchangeRate(source, trading_pair, exchange_rate) => - EXCHANGE_RATE - .get_metric_with_label_values(&[source.as_str(), trading_pair.as_str()]) - .map(|m| m.set(exchange_rate.to_num())) - .map_err(|e| Error::Custom(e.into()))?, - - ExchangeRateOracleMetric::ResponseTime(source, t) => RESPONSE_TIME - .get_metric_with_label_values(&[source.as_str()]) - .map(|m| m.set(t as i64)) - .map_err(|e| Error::Custom(e.into()))?, - - ExchangeRateOracleMetric::NumberRequestsIncrement(source) => NUMBER_OF_REQUESTS - .get_metric_with_label_values(&[source.as_str()]) - .map(|m| m.inc()) - .map_err(|e| Error::Custom(e.into()))?, - }; - Ok(()) -} diff --git a/tee-worker/service/src/tests/mock.rs b/tee-worker/service/src/tests/mock.rs index 0587669dc4..a36ae0a5ce 100644 --- a/tee-worker/service/src/tests/mock.rs +++ b/tee-worker/service/src/tests/mock.rs @@ -15,8 +15,8 @@ */ -use itp_node_api::api_client::{ApiResult, PalletTeerexApi}; -use itp_types::{Enclave, MrEnclave, ShardIdentifier, H256 as Hash}; +use itp_node_api::api_client::{ApiResult, PalletTeebagApi}; +use itp_types::{AccountId, Enclave, MrEnclave, ShardIdentifier, WorkerType, H256 as Hash}; use std::collections::HashSet; pub struct TestNodeApi; @@ -26,43 +26,44 @@ pub const W2_URL: &str = "127.0.0.1:33333"; pub fn enclaves() -> Vec { vec![ - Enclave::new([0; 32].into(), [1; 32], 1, format!("wss://{}", W1_URL)), - Enclave::new([2; 32].into(), [3; 32], 2, format!("wss://{}", W2_URL)), + Enclave::new(WorkerType::Identity).with_url(W1_URL.into()), + Enclave::new(WorkerType::Identity).with_url(W2_URL.into()), ] } -impl PalletTeerexApi for TestNodeApi { +impl PalletTeebagApi for TestNodeApi { type Hash = Hash; - fn enclave(&self, index: u64, _at_block: Option) -> ApiResult> { - Ok(Some(enclaves().remove(index as usize))) + fn enclave(&self, _account: &AccountId, _at_block: Option) -> ApiResult> { + unreachable!() } - fn enclave_count(&self, _at_block: Option) -> ApiResult { + fn enclave_count(&self, _worker_type: WorkerType, _at_block: Option) -> ApiResult { unreachable!() } - fn all_enclaves(&self, _at_block: Option) -> ApiResult> { + fn all_enclaves( + &self, + _worker_type: WorkerType, + _at_block: Option, + ) -> ApiResult> { Ok(enclaves()) } - fn worker_for_shard( + fn primary_enclave_identifier_for_shard( &self, - _: &ShardIdentifier, - _at_block: Option, - ) -> ApiResult> { + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { unreachable!() } - fn latest_ipfs_hash( + + fn primary_enclave_for_shard( &self, - _: &ShardIdentifier, - _at_block: Option, - ) -> ApiResult> { + worker_type: WorkerType, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { unreachable!() } - - fn all_scheduled_mrenclaves(&self, _at_block: Option) -> ApiResult> { - let enclaves = enclaves(); - let mr_enclaves: HashSet<_> = enclaves.into_iter().map(|e| e.mr_enclave).collect(); - Ok(mr_enclaves.into_iter().collect()) - } } diff --git a/tee-worker/service/src/tests/mocks/enclave_api_mock.rs b/tee-worker/service/src/tests/mocks/enclave_api_mock.rs index af27dd3fae..e9b5d4c884 100644 --- a/tee-worker/service/src/tests/mocks/enclave_api_mock.rs +++ b/tee-worker/service/src/tests/mocks/enclave_api_mock.rs @@ -24,10 +24,9 @@ use itc_parentchain::primitives::{ use itp_enclave_api::{enclave_base::EnclaveBase, sidechain::Sidechain, EnclaveResult}; use itp_settings::worker::MR_ENCLAVE_SIZE; use itp_storage::StorageProof; -use itp_types::ShardIdentifier; +use itp_types::{EnclaveFingerprint, ShardIdentifier}; use sgx_crypto_helper::rsa3072::Rsa3072PubKey; use sp_core::ed25519; -use teerex_primitives::EnclaveFingerprint; /// mock for EnclaveBase - use in tests pub struct EnclaveMock; diff --git a/tee-worker/service/src/worker.rs b/tee-worker/service/src/worker.rs index 638e4f081b..9f96b2a94f 100644 --- a/tee-worker/service/src/worker.rs +++ b/tee-worker/service/src/worker.rs @@ -25,13 +25,14 @@ use async_trait::async_trait; use codec::{Decode, Encode}; use itc_rpc_client::direct_client::{DirectApi, DirectClient as DirectWorkerApi}; use itp_enclave_api::enclave_base::EnclaveBase; -use itp_node_api::{api_client::PalletTeerexApi, node_api_factory::CreateNodeApi}; +use itp_node_api::{api_client::PalletTeebagApi, node_api_factory::CreateNodeApi}; use its_primitives::types::SignedBlock as SignedSidechainBlock; use its_rpc_handler::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; use jsonrpsee::{ types::{to_json_value, traits::Client}, ws_client::WsClientBuilder, }; +use litentry_primitives::WorkerType; use log::*; use std::{ collections::HashSet, @@ -187,11 +188,11 @@ where .node_api_factory .create_api() .map_err(|e| Error::Custom(format!("Failed to create NodeApi: {:?}", e).into()))?; - let enclaves = node_api.all_enclaves(None)?; + let enclaves = node_api.all_enclaves(WorkerType::Identity, None)?; let mut peer_urls = HashSet::::new(); for enclave in enclaves { // FIXME: This is temporary only, as block broadcasting should be moved to trusted ws server. - let enclave_url = enclave.url.clone(); + let enclave_url = String::from_utf8_lossy(enclave.url.as_slice()).to_string(); let worker_api_direct = DirectWorkerApi::new(enclave_url.clone()); match worker_api_direct.get_untrusted_worker_url() { Ok(untrusted_worker_url) => { diff --git a/tee-worker/sidechain/consensus/aura/src/lib.rs b/tee-worker/sidechain/consensus/aura/src/lib.rs index 2ca8b88edb..4114852c73 100644 --- a/tee-worker/sidechain/consensus/aura/src/lib.rs +++ b/tee-worker/sidechain/consensus/aura/src/lib.rs @@ -47,7 +47,7 @@ use its_primitives::{ use its_validateer_fetch::ValidateerFetch; use lc_scheduled_enclave::ScheduledEnclaveUpdater; use litentry_hex_utils::hex_encode; -use sp_core::ByteArray; +use sp_core::crypto::UncheckedFrom; use sp_runtime::{ app_crypto::{sp_core::H256, Pair}, generic::SignedBlock as SignedParentchainBlock, @@ -189,6 +189,7 @@ impl< StateHandler, > where AuthorityPair: Pair, + AuthorityPair::Public: UncheckedFrom<[u8; 32]>, // todo: Relax hash trait bound, but this needs a change to some other parts in the code. ParentchainBlock: ParentchainBlockTrait, E: Environment, @@ -222,7 +223,6 @@ impl< fn epoch_data( &self, header: &ParentchainBlock::Header, - _shard: ShardIdentifierFor, _slot: Slot, ) -> Result { authorities::<_, AuthorityPair, ParentchainBlock::Header>(&self.ocall_api, header) @@ -391,13 +391,14 @@ fn authorities( where ValidateerFetcher: ValidateerFetch + EnclaveOnChainOCallApi, P: Pair, + P::Public: UncheckedFrom<[u8; 32]>, ParentchainHeader: ParentchainHeaderTrait, { Ok(ocall_api - .current_validateers(header) + .current_validateers::(header) .map_err(|e| ConsensusError::CouldNotGetAuthorities(e.to_string()))? - .into_iter() - .filter_map(|e| AuthorityId::

::from_slice(e.pubkey.as_ref()).ok()) + .iter() + .map(|account| P::Public::unchecked_from(*account.as_ref())) .collect()) } @@ -411,14 +412,14 @@ pub enum AnyImportTrigger { mod tests { use super::*; use crate::test::{ - fixtures::{types::TestAura, validateer, SLOT_DURATION}, + fixtures::{types::TestAura, SLOT_DURATION}, mocks::environment_mock::{EnvironmentMock, OutdatedBlockEnvironmentMock}, }; use itc_parentchain_block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; use itc_parentchain_test::{ParentchainBlockBuilder, ParentchainHeaderBuilder}; use itp_test::mock::{handle_state_mock::HandleStateMock, onchain_mock::OnchainMock}; use itp_types::{ - Block as ParentchainBlock, Enclave, Header as ParentchainHeader, ShardIdentifier, + AccountId, Block as ParentchainBlock, Header as ParentchainHeader, ShardIdentifier, SignedBlock as SignedParentchainBlock, }; use its_consensus_slots::PerShardSlotWorkerScheduler; @@ -483,8 +484,8 @@ mod tests { vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()] } - fn create_validateer_set_from_publics(authorities: Vec) -> Vec { - authorities.iter().map(|a| validateer(a.clone().into())).collect() + fn create_validateer_set_from_publics(authorities: Vec) -> Vec { + authorities.iter().map(|a| AccountId::from(a.clone())).collect() } fn onchain_mock( diff --git a/tee-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs b/tee-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs index 447aa18c62..be23004cf0 100644 --- a/tee-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs +++ b/tee-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs @@ -87,10 +87,10 @@ fn test_fixtures( ) -> (TestBlockImporter, Arc, Arc) { let state_handler = Arc::new(HandleStateMock::from_shard(shard()).unwrap()); let top_pool_author = Arc::new(TestTopPoolAuthor::default()); - let ocall_api = Arc::new(OnchainMock::default().add_validateer_set( - parentchain_header, - Some(vec![validateer(Keyring::Alice.public().into())]), - )); + let ocall_api = Arc::new( + OnchainMock::default() + .add_validateer_set(parentchain_header, Some(vec![Keyring::Alice.public().into()])), + ); let state_key_repository = Arc::new(TestStateKeyRepo::new(state_key())); let peer_updater_mock = Arc::new(PeerUpdaterMock {}); diff --git a/tee-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs b/tee-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs index 54d47324fa..de85405549 100644 --- a/tee-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs +++ b/tee-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs @@ -23,5 +23,5 @@ use std::time::Duration; pub const SLOT_DURATION: Duration = Duration::from_millis(300); pub fn validateer(account: AccountId) -> Enclave { - Enclave::new(account, Default::default(), Default::default(), Default::default()) + Enclave::default() } diff --git a/tee-worker/sidechain/consensus/aura/src/verifier.rs b/tee-worker/sidechain/consensus/aura/src/verifier.rs index 0c1f64b138..121cef58eb 100644 --- a/tee-worker/sidechain/consensus/aura/src/verifier.rs +++ b/tee-worker/sidechain/consensus/aura/src/verifier.rs @@ -24,6 +24,7 @@ use its_primitives::{ types::block::BlockHash, }; use its_validateer_fetch::ValidateerFetch; +use sp_core::crypto::UncheckedFrom; use sp_runtime::{app_crypto::Pair, traits::Block as ParentchainBlockTrait}; use std::{fmt::Debug, time::Duration}; @@ -57,7 +58,7 @@ impl for AuraVerifier where AuthorityPair: Pair, - AuthorityPair::Public: Debug, + AuthorityPair::Public: Debug + UncheckedFrom<[u8; 32]>, // todo: Relax hash trait bound, but this needs a change to some other parts in the code. ParentchainBlock: ParentchainBlockTrait, SignedSidechainBlock: SignedSidechainBlockTrait + 'static, diff --git a/tee-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs b/tee-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs index be93feb51c..ee2b5f3ede 100644 --- a/tee-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs +++ b/tee-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs @@ -20,7 +20,7 @@ use itc_parentchain_light_client::{ concurrent_access::ValidatorAccess, BlockNumberOps, ExtrinsicSender, NumberFor, }; use itp_extrinsics_factory::CreateExtrinsics; -use itp_node_api_metadata::{pallet_sidechain::SidechainCallIndexes, NodeMetadataTrait}; +use itp_node_api_metadata::{pallet_teebag::TeebagCallIndexes, NodeMetadataTrait}; use itp_node_api_metadata_provider::AccessNodeMetadata; use itp_settings::worker::BLOCK_NUMBER_FINALIZATION_DIFF; use itp_types::{OpaqueCall, ShardIdentifier}; @@ -102,7 +102,7 @@ impl< fn confirm_import(&self, header: &SidechainHeader, shard: &ShardIdentifier) -> Result<()> { let call = self .metadata_repository - .get_from_metadata(|m| m.confirm_imported_sidechain_block_indexes()) + .get_from_metadata(|m| m.sidechain_block_imported_call_indexes()) .map_err(|e| Error::Other(e.into()))? .map_err(|e| Error::Other(format!("{:?}", e).into()))?; diff --git a/tee-worker/sidechain/consensus/slots/src/lib.rs b/tee-worker/sidechain/consensus/slots/src/lib.rs index e09e55b1d6..b2201cfb08 100644 --- a/tee-worker/sidechain/consensus/slots/src/lib.rs +++ b/tee-worker/sidechain/consensus/slots/src/lib.rs @@ -206,7 +206,6 @@ pub trait SimpleSlotWorker { fn epoch_data( &self, header: &ParentchainBlock::Header, - shard: ShardIdentifierFor, slot: Slot, ) -> Result; @@ -329,7 +328,7 @@ pub trait SimpleSlotWorker { maybe_latest_target_b_parentchain_header.clone().map(|h| *h.number()) ); - let epoch_data = match self.epoch_data(&latest_integritee_parentchain_header, shard, slot) { + let epoch_data = match self.epoch_data(&latest_integritee_parentchain_header, slot) { Ok(epoch_data) => epoch_data, Err(e) => { warn!( @@ -467,7 +466,7 @@ pub trait SimpleSlotWorker { }; if is_single_worker { - error!("Running as single worker, skipping timestamp within slot check") + warn!("Running as single worker, skipping timestamp within slot check") } else if !timestamp_within_slot(&slot_info, &proposing.block) { warn!( "⌛️ Discarding proposal for slot {}, block number {}; block production took too long", diff --git a/tee-worker/sidechain/consensus/slots/src/mocks.rs b/tee-worker/sidechain/consensus/slots/src/mocks.rs index c84467640d..72d6f9fee8 100644 --- a/tee-worker/sidechain/consensus/slots/src/mocks.rs +++ b/tee-worker/sidechain/consensus/slots/src/mocks.rs @@ -70,12 +70,7 @@ where todo!() } - fn epoch_data( - &self, - _header: &B::Header, - _shard: ShardIdentifierFor, - _slot: Slot, - ) -> Result { + fn epoch_data(&self, _header: &B::Header, _slot: Slot) -> Result { todo!() } diff --git a/tee-worker/sidechain/peer-fetch/Cargo.toml b/tee-worker/sidechain/peer-fetch/Cargo.toml index 63e2612d91..66c10302c9 100644 --- a/tee-worker/sidechain/peer-fetch/Cargo.toml +++ b/tee-worker/sidechain/peer-fetch/Cargo.toml @@ -16,6 +16,7 @@ thiserror = { version = "1.0" } # local itc-rpc-client = { path = "../../core/rpc-client" } itp-node-api = { path = "../../core-primitives/node-api" } +itp-types = { path = "../../core-primitives/types" } its-primitives = { path = "../primitives" } its-rpc-handler = { path = "../rpc-handler" } its-storage = { path = "../storage" } diff --git a/tee-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs b/tee-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs index 7ff9434103..488590f761 100644 --- a/tee-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs +++ b/tee-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs @@ -17,7 +17,8 @@ use crate::error::{Error, Result}; use itc_rpc_client::direct_client::{DirectApi, DirectClient as DirectWorkerApi}; -use itp_node_api::{api_client::PalletTeerexApi, node_api_factory::CreateNodeApi}; +use itp_node_api::{api_client::PalletTeebagApi, node_api_factory::CreateNodeApi}; +use itp_types::WorkerType; use its_primitives::types::ShardIdentifier; use std::sync::Arc; @@ -50,10 +51,11 @@ where let node_api = self.node_api_factory.create_api()?; let validateer = node_api - .worker_for_shard(shard, None)? + .primary_enclave_for_shard(WorkerType::Identity, shard, None)? .ok_or_else(|| Error::NoPeerFoundForShard(*shard))?; - let trusted_worker_client = DirectWorkerApi::new(validateer.url); + let trusted_worker_client = + DirectWorkerApi::new(String::from_utf8_lossy(validateer.url.as_slice()).to_string()); Ok(trusted_worker_client.get_untrusted_worker_url()?) } } diff --git a/tee-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs b/tee-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs index d832e91024..afd5990600 100644 --- a/tee-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs +++ b/tee-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs @@ -349,11 +349,11 @@ async fn request_vc_inner(params: Params) -> Result { Ok(RpcReturnValue { do_watch: false, value: response, status: DirectRequestStatus::Ok }), Ok(Err(e)) => { log::error!("Received error in jsonresponse: {:?} ", e); - Err(compute_hex_encoded_return_error(&e)) + Err(e) }, Err(_) => { // This case will only happen if the sender has been dropped - Err(compute_hex_encoded_return_error("The sender has been dropped")) + Err("The sender has been dropped".to_string()) }, } } diff --git a/tee-worker/sidechain/validateer-fetch/Cargo.toml b/tee-worker/sidechain/validateer-fetch/Cargo.toml index 7aca2dbf7a..2df88400d5 100644 --- a/tee-worker/sidechain/validateer-fetch/Cargo.toml +++ b/tee-worker/sidechain/validateer-fetch/Cargo.toml @@ -15,11 +15,8 @@ sp-std = { default-features = false, git = "https://github.com/paritytech/substr # local deps itp-ocall-api = { path = "../../core-primitives/ocall-api", default-features = false } -itp-teerex-storage = { path = "../../core-primitives/teerex-storage", default-features = false } itp-types = { path = "../../core-primitives/types", default-features = false } - -# litentry -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +lc-teebag-storage = { path = "../../litentry/core/teebag-storage", default-features = false } [features] default = ["std"] @@ -30,7 +27,7 @@ std = [ "sp-std/std", "itp-types/std", "itp-ocall-api/std", - "frame-support/std", + "lc-teebag-storage/std", ] [dev-dependencies] diff --git a/tee-worker/sidechain/validateer-fetch/src/validateer.rs b/tee-worker/sidechain/validateer-fetch/src/validateer.rs index 4af8d86274..37373c0f32 100644 --- a/tee-worker/sidechain/validateer-fetch/src/validateer.rs +++ b/tee-worker/sidechain/validateer-fetch/src/validateer.rs @@ -16,10 +16,9 @@ */ use crate::error::{Error, Result}; -use frame_support::ensure; use itp_ocall_api::EnclaveOnChainOCallApi; -use itp_teerex_storage::{TeeRexStorage, TeerexStorageKeys}; -use itp_types::{parentchain::ParentchainId, Enclave}; +use itp_types::{parentchain::ParentchainId, AccountId, WorkerType}; +use lc_teebag_storage::{TeebagStorage, TeebagStorageKeys}; use sp_core::H256; use sp_runtime::traits::Header as HeaderT; use sp_std::prelude::Vec; @@ -28,7 +27,8 @@ pub trait ValidateerFetch { fn current_validateers>( &self, latest_header: &Header, - ) -> Result>; + ) -> Result>; + fn validateer_count>(&self, latest_header: &Header) -> Result; } @@ -37,31 +37,21 @@ impl ValidateerFetch for OnchainStorage fn current_validateers>( &self, header: &Header, - ) -> Result> { - let count = self.validateer_count(header)?; - - let mut hashes = Vec::with_capacity(count as usize); - for i in 1..=count { - hashes.push(TeeRexStorage::enclave(i)) - } - - let enclaves: Vec = self - .get_multiple_storages_verified(hashes, header, &ParentchainId::Litentry)? - .into_iter() - .filter_map(|e| e.into_tuple().1) - .collect(); - ensure!( - enclaves.len() == count as usize, - Error::Other("Found less validateers onchain than validateer count") - ); - Ok(enclaves) + ) -> Result> { + let identifiers = self + .get_storage_verified( + TeebagStorage::enclave_identifier(WorkerType::Identity), + header, + &ParentchainId::Litentry, + )? + .into_tuple() + .1 + .ok_or_else(|| Error::Other("Could not get validateer list from chain"))?; + Ok(identifiers) } fn validateer_count>(&self, header: &Header) -> Result { - self.get_storage_verified(TeeRexStorage::enclave_count(), header, &ParentchainId::Litentry)? - .into_tuple() - .1 - .ok_or_else(|| Error::Other("Could not get validateer count from chain")) + Ok(self.current_validateers::

(header)?.len() as u64) } } @@ -84,21 +74,7 @@ mod tests { pub fn get_validateer_set_works() { let header = ParentchainHeaderBuilder::default().build(); let mock = OnchainMock::default().add_validateer_set(&header, None); - let validateers = validateer_set(); - assert_eq!(mock.current_validateers(&header).unwrap(), validateers); } - - #[test] - pub fn if_validateer_count_bigger_than_returned_validateers_return_err() { - let header = ParentchainHeaderBuilder::default().build(); - let mut mock = OnchainMock::default().add_validateer_set(&header, None); - mock.insert_at_header(&header, TeeRexStorage::enclave_count(), 5u64.encode()); - - assert_eq!( - mock.current_validateers(&header).unwrap_err().to_string(), - "Found less validateers onchain than validateer count".to_string() - ); - } } diff --git a/tee-worker/ts-tests/README.md b/tee-worker/ts-tests/README.md index e989771f35..bb69030767 100644 --- a/tee-worker/ts-tests/README.md +++ b/tee-worker/ts-tests/README.md @@ -29,14 +29,18 @@ pnpm install ## Usage(ts-tests folder) -II identity test: `pnpm --filter integration-tests run test-ii-identity:local` +``` +pnpm --filter integration-tests run test your-testfile.test.ts +``` + +II identity test: `pnpm --filter integration-tests run test ii_identity.test.ts` -II vc test: `pnpm --filter integration-tests run test-ii-vc:local` +II vc test: `pnpm --filter integration-tests run test ii_vc.test.ts` -II batch identity test: `pnpm --filter integration-tests run test-ii-batch:local` +II batch identity test: `pnpm --filter integration-tests run test ii_batch.test.ts` -Direct invocation substrate identity test: `pnpm --filter integration-tests run test-di-substrate-identity:local` +Direct invocation substrate identity test: `pnpm --filter integration-tests run test di_substrate_identity.test.ts` -Direct invocation evm identity test: `pnpm --filter integration-tests run test-di-evm-identity:local` +Direct invocation evm identity test: `pnpm --filter integration-tests run test di_evm_identity.test.ts` -Direct invocation vc test: `pnpm --filter integration-tests run test-di-vc:local` \ No newline at end of file +Direct invocation vc test: `pnpm --filter integration-tests run test di_vc.test.ts` diff --git a/tee-worker/ts-tests/integration-tests/common/config.js b/tee-worker/ts-tests/integration-tests/common/config.js index 3226f64181..3dbb229aa4 100644 --- a/tee-worker/ts-tests/integration-tests/common/config.js +++ b/tee-worker/ts-tests/integration-tests/common/config.js @@ -1,4 +1,4 @@ import dotenv from 'dotenv'; // eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef -dotenv.config({ path: `.env.${process.env.NODE_ENV}` }); +dotenv.config({ path: `.env.${process.env.NODE_ENV || 'local'}` }); diff --git a/tee-worker/ts-tests/integration-tests/common/credential-json/achainable.json b/tee-worker/ts-tests/integration-tests/common/credential-json/achainable.json new file mode 100644 index 0000000000..cf1a986f3b --- /dev/null +++ b/tee-worker/ts-tests/integration-tests/common/credential-json/achainable.json @@ -0,0 +1,251 @@ +[ + { + "id": "bab-holder", + "name": "Trustworthy Binance user", + "description": "You are holding a Binance Account Bound(BAB) token", + "assertion": { + "id": "Achainable", + "payload": { + "Basic": { + "name": "BAB token holder", + "chain": "Bsc" + } + } + }, + "dataProvider": "achainable", + "network": "ethereum", + "mockDid": "litentry:evm:0xdB01C6a38E780a2644b3B26961b14313b019714a", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "uniswap-v2-v3-user", + "name": "Uniswap V2/V3 User", + "description": "You are a trader or liquidity provider of Uniswap V2 or V3\nUniswap V2 Factory Contract: 0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f\nUniswap V3 Factory Contract: 0x1f98431c8ad98523631ae4a59f267346ea31f984", + "assertion": { + "id": "Achainable", + "payload": { + "Basic": { + "name": "Uniswap V2/V3 user", + "chain": "Ethereum" + } + } + }, + "dataProvider": "achainable", + "network": "ethereum", + "mockDid": "litentry:evm:0x7031a420603a83EFBE85503e5A4BF562121A85ab", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "dot-holder", + "name": "DOT Holding Time", + "description": "The length of time a user continues to hold DOT token (threshold DOT > 5)", + "assertion": { + "id": "A7", + "payload": "5" + }, + "dataProvider": "achainable", + "network": "polkadot", + "mockDid": "litentry:substrate:0xbf6e312fd006908b0152da113ec73b9ffc9983f9b848698180b9b43c5ad44681", + "mockWeb3Network": "litentry,polkadot", + "expectedCredentialValue": true + }, + { + "id": "eth-holder", + "name": "ETH Holding Time", + "description": "The length of time a user continues to hold ETH token (threshold ETH > 0.01)", + "assertion": { + "id": "A11", + "payload": "0.01" + }, + "dataProvider": "achainable", + "network": "ethereum", + "mockDid": "litentry:evm:0x6887246668a3b87F54DeB3b94Ba47a6f63F32985", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": false + }, + { + "id": "wbtc-holder", + "name": "WBTC Holding Time", + "description": "The length of time a user continues to hold WBTC token (threshold WBTC > 0.001)", + "assertion": { + "id": "A10", + "payload": 0.001 + }, + "dataProvider": "achainable", + "network": "ethereum", + "mockDid": "litentry:evm:0x5680b3FcBB64FB161adbD347BC92e8DDEDA97008", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "lit-holder", + "name": "LIT Holding Time", + "description": "The length of time a user continues to hold LIT token (threshold LIT > 10)", + "assertion": { + "id": "A4", + "payload": "10" + }, + "dataProvider": "achainable", + "network": "litentry", + "mockDid": "litentry:substrate:0x6c7fdb8b8eaad1af9faaf918493606e1a3e8c20f9d852773ab5ebfbb93bd1948", + "mockWeb3Network": "litentry,polkadot", + "expectedCredentialValue": true + }, + { + "id": "ethereum-account-class-of-year", + "name": "Ethereum Account Class of Year", + "description": "The class of year that your Ethereum account was created (must have on-chain records)", + "assertion": { + "id": "achainable", + "payload": { + "ClassOfYear": { + "name": "Account created between {dates}", + "chain": "Ethereum" + } + } + }, + "dataProvider": "achainable", + "network": "ethereum", + "mockDid": "litentry:evm:0x3D66aF7cBeb2d9c6b4497a2269F7e3fcd9996524", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "evm-transaction-count", + "name": "ETH Transaction Count", + "description": "Your total transaction amount on these EVM networks: Ethereum", + "assertion": { + "id": "A8", + "payload": ["Ethereum"] + }, + "dataProvider": "achainable", + "network": "ethereum", + "mockDid": "litentry:evm:0xb144EeFd29B2E448419fd8dD6Cd6c7EB258D4715", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": false + }, + { + "id": "litentry-transaction-count", + "name": "LIT Transaction Count", + "description": "Your total transaction amount on these Substrate networks: Litentry, Litmus, Ethereum.", + "assertion": { + "id": "A8", + "payload": ["Litentry", "Litmus", "Ethereum"] + }, + "dataProvider": "achainable", + "network": "litentry", + "mockDid": "litentry:substrate:0xcacb83fc3d36caa4d03a80c0669aa19b38ffd1a9bb54d78b719fac1942816b40", + "mockWeb3Network": "litentry,polkadot", + "expectedCredentialValue": true + }, + { + "id": "polkadot-governance-participation", + "name": "Polkadot Governance Participation Proof", + "description": "You have ever participated in any Polkadot on-chain governance events. This credential is counting: Technical Committee Proposals, Democracy Proposals, Council Proposals, Proposal Seconds, Proposal Votes, Democracy Votes, Council Votes, Treasury Spend Proposals.", + "assertion": { + "id": "A14", + "payload": [] + }, + "dataProvider": "achainable", + "network": "litentry", + "mockDid": "litentry:substrate:0x5FeEE1E799015A22EbD216d43484FCB3BA88de20", + "mockWeb3Network": "litentry,polkadot", + "expectedCredentialValue": true + }, + { + "id": "contract-creator", + "name": "Ethereum Contract Creator", + "description": "You are a deployer of a smart contract on these networks: Ethereum", + "assertion": { + "id": "Achainable", + "payload": { + "Amount": { + "name": "Created over {amount} contracts", + "chain": "Ethereum", + "amount": "0" + } + } + }, + "dataProvider": "achainable", + "network": "ethereum", + "mockDid": "litentry:evm:0x11fBffc1F3dF23E7219e2B3036fe2A12C10cD3AD", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holder-dot", + "name": "DOT Holder", + "description": "The number of DOT tokens you hold > 0", + "assertion": { + "id": "Achainable", + "payload": { + "Amount": { + "name": "Balance over {amount}", + "chain": "Polkadot", + "amount": "0" + } + } + }, + "dataProvider": "achainable", + "network": "litentry", + "mockDid": "litentry:substrate:0x0d584a4cbbfd9a4878d816512894e65918e54fae13df39a6f520fc90caea2fb0", + "mockWeb3Network": "litentry,polkadot", + "expectedCredentialValue": true + }, + { + "id": "token-holder-eth", + "name": "ETH Holder", + "description": "The number of ETH tokens you hold > 0", + "assertion": { + "id": "Achainable", + "payload": { + "Amount": { + "name": "Balance over {amount}", + "chain": "Ethereum", + "amount": "0" + } + } + }, + "dataProvider": "achainable", + "network": "litentry", + "mockDid": "litentry:evm:0x66485bB62896Bd7bE54dE8E2050cc8746a50E0b2", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holder-lit", + "name": "LIT Holder", + "description": "The number of LIT tokens you hold > 0", + "assertion": { + "id": "Achainable", + "payload": { + "Amount": { + "name": "Balance over {amount}", + "chain": "Litentry", + "amount": "0" + } + } + }, + "dataProvider": "achainable", + "network": "litentry", + "mockDid": "litentry:substrate:0xc0103c4b56ce752d05b16a88260e3a9e2c44306602a74c5edd1cd4ff56356f7c", + "mockWeb3Network": "litentry,polkadot", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-btcs", + "name": "BTCS Holding Time", + "description": "The number of BTCS tokens you hold > 0", + "assertion": { + "id": "Brc20AmountHolder", + "payload": [] + }, + "dataProvider": "achainable", + "network": "litentry", + "mockDid": "litentry:bitcoin:0x030b0998ea7d5052e3016bd8c83f920f452f6102c06e91a2880556b91db68bce90", + "mockWeb3Network": "BitcoinP2tr", + "expectedCredentialValue": null + } +] diff --git a/tee-worker/ts-tests/integration-tests/common/credential-json/discord.json b/tee-worker/ts-tests/integration-tests/common/credential-json/discord.json new file mode 100644 index 0000000000..3f3f28c2f4 --- /dev/null +++ b/tee-worker/ts-tests/integration-tests/common/credential-json/discord.json @@ -0,0 +1,110 @@ +[ + { + "id": "id-hubber", + "name": "Active Discord ID-Hubber", + "description": "You have commented in Litentry Discord #🪂id-hubber channel. Channel link: https://discord.com/channels/807161594245152800/1093886939746291882", + "assertion": { + "id": "A3", + "payload": ["807161594245152800", "1093886939746291882", "1088092822592307240"] + }, + "dataProvider": "discord", + "network": "discord", + "mockDid": "litentry:discord:niceguy2309", + "mockWeb3Network": "", + "expectedCredentialValue": true + }, + { + "id": "join-litentry-discord", + "name": "Litentry Discord Member", + "description": "The user is a member of Litentry Discord.\nServer link: 'https://discord.gg/phBSa3eMX9'.\nGuild ID: 807161594245152800", + "assertion": { + "id": "A2", + "payload": "807161594245152800" + }, + "dataProvider": "discord", + "network": "discord", + "mockDid": "litentry:discord:almuyaad_jr", + "mockWeb3Network": "", + "expectedCredentialValue": true + }, + { + "id": "litentry-and-sora-quiz-attendee", + "name": "Litentry & SORA Quiz Attendee", + "description": "Congratulations on your participation in our first quiz in collaboration with our partner, SORA. You have embarked on an exciting educational journey, exploring the world of DeFi & Web3 Identity, we truly appreciate your curiosity and dedication.", + "assertion": { + "id": "GenericDiscordRole", + "payload": { + "soraquiz": "attendee" + } + }, + "dataProvider": "discord", + "network": "discord", + "mockDid": "litentry:discord:light_bearer01", + "mockWeb3Network": "", + "expectedCredentialValue": false + }, + { + "id": "litentry-and-ordinals-user", + "name": "Litentry & Ordinals User", + "description": "Litentry Participants in the Bitcoin Ecosystem", + "assertion": { + "id": "GenericDiscordRole", + "payload": { + "soraquiz": "master" + } + }, + "dataProvider": "discord", + "network": "discord", + "mockDid": "litentry:discord:cynthian09021", + "mockWeb3Network": "", + "expectedCredentialValue": false + }, + { + "id": "score-contest-legend", + "name": "Contest Legend", + "description": "You got the Top Award of community contest", + "assertion": { + "id": "GenericDiscordRole", + "payload": { + "soraquiz": "legend" + } + }, + "dataProvider": "discord", + "network": "discord", + "mockDid": "litentry:discord:zawmyosatservice0737", + "mockWeb3Network": "", + "expectedCredentialValue": false + }, + { + "id": "score-contest-popularity", + "name": "Contest Popularity", + "description": "You got the Popularity of community contest", + "assertion": { + "id": "GenericDiscordRole", + "payload": { + "soraquiz": "popularity" + } + }, + "dataProvider": "discord", + "network": "discord", + "mockDid": "litentry:discord:eudizjr", + "mockWeb3Network": "", + "expectedCredentialValue": false + }, + { + "id": "score-contest-participant", + "name": "Contest Participant", + "description": "You got the Participant of community contest", + "assertion": { + "id": "GenericDiscordRole", + "payload": { + "soraquiz": "participant" + } + }, + "dataProvider": "discord", + "network": "discord", + "mockDid": "litentry:discord:neo_travolta", + "mockWeb3Network": "", + "expectedCredentialValue": false + } +] diff --git a/tee-worker/ts-tests/integration-tests/common/credential-json/index.ts b/tee-worker/ts-tests/integration-tests/common/credential-json/index.ts index 19f9c55267..6d7af24221 100644 --- a/tee-worker/ts-tests/integration-tests/common/credential-json/index.ts +++ b/tee-worker/ts-tests/integration-tests/common/credential-json/index.ts @@ -1,16 +1,24 @@ import { CorePrimitivesAssertion, CorePrimitivesNetworkWeb3Network } from 'parachain-api'; import type { Codec } from '@polkadot/types-codec/types'; import type { U8aLike } from '@polkadot/util/types'; -type DataProvider = { - id: string; - name: string; - url: string; -}; type AssertionGenericPayload = string | Array | Record; -import vip3Json from './vip3-credential-test.json' assert { type: 'json' }; -export const vip3CredentialJson = vip3Json as unknown as CredentialDefinition[]; +import vip3Json from './vip3.json' assert { type: 'json' }; +import achainableJson from './achainable.json' assert { type: 'json' }; +import noderealJson from './nodereal.json' assert { type: 'json' }; +import discordJson from './discord.json' assert { type: 'json' }; +import litentryJson from './litentry.json' assert { type: 'json' }; +import twitterJson from './twitter.json' assert { type: 'json' }; +import oneblockJson from './oneblock.json' assert { type: 'json' }; +export const vip3 = vip3Json as unknown as CredentialDefinition[]; +export const achainable = achainableJson as unknown as CredentialDefinition[]; +export const nodereal = noderealJson as unknown as CredentialDefinition[]; +export const discord = discordJson as unknown as CredentialDefinition[]; +export const litentry = litentryJson as unknown as CredentialDefinition[]; +export const twitter = twitterJson as unknown as CredentialDefinition[]; +export const oneblock = oneblockJson as unknown as CredentialDefinition[]; +export const credentialsJson = [...vip3, ...achainable, ...nodereal, ...litentry, ...twitter, ...oneblock, ...discord]; export interface CredentialDefinition { id: string; @@ -20,7 +28,7 @@ export interface CredentialDefinition { id: CorePrimitivesAssertion['type']; payload: AssertionGenericPayload; }; - dataProvider: DataProvider; + dataProvider: string; network: CorePrimitivesNetworkWeb3Network['type']; mockDid: string; mockWeb3Network: string; diff --git a/tee-worker/ts-tests/integration-tests/common/credential-json/litentry.json b/tee-worker/ts-tests/integration-tests/common/credential-json/litentry.json new file mode 100644 index 0000000000..770dba85c5 --- /dev/null +++ b/tee-worker/ts-tests/integration-tests/common/credential-json/litentry.json @@ -0,0 +1,16 @@ +[ + { + "id": "evm-version-early-bird", + "name": "IDHub EVM Version Early Bird", + "description": "The user is an early bird user of the IdentityHub EVM version and has generated at least 1 credential during 2023 Aug 14th ~ Aug 21st.", + "assertion": { + "id": "A20", + "payload": [] + }, + "dataProvider": "litentryIndexer", + "network": "litentry", + "mockDid": "litentry:substrate:0xa20d2c66bd88271ce78b2d8b7367c025e108944fda26a5a4e95b5efcc3f26b45", + "mockWeb3Network": "litentry,polkadot", + "expectedCredentialValue": false + } +] diff --git a/tee-worker/ts-tests/integration-tests/common/credential-json/nodereal.json b/tee-worker/ts-tests/integration-tests/common/credential-json/nodereal.json new file mode 100644 index 0000000000..298a0a7a2c --- /dev/null +++ b/tee-worker/ts-tests/integration-tests/common/credential-json/nodereal.json @@ -0,0 +1,311 @@ +[ + { + "id": "bnb-domain-holding-amount", + "name": ".bnb Holding Amount", + "description": "You are holding a certain amount of bnb domain names", + + "assertion": { + "id": "BnbDomainHolding", + "payload": [] + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xf813361F1FADC5c51EFdd0ba5b93e2760a5537EC", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "bnb-999-club-member", + "name": "000-999.bnb Domain Holding Amount", + "description": "You are holding a certain amount of 000-999.bnb domain names", + "assertion": { + "id": "BnbDigitDomainClub", + "payload": "Bnb999ClubMember" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xA6E3d8B20a5DC12c986AF63E496B8D585117aBBd", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "bnb-10k-club-member", + "name": "0000-9999.bnb Holding Amount", + "description": "You are holding a certain amount of 0000-9999.bnb domain names", + "assertion": { + "id": "BnbDigitDomainClub", + "payload": "Bnb10KClubMember" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xD673b52E4c560f5d2BD41fd92e7566Ef445DC5AB", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-amp", + "name": "AMP Holding Amount", + "description": "The number of AMP tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Amp" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x5029bC78f84Fc7F1568FbA1A7808e753691E6675", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-comp", + "name": "COMP Holding Amount", + "description": "The number of COMP tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Comp" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xA5044e67f0c35b31fe82F2Ded6606b0b91545e98", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-crv", + "name": "CRV Holding Amount", + "description": "The number of CRV tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Crv" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xd14A1dB9B2Bfe0cE9cC175C24d6B01a16aB84f42", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-cvx", + "name": "CVX Holding Amount", + "description": "The number of CVX tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Cvx" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xAA1582084c4f588eF9BE86F5eA1a919F86A3eE57", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-dydx", + "name": "DYDX Holding Amount", + "description": "The number of DYDX tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Dydx" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xe7DAE0cEd7a64d50136D466945257b600e718ACa", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-grt", + "name": "GRT Holding Amount", + "description": "The number of GRT tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Grt" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x46f80018211D5cBBc988e853A8683501FCA4ee9b", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-gtc", + "name": "GTC Holding Amount", + "description": "The number of GTC tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Gtc" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x310E035d176ccB589511eD16af7aE7BAc4fc7f83", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-gusd", + "name": "GUSD Holding Amount", + "description": "The number of GUSD tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Gusd" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x94CFF34005A073911C3179abE89F1677f0D37d42", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-link", + "name": "LINK Holding Amount", + "description": "The number of LINK tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Link" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xB4e9275827B5f049196f5337F69533937475A3de", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-lit", + "name": "LIT Holding Amount", + "description": "The number of LIT tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Lit" + }, + "dataProvider": "nodereal", + "network": "litentry", + "mockDid": "litentry:evm:0xcFD97648df7fB75A545c69106d2049aa3D540334", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-people", + "name": "PEOPLE Holding Amount", + "description": "The number of PEOPLE tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "People" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x60E4F4bF50204dEeeD8bF4C6216b41BA2e5e453a", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-ton", + "name": "TON Holding Amount", + "description": "The number of TON tokens you hold > 0", + "assertion": { + "id": "EvmAmountHolding", + "payload": "Ton" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x8BaE6C9EA994d18e6b05cE33aE3e54Fa6F7FcE82", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-trx", + "name": "TRX Holding Amount", + "description": "The number of TRX tokens you hold > 0", + "assertion": { + "id": "EvmAmountHolding", + "payload": "Trx" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x2d23D597b21F88c55fC6f1E2a84f42b06b7915dF", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-tusd", + "name": "TUSD Holding Amount", + "description": "The number of TUSD tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Tusd" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xDebc74120F822C0F0e6Eb69dB5F347F574d2D446", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-usdd", + "name": "USDD Holding Amount", + "description": "The number of USDD tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Usdd" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x31743a08D895d01a49dB98b8F9c8469D92f63745", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-usdt", + "name": "USDT Holding Amount", + "description": "The number of USDT tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Usdt" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x67aB29354a70732CDC97f372Be81d657ce8822cd", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-holding-amount-matic", + "name": "MATIC Holding Amount", + "description": "The number of MATIC tokens you hold > 0", + "assertion": { + "id": "TokenHoldingAmount", + "payload": "Matic" + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0x3B7BB88dB769923dC2eE1e9e6A83c00A74c407D2", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + }, + { + "id": "token-staking-amount-lit", + "name": "LIT Staking Amount", + "description": "You are staking a certain amount of LIT", + "assertion": { + "id": "LitStaking", + "payload": [] + }, + "dataProvider": "nodereal", + "network": "litentry", + "mockDid": "litentry:substrate:0xfc7a9dd32be14db4695555aa9a2abd240a8c2160f84ccb403a985701dd13fe50", + "mockWeb3Network": "litentry,polkadot", + "expectedCredentialValue": true + }, + { + "id": "weirdo-ghost-gang-holder", + "name": "WeirdoGhostGang Holder", + "description": "You are WeirdoGhostGang NFT holder", + "assertion": { + "id": "WeirdoGhostGangHolder", + "payload": [] + }, + "dataProvider": "nodereal", + "network": "ethereum", + "mockDid": "litentry:evm:0xCaA18Cd73E2756c680859F0A97E2C4846D50f71B", + "mockWeb3Network": "bsc,ethereum", + "expectedCredentialValue": true + } +] diff --git a/tee-worker/ts-tests/integration-tests/common/credential-json/oneblock.json b/tee-worker/ts-tests/integration-tests/common/credential-json/oneblock.json new file mode 100644 index 0000000000..a3272ce8bc --- /dev/null +++ b/tee-worker/ts-tests/integration-tests/common/credential-json/oneblock.json @@ -0,0 +1,44 @@ +[ + { + "id": "oneblock-course-participation", + "name": "OneBlock+ Substrate Blockchain Development Course Participation", + "description": "You were a participant to the course co-created by OneBlock+ and Parity: \"Introduction to Substrate Blockchain Development, Phase 12\".", + "assertion": { + "id": "Oneblock", + "payload": "CourseParticipation" + }, + "dataProvider": "oneblock", + "network": "oneblock", + "mockDid": "litentry:substrate:0xf26f4f77ccb38173185242cd1199696e5df5201666aae383de86eeb9e8251b3b", + "mockWeb3Network": "polkadot,kusama", + "expectedCredentialValue": false + }, + { + "id": "oneblock-course-completion", + "name": "OneBlock+ Substrate Blockchain Development Course Completion", + "description": "You have completed the course co-created by OneBlock+ and Parity: \"Introduction to Substrate Blockchain Development, Phase 12\". \n\n OneBlock+: “We hope you will keep your enthusiasm and continue to explore on the road ahead.”", + "assertion": { + "id": "Oneblock", + "payload": "CourseCompletion" + }, + "dataProvider": "oneblock", + "network": "oneblock", + "mockDid": "litentry:substrate:0xaa639b158b45acd0f4315be3a074aee110979f34123828a0c8ef74c24925d96f", + "mockWeb3Network": "polkadot,kusama", + "expectedCredentialValue": true + }, + { + "id": "oneblock-course-outstanding", + "name": "OneBlock+ Substrate Blockchain Development Course Outstanding Student", + "description": "You were awarded the title \"Outstanding Student\" in the course \"Introduction to Substrate Blockchain Development, Phase 12” co-created by OneBlock+ and Parity.", + "assertion": { + "id": "Oneblock", + "payload": "CourseOutstanding" + }, + "dataProvider": "oneblock", + "network": "oneblock", + "mockDid": "litentry:substrate:0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d", + "mockWeb3Network": "polkadot,kusama", + "expectedCredentialValue": true + } +] diff --git a/tee-worker/ts-tests/integration-tests/common/credential-json/twitter.json b/tee-worker/ts-tests/integration-tests/common/credential-json/twitter.json new file mode 100644 index 0000000000..c10bb75859 --- /dev/null +++ b/tee-worker/ts-tests/integration-tests/common/credential-json/twitter.json @@ -0,0 +1,16 @@ +[ + { + "id": "twitter-follower-amount", + "name": "Twitter Follower Amount", + "description": "You have a certain amount of Twitter followers.", + "assertion": { + "id": "A6", + "payload": "A6" + }, + "dataProvider": "twitter", + "network": "twitter", + "mockDid": "litentry:twitter:litentry", + "mockWeb3Network": "", + "expectedCredentialValue": true + } +] diff --git a/tee-worker/ts-tests/integration-tests/common/credential-json/vip3-credential-test.json b/tee-worker/ts-tests/integration-tests/common/credential-json/vip3.json similarity index 100% rename from tee-worker/ts-tests/integration-tests/common/credential-json/vip3-credential-test.json rename to tee-worker/ts-tests/integration-tests/common/credential-json/vip3.json diff --git a/tee-worker/ts-tests/integration-tests/common/di-utils.ts b/tee-worker/ts-tests/integration-tests/common/di-utils.ts index 4242dfc1c6..7fc65e134b 100644 --- a/tee-worker/ts-tests/integration-tests/common/di-utils.ts +++ b/tee-worker/ts-tests/integration-tests/common/di-utils.ts @@ -11,7 +11,6 @@ import { createPublicKey, KeyObject } from 'crypto'; import WebSocketAsPromised from 'websocket-as-promised'; import { H256, Index } from '@polkadot/types/interfaces'; import { blake2AsHex } from '@polkadot/util-crypto'; -import type { PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; import { createJsonRpcRequest, nextRequestId } from './helpers'; // Send the request to worker ws @@ -35,7 +34,7 @@ async function sendRequest( const parsed = JSON.parse(data); if (parsed.id === request.id) { const result = parsed.result; - const res: WorkerRpcReturnValue = api.createType('WorkerRpcReturnValue', result) as any; + const res = api.createType('WorkerRpcReturnValue', result); console.log('Got response: ' + JSON.stringify(res.toHuman())); @@ -94,25 +93,18 @@ export const createSignedTrustedCall = async ( payload = u8aConcat(stringToU8a(''), payload, stringToU8a('')); } - let signature; - // for bitcoin signature, we expect a hex-encoded `string` without `0x` prefix - // TODO: any better idiomatic way? - if (signer.type() === 'bitcoin') { - const payloadStr = u8aToHex(payload).substring(2); - signature = parachainApi.createType('LitentryMultiSignature', { - [signer.type()]: u8aToHex(await signer.sign(payloadStr)), - }); - } else { - signature = parachainApi.createType('LitentryMultiSignature', { - [signer.type()]: u8aToHex(await signer.sign(payload)), - }); - } + const signature = parachainApi.createType('LitentryMultiSignature', { + [signer.type()]: u8aToHex( + await signer.sign(signer.type() === 'bitcoin' ? u8aToHex(payload).substring(2) : payload) + ), + }); + return parachainApi.createType('TrustedCallSigned', { call: call, index: nonce, signature: signature, - }) as unknown as TrustedCallSigned; + }); }; export const createSignedTrustedGetter = async ( @@ -221,6 +213,7 @@ export async function createSignedTrustedCallRequestVc( [primeIdentity.toHuman(), primeIdentity.toHuman(), assertion, aesKey, hash] ); } + export async function createSignedTrustedCallDeactivateIdentity( parachainApi: ApiPromise, mrenclave: string, @@ -271,7 +264,7 @@ export async function createSignedTrustedGetterIdGraph( signer, primeIdentity.toHuman() ); - return parachainApi.createType('Getter', { trusted: getterSigned }) as unknown as Getter; // @fixme 1878; + return parachainApi.createType('Getter', { trusted: getterSigned }); } export const getSidechainNonce = async ( @@ -280,7 +273,7 @@ export const getSidechainNonce = async ( primeIdentity: CorePrimitivesIdentity ): Promise => { const getterPublic = createPublicGetter(context.api, ['nonce', '(LitentryIdentity)'], primeIdentity.toHuman()); - const getter = context.api.createType('Getter', { public: getterPublic }) as unknown as Getter; // @fixme 1878 + const getter = context.api.createType('Getter', { public: getterPublic }); const res = await sendRequestFromGetter(context, teeShieldingKey, getter); const nonce = context.api.createType('Option', hexToU8a(res.value.toHex())).unwrap(); return context.api.createType('Index', nonce); @@ -296,7 +289,7 @@ export const getIdGraphHash = async ( ['id_graph_hash', '(LitentryIdentity)'], primeIdentity.toHuman() ); - const getter = context.api.createType('Getter', { public: getterPublic }) as unknown as Getter; // @fixme 1878 + const getter = context.api.createType('Getter', { public: getterPublic }); const res = await sendRequestFromGetter(context, teeShieldingKey, getter); const hash = context.api.createType('Option', hexToU8a(res.value.toHex())).unwrap(); return context.api.createType('H256', hash); @@ -305,7 +298,8 @@ export const getIdGraphHash = async ( export const sendRequestFromTrustedCall = async ( context: IntegrationTestContext, teeShieldingKey: KeyObject, - call: TrustedCallSigned + call: TrustedCallSigned, + isVcDirect = false ) => { // construct trusted operation const trustedOperation = context.api.createType('TrustedOperation', { direct_call: call }); @@ -320,7 +314,7 @@ export const sendRequestFromTrustedCall = async ( trustedOperation.toU8a() ); const request = createJsonRpcRequest( - 'author_submitAndWatchAesRequest', + isVcDirect ? 'author_requestVc' : 'author_submitAndWatchAesRequest', [u8aToHex(requestParam)], nextRequestId(context) ); @@ -399,7 +393,7 @@ export const createAesRequest = async ( ciphertext: compactAddLength( hexToU8a(encryptWithAes(u8aToHex(aesKey), hexToU8a(keyNonce), Buffer.from(top))) ), - add: hexToU8a('0x'), + aad: hexToU8a('0x'), nonce: hexToU8a(keyNonce), }) .toU8a(), @@ -412,7 +406,7 @@ export function decodeIdGraph(sidechainRegistry: TypeRegistry, value: Bytes) { return sidechainRegistry.createType( 'Vec<(CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', idgraphBytes.unwrap() - ) as unknown as [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][]; + ); } export function getTopHash(parachainApi: ApiPromise, call: TrustedCallSigned) { diff --git a/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts b/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts index fee60cc199..44c5e1f756 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/assertion.ts @@ -1,63 +1,23 @@ -import { ApiPromise } from '@polkadot/api'; import { Event } from '@polkadot/types/interfaces'; import { hexToU8a, u8aToHex } from '@polkadot/util'; -import Ajv from 'ajv'; -import { assert, expect } from 'chai'; +import { assert } from 'chai'; import * as ed from '@noble/ed25519'; import { parseIdGraph } from './identity-helper'; -import type { PalletIdentityManagementTeeError } from 'sidechain-api'; -import { TeerexPrimitivesEnclave, CorePrimitivesIdentity } from 'parachain-api'; +import { CorePrimitivesIdentity } from 'parachain-api'; import type { IntegrationTestContext } from '../common-types'; import { getIdGraphHash } from '../di-utils'; import type { HexString } from '@polkadot/util/types'; -import { jsonSchema } from './vc-helper'; import { aesKey } from '../call'; import colors from 'colors'; -import { - CorePrimitivesErrorErrorDetail, - FrameSystemEventRecord, - WorkerRpcReturnValue, - RequestVCResult, - StfError, -} from 'parachain-api'; +import { WorkerRpcReturnValue, StfError } from 'parachain-api'; import { Bytes } from '@polkadot/types-codec'; import { Signer, decryptWithAes } from './crypto'; import { blake2AsHex } from '@polkadot/util-crypto'; +import { validateVcSchema } from '@litentry/vc-schema-validator'; import { PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; import { KeyObject } from 'crypto'; import * as base58 from 'micro-base58'; -export async function assertFailedEvent( - context: IntegrationTestContext, - events: FrameSystemEventRecord[], - eventType: 'LinkIdentityFailed' | 'DeactivateIdentityFailed', - expectedEvent: CorePrimitivesErrorErrorDetail['type'] | PalletIdentityManagementTeeError['type'] -) { - const failedType = context.api.events.identityManagement[eventType]; - const isFailed = failedType.is.bind(failedType); - type EventLike = Parameters[0]; - const ievents: EventLike[] = events.map(({ event }) => event); - const failedEvent = ievents.filter(isFailed); - /* - @fix Why this type don't work?????? https://github.com/litentry/litentry-parachain/issues/1917 - */ - const eventData = failedEvent[0].data[1] as CorePrimitivesErrorErrorDetail; - assert.lengthOf(failedEvent, 1); - if (eventData.isStfError) { - assert.equal( - eventData.asStfError.toHuman(), - expectedEvent, - `check event detail is ${expectedEvent}, but is ${eventData.asStfError.toHuman()}` - ); - } else { - assert.equal( - eventData.type, - expectedEvent, - `check event detail is ${expectedEvent}, but is ${eventData.type}` - ); - } -} - export function assertIdGraph( actual: [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][], expected: [CorePrimitivesIdentity, boolean][] @@ -134,44 +94,6 @@ export async function checkErrorDetail(events: Event[], expectedDetail: string) }); } -export async function verifySignature(data: any, index: HexString, proofJson: any, api: ApiPromise) { - const count = await api.query.teerex.enclaveCount(); - const enclaveRegistry = (await api.query.teerex.enclaveRegistry(count)) as unknown as TeerexPrimitivesEnclave; - - // Check vc index - expect(index).to.be.eq(data.id); - const signature = Buffer.from(hexToU8a(`0x${proofJson.proofValue}`)); - const message = Buffer.from(data.issuer.mrenclave); - const vcPubkey = Buffer.from(hexToU8a(enclaveRegistry.toHuman()['vcPubkey'] as HexString)); - - const isValid = await ed.verify(signature, message, vcPubkey); - - expect(isValid).to.be.true; - return true; -} - -export async function checkVc(vcObj: any, index: HexString, proof: any, api: ApiPromise): Promise { - const vc = JSON.parse(JSON.stringify(vcObj)); - delete vc.proof; - const signatureValid = await verifySignature(vc, index, proof, api); - expect(signatureValid).to.be.true; - - const jsonValid = await checkJson(vcObj, proof); - expect(jsonValid).to.be.true; - return true; -} - -// Check VC json fields -export async function checkJson(vc: any, proofJson: any): Promise { - //check jsonSchema - const ajv = new Ajv(); - const validate = ajv.compile(jsonSchema); - const isValid = validate(vc); - expect(isValid).to.be.true; - expect(vc.type[0] === 'VerifiableCredential' && proofJson.type === 'Ed25519Signature2020').to.be.true; - return true; -} - // for IdGraph mutation, assert the corresponding event is emitted for the given signer and the id_graph_hash matches export async function assertIdGraphMutationEvent( context: IntegrationTestContext, @@ -200,7 +122,7 @@ export function assertWorkerError( check: (returnValue: StfError) => void, returnValue: WorkerRpcReturnValue ) { - const errValueDecoded = context.api.createType('StfError', returnValue.value) as unknown as StfError; + const errValueDecoded = context.api.createType('StfError', returnValue.value); check(errValueDecoded); } @@ -218,7 +140,7 @@ export async function assertIdGraphMutationResult( | 'SetIdentityNetworksResult', expectedIdGraph: [CorePrimitivesIdentity, boolean][] ): Promise { - const decodedResult = context.api.createType(resultType, returnValue.value) as any; + const decodedResult = context.api.createType(resultType, returnValue.value); assert.isNotNull(decodedResult.mutated_id_graph); const idGraph = parseIdGraph(context.sidechainRegistry, decodedResult.mutated_id_graph, aesKey); assertIdGraph(idGraph, expectedIdGraph); @@ -229,7 +151,7 @@ export async function assertIdGraphMutationResult( return u8aToHex(decodedResult.id_graph_hash); } -/* +/* assert vc steps: 1. check vc status should be Active @@ -237,13 +159,13 @@ export async function assertIdGraphMutationResult( 3. check subject 4. compare vc index with vcPayload id 5. check vc signature - 6. compare vc wtih jsonSchema + 6. check vc schema TODO: This is incomplete; we still need to further check: https://github.com/litentry/litentry-parachain/issues/1873 */ export async function assertVc(context: IntegrationTestContext, subject: CorePrimitivesIdentity, data: Bytes) { - const results = context.api.createType('RequestVCResult', data) as unknown as RequestVCResult; + const results = context.api.createType('RequestVCResult', data); // step 1 // decryptWithAes function added 0x prefix const vcPayload = results.vc_payload; @@ -272,23 +194,24 @@ export async function assertVc(context: IntegrationTestContext, subject: CorePri // step 4 // extrac proof and vc without proof json const vcPayloadJson = JSON.parse(decryptVcPayload); - + console.log('credential: ', JSON.stringify(vcPayloadJson, null, 2)); const { proof, ...vcWithoutProof } = vcPayloadJson; // step 5 - // prepare teerex enclave registry data for further checks + // prepare teebag enclave registry data for further checks const parachainBlockHash = await context.api.query.system.blockHash(vcPayloadJson.parachainBlockNumber); const apiAtVcIssuedBlock = await context.api.at(parachainBlockHash); - const enclaveCount = await apiAtVcIssuedBlock.query.teerex.enclaveCount(); - - const lastRegisteredEnclave = (await apiAtVcIssuedBlock.query.teerex.enclaveRegistry(enclaveCount)) - .value as TeerexPrimitivesEnclave; + const enclaveIdentifier = await apiAtVcIssuedBlock.query.teebag.enclaveIdentifier('Identity'); + const lastRegisteredEnclave = ( + await apiAtVcIssuedBlock.query.teebag.enclaveRegistry(enclaveIdentifier[enclaveIdentifier.length - 1]) + ).unwrap(); // step 6 // check vc signature const signature = Buffer.from(hexToU8a(`0x${proof.proofValue}`)); const message = Buffer.from(JSON.stringify(vcWithoutProof)); - const vcPubkey = Buffer.from(lastRegisteredEnclave.vcPubkey.value); + const vcPubkeyBytes = context.api.createType('Option', lastRegisteredEnclave.vcPubkey).unwrap(); + const vcPubkey = Buffer.from(hexToU8a(vcPubkeyBytes.toHex())); const signatureStatus = await ed.verify(signature, message, vcPubkey); assert.isTrue(signatureStatus, 'Check Vc signature error: signature should be valid'); @@ -296,7 +219,7 @@ export async function assertVc(context: IntegrationTestContext, subject: CorePri // step 7 // check VC mrenclave with enclave's mrenclave from registry assert.equal( - base58.encode(lastRegisteredEnclave.mrEnclave), + base58.encode(lastRegisteredEnclave.mrenclave), vcPayloadJson.issuer.mrenclave, 'Check VC mrenclave: it should equals enclaves mrenclave from parachains enclave registry' ); @@ -304,20 +227,20 @@ export async function assertVc(context: IntegrationTestContext, subject: CorePri // step 8 // check vc issuer id assert.equal( - `did:litentry:substrate:${lastRegisteredEnclave.vcPubkey.value.toHex()}`, + `did:litentry:substrate:${vcPubkeyBytes.toHex()}`, vcPayloadJson.issuer.id, 'Check VC id: it should equals enclaves pubkey from parachains enclave registry' ); // step 9 // validate VC aganist schema - const ajv = new Ajv(); - const validate = ajv.compile(jsonSchema); + const schemaResult = await validateVcSchema(vcPayloadJson); + + if (schemaResult.errors) console.log('Schema Validation errors: ', schemaResult.errors); - const isValid = validate(vcPayloadJson); + assert.isTrue(schemaResult.isValid, 'Check Vc payload error: vcPayload should be valid'); - assert.isTrue(isValid, 'Check Vc payload error: vcPayload should be valid'); assert.equal( vcWithoutProof.type[0], 'VerifiableCredential', diff --git a/tee-worker/ts-tests/integration-tests/common/utils/context.ts b/tee-worker/ts-tests/integration-tests/common/utils/context.ts index 2903aa1227..4b9d5d9d26 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/context.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/context.ts @@ -1,6 +1,7 @@ -import { WsProvider, ApiPromise, TeerexPrimitivesEnclave } from 'parachain-api'; +import { WsProvider, ApiPromise } from 'parachain-api'; import { Keyring } from '@polkadot/api'; import { cryptoWaitReady } from '@polkadot/util-crypto'; +import { hexToString } from '@polkadot/util'; import { ethers } from 'ethers'; import WebSocketAsPromised from 'websocket-as-promised'; import WebSocket from 'ws'; @@ -85,28 +86,24 @@ export async function getEnclave(api: ApiPromise): Promise<{ mrEnclave: HexString; teeShieldingKey: KeyObject; }> { - const count = await api.query.teerex.enclaveCount(); + const enclaveIdentifier = api.createType('Vec', await api.query.teebag.enclaveIdentifier('Identity')); + const primaryEnclave = (await api.query.teebag.enclaveRegistry(enclaveIdentifier[0])).unwrap(); - const enclaveRegistry = ( - await api.query.teerex.enclaveRegistry(count) - ).toHuman() as unknown as TeerexPrimitivesEnclave; + const shieldingPubkeyBytes = api.createType('Option', primaryEnclave.shieldingPubkey).unwrap(); + const shieldingPubkey = hexToString(shieldingPubkeyBytes.toHex()); const teeShieldingKey = crypto.createPublicKey({ key: { alg: 'RSA-OAEP-256', kty: 'RSA', use: 'enc', - n: Buffer.from(JSON.parse(enclaveRegistry.shieldingKey as unknown as HexString).n.reverse()).toString( - 'base64url' - ), - e: Buffer.from(JSON.parse(enclaveRegistry.shieldingKey as unknown as HexString).e.reverse()).toString( - 'base64url' - ), + n: Buffer.from(JSON.parse(shieldingPubkey).n.reverse()).toString('base64url'), + e: Buffer.from(JSON.parse(shieldingPubkey).e.reverse()).toString('base64url'), }, format: 'jwk', }); //@TODO mrEnclave should verify from storage - const mrEnclave = enclaveRegistry.mrEnclave as unknown as HexString; + const mrEnclave = primaryEnclave.mrenclave.toHex(); return { mrEnclave, teeShieldingKey, diff --git a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts index 233e24d986..1ff8766949 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/identity-helper.ts @@ -4,7 +4,7 @@ import type { IntegrationTestContext } from '../common-types'; import { AesOutput } from 'parachain-api'; import { decryptWithAes, encryptWithTeeShieldingKey, Signer } from './crypto'; import { ethers } from 'ethers'; -import type { TypeRegistry } from '@polkadot/types'; +import type { Bytes, TypeRegistry, Vec } from '@polkadot/types'; import type { PalletIdentityManagementTeeIdentityContext } from 'sidechain-api'; import type { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; import type { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types'; @@ -35,7 +35,7 @@ export async function buildIdentityHelper( const identity = { [type]: address, }; - return context.api.createType('CorePrimitivesIdentity', identity) as unknown as CorePrimitivesIdentity; + return context.api.createType('CorePrimitivesIdentity', identity); } export async function buildIdentityFromKeypair( @@ -64,7 +64,7 @@ export async function buildIdentityFromKeypair( [type]: address, }; - return context.api.createType('CorePrimitivesIdentity', identity) as unknown as CorePrimitivesIdentity; + return context.api.createType('CorePrimitivesIdentity', identity); } // If multiple transactions are built from multiple accounts, pass the signers as an array. @@ -77,7 +77,7 @@ export async function buildIdentityTxs( identities: CorePrimitivesIdentity[], method: 'linkIdentity' | 'deactivateIdentity' | 'activateIdentity', validations?: LitentryValidationData[], - web3networks?: Web3Network[][] + web3networks?: (Bytes | Vec)[] ): Promise { const txs: { tx: SubmittableExtrinsic; @@ -138,7 +138,7 @@ export function parseIdGraph( sidechainRegistry.createType( 'Vec<(CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext)>', decryptedIdGraph - ) as unknown as [CorePrimitivesIdentity, PalletIdentityManagementTeeIdentityContext][]; + ); return idGraph; } @@ -182,10 +182,7 @@ export async function buildValidations( evmValidationData!.Web3Validation.Evm.signature.Ethereum = evmSignature; console.log('evmValidationData', evmValidationData); - const encodedVerifyIdentityValidation = context.api.createType( - 'LitentryValidationData', - evmValidationData - ) as unknown as LitentryValidationData; + const encodedVerifyIdentityValidation = context.api.createType('LitentryValidationData', evmValidationData); validations.push(encodedVerifyIdentityValidation); } else if (network === 'substrate') { @@ -207,7 +204,7 @@ export async function buildValidations( const encodedVerifyIdentityValidation: LitentryValidationData = context.api.createType( 'LitentryValidationData', substrateValidationData - ) as unknown as LitentryValidationData; + ); validations.push(encodedVerifyIdentityValidation); } else if (network === 'bitcoin') { const bitcoinValidationData = { @@ -233,7 +230,7 @@ export async function buildValidations( const encodedVerifyIdentityValidation: LitentryValidationData = context.api.createType( 'LitentryValidationData', bitcoinValidationData - ) as unknown as LitentryValidationData; + ); validations.push(encodedVerifyIdentityValidation); } else if (network === 'bitcoinPrettified') { const bitcoinValidationData = { @@ -258,7 +255,7 @@ export async function buildValidations( const encodedVerifyIdentityValidation: LitentryValidationData = context.api.createType( 'LitentryValidationData', bitcoinValidationData - ) as unknown as LitentryValidationData; + ); validations.push(encodedVerifyIdentityValidation); } else if (network === 'twitter') { console.log('post verification msg to twitter: ', msg); @@ -273,7 +270,7 @@ export async function buildValidations( const encodedVerifyIdentityValidation = context.api.createType( 'LitentryValidationData', twitterValidationData - ) as unknown as LitentryValidationData; + ); validations.push(encodedVerifyIdentityValidation); } } diff --git a/tee-worker/ts-tests/integration-tests/common/utils/storage.ts b/tee-worker/ts-tests/integration-tests/common/utils/storage.ts index ede4aced87..33491b10af 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/storage.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/storage.ts @@ -105,9 +105,6 @@ export async function checkIdGraph( const request = createJsonRpcRequest('state_getStorage', [base58mrEnclave, storageKey], nextRequestId(context)); const resp = await sendRequest(context.tee, request, context.api); - const idGraph = context.sidechainRegistry.createType( - 'PalletIdentityManagementTeeIdentityContext', - resp.value - ) as unknown as PalletIdentityManagementTeeIdentityContext; + const idGraph = context.sidechainRegistry.createType('PalletIdentityManagementTeeIdentityContext', resp.value); return idGraph; } diff --git a/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts b/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts index 9ad26dda1d..e67e8cfa33 100644 --- a/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts +++ b/tee-worker/ts-tests/integration-tests/common/utils/vc-helper.ts @@ -78,7 +78,7 @@ export const defaultAssertions = [ Achainable: { Basic: { name: 'Uniswap V2/V3 user', - chain: 'Ethereum', + chain: ['Ethereum'], }, }, }, @@ -89,7 +89,7 @@ export const defaultAssertions = [ Achainable: { Amount: { name: 'Balance over {amount}', - chain: 'Ethereum', + chain: ['Ethereum'], amount: '0', }, @@ -102,7 +102,7 @@ export const defaultAssertions = [ Achainable: { ClassOfYear: { name: 'Account created between {dates}', - chain: 'Ethereum', + chain: ['Ethereum'], }, }, }, @@ -113,7 +113,7 @@ export const defaultAssertions = [ Achainable: { Amount: { name: 'Created over {amount} contracts', - chain: 'Ethereum', + chain: ['Ethereum'], amount: '0', }, }, @@ -132,23 +132,23 @@ export const defaultAssertions = [ }, // VIP3 { - description: 'VIP3 Gold Card Holder', + description: 'VIP3 Silver Card Holder', assertion: { - VIP3MembershipCard: 'Gold', + VIP3MembershipCard: 'Silver', }, }, ]; // In both cases as below, it's sufficient to check if the condition is valid, should be invalid. -// For the 'oneblock' assertion, need to configure the Polkadot/Kusma address, +// For the 'OneBlock' assertion, need to configure the Polkadot/Kusma address, // and for 'bnb,' need to configure the NODEREAL_API_KEY // We cannot submit these two types of data involving privacy(from @zhouhui), so we only need to test that their DI response is invalid and that the RequestVCFailed event is received, which should be tested separately from the defaultAssertions. export const unconfiguredAssertions = [ - // Oneblock + // OneBlock { description: 'A participant to the course co-created by OneBlock+ and Parity', assertion: { - oneblock: 'CourseParticipation', + OneBlock: 'CourseParticipation', }, }, @@ -166,85 +166,3 @@ export const unconfiguredAssertions = [ }, }, ]; -export const jsonSchema = { - type: 'object', - properties: { - id: { - type: 'string', - }, - type: { - type: 'array', - }, - issuer: { - type: 'object', - properties: { - id: { - type: 'string', - }, - name: { - type: 'string', - }, - shard: { - type: 'string', - }, - }, - }, - issuanceDate: { - type: 'string', - }, - credentialSubject: { - type: 'object', - properties: { - id: { - type: 'string', - }, - description: { - type: 'string', - }, - type: { - type: 'string', - }, - tag: { - type: 'array', - }, - assertions: { - type: 'array', - items: { - type: 'object', - }, - }, - values: { - type: 'array', - items: { - type: 'boolean', - }, - }, - endpoint: { - type: 'string', - }, - }, - required: ['id', 'description', 'type', 'assertions', 'values', 'endpoint'], - }, - proof: { - type: 'object', - properties: { - created: { - type: 'string', - }, - type: { - enum: ['Ed25519Signature2020'], - }, - proofPurpose: { - enum: ['assertionMethod'], - }, - proofValue: { - type: 'string', - }, - verificationMethod: { - type: 'string', - }, - }, - }, - }, - required: ['id', 'type', 'credentialSubject', 'issuer', 'issuanceDate', 'proof'], -}; diff --git a/tee-worker/ts-tests/integration-tests/data-providers.test.ts b/tee-worker/ts-tests/integration-tests/data-provider.test.ts similarity index 80% rename from tee-worker/ts-tests/integration-tests/data-providers.test.ts rename to tee-worker/ts-tests/integration-tests/data-provider.test.ts index 78903f6a7f..bf34106353 100644 --- a/tee-worker/ts-tests/integration-tests/data-providers.test.ts +++ b/tee-worker/ts-tests/integration-tests/data-provider.test.ts @@ -17,7 +17,7 @@ import { $ as zx } from 'zx'; import { subscribeToEventsWithExtHash } from './common/transactions'; import { KeyringPair } from '@polkadot/keyring/types'; import { u8aToHex } from '@polkadot/util'; -import { vip3CredentialJson, CredentialDefinition } from './common/credential-json'; +import { CredentialDefinition, credentialsJson } from './common/credential-json'; describe('Test Vc (direct invocation)', function () { let context: IntegrationTestContext = undefined as any; let teeShieldingKey: KeyObject = undefined as any; @@ -27,7 +27,6 @@ describe('Test Vc (direct invocation)', function () { const reqExtHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; const keyringPairs: KeyringPair[] = []; let argvId = ''; - const credentialsJson: CredentialDefinition[] = [...vip3CredentialJson]; this.timeout(6000000); before(async () => { @@ -38,8 +37,8 @@ describe('Test Vc (direct invocation)', function () { // usage example: // `pnpm run test-data-providers:local --id=vip3-membership-card-gold` for single test // `pnpm run test-data-providers:local` for all tests - const argv = process.argv.indexOf('--id'); - argvId = process.argv[argv + 1]; + const idIndex = process.argv.indexOf('--id'); + argvId = process.argv[idIndex + 1]; const { protocol: workerProtocal, hostname: workerHostname, @@ -49,6 +48,7 @@ describe('Test Vc (direct invocation)', function () { async function linkIdentityViaCli(id: string) { const credentialDefinitions = credentialsJson.find((item) => item.id === id) as CredentialDefinition; + console.log(`linking identity-${credentialDefinitions.mockDid} via cli`); const keyringPair = randomSubstrateWallet(); keyringPairs.push(keyringPair); @@ -79,15 +79,16 @@ describe('Test Vc (direct invocation)', function () { async function requestVc(id: string, index: number) { const credentialDefinitions = credentialsJson.find((item) => item.id === id) as CredentialDefinition; - const assertion = { [credentialDefinitions.assertion.id]: credentialDefinitions.assertion.payload, }; + console.log('vc description: ', credentialDefinitions.description); + + console.log('assertion: ', assertion); let currentNonce = (await getSidechainNonce(context, teeShieldingKey, substrateIdentities[index])).toNumber(); const getNextNonce = () => currentNonce++; const nonce = getNextNonce(); - console.log(nonce, substrateIdentities[index].toHuman(), u8aToHex(keyringPairs[index].publicKey)); const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; const requestVcCall = await createSignedTrustedCallRequestVc( @@ -103,32 +104,29 @@ describe('Test Vc (direct invocation)', function () { const res = await sendRequestFromTrustedCall(context, teeShieldingKey, requestVcCall); await assertIsInSidechainBlock(`${Object.keys(assertion)[0]} requestVcCall`, res); - const vcResults = context.api.createType('RequestVCResult', res.value) as unknown as RequestVCResult; + const vcResults = context.api.createType('RequestVCResult', res.value); const decryptVcPayload = decryptWithAes(aesKey, vcResults.vc_payload, 'utf-8').replace('0x', ''); const vcPayloadJson = JSON.parse(decryptVcPayload); + console.log('vcPayload: ', vcPayloadJson); - assert.equal(vcPayloadJson.credentialSubject.values[0], credentialDefinitions.expectedCredentialValue); + assert.equal( + vcPayloadJson.credentialSubject.values[0], + credentialDefinitions.expectedCredentialValue, + "credential value doesn't match, please check the credential json expectedCredentialValue" + ); } if (argvId && credentialsJson.find((item) => item.id === argvId)) { - const credentialDefinitions = credentialsJson.find((item) => item.id === argvId) as CredentialDefinition; - - step( - `linking identity::${credentialDefinitions.mockDid} via cli and request vc::${credentialDefinitions.mockDid}`, - async function () { - await linkIdentityViaCli(argvId); - await requestVc(argvId, 0); - } - ); + step(`link identity && request vc with specific credentials for ${argvId}`, async function () { + await linkIdentityViaCli(argvId); + await requestVc(argvId, 0); + }); } else { credentialsJson.forEach(({ id }, index) => { - step( - `linking identity::${credentialsJson[index].mockDid} via cli and request vc::${credentialsJson[index].id}`, - async function () { - await linkIdentityViaCli(id); - await requestVc(id, index); - } - ); + step(`link identity && request vc with all credentials for ${id}`, async function () { + await linkIdentityViaCli(id); + await requestVc(id, index); + }); }); } }); diff --git a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts index 9faa4af64f..cf5c23492f 100644 --- a/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_bitcoin_identity.test.ts @@ -27,7 +27,7 @@ import { import type { IntegrationTestContext } from './common/common-types'; import { aesKey } from './common/call'; import { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; -import { Vec } from '@polkadot/types'; +import { Bytes, Vec } from '@polkadot/types'; import { subscribeToEventsWithExtHash } from './common/transactions'; describe('Test Identity (bitcoin direct invocation)', function () { @@ -44,7 +44,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { nonce: number; identity: CorePrimitivesIdentity; validation: LitentryValidationData; - networks: Vec; + networks: Bytes | Vec; }[] = []; const deactivateIdentityRequestParams: { @@ -103,10 +103,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { undefined, [context.ethersWallet.alice] ); - const aliceEvmNetworks = context.api.createType('Vec', [ - 'Ethereum', - 'Bsc', - ]) as unknown as Vec; // @fixme #1878 + const aliceEvmNetworks = context.api.createType('Vec', ['Ethereum', 'Bsc']); linkIdentityRequestParams.push({ nonce: aliceEvmNonce, identity: aliceEvmIdentity, @@ -126,9 +123,7 @@ describe('Test Identity (bitcoin direct invocation)', function () { undefined, context.bitcoinWallet.bob ); - const bobBitcoinNetowrks = context.api.createType('Vec', [ - 'BitcoinP2tr', - ]) as unknown as Vec; // @fixme #1878 + const bobBitcoinNetowrks = context.api.createType('Vec', ['BitcoinP2tr']); linkIdentityRequestParams.push({ nonce: bobBitcoinNonce, identity: bobBitcoinIdentity, diff --git a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts index 36a6d947ec..b2009c942c 100644 --- a/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_evm_identity.test.ts @@ -26,7 +26,7 @@ import { import type { IntegrationTestContext } from './common/common-types'; import { aesKey } from './common/call'; import { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; -import { Vec } from '@polkadot/types'; +import { Vec, Bytes } from '@polkadot/types'; import { subscribeToEventsWithExtHash } from './common/transactions'; describe('Test Identity (evm direct invocation)', function () { @@ -43,7 +43,7 @@ describe('Test Identity (evm direct invocation)', function () { nonce: number; identity: CorePrimitivesIdentity; validation: LitentryValidationData; - networks: Vec; + networks: Bytes | Vec; }[] = []; this.timeout(6000000); @@ -85,10 +85,7 @@ describe('Test Identity (evm direct invocation)', function () { undefined, [context.ethersWallet.bob] ); - const bobEvmNetworks = context.api.createType('Vec', [ - 'Ethereum', - 'Bsc', - ]) as unknown as Vec; // @fixme #1878 + const bobEvmNetworks = context.api.createType('Vec', ['Ethereum', 'Bsc']); linkIdentityRequestParams.push({ nonce: bobEvmNonce, identity: bobEvmIdentity, @@ -110,10 +107,7 @@ describe('Test Identity (evm direct invocation)', function () { 'substrate', context.substrateWallet.eve ); - const eveSubstrateNetworks = context.api.createType('Vec', [ - 'Litentry', - 'Khala', - ]) as unknown as Vec; // @fixme #1878 + const eveSubstrateNetworks = context.api.createType('Vec', ['Litentry', 'Khala']); linkIdentityRequestParams.push({ nonce: eveSubstrateNonce, identity: eveSubstrateIdentity, diff --git a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts index 8f19167d5e..e01e532bbc 100644 --- a/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_substrate_identity.test.ts @@ -12,7 +12,7 @@ import { initIntegrationTestContext, PolkadotSigner, } from './common/utils'; -import { assertFailedEvent, assertIsInSidechainBlock, assertIdGraphMutationEvent } from './common/utils/assertion'; +import { assertIsInSidechainBlock, assertIdGraphMutationEvent } from './common/utils/assertion'; import { createSignedTrustedCallLinkIdentity, createSignedTrustedGetterIdGraph, @@ -28,7 +28,7 @@ import { import type { IntegrationTestContext } from './common/common-types'; import { aesKey } from './common/call'; import { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; -import { Vec } from '@polkadot/types'; +import { Vec, Bytes } from '@polkadot/types'; import { ethers } from 'ethers'; import type { HexString } from '@polkadot/util/types'; import { subscribeToEventsWithExtHash } from './common/transactions'; @@ -47,7 +47,7 @@ describe('Test Identity (direct invocation)', function () { nonce: number; identity: CorePrimitivesIdentity; validation: LitentryValidationData; - networks: Vec; + networks: Bytes | Vec; }[] = []; this.timeout(6000000); @@ -89,7 +89,7 @@ describe('Test Identity (direct invocation)', function () { twitterNonce, 'twitter' ); - const twitterNetworks = context.api.createType('Vec', []) as unknown as Vec; // @fixme #1878 + const twitterNetworks = context.api.createType('Vec', []); linkIdentityRequestParams.push({ nonce: twitterNonce, identity: twitterIdentity, @@ -108,10 +108,7 @@ describe('Test Identity (direct invocation)', function () { undefined, [context.ethersWallet.alice] ); - const evmNetworks = context.api.createType('Vec', [ - 'Ethereum', - 'Bsc', - ]) as unknown as Vec; // @fixme #1878 + const evmNetworks = context.api.createType('Vec', ['Ethereum', 'Bsc']); linkIdentityRequestParams.push({ nonce: evmNonce, identity: evmIdentity, @@ -133,10 +130,7 @@ describe('Test Identity (direct invocation)', function () { 'substrate', context.substrateWallet.eve ); - const eveSubstrateNetworks = context.api.createType('Vec', [ - 'Polkadot', - 'Litentry', - ]) as unknown as Vec; // @fixme #1878 + const eveSubstrateNetworks = context.api.createType('Vec', ['Polkadot', 'Litentry']); linkIdentityRequestParams.push({ nonce: eveSubstrateNonce, identity: eveSubstrateIdentity, @@ -161,9 +155,7 @@ describe('Test Identity (direct invocation)', function () { undefined, context.bitcoinWallet.alice ); - const bitcoinNetworks = context.api.createType('Vec', [ - 'BitcoinP2tr', - ]) as unknown as Vec; // @fixme #1878 + const bitcoinNetworks = context.api.createType('Vec', ['BitcoinP2tr']); linkIdentityRequestParams.push({ nonce: bitcoinNonce, identity: bitcoinIdentity, @@ -325,7 +317,7 @@ describe('Test Identity (direct invocation)', function () { res ); const events = await eventsPromise; - await assertFailedEvent(context, events, 'LinkIdentityFailed', 'InvalidIdentity'); + assert.lengthOf(events, 1); }); step('linking identity with wrong signature', async function () { @@ -384,7 +376,7 @@ describe('Test Identity (direct invocation)', function () { ); const events = await eventsPromise; - await assertFailedEvent(context, events, 'LinkIdentityFailed', 'UnexpectedMessage'); + assert.lengthOf(events, 1); }); step('linking already linked identity', async function () { @@ -433,7 +425,7 @@ describe('Test Identity (direct invocation)', function () { res ); const events = await eventsPromise; - await assertFailedEvent(context, events, 'LinkIdentityFailed', 'IdentityAlreadyLinked'); + assert.lengthOf(events, 1); }); step('deactivating linked identities', async function () { diff --git a/tee-worker/ts-tests/integration-tests/di_vc.test.ts b/tee-worker/ts-tests/integration-tests/di_vc.test.ts index 9403bafbd8..f69984dd5c 100644 --- a/tee-worker/ts-tests/integration-tests/di_vc.test.ts +++ b/tee-worker/ts-tests/integration-tests/di_vc.test.ts @@ -18,7 +18,7 @@ import { CorePrimitivesIdentity } from 'parachain-api'; import { subscribeToEventsWithExtHash } from './common/transactions'; import { defaultAssertions, unconfiguredAssertions } from './common/utils/vc-helper'; import { LitentryValidationData, Web3Network } from 'parachain-api'; -import { Vec } from '@polkadot/types'; +import { Vec, Bytes } from '@polkadot/types'; describe('Test Vc (direct invocation)', function () { let context: IntegrationTestContext = undefined as any; @@ -35,7 +35,7 @@ describe('Test Vc (direct invocation)', function () { nonce: number; identity: CorePrimitivesIdentity; validation: LitentryValidationData; - networks: Vec; + networks: Bytes | Vec; }[] = []; this.timeout(6000000); @@ -64,7 +64,7 @@ describe('Test Vc (direct invocation)', function () { twitterNonce, 'twitter' ); - const twitterNetworks = context.api.createType('Vec', []) as unknown as Vec; // @fixme #1878 + const twitterNetworks = context.api.createType('Vec', []); linkIdentityRequestParams.push({ nonce: twitterNonce, identity: twitterIdentity, @@ -83,10 +83,7 @@ describe('Test Vc (direct invocation)', function () { undefined, [context.ethersWallet.alice] ); - const evmNetworks = context.api.createType('Vec', [ - 'Ethereum', - 'Bsc', - ]) as unknown as Vec; // @fixme #1878 + const evmNetworks = context.api.createType('Vec', ['Ethereum', 'Bsc']); linkIdentityRequestParams.push({ nonce: evmNonce, identity: evmIdentity, @@ -111,9 +108,7 @@ describe('Test Vc (direct invocation)', function () { undefined, context.bitcoinWallet.alice ); - const bitcoinNetworks = context.api.createType('Vec', [ - 'BitcoinP2tr', - ]) as unknown as Vec; // @fixme #1878 + const bitcoinNetworks = context.api.createType('Vec', ['BitcoinP2tr']); linkIdentityRequestParams.push({ nonce: bitcoinNonce, identity: bitcoinIdentity, @@ -176,6 +171,7 @@ describe('Test Vc (direct invocation)', function () { await assertVc(context, aliceSubstrateIdentity, res.value); }); }); + unconfiguredAssertions.forEach(({ description, assertion }) => { it(`request vc ${Object.keys(assertion)[0]} (alice)`, async function () { let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); diff --git a/tee-worker/ts-tests/integration-tests/dr_vc.test.ts b/tee-worker/ts-tests/integration-tests/dr_vc.test.ts new file mode 100644 index 0000000000..f228e6ac24 --- /dev/null +++ b/tee-worker/ts-tests/integration-tests/dr_vc.test.ts @@ -0,0 +1,201 @@ +import { randomBytes, KeyObject } from 'crypto'; +import { step } from 'mocha-steps'; +import { assert } from 'chai'; +import { u8aToHex, bufferToU8a } from '@polkadot/util'; +import { buildIdentityFromKeypair, initIntegrationTestContext, PolkadotSigner } from './common/utils'; +import { assertIsInSidechainBlock, assertVc } from './common/utils/assertion'; +import { + getSidechainNonce, + createSignedTrustedCallLinkIdentity, + getTeeShieldingKey, + sendRequestFromTrustedCall, + createSignedTrustedCallRequestVc, +} from './common/di-utils'; // @fixme move to a better place +import { buildIdentityHelper, buildValidations } from './common/utils'; +import type { IntegrationTestContext } from './common/common-types'; +import { aesKey } from './common/call'; +import { CorePrimitivesIdentity } from 'parachain-api'; +import { subscribeToEventsWithExtHash } from './common/transactions'; +import { defaultAssertions, unconfiguredAssertions } from './common/utils/vc-helper'; +import { LitentryValidationData, Web3Network } from 'parachain-api'; +import { Vec, Bytes } from '@polkadot/types'; + +describe('Test Vc (direct request)', function () { + let context: IntegrationTestContext = undefined as any; + let teeShieldingKey: KeyObject = undefined as any; + let aliceSubstrateIdentity: CorePrimitivesIdentity = undefined as any; + + // Alice links: + // - a `mock_user` twitter + // - alice's evm identity + // - alice's bitcoin identity] + // + // We need this linking to not have empty eligible identities for any vc request + const linkIdentityRequestParams: { + nonce: number; + identity: CorePrimitivesIdentity; + validation: LitentryValidationData; + networks: Bytes | Vec; + }[] = []; + this.timeout(6000000); + + before(async () => { + context = await initIntegrationTestContext( + process.env.WORKER_ENDPOINT!, // @fixme evil assertion; centralize env access + process.env.NODE_ENDPOINT! // @fixme evil assertion; centralize env access + ); + teeShieldingKey = await getTeeShieldingKey(context); + aliceSubstrateIdentity = await buildIdentityFromKeypair( + new PolkadotSigner(context.substrateWallet.alice), + context + ); + }); + + step('linking identities (alice)', async function () { + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); + const getNextNonce = () => currentNonce++; + + const twitterNonce = getNextNonce(); + const twitterIdentity = await buildIdentityHelper('mock_user', 'Twitter', context); + const [twitterValidation] = await buildValidations( + context, + [aliceSubstrateIdentity], + [twitterIdentity], + twitterNonce, + 'twitter' + ); + const twitterNetworks = context.api.createType('Vec', []); + linkIdentityRequestParams.push({ + nonce: twitterNonce, + identity: twitterIdentity, + validation: twitterValidation, + networks: twitterNetworks, + }); + + const evmNonce = getNextNonce(); + const evmIdentity = await buildIdentityHelper(context.ethersWallet.alice.address, 'Evm', context); + const [evmValidation] = await buildValidations( + context, + [aliceSubstrateIdentity], + [evmIdentity], + evmNonce, + 'ethereum', + undefined, + [context.ethersWallet.alice] + ); + const evmNetworks = context.api.createType('Vec', ['Ethereum', 'Bsc']); + linkIdentityRequestParams.push({ + nonce: evmNonce, + identity: evmIdentity, + validation: evmValidation, + networks: evmNetworks, + }); + + const bitcoinNonce = getNextNonce(); + const bitcoinIdentity = await buildIdentityHelper( + u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())), + 'Bitcoin', + context + ); + console.log('bitcoin id: ', bitcoinIdentity.toHuman()); + const [bitcoinValidation] = await buildValidations( + context, + [aliceSubstrateIdentity], + [bitcoinIdentity], + bitcoinNonce, + 'bitcoin', + undefined, + undefined, + context.bitcoinWallet.alice + ); + const bitcoinNetworks = context.api.createType('Vec', ['BitcoinP2tr']); + linkIdentityRequestParams.push({ + nonce: bitcoinNonce, + identity: bitcoinIdentity, + validation: bitcoinValidation, + networks: bitcoinNetworks, + }); + + for (const { nonce, identity, validation, networks } of linkIdentityRequestParams) { + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + const linkIdentityCall = await createSignedTrustedCallLinkIdentity( + context.api, + context.mrEnclave, + context.api.createType('Index', nonce), + new PolkadotSigner(context.substrateWallet.alice), + aliceSubstrateIdentity, + identity.toHex(), + validation.toHex(), + networks.toHex(), + context.api.createType('Option', aesKey).toHex(), + requestIdentifier + ); + + const res = await sendRequestFromTrustedCall(context, teeShieldingKey, linkIdentityCall); + await assertIsInSidechainBlock('linkIdentityCall', res); + } + }); + + defaultAssertions.forEach(({ description, assertion }) => { + step(`request vc direct ${Object.keys(assertion)[0]} (alice)`, async function () { + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); + const getNextNonce = () => currentNonce++; + const nonce = getNextNonce(); + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + console.log( + `request vc direct ${Object.keys(assertion)[0]} for Alice ... Assertion description: ${description}` + ); + const eventsPromise = subscribeToEventsWithExtHash(requestIdentifier, context); + + const requestVcCall = await createSignedTrustedCallRequestVc( + context.api, + context.mrEnclave, + context.api.createType('Index', nonce), + new PolkadotSigner(context.substrateWallet.alice), + aliceSubstrateIdentity, + context.api.createType('Assertion', assertion).toHex(), + context.api.createType('Option', aesKey).toHex(), + requestIdentifier + ); + + const isVcDirect = true; + const res = await sendRequestFromTrustedCall(context, teeShieldingKey, requestVcCall, isVcDirect); + const events = await eventsPromise; + const vcIssuedEvents = events + .map(({ event }) => event) + .filter(({ section, method }) => section === 'vcManagement' && method === 'VCIssued'); + + assert.equal( + vcIssuedEvents.length, + 1, + `vcIssuedEvents.length != 1, please check the ${Object.keys(assertion)[0]} call` + ); + await assertVc(context, aliceSubstrateIdentity, res.value); + }); + }); + unconfiguredAssertions.forEach(({ description, assertion }) => { + it(`request vc ${Object.keys(assertion)[0]} (alice)`, async function () { + let currentNonce = (await getSidechainNonce(context, teeShieldingKey, aliceSubstrateIdentity)).toNumber(); + const getNextNonce = () => currentNonce++; + const nonce = getNextNonce(); + const requestIdentifier = `0x${randomBytes(32).toString('hex')}`; + console.log(`request vc ${Object.keys(assertion)[0]} for Alice ... Assertion description: ${description}`); + subscribeToEventsWithExtHash(requestIdentifier, context); + + const requestVcCall = await createSignedTrustedCallRequestVc( + context.api, + context.mrEnclave, + context.api.createType('Index', nonce), + new PolkadotSigner(context.substrateWallet.alice), + aliceSubstrateIdentity, + context.api.createType('Assertion', assertion).toHex(), + context.api.createType('Option', aesKey).toHex(), + requestIdentifier + ); + + await sendRequestFromTrustedCall(context, teeShieldingKey, requestVcCall); + // pending test + this.skip(); + }); + }); +}); diff --git a/tee-worker/ts-tests/integration-tests/ii_batch.test.ts b/tee-worker/ts-tests/integration-tests/ii_batch.test.ts index c7522fcfea..d03845a69c 100644 --- a/tee-worker/ts-tests/integration-tests/ii_batch.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_batch.test.ts @@ -12,13 +12,13 @@ import { sendTxsWithUtility } from './common/transactions'; import { generateWeb3Wallets, assertIdGraphMutationEvent, assertIdentityDeactivated } from './common/utils'; import { ethers } from 'ethers'; import type { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api'; -import { Vec } from '@polkadot/types'; +import { Vec, Bytes } from '@polkadot/types'; describeLitentry('Test Batch Utility', (context) => { let identities: CorePrimitivesIdentity[] = []; let validations: LitentryValidationData[] = []; let evmSigners: ethers.Wallet[] = []; - const we3networks: Web3Network[][] = []; + const web3networks: (Bytes | Vec)[] = []; const signerIdentities: CorePrimitivesIdentity[] = []; step('generate web3 wallets', async function () { @@ -39,7 +39,7 @@ describeLitentry('Test Batch Utility', (context) => { const signer = evmSigners[index]; const evmIdentity = await buildIdentityHelper(signer.address, 'Evm', context); identities.push(evmIdentity); - we3networks.push(defaultNetworks as unknown as Vec); // @fixme #1878 + web3networks.push(defaultNetworks); signerIdentities.push(aliceSubstrateIdentity); } @@ -60,7 +60,7 @@ describeLitentry('Test Batch Utility', (context) => { identities, 'linkIdentity', validations, - we3networks + web3networks ); const events = await sendTxsWithUtility(context, context.substrateWallet.alice, txs, 'identityManagement', [ 'IdentityLinked', diff --git a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts index 281a8c9b63..eaa987b117 100644 --- a/tee-worker/ts-tests/integration-tests/ii_identity.test.ts +++ b/tee-worker/ts-tests/integration-tests/ii_identity.test.ts @@ -24,6 +24,7 @@ import { sendRequest } from './common/call'; import * as base58 from 'micro-base58'; import { decodeRpcBytesAsString } from './common/call'; import { createJsonRpcRequest, nextRequestId } from './common/helpers'; +import { Bytes, Vec } from '@polkadot/types'; async function getEnclaveSignerPublicKey(context: IntegrationTestContext): Promise { const request = createJsonRpcRequest('author_getEnclaveSignerAccount', [], nextRequestId(context)); @@ -58,7 +59,7 @@ describeLitentry('Test Identity', (context) => { let charlieIdentities: CorePrimitivesIdentity[] = []; let eveValidations: LitentryValidationData[] = []; let bobValidations: LitentryValidationData[] = []; - let web3networks: Web3Network[][] = []; + let web3networks: (Bytes | Vec)[] = []; let base58mrEnclave: string; let workerAddress: string; let identityLinkedEvents; @@ -127,12 +128,9 @@ describeLitentry('Test Identity', (context) => { eveValidations = [...evmValidations, ...eveSubstrateValidations, ...twitterValidations]; - const twitterNetworks = context.api.createType('Vec', []) as unknown as Web3Network[]; - const evmNetworks = context.api.createType('Vec', ['Ethereum', 'Bsc']) as unknown as Web3Network[]; - const eveSubstrateNetworks = context.api.createType('Vec', [ - 'Litentry', - 'Polkadot', - ]) as unknown as Web3Network[]; + const twitterNetworks = context.api.createType('Vec', []); + const evmNetworks = context.api.createType('Vec', ['Ethereum', 'Bsc']); + const eveSubstrateNetworks = context.api.createType('Vec', ['Litentry', 'Polkadot']); web3networks = [evmNetworks, eveSubstrateNetworks, twitterNetworks]; @@ -194,13 +192,10 @@ describeLitentry('Test Identity', (context) => { const bobSubstrateValidation = context.api.createType( 'LitentryValidationData', substrateExtensionValidationData - ) as unknown as LitentryValidationData; + ); bobValidations = [bobSubstrateValidation]; - const bobSubstrateNetworks = context.api.createType('Vec', [ - 'Litentry', - 'Polkadot', - ]) as unknown as Web3Network[]; + const bobSubstrateNetworks = context.api.createType('Vec', ['Litentry', 'Polkadot']); const bobTxs = await buildIdentityTxs( context, @@ -290,10 +285,7 @@ describeLitentry('Test Identity', (context) => { }, }, }; - const evmValidationData: LitentryValidationData = context.api.createType( - 'LitentryValidationData', - validation - ) as unknown as LitentryValidationData; + const evmValidationData: LitentryValidationData = context.api.createType('LitentryValidationData', validation); const aliceTxs = await buildIdentityTxs( context, context.substrateWallet.alice, diff --git a/tee-worker/ts-tests/integration-tests/package.json b/tee-worker/ts-tests/integration-tests/package.json index 1e5f3dd9a7..60d8500abf 100644 --- a/tee-worker/ts-tests/integration-tests/package.json +++ b/tee-worker/ts-tests/integration-tests/package.json @@ -3,26 +3,13 @@ "license": "ISC", "type": "module", "scripts": { - "check-format": "pnpm exec prettier --check .", - "format": "pnpm exec prettier --write .", - "test-ii-identity:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'ii_identity.test.ts'", - "test-ii-identity:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm --loader=ts-node/esm 'ii_identity.test.ts'", - "test-di-substrate-identity:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_substrate_identity.test.ts'", - "test-di-substrate-identity:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_substrate_identity.test.ts'", - "test-di-evm-identity:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_evm_identity.test.ts'", - "test-di-evm-identity:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_evm_identity.test.ts'", - "test-di-bitcoin-identity:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_bitcoin_identity.test.ts'", - "test-di-bitcoin-identity:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_bitcoin_identity.test.ts'", - "test-di-vc:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_vc.test.ts'", - "test-di-vc:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'di_vc.test.ts'", - "test-ii-vc:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'ii_vc.test.ts'", - "test-ii-vc:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'ii_vc.test.ts'", - "test-ii-batch:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'ii_batch.test.ts'", - "test-ii-batch:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'ii_batch.test.ts'", - "test-data-providers:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'data-providers.test.ts'", - "test-data-providers:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'data-providers.test.ts'" + "check-format": "prettier --check .", + "format": "prettier --write .", + "pretest": "eslint .", + "test": "mocha --exit --sort -r ts-node/register --loader=ts-node/esm" }, "dependencies": { + "@litentry/vc-schema-validator": "^0.0.1", "@noble/ed25519": "^1.7.3", "@polkadot/api": "^10.9.1", "@polkadot/api-augment": "^10.9.1", @@ -39,7 +26,6 @@ "@polkadot/util": "^12.5.1", "@polkadot/util-crypto": "^12.5.1", "add": "^2.0.6", - "ajv": "^8.12.0", "bitcore-lib": "^10.0.21", "chai": "^4.3.6", "colors": "^1.4.0", diff --git a/tee-worker/ts-tests/integration-tests/vc.issuer.attest.example.ts b/tee-worker/ts-tests/integration-tests/vc.issuer.attest.example.ts index 3e25a7b1b7..1945a06f92 100644 --- a/tee-worker/ts-tests/integration-tests/vc.issuer.attest.example.ts +++ b/tee-worker/ts-tests/integration-tests/vc.issuer.attest.example.ts @@ -69,11 +69,10 @@ const vc = { * */ const enclaveRegistry = { - pubkey: 'jcPcHgptXWGsTAefDqW7GpbX8LYrNVEYLLKihV3RsizqSga1Z', - mrEnclave: '0x168b47aceff04e8cd20f4606a7eb255ffc1981cd3b8ba1d44face858f9a4c25b', - timestamp: '1,677,164,874,078', + mrenclave: '0x168b47aceff04e8cd20f4606a7eb255ffc1981cd3b8ba1d44face858f9a4c25b', + lastSeen: '1,677,164,874,078', url: 'wss://localhost:2000', - shieldingKey: + shieldingPubkey: '{n:[189,64,222,165,185,105,241,193,170,87,19,231,76,95,247,110,231,7,196,65,135,231,55,75,60,58,158,23,77,230,154,23,203,167,163,219,18,113,83,23,172,131,29,222,200,73,217,159,155,120,217,194,74,33,79,99,88,227,2,242,225,141,116,231,89,68,119,109,183,56,135,70,151,177,245,199,196,222,193,33,28,47,252,83,240,120,238,81,99,154,219,75,84,108,96,199,108,42,64,70,217,164,89,81,156,188,168,181,169,228,21,140,90,18,126,77,50,31,19,149,26,86,160,108,197,78,134,19,54,25,89,80,239,106,95,226,42,109,202,54,158,128,224,243,1,197,209,131,48,1,208,207,48,197,66,44,203,76,113,150,100,73,81,17,94,153,217,11,14,193,230,43,207,24,236,200,207,15,63,16,75,173,191,245,127,191,186,18,111,111,90,24,177,167,177,7,61,94,60,161,130,242,31,210,158,152,31,35,202,80,179,138,219,244,139,19,60,134,108,94,151,228,224,22,29,139,21,241,71,221,65,145,210,108,80,0,76,137,98,128,107,224,16,32,135,232,168,150,9,225,30,120,17,176,26,2,8,100,185,121,158,67,89,110,130,126,122,113,248,169,73,27,52,90,109,66,249,255,161,105,174,129,163,7,14,180,63,178,218,81,86,108,116,118,81,185,248,231,84,150,13,140,49,239,103,44,119,97,37,30,13,230,100,73,24,229,178,3,89,14,26,155,245,254,12,152,7,72,209,209,24,224,5,131,144,124,254,204,209,138,57,196,176,244,231,185,190,187,118,215,46,45,57,81,238,163,11,152,73,217,252,9,77,95,86,4,201,34,68,88,235,103,15,120,159,134,5,182,83,122,128,111,160,141],e:[1,0,0,1]}', vcPubkey: '0xde17d6daedb66ec9f5e096cc0317bd6cbf881c0d8273e54105ee7c22a2e48648', sgxMode: 'Debug', @@ -95,7 +94,7 @@ function checkIssuerAttestation() { console.log(' [IssuerAttestation] mrEnclaveFromVc: ', mrEnclaveFromVc); // Fetch mrEnclave from parachain - const mrEnclaveFromParachain = enclaveRegistry.mrEnclave; + const mrEnclaveFromParachain = enclaveRegistry.mrenclave; console.log(' [IssuerAttestation] mrEnclaveFromParachain: ', mrEnclaveFromParachain); // >>>0. Check mrEnclave diff --git a/tee-worker/ts-tests/pnpm-lock.yaml b/tee-worker/ts-tests/pnpm-lock.yaml index edaf43607f..878d19c8f7 100644 --- a/tee-worker/ts-tests/pnpm-lock.yaml +++ b/tee-worker/ts-tests/pnpm-lock.yaml @@ -10,6 +10,9 @@ importers: integration-tests: dependencies: + '@litentry/vc-schema-validator': + specifier: ^0.0.1 + version: 0.0.1(ajv-formats@2.1.1)(ajv@8.12.0)(fast-glob@3.3.2)(tslib@2.6.2) '@noble/ed25519': specifier: ^1.7.3 version: 1.7.3 @@ -58,9 +61,6 @@ importers: add: specifier: ^2.0.6 version: 2.0.6 - ajv: - specifier: ^8.12.0 - version: 8.12.0 bitcore-lib: specifier: ^10.0.21 version: 10.0.21 @@ -779,6 +779,20 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@litentry/vc-schema-validator@0.0.1(ajv-formats@2.1.1)(ajv@8.12.0)(fast-glob@3.3.2)(tslib@2.6.2): + resolution: {integrity: sha512-Utnu2m/IPcGbqpopNsEdB1AvRimoL300dGpk/9g/8P16OemCHYxHE8j+n2JrHS+BUvH9upDiNMy5sbZPmDAAfQ==} + peerDependencies: + ajv: ^8.12.0 + ajv-formats: ^2.1.1 + fast-glob: ^3.3.2 + tslib: ^2.3.0 + dependencies: + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + fast-glob: 3.3.2 + tslib: 2.6.2 + dev: false + /@noble/curves@1.2.0: resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} dependencies: @@ -1496,6 +1510,17 @@ packages: resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} dev: true + /ajv-formats@2.1.1(ajv@8.12.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + dev: false + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -2134,6 +2159,17 @@ packages: merge2: 1.4.1 micromatch: 4.0.5 + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: false + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true diff --git a/tee-worker/ts-tests/stress/package.json b/tee-worker/ts-tests/stress/package.json index 1173ee80c6..7626051262 100644 --- a/tee-worker/ts-tests/stress/package.json +++ b/tee-worker/ts-tests/stress/package.json @@ -3,11 +3,10 @@ "license": "ISC", "type": "module", "scripts": { - "format": "pnpm exec prettier --write .", - "check-format": "pnpm exec prettier --check .", - "run-script": "NODE_TLS_REJECT_UNAUTHORIZED=0 pnpm exec ts-node bin/stress.ts", - "test-stress-script:local": "pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'test/test.ts'", - "test-stress-script:staging": "pnpm exec cross-env NODE_ENV=staging mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'test/test.ts'" + "format": "prettier --write .", + "check-format": "prettier --check .", + "run-script": "NODE_TLS_REJECT_UNAUTHORIZED=0 ts-node bin/stress.ts", + "test": "mocha --exit --sort -r ts-node/register --loader=ts-node/esm" }, "dependencies": { "@noble/ed25519": "^1.7.3", diff --git a/tee-worker/ts-tests/stress/src/litentry-api.ts b/tee-worker/ts-tests/stress/src/litentry-api.ts index af3b425aed..17a7e2630c 100644 --- a/tee-worker/ts-tests/stress/src/litentry-api.ts +++ b/tee-worker/ts-tests/stress/src/litentry-api.ts @@ -8,6 +8,7 @@ import { u8aToHex, u8aConcat, stringToU8a, + hexToString, } from '@polkadot/util'; import { blake2AsHex } from '@polkadot/util-crypto'; import crypto, { KeyObject, createPublicKey } from 'crypto'; @@ -106,7 +107,7 @@ export async function buildValidation( }, }, }, - }) as unknown as LitentryValidationData; + }); } export async function buildIdentityFromWallet( @@ -118,7 +119,7 @@ export async function buildIdentityFromWallet( Evm: wallet.wallet.address, }; - return api.createType('CorePrimitivesIdentity', identity) as unknown as CorePrimitivesIdentity; + return api.createType('CorePrimitivesIdentity', identity); } const { keyringPair } = wallet; @@ -142,7 +143,7 @@ export async function buildIdentityFromWallet( [type]: address, }; - return api.createType('CorePrimitivesIdentity', identity) as unknown as CorePrimitivesIdentity; + return api.createType('CorePrimitivesIdentity', identity); } export function decodeRpcBytesAsString(value: Bytes): string { @@ -220,7 +221,7 @@ const createPublicGetter = ( const [variant, argType] = publicGetter; const getter = parachainApi.createType('PublicGetter', { [variant]: parachainApi.createType(argType, params), - }) as unknown as PublicGetter; + }); return getter; }; @@ -256,7 +257,7 @@ export function createSignedTrustedGetterUserShieldingKey( signer, subject.toHuman() ); - return parachainApi.createType('Getter', { trusted: getterSigned }) as unknown as Getter; + return parachainApi.createType('Getter', { trusted: getterSigned }); } const sendRequestFromGetter = async ( @@ -331,7 +332,7 @@ export const getSidechainNonce = async ( log: WritableStream ): Promise => { const getterPublic = createPublicGetter(parachainApi, ['nonce', '(LitentryIdentity)'], subject.toHuman()); - const getter = parachainApi.createType('Getter', { public: getterPublic }) as unknown as Getter; + const getter = parachainApi.createType('Getter', { public: getterPublic }); const nonce = await sendRequestFromGetter(teeWorker, parachainApi, mrenclave, teeShieldingKey, getter, log); const nonceValue = decodeNonce(nonce.value.toHex()); return parachainApi.createType('Index', nonceValue) as Index; @@ -341,27 +342,25 @@ export async function getEnclave(api: ParachainApiPromise): Promise<{ mrEnclave: `0x${string}`; teeShieldingKey: KeyObject; }> { - const count = await api.query.teerex.enclaveCount(); + const enclaveIdentifier = api.createType('Vec', await api.query.teebag.enclaveIdentifier('Identity')); + const primaryEnclave = (await api.query.teebag.enclaveRegistry(enclaveIdentifier[0])).unwrap(); - const res = (await api.query.teerex.enclaveRegistry(count)).toHuman() as { - mrEnclave: `0x${string}`; - shieldingKey: `0x${string}`; - vcPubkey: `0x${string}`; - sgxMetadata: object; - }; + const shieldingPubkeyBytes = api.createType('Option', primaryEnclave.shieldingPubkey).unwrap(); + const shieldingPubkey = hexToString(shieldingPubkeyBytes.toHex()); const teeShieldingKey = crypto.createPublicKey({ key: { alg: 'RSA-OAEP-256', kty: 'RSA', use: 'enc', - n: Buffer.from(JSON.parse(res.shieldingKey).n.reverse()).toString('base64url'), - e: Buffer.from(JSON.parse(res.shieldingKey).e.reverse()).toString('base64url'), + n: Buffer.from(JSON.parse(shieldingPubkey).n.reverse()).toString('base64url'), + e: Buffer.from(JSON.parse(shieldingPubkey).e.reverse()).toString('base64url'), }, format: 'jwk', }); //@TODO mrEnclave should verify from storage - const mrEnclave = res.mrEnclave; + const mrEnclave = primaryEnclave.mrenclave.toHex(); + return { mrEnclave, teeShieldingKey, @@ -404,7 +403,7 @@ const createSignedTrustedCall = async ( call: call, index: nonce, signature: signature, - }) as unknown as TrustedCallSigned; + }); }; export const subscribeToEventsWithExtHash = async ( diff --git a/tee-worker/ts-tests/worker/package.json b/tee-worker/ts-tests/worker/package.json index 2113d20611..03268303cf 100644 --- a/tee-worker/ts-tests/worker/package.json +++ b/tee-worker/ts-tests/worker/package.json @@ -3,10 +3,9 @@ "license": "ISC", "type": "module", "scripts": { - "format": "pnpm exec prettier --write .", - "check-format": "pnpm exec prettier --check .", - "test-resuming-worker:staging": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=staging mocha --trace-warnings --full-trace --exit --sort -r ts-node/register --loader=ts-node/esm 'resuming_worker.test.ts'", - "test-resuming-worker:local": "pnpm exec eslint . && pnpm exec cross-env NODE_ENV=local mocha --exit --sort -r ts-node/register --loader=ts-node/esm 'resuming_worker.test.ts'" + "format": "prettier --write .", + "check-format": "prettier --check .", + "test": "mocha --trace-warnings --full-trace --exit --sort -r ts-node/register --loader=ts-node/esm" }, "dependencies": { "chai": "^4.3.6", diff --git a/tee-worker/ts-tests/worker/resuming_worker.test.ts b/tee-worker/ts-tests/worker/resuming_worker.test.ts index f5a7f49c1d..0e3060de9d 100644 --- a/tee-worker/ts-tests/worker/resuming_worker.test.ts +++ b/tee-worker/ts-tests/worker/resuming_worker.test.ts @@ -141,7 +141,7 @@ async function spawnWorkerJob( let shard: HexString | undefined = undefined; const job = spawn( - `./litentry-worker`, + `RUST_LOG=info ./litentry-worker`, [generateWorkerCommandArguments(command, nodeConfig, workerConfig)], { cwd: workingDir, diff --git a/ts-tests/common/setup/setup-enclave.ts b/ts-tests/common/setup/setup-enclave.ts index 36faf3db7b..818236a978 100644 --- a/ts-tests/common/setup/setup-enclave.ts +++ b/ts-tests/common/setup/setup-enclave.ts @@ -11,17 +11,17 @@ async function setAliceAsAdmin(api: ApiPromise, config: any) { const keyring = new Keyring({ type: 'sr25519' }); const alice = keyring.addFromUri('//Alice'); - const tx = api.tx.sudo.sudo(api.tx.teerex.setAdmin('esqZdrqhgH8zy1wqYh1aLKoRyoRWLFbX9M62eKfaTAoK67pJ5')); + const tx = api.tx.sudo.sudo(api.tx.teebag.setAdmin('esqZdrqhgH8zy1wqYh1aLKoRyoRWLFbX9M62eKfaTAoK67pJ5')); - console.log(`Setting Alice as Admin for Teerex`); + console.log(`Setting Alice as Admin for Teebag`); return signAndSend(tx, alice); } -async function updateScheduledEnclave(api: ApiPromise, config: any) { +async function setScheduledEnclave(api: ApiPromise, config: any) { const keyring = new Keyring({ type: 'sr25519' }); const alice = keyring.addFromUri('//Alice'); - const tx = api.tx.teerex.updateScheduledEnclave(block, hexToU8a(`0x${mrenclave}`)); + const tx = api.tx.teebag.setScheduledEnclave('Identity', block, hexToU8a(`0x${mrenclave}`)); console.log('Schedule Enclave Extrinsic sent'); return signAndSend(tx, alice); @@ -37,7 +37,7 @@ async function updateScheduledEnclave(api: ApiPromise, config: any) { }); await setAliceAsAdmin(api, config); - await updateScheduledEnclave(api, config); + await setScheduledEnclave(api, config); await api.disconnect(); provider.on('disconnected', () => { diff --git a/ts-tests/common/setup/skip-schedule-enclave-check.ts b/ts-tests/common/setup/teebag-set-dev-mode.ts similarity index 68% rename from ts-tests/common/setup/skip-schedule-enclave-check.ts rename to ts-tests/common/setup/teebag-set-dev-mode.ts index 47e150d6d5..fc41a5c1dd 100644 --- a/ts-tests/common/setup/skip-schedule-enclave-check.ts +++ b/ts-tests/common/setup/teebag-set-dev-mode.ts @@ -1,29 +1,25 @@ import '@polkadot/api-augment'; import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; import { loadConfig, signAndSend } from '../utils'; -import { hexToU8a } from '@polkadot/util'; - -const mrenclave = process.argv[2]; -const block = process.argv[3]; async function setAliceAsAdmin(api: ApiPromise, config: any) { // Get keyring of Alice, who is also the sudo in dev chain spec const keyring = new Keyring({ type: 'sr25519' }); const alice = keyring.addFromUri('//Alice'); - const tx = api.tx.sudo.sudo(api.tx.teerex.setAdmin('esqZdrqhgH8zy1wqYh1aLKoRyoRWLFbX9M62eKfaTAoK67pJ5')); + const tx = api.tx.sudo.sudo(api.tx.teebag.setAdmin('esqZdrqhgH8zy1wqYh1aLKoRyoRWLFbX9M62eKfaTAoK67pJ5')); - console.log(`Setting Alice as Admin for Teerex`); + console.log(`Setting Alice as Admin for Teebag`); return signAndSend(tx, alice); } -async function updateSkipScheduledEnclaveCheck(api: ApiPromise, config: any) { +async function setDevelopmentMode(api: ApiPromise, config: any) { const keyring = new Keyring({ type: 'sr25519' }); const alice = keyring.addFromUri('//Alice'); - const tx = api.tx.teerex.setSkipScheduledEnclaveCheck(true); + const tx = api.tx.teebag.setMode('Development'); - console.log('set Skip Schedule Enclave Extrinsic sent'); + console.log('set development mode Extrinsic sent'); return signAndSend(tx, alice); } @@ -37,7 +33,7 @@ async function updateSkipScheduledEnclaveCheck(api: ApiPromise, config: any) { }); await setAliceAsAdmin(api, config); - await updateSkipScheduledEnclaveCheck(api, config); + await setDevelopmentMode(api, config); await api.disconnect(); provider.on('disconnected', () => {