Cómo realizar transacciones de recursos digitales con computación de varias partes y Confidential Space

1. Descripción general

Antes de comenzar, aunque no es completamente necesario, un conocimiento práctico de las siguientes funciones y conceptos será útil en este codelab.

4670cd5427aa39a6.png

Qué aprenderás

En este lab, se proporciona una implementación de referencia para realizar firmas de cadena de bloques compatibles con MPC mediante Confidential Space. Para ilustrar los conceptos, analizaremos una situación en la que la Empresa Primus quiere transferir recursos digitales a la Empresa Secundus. En esta situación, la Empresa Primus utiliza un modelo que cumple con MPC, lo que significa que en lugar de usar claves privadas individuales, utiliza claves compartidas distribuidas. Estas acciones clave están en manos de varias partes, en este caso Alicia y Roberto. Este enfoque le proporciona a la Empresa Primus varios beneficios, incluida una experiencia del usuario simplificada, eficiencia operativa y control sobre sus claves privadas.

Para explicar los aspectos fundamentales de este proceso, detallaremos la configuración técnica y te guiaremos en el proceso de aprobación y firma que inicia la transferencia de recursos digitales de la Empresa Primus a la Empresa Secundus. Ten en cuenta que Roberto y Alicia, que son empleados de la Empresa Primus, deben aprobar la transacción.

Aunque en esta implementación de referencia se muestran las operaciones de firmas, no se abarcan todos los aspectos de la administración de claves de MPC. Por ejemplo, no analizaremos la generación de claves. Además, existen enfoques alternativos y complementarios, como usar servicios que no son de Google Cloud para generar firmas conjuntas o hacer que los cofirmantes creen firmas de cadena de bloques en sus propios entornos, que es una arquitectura más descentralizada. Esperamos que este lab inspire diferentes enfoques de MPC en Google Cloud.

Trabajarás con una carga de trabajo simple que firma una transacción de Ethereum en Confidential Space mediante materiales de clave de cofirmante. La firma de transacciones de Ethereum es un proceso mediante el cual un usuario puede autorizar una transacción en la cadena de bloques de Ethereum. Para enviar una transacción de Ethereum, debes firmarla con tu clave privada. Esto demuestra que eres el propietario de la cuenta y autorizas la transacción. El proceso de firma es el siguiente:

  1. El remitente crea un objeto de transacción que especifica la dirección del destinatario, la cantidad de ETH que se enviará y cualquier otro dato relevante.
  2. La clave privada del remitente se usa para generar un hash en los datos de la transacción.
  3. Luego, el hash se firma con la clave privada.
  4. La firma se adjunta al objeto de transacción.
  5. La transacción se transmite a la red de Ethereum.

Cuando un nodo de la red recibe una transacción, verifica la firma para asegurarse de que haya sido firmada por el propietario de la cuenta. Si la firma es válida, el nodo agregará la transacción a la cadena de bloques.

Para comenzar, configurarás los recursos de Cloud necesarios. Luego, ejecutarás la carga de trabajo en Confidential Space. En este codelab, te guiaremos en los siguientes pasos de alto nivel:

  • Cómo configurar los recursos de Cloud necesarios para ejecutar Confidential Space
  • Cómo autorizar el acceso a recursos protegidos según los atributos de:
  • Qué: El contenedor de carga de trabajo
  • Dónde: El entorno de Confidential Space (la imagen de Confidential Space en Confidential VM)
  • Quién: La cuenta que ejecuta la carga de trabajo
  • Cómo ejecutar la carga de trabajo en una Confidential VM que ejecuta la imagen de VM de Confidential Space

APIs requeridas

Debes habilitar las siguientes APIs en los proyectos especificados para poder completar esta guía.

Nombre de la API

Título de la API

cloudkms.googleapis.com

Cloud KMS

compute.googleapis.com

Compute Engine

confidentialcomputing.googleapis.com

Confidential Computing

iamcredentials.googleapis.com

IAM

artifactregistry.googleapis.com

Artifact Registry

2. Configura recursos en la nube

Antes de comenzar

  • Clona este repositorio con el siguiente comando para obtener las secuencias de comandos necesarias que se usan como parte de este codelab.
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
  • Cambia el directorio de este codelab.
cd confidential-space/codelabs/digital_asset_transaction_codelab/scripts
  • Asegúrate de haber establecido las variables de entorno necesarias del proyecto como se muestra a continuación. Para obtener más información sobre cómo configurar un proyecto de GCP, consulta este codelab. Puedes consultar esta página para obtener detalles sobre cómo recuperar el ID del proyecto y en qué se diferencia del nombre y el número del proyecto. .
export PRIMUS_PROJECT_ID=<GCP project id>
  • Habilita la facturación para tus proyectos.
  • Habilitar la API de Confidential Computing y seguir las APIs para ambos proyectos
gcloud services enable \
   cloudapis.googleapis.com \
    cloudkms.googleapis.com \
    cloudresourcemanager.googleapis.com \
    cloudshell.googleapis.com \
    container.googleapis.com \
    containerregistry.googleapis.com \
    iam.googleapis.com \
    confidentialcomputing.googleapis.com
  • Si deseas establecer las variables para los nombres de los recursos, puedes usar el siguiente comando. Ten en cuenta que esto anulará los nombres de recursos específicos de tu proyecto de GCP para la empresa A, por ejemplo, export PRIMUS_INPUT_STORAGE_BUCKET='primus-input-bucket'.
  • Se pueden configurar las siguientes variables para tu proyecto de GCP en la empresa A:

$PRIMUS_INPUT_STORAGE_BUCKET

El bucket que almacena las claves encriptadas.

$PRIMUS_RESULT_STORAGE_BUCKET

El bucket que almacena el resultado de la transacción de MPC.

$PRIMUS_KEY

La clave de KMS que se usa para encriptar los datos almacenados en $PRIMUS_INPUT_STORAGE_BUCKET para Primus Bank.

CLAVE $PRIMUS_KEYRING

El llavero de claves de KMS que se usará para crear la clave de encriptación $PRIMUS_KEY para Primus Bank.

$PRIMUS_WIP_PROVIDER

El proveedor de grupos de Workload Identity, que incluye la condición del atributo que se usará para los tokens firmados por el servicio de cargas de trabajo de MPC.

$PRIMUS_SERVICEACCOUNT

La cuenta de servicio que usa $PRIMUS_WORKLOAD_IDENTITY_POOL para acceder a los recursos protegidos. Esta cuenta de servicio tendrá permiso para ver las claves encriptadas que se almacenan en el bucket $PRIMUS_INPUT_STORAGE_BUCKET.

$PRIMUS_ARTIFACT_REPOSITORY

El repositorio de artefactos para almacenar la imagen de contenedor de la carga de trabajo.

$WORKLOAD_SERVICEACCOUNT

La cuenta de servicio que tiene permiso para acceder a la Confidential VM que ejecuta la carga de trabajo.

$WORKLOAD_CONTAINER

El contenedor de Docker que ejecuta la carga de trabajo.

$WORKLOAD_IMAGE_NAME

El nombre de la imagen de contenedor de la carga de trabajo.

$WORKLOAD_IMAGE_TAG

La etiqueta de la imagen de contenedor de la carga de trabajo.

  • Ejecuta la siguiente secuencia de comandos para establecer los nombres de variables restantes en valores basados en el ID del proyecto para los nombres de recursos.
source config_env.sh

Configura recursos de Cloud

Como parte de este paso, configurarás los recursos en la nube necesarios para el procesamiento de varias partes. En este lab, usarás la siguiente clave privada: 0000000000000000000000000000000000000000000000000000000000000001

En un entorno de producción, generarás tu propia clave privada. Sin embargo, a los fines de este lab, dividiremos esta clave privada en dos recursos compartidos y encriptaremos cada uno de ellos. En una situación de producción, las claves nunca deben almacenarse en archivos de texto simple. En su lugar, la clave privada se puede generar fuera de Google Cloud (o omitirse por completo y reemplazarse por la creación de fragmentos de clave MPC personalizados) y, luego, encriptarse para que nadie tenga acceso a la clave privada ni a las claves compartidas. Para los fines de este lab, usaremos gcloud CLI.

Ejecuta la siguiente secuencia de comandos para configurar los recursos de nube necesarios. Como parte de estos pasos, se crearán los siguientes recursos:

  • Un bucket de Cloud Storage ($PRIMUS_INPUT_STORAGE_BUCKET) para almacenar los recursos compartidos de claves privadas encriptadas.
  • Un bucket de Cloud Storage ($PRIMUS_RESULT_STORAGE_BUCKET) para almacenar el resultado de la transacción de activo digital.
  • Una clave de encriptación ($PRIMUS_KEY) y un llavero de claves ($PRIMUS_KEYRING) en KMS para encriptar los recursos compartidos de claves privadas.
  • Un grupo de identidades para cargas de trabajo ($PRIMUS_WORKLOAD_IDENTITY_POOL) para validar reclamaciones según las condiciones de atributos configuradas en el proveedor
  • Una cuenta de servicio ($PRIMUS_SERVICEACCOUNT) vinculada al grupo de identidades para cargas de trabajo mencionado anteriormente ($PRIMUS_WORKLOAD_IDENTITY_POOL) con el siguiente acceso de IAM:
  • roles/cloudkms.cryptoKeyDecrypter para desencriptar los datos con la clave de KMS
  • objectViewer para leer datos del bucket de Cloud Storage
  • roles/iam.workloadIdentityUser para conectar esta cuenta de servicio al grupo de Workload Identity.
./setup_resources.sh

3. Crear carga de trabajo

Crea una cuenta de servicio de carga de trabajo

Ahora crearás una cuenta de servicio para la carga de trabajo con los roles y permisos necesarios. Para ello, ejecuta la siguiente secuencia de comandos, que creará una cuenta de servicio de carga de trabajo para la empresa A. La VM que ejecuta la carga de trabajo usará esta cuenta de servicio.

La cuenta de servicio de carga de trabajo ($WORKLOAD_SERVICEACCOUNT) tendrá los siguientes roles:

  • confidentialcomputing.workloadUser para obtener un token de certificación
  • logging.logWriter para escribir registros en Cloud Logging
  • objectViewer para leer datos del bucket $PRIMUS_INPUT_STORAGE_BUCKET de Cloud Storage
  • objectUser para escribir el resultado de la carga de trabajo en el bucket $PRIMUS_RESULT_STORAGE_BUCKET de Cloud Storage
./create_workload_service_account.sh

Crear carga de trabajo

Este paso implica crear una imagen de Docker de carga de trabajo. La carga de trabajo de este codelab es una aplicación sencilla de MPC de Node.js que firma transacciones digitales para transferir recursos usando recursos compartidos de claves privadas encriptadas. Aquí está el código del proyecto de la carga de trabajo. El proyecto de carga de trabajo incluye los siguientes archivos.

package.json: Este archivo contiene la lista de paquetes que se deben usar para la aplicación de carga de trabajo MPC. En este caso, usamos las bibliotecas @google-cloud/kms, @google-cloud/storage, ethers y fast-crc32c. Aquí se encuentra el archivo package.json que usaremos para este codelab.

index.js: Este es un punto de entrada de una aplicación de carga de trabajo y especifica qué comandos se deben ejecutar cuando se inicia el contenedor de carga de trabajo. También incluimos un ejemplo de transacción sin firmar que normalmente proporcionaría una aplicación no confiable que les solicita a los usuarios su firma. Este archivo index.js también importa funciones de mpc.js, que crearemos a continuación. A continuación, se muestra el contenido del archivo index.js, que también puedes encontrar aquí.

import {signTransaction, submitTransaction, uploadFromMemory} from './mpc.js';

const signAndSubmitTransaction = async () => {
  try {
    // Create the unsigned transaction object
    const unsignedTransaction = {
      nonce: 0,
      gasLimit: 21000,
      gasPrice: '0x09184e72a000',
      to: '0x0000000000000000000000000000000000000000',
      value: '0x00',
      data: '0x',
    };

    // Sign the transaction
    const signedTransaction = await signTransaction(unsignedTransaction);

    // Submit the transaction to Ganache
    const transaction = await submitTransaction(signedTransaction);

    // Write the transaction receipt
    uploadFromMemory(transaction);

    return transaction;
  } catch (e) {
    console.log(e);
    uploadFromMemory(e);
  }
};

await signAndSubmitTransaction();

mpc.js: Aquí es donde se realiza la firma de la transacción. Importa funciones desde kms-decrypt y credentials-config, que analizaremos a continuación. A continuación, encontrarás el contenido del archivo mpc.js. También puedes encontrarlo aquí.

import {Storage} from '@google-cloud/storage';
import {ethers} from 'ethers';

import {credentialConfig} from './credential-config.js';
import {decryptSymmetric} from './kms-decrypt.js';

const providers = ethers.providers;
const Wallet = ethers.Wallet;

// The ID of the GCS bucket holding the encrypted keys
const bucketName = process.env.KEY_BUCKET;

// Name of the encrypted key files.
const encryptedKeyFile1 = 'alice_encrypted_key_share';
const encryptedKeyFile2 = 'bob_encrypted_key_share';

// Create a new storage client with the credentials
const storageWithCreds = new Storage({
  credentials: credentialConfig,
});

// Create a new storage client without the credentials
const storage = new Storage();

const downloadIntoMemory = async (keyFile) => {
  // Downloads the file into a buffer in memory.
  const contents =
      await storageWithCreds.bucket(bucketName).file(keyFile).download();

  return contents;
};

const provider =
    new providers.JsonRpcProvider(`http://${process.env.NODE_URL}:80`);

export const signTransaction = async (unsignedTransaction) => {
  /* Check if Alice and Bob have both approved the transaction
  For this example, we're checking if their encrypted keys are available. */
  const encryptedKey1 =
      await downloadIntoMemory(encryptedKeyFile1).catch(console.error);
  const encryptedKey2 =
      await downloadIntoMemory(encryptedKeyFile2).catch(console.error);

  // For each key share, make a call to KMS to decrypt the key
  const privateKeyshare1 = await decryptSymmetric(encryptedKey1[0]);
  const privateKeyshare2 = await decryptSymmetric(encryptedKey2[0]);

  /* Perform the MPC calculations
  In this example, we're combining the private key shares
  Alternatively, you could import your mpc calculations here */
  const wallet = new Wallet(privateKeyshare1 + privateKeyshare2);

  // Sign the transaction
  const signedTransaction = await wallet.signTransaction(unsignedTransaction);

  return signedTransaction;
};

export const submitTransaction = async (signedTransaction) => {
  // This can now be sent to Ganache
  const hash = await provider.sendTransaction(signedTransaction);
  return hash;
};

export const uploadFromMemory = async (contents) => {
  // Upload the results to the bucket without service account impersonation
  await storage.bucket(process.env.RESULTS_BUCKET)
      .file('transaction_receipt_' + Date.now())
      .save(JSON.stringify(contents));
};

kms-decrypt.js: Este archivo contiene el código para la desencriptación con claves administradas en KMS. A continuación, se muestra el contenido del archivo kms-decrypt.js, que también puedes encontrar aquí.

import {KeyManagementServiceClient} from '@google-cloud/kms';
import crc32c from 'fast-crc32c';

import {credentialConfig} from './credential-config.js';

const projectId = process.env.PRIMUS_PROJECT_ID;
const locationId = process.env.PRIMUS_LOCATION;
const keyRingId = process.env.PRIMUS_ENC_KEYRING;
const keyId = process.env.PRIMUS_ENC_KEY;

// Instantiates a client
const client = new KeyManagementServiceClient({
  credentials: credentialConfig,
});

// Build the key name
const keyName = client.cryptoKeyPath(projectId, locationId, keyRingId, keyId);

export const decryptSymmetric = async (ciphertext) => {
  const ciphertextCrc32c = crc32c.calculate(ciphertext);
  const [decryptResponse] = await client.decrypt({
    name: keyName,
    ciphertext,
    ciphertextCrc32c: {
      value: ciphertextCrc32c,
    },
  });

  // Optional, but recommended: perform integrity verification on
  // decryptResponse. For more details on ensuring E2E in-transit integrity to
  // and from Cloud KMS visit:
  // https://cloud.google.com/kms/docs/data-integrity-guidelines
  if (crc32c.calculate(decryptResponse.plaintext) !==
      Number(decryptResponse.plaintextCrc32c.value)) {
    throw new Error('Decrypt: response corrupted in-transit');
  }

  const plaintext = decryptResponse.plaintext.toString();

  return plaintext;
};

credential-config.js: En el archivo, se almacenan las rutas de acceso del grupo de identidades para cargas de trabajo y los detalles para la suplantación de la cuenta de servicio. Aquí se encuentra el archivo credentials-config.js que utilizaremos para este codelab.

Dockerfile: Por último, crearemos nuestro Dockerfile que se usará para compilar la imagen de Docker de la carga de trabajo. define el Dockerfile como se especifica aquí.

FROM node:16.18.0

ENV NODE_ENV=production

WORKDIR /app

COPY ["package.json", "package-lock.json*", "./"]

RUN npm install --production

COPY . .

LABEL "tee.launch_policy.allow_cmd_override"="true"
LABEL "tee.launch_policy.allow_env_override"="NODE_URL,RESULTS_BUCKET,KEY_BUCKET,PRIMUS_PROJECT_NUMBER,PRIMUS_PROJECT_ID,PRIMUS_WORKLOAD_IDENTITY_POOL,PRIMUS_WIP_PROVIDER,PRIMUS_SERVICEACCOUNT,PRIMUS_ENC_KEYRING,PRIMUS_ENC_KEY"

CMD [ "node", "index.js" ]

Nota: LABEL "tee.launch_policy.allow_cmd_override"="true" en Dockerfile es una política de inicio establecida por el autor de la imagen. Permite al operador anular el CMD cuando ejecuta la carga de trabajo. De forma predeterminada, allow_cmd_override se establece como falso. LABEL &quot;tee.launch_policy.allow_env_override&quot; le indica a Confidential Space qué variables de entorno pueden usar los usuarios de la imagen .

Ejecuta la siguiente secuencia de comandos para crear una carga de trabajo en la que se realicen los siguientes pasos:

  • Crea Artifact Registry($PRIMUS_ARTIFACT_REPOSITORY) para almacenar la imagen de Docker de la carga de trabajo.
  • Actualiza el código de la carga de trabajo con los nombres de los recursos necesarios. Aquí se muestra el código de la carga de trabajo que se usa para este codelab.
  • Crear un Dockerfile para compilar una imagen de Docker del código de la carga de trabajo Puedes encontrar el Dockerfile aquí.
  • Compila y publica la imagen de Docker en Artifact Registry ($PRIMUS_ARTIFACT_REPOSITORY) que creaste en el paso anterior.
  • Otorga a $WORKLOAD_SERVICEACCOUNT permiso de lectura para $PRIMUS_ARTIFACT_REPOSITORY. Esto es necesario para que el contenedor de carga de trabajo extraiga la imagen de Docker de la carga de trabajo desde Artifact Registry.
./create_workload.sh

Crea el nodo de cadena de bloques

Ganache Ethereum Node

Antes de autorizar la carga de trabajo, debemos crear la instancia Ethereum Ganache. La transacción firmada se enviará a esta instancia de Ganache. Toma nota de la dirección IP de esta instancia. Después de ejecutar el siguiente comando, es posible que debas ingresar y para habilitar la API.

gcloud config set project $PRIMUS_PROJECT_ID
gcloud compute instances create-with-container mpc-lab-ethereum-node \
  --zone=${PRIMUS_PROJECT_ZONE}\
  --tags=http-server \
  --shielded-secure-boot \
  --shielded-vtpm \
  --shielded-integrity-monitoring \
  --container-image=docker.io/trufflesuite/ganache:v7.7.3 \
--container-arg=--wallet.accounts=\"0x0000000000000000000000000000000000000000000000000000000000000001,0x21E19E0C9BAB2400000\" \
  --container-arg=--port=80

4. Autorizar y ejecutar cargas de trabajo

Autorizar carga de trabajo

Como parte de este paso, configuraremos el proveedor de grupo de identidades para cargas de trabajo en el grupo de identidades para cargas de trabajo ($PRIMUS_WORKLOAD_IDENTITY_POOL). Hay condiciones de atributos configuradas para Workload Identity, como se muestra a continuación. Una de las condiciones es validar que la imagen de carga de trabajo se extraiga del repositorio de artefactos esperado.

gcloud config set project $PRIMUS_PROJECT_ID
gcloud iam workload-identity-pools providers create-oidc ${PRIMUS_WIP_PROVIDER} \
 --location="${PRIMUS_PROJECT_LOCATION}" \
 --workload-identity-pool="$PRIMUS_WORKLOAD_IDENTITY_POOL" \
 --issuer-uri="https://confidentialcomputing.googleapis.com/" \
 --allowed-audiences="https://sts.googleapis.com" \
 --attribute-mapping="google.subject='assertion.sub'" \
 --attribute-condition="assertion.swname == 'CONFIDENTIAL_SPACE' && 'STABLE' in assertion.submods.confidential_space.support_attributes && assertion.submods.container.image_reference == '${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG' && '$WORKLOAD_SERVICEACCOUNT@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com' in assertion.google_service_accounts"

Ejecutar carga de trabajo

En esta sección, se explica cómo ejecutar la carga de trabajo en Confidential VM. Para ello, pasaremos los argumentos del TEE necesarios con la marca de metadatos. Además, estableceremos variables de entorno para el contenedor de carga de trabajo mediante el comando “tee-env-*” marca. La imagen tiene las siguientes variables:

  • NODE_URL: Es la URL del nodo de Ethereum que procesará la transacción firmada.
  • RESULTS_BUCKET: Es el bucket que almacena el resultado de la transacción de mpc.
  • KEY_BUCKET: Es el bucket que almacena las claves encriptadas de MPC.
  • PRIMUS_PROJECT_NUMBER: Es el número de proyecto que se usa para el archivo de configuración de credenciales.
  • PRIMUS_PROJECT_ID: Es el ID del proyecto que se usa para el archivo de configuración de credenciales. El resultado de la ejecución de la carga de trabajo se publicará en $PRIMUS_RESULT_STORAGE_BUCKET.
  • PRIMUS_WORKLOAD_IDENTITY_POOL: El grupo de identidades para cargas de trabajo que se usa para validar reclamaciones.
  • PRIMUS_WIP_POROVIDER: El proveedor de grupo de identidades para cargas de trabajo, que incluye las condiciones del atributo que se usarán para validar los tokens que presenta la carga de trabajo.
  • WORKLOAD_SERVICEACCOUNT: La cuenta de servicio de la carga de trabajo.
gcloud config set project $PRIMUS_PROJECT_ID
gcloud compute instances create $WORKLOAD_VM \
 --confidential-compute-type=SEV \
 --shielded-secure-boot \
 --maintenance-policy=TERMINATE \
 --scopes=cloud-platform \
 --zone=${PRIMUS_PROJECT_ZONE} \
 --image-project=confidential-space-images \
 --image-family=confidential-space \
 --service-account=$WORKLOAD_SERVICEACCOUNT@$PRIMUS_PROJECT_ID.iam.gserviceaccount.com \
 --metadata "^~^tee-image-reference=${PRIMUS_PROJECT_REPOSITORY_REGION}-docker.pkg.dev/$PRIMUS_PROJECT_ID/$PRIMUS_ARTIFACT_REPOSITORY/$WORKLOAD_IMAGE_NAME:$WORKLOAD_IMAGE_TAG~tee-restart-policy=Never~tee-env-NODE_URL=$(gcloud compute instances describe mpc-lab-ethereum-node --format='get(networkInterfaces[0].networkIP)' --zone=${PRIMUS_PROJECT_ZONE})~tee-env-RESULTS_BUCKET=$PRIMUS_RESULT_STORAGE_BUCKET~tee-env-KEY_BUCKET=$PRIMUS_INPUT_STORAGE_BUCKET~tee-env-PRIMUS_PROJECT_ID=$PRIMUS_PROJECT_ID~tee-env-PRIMUS_PROJECT_NUMBER=$(gcloud projects describe $PRIMUS_PROJECT_ID --format="value(projectNumber)")~tee-env-PRIMUS_WORKLOAD_IDENTITY_POOL=$PRIMUS_WORKLOAD_IDENTITY_POOL~tee-env-PRIMUS_PROJECT_LOCATION=${PRIMUS_PROJECT_LOCATION}~tee-env-PRIMUS_WIP_PROVIDER=$PRIMUS_WIP_PROVIDER~tee-env-PRIMUS_SERVICEACCOUNT=$PRIMUS_SERVICEACCOUNT~tee-env-PRIMUS_KEY=${PRIMUS_KEY}~tee-env-PRIMUS_KEYRING=${PRIMUS_KEYRING}"

Verifica los resultados de Cloud Storage

Puedes ver el recibo de la transacción en Cloud Storage. Es posible que Confidential Space tarde unos minutos en iniciarse y que aparezcan los resultados. Sabrás que el contenedor está listo cuando la VM esté en estado detenida.

  1. Ve a la página Navegador de Cloud Storage.
  2. Haz clic en $PRIMUS_RESULT_STORAGE_BUCKET.
  3. Haz clic en el archivo transaction_receipt.
  4. Haz clic en Descargar para descargar y ver la respuesta de la transacción.

Nota: Si no aparecen los resultados, puedes ir a $WORKLOAD_VM en la página de la consola de Cloud de Compute Engine y hacer clic en “Puerto en serie 1 (consola)”. para ver los registros.

Verifica la transacción de cadena de bloques de Ganache

También puedes ver la transacción en el registro de la cadena de bloques.

  1. Ve a la página de Cloud Compute Engine.
  2. Haz clic en mpc-lab-ethereum-node VM.
  3. Haz clic en SSH para abrir la ventana de SSH en el navegador.
  4. En la ventana de SSH, ingresa sudo docker ps para ver el contenedor de Ganache en ejecución.
  5. Busca el ID del contenedor de trufflesuite/ganache:v7.7.3
  6. Ingresa sudo docker logs CONTAINER_ID y reemplaza CONTAINER_ID por el ID de trufflesuite/ganache:v7.7.3.
  7. Revisa los registros de Ganache y confirma que haya una transacción en la lista.

5. Limpia

Aquí se encuentra la secuencia de comandos que se puede usar para limpiar los recursos que creamos como parte de este codelab. Como parte de esta limpieza, se borrarán los siguientes recursos:

  • Bucket de almacenamiento de entrada que se usa para almacenar archivos compartidos de claves encriptados ($PRIMUS_INPUT_STORAGE_BUCKET).
  • Clave de encriptación y llavero de claves ($PRIMUS_KEY y $PRIMUS_KEYRING).
  • Cuenta de servicio usada para acceder a los recursos protegidos ($PRIMUS_SERVICEACCOUNT).
  • Grupo de Workload Identity ($PRIMUS_WORKLOAD_IDENTITY_POOL).
  • Cuenta de servicio de carga de trabajo ($WORKLOAD_SERVICEACCOUNT).
  • Instancias de procesamiento de cargas de trabajo.
  • Bucket de almacenamiento de resultados que se usa para almacenar el resultado de la transacción ($PRIMUS_RESULT_STORAGE_BUCKET).
  • Artifact Registry que se usa para almacenar la imagen de carga de trabajo ($PRIMUS_ARTIFACT_REPOSITORY).
./cleanup.sh

Si terminaste de explorar, considera borrar tu proyecto.

  • Ve a la consola de Google Cloud.
  • Selecciona el proyecto que deseas cerrar y haz clic en “Borrar”. en la parte superior. Esto programa la eliminación del proyecto.

¿Qué sigue?

Echa un vistazo a algunos de estos codelabs similares...

Lecturas adicionales