diff --git a/app-libs/stf/src/stf_sgx.rs b/app-libs/stf/src/stf_sgx.rs index 54dd3d96a9..e7871b4755 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 f96e59d5d6..0f6e4f2b9b 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 bff2cdd0ab..5cd73b0061 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 009f859604..b1c42dfce6 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 0000000000..4ec7ac50fe --- /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 18abc0cb9a..cb32046af2 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 f6b1f1b93e..91aa437564 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 1c3ceb4c55..e41729c12f 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 99caf605f9..9e97ad2aa2 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 ba64ee8fa8..895c55cb58 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 9bb8920b4a..cbdfcd09a0 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 86ffceaeb9..def5d3ee47 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 196852c3f0..572b671764 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 9bb09a21fb..c290c2ab32 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 0000000000..185f0efff3 --- /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 e28061cf1d..a1e515ac65 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 c47bbfd931..2bd1ca2104 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 aa70e4b74d..0567e88b70 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 161bd5824c..3c5f53afb9 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 af9d88ba81..f2af1c75be 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 4137834625..66ae77495b 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 83f90d2fb6..c4c314cc27 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 8a96dde164..1ed4efdc0f 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 c8d57df86c..1d674833af 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 7cb9831647..fc4a000178 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 0074ee3af5..b83749d249 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 55231dfffb..423f73236f 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 0a919f5390..b77805d111 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 c25aa51717..4f2da407de 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 0000000000..869e74f3ec --- /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 3cc0efcf34..9e069bc2ec 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 f6482c9233..fda60d74b0 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 9937729c15..661934fe31 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 61baf247ee..114d684382 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 ea8bd53ad9..e23761b098 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 7a182d130e..107008f98d 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 a199a10c45..055672ea6e 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 29ab55e6eb..c8cf058ec1 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 f45fecbded..ae609f279b 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 3519bad137..64eecb83d8 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 d3fd7789fa..0e9a74b390 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 d2e113fa7d..d1484acbfe 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 91ce1a12b4..998e3398ab 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 7b43450e6b..f13961aa8a 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 0000000000..d84624f0e6 --- /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 2206289d5c..b120e29bed 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 0000000000..56bb011919 --- /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 87efa644a5..60259eedbe 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 750b05b93b..0e9640e9ea 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 c79cd6c19a..4db3bbbba4 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 913a0a7d53..d79c5d5540 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 9436cb1aae..460357fc94 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 1621a206eb..ec543b1718 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 a78d648b06..6f3d7a252e 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 bd5ad1156b..0000000000 --- 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 db3b3b9119..3d48b8fbc8 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 9eb1546b2a..630f8877d3 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 836b146b9d..e47ca50ed8 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 31310d783d..3b3fac3876 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 38caa5998e..f997396e3a 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 477c9c85d3..dae7125985 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 0000000000..21508ce4c0 --- /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 6d5e2316da..dc9fe7cf5f 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 36bdd669d9..071929734c 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 e9bf284ed7..00a94d5975 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 0000000000..e1666b9b93 --- /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 2faedcf9d6..98ecfe4b9f 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 4b441b173c..8705074223 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 25a837772a..d8e1744965 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 78800641d3..8d58bd0448 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 b15e3116bf..f6dcdc0e75 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 19bf289c24..d9e5220507 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 64820175bf..7dbd9be957 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 1dfea987cf..272e45b307 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 b0a9c44395..ee02dc0c9e 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 6535091f26..7e7c59cd86 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 c78ce4d949..012cb1ad09 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 21a64323be..9bebb76646 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 d3006639b1..78af8525f5 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 3f0c099917..84d77026cf 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