From e58c082daf874ad57a60624ea92f29714a8f4c62 Mon Sep 17 00:00:00 2001 From: smtmfft <99081233+smtmfft@users.noreply.github.com> Date: Mon, 20 May 2024 17:22:48 +0800 Subject: [PATCH] feat(raiko): update docker build (#225) * feat(raiko): update docker build * fix docker compose & fmt * fix entrypoint.sh * feat: Add anyhow crate as a dependency --------- Co-authored-by: john xu --- Cargo.lock | 1 + Dockerfile | 2 + docker/docker-compose.yml | 10 +++- docker/entrypoint.sh | 26 ++++++++++ host/src/lib.rs | 2 +- provers/sgx/prover/Cargo.toml | 3 +- provers/sgx/prover/src/lib.rs | 4 +- provers/sgx/prover/src/sgx_register_utils.rs | 25 ++++++++- provers/sgx/setup/src/setup_bootstrap.rs | 54 ++++++++++---------- 9 files changed, 94 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f455865d..05a72a7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6291,6 +6291,7 @@ dependencies = [ "alloy-signer-wallet 0.1.0 (git+https://github.com/brechtpd/alloy?branch=175_4e22b9e)", "alloy-sol-types", "alloy-transport-http 0.1.0 (git+https://github.com/brechtpd/alloy?branch=175_4e22b9e)", + "anyhow", "bincode", "once_cell", "pem 3.0.4", diff --git a/Dockerfile b/Dockerfile index b464e7af..179981da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,6 +33,7 @@ RUN curl -o setup.sh -sL https://deb.nodesource.com/setup_18.x && \ libsgx-dcap-ql \ libsgx-urts \ sgx-pck-id-retrieval-tool \ + jq \ sudo && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -49,6 +50,7 @@ COPY --from=builder /opt/raiko/docker/entrypoint.sh ./bin/ COPY --from=builder /opt/raiko/provers/sgx/config/sgx-guest.docker.manifest.template ./provers/sgx/config/sgx-guest.local.manifest.template # copy to /etc/raiko, but if self register mode, the mounted one will overwrite it. COPY --from=builder /opt/raiko/host/config/config.sgx.json /etc/raiko/ +COPY --from=builder /opt/raiko/host/config/chain_spec_list_default.json /etc/raiko/chain_spec_list.docker.json COPY --from=builder /opt/raiko/target/release/sgx-guest ./bin/ COPY --from=builder /opt/raiko/target/release/raiko-host ./bin/ COPY --from=builder /opt/raiko/target/release/raiko-setup ./bin/ diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index e7697f02..4748a1ea 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -40,6 +40,9 @@ services: - L1_RPC=${L1_RPC} - L1_CHAIN_ID=${L1_CHAIN_ID} - SGX_VERIFIER_ADDRESS=${SGX_VERIFIER_ADDRESS} + - HOLESKY_RPC=${HOLESKY_RPC} + - HOLESKY_BEACON_RPC=${HOLESKY_BEACON_RPC} + - TAIKO_A7_RPC=${TAIKO_A7_RPC} #- PCCS_HOST=host.docker.internal:8081 depends_on: - pccs @@ -49,7 +52,7 @@ services: dockerfile: Dockerfile image: gcr.io/evmchain/raiko:latest container_name: raiko - command: --config-path=/etc/raiko/config.sgx.json + command: --config-path=/etc/raiko/config.sgx.json --chain-spec-path=/etc/raiko/chain_spec_list.docker.json devices: - "/dev/sgx_enclave:/dev/sgx_enclave" - "/dev/sgx_provision:/dev/sgx_provision" @@ -63,6 +66,9 @@ services: # Set to 0 (which is the default) to run on real hardware; use 1 for testing - SGX_DIRECT=${SGX_DIRECT} - SGX_INSTANCE_ID=${SGX_INSTANCE_ID} + - HOLESKY_RPC=${HOLESKY_RPC} + - HOLESKY_BEACON_RPC=${HOLESKY_BEACON_RPC} + - TAIKO_A7_RPC=${TAIKO_A7_RPC} # you can use your own PCCS host #- PCCS_HOST=host.docker.internal:8081 # use the host's network to connect to the PCCS @@ -76,7 +82,7 @@ services: dockerfile: Dockerfile image: gcr.io/evmchain/raiko-self-register:latest container_name: raiko-self-register - command: --config-path=/etc/raiko/config.sgx.json + command: --config-path=/etc/raiko/config.sgx.json --chain-spec-path=/etc/raiko/chain_spec_list.docker.json devices: - "/dev/sgx_enclave:/dev/sgx_enclave" - "/dev/sgx_provision:/dev/sgx_provision" diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index ae43f8f4..d9774642 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -8,6 +8,7 @@ RAIKO_DOCKER_VOLUME_CONFIG_PATH="$RAIKO_DOCKER_VOLUME_PATH/config" RAIKO_DOCKER_VOLUME_SECRETS_PATH="$RAIKO_DOCKER_VOLUME_PATH/secrets" RAIKO_DOCKER_VOLUME_PRIV_KEY_PATH="$RAIKO_DOCKER_VOLUME_SECRETS_PATH/priv.key" RAIKO_APP_DIR="/opt/raiko/bin" +RAIKO_CONF_DIR="/etc/raiko" RAIKO_GUEST_APP_FILENAME="sgx-guest" RAIKO_GUEST_SETUP_FILENAME="raiko-setup" RAIKO_INPUT_MANIFEST_FILENAME="$RAIKO_GUEST_APP_FILENAME.docker.manifest.template" @@ -37,6 +38,29 @@ function bootstrap_with_self_register() { cd - } +function update_docker_chain_specs() { + CONFIG_FILE="$RAIKO_CONF_DIR/chain_spec_list.docker.json" + if [ ! -f $CONFIG_FILE ]; then + echo "chain_spec_list.docker.json file not found." + return 1 + fi + + if [ -n "${HOLESKY_RPC}" ]; then + jq --arg rpc "$HOLESKY_RPC" 'map(if .name == "holesky" then .rpc = $rpc else . end)' $CONFIG_FILE > /tmp/config_tmp.json && mv /tmp/config_tmp.json $CONFIG_FILE; + echo "Updated config.json with .rpc=$HOLESKY_RPC" + fi + + if [ -n "${HOLESKY_BEACON_RPC}" ]; then + jq --arg beacon_rpc "$HOLESKY_BEACON_RPC" 'map(if .name == "holesky" then .beacon_rpc = $beacon_rpc else . end)' $CONFIG_FILE > /tmp/config_tmp.json && mv /tmp/config_tmp.json $CONFIG_FILE; + echo "Updated config.json with .beacon_rpc=$HOLESKY_BEACON_RPC" + fi + + if [ -n "${TAIKO_A7_RPC}" ]; then + jq --arg taiko_a7_rpc "$TAIKO_A7_RPC" 'map(if .name == "taiko_a7" then .rpc = $taiko_a7_rpc else . end)' $CONFIG_FILE > /tmp/config_tmp.json && mv /tmp/config_tmp.json $CONFIG_FILE; + echo "Updated config.json with .taiko_a7_rpc=$TAIKO_A7_RPC" + fi +} + if [[ -z "${PCCS_HOST}" ]]; then MY_PCCS_HOST=pccs:8081 else @@ -66,5 +90,7 @@ else sed -i "s/123456/${SGX_INSTANCE_ID}/" /etc/raiko/config.sgx.json fi + update_docker_chain_specs + /opt/raiko/bin/raiko-host "$@" fi diff --git a/host/src/lib.rs b/host/src/lib.rs index dfeb5d81..3bc88ecd 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -152,11 +152,11 @@ impl ProverState { let chain_specs = if let Some(cs_path) = &opts.chain_spec_path { let chain_specs = SupportedChainSpecs::merge_from_file(cs_path.clone()) .unwrap_or(SupportedChainSpecs::default()); - info!("Supported chains: {:?}", chain_specs.supported_networks()); chain_specs } else { SupportedChainSpecs::default() }; + info!("Supported chains: {:?}", chain_specs); // Check if the cache path exists and create it if it doesn't. if let Some(cache_path) = &opts.cache_path { diff --git a/provers/sgx/prover/Cargo.toml b/provers/sgx/prover/Cargo.toml index 6a37ed51..604ff1b6 100644 --- a/provers/sgx/prover/Cargo.toml +++ b/provers/sgx/prover/Cargo.toml @@ -22,8 +22,9 @@ alloy-provider = { workspace = true } alloy-signer-wallet = { workspace = true } alloy-rpc-client = { workspace = true } alloy-transport-http = { workspace = true } -pem = {version = "3.0.4", optional = true} +pem = { version = "3.0.4", optional = true } url = { workspace = true } +anyhow = { workspace = true } [features] default = ["dep:pem"] diff --git a/provers/sgx/prover/src/lib.rs b/provers/sgx/prover/src/lib.rs index 2a22f751..414dde2a 100644 --- a/provers/sgx/prover/src/lib.rs +++ b/provers/sgx/prover/src/lib.rs @@ -20,7 +20,9 @@ use serde_json::Value; use serde_with::serde_as; use tokio::{process::Command, sync::OnceCell}; -pub use crate::sgx_register_utils::register_sgx_instance; +pub use crate::sgx_register_utils::{ + get_instance_id, register_sgx_instance, remove_instance_id, set_instance_id, +}; pub const PRIV_KEY_FILENAME: &str = "priv.key"; diff --git a/provers/sgx/prover/src/sgx_register_utils.rs b/provers/sgx/prover/src/sgx_register_utils.rs index 27a3f1b9..71c5493d 100644 --- a/provers/sgx/prover/src/sgx_register_utils.rs +++ b/provers/sgx/prover/src/sgx_register_utils.rs @@ -1,17 +1,38 @@ -use std::env; - use alloy_provider::{network::EthereumSigner, Provider, ProviderBuilder, RootProvider}; use alloy_rpc_client::RpcClient; use alloy_signer::Signer; use alloy_sol_types::sol; use alloy_transport_http::Http; +use anyhow::Result; use pem::parse_many; use raiko_primitives::{ alloy_eips::{BlockId, BlockNumberOrTag}, hex, Address, Bytes, FixedBytes, U256, }; +use std::{env, path::Path}; +use std::{fs, io}; use url::Url; +const REGISTERED_FILE: &str = "registered"; + +pub fn get_instance_id(dir: &Path) -> Result { + let file = dir.join(REGISTERED_FILE); + let id = fs::read_to_string(file)?.parse()?; + Ok(id) +} + +pub fn set_instance_id(dir: &Path, id: u64) -> io::Result<()> { + let file = dir.join(REGISTERED_FILE); + fs::write(file, id.to_string())?; + Ok(()) +} + +pub fn remove_instance_id(dir: &Path) -> io::Result<()> { + let file = dir.join(REGISTERED_FILE); + fs::remove_file(file)?; + Ok(()) +} + sol! { #[derive(Debug)] struct Header { diff --git a/provers/sgx/setup/src/setup_bootstrap.rs b/provers/sgx/setup/src/setup_bootstrap.rs index 4a0840f2..cc1d49b7 100644 --- a/provers/sgx/setup/src/setup_bootstrap.rs +++ b/provers/sgx/setup/src/setup_bootstrap.rs @@ -10,7 +10,10 @@ use crate::app_args::BootstrapArgs; use alloy_primitives::Address; use anyhow::{Context, Result}; use serde_json::{Number, Value}; -use sgx_prover::{bootstrap, check_bootstrap, register_sgx_instance, ELF_NAME}; +use sgx_prover::{ + bootstrap, check_bootstrap, get_instance_id, register_sgx_instance, remove_instance_id, + set_instance_id, ELF_NAME, +}; use std::process::Command; use tracing::info; @@ -31,19 +34,16 @@ pub(crate) async fn setup_bootstrap( cmd }; - let registered_check_file = PathBuf::from(&bootstrap_args.config_path) - .parent() - .unwrap() - .join("registered"); - + let mut instance_id = get_instance_id(&bootstrap_args.config_path).ok(); let need_init = check_bootstrap(secret_dir.clone(), gramine_cmd()) .await .is_err() - || fs::metadata(®istered_check_file).is_err(); + || instance_id.is_none(); if need_init { let bootstrap_proof = bootstrap(secret_dir, gramine_cmd()).await?; - match fs::remove_file(®istered_check_file) { + // clean check file + match remove_instance_id(&bootstrap_args.config_path) { Ok(_) => Ok(()), Err(e) => { if e.kind() == std::io::ErrorKind::NotFound { @@ -53,7 +53,7 @@ pub(crate) async fn setup_bootstrap( } } }?; - let _register_res = register_sgx_instance( + let register_id = register_sgx_instance( &bootstrap_proof.quote, &bootstrap_args.l1_rpc, bootstrap_args.l1_chain_id, @@ -61,25 +61,27 @@ pub(crate) async fn setup_bootstrap( ) .await .map_err(|e| anyhow::Error::msg(e.to_string()))?; - //todo: update the config - // Config file has the lowest preference - let file = File::open(&bootstrap_args.config_path)?; - let reader = BufReader::new(file); - let mut file_config: Value = serde_json::from_reader(reader)?; - file_config["sgx"]["instance_id"] = Value::Number(Number::from(_register_res)); + info!("Saving instance id {}", register_id,); + // set check file + set_instance_id(&bootstrap_args.config_path, register_id)?; - //save to the same file - info!( - "Saving bootstrap data file {}", - bootstrap_args.config_path.display() - ); - let json = serde_json::to_string_pretty(&file_config)?; - fs::write(&bootstrap_args.config_path, json).context(format!( - "Saving bootstrap data file {} failed", - bootstrap_args.config_path.display() - ))?; - File::create(®istered_check_file)?; + instance_id = Some(register_id); } + // Always reset the configuration with a persistent instance ID upon restart. + let file = File::open(&bootstrap_args.config_path)?; + let reader = BufReader::new(file); + let mut file_config: Value = serde_json::from_reader(reader)?; + file_config["sgx"]["instance_id"] = Value::Number(Number::from(instance_id.unwrap())); + //save to the same file + info!( + "Saving bootstrap data file {}", + bootstrap_args.config_path.display() + ); + let json = serde_json::to_string_pretty(&file_config)?; + fs::write(&bootstrap_args.config_path, json).context(format!( + "Saving bootstrap data file {} failed", + bootstrap_args.config_path.display() + ))?; Ok(()) }