From 21cacf9ae6961cd70bd5e6fc728305b3be94fb81 Mon Sep 17 00:00:00 2001 From: mosonyi Date: Thu, 24 Aug 2023 16:53:51 +0200 Subject: [PATCH 1/5] Remove debug message (#1421) --- docker/entrypoint.sh | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index c7e9e2c9..bceee8d4 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -4,29 +4,4 @@ set -e # run aesmd in the background /opt/intel/sgx-aesm-service/aesm/aesm_service -# for debugging: will be in the CI logs: -cat /etc/sgx_default_qcnl.conf - -echo '{ - - "pccs_url": "https://ajuna-02.cluster.securitee.tech:8081/sgx/certification/v4/", - - "use_secure_cert": false, - - "collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/", - - - "retry_times": 6, - - "retry_delay": 10, - - - "pck_cache_expire_hours": 168, - - "verify_collateral_cache_expire_hours": 168 - -}' > /etc/sgx_default_qcnl.conf - -cat /etc/sgx_default_qcnl.conf - exec /usr/local/bin/integritee-service "${@}" From 1643dc7084554c214639643498e912c9983f5149 Mon Sep 17 00:00:00 2001 From: clangenb <37865735+clangenb@users.noreply.github.com> Date: Sat, 26 Aug 2023 12:48:49 +0200 Subject: [PATCH 2/5] [GHA] fix sccache install failure (#1425) --- build.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.Dockerfile b/build.Dockerfile index 13f8dfb4..5f4e5985 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -43,7 +43,7 @@ ENV WORKHOME=/home/ubuntu/work ENV HOME=/home/ubuntu RUN rustup default stable -RUN cargo install sccache +RUN cargo install sccache --locked ENV SCCACHE_CACHE_SIZE="20G" ENV SCCACHE_DIR=$HOME/.cache/sccache From 1d4b9fe1ea0cac2249e8f338b63cc9448569644b Mon Sep 17 00:00:00 2001 From: brenzi Date: Tue, 29 Aug 2023 11:39:05 +0200 Subject: [PATCH 3/5] Ab/fix demos (#1429) * let pallet and node point to release branches * use new integritee-dev image and allow passing additional arguments to worker docker to make demo tutorials work * bump crate versions and add more verbose outputs for demos * fix clippy --- .github/workflows/build_and_test.yml | 2 +- Cargo.lock | 33 ++++++++++--------- Dockerfile | 2 +- Jenkinsfile | 2 +- app-libs/sgx-runtime/Cargo.toml | 2 +- app-libs/stf/Cargo.toml | 4 +-- build.Dockerfile | 16 ++++----- cli/Cargo.toml | 10 +++--- cli/demo_direct_call.sh | 2 ++ cli/demo_direct_call_2_workers.sh | 9 ++++- cli/demo_indirect_invocation.sh | 9 ++++- cli/demo_shielding_unshielding.sh | 1 + cli/demo_sidechain.sh | 5 +-- cli/demo_smart_contract.sh | 1 + cli/demo_teeracle_generic.sh | 1 + cli/demo_teeracle_whitelist.sh | 1 + cli/src/lib.rs | 4 ++- core-primitives/enclave-api/Cargo.toml | 2 +- .../node-api/api-client-types/Cargo.toml | 2 +- core-primitives/types/Cargo.toml | 6 ++-- docker/docker-compose.yml | 4 +-- enclave-runtime/Cargo.lock | 10 +++--- enclave-runtime/Cargo.toml | 4 +-- local-setup/py/helpers.py | 2 +- service/Cargo.toml | 10 +++--- service/src/cli.yml | 2 +- service/src/main.rs | 25 +++++++++++++- 27 files changed, 109 insertions(+), 62 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 51c99311..c18b6a4f 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -127,7 +127,7 @@ jobs: clippy: runs-on: ubuntu-latest - container: "integritee/integritee-dev:0.2.1" + container: "integritee/integritee-dev:0.2.2" steps: - uses: actions/checkout@v3 - name: init rust diff --git a/Cargo.lock b/Cargo.lock index 56e63303..6d917ea0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -726,7 +726,7 @@ dependencies = [ [[package]] name = "claims-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "parity-scale-codec", "rustc-hex", @@ -831,7 +831,7 @@ dependencies = [ [[package]] name = "common-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +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", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "enclave-bridge-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "common-primitives", "log 0.4.19", @@ -2746,7 +2746,7 @@ dependencies = [ [[package]] name = "integritee-cli" -version = "0.9.0" +version = "0.12.0" dependencies = [ "array-bytes 6.1.0", "base58", @@ -2795,7 +2795,7 @@ dependencies = [ [[package]] name = "integritee-node-runtime" version = "1.1.34" -source = "git+https://github.com/integritee-network/integritee-node.git?branch=polkadot-v0.9.42#31b72e13596c36c4963ed6caf631377b68d34754" +source = "git+https://github.com/integritee-network/integritee-node.git?branch=sdk-v0.12.0-polkadot-v0.9.42#1fb7b051ca3b3ce63fcb1ae2f898aa067f8b3a1d" dependencies = [ "frame-executive", "frame-support", @@ -2840,7 +2840,7 @@ dependencies = [ [[package]] name = "integritee-service" -version = "0.9.0" +version = "0.12.0" dependencies = [ "anyhow", "async-trait", @@ -5387,7 +5387,7 @@ dependencies = [ [[package]] name = "pallet-claims" version = "0.9.12" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "claims-primitives", "frame-support", @@ -5457,7 +5457,7 @@ dependencies = [ [[package]] name = "pallet-enclave-bridge" version = "0.10.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "enclave-bridge-primitives", "frame-support", @@ -5555,7 +5555,7 @@ dependencies = [ [[package]] name = "pallet-parentchain" version = "0.9.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "frame-support", "frame-system", @@ -5640,7 +5640,7 @@ dependencies = [ [[package]] name = "pallet-sidechain" version = "0.10.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "enclave-bridge-primitives", "frame-support", @@ -5699,7 +5699,7 @@ dependencies = [ [[package]] name = "pallet-teeracle" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "frame-support", "frame-system", @@ -5719,10 +5719,11 @@ dependencies = [ [[package]] name = "pallet-teerex" version = "0.10.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "frame-support", "frame-system", + "hex", "log 0.4.19", "pallet-timestamp", "parity-scale-codec", @@ -7204,7 +7205,7 @@ dependencies = [ [[package]] name = "sgx-verify" version = "0.1.4" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "base64 0.13.1", "chrono 0.4.26", @@ -7491,7 +7492,7 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "sidechain-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "parity-scale-codec", "scale-info", @@ -8426,7 +8427,7 @@ checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" [[package]] name = "teeracle-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "common-primitives", "sp-std", @@ -8436,7 +8437,7 @@ dependencies = [ [[package]] name = "teerex-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets.git?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "common-primitives", "derive_more", diff --git a/Dockerfile b/Dockerfile index 076a2a3b..95bd8a9d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM integritee/integritee-dev:0.1.13 +FROM integritee/integritee-dev:0.2.2 LABEL maintainer="zoltan@integritee.network" # By default we warp the service diff --git a/Jenkinsfile b/Jenkinsfile index c92d5df2..62c9197d 100755 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,7 +1,7 @@ pipeline { agent { docker { - image 'integritee/integritee-dev:0.1.7' + image 'integritee/integritee-dev:0.2.2' args ''' -u root --privileged diff --git a/app-libs/sgx-runtime/Cargo.toml b/app-libs/sgx-runtime/Cargo.toml index e55df95e..381bafc6 100644 --- a/app-libs/sgx-runtime/Cargo.toml +++ b/app-libs/sgx-runtime/Cargo.toml @@ -46,7 +46,7 @@ sp-version = { default-features = false, git = "https://github.com/paritytech/su # 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 = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +pallet-parentchain = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } [features] default = ["std"] diff --git a/app-libs/stf/Cargo.toml b/app-libs/stf/Cargo.toml index 865edd49..719653ba 100644 --- a/app-libs/stf/Cargo.toml +++ b/app-libs/stf/Cargo.toml @@ -39,8 +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" } # scs / integritee -my-node-runtime = { package = "integritee-node-runtime", optional = true, git = "https://github.com/integritee-network/integritee-node.git", branch = "polkadot-v0.9.42" } -pallet-parentchain = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +my-node-runtime = { package = "integritee-node-runtime", optional = true, git = "https://github.com/integritee-network/integritee-node.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } +pallet-parentchain = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } [dev-dependencies] diff --git a/build.Dockerfile b/build.Dockerfile index 5f4e5985..6f7c6da7 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -21,7 +21,7 @@ # A builder stage that uses sccache to speed up local builds with docker # Installation and setup of sccache should be moved to the integritee-dev image, so we don't # always need to compile and install sccache on CI (where we have no caching so far). -FROM integritee/integritee-dev:0.2.1 AS builder +FROM integritee/integritee-dev:0.2.2 AS builder LABEL maintainer="zoltan@integritee.network" # set environment variables @@ -42,7 +42,7 @@ ENV SGX_PRODUCTION=$SGX_PRODUCTION ENV WORKHOME=/home/ubuntu/work ENV HOME=/home/ubuntu -RUN rustup default stable +RUN rustup default stable RUN cargo install sccache --locked ENV SCCACHE_CACHE_SIZE="20G" @@ -84,12 +84,12 @@ RUN apt-get install -y \ libsgx-aesm-quote-ex-plugin \ libsgx-dcap-default-qpl \ libsgx-dcap-ql \ - libsgx-dcap-quote-verify \ - libsgx-epid \ - libsgx-headers \ - libsgx-quote-ex \ - libsgx-ra-network \ - libsgx-ra-uefi \ + libsgx-dcap-quote-verify \ + libsgx-epid \ + libsgx-headers \ + libsgx-quote-ex \ + libsgx-ra-network \ + libsgx-ra-uefi \ libsgx-uae-service ### Deployed CLI client diff --git a/cli/Cargo.toml b/cli/Cargo.toml index f49593f1..3f2e862e 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "integritee-cli" -version = "0.9.0" +version = "0.12.0" authors = ["Integritee AG "] edition = "2021" @@ -25,12 +25,12 @@ thiserror = "1.0" ws = { version = "0.9.1", features = ["ssl"] } # scs / integritee -my-node-runtime = { package = "integritee-node-runtime", git = "https://github.com/integritee-network/integritee-node.git", branch = "polkadot-v0.9.42" } -pallet-enclave-bridge = { git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +my-node-runtime = { package = "integritee-node-runtime", git = "https://github.com/integritee-network/integritee-node.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } +pallet-enclave-bridge = { git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } pallet-evm = { optional = true, git = "https://github.com/integritee-network/frontier.git", branch = "bar/polkadot-v0.9.42" } -pallet-teerex = { git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +pallet-teerex = { git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } # `default-features = false` to remove the jsonrpsee dependency. -enclave-bridge-primitives = { git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +enclave-bridge-primitives = { git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } substrate-api-client = { default-features = false, features = ["std", "ws-client"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.10.0" } substrate-client-keystore = { git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.10.0" } diff --git a/cli/demo_direct_call.sh b/cli/demo_direct_call.sh index 6f6f1f92..f96e59d5 100755 --- a/cli/demo_direct_call.sh +++ b/cli/demo_direct_call.sh @@ -57,10 +57,12 @@ WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version echo "Using node uri ${NODEURL}:${NPORT}" echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" echo "" + AMOUNTSHIELD=50000000000 AMOUNTTRANSFER=40000000000 diff --git a/cli/demo_direct_call_2_workers.sh b/cli/demo_direct_call_2_workers.sh index c92615e3..bff2cdd0 100755 --- a/cli/demo_direct_call_2_workers.sh +++ b/cli/demo_direct_call_2_workers.sh @@ -45,9 +45,16 @@ WORKER2URL=${WORKER2URL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${NODEURL}:${NPORT}" +echo "Using trusted-worker uri 1 ${WORKER1URL}:${WORKER1PORT}" +echo "Using trusted-worker uri 2 ${WORKER2URL}:${WORKER2PORT}" +echo "" + SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) "${SCRIPT_DIR}"/demo_direct_call.sh -p "${NPORT}" -u "${NODEURL}" -V "${WORKER1URL}" -P "${WORKER1PORT}" -C "${CLIENT_BIN}" -t first "${SCRIPT_DIR}"/demo_direct_call.sh -p "${NPORT}" -u "${NODEURL}" -V "${WORKER2URL}" -P "${WORKER2PORT}" -C "${CLIENT_BIN}" -t second -exit 0 \ No newline at end of file +exit 0 diff --git a/cli/demo_indirect_invocation.sh b/cli/demo_indirect_invocation.sh index 68bdf352..009f8596 100755 --- a/cli/demo_indirect_invocation.sh +++ b/cli/demo_indirect_invocation.sh @@ -43,9 +43,16 @@ WORKER2URL=${WORKER2URL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${NODEURL}:${NPORT}" +echo "Using trusted-worker 1 uri ${WORKER1URL}:${WORKER1PORT}" +echo "Using trusted-worker 2 uri ${WORKER2URL}:${WORKER2PORT}" +echo "" + SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) "${SCRIPT_DIR}"/demo_shielding_unshielding.sh -p "${NPORT}" -u "${NODEURL}" -V "${WORKER1URL}" -P "${WORKER1PORT}" -C "${CLIENT_BIN}" -t first "${SCRIPT_DIR}"/demo_shielding_unshielding.sh -p "${NPORT}" -u "${NODEURL}" -V "${WORKER2URL}" -P "${WORKER2PORT}" -C "${CLIENT_BIN}" -t second -exit 0 \ No newline at end of file +exit 0 diff --git a/cli/demo_shielding_unshielding.sh b/cli/demo_shielding_unshielding.sh index 25b684ad..18abc0cb 100755 --- a/cli/demo_shielding_unshielding.sh +++ b/cli/demo_shielding_unshielding.sh @@ -60,6 +60,7 @@ WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version echo "Using node uri ${NODEURL}:${NPORT}" echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" echo "" diff --git a/cli/demo_sidechain.sh b/cli/demo_sidechain.sh index a9c160cf..f6b1f1b9 100755 --- a/cli/demo_sidechain.sh +++ b/cli/demo_sidechain.sh @@ -70,9 +70,10 @@ WORKER2URL=${WORKER2URL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version echo "Using node uri ${NODEURL}:${NPORT}" -echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" -echo "Using trusted-worker-2 uri ${WORKER2URL}:${WORKER2PORT}" +echo "Using trusted-worker 1 uri ${WORKER1URL}:${WORKER1PORT}" +echo "Using trusted-worker 2 uri ${WORKER2URL}:${WORKER2PORT}" INITIALFUNDS=50000000000 AMOUNTTRANSFER=20000000000 diff --git a/cli/demo_smart_contract.sh b/cli/demo_smart_contract.sh index e04b6e4d..1c3ceb4c 100755 --- a/cli/demo_smart_contract.sh +++ b/cli/demo_smart_contract.sh @@ -53,6 +53,7 @@ WORKERURL=${WORKERURL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version echo "Using node uri ${NODEURL}:${NPORT}" echo "Using trusted-worker uri ${WORKERURL}:${WORKERPORT}" diff --git a/cli/demo_teeracle_generic.sh b/cli/demo_teeracle_generic.sh index 34692c6a..99caf605 100755 --- a/cli/demo_teeracle_generic.sh +++ b/cli/demo_teeracle_generic.sh @@ -67,6 +67,7 @@ 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 ${NODEURL}:${NPORT}" echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" echo "Using worker data update interval ${INTERVAL}" diff --git a/cli/demo_teeracle_whitelist.sh b/cli/demo_teeracle_whitelist.sh index d56b0172..ba64ee8f 100755 --- a/cli/demo_teeracle_whitelist.sh +++ b/cli/demo_teeracle_whitelist.sh @@ -67,6 +67,7 @@ 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 ${NODEURL}:${NPORT}" echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" echo "Using worker market data update interval ${INTERVAL}" diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 3cde1331..68c1dba1 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -59,7 +59,9 @@ pub(crate) const ED25519_KEY_TYPE: KeyTypeId = KeyTypeId(*b"ed25"); #[clap(name = "integritee-cli")] #[clap(version = VERSION)] #[clap(author = "Integritee AG ")] -#[clap(about = "interact with integritee-node and workers", long_about = None)] +#[cfg_attr(feature = "teeracle", clap(about = "interact with integritee-node and teeracle", long_about = None))] +#[cfg_attr(feature = "sidechain", clap(about = "interact with integritee-node and sidechain", long_about = None))] +#[cfg_attr(feature = "offchain-worker", clap(about = "interact with integritee-node 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 diff --git a/core-primitives/enclave-api/Cargo.toml b/core-primitives/enclave-api/Cargo.toml index 00500004..c1d4249a 100644 --- a/core-primitives/enclave-api/Cargo.toml +++ b/core-primitives/enclave-api/Cargo.toml @@ -20,7 +20,7 @@ sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate.git", br sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } -teerex-primitives = { git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +teerex-primitives = { git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } itc-parentchain = { path = "../../core/parentchain/parentchain-crate" } itp-enclave-api-ffi = { path = "ffi" } diff --git a/core-primitives/node-api/api-client-types/Cargo.toml b/core-primitives/node-api/api-client-types/Cargo.toml index d8f8452d..677e4b61 100644 --- a/core-primitives/node-api/api-client-types/Cargo.toml +++ b/core-primitives/node-api/api-client-types/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] # integritee-node -my-node-runtime = { package = "integritee-node-runtime", optional = true, git = "https://github.com/integritee-network/integritee-node.git", branch = "polkadot-v0.9.42" } +my-node-runtime = { package = "integritee-node-runtime", optional = true, git = "https://github.com/integritee-network/integritee-node.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } # scs substrate-api-client = { default-features = false, git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.10.0" } diff --git a/core-primitives/types/Cargo.toml b/core-primitives/types/Cargo.toml index 49747cdc..5d1bc846 100644 --- a/core-primitives/types/Cargo.toml +++ b/core-primitives/types/Cargo.toml @@ -25,9 +25,9 @@ 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" } # integritee-node -enclave-bridge-primitives = { git = "https://github.com/integritee-network/pallets.git", default-features = false, branch = "polkadot-v0.9.42" } -my-node-runtime = { package = "integritee-node-runtime", optional = true, git = "https://github.com/integritee-network/integritee-node.git", branch = "polkadot-v0.9.42" } -teerex-primitives = { git = "https://github.com/integritee-network/pallets.git", default-features = false, branch = "polkadot-v0.9.42" } +enclave-bridge-primitives = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } +my-node-runtime = { package = "integritee-node-runtime", optional = true, git = "https://github.com/integritee-network/integritee-node.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } +teerex-primitives = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } [features] diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 3a45992a..dff07411 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -43,7 +43,7 @@ services: interval: 10s timeout: 10s retries: 25 - command: "--clean-reset --ws-external -M integritee-worker-1 -T wss://integritee-worker-1 -u ws://integritee-node -U ws://integritee-worker-1 -P 2011 -w 2101 -p 9912 -h 4645 run --dev" + command: "--clean-reset --data-dir /tmp/worker1 --ws-external -M integritee-worker-1 -T wss://integritee-worker-1 -u ws://integritee-node -U ws://integritee-worker-1 -P 2011 -w 2101 -p 9912 -h 4645 run --dev ${ADDITIONAL_RUNTIME_FLAGS}" restart: "no" "integritee-worker-2-${VERSION}": image: integritee-worker:${VERSION:-dev} @@ -72,7 +72,7 @@ services: interval: 10s timeout: 10s retries: 25 - command: "--clean-reset --ws-external -M integritee-worker-2 -T wss://integritee-worker-2 -u ws://integritee-node -U ws://integritee-worker-2 -P 2012 -w 2102 -p 9912 -h 4646 run --dev --request-state" + command: "--clean-reset --data-dir /tmp/worker2 --ws-external -M integritee-worker-2 -T wss://integritee-worker-2 -u ws://integritee-node -U ws://integritee-worker-2 -P 2012 -w 2102 -p 9912 -h 4646 run --dev --request-state ${ADDITIONAL_RUNTIME_FLAGS}" restart: "no" networks: integritee-test-network: diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index 5dad567a..c3d8e682 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -487,7 +487,7 @@ dependencies = [ [[package]] name = "common-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +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", @@ -708,7 +708,7 @@ dependencies = [ [[package]] name = "enclave-bridge-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "common-primitives", "log", @@ -723,7 +723,7 @@ dependencies = [ [[package]] name = "enclave-runtime" -version = "0.9.0" +version = "0.12.0" dependencies = [ "array-bytes 6.1.0", "cid", @@ -3001,7 +3001,7 @@ dependencies = [ [[package]] name = "pallet-parentchain" version = "0.9.0" -source = "git+https://github.com/integritee-network/pallets?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "frame-support", "frame-system", @@ -4573,7 +4573,7 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "teerex-primitives" version = "0.1.0" -source = "git+https://github.com/integritee-network/pallets?branch=polkadot-v0.9.42#5c52182eb3a5156e8d9f69c10ca1441214ee6662" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" dependencies = [ "common-primitives", "derive_more", diff --git a/enclave-runtime/Cargo.toml b/enclave-runtime/Cargo.toml index 0447caad..ac380e5f 100644 --- a/enclave-runtime/Cargo.toml +++ b/enclave-runtime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enclave-runtime" -version = "0.9.0" +version = "0.12.0" authors = ["Integritee AG "] edition = "2021" @@ -89,7 +89,7 @@ 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 = { git = "https://github.com/integritee-network/pallets", branch = "polkadot-v0.9.42", default-features = false } +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"] } diff --git a/local-setup/py/helpers.py b/local-setup/py/helpers.py index 9eedd716..9c00d50c 100644 --- a/local-setup/py/helpers.py +++ b/local-setup/py/helpers.py @@ -32,7 +32,7 @@ def setup_working_dir(source_dir: str, target_dir: str): if os.path.exists(source): shutil.copy(source, target) else: - print(f'{source} does not exist, this is fine, but you can\'t perform remote attestation with this.') + print(f'{source} does not exist, this may be fine for DCAP or skip-ra, but you can\'t perform IAS remote attestation without this file.') mandatory = ['enclave.signed.so', 'integritee-service'] diff --git a/service/Cargo.toml b/service/Cargo.toml index 0ecd12ed..774d9794 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "integritee-service" -version = "0.9.0" +version = "0.12.0" authors = ["Integritee AG "] build = "build.rs" edition = "2021" @@ -60,12 +60,12 @@ its-storage = { path = "../sidechain/storage" } # scs / integritee -my-node-runtime = { package = "integritee-node-runtime", git = "https://github.com/integritee-network/integritee-node.git", branch = "polkadot-v0.9.42" } -sgx-verify = { git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +my-node-runtime = { package = "integritee-node-runtime", git = "https://github.com/integritee-network/integritee-node.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } +sgx-verify = { git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } # `default-features = false` to remove the jsonrpsee dependency. -enclave-bridge-primitives = { git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +enclave-bridge-primitives = { git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } substrate-api-client = { default-features = false, features = ["std", "ws-client"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.10.0" } -teerex-primitives = { git = "https://github.com/integritee-network/pallets.git", branch = "polkadot-v0.9.42" } +teerex-primitives = { git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } # Substrate dependencies frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } diff --git a/service/src/cli.yml b/service/src/cli.yml index 42f22834..2faedcf9 100644 --- a/service/src/cli.yml +++ b/service/src/cli.yml @@ -1,5 +1,5 @@ name: "integritee-service" -version: "0.8.0" +version: "0.12.0" about: Worker using Intel SGX TEE for Integritee-node authors: "Integritee AG " diff --git a/service/src/main.rs b/service/src/main.rs index cab77e72..25a83777 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -316,7 +316,30 @@ fn start_worker( let run_config = config.run_config().clone().expect("Run config missing"); let skip_ra = run_config.skip_ra(); - println!("Integritee Worker v{}", VERSION); + #[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!("Integritee Worker for {} v{}", flavor_str, VERSION); + + #[cfg(feature = "dcap")] + println!(" DCAP is enabled"); + #[cfg(not(feature = "dcap"))] + println!(" DCAP is disabled"); + #[cfg(feature = "production")] + 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()); // ------------------------------------------------------------------------ // check for required files From 1323415d284c8bf0e5a24e367f4d077dd54dfcf2 Mon Sep 17 00:00:00 2001 From: clangenb <37865735+clangenb@users.noreply.github.com> Date: Fri, 8 Sep 2023 13:47:20 +0200 Subject: [PATCH 4/5] multiple parentchain handlers (#1420) * [enclave-runtime/initialization] lift some code out of the innermost function * [enclave-runtime/initialization] rename `EnclaveIndirectExecutor` to `TeerexParentchainIndirectExecutor` * [enclave-runtime/initialization] rename stuff that is only for the primary parentchain containing the teerex pallet * [enclave-runtime/initialization] naively add second set of components needed for a second parachain * [enclave-runtime/initialization] introduce second nonce cache for the second parachain * [enclave-runtime/initialization/global_components] fix wrong type arg * [indirect-calls-executor] fix `DenyAll` implementation * [enclave-runtime/initialization] code compiles for instantiating a secondary parachain parentchain handler. * [enclave-runtime/initialization] fmt * [enclave-runtime/initialization] add second set of solochain parentchain handler * [enclave-runtime/initialization] extend parentchain init params with the secondary parentchains * [enclave-runtime/initialization] add second light-client seal * change parentchain init params enum, and add full code for initialization. * fix some comments and naming * [service] add cli options for the secondary node * extract `init_parentchain` function in service and add `parentchain_id` to `set_nonce` and `set_metadata` ecalls (id is not used yet in the enclave) * rename `get_node_metadata_repository_from_solo_or_parachain` to `get_node_metadata_repository_from_teerex_solo_or_parachain` and add `get_node_metadata_repository_from_secondary_solo_or_parachain` * [enclave-runtime] `set_nonce` takes into account the parentchain id now * fix test compilation * add complete code for secondary parentchain * [service/config] fix cli naming * [service] indicate in logs that they are for the secondary parentchain * [service] fix clippy * [service] fix tests * [enclave-runtime] fix: don't initialize second light client seal on the global for the first client * [service/setup] fix purging second light client db. * [service] print block number at which the enclave registered. * [parentchain] remove some unnecessary trait bounds (simplify error message) * [enclave-runtime] remove unused unit test * OnchainOcallApi does not take a paramenter such that it nows, which parentchain to talk to. * [stf-executor] remove code that executes a state update upon before stf execution as it is apparently no longer needed * [service] propagate parentchain id throughout the codebase * [service] fix tests * [local-setup] prepare configs to run multiple nodes * [stf-executor/executor] fix wrong import * [local-setup] add a config that spawns two nodes * [service] remove unnecessary traitbounds * [service] minor logging fixes * `sync_parentchain` and `trigger_parentchain_block_import` have the `ParentchainId` are too now. * [service/worker_onchain_ocall] log to which parentchain we want to send the extrinsic * [service/ocall_bridge] fix log typo * [enclave-runtime] supress clippy warning * [service] fix: fund enclave on secondary parentchain * [service/worker_on_chain_ocall] improve log for extrinsic * [local-setup] sleep 18 between setting up nodes, so that the logs are easier to distinguish * add new indirect calls filer, which checks for transfers to alice to shield these funds * [indirect-executor] use correct type in `TransferToAliceShieldsFundsFilter` * [indirect-executor] better logging * [local-setup/tmux_logger_two_nodes] only use three panes as the last one was unused * [indirect-executor] remove unused imports * [indirect-executor/transfer_to_alice_shields_funds] fix alice account * [local-setup] use trace in indirect executor * [cli] add `demo_shielding_unshielding_two_nodes` (working) * rename `ParentchainId` enum variants to `Integritee` and `TargetA` * [node-api/metadata] format pallet_balances licence header. * [indirect-calls-executor] fix documentation * [indirect-calls-executor] rename `ALICE_ENCODED` to `ALICE_SEED` * [Enclave.edl] fix indents * rename `get_node_metadata_from_teerex_solo_or_parachain` to `get_node_metadata_repository_from_integritee_solo_or_parachain` * [enclave-runtime] rename error `NoTeerexParentchainAssigned` to `NoIntegriteeParentchainAssigned` * [enclave-runtime] rename error `NoSecondaryParentchainAssigned` to `NoTargetAParentchainAssigned` * [itp-nonce-cache] rename caches to `INTEGRITEE_NONCE_CACHE` and `TARGET_A_PARENTCHAIN_NONCE_CACHE` * move nonce caches to the enclave-runtimes global components * [enclave-runtime] change doc comments to regular comments were suitable * [itp-settings] rename light-client db paths * [enclave-runtime/initialization] rename parachain.rs to integritee_parachain.rs and `FullParachainHandler` to `IntegriteeParachainHandler` * [enclave-runtime/initialization] rename parachain2.rs to target_a_parachain.rs and `FullParachainHandler2` to `TargetAParachainHandler` * [enclave-runtime/initialization] rename solochain.rs to integritee_solochain.rs and `FullSolochainHandler` to `IntegriteeSolochainHandler` * [enclave-runtime/initialization] rename solochain2.rs to target_a_solochain.rs and `FullSolochainHandler2` to `TargetASolochainHandler` * [enclave-runtime/initialization] reflect previous changes in global components naming * [enclave-runtime/initialization] consistent naming in global components * [enclave-runtime/initialization] rename Teerex... types to Integritee... types * [enclave-runtime/initialization] rename Secondary... types to TargetA... types * [enclave-runtime/initialization] better distinguish the two light-client seals * [enclave-runtime] some more minor renamings for new scheme * [itp-settings] fix naming of target_a light client db path * [enclave-runtime/global_components] fix grammar in doc * [enclave-runtime/global_components] minor doc fixes * [enclave-runtime/initialization] fix naming of light-client-db variables * [cli] rename cli args in demo scripts to be more readable and use new names for parentchains * fmt * [enclave-runtime] more ergonomic code due to shorter variable names. * [indirect-calls-executor] simplify creation of alice's account id * [indirect-calls-executor] add an assert_eq in the doc test * [service] update cli arguments to new parentchain naming * [service/config] fix missing renamings * [service/node_api_factory] add endpoint renamings * [service/main] rename node_api to integritee_rpc_api * [service/main] rename `init_parentchain` and `init_secondary_parentchain` to `init_integritee_parentchain` and `init_target_a_parentchain` * [service/config] fix naming * [service/main] fix moving of variables * [service] fix tests * [service/bridge-api] rename error to new chain naming * [service/ocall_bridge] rename api factories for new naming * consisten naming change remaning: target_a_chain -> target_a_parentchain * fix missing minor renamings * clippy * [enclave-runtime/global-components] fix misallocation of `IntegriteeBlockImporter` to a Target A parentchain type. (this did not have any effect in the offchain-worker case) --- app-libs/stf/src/stf_sgx.rs | 9 +- cli/demo_direct_call.sh | 27 ++- cli/demo_direct_call_2_workers.sh | 3 + cli/demo_indirect_invocation.sh | 37 +-- ...d_on_second_node_with_transfer_to_alice.sh | 149 ++++++++++++ cli/demo_shielding_unshielding.sh | 29 ++- cli/demo_sidechain.sh | 46 ++-- cli/demo_smart_contract.sh | 27 ++- cli/demo_teeracle_generic.sh | 25 +- cli/demo_teeracle_whitelist.sh | 25 +- core-primitives/enclave-api/ffi/src/lib.rs | 9 +- .../enclave-api/src/enclave_base.rs | 59 ++++- core-primitives/enclave-api/src/sidechain.rs | 9 +- core-primitives/node-api/metadata/src/lib.rs | 1 + .../node-api/metadata/src/pallet_balances.rs | 37 +++ core-primitives/nonce-cache/src/lib.rs | 9 - core-primitives/ocall-api/src/lib.rs | 13 +- core-primitives/settings/src/lib.rs | 7 +- core-primitives/stf-executor/src/executor.rs | 110 +++++---- core-primitives/stf-executor/src/traits.rs | 8 +- core-primitives/stf-interface/src/lib.rs | 4 +- core-primitives/stf-interface/src/mocks.rs | 4 +- core-primitives/test/src/mock/onchain_mock.rs | 15 +- core-primitives/types/src/parentchain.rs | 13 + .../block-import-dispatcher/src/lib.rs | 3 - .../block-importer/src/block_importer.rs | 26 +- .../indirect-calls-executor/src/executor.rs | 4 + .../src/filter_metadata.rs | 109 ++++++++- .../src/indirect_calls/mod.rs | 2 + .../transfer_to_alice_shields_funds.rs | 89 +++++++ .../indirect-calls-executor/src/traits.rs | 2 + .../light-client/src/concurrent_access.rs | 9 + core/parentchain/light-client/src/io.rs | 32 ++- .../src/light_client_init_params.rs | 17 ++ .../light-client/src/light_validation.rs | 7 +- .../src/mocks/validator_access_mock.rs | 11 +- .../parentchain-crate/src/primitives.rs | 27 ++- enclave-runtime/Enclave.edl | 16 +- enclave-runtime/src/attestation.rs | 12 +- enclave-runtime/src/error.rs | 3 +- .../src/initialization/global_components.rs | 142 ++++++++--- enclave-runtime/src/initialization/mod.rs | 38 ++- .../src/initialization/parentchain/common.rs | 107 +++++++-- .../{parachain.rs => integritee_parachain.rs} | 62 ++--- .../parentchain/integritee_solochain.rs | 118 ++++++++++ .../src/initialization/parentchain/mod.rs | 78 +++++- .../parentchain/target_a_parachain.rs | 122 ++++++++++ .../{solochain.rs => target_a_solochain.rs} | 52 ++-- enclave-runtime/src/lib.rs | 222 +++++++++++++----- enclave-runtime/src/ocall/ffi.rs | 4 + enclave-runtime/src/ocall/on_chain_ocall.rs | 20 +- enclave-runtime/src/teeracle/mod.rs | 8 +- .../test/mocks/propose_to_import_call_mock.rs | 10 +- enclave-runtime/src/test/mod.rs | 1 - .../src/test/on_chain_ocall_tests.rs | 46 ---- enclave-runtime/src/test/tests_main.rs | 2 - enclave-runtime/src/tls_ra/tls_ra_client.rs | 6 +- enclave-runtime/src/tls_ra/tls_ra_server.rs | 6 +- enclave-runtime/src/utils.rs | 80 ++++--- local-setup/config/benchmark.json | 35 +-- local-setup/config/one-worker.json | 35 +-- local-setup/config/two-nodes-one-worker.json | 70 ++++++ local-setup/config/two-workers.json | 35 +-- local-setup/launch.py | 20 +- local-setup/py/worker.py | 1 + local-setup/tmux_logger_two_nodes.sh | 32 +++ service/src/cli.yml | 22 +- service/src/config.rs | 69 ++++-- service/src/main.rs | 186 +++++++++++---- service/src/ocall_bridge/bridge_api.rs | 16 +- service/src/ocall_bridge/component_factory.rs | 14 +- .../ocall_bridge/ffi/send_to_parentchain.rs | 17 +- .../src/ocall_bridge/ffi/worker_request.rs | 19 +- .../src/ocall_bridge/worker_on_chain_ocall.rs | 65 ++++- service/src/parentchain_handler.rs | 24 +- service/src/setup.rs | 16 +- service/src/tests/commons.rs | 2 + service/src/tests/mocks/enclave_api_mock.rs | 14 +- service/src/tests/parentchain_handler_test.rs | 6 +- sidechain/validateer-fetch/src/validateer.rs | 6 +- 80 files changed, 2170 insertions(+), 702 deletions(-) create mode 100755 cli/demo_shield_on_second_node_with_transfer_to_alice.sh create mode 100644 core-primitives/node-api/metadata/src/pallet_balances.rs create mode 100644 core/parentchain/indirect-calls-executor/src/indirect_calls/transfer_to_alice_shields_funds.rs rename enclave-runtime/src/initialization/parentchain/{parachain.rs => integritee_parachain.rs} (62%) create mode 100644 enclave-runtime/src/initialization/parentchain/integritee_solochain.rs create mode 100644 enclave-runtime/src/initialization/parentchain/target_a_parachain.rs rename enclave-runtime/src/initialization/parentchain/{solochain.rs => target_a_solochain.rs} (65%) delete mode 100644 enclave-runtime/src/test/on_chain_ocall_tests.rs create mode 100644 local-setup/config/two-nodes-one-worker.json create mode 100755 local-setup/tmux_logger_two_nodes.sh diff --git a/app-libs/stf/src/stf_sgx.rs b/app-libs/stf/src/stf_sgx.rs index 54dd3d96..e7871b47 100644 --- a/app-libs/stf/src/stf_sgx.rs +++ b/app-libs/stf/src/stf_sgx.rs @@ -31,7 +31,7 @@ use itp_stf_interface::{ }; use itp_stf_primitives::types::ShardIdentifier; use itp_storage::storage_value_key; -use itp_types::OpaqueCall; +use itp_types::{parentchain::ParentchainId, OpaqueCall}; use itp_utils::stringify::account_id_to_string; use log::*; use sp_runtime::traits::StaticLookup; @@ -114,9 +114,12 @@ where }); } - fn storage_hashes_to_update_on_block() -> Vec> { + fn storage_hashes_to_update_on_block(parentchain_id: &ParentchainId) -> Vec> { // Get all shards that are currently registered. - vec![shards_key_hash()] + match parentchain_id { + ParentchainId::Integritee => vec![shards_key_hash()], + ParentchainId::TargetA => vec![], + } } } diff --git a/cli/demo_direct_call.sh b/cli/demo_direct_call.sh index f96e59d5..0f6e4f2b 100755 --- a/cli/demo_direct_call.sh +++ b/cli/demo_direct_call.sh @@ -27,46 +27,49 @@ while getopts ":m:p:P:t:u:V:C:" opt; do TEST=$OPTARG ;; m) - READMRENCLAVE=$OPTARG + READ_MRENCLAVE=$OPTARG ;; p) - NPORT=$OPTARG + INTEGRITEE_RPC_PORT=$OPTARG ;; P) - WORKER1PORT=$OPTARG + WORKER_1_PORT=$OPTARG ;; u) - NODEURL=$OPTARG + INTEGRITEE_RPC_URL=$OPTARG ;; V) - WORKER1URL=$OPTARG + WORKER_1_URL=$OPTARG ;; C) CLIENT_BIN=$OPTARG ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 esac done # Using default port if none given as arguments. -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} -WORKER1PORT=${WORKER1PORT:-2000} -WORKER1URL=${WORKER1URL:-"wss://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/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" ${CLIENT_BIN} --version -echo "Using node uri ${NODEURL}:${NPORT}" -echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" echo "" AMOUNTSHIELD=50000000000 AMOUNTTRANSFER=40000000000 -CLIENT="${CLIENT_BIN} -p ${NPORT} -P ${WORKER1PORT} -u ${NODEURL} -U ${WORKER1URL}" +CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" read -r MRENCLAVE <<< "$($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }')" echo "" diff --git a/cli/demo_direct_call_2_workers.sh b/cli/demo_direct_call_2_workers.sh index bff2cdd0..5cd73b00 100755 --- a/cli/demo_direct_call_2_workers.sh +++ b/cli/demo_direct_call_2_workers.sh @@ -30,6 +30,9 @@ while getopts ":p:A:B:u:W:V:C:" opt; do C) CLIENT_BIN=$OPTARG ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 esac done diff --git a/cli/demo_indirect_invocation.sh b/cli/demo_indirect_invocation.sh index 009f8596..b1c42dfc 100755 --- a/cli/demo_indirect_invocation.sh +++ b/cli/demo_indirect_invocation.sh @@ -8,51 +8,54 @@ set -euo pipefail while getopts ":p:A:B:u:W:V:C:" opt; do case $opt in p) - NPORT=$OPTARG + INTEGRITEE_RPC_PORT=$OPTARG ;; A) - WORKER1PORT=$OPTARG + WORKER_1_PORT=$OPTARG ;; B) - WORKER2PORT=$OPTARG + WORKER_2_PORT=$OPTARG ;; u) - NODEURL=$OPTARG + INTEGRITEE_RPC_URL=$OPTARG ;; V) - WORKER1URL=$OPTARG + WORKER_1_URL=$OPTARG ;; W) - WORKER2URL=$OPTARG + WORKER_2_URL=$OPTARG ;; C) CLIENT_BIN=$OPTARG ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 esac done # Using default port if none given as arguments. -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} -WORKER1PORT=${WORKER1PORT:-2000} -WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} -WORKER2PORT=${WORKER2PORT:-3000} -WORKER2URL=${WORKER2URL:-"wss://127.0.0.1"} +WORKER_2_PORT=${WORKER_2_PORT:-3000} +WORKER_2_URL=${WORKER_2_URL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" ${CLIENT_BIN} --version -echo "Using node uri ${NODEURL}:${NPORT}" -echo "Using trusted-worker 1 uri ${WORKER1URL}:${WORKER1PORT}" -echo "Using trusted-worker 2 uri ${WORKER2URL}:${WORKER2PORT}" +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using trusted-worker 1 uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "Using trusted-worker 2 uri ${WORKER_2_URL}:${WORKER_2_PORT}" echo "" SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) -"${SCRIPT_DIR}"/demo_shielding_unshielding.sh -p "${NPORT}" -u "${NODEURL}" -V "${WORKER1URL}" -P "${WORKER1PORT}" -C "${CLIENT_BIN}" -t first -"${SCRIPT_DIR}"/demo_shielding_unshielding.sh -p "${NPORT}" -u "${NODEURL}" -V "${WORKER2URL}" -P "${WORKER2PORT}" -C "${CLIENT_BIN}" -t second +"${SCRIPT_DIR}"/demo_shielding_unshielding.sh -p "${INTEGRITEE_RPC_PORT}" -u "${INTEGRITEE_RPC_URL}" -V "${WORKER_1_URL}" -P "${WORKER_1_PORT}" -C "${CLIENT_BIN}" -t first +"${SCRIPT_DIR}"/demo_shielding_unshielding.sh -p "${INTEGRITEE_RPC_PORT}" -u "${INTEGRITEE_RPC_URL}" -V "${WORKER_2_URL}" -P "${WORKER_2_PORT}" -C "${CLIENT_BIN}" -t second exit 0 diff --git a/cli/demo_shield_on_second_node_with_transfer_to_alice.sh b/cli/demo_shield_on_second_node_with_transfer_to_alice.sh new file mode 100755 index 00000000..4ec7ac50 --- /dev/null +++ b/cli/demo_shield_on_second_node_with_transfer_to_alice.sh @@ -0,0 +1,149 @@ +#!/bin/bash +set -euo pipefail + +# Verifies that shielding from the Target A parentchain works by sending a transfer to //Alice + +while getopts ":m:p:A:B:u:W:V:x:y:C:" opt; do + case $opt in + p) + INTEGRITEE_RPC_PORT=$OPTARG + ;; + A) + WORKER_1_PORT=$OPTARG + ;; + B) + WORKER_2_PORT=$OPTARG + ;; + u) + INTEGRITEE_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + W) + WORKER_2_URL=$OPTARG + ;; + x) + TARGET_A_PARENTCHAIN_RPC_URL=$OPTARG + ;; + y) + TARGET_A_PARENTCHAIN_RPC_PORT=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} +TARGET_A_PARENTCHAIN_RPC_PORT=${TARGET_A_PARENTCHAIN_RPC_PORT:-9966} +TARGET_A_PARENTCHAIN_RPC_URL=${TARGET_A_PARENTCHAIN_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"} + +WORKER_2_PORT=${WORKER_2_PORT:-3000} +WORKER_2_URL=${WORKER_2_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using node 2 uri ${TARGET_A_PARENTCHAIN_RPC_URL}:${TARGET_A_PARENTCHAIN_RPC_PORT}" +echo "Using trusted-worker 1 uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "Using trusted-worker 2 uri ${WORKER_2_URL}:${WORKER_2_PORT}" +echo "" + +# the parentchain token is 12 decimal +UNIT=$(( 10 ** 12 )) + +# make these amounts greater than ED +AMOUNT_SHIELD=$(( 6 * UNIT )) +AMOUNT_TRANSFER=$(( 2 * UNIT )) +AMOUNT_UNSHIELD=$(( 1 * UNIT )) + +CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" +CLIENT2="${CLIENT_BIN} -p ${TARGET_A_PARENTCHAIN_RPC_PORT} -P ${WORKER_1_PORT} -u ${TARGET_A_PARENTCHAIN_RPC_URL} -U ${WORKER_1_URL}" + +# interval and max rounds to wait to check the given account balance in sidechain +WAIT_INTERVAL_SECONDS=10 +WAIT_ROUNDS=20 + +# Poll and assert the given account's state is equal to expected, +# with timeout WAIT_INTERVAL_SECONDS * WAIT_ROUNDS +# usage: +# wait_assert_state +# the `state-name` has to be the supported subcommand, e.g. `balance`, `nonce` +function wait_assert_state() +{ + for i in $(seq 1 $WAIT_ROUNDS); do + sleep $WAIT_INTERVAL_SECONDS + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if [ $state -eq "$4" ]; then + return + else + : + fi + done + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state" + exit 1 +} + +# Do a live query and assert the given account's state is equal to expected +# usage: +# assert_state +function assert_state() +{ + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if [ -z "$state" ]; then + echo "Query $2 $3 failed" + exit 1 + fi + + if [ $state -eq "$4" ]; then + return + fi + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state" + exit 1 +} + +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; } + +ALICETRUSTEDACCOUNT=//Alice +echo " Alice's trusted account (same as public account) = ${ALICETRUSTEDACCOUNT}" +echo "" + +# Assert the initial trusted balance of Alice incognito +TRUSTED_BALANCE_ALICE=1000000000000000 +wait_assert_state ${MRENCLAVE} ${ALICETRUSTEDACCOUNT} balance ${TRUSTED_BALANCE_ALICE} + + +echo "* Send ${AMOUNT_SHIELD} from //Alice to //Alice on L1, which should trigger the demo shield process" +${CLIENT2} transfer //Alice ${ALICETRUSTEDACCOUNT} ${AMOUNT_SHIELD} +echo "" + +echo "* Wait and assert Alice's incognito account balance, should be $(( TRUSTED_BALANCE_ALICE + AMOUNT_SHIELD ))" +wait_assert_state ${MRENCLAVE} ${ALICETRUSTEDACCOUNT} balance $(( TRUSTED_BALANCE_ALICE + AMOUNT_SHIELD )) +echo "✔ ok" + +echo "" +echo "-----------------------" +echo "✔ The test passed!" +echo "-----------------------" +echo "" diff --git a/cli/demo_shielding_unshielding.sh b/cli/demo_shielding_unshielding.sh index 18abc0cb..cb32046a 100755 --- a/cli/demo_shielding_unshielding.sh +++ b/cli/demo_shielding_unshielding.sh @@ -30,39 +30,42 @@ while getopts ":m:p:P:t:u:V:C:" opt; do TEST=$OPTARG ;; m) - READMRENCLAVE=$OPTARG + READ_MRENCLAVE=$OPTARG ;; p) - NPORT=$OPTARG + INTEGRITEE_RPC_PORT=$OPTARG ;; P) - WORKER1PORT=$OPTARG + WORKER_1_PORT=$OPTARG ;; u) - NODEURL=$OPTARG + INTEGRITEE_RPC_URL=$OPTARG ;; V) - WORKER1URL=$OPTARG + WORKER_1_URL=$OPTARG ;; C) CLIENT_BIN=$OPTARG ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 esac done # Using default port if none given as arguments. -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} -WORKER1PORT=${WORKER1PORT:-2000} -WORKER1URL=${WORKER1URL:-"wss://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/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" ${CLIENT_BIN} --version -echo "Using node uri ${NODEURL}:${NPORT}" -echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" echo "" # the parentchain token is 12 decimal @@ -73,7 +76,7 @@ AMOUNT_SHIELD=$(( 6 * UNIT )) AMOUNT_TRANSFER=$(( 2 * UNIT )) AMOUNT_UNSHIELD=$(( 1 * UNIT )) -CLIENT="${CLIENT_BIN} -p ${NPORT} -P ${WORKER1PORT} -u ${NODEURL} -U ${WORKER1URL}" +CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" # offchain-worker only suppports indirect calls CALLTYPE= @@ -131,7 +134,7 @@ echo "* Query on-chain enclave registry:" ${CLIENT} list-workers echo "" -if [ "$READMRENCLAVE" = "file" ] +if [ "$READ_MRENCLAVE" = "file" ] then read MRENCLAVE <<< $(cat ~/mrenclave.b58) echo "Reading MRENCLAVE from file: ${MRENCLAVE}" diff --git a/cli/demo_sidechain.sh b/cli/demo_sidechain.sh index f6b1f1b9..91aa4375 100755 --- a/cli/demo_sidechain.sh +++ b/cli/demo_sidechain.sh @@ -20,68 +20,68 @@ # # usage: # export RUST_LOG_LOG=integritee-cli=info,ita_stf=info -# demo_sidechain.sh -p -A -B -m file +# demo_sidechain.sh -p -A -B -m file # # TEST_BALANCE_RUN is either "first" or "second" # if -m file is set, the mrenclave will be read from file. while getopts ":m:p:A:B:t:u:W:V:C:" opt; do case $opt in - t) - TEST=$OPTARG - ;; m) - READMRENCLAVE=$OPTARG + READ_MRENCLAVE=$OPTARG ;; p) - NPORT=$OPTARG + INTEGRITEE_RPC_PORT=$OPTARG ;; A) - WORKER1PORT=$OPTARG + WORKER_1_PORT=$OPTARG ;; B) - WORKER2PORT=$OPTARG + WORKER_2_PORT=$OPTARG ;; u) - NODEURL=$OPTARG + INTEGRITEE_RPC_URL=$OPTARG ;; V) - WORKER1URL=$OPTARG + WORKER_1_URL=$OPTARG ;; W) - WORKER2URL=$OPTARG + WORKER_2_URL=$OPTARG ;; C) CLIENT_BIN=$OPTARG ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 esac done # Using default port if none given as arguments. -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} -WORKER1PORT=${WORKER1PORT:-2000} -WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} -WORKER2PORT=${WORKER2PORT:-3000} -WORKER2URL=${WORKER2URL:-"wss://127.0.0.1"} +WORKER_2_PORT=${WORKER_2_PORT:-3000} +WORKER_2_URL=${WORKER_2_URL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" ${CLIENT_BIN} --version -echo "Using node uri ${NODEURL}:${NPORT}" -echo "Using trusted-worker 1 uri ${WORKER1URL}:${WORKER1PORT}" -echo "Using trusted-worker 2 uri ${WORKER2URL}:${WORKER2PORT}" +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using trusted-worker 1 uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "Using trusted-worker 2 uri ${WORKER_2_URL}:${WORKER_2_PORT}" INITIALFUNDS=50000000000 AMOUNTTRANSFER=20000000000 -CLIENTWORKER1="${CLIENT_BIN} -p ${NPORT} -P ${WORKER1PORT} -u ${NODEURL} -U ${WORKER1URL}" -CLIENTWORKER2="${CLIENT_BIN} -p ${NPORT} -P ${WORKER2PORT} -u ${NODEURL} -U ${WORKER2URL}" +CLIENTWORKER1="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" +CLIENTWORKER2="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_2_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_2_URL}" -if [ "$READMRENCLAVE" = "file" ] +if [ "$READ_MRENCLAVE" = "file" ] then read MRENCLAVE <<< $(cat ~/mrenclave.b58) echo "Reading MRENCLAVE from file: ${MRENCLAVE}" diff --git a/cli/demo_smart_contract.sh b/cli/demo_smart_contract.sh index 1c3ceb4c..e41729c1 100755 --- a/cli/demo_smart_contract.sh +++ b/cli/demo_smart_contract.sh @@ -13,25 +13,28 @@ # usage: # export RUST_LOG_LOG=integritee-cli=info,ita_stf=info -# demo_smart_contract.sh -p -P +# demo_smart_contract.sh -p -P while getopts ":p:A:u:V:C:" opt; do case $opt in p) - NPORT=$OPTARG + INTEGRITEE_RPC_PORT=$OPTARG ;; A) - WORKERPORT=$OPTARG + WORKER_PORT=$OPTARG ;; u) - NODEURL=$OPTARG + INTEGRITEE_RPC_URL=$OPTARG ;; V) - WORKERURL=$OPTARG + WORKER_URL=$OPTARG ;; C) CLIENT_BIN=$OPTARG ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 esac done @@ -43,21 +46,21 @@ ADDFUNCTION="1003e2d200000000000000000000000000000000000000000000000000000000000 # using default port if none given as arguments -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} -WORKERPORT=${WORKERPORT:-2000} -WORKERURL=${WORKERURL:-"wss://127.0.0.1"} +WORKER_PORT=${WORKER_PORT:-2000} +WORKER_URL=${WORKER_URL:-"wss://127.0.0.1"} CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" ${CLIENT_BIN} --version -echo "Using node uri ${NODEURL}:${NPORT}" -echo "Using trusted-worker uri ${WORKERURL}:${WORKERPORT}" +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_URL}:${WORKER_PORT}" -CLIENTWORKER="${CLIENT_BIN} -p ${NPORT} -P ${WORKERPORT} -u ${NODEURL} -U ${WORKERURL}" +CLIENTWORKER="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_URL}" # this will always take the first MRENCLAVE found in the registry !! diff --git a/cli/demo_teeracle_generic.sh b/cli/demo_teeracle_generic.sh index 99caf605..9e97ad2a 100755 --- a/cli/demo_teeracle_generic.sh +++ b/cli/demo_teeracle_generic.sh @@ -28,10 +28,10 @@ trap "echo The demo is terminated (SIGTERM); exit 1" SIGTERM while getopts ":p:P:d:i:u:V:C:" opt; do case $opt in p) - NPORT=$OPTARG + INTEGRITEE_RPC_PORT=$OPTARG ;; P) - WORKER1PORT=$OPTARG + WORKER_1_PORT=$OPTARG ;; d) DURATION=$OPTARG @@ -40,23 +40,26 @@ while getopts ":p:P:d:i:u:V:C:" opt; do INTERVAL=$OPTARG ;; u) - NODEURL=$OPTARG + INTEGRITEE_RPC_URL=$OPTARG ;; V) - WORKER1URL=$OPTARG + WORKER_1_URL=$OPTARG ;; C) CLIENT_BIN=$OPTARG ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 esac done # using default port if none given as arguments -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} -WORKER1PORT=${WORKER1PORT:-2000} -WORKER1URL=${WORKER1URL:-"wss://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/integritee-cli"} @@ -68,8 +71,8 @@ ADD_TO_WHITELIST_CMD="oracle add-to-whitelist" echo "Using client binary ${CLIENT_BIN}" ${CLIENT_BIN} --version -echo "Using node uri ${NODEURL}:${NPORT}" -echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_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 "" @@ -81,7 +84,7 @@ echo "Minimum expected number of events with a single oracle source: ${MIN_EXPEC # 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 ${NPORT} -P ${WORKER1PORT} -u ${NODEURL} -U ${WORKER1URL}" +CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" echo "* Query on-chain enclave registry:" ${CLIENT} list-workers diff --git a/cli/demo_teeracle_whitelist.sh b/cli/demo_teeracle_whitelist.sh index ba64ee8f..895c55cb 100755 --- a/cli/demo_teeracle_whitelist.sh +++ b/cli/demo_teeracle_whitelist.sh @@ -28,10 +28,10 @@ trap "echo The demo is terminated (SIGTERM); exit 1" SIGTERM while getopts ":p:P:d:i:u:V:C:" opt; do case $opt in p) - NPORT=$OPTARG + INTEGRITEE_RPC_PORT=$OPTARG ;; P) - WORKER1PORT=$OPTARG + WORKER_1_PORT=$OPTARG ;; d) DURATION=$OPTARG @@ -40,23 +40,26 @@ while getopts ":p:P:d:i:u:V:C:" opt; do INTERVAL=$OPTARG ;; u) - NODEURL=$OPTARG + INTEGRITEE_RPC_URL=$OPTARG ;; V) - WORKER1URL=$OPTARG + WORKER_1_URL=$OPTARG ;; C) CLIENT_BIN=$OPTARG ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 esac done # using default port if none given as arguments -NPORT=${NPORT:-9944} -NODEURL=${NODEURL:-"ws://127.0.0.1"} +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} -WORKER1PORT=${WORKER1PORT:-2000} -WORKER1URL=${WORKER1URL:-"wss://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/integritee-cli"} @@ -68,8 +71,8 @@ ADD_TO_WHITELIST_CMD="oracle add-to-whitelist" echo "Using client binary ${CLIENT_BIN}" ${CLIENT_BIN} --version -echo "Using node uri ${NODEURL}:${NPORT}" -echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_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 "" @@ -82,7 +85,7 @@ echo "Minimum expected number of events with a single oracle source: ${MIN_EXPEC 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 ${NPORT} -P ${WORKER1PORT} -u ${NODEURL} -U ${WORKER1URL}" +CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" echo "* Query on-chain enclave registry:" ${CLIENT} list-workers diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index 9bb8920b..cbdfcd09 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -60,6 +60,8 @@ extern "C" { pub fn trigger_parentchain_block_import( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, + parentchain_id: *const u8, + 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; @@ -73,13 +75,16 @@ extern "C" { events_size: usize, events_proofs: *const u8, events_proofs_size: usize, - nonce: *const u32, + parentchain_id: *const u8, + parentchain_id_size: u32, ) -> sgx_status_t; pub fn set_nonce( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, nonce: *const u32, + parentchain_id: *const u8, + parentchain_id_size: u32, ) -> sgx_status_t; pub fn set_node_metadata( @@ -87,6 +92,8 @@ extern "C" { retval: *mut sgx_status_t, node_metadata: *const u8, node_metadata_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, ) -> sgx_status_t; pub fn get_rsa_encryption_pubkey( diff --git a/core-primitives/enclave-api/src/enclave_base.rs b/core-primitives/enclave-api/src/enclave_base.rs index 86ffceae..def5d3ee 100644 --- a/core-primitives/enclave-api/src/enclave_base.rs +++ b/core-primitives/enclave-api/src/enclave_base.rs @@ -20,7 +20,7 @@ use crate::{error::Error, Enclave, EnclaveResult}; use codec::{Decode, Encode}; use core::fmt::Debug; use frame_support::ensure; -use itc_parentchain::primitives::ParentchainInitParams; +use itc_parentchain::primitives::{ParentchainId, ParentchainInitParams}; use itp_enclave_api_ffi as ffi; use itp_settings::worker::{ HEADER_MAX_SIZE, MR_ENCLAVE_SIZE, SHIELDING_KEY_SIZE, SIGNING_KEY_SIZE, @@ -58,11 +58,16 @@ pub trait EnclaveBase: Send + Sync + 'static { /// Trigger the import of parentchain block explicitly. Used when initializing a light-client /// with a triggered import dispatcher. - fn trigger_parentchain_block_import(&self) -> EnclaveResult<()>; + fn trigger_parentchain_block_import(&self, parentchain_id: &ParentchainId) + -> EnclaveResult<()>; - fn set_nonce(&self, nonce: u32) -> EnclaveResult<()>; + fn set_nonce(&self, nonce: u32, parentchain_id: ParentchainId) -> EnclaveResult<()>; - fn set_node_metadata(&self, metadata: Vec) -> EnclaveResult<()>; + fn set_node_metadata( + &self, + metadata: Vec, + parentchain_id: ParentchainId, + ) -> EnclaveResult<()>; fn get_rsa_shielding_pubkey(&self) -> EnclaveResult; @@ -159,10 +164,21 @@ impl EnclaveBase for Enclave { Ok(()) } - fn trigger_parentchain_block_import(&self) -> EnclaveResult<()> { + fn trigger_parentchain_block_import( + &self, + parentchain_id: &ParentchainId, + ) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; + let parentchain_id_enc = parentchain_id.encode(); - let result = unsafe { ffi::trigger_parentchain_block_import(self.eid, &mut retval) }; + let result = unsafe { + ffi::trigger_parentchain_block_import( + self.eid, + &mut retval, + parentchain_id_enc.as_ptr(), + parentchain_id_enc.len() as u32, + ) + }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); @@ -170,10 +186,20 @@ impl EnclaveBase for Enclave { Ok(()) } - fn set_nonce(&self, nonce: u32) -> EnclaveResult<()> { + fn set_nonce(&self, nonce: u32, parentchain_id: ParentchainId) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; - let result = unsafe { ffi::set_nonce(self.eid, &mut retval, &nonce) }; + let parentchain_id_enc = parentchain_id.encode(); + + let result = unsafe { + ffi::set_nonce( + self.eid, + &mut retval, + &nonce, + parentchain_id_enc.as_ptr(), + parentchain_id_enc.len() as u32, + ) + }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); @@ -181,11 +207,24 @@ impl EnclaveBase for Enclave { Ok(()) } - fn set_node_metadata(&self, metadata: Vec) -> EnclaveResult<()> { + fn set_node_metadata( + &self, + metadata: Vec, + parentchain_id: ParentchainId, + ) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; + let parentchain_id_enc = parentchain_id.encode(); + let result = unsafe { - ffi::set_node_metadata(self.eid, &mut retval, metadata.as_ptr(), metadata.len() as u32) + ffi::set_node_metadata( + self.eid, + &mut retval, + metadata.as_ptr(), + metadata.len() as u32, + parentchain_id_enc.as_ptr(), + parentchain_id_enc.len() as u32, + ) }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); diff --git a/core-primitives/enclave-api/src/sidechain.rs b/core-primitives/enclave-api/src/sidechain.rs index 196852c3..572b6717 100644 --- a/core-primitives/enclave-api/src/sidechain.rs +++ b/core-primitives/enclave-api/src/sidechain.rs @@ -21,6 +21,7 @@ use codec::Encode; use frame_support::ensure; use itp_enclave_api_ffi as ffi; use itp_storage::StorageProof; +use itp_types::parentchain::ParentchainId; use sgx_types::sgx_status_t; use sp_runtime::{generic::SignedBlock, traits::Block as ParentchainBlockTrait}; @@ -33,7 +34,7 @@ pub trait Sidechain: Send + Sync + 'static { blocks: &[SignedBlock], events: &[Vec], events_proofs: &[StorageProof], - nonce: u32, + parentchain_id: &ParentchainId, ) -> EnclaveResult<()>; fn execute_trusted_calls(&self) -> EnclaveResult<()>; @@ -45,12 +46,13 @@ impl Sidechain for Enclave { blocks: &[SignedBlock], events: &[Vec], events_proofs: &[StorageProof], - nonce: u32, + parentchain_id: &ParentchainId, ) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; let blocks_enc = blocks.encode(); let events_enc = events.encode(); let events_proofs_enc = events_proofs.encode(); + let parentchain_id_enc = parentchain_id.encode(); let result = unsafe { ffi::sync_parentchain( @@ -62,7 +64,8 @@ impl Sidechain for Enclave { events_enc.len(), events_proofs_enc.as_ptr(), events_proofs_enc.len(), - &nonce, + parentchain_id_enc.as_ptr(), + parentchain_id_enc.len() as u32, ) }; diff --git a/core-primitives/node-api/metadata/src/lib.rs b/core-primitives/node-api/metadata/src/lib.rs index 9bb09a21..c290c2ab 100644 --- a/core-primitives/node-api/metadata/src/lib.rs +++ b/core-primitives/node-api/metadata/src/lib.rs @@ -30,6 +30,7 @@ pub use crate::error::Error; pub use itp_api_client_types::{Metadata, MetadataError}; pub mod error; +pub mod pallet_balances; pub mod pallet_enclave_bridge; pub mod pallet_sidechain; pub mod pallet_teeracle; diff --git a/core-primitives/node-api/metadata/src/pallet_balances.rs b/core-primitives/node-api/metadata/src/pallet_balances.rs new file mode 100644 index 00000000..185f0eff --- /dev/null +++ b/core-primitives/node-api/metadata/src/pallet_balances.rs @@ -0,0 +1,37 @@ +/* + 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: +const BALANCES: &str = "Balances"; + +pub trait BalancesCallIndexes { + fn transfer_call_index(&self) -> Result<[u8; 2]>; + + fn transfer_allow_death_call_index(&self) -> Result<[u8; 2]>; +} + +impl BalancesCallIndexes for NodeMetadata { + fn transfer_call_index(&self) -> Result<[u8; 2]> { + self.call_indexes(BALANCES, "transfer") + } + + fn transfer_allow_death_call_index(&self) -> Result<[u8; 2]> { + self.call_indexes(BALANCES, "transfer_allow_death") + } +} diff --git a/core-primitives/nonce-cache/src/lib.rs b/core-primitives/nonce-cache/src/lib.rs index e28061cf..a1e515ac 100644 --- a/core-primitives/nonce-cache/src/lib.rs +++ b/core-primitives/nonce-cache/src/lib.rs @@ -36,18 +36,9 @@ use std::sync::RwLockWriteGuard; use std::sync::SgxRwLockWriteGuard as RwLockWriteGuard; use crate::error::Result; -use lazy_static::lazy_static; -use std::sync::Arc; pub use nonce_cache::NonceCache; -lazy_static! { - /// Global instance of a nonce cache - /// - /// Concurrent access is managed internally, using RW locks - pub static ref GLOBAL_NONCE_CACHE: Arc = Default::default(); -} - pub mod error; pub mod nonce_cache; diff --git a/core-primitives/ocall-api/src/lib.rs b/core-primitives/ocall-api/src/lib.rs index c47bbfd9..2bd1ca21 100644 --- a/core-primitives/ocall-api/src/lib.rs +++ b/core-primitives/ocall-api/src/lib.rs @@ -25,8 +25,8 @@ use core::result::Result as StdResult; use derive_more::{Display, From}; use itp_storage::Error as StorageError; use itp_types::{ - storage::StorageEntryVerified, BlockHash, ShardIdentifier, TrustedOperationStatus, - WorkerRequest, WorkerResponse, + parentchain::ParentchainId, storage::StorageEntryVerified, BlockHash, ShardIdentifier, + TrustedOperationStatus, WorkerRequest, WorkerResponse, }; use sgx_types::*; use sp_core::H256; @@ -89,23 +89,30 @@ pub trait EnclaveRpcOCallApi: Clone + Send + Sync + Default { /// trait for o-calls related to on-chain interactions pub trait EnclaveOnChainOCallApi: Clone + Send + Sync { - fn send_to_parentchain(&self, extrinsics: Vec) -> SgxResult<()>; + fn send_to_parentchain( + &self, + extrinsics: Vec, + parentchain_id: &ParentchainId, + ) -> SgxResult<()>; fn worker_request( &self, req: Vec, + parentchain_id: &ParentchainId, ) -> SgxResult>>; fn get_storage_verified, V: Decode>( &self, storage_hash: Vec, header: &H, + parentchain_id: &ParentchainId, ) -> Result>; fn get_multiple_storages_verified, V: Decode>( &self, storage_hashes: Vec>, header: &H, + parentchain_id: &ParentchainId, ) -> Result>>; } diff --git a/core-primitives/settings/src/lib.rs b/core-primitives/settings/src/lib.rs index aa70e4b7..0567e88b 100644 --- a/core-primitives/settings/src/lib.rs +++ b/core-primitives/settings/src/lib.rs @@ -42,8 +42,11 @@ pub mod files { pub static SIDECHAIN_PURGE_LIMIT: u64 = 100; // keep the last.. sidechainblocks when purging // used by enclave - /// Path to the light-client db. - pub const LIGHT_CLIENT_DB_PATH: &str = "light_client_db"; + /// Path to the light-client db for the Integritee parentchain. + pub const INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "integritee_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"; pub const RA_DUMP_CERT_DER_FILE: &str = "ra_dump_cert.der"; diff --git a/core-primitives/stf-executor/src/executor.rs b/core-primitives/stf-executor/src/executor.rs index 161bd582..3c5f53af 100644 --- a/core-primitives/stf-executor/src/executor.rs +++ b/core-primitives/stf-executor/src/executor.rs @@ -30,12 +30,12 @@ use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; use itp_ocall_api::{EnclaveAttestationOCallApi, EnclaveOnChainOCallApi}; use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; use itp_stf_interface::{ - parentchain_pallet::ParentchainPalletInterface, ExecuteCall, StateCallInterface, UpdateState, + parentchain_pallet::ParentchainPalletInterface, StateCallInterface, UpdateState, }; use itp_stf_primitives::types::ShardIdentifier; use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; use itp_time_utils::duration_now; -use itp_types::{storage::StorageEntryVerified, OpaqueCall, H256}; +use itp_types::{parentchain::ParentchainId, storage::StorageEntryVerified, OpaqueCall, H256}; use log::*; use sp_runtime::traits::Header as HeaderTrait; use std::{ @@ -83,7 +83,7 @@ where &self, state: &mut StateHandler::StateT, trusted_operation: &TrustedOperation, - header: &PH, + _header: &PH, shard: &ShardIdentifier, post_processing: StatePostProcessing, ) -> Result @@ -108,19 +108,6 @@ where return Ok(ExecutedOperation::failed(top_or_hash)) } - // Necessary because light client sync may not be up to date - // see issue #208 - debug!("Update STF storage!"); - - let storage_hashes = >::get_storage_hashes_to_update(trusted_call.clone()); - let update_map = self - .ocall_api - .get_multiple_storages_verified(storage_hashes, header) - .map(into_map)?; - - debug!("Apply state diff with {} entries from parentchain block", update_map.len()); - Stf::apply_state_diff(state, update_map.into()); - debug!("execute on STF, call with nonce {}", trusted_call.nonce); let mut extrinsic_call_backs: Vec = Vec::new(); if let Err(e) = Stf::execute_call( @@ -161,9 +148,13 @@ where ::SgxExternalitiesDiffType: From, Option>>>, { - fn update_states(&self, header: &ParentchainHeader) -> Result<()> { + fn update_states( + &self, + header: &ParentchainHeader, + parentchain_id: &ParentchainId, + ) -> Result<()> { debug!("Update STF storage upon block import!"); - let storage_hashes = Stf::storage_hashes_to_update_on_block(); + let storage_hashes = Stf::storage_hashes_to_update_on_block(parentchain_id); if storage_hashes.is_empty() { return Ok(()) @@ -172,7 +163,7 @@ where // global requests they are the same for every shard let state_diff_update = self .ocall_api - .get_multiple_storages_verified(storage_hashes, header) + .get_multiple_storages_verified(storage_hashes, header, parentchain_id) .map(into_map)?; // Update parentchain block on all states. @@ -189,33 +180,15 @@ where } } + if parentchain_id != &ParentchainId::Integritee { + // nothing else to do + return Ok(()) + } + // look for new shards an initialize them if let Some(maybe_shards) = state_diff_update.get(&shards_key_hash()) { match maybe_shards { - Some(shards) => { - let shards: Vec = Decode::decode(&mut shards.as_slice())?; - - for shard_id in shards { - let (state_lock, mut state) = - self.state_handler.load_for_mutation(&shard_id)?; - trace!("Successfully loaded state, updating states ..."); - - // per shard (cid) requests - let per_shard_hashes = storage_hashes_to_update_per_shard(&shard_id); - let per_shard_update = self - .ocall_api - .get_multiple_storages_verified(per_shard_hashes, header) - .map(into_map)?; - - Stf::apply_state_diff(&mut state, per_shard_update.into()); - Stf::apply_state_diff(&mut state, state_diff_update.clone().into()); - if let Err(e) = Stf::update_parentchain_block(&mut state, header.clone()) { - error!("Could not update parentchain block. {:?}: {:?}", shard_id, e) - } - - self.state_handler.write_after_mutation(state, state_lock, &shard_id)?; - } - }, + Some(shards) => self.initialize_new_shards(header, &state_diff_update, &shards)?, None => debug!("No shards are on the chain yet"), }; }; @@ -223,6 +196,57 @@ where } } +impl + StfExecutor +where + ::SgxExternalitiesDiffType: + From, Option>>> + IntoIterator, Option>)>, + >::Error: Debug, + NodeMetadataRepository: AccessNodeMetadata, + OCallApi: EnclaveAttestationOCallApi + EnclaveOnChainOCallApi, + StateHandler: HandleState + QueryShardState, + StateHandler::StateT: Encode + SgxExternalitiesTrait, + Stf: ParentchainPalletInterface + + UpdateState< + StateHandler::StateT, + ::SgxExternalitiesDiffType, + >, +{ + fn initialize_new_shards( + &self, + header: &ParentchainHeader, + state_diff_update: &BTreeMap, Option>>, + shards: &Vec, + ) -> Result<()> { + let shards: Vec = Decode::decode(&mut shards.as_slice())?; + + for shard_id in shards { + let (state_lock, mut state) = self.state_handler.load_for_mutation(&shard_id)?; + trace!("Successfully loaded state, updating states ..."); + + // per shard (cid) requests + let per_shard_hashes = storage_hashes_to_update_per_shard(&shard_id); + let per_shard_update = self + .ocall_api + .get_multiple_storages_verified( + per_shard_hashes, + header, + &ParentchainId::Integritee, + ) + .map(into_map)?; + + Stf::apply_state_diff(&mut state, per_shard_update.into()); + Stf::apply_state_diff(&mut state, state_diff_update.clone().into()); + if let Err(e) = Stf::update_parentchain_block(&mut state, header.clone()) { + error!("Could not update parentchain block. {:?}: {:?}", shard_id, e) + } + + self.state_handler.write_after_mutation(state, state_lock, &shard_id)?; + } + Ok(()) + } +} + impl StateUpdateProposer for StfExecutor where diff --git a/core-primitives/stf-executor/src/traits.rs b/core-primitives/stf-executor/src/traits.rs index af9d88ba..f2af1c75 100644 --- a/core-primitives/stf-executor/src/traits.rs +++ b/core-primitives/stf-executor/src/traits.rs @@ -20,7 +20,7 @@ use codec::Encode; use ita_stf::{ParentchainHeader, TrustedCall, TrustedCallSigned, TrustedOperation}; use itp_sgx_externalities::SgxExternalitiesTrait; use itp_stf_primitives::types::{AccountId, ShardIdentifier}; -use itp_types::H256; +use itp_types::{parentchain::ParentchainId, H256}; use sp_runtime::traits::Header as HeaderTrait; use std::time::Duration; @@ -68,5 +68,9 @@ pub trait StateUpdateProposer { /// /// Cannot be implemented for a generic header currently, because the runtime expects a ParentchainHeader. pub trait StfUpdateState { - fn update_states(&self, header: &ParentchainHeader) -> Result<()>; + fn update_states( + &self, + header: &ParentchainHeader, + parentchain_id: &ParentchainId, + ) -> Result<()>; } diff --git a/core-primitives/stf-interface/src/lib.rs b/core-primitives/stf-interface/src/lib.rs index 41378346..66ae7749 100644 --- a/core-primitives/stf-interface/src/lib.rs +++ b/core-primitives/stf-interface/src/lib.rs @@ -25,7 +25,7 @@ extern crate alloc; use alloc::{sync::Arc, vec::Vec}; use itp_node_api_metadata::NodeMetadataTrait; use itp_node_api_metadata_provider::AccessNodeMetadata; -use itp_types::OpaqueCall; +use itp_types::{parentchain::ParentchainId, OpaqueCall}; #[cfg(feature = "mocks")] pub mod mocks; @@ -44,7 +44,7 @@ pub trait InitState { pub trait UpdateState { /// Updates a given state for fn apply_state_diff(state: &mut State, state_diff: StateDiff); - fn storage_hashes_to_update_on_block() -> Vec>; + fn storage_hashes_to_update_on_block(parentchain_id: &ParentchainId) -> Vec>; } /// Interface to execute state mutating calls on a state. diff --git a/core-primitives/stf-interface/src/mocks.rs b/core-primitives/stf-interface/src/mocks.rs index 83f90d2f..c4c314cc 100644 --- a/core-primitives/stf-interface/src/mocks.rs +++ b/core-primitives/stf-interface/src/mocks.rs @@ -26,7 +26,7 @@ use alloc::{string::String, sync::Arc, vec::Vec}; use core::marker::PhantomData; use itp_node_api_metadata::metadata_mocks::NodeMetadataMock; use itp_node_api_metadata_provider::NodeMetadataRepository; -use itp_types::{AccountId, Index, OpaqueCall}; +use itp_types::{parentchain::ParentchainId, AccountId, Index, OpaqueCall}; #[derive(Default)] pub struct StateInterfaceMock { @@ -46,7 +46,7 @@ impl UpdateState for StateInterfaceMock Vec> { + fn storage_hashes_to_update_on_block(_: &ParentchainId) -> Vec> { unimplemented!() } } diff --git a/core-primitives/test/src/mock/onchain_mock.rs b/core-primitives/test/src/mock/onchain_mock.rs index 8a96dde1..1ed4efdc 100644 --- a/core-primitives/test/src/mock/onchain_mock.rs +++ b/core-primitives/test/src/mock/onchain_mock.rs @@ -25,8 +25,8 @@ use itp_ocall_api::{ }; use itp_storage::Error::StorageValueUnavailable; use itp_types::{ - storage::StorageEntryVerified, AccountId, BlockHash, EnclaveFingerprint, ShardIdentifier, - ShardSignerStatus, WorkerRequest, WorkerResponse, + parentchain::ParentchainId, storage::StorageEntryVerified, AccountId, BlockHash, + EnclaveFingerprint, ShardIdentifier, ShardSignerStatus, WorkerRequest, WorkerResponse, }; use sgx_types::*; use sp_core::H256; @@ -176,13 +176,18 @@ impl EnclaveMetricsOCallApi for OnchainMock { } impl EnclaveOnChainOCallApi for OnchainMock { - fn send_to_parentchain(&self, _extrinsics: Vec) -> SgxResult<()> { + fn send_to_parentchain( + &self, + _extrinsics: Vec, + _: &ParentchainId, + ) -> SgxResult<()> { Ok(()) } fn worker_request( &self, _req: Vec, + _: &ParentchainId, ) -> SgxResult>> { Ok(Vec::new()) } @@ -191,8 +196,9 @@ impl EnclaveOnChainOCallApi for OnchainMock { &self, storage_hash: Vec, header: &Header, + parentchain_id: &ParentchainId, ) -> Result, itp_ocall_api::Error> { - self.get_multiple_storages_verified(vec![storage_hash], header)? + self.get_multiple_storages_verified(vec![storage_hash], header, parentchain_id)? .into_iter() .next() .ok_or_else(|| itp_ocall_api::Error::Storage(StorageValueUnavailable)) @@ -202,6 +208,7 @@ impl EnclaveOnChainOCallApi for OnchainMock { &self, storage_hashes: Vec>, header: &Header, + _: &ParentchainId, ) -> Result>, itp_ocall_api::Error> { let mut entries = Vec::with_capacity(storage_hashes.len()); for hash in storage_hashes.into_iter() { diff --git a/core-primitives/types/src/parentchain.rs b/core-primitives/types/src/parentchain.rs index c8d57df8..1d674833 100644 --- a/core-primitives/types/src/parentchain.rs +++ b/core-primitives/types/src/parentchain.rs @@ -17,6 +17,7 @@ //! Parentchain specific params. Be sure to change them if your node uses different types. +use codec::{Decode, Encode}; use sp_runtime::{generic::Header as HeaderG, traits::BlakeTwo256, MultiAddress, MultiSignature}; use sp_std::vec::Vec; @@ -40,3 +41,15 @@ pub type BlockHash = sp_core::H256; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = MultiSignature; + +#[derive(Encode, Decode, Copy, Clone, Debug, PartialEq, Eq)] +pub enum ParentchainId { + /// The Integritee Parentchain, the trust root of the enclave and serving finality to sidechains. + Integritee, + /// A target chain containing custom business logics. + TargetA, +} + +pub trait IdentifyParentchain { + fn parentchain_id(&self) -> ParentchainId; +} diff --git a/core/parentchain/block-import-dispatcher/src/lib.rs b/core/parentchain/block-import-dispatcher/src/lib.rs index 7cb98316..fc4a0001 100644 --- a/core/parentchain/block-import-dispatcher/src/lib.rs +++ b/core/parentchain/block-import-dispatcher/src/lib.rs @@ -37,7 +37,6 @@ pub mod triggered_dispatcher; #[cfg(feature = "mocks")] pub mod trigger_parentchain_block_import_mock; -use crate::triggered_dispatcher::TriggerParentchainBlockImport; use error::{Error, Result}; use std::{sync::Arc, vec::Vec}; @@ -61,8 +60,6 @@ pub enum BlockImportDispatcher { impl BlockImportDispatcher -where - TriggeredDispatcher: TriggerParentchainBlockImport, { pub fn new_triggered_dispatcher(triggered_dispatcher: Arc) -> Self { BlockImportDispatcher::TriggeredDispatcher(triggered_dispatcher) diff --git a/core/parentchain/block-importer/src/block_importer.rs b/core/parentchain/block-importer/src/block_importer.rs index 0074ee3a..b83749d2 100644 --- a/core/parentchain/block-importer/src/block_importer.rs +++ b/core/parentchain/block-importer/src/block_importer.rs @@ -25,7 +25,7 @@ use itc_parentchain_light_client::{ }; use itp_extrinsics_factory::CreateExtrinsics; use itp_stf_executor::traits::StfUpdateState; -use itp_types::{OpaqueCall, H256}; +use itp_types::{parentchain::IdentifyParentchain, OpaqueCall, H256}; use log::*; use sp_runtime::{ generic::SignedBlock as SignedBlockG, @@ -40,14 +40,7 @@ pub struct ParentchainBlockImporter< StfExecutor, ExtrinsicsFactory, IndirectCallsExecutor, -> where - ParentchainBlock: ParentchainBlockTrait, - NumberFor: BlockNumberOps, - ValidatorAccessor: ValidatorAccess, - StfExecutor: StfUpdateState, - ExtrinsicsFactory: CreateExtrinsics, - IndirectCallsExecutor: ExecuteIndirectCalls, -{ +> { validator_accessor: Arc, stf_executor: Arc, extrinsics_factory: Arc, @@ -68,13 +61,7 @@ impl< StfExecutor, ExtrinsicsFactory, IndirectCallsExecutor, - > where - ParentchainBlock: ParentchainBlockTrait, - NumberFor: BlockNumberOps, - ValidatorAccessor: ValidatorAccess, - StfExecutor: StfUpdateState, - ExtrinsicsFactory: CreateExtrinsics, - IndirectCallsExecutor: ExecuteIndirectCalls, + > { pub fn new( validator_accessor: Arc, @@ -108,7 +95,7 @@ impl< > where ParentchainBlock: ParentchainBlockTrait, NumberFor: BlockNumberOps, - ValidatorAccessor: ValidatorAccess, + ValidatorAccessor: ValidatorAccess + IdentifyParentchain, StfExecutor: StfUpdateState, ExtrinsicsFactory: CreateExtrinsics, IndirectCallsExecutor: ExecuteIndirectCalls, @@ -139,7 +126,10 @@ impl< let block = signed_block.block; // Perform state updates. - if let Err(e) = self.stf_executor.update_states(block.header()) { + if let Err(e) = self + .stf_executor + .update_states(block.header(), &self.validator_accessor.parentchain_id()) + { error!("Error performing state updates upon block import"); return Err(e.into()) } diff --git a/core/parentchain/indirect-calls-executor/src/executor.rs b/core/parentchain/indirect-calls-executor/src/executor.rs index 55231dff..423f7323 100644 --- a/core/parentchain/indirect-calls-executor/src/executor.rs +++ b/core/parentchain/indirect-calls-executor/src/executor.rs @@ -251,6 +251,10 @@ impl< Ok(self.stf_enclave_signer.get_enclave_account()?) } + fn get_default_shard(&self) -> ShardIdentifier { + self.top_pool_author.list_handled_shards().first().copied().unwrap_or_default() + } + fn sign_call_with_self( &self, trusted_call: &TrustedCall, diff --git a/core/parentchain/indirect-calls-executor/src/filter_metadata.rs b/core/parentchain/indirect-calls-executor/src/filter_metadata.rs index 0a919f53..b77805d1 100644 --- a/core/parentchain/indirect-calls-executor/src/filter_metadata.rs +++ b/core/parentchain/indirect-calls-executor/src/filter_metadata.rs @@ -18,14 +18,18 @@ use crate::{ error::Result, event_filter::{FilterEvents, MockEvents}, - indirect_calls::{InvokeArgs, ShieldFundsArgs}, + indirect_calls::{ + InvokeArgs, ShieldFundsArgs, TransferToAliceShieldsFundsArgs, ALICE_ACCOUNT_ID, + }, parentchain_parser::ParseExtrinsic, IndirectDispatch, IndirectExecutor, }; use codec::{Decode, Encode}; use core::marker::PhantomData; use itp_api_client_types::{Events, Metadata}; -use itp_node_api::metadata::{NodeMetadata, NodeMetadataTrait}; +use itp_node_api::metadata::{ + pallet_balances::BalancesCallIndexes, NodeMetadata, NodeMetadataTrait, +}; use itp_types::H256; pub trait EventsFromMetadata { @@ -86,15 +90,13 @@ pub trait FilterIntoDataFrom { /// Indirect calls filter denying all indirect calls. pub struct DenyAll; -impl FilterIntoDataFrom for DenyAll { - type Output = (); - type ParseParentchainMetadata = (); - - fn filter_into_from_metadata(_: &[u8], _: &NodeMetadata) -> Option { - None - } +/// Simple demo filter for testing. +/// +/// A transfer to Alice will issue the corresponding balance to Alice in the enclave. +/// It does not do anything else. +pub struct TransferToAliceShieldsFundsFilter { + _phantom: PhantomData, } - /// Default filter we use for the Integritee-Parachain. pub struct ShieldFundsAndInvokeFilter { _phantom: PhantomData, @@ -119,13 +121,19 @@ where let xt = match Self::ParseParentchainMetadata::parse(call_mut) { Ok(xt) => xt, Err(e) => { - log::error!("Could not parse parentchain extrinsic: {:?}", e); + log::error!( + "[ShieldFundsAndInvokeFilter] Could not parse parentchain extrinsic: {:?}", + e + ); return None }, }; let index = xt.call_index; let call_args = &mut &xt.call_args[..]; - log::trace!("attempting to execute indirect call with index {:?}", index); + log::trace!( + "[ShieldFundsAndInvokeFilter] attempting to execute indirect call with index {:?}", + index + ); if index == metadata.shield_funds_call_indexes().ok()? { log::trace!("executing shield funds call"); let args = decode_and_log_error::(call_args)?; @@ -140,6 +148,50 @@ where } } +impl FilterIntoDataFrom + for TransferToAliceShieldsFundsFilter +where + ExtrinsicParser: ParseExtrinsic, +{ + type Output = IndirectCall; + type ParseParentchainMetadata = ExtrinsicParser; + + fn filter_into_from_metadata( + encoded_data: &[u8], + metadata: &NodeMetadata, + ) -> Option { + let call_mut = &mut &encoded_data[..]; + + // Todo: the filter should not need to parse, only filter. This should directly be configured + // in the indirect executor. + let xt = match Self::ParseParentchainMetadata::parse(call_mut) { + Ok(xt) => xt, + Err(e) => { + log::error!("[TransferToAliceShieldsFundsFilter] Could not parse parentchain extrinsic: {:?}", e); + return None + }, + }; + let index = xt.call_index; + let call_args = &mut &xt.call_args[..]; + log::trace!("[TransferToAliceShieldsFundsFilter] attempting to execute indirect call with index {:?}", index); + if index == metadata.transfer_call_index().ok()? + || index == metadata.transfer_allow_death_call_index().ok()? + { + log::trace!("found `transfer` or `transfer_allow_death` call."); + let args = decode_and_log_error::(call_args)?; + if args.destination == ALICE_ACCOUNT_ID.into() { + Some(IndirectCall::TransferToAliceShieldsFunds(args)) + } else { + log::trace!("Parentchain transfer was not for Alice; ignoring..."); + // No need to put it into the top pool if it isn't executed in the first place. + None + } + } else { + None + } + } +} + /// The default indirect call of the Integritee-Parachain. /// /// Todo: Move or provide a template in app-libs such that users @@ -148,6 +200,7 @@ where pub enum IndirectCall { ShieldFunds(ShieldFundsArgs), Invoke(InvokeArgs), + TransferToAliceShieldsFunds(TransferToAliceShieldsFundsArgs), } impl IndirectDispatch for IndirectCall { @@ -155,6 +208,7 @@ impl IndirectDispatch for IndirectCall { match self { IndirectCall::ShieldFunds(shieldfunds_args) => shieldfunds_args.dispatch(executor), IndirectCall::Invoke(invoke_args) => invoke_args.dispatch(executor), + IndirectCall::TransferToAliceShieldsFunds(args) => args.dispatch(executor), } } } @@ -168,3 +222,34 @@ fn decode_and_log_error(encoded: &mut &[u8]) -> Option { }, } } + +mod seal { + use super::*; + + /// Stub struct for the `DenyAll` filter that never executes anything. + #[derive(Debug, Encode)] + pub struct CantExecute; + + impl FilterIntoDataFrom for DenyAll { + type Output = CantExecute; + type ParseParentchainMetadata = (); + + fn filter_into_from_metadata(_: &[u8], _: &NodeMetadata) -> Option { + None + } + } + + impl IndirectDispatch for CantExecute { + fn dispatch(&self, _: &Executor) -> Result<()> { + // We should never get here because `CantExecute` is in a private module and the trait + // implementation is sealed and always returns `None` instead of a `CantExecute` instance. + // Regardless, we never want the enclave to panic, this is why we take this extra safety + // measure. + log::warn!( + "Executed indirect dispatch for 'CantExecute'\ + this means there is some logic error." + ); + Ok(()) + } + } +} diff --git a/core/parentchain/indirect-calls-executor/src/indirect_calls/mod.rs b/core/parentchain/indirect-calls-executor/src/indirect_calls/mod.rs index c25aa517..4f2da407 100644 --- a/core/parentchain/indirect-calls-executor/src/indirect_calls/mod.rs +++ b/core/parentchain/indirect-calls-executor/src/indirect_calls/mod.rs @@ -17,6 +17,8 @@ mod invoke; mod shield_funds; +mod transfer_to_alice_shields_funds; pub use invoke::InvokeArgs; pub use shield_funds::ShieldFundsArgs; +pub use transfer_to_alice_shields_funds::{TransferToAliceShieldsFundsArgs, ALICE_ACCOUNT_ID}; diff --git a/core/parentchain/indirect-calls-executor/src/indirect_calls/transfer_to_alice_shields_funds.rs b/core/parentchain/indirect-calls-executor/src/indirect_calls/transfer_to_alice_shields_funds.rs new file mode 100644 index 00000000..869e74f3 --- /dev/null +++ b/core/parentchain/indirect-calls-executor/src/indirect_calls/transfer_to_alice_shields_funds.rs @@ -0,0 +1,89 @@ +/* + 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, IndirectDispatch, IndirectExecutor}; +use codec::{Decode, Encode}; +use ita_stf::{TrustedCall, TrustedOperation}; +use itp_stf_primitives::types::AccountId; +use itp_types::Balance; +use log::info; +use sp_runtime::MultiAddress; + +/// Arguments of a parentchains `transfer` or `transfer_allow_death` dispatchable. +/// +/// This is a simple demo indirect call where a transfer to alice on chain will transfer +/// funds to alice on sidechain. +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct TransferToAliceShieldsFundsArgs { + // () is just a placeholder for index, which we don't use + pub destination: MultiAddress, + #[codec(compact)] + pub value: Balance, +} + +/// AccountId for `//Alice` because we can't derive the alice account in `no-std` otherwise. +/// +/// The following seed has been obtained by: +/// +/// ``` +/// use sp_core::{sr25519, Pair}; +/// use itc_parentchain_indirect_calls_executor::indirect_calls::ALICE_ACCOUNT_ID; +/// +/// let alice = sr25519::Pair::from_string_with_seed("//Alice", None).unwrap(); +/// println!("{:?}", alice.0.public().to_vec()); +/// assert_eq!(ALICE_ACCOUNT_ID, alice.0.public().into()) +/// ``` +pub const ALICE_ACCOUNT_ID: AccountId = AccountId::new([ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, + 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, +]); + +impl IndirectDispatch for TransferToAliceShieldsFundsArgs { + fn dispatch(&self, executor: &Executor) -> Result<()> { + if self.destination == ALICE_ACCOUNT_ID.into() { + info!("Found Transfer to Alice extrinsic in block: \nAmount: {}", self.value); + + let shard = executor.get_default_shard(); + let trusted_call = TrustedCall::balance_shield( + executor.get_enclave_account()?, + ALICE_ACCOUNT_ID, + self.value, + ); + let signed_trusted_call = executor.sign_call_with_self(&trusted_call, &shard)?; + let trusted_operation = TrustedOperation::indirect_call(signed_trusted_call); + + let encrypted_trusted_call = executor.encrypt(&trusted_operation.encode())?; + executor.submit_trusted_call(shard, encrypted_trusted_call); + } else { + log::trace!("Transfer on parentchain was not for alice") + } + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use crate::indirect_calls::transfer_to_alice_shields_funds::ALICE_ACCOUNT_ID; + use sp_core::{sr25519, Pair}; + + #[test] + fn alice_account_is_correct() { + let alice = sr25519::Pair::from_string_with_seed("//Alice", None).unwrap(); + assert_eq!(ALICE_ACCOUNT_ID, alice.0.public().into()); + } +} diff --git a/core/parentchain/indirect-calls-executor/src/traits.rs b/core/parentchain/indirect-calls-executor/src/traits.rs index 3cc0efcf..9e069bc2 100644 --- a/core/parentchain/indirect-calls-executor/src/traits.rs +++ b/core/parentchain/indirect-calls-executor/src/traits.rs @@ -64,6 +64,8 @@ pub trait IndirectExecutor { fn get_enclave_account(&self) -> Result; + fn get_default_shard(&self) -> ShardIdentifier; + fn sign_call_with_self( &self, trusted_call: &TrustedCall, diff --git a/core/parentchain/light-client/src/concurrent_access.rs b/core/parentchain/light-client/src/concurrent_access.rs index f6482c92..fda60d74 100644 --- a/core/parentchain/light-client/src/concurrent_access.rs +++ b/core/parentchain/light-client/src/concurrent_access.rs @@ -30,6 +30,7 @@ use crate::{ LightValidationState, Validator as ValidatorTrait, }; use finality_grandpa::BlockNumberOps; +use itp_types::parentchain::{IdentifyParentchain, ParentchainId}; use sp_runtime::traits::{Block as ParentchainBlockTrait, NumberFor}; use std::{marker::PhantomData, sync::Arc}; @@ -79,6 +80,14 @@ impl } } +impl IdentifyParentchain + for ValidatorAccessor +{ + fn parentchain_id(&self) -> ParentchainId { + (*self.seal).parentchain_id() + } +} + impl ValidatorAccess for ValidatorAccessor where diff --git a/core/parentchain/light-client/src/io.rs b/core/parentchain/light-client/src/io.rs index 9937729c..661934fe 100644 --- a/core/parentchain/light-client/src/io.rs +++ b/core/parentchain/light-client/src/io.rs @@ -27,6 +27,7 @@ use codec::{Decode, Encode}; use core::{fmt::Debug, marker::PhantomData}; use itp_ocall_api::EnclaveOnChainOCallApi; use itp_sgx_io::{seal, unseal}; +use itp_types::parentchain::{IdentifyParentchain, ParentchainId}; use log::*; use sp_runtime::traits::{Block, Header}; use std::{ @@ -121,12 +122,23 @@ impl LightClientSealing #[derive(Debug)] pub struct LightClientStateSealSync { seal: LightClientStateSeal, + parentchain_id: ParentchainId, _rw_lock: RwLock<()>, } impl LightClientStateSealSync { - pub fn new(base_path: PathBuf) -> Result { - Ok(Self { seal: LightClientStateSeal::new(base_path)?, _rw_lock: RwLock::new(()) }) + pub fn new(base_path: PathBuf, parentchain_id: ParentchainId) -> Result { + Ok(Self { + seal: LightClientStateSeal::new(base_path)?, + parentchain_id, + _rw_lock: RwLock::new(()), + }) + } +} + +impl IdentifyParentchain for LightClientStateSealSync { + fn parentchain_id(&self) -> ParentchainId { + self.parentchain_id } } @@ -160,6 +172,7 @@ pub fn read_or_init_grandpa_validator( params: GrandpaParams, ocall_api: Arc, seal: &LightClientSeal, + parentchain_id: ParentchainId, ) -> Result> where B: Block, @@ -178,6 +191,7 @@ where let validator = init_grandpa_validator::( ocall_api, RelayState::new(params.genesis_header, params.authorities).into(), + parentchain_id, )?; seal.seal(validator.get_state())?; return Ok(validator) @@ -197,7 +211,7 @@ where RelayState::new(params.genesis_header, params.authorities).into() }; - let validator = init_grandpa_validator::(ocall_api, init_state)?; + let validator = init_grandpa_validator::(ocall_api, init_state, parentchain_id)?; info!("light client state: {:?}", validator); @@ -209,6 +223,7 @@ pub fn read_or_init_parachain_validator( params: SimpleParams, ocall_api: Arc, seal: &LightClientSeal, + parentchain_id: ParentchainId, ) -> Result> where B: Block, @@ -221,6 +236,7 @@ where let validator = init_parachain_validator::( ocall_api, RelayState::new(params.genesis_header, Default::default()).into(), + parentchain_id, )?; seal.seal(validator.get_state())?; return Ok(validator) @@ -240,7 +256,7 @@ where RelayState::new(params.genesis_header, vec![]).into() }; - let validator = init_parachain_validator::(ocall_api, init_state)?; + let validator = init_parachain_validator::(ocall_api, init_state, parentchain_id)?; info!("light client state: {:?}", validator); seal.seal(validator.get_state())?; @@ -250,6 +266,7 @@ where fn init_grandpa_validator( ocall_api: Arc, state: LightValidationState, + parentchain_id: ParentchainId, ) -> Result> where B: Block, @@ -259,7 +276,7 @@ where let finality: Arc + Sync + Send + 'static>> = Arc::new(Box::new(GrandpaFinality)); - let validator = LightValidation::::new(ocall_api, finality, state); + let validator = LightValidation::::new(ocall_api, finality, state, parentchain_id); Ok(validator) } @@ -267,6 +284,7 @@ where fn init_parachain_validator( ocall_api: Arc, state: LightValidationState, + parentchain_id: ParentchainId, ) -> Result> where B: Block, @@ -276,7 +294,7 @@ where let finality: Arc + Sync + Send + 'static>> = Arc::new(Box::new(ParachainFinality)); - let validator = LightValidation::::new(ocall_api, finality, state); + let validator = LightValidation::::new(ocall_api, finality, state, parentchain_id); Ok(validator) } @@ -290,6 +308,7 @@ pub mod sgx_tests { use itc_parentchain_test::{Block, Header, ParentchainHeaderBuilder}; use itp_sgx_temp_dir::TempDir; use itp_test::mock::onchain_mock::OnchainMock; + use itp_types::parentchain::ParentchainId; use sp_runtime::OpaqueExtrinsic; type TestBlock = Block; @@ -308,6 +327,7 @@ pub mod sgx_tests { parachain_params.clone(), Arc::new(OnchainMock::default()), &seal, + ParentchainId::Integritee, ) .unwrap(); diff --git a/core/parentchain/light-client/src/light_client_init_params.rs b/core/parentchain/light-client/src/light_client_init_params.rs index 61baf247..114d6843 100644 --- a/core/parentchain/light-client/src/light_client_init_params.rs +++ b/core/parentchain/light-client/src/light_client_init_params.rs @@ -26,7 +26,24 @@ pub struct GrandpaParams
{ pub authorities: AuthorityList, pub authority_proof: Vec>, } + +impl
GrandpaParams
{ + pub fn new( + genesis_header: Header, + authorities: AuthorityList, + authority_proof: Vec>, + ) -> Self { + Self { genesis_header, authorities, authority_proof } + } +} + #[derive(Encode, Decode, Clone)] pub struct SimpleParams
{ pub genesis_header: Header, } + +impl
SimpleParams
{ + pub fn new(genesis_header: Header) -> Self { + Self { genesis_header } + } +} diff --git a/core/parentchain/light-client/src/light_validation.rs b/core/parentchain/light-client/src/light_validation.rs index ea8bd53a..e23761b0 100644 --- a/core/parentchain/light-client/src/light_validation.rs +++ b/core/parentchain/light-client/src/light_validation.rs @@ -25,6 +25,7 @@ use codec::Encode; use core::iter::Iterator; use itp_ocall_api::EnclaveOnChainOCallApi; use itp_storage::{Error as StorageError, StorageProof, StorageProofChecker}; +use itp_types::parentchain::ParentchainId; use log::*; use sp_runtime::{ generic::SignedBlock, @@ -37,6 +38,7 @@ use std::{boxed::Box, fmt, sync::Arc, vec::Vec}; pub struct LightValidation { light_validation_state: LightValidationState, ocall_api: Arc, + parentchain_id: ParentchainId, finality: Arc + Sync + Send + 'static>>, } @@ -47,8 +49,9 @@ impl ocall_api: Arc, finality: Arc + Sync + Send + 'static>>, light_validation_state: LightValidationState, + parentchain_id: ParentchainId, ) -> Self { - Self { light_validation_state, ocall_api, finality } + Self { light_validation_state, ocall_api, finality, parentchain_id } } // A naive way to check whether a `child` header is a descendant @@ -198,7 +201,7 @@ where } self.ocall_api - .send_to_parentchain(extrinsics) + .send_to_parentchain(extrinsics, &self.parentchain_id) .map_err(|e| Error::Other(format!("Failed to send extrinsics: {}", e).into())) } } diff --git a/core/parentchain/light-client/src/mocks/validator_access_mock.rs b/core/parentchain/light-client/src/mocks/validator_access_mock.rs index 7a182d13..107008f9 100644 --- a/core/parentchain/light-client/src/mocks/validator_access_mock.rs +++ b/core/parentchain/light-client/src/mocks/validator_access_mock.rs @@ -26,7 +26,10 @@ use crate::{ error::{Error, Result}, mocks::validator_mock::ValidatorMock, }; -use itp_types::Block; +use itp_types::{ + parentchain::{IdentifyParentchain, ParentchainId}, + Block, +}; /// Mock for the validator access. /// @@ -55,3 +58,9 @@ impl ValidatorAccess for ValidatorAccessMock { mutating_function(&mut validator_lock) } } + +impl IdentifyParentchain for ValidatorAccessMock { + fn parentchain_id(&self) -> ParentchainId { + ParentchainId::Integritee + } +} diff --git a/core/parentchain/parentchain-crate/src/primitives.rs b/core/parentchain/parentchain-crate/src/primitives.rs index a199a10c..055672ea 100644 --- a/core/parentchain/parentchain-crate/src/primitives.rs +++ b/core/parentchain/parentchain-crate/src/primitives.rs @@ -22,7 +22,7 @@ use codec::{Decode, Encode}; use sp_runtime::traits::Block; -pub use itp_types::{Block as ParachainBlock, Block as SolochainBlock}; +pub use itp_types::{parentchain::ParentchainId, Block as ParachainBlock, Block as SolochainBlock}; pub type HeaderFor = ::Header; pub type SolochainHeader = HeaderFor; pub type ParachainHeader = HeaderFor; @@ -33,18 +33,27 @@ pub type ParachainParams = SimpleParams; /// Allows to use a single E-call for the initialization of different parentchain types. #[derive(Encode, Decode, Clone)] pub enum ParentchainInitParams { - Solochain { params: SolochainParams }, - Parachain { params: ParachainParams }, + Solochain { id: ParentchainId, params: SolochainParams }, + Parachain { id: ParentchainId, params: ParachainParams }, } -impl From for ParentchainInitParams { - fn from(params: SolochainParams) -> Self { - ParentchainInitParams::Solochain { params } +impl ParentchainInitParams { + pub fn id(&self) -> &ParentchainId { + match self { + Self::Solochain { id, .. } => id, + Self::Parachain { id, .. } => id, + } } } -impl From for ParentchainInitParams { - fn from(params: ParachainParams) -> Self { - ParentchainInitParams::Parachain { params } +impl From<(ParentchainId, SolochainParams)> for ParentchainInitParams { + fn from(value: (ParentchainId, SolochainParams)) -> Self { + Self::Solochain { id: value.0, params: value.1 } + } +} + +impl From<(ParentchainId, ParachainParams)> for ParentchainInitParams { + fn from(value: (ParentchainId, ParachainParams)) -> Self { + Self::Parachain { id: value.0, params: value.1 } } } diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index 29ab55e6..c8cf058e 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -58,7 +58,9 @@ enclave { [in, size=shard_size] uint8_t* shard, uint32_t shard_size ); - public sgx_status_t trigger_parentchain_block_import(); + public sgx_status_t trigger_parentchain_block_import( + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size + ); public sgx_status_t execute_trusted_calls(); @@ -66,15 +68,17 @@ enclave { [in, size=blocks_size] uint8_t* blocks, size_t blocks_size, [in, size=events_size] uint8_t* events, size_t events_size, [in, size=events_proofs_size] uint8_t* events_proofs, size_t events_proofs_size, - [in] uint32_t* nonce + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size ); public sgx_status_t set_nonce( - [in] uint32_t* nonce + [in] uint32_t* nonce, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size ); public sgx_status_t set_node_metadata( - [in, size=node_metadata_size] uint8_t* node_metadata, uint32_t node_metadata_size + [in, size=node_metadata_size] uint8_t* node_metadata, uint32_t node_metadata_size, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size ); public sgx_status_t get_rsa_encryption_pubkey( @@ -213,6 +217,7 @@ enclave { sgx_status_t ocall_worker_request( [in, size = req_size] uint8_t * request, uint32_t req_size, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size, [out, size = resp_size] uint8_t * response, uint32_t resp_size ); @@ -236,7 +241,8 @@ enclave { ); sgx_status_t ocall_send_to_parentchain( - [in, size = extrinsics_size] uint8_t * extrinsics, uint32_t extrinsics_size + [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/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index f45fecbd..ae609f27 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -31,7 +31,7 @@ use crate::{ initialization::global_components::GLOBAL_ATTESTATION_HANDLER_COMPONENT, utils::{ get_extrinsic_factory_from_solo_or_parachain, - get_node_metadata_repository_from_solo_or_parachain, + get_node_metadata_repository_from_integritee_solo_or_parachain, }, Error as EnclaveError, Result as EnclaveResult, }; @@ -289,7 +289,7 @@ pub fn generate_dcap_ra_extrinsic_from_quote_internal( url: String, quote: &[u8], ) -> EnclaveResult { - let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; info!(" [Enclave] Compose register enclave getting callIDs:"); let call_ids = node_metadata_repo @@ -311,7 +311,7 @@ pub fn generate_dcap_skip_ra_extrinsic_from_mr_enclave( url: String, quote: &[u8], ) -> EnclaveResult { - let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; info!(" [Enclave] Compose register enclave (skip-ra) getting callIDs:"); let call_ids = node_metadata_repo @@ -347,7 +347,7 @@ pub fn generate_ias_ra_extrinsic_from_der_cert_internal( url: String, cert_der: &[u8], ) -> EnclaveResult { - let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; info!(" [Enclave] Compose register enclave call"); let call_ids = node_metadata_repo @@ -363,7 +363,7 @@ pub fn generate_ias_skip_ra_extrinsic_from_der_cert_internal( url: String, cert_der: &[u8], ) -> EnclaveResult { - let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; info!(" [Enclave] Compose register ias enclave (skip-ra) call"); let call_ids = node_metadata_repo @@ -461,7 +461,7 @@ where { let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; - let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; let call_ids = node_metadata_repo .get_from_metadata(getter)? .map_err(MetadataProviderError::MetadataError)?; diff --git a/enclave-runtime/src/error.rs b/enclave-runtime/src/error.rs index 3519bad1..64eecb83 100644 --- a/enclave-runtime/src/error.rs +++ b/enclave-runtime/src/error.rs @@ -41,7 +41,8 @@ pub enum Error { ParentchainBlockImportDispatch(itc_parentchain::block_import_dispatcher::error::Error), ExpectedTriggeredImportDispatcher, CouldNotDispatchBlockImport, - NoParentchainAssigned, + NoIntegriteeParentchainAssigned, + NoTargetAParentchainAssigned, ParentChainValidation(itp_storage::error::Error), ParentChainSync, PrimitivesAccess(itp_primitives_cache::error::Error), diff --git a/enclave-runtime/src/initialization/global_components.rs b/enclave-runtime/src/initialization/global_components.rs index d3fd7789..0e9a74b3 100644 --- a/enclave-runtime/src/initialization/global_components.rs +++ b/enclave-runtime/src/initialization/global_components.rs @@ -22,7 +22,9 @@ use crate::{ initialization::parentchain::{ - parachain::FullParachainHandler, solochain::FullSolochainHandler, + integritee_parachain::IntegriteeParachainHandler, + integritee_solochain::IntegriteeSolochainHandler, + target_a_parachain::TargetAParachainHandler, target_a_solochain::TargetASolochainHandler, }, ocall::OcallApi, rpc::rpc_response_channel::RpcResponseChannel, @@ -41,7 +43,9 @@ use itc_parentchain::{ }, block_importer::ParentchainBlockImporter, indirect_calls_executor::{ - filter_metadata::{EventCreator, ShieldFundsAndInvokeFilter}, + filter_metadata::{ + EventCreator, ShieldFundsAndInvokeFilter, TransferToAliceShieldsFundsFilter, + }, parentchain_parser::ParentchainExtrinsicParser, IndirectCallsExecutor, }, @@ -88,9 +92,11 @@ use its_sidechain::{ block_composer::BlockComposer, consensus_common::{BlockImportConfirmationHandler, BlockImportQueueWorker, PeerBlockSync}, }; +use lazy_static::lazy_static; use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; use sgx_tstd::vec::Vec; use sp_core::{ed25519, ed25519::Pair}; +use std::sync::Arc; pub type EnclaveParentchainSigner = itp_node_api::api_client::StaticExtrinsicSigner; @@ -130,46 +136,95 @@ pub type EnclaveWebSocketServer = TungsteniteWsServer; pub type EnclaveSidechainApi = SidechainApi; -// Parentchain types +// Parentchain types relevant for all parentchains pub type EnclaveLightClientSeal = LightClientStateSealSync>; pub type EnclaveExtrinsicsFactory = ExtrinsicsFactory; -pub type EnclaveIndirectCallsExecutor = IndirectCallsExecutor< + +/// The enclave's generic indirect executor type. +/// +/// The `IndirectCallsFilter` calls filter can be configured per parentchain. +pub type EnclaveIndirectCallsExecutor = IndirectCallsExecutor< EnclaveShieldingKeyRepository, EnclaveStfEnclaveSigner, EnclaveTopPoolAuthor, EnclaveNodeMetadataRepository, - ShieldFundsAndInvokeFilter, + IndirectCallsFilter, EventCreator, >; + pub type EnclaveValidatorAccessor = ValidatorAccessor< LightValidation, ParentchainBlock, EnclaveLightClientSeal, >; -pub type EnclaveParentchainBlockImporter = ParentchainBlockImporter< + +pub type EnclaveParentchainBlockImportQueue = ImportQueue; + +/// Import queue for the events +/// +/// Note: `Vec` is correct. It should not be `Vec` +pub type EnclaveParentchainEventImportQueue = ImportQueue>; + +// Stuff for the integritee parentchain + +pub type IntegriteeParentchainIndirectExecutor = + EnclaveIndirectCallsExecutor>; + +pub type IntegriteeParentchainBlockImporter = ParentchainBlockImporter< ParentchainBlock, EnclaveValidatorAccessor, EnclaveStfExecutor, EnclaveExtrinsicsFactory, - EnclaveIndirectCallsExecutor, + IntegriteeParentchainIndirectExecutor, >; -pub type EnclaveParentchainBlockImportQueue = ImportQueue; -// Should not be a Vec> -pub type EnclaveParentchainEventImportQueue = ImportQueue>; -pub type EnclaveTriggeredParentchainBlockImportDispatcher = TriggeredDispatcher< - EnclaveParentchainBlockImporter, + +pub type IntegriteeParentchainTriggeredBlockImportDispatcher = TriggeredDispatcher< + IntegriteeParentchainBlockImporter, + EnclaveParentchainBlockImportQueue, + EnclaveParentchainEventImportQueue, +>; + +pub type IntegriteeParentchainImmediateBlockImportDispatcher = + ImmediateDispatcher; + +pub type IntegriteeParentchainBlockImportDispatcher = BlockImportDispatcher< + IntegriteeParentchainTriggeredBlockImportDispatcher, + IntegriteeParentchainImmediateBlockImportDispatcher, +>; + +// Stuff for the Target A parentchain + +/// IndirectCalls executor instance of the Target A parentchain. +/// +/// **Note**: The filter here is purely used for demo purposes. +/// +/// Also note that the extrinsic parser must be changed if the signed extra contains the +/// `AssetTxPayment`. +pub type TargetAParentchainIndirectExecutor = + EnclaveIndirectCallsExecutor>; + +pub type TargetAParentchainBlockImporter = ParentchainBlockImporter< + ParentchainBlock, + EnclaveValidatorAccessor, + EnclaveStfExecutor, + EnclaveExtrinsicsFactory, + TargetAParentchainIndirectExecutor, +>; + +pub type TargetAParentchainTriggeredBlockImportDispatcher = TriggeredDispatcher< + TargetAParentchainBlockImporter, EnclaveParentchainBlockImportQueue, EnclaveParentchainEventImportQueue, >; -pub type EnclaveImmediateParentchainBlockImportDispatcher = - ImmediateDispatcher; +pub type TargetAParentchainImmediateBlockImportDispatcher = + ImmediateDispatcher; -pub type EnclaveParentchainBlockImportDispatcher = BlockImportDispatcher< - EnclaveTriggeredParentchainBlockImportDispatcher, - EnclaveImmediateParentchainBlockImportDispatcher, +pub type TargetAParentchainBlockImportDispatcher = BlockImportDispatcher< + TargetAParentchainTriggeredBlockImportDispatcher, + TargetAParentchainImmediateBlockImportDispatcher, >; /// Sidechain types @@ -192,7 +247,8 @@ pub type EnclaveSidechainBlockImporter = SidechainBlockImporter< EnclaveStateHandler, EnclaveStateKeyRepository, EnclaveTopPoolAuthor, - EnclaveTriggeredParentchainBlockImportDispatcher, + // For now the sidechain does only support one parentchain. + IntegriteeParentchainTriggeredBlockImportDispatcher, >; pub type EnclaveSidechainBlockImportQueue = ImportQueue; pub type EnclaveBlockImportConfirmationHandler = BlockImportConfirmationHandler< @@ -231,8 +287,8 @@ pub type EnclaveOffchainWorkerExecutor = itc_offchain_worker_executor::executor: EnclaveStf, >; -/// Base component instances -///------------------------------------------------------------------------------------------------- +// Base component instances +//------------------------------------------------------------------------------------------------- /// State key repository pub static GLOBAL_STATE_KEY_REPOSITORY_COMPONENT: ComponentContainer = @@ -248,9 +304,15 @@ pub static GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT: ComponentContainer< EnclaveSigningKeyRepository, > = ComponentContainer::new("Signing key repository"); -/// Light client db seal. -pub static GLOBAL_LIGHT_CLIENT_SEAL: ComponentContainer = - ComponentContainer::new("EnclaveLightClientSealSync"); +/// Light client db seal for the Integritee parentchain +pub static GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer< + EnclaveLightClientSeal, +> = ComponentContainer::new("Integritee Parentchain EnclaveLightClientSealSync"); + +/// Light client db seal for the Target A parentchain. +pub static GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer< + EnclaveLightClientSeal, +> = ComponentContainer::new("Target A EnclaveLightClientSealSync"); /// O-Call API pub static GLOBAL_OCALL_API_COMPONENT: ComponentContainer = @@ -276,18 +338,36 @@ pub static GLOBAL_TOP_POOL_AUTHOR_COMPONENT: ComponentContainer = ComponentContainer::new("Attestation handler"); -/// Parentchain component instances -///------------------------------------------------------------------------------------------------- +// Parentchain component instances +//------------------------------------------------------------------------------------------------- + +lazy_static! { + /// Global nonce cache for the Integritee Parentchain. + pub static ref GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE: Arc = Default::default(); + + /// Global nonce cache for the Target A parentchain.. + pub static ref GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE: Arc = Default::default(); +} /// Solochain Handler. -pub static GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT: ComponentContainer = - ComponentContainer::new("full solochain handler"); +pub static GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT: ComponentContainer< + IntegriteeSolochainHandler, +> = ComponentContainer::new("integritee solochain handler"); + +pub static GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT: ComponentContainer< + IntegriteeParachainHandler, +> = ComponentContainer::new("integritee parachain handler"); + +pub static GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT: ComponentContainer< + TargetASolochainHandler, +> = ComponentContainer::new("target A solochain handler"); -pub static GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT: ComponentContainer = - ComponentContainer::new("full parachain handler"); +pub static GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT: ComponentContainer< + TargetAParachainHandler, +> = ComponentContainer::new("target A parachain handler"); -/// Sidechain component instances -///------------------------------------------------------------------------------------------------- +// Sidechain component instances +//------------------------------------------------------------------------------------------------- /// Enclave RPC WS handler. pub static GLOBAL_RPC_WS_HANDLER_COMPONENT: ComponentContainer = diff --git a/enclave-runtime/src/initialization/mod.rs b/enclave-runtime/src/initialization/mod.rs index d2e113fa..d1484acb 100644 --- a/enclave-runtime/src/initialization/mod.rs +++ b/enclave-runtime/src/initialization/mod.rs @@ -28,19 +28,20 @@ use crate::{ EnclaveSidechainBlockSyncer, EnclaveStateFileIo, EnclaveStateHandler, EnclaveStateInitializer, EnclaveStateObserver, EnclaveStateSnapshotRepository, EnclaveStfEnclaveSigner, EnclaveTopPool, EnclaveTopPoolAuthor, - GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_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_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_ATTESTATION_HANDLER_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_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_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_solo_or_parachain, - get_node_metadata_repository_from_solo_or_parachain, + get_node_metadata_repository_from_integritee_solo_or_parachain, get_triggered_dispatcher_from_solo_or_parachain, get_validator_accessor_from_solo_or_parachain, }, @@ -59,7 +60,10 @@ use itc_tls_websocket_server::{ use itp_attestation_handler::IntelAttestationHandler; use itp_component_container::{ComponentGetter, ComponentInitializer}; use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; -use itp_settings::files::{LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE}; +use itp_settings::files::{ + INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, + TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, +}; use itp_sgx_crypto::{ get_aes_repository, get_ed25519_repository, get_rsa3072_repository, key_repository::AccessKey, }; @@ -70,7 +74,7 @@ use itp_stf_state_handler::{ }; use itp_top_pool::pool::Options as PoolOptions; use itp_top_pool_author::author::AuthorTopFilter; -use itp_types::ShardIdentifier; +use itp_types::{parentchain::ParentchainId, ShardIdentifier}; use its_sidechain::block_composer::BlockComposer; use log::*; use sp_core::crypto::Pair; @@ -94,9 +98,17 @@ pub(crate) fn init_enclave( let state_key_repository = Arc::new(get_aes_repository(base_dir.clone())?); GLOBAL_STATE_KEY_REPOSITORY_COMPONENT.initialize(state_key_repository.clone()); - let light_client_seal = - Arc::new(EnclaveLightClientSeal::new(base_dir.join(LIGHT_CLIENT_DB_PATH))?); - GLOBAL_LIGHT_CLIENT_SEAL.initialize(light_client_seal); + let integritee_light_client_seal = Arc::new(EnclaveLightClientSeal::new( + base_dir.join(INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), + ParentchainId::Integritee, + )?); + GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.initialize(integritee_light_client_seal); + + let target_a_light_client_seal = Arc::new(EnclaveLightClientSeal::new( + base_dir.join(TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), + ParentchainId::TargetA, + )?); + GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL.initialize(target_a_light_client_seal); let state_file_io = Arc::new(EnclaveStateFileIo::new(state_key_repository, StateDir::new(base_dir))); @@ -206,7 +218,7 @@ pub(crate) fn init_enclave_sidechain_components() -> EnclaveResult<()> { )); let sidechain_block_import_queue = GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT.get()?; - let metadata_repository = get_node_metadata_repository_from_solo_or_parachain()?; + let metadata_repository = get_node_metadata_repository_from_integritee_solo_or_parachain()?; let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; let validator_accessor = get_validator_accessor_from_solo_or_parachain()?; diff --git a/enclave-runtime/src/initialization/parentchain/common.rs b/enclave-runtime/src/initialization/parentchain/common.rs index 91ce1a12..998e3398 100644 --- a/enclave-runtime/src/initialization/parentchain/common.rs +++ b/enclave-runtime/src/initialization/parentchain/common.rs @@ -19,12 +19,15 @@ use crate::{ error::Result, initialization::{ global_components::{ - EnclaveExtrinsicsFactory, EnclaveImmediateParentchainBlockImportDispatcher, - EnclaveIndirectCallsExecutor, EnclaveNodeMetadataRepository, - EnclaveOffchainWorkerExecutor, EnclaveParentchainBlockImportDispatcher, - EnclaveParentchainBlockImportQueue, EnclaveParentchainBlockImporter, - EnclaveParentchainEventImportQueue, EnclaveParentchainSigner, EnclaveStfExecutor, - EnclaveTriggeredParentchainBlockImportDispatcher, EnclaveValidatorAccessor, + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOffchainWorkerExecutor, + EnclaveParentchainBlockImportQueue, EnclaveParentchainEventImportQueue, + EnclaveParentchainSigner, EnclaveStfExecutor, EnclaveValidatorAccessor, + IntegriteeParentchainBlockImportDispatcher, IntegriteeParentchainBlockImporter, + IntegriteeParentchainImmediateBlockImportDispatcher, + IntegriteeParentchainIndirectExecutor, + IntegriteeParentchainTriggeredBlockImportDispatcher, + TargetAParentchainBlockImportDispatcher, TargetAParentchainBlockImporter, + TargetAParentchainImmediateBlockImportDispatcher, TargetAParentchainIndirectExecutor, 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, @@ -33,18 +36,18 @@ use crate::{ }, }; use itp_component_container::ComponentGetter; -use itp_nonce_cache::GLOBAL_NONCE_CACHE; +use itp_nonce_cache::NonceCache; use itp_sgx_crypto::key_repository::AccessKey; use log::*; use sp_core::H256; use std::sync::Arc; -pub(crate) fn create_parentchain_block_importer( +pub(crate) fn create_integritee_parentchain_block_importer( validator_access: Arc, stf_executor: Arc, extrinsics_factory: Arc, node_metadata_repository: Arc, -) -> Result { +) -> Result { let state_observer = GLOBAL_STATE_OBSERVER_COMPONENT.get()?; let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; let shielding_key_repository = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get()?; @@ -56,13 +59,44 @@ pub(crate) fn create_parentchain_block_importer( shielding_key_repository.clone(), top_pool_author.clone(), )); - let indirect_calls_executor = Arc::new(EnclaveIndirectCallsExecutor::new( + let indirect_calls_executor = Arc::new(IntegriteeParentchainIndirectExecutor::new( shielding_key_repository, stf_enclave_signer, top_pool_author, node_metadata_repository, )); - Ok(EnclaveParentchainBlockImporter::new( + Ok(IntegriteeParentchainBlockImporter::new( + validator_access, + stf_executor, + extrinsics_factory, + indirect_calls_executor, + )) +} + +pub(crate) fn create_target_a_parentchain_block_importer( + validator_access: Arc, + stf_executor: Arc, + extrinsics_factory: Arc, + node_metadata_repository: Arc, +) -> Result { + let state_observer = GLOBAL_STATE_OBSERVER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + let shielding_key_repository = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get()?; + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + + let stf_enclave_signer = Arc::new(EnclaveStfEnclaveSigner::new( + state_observer, + ocall_api, + shielding_key_repository.clone(), + top_pool_author.clone(), + )); + let indirect_calls_executor = Arc::new(TargetAParentchainIndirectExecutor::new( + shielding_key_repository, + stf_enclave_signer, + top_pool_author, + node_metadata_repository, + )); + Ok(TargetAParentchainBlockImporter::new( validator_access, stf_executor, extrinsics_factory, @@ -72,6 +106,7 @@ pub(crate) fn create_parentchain_block_importer( pub(crate) fn create_extrinsics_factory( genesis_hash: H256, + nonce_cache: Arc, node_metadata_repository: Arc, ) -> Result> { let signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; @@ -79,17 +114,47 @@ pub(crate) fn create_extrinsics_factory( Ok(Arc::new(EnclaveExtrinsicsFactory::new( genesis_hash, EnclaveParentchainSigner::new(signer), - GLOBAL_NONCE_CACHE.clone(), + nonce_cache, node_metadata_repository, ))) } -pub(crate) fn create_offchain_immediate_import_dispatcher( +pub(crate) fn create_integritee_offchain_immediate_import_dispatcher( + stf_executor: Arc, + block_importer: IntegriteeParentchainBlockImporter, + validator_access: Arc, + extrinsics_factory: Arc, +) -> Result> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + + let offchain_worker_executor = Arc::new(EnclaveOffchainWorkerExecutor::new( + top_pool_author, + stf_executor, + state_handler, + validator_access, + extrinsics_factory, + )); + let immediate_dispatcher = IntegriteeParentchainImmediateBlockImportDispatcher::new( + block_importer, + ) + .with_observer(move || { + if let Err(e) = offchain_worker_executor.execute() { + error!("Failed to execute trusted calls: {:?}", e); + } + }); + + Ok(Arc::new(IntegriteeParentchainBlockImportDispatcher::new_immediate_dispatcher(Arc::new( + immediate_dispatcher, + )))) +} + +pub(crate) fn create_target_a_offchain_immediate_import_dispatcher( stf_executor: Arc, - block_importer: EnclaveParentchainBlockImporter, + block_importer: TargetAParentchainBlockImporter, validator_access: Arc, extrinsics_factory: Arc, -) -> Result> { +) -> Result> { let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; @@ -100,7 +165,7 @@ pub(crate) fn create_offchain_immediate_import_dispatcher( validator_access, extrinsics_factory, )); - let immediate_dispatcher = EnclaveImmediateParentchainBlockImportDispatcher::new( + let immediate_dispatcher = TargetAParentchainImmediateBlockImportDispatcher::new( block_importer, ) .with_observer(move || { @@ -109,22 +174,22 @@ pub(crate) fn create_offchain_immediate_import_dispatcher( } }); - Ok(Arc::new(EnclaveParentchainBlockImportDispatcher::new_immediate_dispatcher(Arc::new( + Ok(Arc::new(TargetAParentchainBlockImportDispatcher::new_immediate_dispatcher(Arc::new( immediate_dispatcher, )))) } pub(crate) fn create_sidechain_triggered_import_dispatcher( - block_importer: EnclaveParentchainBlockImporter, -) -> Arc { + block_importer: IntegriteeParentchainBlockImporter, +) -> Arc { let parentchain_block_import_queue = EnclaveParentchainBlockImportQueue::default(); let parentchain_event_import_queue = EnclaveParentchainEventImportQueue::default(); - let triggered_dispatcher = EnclaveTriggeredParentchainBlockImportDispatcher::new( + let triggered_dispatcher = IntegriteeParentchainTriggeredBlockImportDispatcher::new( block_importer, parentchain_block_import_queue, parentchain_event_import_queue, ); - Arc::new(EnclaveParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( + Arc::new(IntegriteeParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( triggered_dispatcher, ))) } diff --git a/enclave-runtime/src/initialization/parentchain/parachain.rs b/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs similarity index 62% rename from enclave-runtime/src/initialization/parentchain/parachain.rs rename to enclave-runtime/src/initialization/parentchain/integritee_parachain.rs index 7b43450e..f13961aa 100644 --- a/enclave-runtime/src/initialization/parentchain/parachain.rs +++ b/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs @@ -20,61 +20,65 @@ use crate::{ initialization::{ global_components::{ EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, - EnclaveParentchainBlockImportDispatcher, EnclaveStfExecutor, EnclaveValidatorAccessor, - GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT, GLOBAL_OCALL_API_COMPONENT, + EnclaveStfExecutor, EnclaveValidatorAccessor, + IntegriteeParentchainBlockImportDispatcher, + GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE, GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, }, parentchain::common::{ - create_extrinsics_factory, create_offchain_immediate_import_dispatcher, - create_parentchain_block_importer, create_sidechain_triggered_import_dispatcher, + create_extrinsics_factory, create_integritee_offchain_immediate_import_dispatcher, + create_integritee_parentchain_block_importer, + create_sidechain_triggered_import_dispatcher, }, }, }; -use codec::Encode; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; -use itp_component_container::{ComponentGetter, ComponentInitializer}; +use itp_component_container::ComponentGetter; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; -use std::{path::PathBuf, sync::Arc, vec::Vec}; +use itp_types::parentchain::ParentchainId; +use std::{path::PathBuf, sync::Arc}; -use crate::initialization::global_components::GLOBAL_LIGHT_CLIENT_SEAL; pub use itc_parentchain::primitives::{ParachainBlock, ParachainHeader, ParachainParams}; #[derive(Clone)] -pub struct FullParachainHandler { +pub struct IntegriteeParachainHandler { pub genesis_header: ParachainHeader, pub node_metadata_repository: Arc, - // FIXME: Probably should be split up into a parentchain dependent executor and one independent. pub stf_executor: Arc, pub validator_accessor: Arc, pub extrinsics_factory: Arc, - pub import_dispatcher: Arc, + pub import_dispatcher: Arc, } -impl FullParachainHandler { +impl IntegriteeParachainHandler { pub fn init( _base_path: PathBuf, params: ParachainParams, - ) -> Result> { + ) -> 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()); let genesis_header = params.genesis_header.clone(); - let light_client_seal = GLOBAL_LIGHT_CLIENT_SEAL.get()?; - let validator = itc_parentchain::light_client::io::read_or_init_parachain_validator::< - ParachainBlock, - EnclaveOCallApi, - _, - >(params, ocall_api.clone(), &*light_client_seal)?; - let latest_header = validator.latest_finalized_header()?; + let light_client_seal = GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let validator = + itc_parentchain::light_client::io::read_or_init_parachain_validator::< + ParachainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::Integritee)?; let validator_accessor = Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; - let extrinsics_factory = - create_extrinsics_factory(genesis_hash, node_metadata_repository.clone())?; + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; let stf_executor = Arc::new(EnclaveStfExecutor::new( ocall_api, @@ -82,7 +86,7 @@ impl FullParachainHandler { node_metadata_repository.clone(), )); - let block_importer = create_parentchain_block_importer( + let block_importer = create_integritee_parentchain_block_importer( validator_accessor.clone(), stf_executor.clone(), extrinsics_factory.clone(), @@ -90,7 +94,7 @@ impl FullParachainHandler { )?; let import_dispatcher = match WorkerModeProvider::worker_mode() { - WorkerMode::OffChainWorker => create_offchain_immediate_import_dispatcher( + WorkerMode::OffChainWorker => create_integritee_offchain_immediate_import_dispatcher( stf_executor.clone(), block_importer, validator_accessor.clone(), @@ -98,20 +102,18 @@ impl FullParachainHandler { )?, WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher(block_importer), WorkerMode::Teeracle => - Arc::new(EnclaveParentchainBlockImportDispatcher::new_empty_dispatcher()), + Arc::new(IntegriteeParentchainBlockImportDispatcher::new_empty_dispatcher()), }; - let parachain_handler = Arc::new(Self { + let parachain_handler = Self { genesis_header, node_metadata_repository, stf_executor, validator_accessor, extrinsics_factory, import_dispatcher, - }); - - GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT.initialize(parachain_handler); + }; - Ok(latest_header.encode()) + Ok(parachain_handler) } } diff --git a/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs b/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs new file mode 100644 index 00000000..d84624f0 --- /dev/null +++ b/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs @@ -0,0 +1,118 @@ +/* + 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::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, + IntegriteeParentchainBlockImportDispatcher, + GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE, GLOBAL_OCALL_API_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, + }, + 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}; + +pub use itc_parentchain::primitives::{SolochainBlock, SolochainHeader, SolochainParams}; + +pub struct IntegriteeSolochainHandler { + pub genesis_header: SolochainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl IntegriteeSolochainHandler { + 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()?; + let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); + + let genesis_header = params.genesis_header.clone(); + + let validator = + itc_parentchain::light_client::io::read_or_init_grandpa_validator::< + SolochainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::Integritee)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_integritee_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + 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 solochain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(solochain_handler) + } +} diff --git a/enclave-runtime/src/initialization/parentchain/mod.rs b/enclave-runtime/src/initialization/parentchain/mod.rs index 2206289d..b120e29b 100644 --- a/enclave-runtime/src/initialization/parentchain/mod.rs +++ b/enclave-runtime/src/initialization/parentchain/mod.rs @@ -15,26 +15,82 @@ */ -use crate::error::Result; -use codec::Decode; -use itc_parentchain::primitives::ParentchainInitParams; +use crate::{ + error::Result, + initialization::{ + global_components::{ + GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, + }, + parentchain::{ + target_a_parachain::TargetAParachainHandler, + target_a_solochain::TargetASolochainHandler, + }, + }, +}; +use codec::{Decode, Encode}; +use integritee_parachain::IntegriteeParachainHandler; +use integritee_solochain::IntegriteeSolochainHandler; +use itc_parentchain::{ + light_client::{concurrent_access::ValidatorAccess, LightClientState}, + primitives::{ParentchainId, ParentchainInitParams}, +}; +use itp_component_container::ComponentInitializer; use itp_settings::worker_mode::ProvideWorkerMode; -use parachain::FullParachainHandler; -use solochain::FullSolochainHandler; use std::{path::PathBuf, vec::Vec}; mod common; -pub mod parachain; -pub mod solochain; +pub mod integritee_parachain; +pub mod integritee_solochain; +pub mod target_a_parachain; +pub mod target_a_solochain; pub(crate) fn init_parentchain_components( base_path: PathBuf, encoded_params: Vec, ) -> Result> { match ParentchainInitParams::decode(&mut encoded_params.as_slice())? { - ParentchainInitParams::Parachain { params } => - FullParachainHandler::init::(base_path, params), - ParentchainInitParams::Solochain { params } => - FullSolochainHandler::init::(base_path, params), + ParentchainInitParams::Parachain { id, params } => match id { + ParentchainId::Integritee => { + let handler = + IntegriteeParachainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + ParentchainId::TargetA => { + let handler = + TargetAParachainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + }, + ParentchainInitParams::Solochain { id, params } => match id { + ParentchainId::Integritee => { + let handler = + IntegriteeSolochainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + ParentchainId::TargetA => { + let handler = + TargetASolochainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + }, } } diff --git a/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs b/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs new file mode 100644 index 00000000..56bb0119 --- /dev/null +++ b/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs @@ -0,0 +1,122 @@ +/* + 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. + +*/ + +//! Naive implementation of adding a second parachain handler to the setup. +//! +//! Ideally, most of the redundant code can be abstracted away, but it turns out +//! that this is quite tedious, so for now this is a copy-past of the [IntegriteeParachainHandler]: +//! * https://github.com/integritee-network/worker/issues/1417 + +use crate::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, TargetAParentchainBlockImportDispatcher, + GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, + }, + parentchain::common::{ + create_extrinsics_factory, create_target_a_offchain_immediate_import_dispatcher, + create_target_a_parentchain_block_importer, + }, + }, +}; +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}; + +pub use itc_parentchain::primitives::{ParachainBlock, ParachainHeader, ParachainParams}; + +#[derive(Clone)] +pub struct TargetAParachainHandler { + pub genesis_header: ParachainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl TargetAParachainHandler { + 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()); + + let genesis_header = params.genesis_header.clone(); + + let light_client_seal = GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let validator = itc_parentchain::light_client::io::read_or_init_parachain_validator::< + ParachainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::TargetA)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_target_a_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + 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 => + unimplemented!("Can't run target a chain in sidechain mode yet."), + WorkerMode::Teeracle => + Arc::new(TargetAParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let parachain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(parachain_handler) + } +} diff --git a/enclave-runtime/src/initialization/parentchain/solochain.rs b/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs similarity index 65% rename from enclave-runtime/src/initialization/parentchain/solochain.rs rename to enclave-runtime/src/initialization/parentchain/target_a_solochain.rs index 87efa644..60259eed 100644 --- a/enclave-runtime/src/initialization/parentchain/solochain.rs +++ b/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs @@ -20,42 +20,41 @@ use crate::{ initialization::{ global_components::{ EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, - EnclaveParentchainBlockImportDispatcher, EnclaveStfExecutor, EnclaveValidatorAccessor, - GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_LIGHT_CLIENT_SEAL, + EnclaveStfExecutor, EnclaveValidatorAccessor, TargetAParentchainBlockImportDispatcher, GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, }, parentchain::common::{ - create_extrinsics_factory, create_offchain_immediate_import_dispatcher, - create_parentchain_block_importer, create_sidechain_triggered_import_dispatcher, + create_extrinsics_factory, create_target_a_offchain_immediate_import_dispatcher, + create_target_a_parentchain_block_importer, }, }, }; -use codec::Encode; use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; -use itp_component_container::{ComponentGetter, ComponentInitializer}; +use itp_component_container::ComponentGetter; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; -use std::{path::PathBuf, sync::Arc, vec::Vec}; +use itp_types::parentchain::ParentchainId; +use std::{path::PathBuf, sync::Arc}; pub use itc_parentchain::primitives::{SolochainBlock, SolochainHeader, SolochainParams}; -pub struct FullSolochainHandler { +pub struct TargetASolochainHandler { pub genesis_header: SolochainHeader, pub node_metadata_repository: Arc, - // FIXME: Probably should be split up into a parentchain dependent executor and one independent. pub stf_executor: Arc, pub validator_accessor: Arc, pub extrinsics_factory: Arc, - pub import_dispatcher: Arc, + pub import_dispatcher: Arc, } -impl FullSolochainHandler { +impl TargetASolochainHandler { pub fn init( _base_path: PathBuf, params: SolochainParams, - ) -> Result> { + ) -> Result { let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; - let light_client_seal = GLOBAL_LIGHT_CLIENT_SEAL.get()?; + let light_client_seal = GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); let genesis_header = params.genesis_header.clone(); @@ -64,15 +63,17 @@ impl FullSolochainHandler { SolochainBlock, EnclaveOCallApi, _, - >(params, ocall_api.clone(), &*light_client_seal)?; - let latest_header = validator.latest_finalized_header()?; + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::TargetA)?; let validator_accessor = Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; - let extrinsics_factory = - create_extrinsics_factory(genesis_hash, node_metadata_repository.clone())?; + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; let stf_executor = Arc::new(EnclaveStfExecutor::new( ocall_api, @@ -80,7 +81,7 @@ impl FullSolochainHandler { node_metadata_repository.clone(), )); - let block_importer = create_parentchain_block_importer( + let block_importer = create_target_a_parentchain_block_importer( validator_accessor.clone(), stf_executor.clone(), extrinsics_factory.clone(), @@ -88,28 +89,27 @@ impl FullSolochainHandler { )?; let import_dispatcher = match WorkerModeProvider::worker_mode() { - WorkerMode::OffChainWorker => create_offchain_immediate_import_dispatcher( + 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(block_importer), + WorkerMode::Sidechain => + unimplemented!("Can't run target a chain in sidechain mode yet."), WorkerMode::Teeracle => - Arc::new(EnclaveParentchainBlockImportDispatcher::new_empty_dispatcher()), + Arc::new(TargetAParentchainBlockImportDispatcher::new_empty_dispatcher()), }; - let solochain_handler = Arc::new(Self { + let solochain_handler = Self { genesis_header, node_metadata_repository, stf_executor, validator_accessor, extrinsics_factory, import_dispatcher, - }); - - GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT.initialize(solochain_handler); + }; - Ok(latest_header.encode()) + Ok(solochain_handler) } } diff --git a/enclave-runtime/src/lib.rs b/enclave-runtime/src/lib.rs index 750b05b9..0e9640e9 100644 --- a/enclave-runtime/src/lib.rs +++ b/enclave-runtime/src/lib.rs @@ -32,24 +32,29 @@ extern crate sgx_tstd as std; use crate::{ error::{Error, Result}, initialization::global_components::{ - GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT, GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT, - GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT, - GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + 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, }, rpc::worker_api_direct::sidechain_io_handler, utils::{ - get_node_metadata_repository_from_solo_or_parachain, - get_triggered_dispatcher_from_solo_or_parachain, utf8_str_from_raw, DecodeRaw, + get_node_metadata_repository_from_integritee_solo_or_parachain, + get_node_metadata_repository_from_target_a_solo_or_parachain, utf8_str_from_raw, DecodeRaw, }, }; use codec::Decode; -use itc_parentchain::block_import_dispatcher::{ - triggered_dispatcher::TriggerParentchainBlockImport, DispatchBlockImport, +use itc_parentchain::{ + block_import_dispatcher::{ + triggered_dispatcher::TriggerParentchainBlockImport, DispatchBlockImport, + }, + primitives::ParentchainId, }; use itp_component_container::ComponentGetter; use itp_import_queue::PushToQueue; use itp_node_api::metadata::NodeMetadata; -use itp_nonce_cache::{MutateNonce, Nonce, GLOBAL_NONCE_CACHE}; +use itp_nonce_cache::{MutateNonce, Nonce}; use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; use itp_sgx_crypto::key_repository::AccessPubkey; use itp_storage::{StorageProof, StorageProofChecker}; @@ -211,18 +216,33 @@ pub unsafe extern "C" fn get_ecc_signing_pubkey(pubkey: *mut u8, pubkey_size: u3 } #[no_mangle] -pub unsafe extern "C" fn set_nonce(nonce: *const u32) -> sgx_status_t { - log::info!("[Ecall Set Nonce] Setting the nonce of the enclave to: {}", *nonce); - - let mut nonce_lock = match GLOBAL_NONCE_CACHE.load_for_mutation() { - Ok(l) => l, +pub unsafe extern "C" fn set_nonce( + nonce: *const u32, + parentchain_id: *const u8, + parentchain_id_size: u32, +) -> sgx_status_t { + let id = match ParentchainId::decode_raw(parentchain_id, parentchain_id_size as usize) { Err(e) => { - error!("Failed to set nonce in enclave: {:?}", e); + error!("Failed to decode parentchain_id: {:?}", e); return sgx_status_t::SGX_ERROR_UNEXPECTED }, + Ok(m) => m, }; - *nonce_lock = Nonce(*nonce); + info!("Setting the nonce of the enclave to: {} for parentchain: {:?}", *nonce, id); + + let nonce_lock = match id { + ParentchainId::Integritee => GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE.load_for_mutation(), + ParentchainId::TargetA => GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE.load_for_mutation(), + }; + + match nonce_lock { + Ok(mut nonce_guard) => *nonce_guard = Nonce(*nonce), + Err(e) => { + error!("Failed to set {:?} parentchain nonce in enclave: {:?}", id, e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; sgx_status_t::SGX_SUCCESS } @@ -231,9 +251,18 @@ pub unsafe extern "C" fn set_nonce(nonce: *const u32) -> sgx_status_t { pub unsafe extern "C" fn set_node_metadata( node_metadata: *const u8, node_metadata_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, ) -> sgx_status_t { - let mut node_metadata_slice = slice::from_raw_parts(node_metadata, node_metadata_size as usize); - let metadata = match NodeMetadata::decode(&mut node_metadata_slice).map_err(Error::Codec) { + let id = match ParentchainId::decode_raw(parentchain_id, parentchain_id_size as usize) { + Err(e) => { + error!("Failed to decode parentchain_id: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + Ok(m) => m, + }; + + let metadata = match NodeMetadata::decode_raw(node_metadata, node_metadata_size as usize) { Err(e) => { error!("Failed to decode node metadata: {:?}", e); return sgx_status_t::SGX_ERROR_UNEXPECTED @@ -241,15 +270,22 @@ pub unsafe extern "C" fn set_node_metadata( Ok(m) => m, }; - let node_metadata_repository = match get_node_metadata_repository_from_solo_or_parachain() { - Ok(r) => r, + info!("Setting node meta data for parentchain: {:?}", id); + + let node_metadata_repository = match id { + ParentchainId::Integritee => + get_node_metadata_repository_from_integritee_solo_or_parachain(), + ParentchainId::TargetA => get_node_metadata_repository_from_target_a_solo_or_parachain(), + }; + + match node_metadata_repository { + Ok(repo) => repo.set_metadata(metadata), Err(e) => { - error!("Component get failure: {:?}", e); + error!("Could not get {:?} parentchain component: {:?}", id, e); return sgx_status_t::SGX_ERROR_UNEXPECTED }, }; - node_metadata_repository.set_metadata(metadata); info!("Successfully set the node meta data"); sgx_status_t::SGX_SUCCESS @@ -395,18 +431,40 @@ pub unsafe extern "C" fn sync_parentchain( events_to_sync_size: usize, events_proofs_to_sync: *const u8, events_proofs_to_sync_size: usize, - _nonce: *const u32, + parentchain_id: *const u8, + parentchain_id_size: u32, ) -> sgx_status_t { - let blocks_to_sync = match Vec::::decode_raw(blocks_to_sync, blocks_to_sync_size) { - Ok(blocks) => blocks, - Err(e) => return Error::Codec(e).into(), - }; + if let Err(e) = sync_parentchain_internal( + blocks_to_sync, + blocks_to_sync_size, + events_to_sync, + events_to_sync_size, + events_proofs_to_sync, + events_proofs_to_sync_size, + parentchain_id, + parentchain_id_size, + ) { + error!("Error synching parentchain: {:?}", e); + } + + sgx_status_t::SGX_SUCCESS +} +#[allow(clippy::too_many_arguments)] +unsafe fn sync_parentchain_internal( + blocks_to_sync: *const u8, + blocks_to_sync_size: usize, + events_to_sync: *const u8, + events_to_sync_size: usize, + events_proofs_to_sync: *const u8, + events_proofs_to_sync_size: usize, + parentchain_id: *const u8, + parentchain_id_size: u32, +) -> Result<()> { + let blocks_to_sync = Vec::::decode_raw(blocks_to_sync, blocks_to_sync_size)?; let events_proofs_to_sync = - match Vec::::decode_raw(events_proofs_to_sync, events_proofs_to_sync_size) { - Ok(events_proofs) => events_proofs, - Err(e) => return Error::Codec(e).into(), - }; + Vec::::decode_raw(events_proofs_to_sync, events_proofs_to_sync_size)?; + let parentchain_id = ParentchainId::decode_raw(parentchain_id, parentchain_id_size as usize)?; let blocks_to_sync_merkle_roots: Vec = blocks_to_sync.iter().map(|block| block.block.header.state_root).collect(); @@ -415,18 +473,13 @@ pub unsafe extern "C" fn sync_parentchain( return e.into() } - let events_to_sync = match Vec::>::decode_raw(events_to_sync, events_to_sync_size) { - Ok(events) => events, - Err(e) => return Error::Codec(e).into(), - }; - - if let Err(e) = - dispatch_parentchain_blocks_for_import::(blocks_to_sync, events_to_sync) - { - return e.into() - } + let events_to_sync = Vec::>::decode_raw(events_to_sync, events_to_sync_size)?; - sgx_status_t::SGX_SUCCESS + dispatch_parentchain_blocks_for_import::( + blocks_to_sync, + events_to_sync, + &parentchain_id, + ) } /// Dispatch the parentchain blocks for import. @@ -440,22 +493,34 @@ pub unsafe extern "C" fn sync_parentchain( fn dispatch_parentchain_blocks_for_import( blocks_to_sync: Vec, events_to_sync: Vec>, + id: &ParentchainId, ) -> Result<()> { if WorkerModeProvider::worker_mode() == WorkerMode::Teeracle { trace!("Not importing any parentchain blocks"); return Ok(()) } - let import_dispatcher = - if let Ok(solochain_handler) = GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT.get() { - solochain_handler.import_dispatcher.clone() - } else if let Ok(parachain_handler) = GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT.get() { - parachain_handler.import_dispatcher.clone() - } else { - return Err(Error::NoParentchainAssigned) - }; + match id { + ParentchainId::Integritee => { + if let Ok(handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import(blocks_to_sync, events_to_sync)?; + } else if let Ok(handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import(blocks_to_sync, events_to_sync)?; + } else { + return Err(Error::NoIntegriteeParentchainAssigned) + }; + }, + ParentchainId::TargetA => { + if let Ok(handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import(blocks_to_sync, events_to_sync)?; + } else if let Ok(handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import(blocks_to_sync, events_to_sync)?; + } else { + return Err(Error::NoTargetAParentchainAssigned) + }; + }, + } - import_dispatcher.dispatch_import(blocks_to_sync, events_to_sync)?; Ok(()) } @@ -502,8 +567,20 @@ fn validate_events( /// This trigger is only useful in combination with a `TriggeredDispatcher` and sidechain. In case no /// sidechain and the `ImmediateDispatcher` are used, this function is obsolete. #[no_mangle] -pub unsafe extern "C" fn trigger_parentchain_block_import() -> sgx_status_t { - match internal_trigger_parentchain_block_import() { +pub unsafe extern "C" fn trigger_parentchain_block_import( + parentchain_id: *const u8, + parentchain_id_size: u32, +) -> sgx_status_t { + let parentchain_id = + match ParentchainId::decode_raw(parentchain_id, parentchain_id_size as usize) { + Ok(id) => id, + Err(e) => { + error!("Could not decode parentchain id: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + match internal_trigger_parentchain_block_import(&parentchain_id) { Ok(()) => sgx_status_t::SGX_SUCCESS, Err(e) => { error!("Failed to trigger import of parentchain blocks: {:?}", e); @@ -512,9 +589,44 @@ pub unsafe extern "C" fn trigger_parentchain_block_import() -> sgx_status_t { } } -fn internal_trigger_parentchain_block_import() -> Result<()> { - let triggered_import_dispatcher = get_triggered_dispatcher_from_solo_or_parachain()?; - triggered_import_dispatcher.import_all()?; +fn internal_trigger_parentchain_block_import(id: &ParentchainId) -> Result<()> { + let _maybe_latest_block = match id { + ParentchainId::Integritee => { + if let Ok(handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler + .import_dispatcher + .triggered_dispatcher() + .ok_or(Error::ExpectedTriggeredImportDispatcher)? + .import_all()? + } else if let Ok(handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + handler + .import_dispatcher + .triggered_dispatcher() + .ok_or(Error::ExpectedTriggeredImportDispatcher)? + .import_all()? + } else { + return Err(Error::NoIntegriteeParentchainAssigned) + } + }, + ParentchainId::TargetA => { + if let Ok(handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler + .import_dispatcher + .triggered_dispatcher() + .ok_or(Error::ExpectedTriggeredImportDispatcher)? + .import_all()? + } else if let Ok(handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { + handler + .import_dispatcher + .triggered_dispatcher() + .ok_or(Error::ExpectedTriggeredImportDispatcher)? + .import_all()? + } else { + return Err(Error::NoTargetAParentchainAssigned) + } + }, + }; + Ok(()) } diff --git a/enclave-runtime/src/ocall/ffi.rs b/enclave-runtime/src/ocall/ffi.rs index c79cd6c1..4db3bbbb 100644 --- a/enclave-runtime/src/ocall/ffi.rs +++ b/enclave-runtime/src/ocall/ffi.rs @@ -71,6 +71,8 @@ extern "C" { ret_val: *mut sgx_status_t, request: *const u8, req_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, response: *mut u8, resp_size: u32, ) -> sgx_status_t; @@ -109,6 +111,8 @@ extern "C" { ret_val: *mut sgx_status_t, extrinsics: *const u8, extrinsics_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, ) -> sgx_status_t; pub fn ocall_read_ipfs( diff --git a/enclave-runtime/src/ocall/on_chain_ocall.rs b/enclave-runtime/src/ocall/on_chain_ocall.rs index 913a0a7d..d79c5d55 100644 --- a/enclave-runtime/src/ocall/on_chain_ocall.rs +++ b/enclave-runtime/src/ocall/on_chain_ocall.rs @@ -19,6 +19,7 @@ use crate::ocall::{ffi, OcallApi}; use codec::{Decode, Encode}; use frame_support::ensure; +use itc_parentchain::primitives::ParentchainId; use itp_ocall_api::{EnclaveOnChainOCallApi, Result}; use itp_storage::{verify_storage_entries, Error as StorageError}; use itp_types::{storage::StorageEntryVerified, WorkerRequest, WorkerResponse, H256}; @@ -28,15 +29,22 @@ use sp_runtime::{traits::Header, OpaqueExtrinsic}; use std::vec::Vec; impl EnclaveOnChainOCallApi for OcallApi { - fn send_to_parentchain(&self, extrinsics: Vec) -> SgxResult<()> { + fn send_to_parentchain( + &self, + extrinsics: Vec, + parentchain_id: &ParentchainId, + ) -> SgxResult<()> { let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; let extrinsics_encoded = extrinsics.encode(); + let parentchain_id_encoded = parentchain_id.encode(); let res = unsafe { ffi::ocall_send_to_parentchain( &mut rt as *mut sgx_status_t, extrinsics_encoded.as_ptr(), extrinsics_encoded.len() as u32, + parentchain_id_encoded.as_ptr(), + parentchain_id_encoded.len() as u32, ) }; @@ -49,16 +57,20 @@ impl EnclaveOnChainOCallApi for OcallApi { fn worker_request( &self, req: Vec, + parentchain_id: &ParentchainId, ) -> SgxResult>> { let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; let mut resp: Vec = vec![0; 4196 * 4]; let request_encoded = req.encode(); + let parentchain_id_encoded = parentchain_id.encode(); let res = unsafe { ffi::ocall_worker_request( &mut rt as *mut sgx_status_t, request_encoded.as_ptr(), request_encoded.len() as u32, + parentchain_id_encoded.as_ptr(), + parentchain_id_encoded.len() as u32, resp.as_mut_ptr(), resp.len() as u32, ) @@ -80,11 +92,12 @@ impl EnclaveOnChainOCallApi for OcallApi { &self, storage_hash: Vec, header: &H, + parentchain_id: &ParentchainId, ) -> Result> { // the code below seems like an overkill, but it is surprisingly difficult to // get an owned value from a `Vec` without cloning. Ok(self - .get_multiple_storages_verified(vec![storage_hash], header)? + .get_multiple_storages_verified(vec![storage_hash], header, parentchain_id)? .into_iter() .next() .ok_or(StorageError::StorageValueUnavailable)?) @@ -94,6 +107,7 @@ impl EnclaveOnChainOCallApi for OcallApi { &self, storage_hashes: Vec>, header: &H, + parentchain_id: &ParentchainId, ) -> Result>> { let requests = storage_hashes .into_iter() @@ -101,7 +115,7 @@ impl EnclaveOnChainOCallApi for OcallApi { .collect(); let storage_entries = self - .worker_request::>(requests) + .worker_request::>(requests, parentchain_id) .map(|storages| verify_storage_entries(storages, header))??; Ok(storage_entries) diff --git a/enclave-runtime/src/teeracle/mod.rs b/enclave-runtime/src/teeracle/mod.rs index 9436cb1a..460357fc 100644 --- a/enclave-runtime/src/teeracle/mod.rs +++ b/enclave-runtime/src/teeracle/mod.rs @@ -20,7 +20,7 @@ use crate::{ initialization::global_components::GLOBAL_OCALL_API_COMPONENT, utils::{ get_extrinsic_factory_from_solo_or_parachain, - get_node_metadata_repository_from_solo_or_parachain, + get_node_metadata_repository_from_integritee_solo_or_parachain, }, }; use codec::{Decode, Encode}; @@ -82,7 +82,8 @@ where println!("Update the longitude: {}, for source {}", longitude, source_base_url); - let node_metadata_repository = get_node_metadata_repository_from_solo_or_parachain()?; + 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()) @@ -247,7 +248,8 @@ where source_base_url, ); - let node_metadata_repository = get_node_metadata_repository_from_solo_or_parachain()?; + 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()) diff --git a/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs b/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs index 1621a206..ec543b17 100644 --- a/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs +++ b/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs @@ -18,6 +18,7 @@ use crate::test::mocks::types::TestBlockImporter; use codec::{Decode, Encode}; +use itc_parentchain::primitives::ParentchainId; use itp_ocall_api::{EnclaveOnChainOCallApi, EnclaveSidechainOCallApi, Result}; use itp_types::{ storage::StorageEntryVerified, BlockHash, Header as ParentchainHeader, ShardIdentifier, @@ -47,13 +48,18 @@ impl ProposeToImportOCallApi { } impl EnclaveOnChainOCallApi for ProposeToImportOCallApi { - fn send_to_parentchain(&self, _extrinsics: Vec) -> SgxResult<()> { + fn send_to_parentchain( + &self, + _extrinsics: Vec, + _: &ParentchainId, + ) -> SgxResult<()> { Ok(()) } fn worker_request( &self, _req: Vec, + _: &ParentchainId, ) -> SgxResult>> { todo!() } @@ -62,6 +68,7 @@ impl EnclaveOnChainOCallApi for ProposeToImportOCallApi { &self, _storage_hash: Vec, _header: &H, + _: &ParentchainId, ) -> Result> { todo!() } @@ -70,6 +77,7 @@ impl EnclaveOnChainOCallApi for ProposeToImportOCallApi { &self, _storage_hashes: Vec>, _header: &H, + _: &ParentchainId, ) -> Result>> { todo!() } diff --git a/enclave-runtime/src/test/mod.rs b/enclave-runtime/src/test/mod.rs index a78d648b..6f3d7a25 100644 --- a/enclave-runtime/src/test/mod.rs +++ b/enclave-runtime/src/test/mod.rs @@ -24,7 +24,6 @@ pub mod evm_pallet_tests; pub mod fixtures; pub mod ipfs_tests; pub mod mocks; -pub mod on_chain_ocall_tests; pub mod sidechain_aura_tests; pub mod sidechain_event_tests; mod state_getter_tests; diff --git a/enclave-runtime/src/test/on_chain_ocall_tests.rs b/enclave-runtime/src/test/on_chain_ocall_tests.rs deleted file mode 100644 index bd5ad115..00000000 --- a/enclave-runtime/src/test/on_chain_ocall_tests.rs +++ /dev/null @@ -1,46 +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::OcallApi; -use itp_node_api::api_client::storage_key; -use itp_ocall_api::EnclaveOnChainOCallApi; -use itp_types::{WorkerRequest, WorkerResponse}; -use log::*; -use std::vec::Vec; - -#[allow(unused)] -fn test_ocall_worker_request() { - info!("testing ocall_worker_request. Hopefully integritee-node is running..."); - let requests = - vec![WorkerRequest::ChainStorage(storage_key("Balances", "TotalIssuance").0, None)]; - - let mut resp: Vec>> = match OcallApi.worker_request(requests) { - Ok(response) => response, - Err(e) => panic!("Worker response decode failed. Error: {:?}", e), - }; - - let first = resp.pop().unwrap(); - info!("Worker response: {:?}", first); - - let (total_issuance, proof) = match first { - WorkerResponse::ChainStorage(_storage_key, value, proof) => (value, proof), - }; - - info!("Total Issuance is: {:?}", total_issuance); - info!("Proof: {:?}", proof) -} diff --git a/enclave-runtime/src/test/tests_main.rs b/enclave-runtime/src/test/tests_main.rs index db3b3b91..3d48b8fb 100644 --- a/enclave-runtime/src/test/tests_main.rs +++ b/enclave-runtime/src/test/tests_main.rs @@ -102,8 +102,6 @@ pub extern "C" fn test_main_entrance() -> size_t { test_submit_trusted_getter_to_top_pool, test_differentiate_getter_and_call_works, test_create_block_and_confirmation_works, - // needs node to be running.. unit tests? - // test_ocall_worker_request, test_create_state_diff, test_executing_call_updates_account_nonce, test_call_set_update_parentchain_block, diff --git a/enclave-runtime/src/tls_ra/tls_ra_client.rs b/enclave-runtime/src/tls_ra/tls_ra_client.rs index 9eb1546b..630f8877 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_client.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_client.rs @@ -22,8 +22,8 @@ use crate::{ attestation::create_ra_report_and_signature, error::{Error as EnclaveError, Result as EnclaveResult}, initialization::global_components::{ - EnclaveSealHandler, GLOBAL_LIGHT_CLIENT_SEAL, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, - GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, + EnclaveSealHandler, GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, }, ocall::OcallApi, tls_ra::seal_handler::SealStateAndKeys, @@ -193,7 +193,7 @@ pub unsafe extern "C" fn request_state_provisioning( }, }; - let light_client_seal = match GLOBAL_LIGHT_CLIENT_SEAL.get() { + let light_client_seal = match GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.get() { Ok(s) => s, Err(e) => { error!("{:?}", e); diff --git a/enclave-runtime/src/tls_ra/tls_ra_server.rs b/enclave-runtime/src/tls_ra/tls_ra_server.rs index 836b146b..e47ca50e 100644 --- a/enclave-runtime/src/tls_ra/tls_ra_server.rs +++ b/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -22,8 +22,8 @@ use crate::{ attestation::create_ra_report_and_signature, error::{Error as EnclaveError, Result as EnclaveResult}, initialization::global_components::{ - EnclaveSealHandler, GLOBAL_LIGHT_CLIENT_SEAL, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, - GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, + EnclaveSealHandler, GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, }, ocall::OcallApi, tls_ra::seal_handler::UnsealStateAndKeys, @@ -198,7 +198,7 @@ pub unsafe extern "C" fn run_state_provisioning_server( }, }; - let light_client_seal = match GLOBAL_LIGHT_CLIENT_SEAL.get() { + let light_client_seal = match GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.get() { Ok(s) => s, Err(e) => { error!("{:?}", e); diff --git a/enclave-runtime/src/utils.rs b/enclave-runtime/src/utils.rs index 31310d78..3b3fac38 100644 --- a/enclave-runtime/src/utils.rs +++ b/enclave-runtime/src/utils.rs @@ -17,10 +17,12 @@ use crate::{ error::{Error, Result}, initialization::global_components::{ - EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, - EnclaveParentchainBlockImportDispatcher, EnclaveStfExecutor, - EnclaveTriggeredParentchainBlockImportDispatcher, EnclaveValidatorAccessor, - GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT, GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT, + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveStfExecutor, + EnclaveValidatorAccessor, IntegriteeParentchainBlockImportDispatcher, + IntegriteeParentchainTriggeredBlockImportDispatcher, + GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, }, }; use codec::{Decode, Input}; @@ -71,20 +73,21 @@ pub unsafe fn utf8_str_from_raw<'a>( // FIXME: When solving #1080, these helper functions should be obsolete, because no dynamic allocation // is necessary anymore. pub(crate) fn get_triggered_dispatcher_from_solo_or_parachain( -) -> Result> { - let dispatcher = if let Ok(solochain_handler) = GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT.get() { - get_triggered_dispatcher(solochain_handler.import_dispatcher.clone())? - } else if let Ok(parachain_handler) = GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT.get() { - get_triggered_dispatcher(parachain_handler.import_dispatcher.clone())? - } else { - return Err(Error::NoParentchainAssigned) - }; +) -> 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::NoIntegriteeParentchainAssigned) + }; Ok(dispatcher) } pub(crate) fn get_triggered_dispatcher( - dispatcher: Arc, -) -> Result> { + dispatcher: Arc, +) -> Result> { let triggered_dispatcher = dispatcher .triggered_dispatcher() .ok_or(Error::ExpectedTriggeredImportDispatcher)?; @@ -94,25 +97,38 @@ pub(crate) fn get_triggered_dispatcher( pub(crate) fn get_validator_accessor_from_solo_or_parachain( ) -> Result> { let validator_accessor = - if let Ok(solochain_handler) = GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT.get() { + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { solochain_handler.validator_accessor.clone() - } else if let Ok(parachain_handler) = GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT.get() { + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { parachain_handler.validator_accessor.clone() } else { - return Err(Error::NoParentchainAssigned) + return Err(Error::NoIntegriteeParentchainAssigned) }; Ok(validator_accessor) } -pub(crate) fn get_node_metadata_repository_from_solo_or_parachain( +pub(crate) fn get_node_metadata_repository_from_integritee_solo_or_parachain( +) -> Result> { + let metadata_repository = + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.node_metadata_repository.clone() + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.node_metadata_repository.clone() + } else { + return Err(Error::NoIntegriteeParentchainAssigned) + }; + Ok(metadata_repository) +} + +pub(crate) fn get_node_metadata_repository_from_target_a_solo_or_parachain( ) -> Result> { let metadata_repository = - if let Ok(solochain_handler) = GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT.get() { + if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { solochain_handler.node_metadata_repository.clone() - } else if let Ok(parachain_handler) = GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT.get() { + } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { parachain_handler.node_metadata_repository.clone() } else { - return Err(Error::NoParentchainAssigned) + return Err(Error::NoTargetAParentchainAssigned) }; Ok(metadata_repository) } @@ -120,24 +136,24 @@ pub(crate) fn get_node_metadata_repository_from_solo_or_parachain( pub(crate) fn get_extrinsic_factory_from_solo_or_parachain() -> Result> { let extrinsics_factory = - if let Ok(solochain_handler) = GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT.get() { + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { solochain_handler.extrinsics_factory.clone() - } else if let Ok(parachain_handler) = GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT.get() { + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { parachain_handler.extrinsics_factory.clone() } else { - return Err(Error::NoParentchainAssigned) + return Err(Error::NoIntegriteeParentchainAssigned) }; Ok(extrinsics_factory) } pub(crate) fn get_stf_executor_from_solo_or_parachain() -> Result> { - let stf_executor = if let Ok(solochain_handler) = GLOBAL_FULL_SOLOCHAIN_HANDLER_COMPONENT.get() - { - solochain_handler.stf_executor.clone() - } else if let Ok(parachain_handler) = GLOBAL_FULL_PARACHAIN_HANDLER_COMPONENT.get() { - parachain_handler.stf_executor.clone() - } else { - return Err(Error::NoParentchainAssigned) - }; + 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::NoIntegriteeParentchainAssigned) + }; Ok(stf_executor) } diff --git a/local-setup/config/benchmark.json b/local-setup/config/benchmark.json index 38caa599..f997396e 100644 --- a/local-setup/config/benchmark.json +++ b/local-setup/config/benchmark.json @@ -1,20 +1,23 @@ { - "node": { - "bin": "../integritee-node/target/release/integritee-node", - "flags": [ - "--tmp", - "--dev", - "-lruntime=info", - "--ws-port", - "9930", - "--port", - "30330", - "--rpc-port", - "8930", - "--ws-external", - "--rpc-external" - ] - }, + "nodes": [ + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--dev", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9944", + "--port", + "30390", + "--rpc-port", + "9933", + "--ws-external", + "--rpc-external" + ] + } + ], "workers": [ { "source": "bin", diff --git a/local-setup/config/one-worker.json b/local-setup/config/one-worker.json index 477c9c85..dae71259 100644 --- a/local-setup/config/one-worker.json +++ b/local-setup/config/one-worker.json @@ -1,20 +1,23 @@ { - "node": { - "bin": "../integritee-node/target/release/integritee-node", - "flags": [ - "--tmp", - "--dev", - "-lruntime=info", - "--ws-port", - "9944", - "--port", - "30390", - "--rpc-port", - "9933", - "--ws-external", - "--rpc-external" - ] - }, + "nodes": [ + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--dev", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9944", + "--port", + "30390", + "--rpc-port", + "9933", + "--ws-external", + "--rpc-external" + ] + } + ], "workers": [ { "source": "bin", diff --git a/local-setup/config/two-nodes-one-worker.json b/local-setup/config/two-nodes-one-worker.json new file mode 100644 index 00000000..21508ce4 --- /dev/null +++ b/local-setup/config/two-nodes-one-worker.json @@ -0,0 +1,70 @@ +{ + "nodes": [ + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--dev", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9944", + "--port", + "30390", + "--rpc-port", + "9933", + "--ws-external", + "--rpc-external" + ] + }, + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--chain", + "dev2", + "--force-authoring", + "--alice", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9966", + "--port", + "30395", + "--rpc-port", + "9955", + "--ws-external", + "--rpc-external" + ] + } + ], + "workers": [ + { + "source": "bin", + "flags": [ + "--clean-reset", + "-P", + "2000", + "-p", + "9944", + "--target-a-parentchain-rpc-url", + "ws://127.0.0.1", + "--target-a-parentchain-rpc-port", + "9966", + "-r", + "3490", + "-w", + "2001", + "-h", + "4545", + "--ws-external", + "--data-dir", + "/tmp/data-dir" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev" + ] + } + ] +} diff --git a/local-setup/config/two-workers.json b/local-setup/config/two-workers.json index 6d5e2316..dc9fe7cf 100644 --- a/local-setup/config/two-workers.json +++ b/local-setup/config/two-workers.json @@ -1,20 +1,23 @@ { - "node": { - "bin": "../integritee-node/target/release/integritee-node", - "flags": [ - "--tmp", - "--dev", - "-lruntime=info", - "--ws-port", - "9944", - "--port", - "30390", - "--rpc-port", - "9933", - "--ws-external", - "--rpc-external" - ] - }, + "nodes": [ + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--dev", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9944", + "--port", + "30390", + "--rpc-port", + "9933", + "--ws-external", + "--rpc-external" + ] + } + ], "workers": [ { "source": "bin", diff --git a/local-setup/launch.py b/local-setup/launch.py index 36bdd669..07192973 100755 --- a/local-setup/launch.py +++ b/local-setup/launch.py @@ -21,8 +21,6 @@ log_dir = 'log' mkdir_p(log_dir) -node_log = open(f'{log_dir}/node.log', 'w+') - def setup_worker(work_dir: str, source_dir: str, std_err: Union[None, int, IO]): print(f'Setting up worker in {work_dir}') @@ -33,9 +31,10 @@ def setup_worker(work_dir: str, source_dir: str, std_err: Union[None, int, IO]): return worker -def run_node(config): - node_cmd = [config["node"]["bin"]] + config["node"]["flags"] - print(f'Run node with command: {node_cmd}') +def run_node(config, i: int): + node_log = open(f'{log_dir}/node{i}.log', 'w+') + node_cmd = [config["bin"]] + config["flags"] + print(f'Run node {i} with command: {node_cmd}') return Popen(node_cmd, stdout=node_log, stderr=STDOUT, bufsize=1) @@ -53,9 +52,16 @@ def main(processes, config_path): with open(config_path) as config_file: config = json.load(config_file) - processes.append(run_node(config)) + n = 1 + for n_conf in config["nodes"]: + processes.append(run_node(n_conf, n)) + n += 1 + # let the first node begin before we start the second one, it is + # easier to track the logs if they don't start at the same time. + sleep(18) + # sleep to give the node some time to startup - sleep(3) + sleep(5) i = 1 for w_conf in config["workers"]: diff --git a/local-setup/py/worker.py b/local-setup/py/worker.py index e9bf284e..00a94d59 100644 --- a/local-setup/py/worker.py +++ b/local-setup/py/worker.py @@ -162,6 +162,7 @@ def run_in_background(self, log_file: TextIO, flags: [str] = None, subcommand_fl 'itp_stf_state_handler=debug,' 'its_consensus_common=debug,' 'its_consensus_aura=trace,' + 'itc_parentchain_indirect_calls_executor=trace,' 'itc_parentchain_block_importer=debug,' 'ita_stf=debug') worker_cmd = self._assemble_cmd(flags=flags, subcommand_flags=subcommand_flags) diff --git a/local-setup/tmux_logger_two_nodes.sh b/local-setup/tmux_logger_two_nodes.sh new file mode 100755 index 00000000..e1666b9b --- /dev/null +++ b/local-setup/tmux_logger_two_nodes.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# script that setups a tmux session with three panes that attach to the log files +# of the node and the two workers launched by `./launch.py` + +################################################################################# +# If you work with docker: +# +# 1. run: ./launch.py in docker +# 2. open a new bash session in a new window in the running container: +# docker exec -it [container-id] bash +# 3. run this script: ./tmux_logger.sh +################################################################################# + + +if tmux has-session -t integritee_logger_two_nodes ; then + echo "detected existing polkadot logger session, attaching..." +else + # or start it up freshly + tmux new-session -d -s integritee_logger_two_nodes \; \ + split-window -v \; \ + split-window -v \; \ + select-layout even-vertical \; \ + send-keys -t integritee_logger_two_nodes:0.0 'tail -f ../log/node1.log' C-m \; \ + send-keys -t integritee_logger_two_nodes:0.1 'tail -f ../log/node2.log' C-m \; \ + send-keys -t integritee_logger_two_nodes:0.2 'tail -f ../log/worker1.log' C-m \; \ + + # Attention: Depending on your tmux conf, indexes may start at 1 + + tmux setw -g mouse on +fi +tmux attach-session -d -t integritee_logger_two_nodes \ No newline at end of file diff --git a/service/src/cli.yml b/service/src/cli.yml index 2faedcf9..98ecfe4b 100644 --- a/service/src/cli.yml +++ b/service/src/cli.yml @@ -12,18 +12,28 @@ settings: # the list is the name of the subcommand, and all settings for that command are # part of a Hash args: - - node-server: + - integritee-rpc-url: short: u - long: node-url - help: Set the node server protocol and IP address + long: integritee-rpc-url + help: Set the url and the protocol of the Integritee RPC endpoint. takes_value: true default_value: "ws://127.0.0.1" - - node-port: + - integritee-rpc-port: short: p - long: node-port - help: Set the websocket port to listen for substrate events + long: integritee-rpc-port + help: Set the port of the Integritee RPC endpoint. takes_value: true default_value: "9944" + - target-a-parentchain-rpc-url: + long: target-a-parentchain-rpc-url + help: Set the url and the protocol of an optional Target A parentchain RPC endpoint that contains your business logic specific pallets. + takes_value: true + required: false + - target-a-parentchain-rpc-port: + long: target-a-parentchain-rpc-port + help: Set the port of the optional Target A parentchain RPC endpoint. + takes_value: true + required: false - data-dir: short: d long: data-dir diff --git a/service/src/config.rs b/service/src/config.rs index 4b441b17..87050742 100644 --- a/service/src/config.rs +++ b/service/src/config.rs @@ -26,8 +26,8 @@ use std::{ time::Duration, }; -static DEFAULT_NODE_SERVER: &str = "ws://127.0.0.1"; -static DEFAULT_NODE_PORT: &str = "9944"; +static DEFAULT_INTEGRITEE_RPC_URL: &str = "ws://127.0.0.1"; +static DEFAULT_INTEGRITEE_RPC_PORT: &str = "9944"; static DEFAULT_TRUSTED_PORT: &str = "2000"; static DEFAULT_UNTRUSTED_PORT: &str = "2001"; static DEFAULT_MU_RA_PORT: &str = "3443"; @@ -36,8 +36,10 @@ static DEFAULT_UNTRUSTED_HTTP_PORT: &str = "4545"; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Config { - node_ip: String, - node_port: String, + integritee_rpc_url: String, + integritee_rpc_port: String, + target_a_parentchain_rpc_url: Option, + target_a_parentchain_rpc_port: Option, worker_ip: String, /// Trusted worker address that will be advertised on the parentchain. trusted_external_worker_address: Option, @@ -66,8 +68,10 @@ pub struct Config { #[allow(clippy::too_many_arguments)] impl Config { pub fn new( - node_ip: String, - node_port: String, + integritee_rpc_url: String, + integritee_rpc_port: String, + target_a_parentchain_rpc_url: Option, + target_a_parentchain_rpc_port: Option, worker_ip: String, trusted_external_worker_address: Option, trusted_worker_port: String, @@ -82,8 +86,10 @@ impl Config { run_config: Option, ) -> Self { Self { - node_ip, - node_port, + integritee_rpc_url, + integritee_rpc_port, + target_a_parentchain_rpc_url, + target_a_parentchain_rpc_port, worker_ip, trusted_external_worker_address, trusted_worker_port, @@ -99,9 +105,24 @@ impl Config { } } - /// Returns the client url of the node (including ws://). - pub fn node_url(&self) -> String { - format!("{}:{}", self.node_ip, self.node_port) + /// Integritee RPC endpoint (including ws://). + pub fn integritee_rpc_endpoint(&self) -> String { + format!("{}:{}", self.integritee_rpc_url, self.integritee_rpc_port) + } + + pub fn target_a_parentchain_rpc_endpoint(&self) -> Option { + if self.target_a_parentchain_rpc_url.is_some() + && self.target_a_parentchain_rpc_port.is_some() + { + return Some(format!( + "{}:{}", + // Can be done better, but this code is obsolete anyhow with clap v4. + self.target_a_parentchain_rpc_url.clone().unwrap(), + self.target_a_parentchain_rpc_port.clone().unwrap() + )) + }; + + None } pub fn trusted_worker_url_internal(&self) -> String { @@ -192,8 +213,10 @@ impl From<&ArgMatches<'_>> for Config { let run_config = m.subcommand_matches("run").map(RunConfig::from); Self::new( - m.value_of("node-server").unwrap_or(DEFAULT_NODE_SERVER).into(), - m.value_of("node-port").unwrap_or(DEFAULT_NODE_PORT).into(), + m.value_of("integritee-rpc-url").unwrap_or(DEFAULT_INTEGRITEE_RPC_URL).into(), + m.value_of("integritee-rpc-port").unwrap_or(DEFAULT_INTEGRITEE_RPC_PORT).into(), + m.value_of("target-a-parentchain-rpc-url").map(Into::into), + m.value_of("target-a-parentchain-rpc-port").map(Into::into), if m.is_present("ws-external") { "0.0.0.0".into() } else { "127.0.0.1".into() }, m.value_of("trusted-external-address") .map(|url| add_port_if_necessary(url, trusted_port)), @@ -333,8 +356,10 @@ mod test { let config = Config::from(&empty_args); let expected_worker_ip = "127.0.0.1"; - assert_eq!(config.node_ip, DEFAULT_NODE_SERVER); - assert_eq!(config.node_port, DEFAULT_NODE_PORT); + assert_eq!(config.integritee_rpc_url, DEFAULT_INTEGRITEE_RPC_URL); + assert_eq!(config.integritee_rpc_port, DEFAULT_INTEGRITEE_RPC_PORT); + assert_eq!(config.target_a_parentchain_rpc_url, None); + assert_eq!(config.target_a_parentchain_rpc_port, None); assert_eq!(config.trusted_worker_port, DEFAULT_TRUSTED_PORT); assert_eq!(config.untrusted_worker_port, DEFAULT_UNTRUSTED_PORT); assert_eq!(config.mu_ra_port, DEFAULT_MU_RA_PORT); @@ -349,7 +374,7 @@ mod test { } #[test] - fn worker_ip_is_set_correcty_for_set_ws_external_flag() { + fn worker_ip_is_set_correctly_for_set_ws_external_flag() { let expected_worker_ip = "0.0.0.0"; let mut args = ArgMatches::default(); @@ -373,8 +398,8 @@ mod test { let mut args = ArgMatches::default(); args.args = HashMap::from([ - ("node-server", Default::default()), - ("node-port", Default::default()), + ("integritee-rpc-url", Default::default()), + ("integritee-rpc-port", Default::default()), ("ws-external", Default::default()), ("trusted-external-address", Default::default()), ("untrusted-external-address", Default::default()), @@ -385,8 +410,8 @@ mod test { ("untrusted-http-port", Default::default()), ]); // Workaround because MatchedArg is private. - args.args.get_mut("node-server").unwrap().vals = vec![node_ip.into()]; - args.args.get_mut("node-port").unwrap().vals = vec![node_port.into()]; + args.args.get_mut("integritee-rpc-url").unwrap().vals = vec![node_ip.into()]; + args.args.get_mut("integritee-rpc-port").unwrap().vals = vec![node_port.into()]; args.args.get_mut("trusted-external-address").unwrap().vals = vec![trusted_ext_addr.into()]; args.args.get_mut("untrusted-external-address").unwrap().vals = vec![untrusted_ext_addr.into()]; @@ -398,8 +423,8 @@ mod test { let config = Config::from(&args); - assert_eq!(config.node_ip, node_ip); - assert_eq!(config.node_port, node_port); + assert_eq!(config.integritee_rpc_url, node_ip); + assert_eq!(config.integritee_rpc_port, node_port); assert_eq!(config.trusted_worker_port, trusted_port); assert_eq!(config.untrusted_worker_port, untrusted_port); assert_eq!(config.mu_ra_port, mu_ra_port); diff --git a/service/src/main.rs b/service/src/main.rs index 25a83777..d8e17449 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -71,6 +71,7 @@ use its_storage::{interface::FetchBlocks, BlockPruner, SidechainStorageLock}; use log::*; use my_node_runtime::{Hash, Header, RuntimeEvent}; use sgx_types::*; +use sp_runtime::traits::Header as HeaderT; use substrate_api_client::{ api::XtStatus, rpc::HandleSubscription, GetHeader, SubmitAndWatch, SubscribeChain, SubscribeEvents, @@ -81,6 +82,7 @@ use teerex_primitives::AnySigner; use sgx_verify::extract_tcb_info_from_raw_dcap_quote; use enclave_bridge_primitives::ShardIdentifier; +use itc_parentchain::primitives::ParentchainId; use sp_core::crypto::{AccountId32, Ss58Codec}; use sp_keyring::AccountKeyring; use sp_runtime::MultiSigner; @@ -145,8 +147,10 @@ fn main() { ) .unwrap(), ); - let node_api_factory = - Arc::new(NodeApiFactory::new(config.node_url(), AccountKeyring::Alice.pair())); + let node_api_factory = Arc::new(NodeApiFactory::new( + config.integritee_rpc_endpoint(), + AccountKeyring::Alice.pair(), + )); let enclave = Arc::new(enclave_init(&config).unwrap()); let initialization_handler = Arc::new(InitializationHandler::default()); let worker = Arc::new(EnclaveWorker::new( @@ -164,9 +168,14 @@ fn main() { Arc::new(BlockFetcher::::new(untrusted_peer_fetcher)); let enclave_metrics_receiver = Arc::new(EnclaveMetricsReceiver {}); + let maybe_target_a_parentchain_api_factory = config + .target_a_parentchain_rpc_endpoint() + .map(|url| Arc::new(NodeApiFactory::new(url, AccountKeyring::Alice.pair()))); + // initialize o-call bridge with a concrete factory implementation OCallBridge::initialize(Arc::new(OCallBridgeComponentFactory::new( node_api_factory.clone(), + maybe_target_a_parentchain_api_factory, sync_block_broadcaster, enclave.clone(), sidechain_blockstorage.clone(), @@ -295,7 +304,7 @@ fn start_worker( shard: &ShardIdentifier, enclave: Arc, sidechain_storage: Arc, - node_api: ParentchainApi, + integritee_rpc_api: ParentchainApi, tokio_handle_getter: Arc, initialization_handler: Arc, quoting_enclave_target_info: Option, @@ -399,8 +408,10 @@ fn start_worker( // ------------------------------------------------------------------------ // Start prometheus metrics server. if config.enable_metrics_server() { - let enclave_wallet = - Arc::new(EnclaveAccountInfoProvider::new(node_api.clone(), tee_accountid.clone())); + let enclave_wallet = Arc::new(EnclaveAccountInfoProvider::new( + integritee_rpc_api.clone(), + tee_accountid.clone(), + )); let metrics_handler = Arc::new(MetricsHandler::new(enclave_wallet)); let metrics_server_port = config .try_parse_metrics_server_port() @@ -445,39 +456,24 @@ fn start_worker( // ------------------------------------------------------------------------ // Init parentchain specific stuff. Needed for parentchain communication. - let parentchain_handler = Arc::new( - ParentchainHandler::new_with_automatic_light_client_allocation( - node_api.clone(), - enclave.clone(), - ) - .unwrap(), - ); - let last_synced_header = parentchain_handler.init_parentchain_components().unwrap(); - trace!("last synched parentchain block: {}", last_synced_header.number); - let nonce = node_api.get_nonce_of(&tee_accountid).unwrap(); - info!("Enclave nonce = {:?}", nonce); - enclave - .set_nonce(nonce) - .expect("Could not set nonce of enclave. Returning here..."); - - let metadata = node_api.metadata().clone(); - let runtime_spec_version = node_api.runtime_version().spec_version; - let runtime_transaction_version = node_api.runtime_version().transaction_version; - enclave - .set_node_metadata( - NodeMetadata::new(metadata, runtime_spec_version, runtime_transaction_version).encode(), - ) - .expect("Could not set the node metadata in the enclave"); + let (parentchain_handler, last_synced_header) = + init_parentchain(&enclave, &integritee_rpc_api, &tee_accountid, ParentchainId::Integritee); #[cfg(feature = "dcap")] - register_collateral(&node_api, &*enclave, &tee_accountid, is_development_mode, skip_ra); + register_collateral( + &integritee_rpc_api, + &*enclave, + &tee_accountid, + is_development_mode, + skip_ra, + ); let trusted_url = config.trusted_worker_url_external(); #[cfg(feature = "attesteer")] fetch_marblerun_events_every_hour( - node_api.clone(), + integritee_rpc_api.clone(), enclave.clone(), tee_accountid.clone(), is_development_mode, @@ -496,16 +492,17 @@ fn start_worker( println!("[!] creating remote attestation report and create enclave register extrinsic."); }; - // clones because of the move - let enclave2 = enclave.clone(); - let node_api2 = node_api.clone(); #[cfg(feature = "dcap")] - enclave2.set_sgx_qpl_logging().expect("QPL logging setup failed"); + enclave.set_sgx_qpl_logging().expect("QPL logging setup failed"); + + let enclave2 = enclave.clone(); #[cfg(not(feature = "dcap"))] let register_xt = move || enclave2.generate_ias_ra_extrinsic(&trusted_url, skip_ra).unwrap(); #[cfg(feature = "dcap")] let register_xt = move || enclave2.generate_dcap_ra_extrinsic(&trusted_url, skip_ra).unwrap(); + // clones because of the move + let node_api2 = integritee_rpc_api.clone(); let tee_accountid_clone = tee_accountid.clone(); let send_register_xt = move || { println!("[+] Send register enclave extrinsic"); @@ -514,11 +511,19 @@ fn start_worker( let register_enclave_block_hash = send_register_xt().unwrap(); - let register_enclave_xt_header = - node_api.get_header(Some(register_enclave_block_hash)).unwrap().unwrap(); + let register_enclave_xt_header = integritee_rpc_api + .get_header(Some(register_enclave_block_hash)) + .unwrap() + .unwrap(); + + println!( + "[+] Enclave registered at block number: {:?}, hash: {:?}", + register_enclave_xt_header.number(), + register_enclave_xt_header.hash() + ); let we_are_primary_validateer = - we_are_primary_worker(&node_api, shard, &tee_accountid).unwrap(); + we_are_primary_worker(&integritee_rpc_api, shard, &tee_accountid).unwrap(); if we_are_primary_validateer { println!("[+] We are the primary worker"); @@ -538,7 +543,7 @@ fn start_worker( ); start_periodic_market_update( - &node_api, + &integritee_rpc_api, run_config.teeracle_update_interval(), enclave.as_ref(), &teeracle_tokio_handle, @@ -546,7 +551,7 @@ fn start_worker( } if WorkerModeProvider::worker_mode() != WorkerMode::Teeracle { - println!("*** [+] Finished syncing light client, syncing parentchain..."); + println!("*** [+] Finished initializing light client, syncing parentchain..."); // Syncing all parentchain blocks, this might take a while.. let mut last_synced_header = @@ -556,7 +561,7 @@ fn start_worker( // Initialize the sidechain if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain { last_synced_header = sidechain_init_block_production( - enclave, + enclave.clone(), ®ister_enclave_xt_header, we_are_primary_validateer, parentchain_handler.clone(), @@ -583,13 +588,17 @@ fn start_worker( // ------------------------------------------------------------------------ if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain { - spawn_worker_for_shard_polling(shard, node_api.clone(), initialization_handler); + spawn_worker_for_shard_polling(shard, integritee_rpc_api.clone(), initialization_handler); + } + + if let Some(url) = config.target_a_parentchain_rpc_endpoint() { + init_target_a_parentchain(&enclave, &tee_accountid, url, is_development_mode) } // ------------------------------------------------------------------------ // Subscribe to events and print them. println!("*** Subscribing to events"); - let mut subscription = node_api.subscribe_events().unwrap(); + let mut subscription = integritee_rpc_api.subscribe_events().unwrap(); println!("[+] Subscribed to events. waiting..."); loop { if let Some(Ok(events)) = subscription.next_event::() { @@ -598,6 +607,99 @@ fn start_worker( } } +fn init_target_a_parentchain( + enclave: &Arc, + tee_account_id: &AccountId32, + url: String, + is_development_mode: bool, +) where + E: EnclaveBase + Sidechain, +{ + let node_api = NodeApiFactory::new(url, AccountKeyring::Alice.pair()) + .create_api() + .expect("Failed to create Target A parentchain node API"); + + // some random bytes not too small to ensure that the enclave has enough funds + setup_account_funding(&node_api, tee_account_id, [0u8; 100].into(), is_development_mode) + .expect("Could not fund Target A parentchain enclave account"); + + let (parentchain_handler, last_synched_header) = + init_parentchain(enclave, &node_api, tee_account_id, ParentchainId::TargetA); + + if WorkerModeProvider::worker_mode() != WorkerMode::Teeracle { + println!("*** [+] Finished initializing Target A parentchain light client, syncing parentchain..."); + + // Syncing all parentchain blocks, this might take a while.. + let last_synched_header = + parentchain_handler.sync_parentchain(last_synched_header).unwrap(); + + // start parentchain syncing loop (subscribe to header updates) + thread::Builder::new() + .name("target_a_parentchain_sync_loop".to_owned()) + .spawn(move || { + if let Err(e) = + subscribe_to_parentchain_new_headers(parentchain_handler, last_synched_header) + { + error!("Target A parentchain block syncing terminated with a failure: {:?}", e); + } + println!("[!] Target A parentchain block syncing has terminated"); + }) + .unwrap(); + } + + // Subscribe to events and print them. + println!("*** Subscribing to events of Target A chain"); + let mut subscription = node_api.subscribe_events().unwrap(); + println!("[+] Subscribed to events. waiting..."); + + thread::Builder::new() + .name("target_a_parentchain_event_subscription".to_owned()) + .spawn(move || loop { + if let Some(Ok(events)) = subscription.next_event::() { + print_events(events) + } + }) + .unwrap(); +} + +fn init_parentchain( + enclave: &Arc, + node_api: &ParentchainApi, + tee_account_id: &AccountId32, + parentchain_id: ParentchainId, +) -> (Arc>, Header) +where + E: EnclaveBase + Sidechain, +{ + let parentchain_handler = Arc::new( + ParentchainHandler::new_with_automatic_light_client_allocation( + node_api.clone(), + enclave.clone(), + parentchain_id, + ) + .unwrap(), + ); + let last_synced_header = parentchain_handler.init_parentchain_components().unwrap(); + trace!("last synched parentchain block: {}", last_synced_header.number); + + let nonce = node_api.get_nonce_of(tee_account_id).unwrap(); + info!("Enclave nonce = {:?}", nonce); + enclave + .set_nonce(nonce, parentchain_id) + .expect("Could not set nonce of enclave. Returning here..."); + + let metadata = node_api.metadata().clone(); + let runtime_spec_version = node_api.runtime_version().spec_version; + let runtime_transaction_version = node_api.runtime_version().transaction_version; + enclave + .set_node_metadata( + NodeMetadata::new(metadata, runtime_spec_version, runtime_transaction_version).encode(), + parentchain_id, + ) + .expect("Could not set the node metadata in the enclave"); + (parentchain_handler, last_synced_header) +} + /// 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 /// considered initialized and ready for the next worker to start (in sidechain mode only). diff --git a/service/src/ocall_bridge/bridge_api.rs b/service/src/ocall_bridge/bridge_api.rs index 78800641..8d58bd04 100644 --- a/service/src/ocall_bridge/bridge_api.rs +++ b/service/src/ocall_bridge/bridge_api.rs @@ -137,8 +137,12 @@ pub enum OCallBridgeError { IpfsError(String), #[error("DirectInvocation Error: {0}")] DirectInvocationError(String), + #[error(transparent)] + Codec(#[from] codec::Error), #[error("Node API factory error: {0}")] NodeApiFactory(#[from] itp_node_api::node_api_factory::NodeApiFactoryError), + #[error("Target A parentchain not initialized")] + TargetAParentchainNotInitialized, } impl From for sgx_status_t { @@ -197,9 +201,17 @@ pub trait RemoteAttestationBridge { /// Trait for all the OCalls related to parentchain operations #[cfg_attr(test, automock)] pub trait WorkerOnChainBridge { - fn worker_request(&self, request: Vec) -> OCallBridgeResult>; + fn worker_request( + &self, + request: Vec, + parentchain_id: Vec, + ) -> OCallBridgeResult>; - fn send_to_parentchain(&self, extrinsics_encoded: Vec) -> OCallBridgeResult<()>; + fn send_to_parentchain( + &self, + extrinsics_encoded: Vec, + parentchain_id: Vec, + ) -> OCallBridgeResult<()>; } /// Trait for updating metrics from inside the enclave. diff --git a/service/src/ocall_bridge/component_factory.rs b/service/src/ocall_bridge/component_factory.rs index b15e3116..f6dcdc0e 100644 --- a/service/src/ocall_bridge/component_factory.rs +++ b/service/src/ocall_bridge/component_factory.rs @@ -53,7 +53,8 @@ pub struct OCallBridgeComponentFactory< TokioHandle, MetricsReceiver, > { - node_api_factory: Arc, + integritee_rpc_api_factory: Arc, + target_a_parentchain_rpc_api_factory: Option>, block_broadcaster: Arc, enclave_api: Arc, block_storage: Arc, @@ -86,7 +87,8 @@ impl< { #[allow(clippy::too_many_arguments)] pub fn new( - node_api_factory: Arc, + integritee_rpc_api_factory: Arc, + target_a_parentchain_rpc_api_factory: Option>, block_broadcaster: Arc, enclave_api: Arc, block_storage: Arc, @@ -96,7 +98,8 @@ impl< metrics_receiver: Arc, ) -> Self { OCallBridgeComponentFactory { - node_api_factory, + integritee_rpc_api_factory, + target_a_parentchain_rpc_api_factory, block_broadcaster, enclave_api, block_storage, @@ -152,7 +155,10 @@ impl< } fn get_oc_api(&self) -> Arc { - Arc::new(WorkerOnChainOCall::new(self.node_api_factory.clone())) + Arc::new(WorkerOnChainOCall::new( + self.integritee_rpc_api_factory.clone(), + self.target_a_parentchain_rpc_api_factory.clone(), + )) } fn get_ipfs_api(&self) -> Arc { diff --git a/service/src/ocall_bridge/ffi/send_to_parentchain.rs b/service/src/ocall_bridge/ffi/send_to_parentchain.rs index 19bf289c..d9e52205 100644 --- a/service/src/ocall_bridge/ffi/send_to_parentchain.rs +++ b/service/src/ocall_bridge/ffi/send_to_parentchain.rs @@ -28,20 +28,33 @@ use std::{slice, sync::Arc, vec::Vec}; pub unsafe extern "C" fn ocall_send_to_parentchain( extrinsics_encoded: *const u8, extrinsics_encoded_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, ) -> sgx_status_t { - send_to_parentchain(extrinsics_encoded, extrinsics_encoded_size, Bridge::get_oc_api()) + send_to_parentchain( + extrinsics_encoded, + extrinsics_encoded_size, + parentchain_id, + parentchain_id_size, + Bridge::get_oc_api(), + ) } fn send_to_parentchain( extrinsics_encoded: *const u8, extrinsics_encoded_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, oc_api: Arc, ) -> sgx_status_t { let extrinsics_encoded_vec: Vec = unsafe { Vec::from(slice::from_raw_parts(extrinsics_encoded, extrinsics_encoded_size as usize)) }; - match oc_api.send_to_parentchain(extrinsics_encoded_vec) { + let parentchain_id: Vec = + unsafe { Vec::from(slice::from_raw_parts(parentchain_id, parentchain_id_size as usize)) }; + + match oc_api.send_to_parentchain(extrinsics_encoded_vec, parentchain_id) { Ok(_) => sgx_status_t::SGX_SUCCESS, Err(e) => { error!("send extrinsics_encoded failed: {:?}", e); diff --git a/service/src/ocall_bridge/ffi/worker_request.rs b/service/src/ocall_bridge/ffi/worker_request.rs index 64820175..7dbd9be9 100644 --- a/service/src/ocall_bridge/ffi/worker_request.rs +++ b/service/src/ocall_bridge/ffi/worker_request.rs @@ -29,15 +29,27 @@ use std::{slice, sync::Arc, vec::Vec}; pub unsafe extern "C" fn ocall_worker_request( request: *const u8, req_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, response: *mut u8, resp_size: u32, ) -> sgx_status_t { - worker_request(request, req_size, response, resp_size, Bridge::get_oc_api()) + worker_request( + request, + req_size, + parentchain_id, + parentchain_id_size, + response, + resp_size, + Bridge::get_oc_api(), + ) } fn worker_request( request: *const u8, req_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, response: *mut u8, resp_size: u32, oc_api: Arc, @@ -45,7 +57,10 @@ fn worker_request( let request_vec: Vec = unsafe { Vec::from(slice::from_raw_parts(request, req_size as usize)) }; - match oc_api.worker_request(request_vec) { + let parentchain_id: Vec = + unsafe { Vec::from(slice::from_raw_parts(parentchain_id, parentchain_id_size as usize)) }; + + match oc_api.worker_request(request_vec, parentchain_id) { Ok(r) => { let resp_slice = unsafe { slice::from_raw_parts_mut(response, resp_size as usize) }; if let Err(e) = write_slice_and_whitespace_pad(resp_slice, r) { diff --git a/service/src/ocall_bridge/worker_on_chain_ocall.rs b/service/src/ocall_bridge/worker_on_chain_ocall.rs index 1dfea987..272e45b3 100644 --- a/service/src/ocall_bridge/worker_on_chain_ocall.rs +++ b/service/src/ocall_bridge/worker_on_chain_ocall.rs @@ -18,20 +18,38 @@ use crate::ocall_bridge::bridge_api::{OCallBridgeError, OCallBridgeResult, WorkerOnChainBridge}; use codec::{Decode, Encode}; +use itp_api_client_types::ParentchainApi; use itp_node_api::node_api_factory::CreateNodeApi; -use itp_types::{WorkerRequest, WorkerResponse}; +use itp_types::{parentchain::ParentchainId, WorkerRequest, WorkerResponse}; use log::*; use sp_runtime::OpaqueExtrinsic; use std::{sync::Arc, vec::Vec}; use substrate_api_client::{serde_impls::StorageKey, GetStorage, SubmitExtrinsic}; pub struct WorkerOnChainOCall { - node_api_factory: Arc, + integritee_api_factory: Arc, + target_a_parentchain_api_factory: Option>, } impl WorkerOnChainOCall { - pub fn new(node_api_factory: Arc) -> Self { - WorkerOnChainOCall { node_api_factory } + pub fn new( + integritee_api_factory: Arc, + target_a_parentchain_api_factory: Option>, + ) -> Self { + WorkerOnChainOCall { integritee_api_factory, target_a_parentchain_api_factory } + } +} + +impl WorkerOnChainOCall { + pub fn create_api(&self, parentchain_id: ParentchainId) -> OCallBridgeResult { + Ok(match parentchain_id { + ParentchainId::Integritee => self.integritee_api_factory.create_api()?, + ParentchainId::TargetA => self + .target_a_parentchain_api_factory + .as_ref() + .ok_or(OCallBridgeError::TargetAParentchainNotInitialized) + .and_then(|f| f.create_api().map_err(Into::into))?, + }) } } @@ -39,16 +57,22 @@ impl WorkerOnChainBridge for WorkerOnChainOCall where F: CreateNodeApi, { - fn worker_request(&self, request: Vec) -> OCallBridgeResult> { + fn worker_request( + &self, + request: Vec, + parentchain_id: Vec, + ) -> OCallBridgeResult> { debug!(" Entering ocall_worker_request"); - let requests: Vec = Decode::decode(&mut request.as_slice()).unwrap(); + let requests: Vec = Decode::decode(&mut request.as_slice())?; if requests.is_empty() { debug!("requests is empty, returning empty vector"); return Ok(Vec::::new().encode()) } - let api = self.node_api_factory.create_api()?; + let parentchain_id = ParentchainId::decode(&mut parentchain_id.as_slice())?; + + let api = self.create_api(parentchain_id)?; let resp: Vec>> = requests .into_iter() @@ -68,7 +92,11 @@ where Ok(encoded_response) } - fn send_to_parentchain(&self, extrinsics_encoded: Vec) -> OCallBridgeResult<()> { + fn send_to_parentchain( + &self, + extrinsics_encoded: Vec, + parentchain_id: Vec, + ) -> OCallBridgeResult<()> { // TODO: improve error handling, using a mut status is not good design? let mut status: OCallBridgeResult<()> = Ok(()); @@ -84,11 +112,20 @@ where }; if !extrinsics.is_empty() { - debug!("Enclave wants to send {} extrinsics", extrinsics.len()); - let api = self.node_api_factory.create_api()?; + let parentchain_id = ParentchainId::decode(&mut parentchain_id.as_slice())?; + debug!( + "Enclave wants to send {} extrinsics to parentchain: {:?}", + extrinsics.len(), + parentchain_id + ); + let api = self.create_api(parentchain_id)?; for call in extrinsics.into_iter() { if let Err(e) = api.submit_opaque_extrinsic(call.encode().into()) { - error!("Could not send extrsinic to node: {:?}, error: {:?}", call, e); + error!( + "Could not send extrinsic to node: {:?}, error: {:?}", + serde_json::to_string(&call), + e + ); } } } @@ -118,9 +155,11 @@ mod tests { let mock_node_api_factory = Arc::new(MockNodeApiFactory::new()); - let on_chain_ocall = WorkerOnChainOCall::new(mock_node_api_factory); + let on_chain_ocall = WorkerOnChainOCall::new(mock_node_api_factory, None); - let response = on_chain_ocall.worker_request(Vec::::new().encode()).unwrap(); + let response = on_chain_ocall + .worker_request(Vec::::new().encode(), ParentchainId::Integritee.encode()) + .unwrap(); assert!(!response.is_empty()); // the encoded empty vector is not empty let decoded_response: Vec = Decode::decode(&mut response.as_slice()).unwrap(); diff --git a/service/src/parentchain_handler.rs b/service/src/parentchain_handler.rs index b0a9c443..ee02dc0c 100644 --- a/service/src/parentchain_handler.rs +++ b/service/src/parentchain_handler.rs @@ -19,7 +19,7 @@ use crate::error::{Error, ServiceResult}; use itc_parentchain::{ light_client::light_client_init_params::{GrandpaParams, SimpleParams}, - primitives::ParentchainInitParams, + primitives::{ParentchainId, ParentchainInitParams}, }; use itp_enclave_api::{enclave_base::EnclaveBase, sidechain::Sidechain}; use itp_node_api::api_client::ChainApi; @@ -54,7 +54,7 @@ pub trait HandleParentchain { } /// Handles the interaction between parentchain and enclave. -pub(crate) struct ParentchainHandler { +pub(crate) struct ParentchainHandler { parentchain_api: ParentchainApi, enclave_api: Arc, parentchain_init_params: ParentchainInitParams, @@ -63,7 +63,7 @@ pub(crate) struct ParentchainHandler ParentchainHandler where ParentchainApi: ChainApi, - EnclaveApi: Sidechain + EnclaveBase, + EnclaveApi: EnclaveBase, { pub fn new( parentchain_api: ParentchainApi, @@ -77,6 +77,7 @@ where pub fn new_with_automatic_light_client_allocation( parentchain_api: ParentchainApi, enclave_api: Arc, + id: ParentchainId, ) -> ServiceResult { let genesis_hash = parentchain_api.get_genesis_hash()?; let genesis_header = @@ -92,14 +93,9 @@ where let authority_list = VersionedAuthorityList::from(grandpas); - GrandpaParams { - genesis_header, - authorities: authority_list.into(), - authority_proof: grandpa_proof, - } - .into() + (id, GrandpaParams::new(genesis_header, authority_list.into(), grandpa_proof)).into() } else { - SimpleParams { genesis_header }.into() + (id, SimpleParams::new(genesis_header)).into() }; Ok(Self::new(parentchain_api, enclave_api, parentchain_init_params)) @@ -108,6 +104,10 @@ where pub fn parentchain_api(&self) -> &ParentchainApi { &self.parentchain_api } + + pub fn parentchain_id(&self) -> &ParentchainId { + self.parentchain_init_params.id() + } } impl HandleParentchain @@ -161,7 +161,7 @@ where block_chunk_to_sync.as_slice(), events_chunk_to_sync.as_slice(), events_proofs_chunk_to_sync.as_slice(), - 0, + self.parentchain_id(), )?; until_synced_header = block_chunk_to_sync @@ -177,7 +177,7 @@ where fn trigger_parentchain_block_import(&self) -> ServiceResult<()> { trace!("trigger parentchain block import"); - Ok(self.enclave_api.trigger_parentchain_block_import()?) + Ok(self.enclave_api.trigger_parentchain_block_import(self.parentchain_id())?) } fn sync_and_import_parentchain_until( diff --git a/service/src/setup.rs b/service/src/setup.rs index 6535091f..7e7c59cd 100644 --- a/service/src/setup.rs +++ b/service/src/setup.rs @@ -21,7 +21,8 @@ use base58::ToBase58; use codec::Encode; use itp_enclave_api::{enclave_base::EnclaveBase, Enclave}; use itp_settings::files::{ - LIGHT_CLIENT_DB_PATH, SHARDS_PATH, SHIELDING_KEY_FILE, SIDECHAIN_STORAGE_PATH, SIGNING_KEY_FILE, + INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, SHARDS_PATH, SHIELDING_KEY_FILE, + SIDECHAIN_STORAGE_PATH, SIGNING_KEY_FILE, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, }; use itp_types::ShardIdentifier; use log::*; @@ -96,7 +97,8 @@ 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, LIGHT_CLIENT_DB_PATH)?; + remove_dir_if_it_exists(root_directory, INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)?; + remove_dir_if_it_exists(root_directory, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)?; Ok(()) } @@ -112,7 +114,7 @@ fn remove_dir_if_it_exists(root_directory: &Path, dir_name: &str) -> ServiceResu #[cfg(test)] mod tests { use super::*; - use itp_settings::files::SHARDS_PATH; + use itp_settings::files::{SHARDS_PATH, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH}; use std::{fs, path::PathBuf}; #[test] @@ -132,13 +134,17 @@ mod tests { 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::create_dir_all(&root_directory.join(LIGHT_CLIENT_DB_PATH)).unwrap(); + fs::create_dir_all(&root_directory.join(INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)) + .unwrap(); + fs::create_dir_all(&root_directory.join(TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)) + .unwrap(); purge_files(&root_directory).unwrap(); assert!(!shards_path.exists()); assert!(!sidechain_db_path.exists()); - assert!(!root_directory.join(LIGHT_CLIENT_DB_PATH).exists()); + assert!(!root_directory.join(INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH).exists()); + assert!(!root_directory.join(TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH).exists()); } #[test] diff --git a/service/src/tests/commons.rs b/service/src/tests/commons.rs index c78ce4d9..012cb1ad 100644 --- a/service/src/tests/commons.rs +++ b/service/src/tests/commons.rs @@ -38,6 +38,8 @@ pub fn local_worker_config( let mut url = worker_url.split(':'); Config::new( + Default::default(), + Default::default(), Default::default(), Default::default(), url.next().unwrap().into(), diff --git a/service/src/tests/mocks/enclave_api_mock.rs b/service/src/tests/mocks/enclave_api_mock.rs index 21a64323..9bebb766 100644 --- a/service/src/tests/mocks/enclave_api_mock.rs +++ b/service/src/tests/mocks/enclave_api_mock.rs @@ -20,7 +20,7 @@ use core::fmt::Debug; use enclave_bridge_primitives::EnclaveFingerprint; use frame_support::sp_runtime::traits::Block as ParentchainBlockTrait; use itc_parentchain::primitives::{ - ParentchainInitParams, + ParentchainId, ParentchainInitParams, ParentchainInitParams::{Parachain, Solochain}, }; use itp_enclave_api::{enclave_base::EnclaveBase, sidechain::Sidechain, EnclaveResult}; @@ -50,8 +50,8 @@ impl EnclaveBase for EnclaveMock { params: ParentchainInitParams, ) -> EnclaveResult
{ let genesis_header_encoded = match params { - Solochain { params } => params.genesis_header.encode(), - Parachain { params } => params.genesis_header.encode(), + Solochain { params, .. } => params.genesis_header.encode(), + Parachain { params, .. } => params.genesis_header.encode(), }; let header = Header::decode(&mut genesis_header_encoded.as_slice())?; Ok(header) @@ -61,15 +61,15 @@ impl EnclaveBase for EnclaveMock { unimplemented!() } - fn trigger_parentchain_block_import(&self) -> EnclaveResult<()> { + fn trigger_parentchain_block_import(&self, _: &ParentchainId) -> EnclaveResult<()> { unimplemented!() } - fn set_nonce(&self, _: u32) -> EnclaveResult<()> { + fn set_nonce(&self, _: u32, _: ParentchainId) -> EnclaveResult<()> { unimplemented!() } - fn set_node_metadata(&self, _metadata: Vec) -> EnclaveResult<()> { + fn set_node_metadata(&self, _metadata: Vec, _: ParentchainId) -> EnclaveResult<()> { todo!() } @@ -92,7 +92,7 @@ impl Sidechain for EnclaveMock { _blocks: &[sp_runtime::generic::SignedBlock], _events: &[Vec], _events_proofs: &[StorageProof], - _nonce: u32, + _: &ParentchainId, ) -> EnclaveResult<()> { Ok(()) } diff --git a/service/src/tests/parentchain_handler_test.rs b/service/src/tests/parentchain_handler_test.rs index d3006639..78af8525 100644 --- a/service/src/tests/parentchain_handler_test.rs +++ b/service/src/tests/parentchain_handler_test.rs @@ -20,7 +20,8 @@ use crate::{ tests::mocks::{enclave_api_mock::EnclaveMock, parentchain_api_mock::ParentchainApiMock}, }; use itc_parentchain::{ - light_client::light_client_init_params::SimpleParams, primitives::ParentchainInitParams, + light_client::light_client_init_params::SimpleParams, + primitives::{ParentchainId, ParentchainInitParams}, }; use itc_parentchain_test::ParentchainHeaderBuilder; use itp_node_api::api_client::ChainApi; @@ -36,7 +37,8 @@ fn test_number_of_synced_blocks() { let enclave_api_mock = EnclaveMock; let parentchain_params: ParentchainInitParams = - SimpleParams { genesis_header: ParentchainHeaderBuilder::default().build() }.into(); + (ParentchainId::Integritee, SimpleParams::new(ParentchainHeaderBuilder::default().build())) + .into(); let parentchain_handler = ParentchainHandler::new( parentchain_api_mock, diff --git a/sidechain/validateer-fetch/src/validateer.rs b/sidechain/validateer-fetch/src/validateer.rs index 3f0c0999..84d77026 100644 --- a/sidechain/validateer-fetch/src/validateer.rs +++ b/sidechain/validateer-fetch/src/validateer.rs @@ -18,7 +18,10 @@ use crate::error::{Error, Result}; use itp_enclave_bridge_storage::{EnclaveBridgeStorage, EnclaveBridgeStorageKeys}; use itp_ocall_api::EnclaveOnChainOCallApi; -use itp_types::{parentchain::AccountId, ShardSignerStatus}; +use itp_types::{ + parentchain::{AccountId, ParentchainId}, + ShardSignerStatus, +}; use its_primitives::traits::{Block as SidechainBlockTrait, Header as HeaderTrait, SignedBlock}; use log::trace; use sp_core::H256; @@ -62,6 +65,7 @@ impl ValidateerFetch for OnchainStorage shard, ), header, + &ParentchainId::Integritee, )? .into_tuple() .1 From 54aeea6e002466869bb8a74d230f23fb77595d3c Mon Sep 17 00:00:00 2001 From: clangenb <37865735+clangenb@users.noreply.github.com> Date: Sun, 10 Sep 2023 14:49:07 +0200 Subject: [PATCH 5/5] [Multiparentchain] add support for third parentchain `Target_B` (#1443) * add support for the target b parentchain inside the enclave * [service] add full Target B parentchain support on the service side * extend local setup and integration tests to include target chain b * [settings] fix doc * [enclave-runtime/initialization] fix wrong target parentchain type in args * [cli] fix use correct client multi parentchain test * [service] fix clippy * [service] fix tests * fine tune block import logs * [service] better log * [enclave-runtime] fix import dispatcher for `TargetBSolochainHandler` * [service] note parentchain id in logs. * [light-client] improve logging by noting the parentchain id. * [service] fix purging light client db for target b * [block-importer] consistently denote parentchain id * [local-setup] adjust log levels * [block_importer] fix logs --- app-libs/stf/src/stf_sgx.rs | 1 + ...on_target_nodes_with_transfer_to_alice.sh} | 45 ++++--- core-primitives/settings/src/lib.rs | 3 + core-primitives/types/src/parentchain.rs | 4 +- .../block-importer/src/block_importer.rs | 12 +- .../src/filter_metadata.rs | 8 +- core/parentchain/light-client/src/io.rs | 54 ++++++-- .../light-client/src/light_validation.rs | 41 ++++-- enclave-runtime/src/error.rs | 1 + .../src/initialization/global_components.rs | 50 +++++++ enclave-runtime/src/initialization/mod.rs | 11 +- .../src/initialization/parentchain/common.rs | 63 +++++++++ .../src/initialization/parentchain/mod.rs | 24 ++++ .../parentchain/target_b_parachain.rs | 122 ++++++++++++++++++ .../parentchain/target_b_solochain.rs | 115 +++++++++++++++++ enclave-runtime/src/lib.rs | 33 ++++- enclave-runtime/src/utils.rs | 16 ++- ...orker.json => three-nodes-one-worker.json} | 24 ++++ local-setup/py/worker.py | 3 +- ...wo_nodes.sh => tmux_logger_three_nodes.sh} | 14 +- service/src/cli.yml | 10 ++ service/src/config.rs | 25 ++++ service/src/main.rs | 74 ++++++++--- service/src/ocall_bridge/bridge_api.rs | 2 + service/src/ocall_bridge/component_factory.rs | 4 + .../src/ocall_bridge/worker_on_chain_ocall.rs | 15 ++- service/src/parentchain_handler.rs | 27 ++-- service/src/setup.rs | 5 + service/src/tests/commons.rs | 2 + 29 files changed, 710 insertions(+), 98 deletions(-) rename cli/{demo_shield_on_second_node_with_transfer_to_alice.sh => test_shield_on_target_nodes_with_transfer_to_alice.sh} (71%) create mode 100644 enclave-runtime/src/initialization/parentchain/target_b_parachain.rs create mode 100644 enclave-runtime/src/initialization/parentchain/target_b_solochain.rs rename local-setup/config/{two-nodes-one-worker.json => three-nodes-one-worker.json} (70%) rename local-setup/{tmux_logger_two_nodes.sh => tmux_logger_three_nodes.sh} (59%) diff --git a/app-libs/stf/src/stf_sgx.rs b/app-libs/stf/src/stf_sgx.rs index e7871b47..d720a815 100644 --- a/app-libs/stf/src/stf_sgx.rs +++ b/app-libs/stf/src/stf_sgx.rs @@ -119,6 +119,7 @@ where match parentchain_id { ParentchainId::Integritee => vec![shards_key_hash()], ParentchainId::TargetA => vec![], + ParentchainId::TargetB => vec![], } } } diff --git a/cli/demo_shield_on_second_node_with_transfer_to_alice.sh b/cli/test_shield_on_target_nodes_with_transfer_to_alice.sh similarity index 71% rename from cli/demo_shield_on_second_node_with_transfer_to_alice.sh rename to cli/test_shield_on_target_nodes_with_transfer_to_alice.sh index 4ec7ac50..b7d6f76a 100755 --- a/cli/demo_shield_on_second_node_with_transfer_to_alice.sh +++ b/cli/test_shield_on_target_nodes_with_transfer_to_alice.sh @@ -1,9 +1,12 @@ #!/bin/bash set -euo pipefail -# Verifies that shielding from the Target A parentchain works by sending a transfer to //Alice +# Verifies that shielding from the Target A and B parentchains works by sending a transfer to //Alice. +# +# Note: This test does not do anything meaningful. It only verifies the basic functionality of the Target parentchain +# connections. -while getopts ":m:p:A:B:u:W:V:x:y:C:" opt; do +while getopts ":m:p:A:u:V:w:x:y:z:C:" opt; do case $opt in p) INTEGRITEE_RPC_PORT=$OPTARG @@ -11,23 +14,23 @@ while getopts ":m:p:A:B:u:W:V:x:y:C:" opt; do A) WORKER_1_PORT=$OPTARG ;; - B) - WORKER_2_PORT=$OPTARG - ;; u) INTEGRITEE_RPC_URL=$OPTARG ;; V) WORKER_1_URL=$OPTARG ;; - W) - WORKER_2_URL=$OPTARG + w) + TARGET_A_PARENTCHAIN_RPC_URL=$OPTARG ;; x) - TARGET_A_PARENTCHAIN_RPC_URL=$OPTARG + TARGET_A_PARENTCHAIN_RPC_PORT=$OPTARG ;; y) - TARGET_A_PARENTCHAIN_RPC_PORT=$OPTARG + TARGET_B_PARENTCHAIN_RPC_URL=$OPTARG + ;; + z) + TARGET_B_PARENTCHAIN_RPC_PORT=$OPTARG ;; C) CLIENT_BIN=$OPTARG @@ -43,21 +46,20 @@ INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} TARGET_A_PARENTCHAIN_RPC_PORT=${TARGET_A_PARENTCHAIN_RPC_PORT:-9966} TARGET_A_PARENTCHAIN_RPC_URL=${TARGET_A_PARENTCHAIN_RPC_URL:-"ws://127.0.0.1"} +TARGET_B_PARENTCHAIN_RPC_PORT=${TARGET_B_PARENTCHAIN_RPC_PORT:-9988} +TARGET_B_PARENTCHAIN_RPC_URL=${TARGET_B_PARENTCHAIN_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"} -WORKER_2_PORT=${WORKER_2_PORT:-3000} -WORKER_2_URL=${WORKER_2_URL:-"wss://127.0.0.1"} - CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} echo "Using client binary ${CLIENT_BIN}" ${CLIENT_BIN} --version -echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" -echo "Using node 2 uri ${TARGET_A_PARENTCHAIN_RPC_URL}:${TARGET_A_PARENTCHAIN_RPC_PORT}" +echo "Using Integritee RPC uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using Target A RPC uri ${TARGET_A_PARENTCHAIN_RPC_URL}:${TARGET_A_PARENTCHAIN_RPC_PORT}" +echo "Using Target B RPC uri ${TARGET_B_PARENTCHAIN_RPC_URL}:${TARGET_B_PARENTCHAIN_RPC_PORT}" echo "Using trusted-worker 1 uri ${WORKER_1_URL}:${WORKER_1_PORT}" -echo "Using trusted-worker 2 uri ${WORKER_2_URL}:${WORKER_2_PORT}" echo "" # the parentchain token is 12 decimal @@ -65,11 +67,10 @@ UNIT=$(( 10 ** 12 )) # make these amounts greater than ED AMOUNT_SHIELD=$(( 6 * UNIT )) -AMOUNT_TRANSFER=$(( 2 * UNIT )) -AMOUNT_UNSHIELD=$(( 1 * UNIT )) CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" CLIENT2="${CLIENT_BIN} -p ${TARGET_A_PARENTCHAIN_RPC_PORT} -P ${WORKER_1_PORT} -u ${TARGET_A_PARENTCHAIN_RPC_URL} -U ${WORKER_1_URL}" +CLIENT3="${CLIENT_BIN} -p ${TARGET_B_PARENTCHAIN_RPC_PORT} -P ${WORKER_1_PORT} -u ${TARGET_B_PARENTCHAIN_RPC_URL} -U ${WORKER_1_URL}" # interval and max rounds to wait to check the given account balance in sidechain WAIT_INTERVAL_SECONDS=10 @@ -134,7 +135,7 @@ TRUSTED_BALANCE_ALICE=1000000000000000 wait_assert_state ${MRENCLAVE} ${ALICETRUSTEDACCOUNT} balance ${TRUSTED_BALANCE_ALICE} -echo "* Send ${AMOUNT_SHIELD} from //Alice to //Alice on L1, which should trigger the demo shield process" +echo "* Send ${AMOUNT_SHIELD} from //Alice to //Alice on the Target A parentchain, which should trigger the shield process" ${CLIENT2} transfer //Alice ${ALICETRUSTEDACCOUNT} ${AMOUNT_SHIELD} echo "" @@ -142,6 +143,14 @@ echo "* Wait and assert Alice's incognito account balance, should be $(( TRUSTED wait_assert_state ${MRENCLAVE} ${ALICETRUSTEDACCOUNT} balance $(( TRUSTED_BALANCE_ALICE + AMOUNT_SHIELD )) echo "✔ ok" +echo "* Send ${AMOUNT_SHIELD} from //Alice to //Alice on the Target B Parentchain, which should trigger the shield process again" +${CLIENT3} transfer //Alice ${ALICETRUSTEDACCOUNT} ${AMOUNT_SHIELD} +echo "" + +echo "* Wait and assert Alice's incognito account balance, should be $(( TRUSTED_BALANCE_ALICE + 2*AMOUNT_SHIELD ))" +wait_assert_state ${MRENCLAVE} ${ALICETRUSTEDACCOUNT} balance $(( TRUSTED_BALANCE_ALICE + 2*AMOUNT_SHIELD )) +echo "✔ ok" + echo "" echo "-----------------------" echo "✔ The test passed!" diff --git a/core-primitives/settings/src/lib.rs b/core-primitives/settings/src/lib.rs index 0567e88b..0066558c 100644 --- a/core-primitives/settings/src/lib.rs +++ b/core-primitives/settings/src/lib.rs @@ -48,6 +48,9 @@ pub mod files { /// Path to the light-client db for the Target A parentchain. pub const TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "target_a_lcdb"; + /// Path to the light-client db for the Target B parentchain. + pub const TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "target_b_lcdb"; + pub const RA_DUMP_CERT_DER_FILE: &str = "ra_dump_cert.der"; // used by worker and enclave diff --git a/core-primitives/types/src/parentchain.rs b/core-primitives/types/src/parentchain.rs index 1d674833..32610d0a 100644 --- a/core-primitives/types/src/parentchain.rs +++ b/core-primitives/types/src/parentchain.rs @@ -46,8 +46,10 @@ pub type Signature = MultiSignature; pub enum ParentchainId { /// The Integritee Parentchain, the trust root of the enclave and serving finality to sidechains. Integritee, - /// A target chain containing custom business logics. + /// A target chain containing custom business logic. TargetA, + /// Another target chain containing custom business logic. + TargetB, } pub trait IdentifyParentchain { diff --git a/core/parentchain/block-importer/src/block_importer.rs b/core/parentchain/block-importer/src/block_importer.rs index b83749d2..f3130c41 100644 --- a/core/parentchain/block-importer/src/block_importer.rs +++ b/core/parentchain/block-importer/src/block_importer.rs @@ -108,8 +108,9 @@ impl< events_to_import: Vec>, ) -> Result<()> { let mut calls = Vec::::new(); + let id = self.validator_accessor.parentchain_id(); - debug!("Import blocks to light-client!"); + debug!("[{:?}] Import blocks to light-client!", id); for (signed_block, raw_events) in blocks_to_import.into_iter().zip(events_to_import.into_iter()) { @@ -120,7 +121,7 @@ impl< v.submit_block(&signed_block) }) { - error!("[Validator] Header submission failed: {:?}", e); + error!("[{:?}] Header submission to light client failed: {:?}", id, e); return Err(e.into()) } @@ -130,7 +131,7 @@ impl< .stf_executor .update_states(block.header(), &self.validator_accessor.parentchain_id()) { - error!("Error performing state updates upon block import"); + error!("[{:?}] Error performing state updates upon block import", id); return Err(e.into()) } @@ -143,11 +144,12 @@ impl< Ok(executed_shielding_calls) => { calls.push(executed_shielding_calls); }, - Err(_) => error!("Error executing relevant extrinsics"), + Err(_) => error!("[{:?}] Error executing relevant extrinsics", id), }; info!( - "Successfully imported parentchain block (number: {}, hash: {})", + "[{:?}] Successfully imported parentchain block (number: {}, hash: {})", + id, block.header().number, block.header().hash() ); diff --git a/core/parentchain/indirect-calls-executor/src/filter_metadata.rs b/core/parentchain/indirect-calls-executor/src/filter_metadata.rs index b77805d1..dd95b8b0 100644 --- a/core/parentchain/indirect-calls-executor/src/filter_metadata.rs +++ b/core/parentchain/indirect-calls-executor/src/filter_metadata.rs @@ -135,11 +135,11 @@ where index ); if index == metadata.shield_funds_call_indexes().ok()? { - log::trace!("executing shield funds call"); + 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::trace!("executing invoke call"); + log::debug!("executing invoke call"); let args = decode_and_log_error::(call_args)?; Some(IndirectCall::Invoke(args)) } else { @@ -177,12 +177,12 @@ where if index == metadata.transfer_call_index().ok()? || index == metadata.transfer_allow_death_call_index().ok()? { - log::trace!("found `transfer` or `transfer_allow_death` call."); + log::debug!("found `transfer` or `transfer_allow_death` call."); let args = decode_and_log_error::(call_args)?; if args.destination == ALICE_ACCOUNT_ID.into() { Some(IndirectCall::TransferToAliceShieldsFunds(args)) } else { - log::trace!("Parentchain transfer was not for Alice; ignoring..."); + log::debug!("Parentchain transfer was not for Alice; ignoring..."); // No need to put it into the top pool if it isn't executed in the first place. None } diff --git a/core/parentchain/light-client/src/io.rs b/core/parentchain/light-client/src/io.rs index 661934fe..99145f51 100644 --- a/core/parentchain/light-client/src/io.rs +++ b/core/parentchain/light-client/src/io.rs @@ -52,16 +52,18 @@ pub struct LightClientStateSeal { base_path: PathBuf, db_path: PathBuf, backup_path: PathBuf, + parentchain_id: ParentchainId, _phantom: PhantomData<(B, LightClientState)>, } impl LightClientStateSeal { - pub fn new(base_path: PathBuf) -> Result { + pub fn new(base_path: PathBuf, parentchain_id: ParentchainId) -> Result { std::fs::create_dir_all(&base_path)?; Ok(Self { base_path: base_path.clone(), db_path: base_path.clone().join(DB_FILE), backup_path: base_path.join(BACKUP_FILE), + parentchain_id, _phantom: Default::default(), }) } @@ -88,19 +90,36 @@ impl LightClientStateSeal { } } +impl IdentifyParentchain for LightClientStateSeal { + fn parentchain_id(&self) -> ParentchainId { + self.parentchain_id + } +} + impl LightClientSealing for LightClientStateSeal { type LightClientState = LightClientState; fn seal(&self, unsealed: &LightClientState) -> Result<()> { - trace!("Backup light client state"); + trace!( + "[{:?}] Backup light client state to {}", + self.parentchain_id, + self.backup_path().display() + ); if let Err(e) = self.backup() { - warn!("Could not backup previous light client state: Error: {}", e); + warn!( + "[{:?}] Could not backup previous light client state: Error: {}", + self.parentchain_id, e + ); }; - trace!("Seal light client State. Current state: {:?}", unsealed); + trace!( + "[{:?}] Seal light client State. Current state: {:?}", + self.parentchain_id, + unsealed + ); Ok(unsealed.using_encoded(|bytes| seal(bytes, self.db_path()))?) } @@ -122,15 +141,13 @@ impl LightClientSealing #[derive(Debug)] pub struct LightClientStateSealSync { seal: LightClientStateSeal, - parentchain_id: ParentchainId, _rw_lock: RwLock<()>, } impl LightClientStateSealSync { pub fn new(base_path: PathBuf, parentchain_id: ParentchainId) -> Result { Ok(Self { - seal: LightClientStateSeal::new(base_path)?, - parentchain_id, + seal: LightClientStateSeal::new(base_path, parentchain_id)?, _rw_lock: RwLock::new(()), }) } @@ -138,7 +155,7 @@ impl LightClientStateSealSync { impl IdentifyParentchain for LightClientStateSealSync { fn parentchain_id(&self) -> ParentchainId { - self.parentchain_id + self.seal.parentchain_id } } @@ -178,7 +195,8 @@ where B: Block, NumberFor: finality_grandpa::BlockNumberOps, OCallApi: EnclaveOnChainOCallApi, - LightClientSeal: LightClientSealing>, + LightClientSeal: + LightClientSealing> + IdentifyParentchain, { check_validator_set_proof::( params.genesis_header.state_root(), @@ -187,7 +205,11 @@ where )?; if !seal.exists() { - info!("[Enclave] ChainRelay DB not found, creating new! {}", seal.path().display()); + info!( + "[{:?}] ChainRelay DB not found, creating new! {}", + seal.parentchain_id(), + seal.path().display() + ); let validator = init_grandpa_validator::( ocall_api, RelayState::new(params.genesis_header, params.authorities).into(), @@ -201,7 +223,11 @@ where let genesis_hash = validation_state.genesis_hash()?; let init_state = if genesis_hash == params.genesis_header.hash() { - info!("Found already initialized light client with Genesis Hash: {:?}", genesis_hash); + info!( + "[{:?}] Found already initialized light client with Genesis Hash: {:?}", + seal.parentchain_id(), + genesis_hash + ); validation_state } else { info!( @@ -213,7 +239,7 @@ where let validator = init_grandpa_validator::(ocall_api, init_state, parentchain_id)?; - info!("light client state: {:?}", validator); + info!("[{:?}] light client state: {:?}", seal.parentchain_id(), validator); seal.seal(validator.get_state())?; Ok(validator) @@ -321,7 +347,7 @@ pub mod sgx_tests { pub fn init_parachain_light_client_works() { let parachain_params = default_simple_params(); let temp_dir = TempDir::with_prefix("init_parachain_light_client_works").unwrap(); - let seal = TestSeal::new(temp_dir.path().to_path_buf()).unwrap(); + let seal = TestSeal::new(temp_dir.path().to_path_buf(), ParentchainId::Integritee).unwrap(); let validator = read_or_init_parachain_validator::( parachain_params.clone(), @@ -343,7 +369,7 @@ pub mod sgx_tests { pub fn sealing_creates_backup() { let params = default_simple_params(); let temp_dir = TempDir::with_prefix("sealing_creates_backup").unwrap(); - let seal = TestSeal::new(temp_dir.path().to_path_buf()).unwrap(); + let seal = TestSeal::new(temp_dir.path().to_path_buf(), ParentchainId::Integritee).unwrap(); let state = RelayState::new(params.genesis_header, Default::default()).into(); seal.seal(&state).unwrap(); diff --git a/core/parentchain/light-client/src/light_validation.rs b/core/parentchain/light-client/src/light_validation.rs index e23761b0..290419c4 100644 --- a/core/parentchain/light-client/src/light_validation.rs +++ b/core/parentchain/light-client/src/light_validation.rs @@ -25,7 +25,7 @@ use codec::Encode; use core::iter::Iterator; use itp_ocall_api::EnclaveOnChainOCallApi; use itp_storage::{Error as StorageError, StorageProof, StorageProofChecker}; -use itp_types::parentchain::ParentchainId; +use itp_types::parentchain::{IdentifyParentchain, ParentchainId}; use log::*; use sp_runtime::{ generic::SignedBlock, @@ -35,13 +35,21 @@ use sp_runtime::{ use std::{boxed::Box, fmt, sync::Arc, vec::Vec}; #[derive(Clone)] -pub struct LightValidation { +pub struct LightValidation { light_validation_state: LightValidationState, ocall_api: Arc, parentchain_id: ParentchainId, finality: Arc + Sync + Send + 'static>>, } +impl IdentifyParentchain + for LightValidation +{ + fn parentchain_id(&self) -> ParentchainId { + self.parentchain_id + } +} + impl LightValidation { @@ -126,7 +134,8 @@ impl relay.verify_tx_inclusion.push(extrinsic); debug!( - "{} extrinsics in cache, waiting for inclusion verification", + "[{:?}] {} extrinsics in cache, waiting for inclusion verification", + self.parentchain_id, relay.verify_tx_inclusion.len() ); } @@ -174,10 +183,15 @@ where found_xts.into_iter().map(|i| relay.verify_tx_inclusion.remove(i)).collect(); if !rm.is_empty() { - info!("Verified inclusion proof of {} extrinsics.", rm.len()); + info!( + "[{:?}] Verified inclusion proof of {} extrinsics.", + self.parentchain_id, + rm.len() + ); } debug!( - "{} extrinsics remaining in cache, waiting for inclusion verification", + "[{:?}] {} extrinsics remaining in cache, waiting for inclusion verification", + self.parentchain_id, relay.verify_tx_inclusion.len() ); @@ -202,7 +216,11 @@ where self.ocall_api .send_to_parentchain(extrinsics, &self.parentchain_id) - .map_err(|e| Error::Other(format!("Failed to send extrinsics: {}", e).into())) + .map_err(|e| { + Error::Other( + format!("[{:?}] Failed to send extrinsics: {}", self.parentchain_id, e).into(), + ) + }) } } @@ -229,17 +247,12 @@ where } } -impl fmt::Debug for LightValidation -where - NumberFor: finality_grandpa::BlockNumberOps, - Block: ParentchainBlockTrait, - OCallApi: EnclaveOnChainOCallApi, -{ +impl fmt::Debug for LightValidation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "LightValidation {{ relay_state: {:?} }}", - self.light_validation_state.relay_state + "LightValidation {{ parentchain_id: {:?}, relay_state: {:?} }}", + self.parentchain_id, self.light_validation_state.relay_state ) } } diff --git a/enclave-runtime/src/error.rs b/enclave-runtime/src/error.rs index 64eecb83..0ecad391 100644 --- a/enclave-runtime/src/error.rs +++ b/enclave-runtime/src/error.rs @@ -43,6 +43,7 @@ pub enum Error { CouldNotDispatchBlockImport, NoIntegriteeParentchainAssigned, NoTargetAParentchainAssigned, + NoTargetBParentchainAssigned, ParentChainValidation(itp_storage::error::Error), ParentChainSync, PrimitivesAccess(itp_primitives_cache::error::Error), diff --git a/enclave-runtime/src/initialization/global_components.rs b/enclave-runtime/src/initialization/global_components.rs index 0e9a74b3..cd71637f 100644 --- a/enclave-runtime/src/initialization/global_components.rs +++ b/enclave-runtime/src/initialization/global_components.rs @@ -25,6 +25,7 @@ use crate::{ integritee_parachain::IntegriteeParachainHandler, integritee_solochain::IntegriteeSolochainHandler, target_a_parachain::TargetAParachainHandler, target_a_solochain::TargetASolochainHandler, + target_b_parachain::TargetBParachainHandler, target_b_solochain::TargetBSolochainHandler, }, ocall::OcallApi, rpc::rpc_response_channel::RpcResponseChannel, @@ -227,6 +228,39 @@ pub type TargetAParentchainBlockImportDispatcher = BlockImportDispatcher< TargetAParentchainImmediateBlockImportDispatcher, >; +// Stuff for the Target B parentchain + +/// IndirectCalls executor instance of the Target B parentchain. +/// +/// **Note**: The filter here is purely used for demo purposes. +/// +/// Also note that the extrinsic parser must be changed if the signed extra contains the +/// `AssetTxPayment`. +pub type TargetBParentchainIndirectExecutor = + EnclaveIndirectCallsExecutor>; + +pub type TargetBParentchainBlockImporter = ParentchainBlockImporter< + ParentchainBlock, + EnclaveValidatorAccessor, + EnclaveStfExecutor, + EnclaveExtrinsicsFactory, + TargetBParentchainIndirectExecutor, +>; + +pub type TargetBParentchainTriggeredBlockImportDispatcher = TriggeredDispatcher< + TargetBParentchainBlockImporter, + EnclaveParentchainBlockImportQueue, + EnclaveParentchainEventImportQueue, +>; + +pub type TargetBParentchainImmediateBlockImportDispatcher = + ImmediateDispatcher; + +pub type TargetBParentchainBlockImportDispatcher = BlockImportDispatcher< + TargetBParentchainTriggeredBlockImportDispatcher, + TargetBParentchainImmediateBlockImportDispatcher, +>; + /// Sidechain types pub type EnclaveTopPool = BasicPool; @@ -314,6 +348,11 @@ pub static GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer< EnclaveLightClientSeal, > = ComponentContainer::new("Target A EnclaveLightClientSealSync"); +/// Light client db seal for the Target A parentchain. +pub static GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer< + EnclaveLightClientSeal, +> = ComponentContainer::new("Target B EnclaveLightClientSealSync"); + /// O-Call API pub static GLOBAL_OCALL_API_COMPONENT: ComponentContainer = ComponentContainer::new("O-call API"); @@ -347,6 +386,9 @@ lazy_static! { /// Global nonce cache for the Target A parentchain.. pub static ref GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE: Arc = Default::default(); + + /// Global nonce cache for the Target B parentchain.. + pub static ref GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE: Arc = Default::default(); } /// Solochain Handler. @@ -366,6 +408,14 @@ pub static GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT: ComponentContainer< TargetAParachainHandler, > = ComponentContainer::new("target A parachain handler"); +pub static GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT: ComponentContainer< + TargetBSolochainHandler, +> = ComponentContainer::new("target B solochain handler"); + +pub static GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT: ComponentContainer< + TargetBParachainHandler, +> = ComponentContainer::new("target B parachain handler"); + // Sidechain component instances //------------------------------------------------------------------------------------------------- diff --git a/enclave-runtime/src/initialization/mod.rs b/enclave-runtime/src/initialization/mod.rs index d1484acb..0573c11c 100644 --- a/enclave-runtime/src/initialization/mod.rs +++ b/enclave-runtime/src/initialization/mod.rs @@ -35,7 +35,8 @@ use crate::{ 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_TOP_POOL_AUTHOR_COMPONENT, GLOBAL_WEB_SOCKET_SERVER_COMPONENT, + 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}, @@ -62,7 +63,7 @@ use itp_component_container::{ComponentGetter, ComponentInitializer}; use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; use itp_settings::files::{ INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, - TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, + 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, @@ -110,6 +111,12 @@ pub(crate) fn init_enclave( )?); GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL.initialize(target_a_light_client_seal); + let target_b_light_client_seal = Arc::new(EnclaveLightClientSeal::new( + base_dir.join(TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), + ParentchainId::TargetB, + )?); + GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL.initialize(target_b_light_client_seal); + let state_file_io = Arc::new(EnclaveStateFileIo::new(state_key_repository, StateDir::new(base_dir))); let state_initializer = diff --git a/enclave-runtime/src/initialization/parentchain/common.rs b/enclave-runtime/src/initialization/parentchain/common.rs index 998e3398..c2b6abea 100644 --- a/enclave-runtime/src/initialization/parentchain/common.rs +++ b/enclave-runtime/src/initialization/parentchain/common.rs @@ -28,6 +28,8 @@ use crate::{ IntegriteeParentchainTriggeredBlockImportDispatcher, TargetAParentchainBlockImportDispatcher, TargetAParentchainBlockImporter, TargetAParentchainImmediateBlockImportDispatcher, TargetAParentchainIndirectExecutor, + TargetBParentchainBlockImportDispatcher, TargetBParentchainBlockImporter, + TargetBParentchainImmediateBlockImportDispatcher, TargetBParentchainIndirectExecutor, 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, @@ -104,6 +106,37 @@ pub(crate) fn create_target_a_parentchain_block_importer( )) } +pub(crate) fn create_target_b_parentchain_block_importer( + validator_access: Arc, + stf_executor: Arc, + extrinsics_factory: Arc, + node_metadata_repository: Arc, +) -> Result { + let state_observer = GLOBAL_STATE_OBSERVER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + let shielding_key_repository = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get()?; + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + + let stf_enclave_signer = Arc::new(EnclaveStfEnclaveSigner::new( + state_observer, + ocall_api, + shielding_key_repository.clone(), + top_pool_author.clone(), + )); + let indirect_calls_executor = Arc::new(TargetBParentchainIndirectExecutor::new( + shielding_key_repository, + stf_enclave_signer, + top_pool_author, + node_metadata_repository, + )); + Ok(TargetBParentchainBlockImporter::new( + validator_access, + stf_executor, + extrinsics_factory, + indirect_calls_executor, + )) +} + pub(crate) fn create_extrinsics_factory( genesis_hash: H256, nonce_cache: Arc, @@ -179,6 +212,36 @@ pub(crate) fn create_target_a_offchain_immediate_import_dispatcher( )))) } +pub(crate) fn create_target_b_offchain_immediate_import_dispatcher( + stf_executor: Arc, + block_importer: TargetBParentchainBlockImporter, + validator_access: Arc, + extrinsics_factory: Arc, +) -> Result> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + + let offchain_worker_executor = Arc::new(EnclaveOffchainWorkerExecutor::new( + top_pool_author, + stf_executor, + state_handler, + validator_access, + extrinsics_factory, + )); + let immediate_dispatcher = TargetBParentchainImmediateBlockImportDispatcher::new( + block_importer, + ) + .with_observer(move || { + if let Err(e) = offchain_worker_executor.execute() { + error!("Failed to execute trusted calls: {:?}", e); + } + }); + + Ok(Arc::new(TargetBParentchainBlockImportDispatcher::new_immediate_dispatcher(Arc::new( + immediate_dispatcher, + )))) +} + pub(crate) fn create_sidechain_triggered_import_dispatcher( block_importer: IntegriteeParentchainBlockImporter, ) -> Arc { diff --git a/enclave-runtime/src/initialization/parentchain/mod.rs b/enclave-runtime/src/initialization/parentchain/mod.rs index b120e29b..a2338009 100644 --- a/enclave-runtime/src/initialization/parentchain/mod.rs +++ b/enclave-runtime/src/initialization/parentchain/mod.rs @@ -23,10 +23,14 @@ use crate::{ 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, }, parentchain::{ target_a_parachain::TargetAParachainHandler, target_a_solochain::TargetASolochainHandler, + target_b_parachain::TargetBParachainHandler, + target_b_solochain::TargetBSolochainHandler, }, }, }; @@ -46,6 +50,8 @@ pub mod integritee_parachain; pub mod integritee_solochain; pub mod target_a_parachain; pub mod target_a_solochain; +pub mod target_b_parachain; +pub mod target_b_solochain; pub(crate) fn init_parentchain_components( base_path: PathBuf, @@ -71,6 +77,15 @@ pub(crate) fn init_parentchain_components GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.initialize(handler.into()); Ok(header.encode()) }, + ParentchainId::TargetB => { + let handler = + TargetBParachainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, }, ParentchainInitParams::Solochain { id, params } => match id { ParentchainId::Integritee => { @@ -91,6 +106,15 @@ pub(crate) fn init_parentchain_components GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.initialize(handler.into()); Ok(header.encode()) }, + ParentchainId::TargetB => { + let handler = + TargetBSolochainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, }, } } diff --git a/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs b/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs new file mode 100644 index 00000000..bd1b628b --- /dev/null +++ b/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs @@ -0,0 +1,122 @@ +/* + 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. + +*/ + +//! Naive implementation of adding a second parachain handler to the setup. +//! +//! Ideally, most of the redundant code can be abstracted away, but it turns out +//! that this is quite tedious, so for now this is a copy-past of the [IntegriteeParachainHandler]: +//! * https://github.com/integritee-network/worker/issues/1417 + +use crate::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, TargetBParentchainBlockImportDispatcher, + GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, + }, + parentchain::common::{ + create_extrinsics_factory, create_target_b_offchain_immediate_import_dispatcher, + create_target_b_parentchain_block_importer, + }, + }, +}; +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}; + +pub use itc_parentchain::primitives::{ParachainBlock, ParachainHeader, ParachainParams}; + +#[derive(Clone)] +pub struct TargetBParachainHandler { + pub genesis_header: ParachainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl TargetBParachainHandler { + 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()); + + let genesis_header = params.genesis_header.clone(); + + let light_client_seal = GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let validator = itc_parentchain::light_client::io::read_or_init_parachain_validator::< + ParachainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::TargetB)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_target_b_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + 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 => + unimplemented!("Can't run target B chain in sidechain mode yet."), + WorkerMode::Teeracle => + Arc::new(TargetBParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let parachain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(parachain_handler) + } +} diff --git a/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs b/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs new file mode 100644 index 00000000..d3ec66be --- /dev/null +++ b/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs @@ -0,0 +1,115 @@ +/* + 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::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, TargetBParentchainBlockImportDispatcher, + GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, + }, + parentchain::common::{ + create_extrinsics_factory, create_target_b_offchain_immediate_import_dispatcher, + create_target_b_parentchain_block_importer, + }, + }, +}; +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}; + +pub use itc_parentchain::primitives::{SolochainBlock, SolochainHeader, SolochainParams}; + +pub struct TargetBSolochainHandler { + pub genesis_header: SolochainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl TargetBSolochainHandler { + 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()?; + let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); + + let genesis_header = params.genesis_header.clone(); + + let validator = itc_parentchain::light_client::io::read_or_init_grandpa_validator::< + SolochainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::TargetB)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_target_b_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + 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 => + unimplemented!("Can't run target B chain in sidechain mode yet."), + WorkerMode::Teeracle => + Arc::new(TargetBParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let solochain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(solochain_handler) + } +} diff --git a/enclave-runtime/src/lib.rs b/enclave-runtime/src/lib.rs index 0e9640e9..3379bcfe 100644 --- a/enclave-runtime/src/lib.rs +++ b/enclave-runtime/src/lib.rs @@ -37,11 +37,14 @@ use crate::{ 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, }, 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, utf8_str_from_raw, DecodeRaw, + get_node_metadata_repository_from_target_a_solo_or_parachain, + get_node_metadata_repository_from_target_b_solo_or_parachain, utf8_str_from_raw, DecodeRaw, }, }; use codec::Decode; @@ -234,6 +237,7 @@ pub unsafe extern "C" fn set_nonce( let nonce_lock = match id { ParentchainId::Integritee => GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE.load_for_mutation(), ParentchainId::TargetA => GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE.load_for_mutation(), + ParentchainId::TargetB => GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE.load_for_mutation(), }; match nonce_lock { @@ -276,6 +280,7 @@ pub unsafe extern "C" fn set_node_metadata( ParentchainId::Integritee => get_node_metadata_repository_from_integritee_solo_or_parachain(), ParentchainId::TargetA => get_node_metadata_repository_from_target_a_solo_or_parachain(), + ParentchainId::TargetB => get_node_metadata_repository_from_target_b_solo_or_parachain(), }; match node_metadata_repository { @@ -519,6 +524,15 @@ fn dispatch_parentchain_blocks_for_import return Err(Error::NoTargetAParentchainAssigned) }; }, + ParentchainId::TargetB => { + if let Ok(handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import(blocks_to_sync, events_to_sync)?; + } else if let Ok(handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import(blocks_to_sync, events_to_sync)?; + } else { + return Err(Error::NoTargetBParentchainAssigned) + }; + }, } Ok(()) @@ -625,6 +639,23 @@ fn internal_trigger_parentchain_block_import(id: &ParentchainId) -> Result<()> { return Err(Error::NoTargetAParentchainAssigned) } }, + ParentchainId::TargetB => { + if let Ok(handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler + .import_dispatcher + .triggered_dispatcher() + .ok_or(Error::ExpectedTriggeredImportDispatcher)? + .import_all()? + } else if let Ok(handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + handler + .import_dispatcher + .triggered_dispatcher() + .ok_or(Error::ExpectedTriggeredImportDispatcher)? + .import_all()? + } else { + return Err(Error::NoTargetBParentchainAssigned) + } + }, }; Ok(()) diff --git a/enclave-runtime/src/utils.rs b/enclave-runtime/src/utils.rs index 3b3fac38..7635385d 100644 --- a/enclave-runtime/src/utils.rs +++ b/enclave-runtime/src/utils.rs @@ -22,7 +22,8 @@ use crate::{ IntegriteeParentchainTriggeredBlockImportDispatcher, GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, - GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, }, }; use codec::{Decode, Input}; @@ -133,6 +134,19 @@ pub(crate) fn get_node_metadata_repository_from_target_a_solo_or_parachain( Ok(metadata_repository) } +pub(crate) fn get_node_metadata_repository_from_target_b_solo_or_parachain( +) -> Result> { + let metadata_repository = + if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.node_metadata_repository.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.node_metadata_repository.clone() + } else { + return Err(Error::NoTargetBParentchainAssigned) + }; + Ok(metadata_repository) +} + pub(crate) fn get_extrinsic_factory_from_solo_or_parachain() -> Result> { let extrinsics_factory = diff --git a/local-setup/config/two-nodes-one-worker.json b/local-setup/config/three-nodes-one-worker.json similarity index 70% rename from local-setup/config/two-nodes-one-worker.json rename to local-setup/config/three-nodes-one-worker.json index 21508ce4..f01b3251 100644 --- a/local-setup/config/two-nodes-one-worker.json +++ b/local-setup/config/three-nodes-one-worker.json @@ -36,6 +36,26 @@ "--ws-external", "--rpc-external" ] + }, + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--chain", + "dev3", + "--force-authoring", + "--alice", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9988", + "--port", + "30395", + "--rpc-port", + "9977", + "--ws-external", + "--rpc-external" + ] } ], "workers": [ @@ -51,6 +71,10 @@ "ws://127.0.0.1", "--target-a-parentchain-rpc-port", "9966", + "--target-b-parentchain-rpc-url", + "ws://127.0.0.1", + "--target-b-parentchain-rpc-port", + "9988", "-r", "3490", "-w", diff --git a/local-setup/py/worker.py b/local-setup/py/worker.py index 00a94d59..59f7387d 100644 --- a/local-setup/py/worker.py +++ b/local-setup/py/worker.py @@ -162,7 +162,8 @@ def run_in_background(self, log_file: TextIO, flags: [str] = None, subcommand_fl 'itp_stf_state_handler=debug,' 'its_consensus_common=debug,' 'its_consensus_aura=trace,' - 'itc_parentchain_indirect_calls_executor=trace,' + 'itc_parentchain_indirect_calls_executor=info,' + 'itc_parentchain_light_client=info,' 'itc_parentchain_block_importer=debug,' 'ita_stf=debug') worker_cmd = self._assemble_cmd(flags=flags, subcommand_flags=subcommand_flags) diff --git a/local-setup/tmux_logger_two_nodes.sh b/local-setup/tmux_logger_three_nodes.sh similarity index 59% rename from local-setup/tmux_logger_two_nodes.sh rename to local-setup/tmux_logger_three_nodes.sh index e1666b9b..5856e910 100755 --- a/local-setup/tmux_logger_two_nodes.sh +++ b/local-setup/tmux_logger_three_nodes.sh @@ -13,20 +13,22 @@ ################################################################################# -if tmux has-session -t integritee_logger_two_nodes ; then +if tmux has-session -t integritee_logger_three_nodes ; then echo "detected existing polkadot logger session, attaching..." else # or start it up freshly - tmux new-session -d -s integritee_logger_two_nodes \; \ + tmux new-session -d -s integritee_logger_three_nodes \; \ + split-window -v \; \ split-window -v \; \ split-window -v \; \ select-layout even-vertical \; \ - send-keys -t integritee_logger_two_nodes:0.0 'tail -f ../log/node1.log' C-m \; \ - send-keys -t integritee_logger_two_nodes:0.1 'tail -f ../log/node2.log' C-m \; \ - send-keys -t integritee_logger_two_nodes:0.2 'tail -f ../log/worker1.log' C-m \; \ + send-keys -t integritee_logger_three_nodes:0.0 'tail -f ../log/node1.log' C-m \; \ + send-keys -t integritee_logger_three_nodes:0.1 'tail -f ../log/node2.log' C-m \; \ + send-keys -t integritee_logger_three_nodes:0.2 'tail -f ../log/node3.log' C-m \; \ + send-keys -t integritee_logger_three_nodes:0.3 'tail -f ../log/worker1.log' C-m \; \ # Attention: Depending on your tmux conf, indexes may start at 1 tmux setw -g mouse on fi -tmux attach-session -d -t integritee_logger_two_nodes \ No newline at end of file +tmux attach-session -d -t integritee_logger_three_nodes \ No newline at end of file diff --git a/service/src/cli.yml b/service/src/cli.yml index 98ecfe4b..c4847ca2 100644 --- a/service/src/cli.yml +++ b/service/src/cli.yml @@ -34,6 +34,16 @@ args: help: Set the port of the optional Target A parentchain RPC endpoint. takes_value: true required: false + - target-b-parentchain-rpc-url: + long: target-b-parentchain-rpc-url + help: Set the url and the protocol of an optional Target B parentchain RPC endpoint that contains your business logic specific pallets. + takes_value: true + required: false + - target-b-parentchain-rpc-port: + long: target-b-parentchain-rpc-port + help: Set the port of the optional Target B parentchain RPC endpoint. + takes_value: true + required: false - data-dir: short: d long: data-dir diff --git a/service/src/config.rs b/service/src/config.rs index 87050742..3d42180a 100644 --- a/service/src/config.rs +++ b/service/src/config.rs @@ -40,6 +40,8 @@ pub struct Config { integritee_rpc_port: String, target_a_parentchain_rpc_url: Option, target_a_parentchain_rpc_port: Option, + target_b_parentchain_rpc_url: Option, + target_b_parentchain_rpc_port: Option, worker_ip: String, /// Trusted worker address that will be advertised on the parentchain. trusted_external_worker_address: Option, @@ -72,6 +74,8 @@ impl Config { integritee_rpc_port: String, target_a_parentchain_rpc_url: Option, target_a_parentchain_rpc_port: Option, + target_b_parentchain_rpc_url: Option, + target_b_parentchain_rpc_port: Option, worker_ip: String, trusted_external_worker_address: Option, trusted_worker_port: String, @@ -90,6 +94,8 @@ impl Config { integritee_rpc_port, target_a_parentchain_rpc_url, target_a_parentchain_rpc_port, + target_b_parentchain_rpc_url, + target_b_parentchain_rpc_port, worker_ip, trusted_external_worker_address, trusted_worker_port, @@ -125,6 +131,21 @@ impl Config { None } + pub fn target_b_parentchain_rpc_endpoint(&self) -> Option { + if self.target_b_parentchain_rpc_url.is_some() + && self.target_b_parentchain_rpc_port.is_some() + { + return Some(format!( + "{}:{}", + // Can be done better, but this code is obsolete anyhow with clap v4. + self.target_b_parentchain_rpc_url.clone().unwrap(), + self.target_b_parentchain_rpc_port.clone().unwrap() + )) + }; + + None + } + pub fn trusted_worker_url_internal(&self) -> String { format!("{}:{}", self.worker_ip, self.trusted_worker_port) } @@ -217,6 +238,8 @@ impl From<&ArgMatches<'_>> for Config { m.value_of("integritee-rpc-port").unwrap_or(DEFAULT_INTEGRITEE_RPC_PORT).into(), m.value_of("target-a-parentchain-rpc-url").map(Into::into), m.value_of("target-a-parentchain-rpc-port").map(Into::into), + m.value_of("target-b-parentchain-rpc-url").map(Into::into), + m.value_of("target-b-parentchain-rpc-port").map(Into::into), if m.is_present("ws-external") { "0.0.0.0".into() } else { "127.0.0.1".into() }, m.value_of("trusted-external-address") .map(|url| add_port_if_necessary(url, trusted_port)), @@ -360,6 +383,8 @@ mod test { assert_eq!(config.integritee_rpc_port, DEFAULT_INTEGRITEE_RPC_PORT); assert_eq!(config.target_a_parentchain_rpc_url, None); assert_eq!(config.target_a_parentchain_rpc_port, None); + assert_eq!(config.target_b_parentchain_rpc_url, None); + assert_eq!(config.target_b_parentchain_rpc_port, None); assert_eq!(config.trusted_worker_port, DEFAULT_TRUSTED_PORT); assert_eq!(config.untrusted_worker_port, DEFAULT_UNTRUSTED_PORT); assert_eq!(config.mu_ra_port, DEFAULT_MU_RA_PORT); diff --git a/service/src/main.rs b/service/src/main.rs index d8e17449..077b30d6 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -172,10 +172,15 @@ fn main() { .target_a_parentchain_rpc_endpoint() .map(|url| Arc::new(NodeApiFactory::new(url, AccountKeyring::Alice.pair()))); + let maybe_target_b_parentchain_api_factory = config + .target_b_parentchain_rpc_endpoint() + .map(|url| Arc::new(NodeApiFactory::new(url, AccountKeyring::Alice.pair()))); + // initialize o-call bridge with a concrete factory implementation OCallBridge::initialize(Arc::new(OCallBridgeComponentFactory::new( node_api_factory.clone(), maybe_target_a_parentchain_api_factory, + maybe_target_b_parentchain_api_factory, sync_block_broadcaster, enclave.clone(), sidechain_blockstorage.clone(), @@ -592,14 +597,30 @@ fn start_worker( } if let Some(url) = config.target_a_parentchain_rpc_endpoint() { - init_target_a_parentchain(&enclave, &tee_accountid, url, is_development_mode) + init_target_parentchain( + &enclave, + &tee_accountid, + url, + ParentchainId::TargetA, + is_development_mode, + ) + } + + if let Some(url) = config.target_b_parentchain_rpc_endpoint() { + init_target_parentchain( + &enclave, + &tee_accountid, + url, + ParentchainId::TargetB, + is_development_mode, + ) } // ------------------------------------------------------------------------ // Subscribe to events and print them. - println!("*** Subscribing to events"); + println!("*** [{:?}] Subscribing to events", ParentchainId::Integritee); let mut subscription = integritee_rpc_api.subscribe_events().unwrap(); - println!("[+] Subscribed to events. waiting..."); + println!("[+] [{:?}] Subscribed to events. waiting...", ParentchainId::Integritee); loop { if let Some(Ok(events)) = subscription.next_event::() { print_events(events) @@ -607,27 +628,34 @@ fn start_worker( } } -fn init_target_a_parentchain( +fn init_target_parentchain( enclave: &Arc, tee_account_id: &AccountId32, url: String, + parentchain_id: ParentchainId, is_development_mode: bool, ) where E: EnclaveBase + Sidechain, { + println!("Initializing parentchain {:?} with url: {}", parentchain_id, url); let node_api = NodeApiFactory::new(url, AccountKeyring::Alice.pair()) .create_api() - .expect("Failed to create Target A parentchain node API"); + .unwrap_or_else(|_| panic!("[{:?}] Failed to create parentchain node API", parentchain_id)); // some random bytes not too small to ensure that the enclave has enough funds setup_account_funding(&node_api, tee_account_id, [0u8; 100].into(), is_development_mode) - .expect("Could not fund Target A parentchain enclave account"); + .unwrap_or_else(|_| { + panic!("[{:?}] Could not fund parentchain enclave account", parentchain_id) + }); let (parentchain_handler, last_synched_header) = - init_parentchain(enclave, &node_api, tee_account_id, ParentchainId::TargetA); + init_parentchain(enclave, &node_api, tee_account_id, parentchain_id); if WorkerModeProvider::worker_mode() != WorkerMode::Teeracle { - println!("*** [+] Finished initializing Target A parentchain light client, syncing parentchain..."); + println!( + "*** [+] [{:?}] Finished initializing light client, syncing parentchain...", + parentchain_id + ); // Syncing all parentchain blocks, this might take a while.. let last_synched_header = @@ -635,25 +663,28 @@ fn init_target_a_parentchain( // start parentchain syncing loop (subscribe to header updates) thread::Builder::new() - .name("target_a_parentchain_sync_loop".to_owned()) + .name(format!("{:?}_parentchain_sync_loop", parentchain_id)) .spawn(move || { if let Err(e) = subscribe_to_parentchain_new_headers(parentchain_handler, last_synched_header) { - error!("Target A parentchain block syncing terminated with a failure: {:?}", e); + error!( + "[{:?}] parentchain block syncing terminated with a failure: {:?}", + parentchain_id, e + ); } - println!("[!] Target A parentchain block syncing has terminated"); + println!("[!] [{:?}] parentchain block syncing has terminated", parentchain_id); }) .unwrap(); } // Subscribe to events and print them. - println!("*** Subscribing to events of Target A chain"); + println!("*** [{:?}] Subscribing to events...", parentchain_id); let mut subscription = node_api.subscribe_events().unwrap(); - println!("[+] Subscribed to events. waiting..."); + println!("[+] [{:?}] Subscribed to events. waiting...", parentchain_id); thread::Builder::new() - .name("target_a_parentchain_event_subscription".to_owned()) + .name(format!("{:?}_parentchain_event_subscription", parentchain_id)) .spawn(move || loop { if let Some(Ok(events)) = subscription.next_event::() { print_events(events) @@ -680,13 +711,13 @@ where .unwrap(), ); let last_synced_header = parentchain_handler.init_parentchain_components().unwrap(); - trace!("last synched parentchain block: {}", last_synced_header.number); + println!("[{:?}] last synced parentchain block: {}", parentchain_id, last_synced_header.number); let nonce = node_api.get_nonce_of(tee_account_id).unwrap(); - info!("Enclave nonce = {:?}", nonce); - enclave - .set_nonce(nonce, parentchain_id) - .expect("Could not set nonce of enclave. Returning here..."); + 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) + }); let metadata = node_api.metadata().clone(); let runtime_spec_version = node_api.runtime_version().spec_version; @@ -696,7 +727,10 @@ where NodeMetadata::new(metadata, runtime_spec_version, runtime_transaction_version).encode(), parentchain_id, ) - .expect("Could not set the node metadata in the enclave"); + .unwrap_or_else(|_| { + panic!("[{:?}] Could not set the node metadata in the enclave", parentchain_id) + }); + (parentchain_handler, last_synced_header) } diff --git a/service/src/ocall_bridge/bridge_api.rs b/service/src/ocall_bridge/bridge_api.rs index 8d58bd04..9fc3e8ee 100644 --- a/service/src/ocall_bridge/bridge_api.rs +++ b/service/src/ocall_bridge/bridge_api.rs @@ -143,6 +143,8 @@ pub enum OCallBridgeError { NodeApiFactory(#[from] itp_node_api::node_api_factory::NodeApiFactoryError), #[error("Target A parentchain not initialized")] TargetAParentchainNotInitialized, + #[error("Target B parentchain not initialized")] + TargetBParentchainNotInitialized, } impl From for sgx_status_t { diff --git a/service/src/ocall_bridge/component_factory.rs b/service/src/ocall_bridge/component_factory.rs index f6dcdc0e..83bc4425 100644 --- a/service/src/ocall_bridge/component_factory.rs +++ b/service/src/ocall_bridge/component_factory.rs @@ -55,6 +55,7 @@ pub struct OCallBridgeComponentFactory< > { 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, @@ -89,6 +90,7 @@ impl< 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, @@ -100,6 +102,7 @@ impl< OCallBridgeComponentFactory { integritee_rpc_api_factory, target_a_parentchain_rpc_api_factory, + target_b_parentchain_rpc_api_factory, block_broadcaster, enclave_api, block_storage, @@ -158,6 +161,7 @@ impl< Arc::new(WorkerOnChainOCall::new( self.integritee_rpc_api_factory.clone(), self.target_a_parentchain_rpc_api_factory.clone(), + self.target_b_parentchain_rpc_api_factory.clone(), )) } diff --git a/service/src/ocall_bridge/worker_on_chain_ocall.rs b/service/src/ocall_bridge/worker_on_chain_ocall.rs index 272e45b3..b178015f 100644 --- a/service/src/ocall_bridge/worker_on_chain_ocall.rs +++ b/service/src/ocall_bridge/worker_on_chain_ocall.rs @@ -29,14 +29,20 @@ use substrate_api_client::{serde_impls::StorageKey, GetStorage, SubmitExtrinsic} pub struct WorkerOnChainOCall { integritee_api_factory: Arc, target_a_parentchain_api_factory: Option>, + target_b_parentchain_api_factory: Option>, } impl WorkerOnChainOCall { pub fn new( integritee_api_factory: Arc, target_a_parentchain_api_factory: Option>, + target_b_parentchain_api_factory: Option>, ) -> Self { - WorkerOnChainOCall { integritee_api_factory, target_a_parentchain_api_factory } + WorkerOnChainOCall { + integritee_api_factory, + target_a_parentchain_api_factory, + target_b_parentchain_api_factory, + } } } @@ -49,6 +55,11 @@ impl WorkerOnChainOCall { .as_ref() .ok_or(OCallBridgeError::TargetAParentchainNotInitialized) .and_then(|f| f.create_api().map_err(Into::into))?, + ParentchainId::TargetB => self + .target_b_parentchain_api_factory + .as_ref() + .ok_or(OCallBridgeError::TargetBParentchainNotInitialized) + .and_then(|f| f.create_api().map_err(Into::into))?, }) } } @@ -155,7 +166,7 @@ mod tests { let mock_node_api_factory = Arc::new(MockNodeApiFactory::new()); - let on_chain_ocall = WorkerOnChainOCall::new(mock_node_api_factory, None); + let on_chain_ocall = WorkerOnChainOCall::new(mock_node_api_factory, None, None); let response = on_chain_ocall .worker_request(Vec::::new().encode(), ParentchainId::Integritee.encode()) diff --git a/service/src/parentchain_handler.rs b/service/src/parentchain_handler.rs index ee02dc0c..78e39606 100644 --- a/service/src/parentchain_handler.rs +++ b/service/src/parentchain_handler.rs @@ -89,7 +89,7 @@ where let grandpas = parentchain_api.grandpa_authorities(Some(genesis_hash))?; let grandpa_proof = parentchain_api.grandpa_authorities_proof(Some(genesis_hash))?; - debug!("Grandpa Authority List: \n {:?} \n ", grandpas); + debug!("[{:?}] Grandpa Authority List: \n {:?} \n ", id, grandpas); let authority_list = VersionedAuthorityList::from(grandpas); @@ -123,20 +123,26 @@ where } fn sync_parentchain(&self, last_synced_header: Header) -> ServiceResult
{ - trace!("Getting current head"); + let id = self.parentchain_id(); + trace!("[{:?}] Getting current head", id); let curr_block = self .parentchain_api .last_finalized_block()? .ok_or(Error::MissingLastFinalizedBlock)?; let curr_block_number = curr_block.block.header.number; + println!( + "[{:?}] Syncing blocks from {} to {}", + id, last_synced_header.number, curr_block_number + ); + let mut until_synced_header = last_synced_header; loop { let block_chunk_to_sync = self.parentchain_api.get_blocks( until_synced_header.number + 1, min(until_synced_header.number + BLOCK_SYNC_BATCH_SIZE, curr_block_number), )?; - println!("[+] Found {} block(s) to sync", block_chunk_to_sync.len()); + println!("[+] [{:?}] Found {} block(s) to sync", id, block_chunk_to_sync.len()); if block_chunk_to_sync.is_empty() { return Ok(until_synced_header) } @@ -148,7 +154,7 @@ where }) .collect::, _>>()?; - println!("[+] Found {} event vector(s) to sync", events_chunk_to_sync.len()); + println!("[+] [{:?}] Found {} event vector(s) to sync", id, events_chunk_to_sync.len()); let events_proofs_chunk_to_sync: Vec = block_chunk_to_sync .iter() @@ -169,14 +175,14 @@ where .map(|b| b.block.header.clone()) .ok_or(Error::EmptyChunk)?; println!( - "Synced {} out of {} finalized parentchain blocks", - until_synced_header.number, curr_block_number, + "[{:?}] Synced {} out of {} finalized parentchain blocks", + id, until_synced_header.number, curr_block_number, ) } } fn trigger_parentchain_block_import(&self) -> ServiceResult<()> { - trace!("trigger parentchain block import"); + trace!("[{:?}] trigger parentchain block import", self.parentchain_id()); Ok(self.enclave_api.trigger_parentchain_block_import(self.parentchain_id())?) } @@ -185,8 +191,11 @@ where last_synced_header: &Header, until_header: &Header, ) -> ServiceResult
{ + let id = self.parentchain_id(); + trace!( - "last synched block number: {}. synching until {}", + "[{:?}] last synced block number: {}. synching until {}", + id, last_synced_header.number, until_header.number ); @@ -194,7 +203,7 @@ where while last_synced_header.number() < until_header.number() { last_synced_header = self.sync_parentchain(last_synced_header)?; - trace!("synched block number: {}", last_synced_header.number); + trace!("[{:?}] synced block number: {}", id, last_synced_header.number); } self.trigger_parentchain_block_import()?; diff --git a/service/src/setup.rs b/service/src/setup.rs index 7e7c59cd..d58dac88 100644 --- a/service/src/setup.rs +++ b/service/src/setup.rs @@ -23,6 +23,7 @@ use itp_enclave_api::{enclave_base::EnclaveBase, Enclave}; use itp_settings::files::{ INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, SHARDS_PATH, SHIELDING_KEY_FILE, SIDECHAIN_STORAGE_PATH, SIGNING_KEY_FILE, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, + TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, }; use itp_types::ShardIdentifier; use log::*; @@ -99,6 +100,7 @@ fn purge_files(root_directory: &Path) -> ServiceResult<()> { remove_dir_if_it_exists(root_directory, INTEGRITEE_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)?; Ok(()) } @@ -138,6 +140,8 @@ mod tests { .unwrap(); fs::create_dir_all(&root_directory.join(TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)) .unwrap(); + fs::create_dir_all(&root_directory.join(TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)) + .unwrap(); purge_files(&root_directory).unwrap(); @@ -145,6 +149,7 @@ mod tests { assert!(!sidechain_db_path.exists()); assert!(!root_directory.join(INTEGRITEE_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()); } #[test] diff --git a/service/src/tests/commons.rs b/service/src/tests/commons.rs index 012cb1ad..f8702016 100644 --- a/service/src/tests/commons.rs +++ b/service/src/tests/commons.rs @@ -42,6 +42,8 @@ pub fn local_worker_config( Default::default(), Default::default(), Default::default(), + Default::default(), + Default::default(), url.next().unwrap().into(), None, url.next().unwrap().into(),