Réaliser des transactions sur des actifs numériques avec le calcul multipartite et Confidential Space

1. Présentation

Avant de commencer, bien que ce ne soit pas absolument nécessaire, une connaissance pratique des fonctionnalités et concepts suivants vous sera utile dans cet atelier de programmation.

4670cd5427aa39a6.png

Points abordés

Cet atelier fournit une implémentation de référence pour effectuer une signature de blockchain conforme à MPC à l'aide de Confidential Space. Pour illustrer les concepts, nous allons examiner un scénario dans lequel l'entreprise Primus souhaite transférer des ressources numériques à l'entreprise Secundus. Dans ce scénario, l'entreprise Primus utilise un modèle conforme à la MPC, ce qui signifie qu'au lieu d'utiliser des clés privées individuelles, elle utilise des quotes-parts de clés distribuées. Ces partages de clés sont détenus par plusieurs parties, en l'occurrence Alice et Bob. Cette approche offre plusieurs avantages à Company Primus, y compris une expérience utilisateur simplifiée, une efficacité opérationnelle et un contrôle sur ses clés privées.

Pour vous expliquer les aspects fondamentaux de ce processus, nous allons détailler la configuration technique et vous guider tout au long du processus d'approbation et de signature qui lance le transfert des composants numériques de l'entreprise Primus vers l'entreprise Secundus. Veuillez noter que Robert et Alice, qui sont tous deux employés de l'entreprise Primus, doivent approuver la transaction.

Bien que cette implémentation de référence présente des opérations de signature, elle ne couvre pas tous les aspects de la gestion des clés MPC. Par exemple, nous ne parlons pas de la génération de clés. Il existe également des approches alternatives et complémentaires, comme l'utilisation de services non Google Cloud pour générer des co-signatures ou le fait de demander aux cosignataires de créer des signatures de blockchain dans leurs propres environnements, ce qui constitue une architecture plus décentralisée. Nous espérons que cet atelier vous inspirera différentes approches pour la MPC sur Google Cloud.

Vous allez travailler avec une charge de travail simple qui signe une transaction Ethereum dans Confidential Space à l'aide de clés de cosignataire. La signature de transactions Ethereum est un processus par lequel un utilisateur peut autoriser une transaction sur la blockchain Ethereum. Pour envoyer une transaction Ethereum, vous devez la signer avec votre clé privée. Cela prouve que vous êtes le propriétaire du compte et que vous autorisez la transaction. Voici le processus de signature :

  1. L'expéditeur crée un objet de transaction qui spécifie l'adresse du destinataire, le montant d'ETH à envoyer et toute autre donnée pertinente.
  2. La clé privée de l'expéditeur est utilisée pour hacher les données de la transaction.
  3. Le hachage est ensuite signé avec la clé privée.
  4. La signature est associée à l'objet de transaction.
  5. La transaction est diffusée sur le réseau Ethereum.

Lorsqu'un nœud du réseau reçoit une transaction, il vérifie la signature pour s'assurer qu'elle a été signée par le titulaire du compte. Si la signature est valide, le nœud ajoute la transaction à la blockchain.

Pour commencer, vous allez configurer les ressources cloud nécessaires. Vous exécuterez ensuite la charge de travail dans Confidential Space. Cet atelier de programmation vous guidera à travers les étapes majeures suivantes :

  • Configurer les ressources Cloud nécessaires pour exécuter Confidential Space
  • Découvrez comment autoriser l'accès aux ressources protégées en fonction des attributs suivants :
  • What : conteneur de charge de travail
  •  : environnement Confidential Space (image Confidential Space sur Confidential VM)
  • Qui : compte qui exécute la charge de travail
  • Exécuter la charge de travail dans une Confidential VM exécutant l'image de VM Confidential Space

API requises

Pour pouvoir suivre ce guide, vous devez activer les API suivantes dans les projets spécifiés.

Nom de l'API

Titre de l'API

cloudkms.googleapis.com

Cloud KMS

compute.googleapis.com

Compute Engine

confidentialcomputing.googleapis.com

Informatique confidentielle

iamcredentials.googleapis.com

IAM

artifactregistry.googleapis.com

Artifact Registry

2. Configurer les ressources cloud

Avant de commencer

  • Clonez ce dépôt à l'aide de la commande ci-dessous pour obtenir les scripts requis utilisés dans cet atelier de programmation.
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
  • Accédez au répertoire de cet atelier de programmation.
cd confidential-space/codelabs/digital_asset_transaction_codelab/scripts
  • Assurez-vous d'avoir défini les variables d'environnement du projet requises, comme indiqué ci-dessous. Pour en savoir plus sur la configuration d'un projet GCP, consultez cet atelier de programmation. Pour savoir comment récupérer l'ID d'un projet et en quoi il diffère du nom et du numéro du projet, consultez cette page. .
export PRIMUS_PROJECT_ID=<GCP project id>
  • Activez la facturation pour vos projets.
  • Activez l'API Confidential Computing et les API suivantes pour les deux projets.
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
  • Pour définir les variables pour les noms de ressources, vous pouvez utiliser la commande suivante. Notez que cela remplacera les noms de ressources spécifiques à votre projet GCP pour l'entreprise A, par exemple export PRIMUS_INPUT_STORAGE_BUCKET='primus-input-bucket'.
  • Les variables suivantes peuvent être définies pour votre projet GCP dans l'entreprise A :

$PRIMUS_INPUT_STORAGE_BUCKET

Bucket dans lequel sont stockées les clés chiffrées.

$PRIMUS_RESULT_STORAGE_BUCKET

Bucket qui stocke le résultat de la transaction MPC.

$PRIMUS_KEY

Clé KMS utilisée pour chiffrer les données stockées dans $PRIMUS_INPUT_STORAGE_BUCKET pour Primus Bank.

$PRIMUS_KEYRING

Trousseau de clés KMS qui sera utilisé pour créer la clé de chiffrement $PRIMUS_KEY pour Primus Bank.

$PRIMUS_WIP_PROVIDER

Fournisseur de pool d'identités de charge de travail qui inclut la condition d'attribut à utiliser pour les jetons signés par le service de charge de travail MPC.

$PRIMUS_SERVICEACCOUNT

Compte de service utilisé par $PRIMUS_WORKLOAD_IDENTITY_POOL pour accéder aux ressources protégées. Ce compte de service sera autorisé à afficher les clés chiffrées stockées dans le bucket $PRIMUS_INPUT_STORAGE_BUCKET.

$PRIMUS_ARTIFACT_REPOSITORY

Dépôt d'artefacts pour stocker l'image du conteneur de charge de travail.

$WORKLOAD_SERVICEACCOUNT

Compte de service autorisé à accéder à la VM confidentielle qui exécute la charge de travail.

$WORKLOAD_CONTAINER

Conteneur Docker qui exécute la charge de travail.

$WORKLOAD_IMAGE_NAME

Nom de l'image du conteneur de charge de travail.

$WORKLOAD_IMAGE_TAG

Tag de l'image du conteneur de charge de travail.

  • Exécutez le script suivant pour définir les noms de variables restants sur des valeurs basées sur l'ID de votre projet pour les noms de ressources.
source config_env.sh

Configurer des ressources cloud

Dans cette étape, vous allez configurer les ressources cloud requises pour le calcul multipartite. Pour cet atelier, vous allez utiliser la clé privée suivante : 0000000000000000000000000000000000000000000000000000000000000001

Dans un environnement de production, vous générerez votre propre clé privée. Toutefois, pour les besoins de cet atelier, nous allons diviser cette clé privée en deux parts et chiffrer chacune d'elles. Dans un scénario de production, les clés ne doivent jamais être stockées dans des fichiers en texte brut. La clé privée peut être générée en dehors de Google Cloud (ou complètement ignorée et remplacée par la création de fragments de clé MPC personnalisés), puis chiffrée afin que personne n'ait accès à la clé privée ni aux fragments de clé. Dans cet atelier, nous utiliserons la gcloud CLI.

Exécutez le script suivant pour configurer les ressources cloud requises. Au cours de ces étapes, les ressources mentionnées ci-dessous seront créées :

  • Un bucket Cloud Storage ($PRIMUS_INPUT_STORAGE_BUCKET) pour stocker les partages de clés privées chiffrées.
  • Un bucket Cloud Storage ($PRIMUS_RESULT_STORAGE_BUCKET) pour stocker le résultat de la transaction d'actifs numériques.
  • Une clé de chiffrement ($PRIMUS_KEY) et un trousseau de clés ($PRIMUS_KEYRING) dans KMS pour chiffrer les partages de clés privées.
  • Un pool d'identités de charge de travail ($PRIMUS_WORKLOAD_IDENTITY_POOL) pour valider les revendications en fonction des conditions d'attributs configurées sous son fournisseur.
  • Un compte de service ($PRIMUS_SERVICEACCOUNT) associé au pool d'identités de charge de travail mentionné ci-dessus ($PRIMUS_WORKLOAD_IDENTITY_POOL) avec l'accès IAM suivant :
  • roles/cloudkms.cryptoKeyDecrypter pour déchiffrer les données à l'aide de la clé KMS.
  • objectViewer pour lire les données du bucket Cloud Storage.
  • roles/iam.workloadIdentityUser pour associer ce compte de service au pool d'identités de charge de travail.
./setup_resources.sh

3. Créer une charge de travail

Créer un compte de service pour la charge de travail

Vous allez maintenant créer un compte de service pour la charge de travail avec les rôles et autorisations requis. Pour ce faire, exécutez le script suivant, qui créera un compte de service de charge de travail pour l'entreprise A. Ce compte de service sera utilisé par la VM qui exécute la charge de travail.

Le compte de service de charge de travail ($WORKLOAD_SERVICEACCOUNT) disposera des rôles suivants :

  • confidentialcomputing.workloadUser pour obtenir un jeton d'attestation
  • logging.logWriter pour écrire des journaux dans Cloud Logging.
  • objectViewer pour lire les données du bucket Cloud Storage $PRIMUS_INPUT_STORAGE_BUCKET.
  • objectUser pour écrire le résultat de la charge de travail dans le bucket Cloud Storage $PRIMUS_RESULT_STORAGE_BUCKET.
./create_workload_service_account.sh

Créer une charge de travail

Cette étape consiste à créer une image Docker de charge de travail. La charge de travail de cet atelier de programmation est une simple application MPC Node.js qui signe des transactions numériques pour transférer des actifs à l'aide de partages de clés privées chiffrées. Ici se trouve le code du projet de charge de travail. Le projet de charge de travail inclut les fichiers suivants.

package.json: : ce fichier contient la liste des packages à utiliser pour l'application MPC de charge de travail. Dans le cas présent, nous utilisons les bibliothèques @google-cloud/kms, @google-cloud/storage, ethers et fast-crc32c. Voici le fichier package.json que nous utiliserons pour cet atelier de programmation.

index.js: : il s'agit d'un point d'entrée de l'application de charge de travail. Il spécifie les commandes à exécuter au démarrage du conteneur de charge de travail. Nous avons également inclus un exemple de transaction non signée qui serait normalement fournie par une application non fiable demandant aux utilisateurs leur signature. Ce fichier index.js importe également des fonctions à partir de mpc.js, que nous allons créer ensuite. Vous trouverez ci-dessous le contenu du fichier index.js. Vous pouvez également le consulter sur cette page.

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: : c'est là que la signature de la transaction a lieu. Il importe des fonctions de kms-decrypt et credential-config, que nous aborderons ensuite. Vous trouverez ci-dessous le contenu du fichier mpc.js. Vous pouvez également le consulter ici.

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 : ce fichier contient le code de déchiffrement à l'aide des clés gérées dans KMS. Vous trouverez ci-dessous le contenu du fichier kms-decrypt.js. Vous pouvez également le consulter sur cette page.

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 : ce fichier stocke les chemins d'accès au pool d'identités de charge de travail et les détails de l'usurpation d'identité du compte de service. Voici le fichier credential-config.js que nous utiliserons pour cet atelier de programmation.

Dockerfile : enfin, nous allons créer notre fichier Dockerfile qui sera utilisé pour créer l'image Docker de la charge de travail. définit le fichier Dockerfile comme spécifié ici.

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" ]

Remarque : LABEL "tee.launch_policy.allow_cmd_override"="true" dans le fichier Dockerfile est une règle de lancement définie par l'auteur de l'image. Il permet à l'opérateur de remplacer la CMD lors de l'exécution de la charge de travail. Par défaut, allow_cmd_override est défini sur "false". Le LIBELLÉ "tee.launch_policy.allow_env_override" indique à Confidential Space les variables d'environnement que les utilisateurs d'images peuvent utiliser .

Exécutez le script suivant pour créer une charge de travail dans laquelle les étapes suivantes sont effectuées :

  • Créez Artifact Registry($PRIMUS_ARTIFACT_REPOSITORY) pour stocker l'image Docker de la charge de travail.
  • Mettez à jour le code de la charge de travail avec les noms des ressources requises. Cliquez ici pour accéder au code de charge de travail utilisé pour cet atelier de programmation.
  • Créez un fichier Dockerfile pour compiler une image Docker du code de charge de travail. Vous trouverez le Dockerfile ici.
  • Créez et publiez l'image Docker dans le registre Artifact Registry ($PRIMUS_ARTIFACT_REPOSITORY) créé à l'étape précédente.
  • Accordez l'autorisation de lecture $WORKLOAD_SERVICEACCOUNT pour $PRIMUS_ARTIFACT_REPOSITORY. Cela est nécessaire pour que le conteneur de charge de travail puisse extraire l'image Docker de charge de travail à partir d'Artifact Registry.
./create_workload.sh

Créer le nœud blockchain

Nœud Ethereum Ganache

Avant d'autoriser la charge de travail, nous devons créer l'instance Ethereum Ganache. La transaction signée sera envoyée à cette instance Ganache. Veuillez noter l'adresse IP de cette instance. Après avoir exécuté la commande ci-dessous, vous devrez peut-être saisir y pour activer l'API.

gcloud compute instances create-with-container ${ETHEREUM_NODE} \
  --zone=${PRIMUS_PROJECT_ZONE} \
  --tags=http-server \
  --project=${PRIMUS_PROJECT_ID} \
  --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. Autoriser et exécuter une charge de travail

Autoriser la charge de travail

Dans cette étape, nous allons configurer le fournisseur de pool d'identités de charge de travail sous le pool d'identités de charge de travail ($PRIMUS_WORKLOAD_IDENTITY_POOL). Des conditions d'attributs sont configurées pour l'identité de charge de travail, comme indiqué ci-dessous. L'une des conditions consiste à valider que l'image de charge de travail est extraite du dépôt d'artefacts attendu.

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"

Exécuter la charge de travail

Cette section explique comment exécuter la charge de travail sur une Confidential VM. Pour ce faire, nous transmettrons les arguments TEE requis à l'aide de l'indicateur de métadonnées. Nous allons également définir des variables d'environnement pour le conteneur de charge de travail à l'aide de l'indicateur "tee-env-*". L'image comporte les variables suivantes :

  • NODE_URL : URL du nœud Ethereum qui traitera la transaction signée.
  • RESULTS_BUCKET : bucket qui stocke le résultat de la transaction MPC.
  • KEY_BUCKET : bucket qui stocke les clés chiffrées par MPC.
  • PRIMUS_PROJECT_NUMBER : numéro de projet utilisé pour le fichier de configuration des identifiants.
  • PRIMUS_PROJECT_ID : ID du projet utilisé pour le fichier de configuration des identifiants. Le résultat de l'exécution de la charge de travail sera publié dans $PRIMUS_RESULT_STORAGE_BUCKET.
  • PRIMUS_WORKLOAD_IDENTITY_POOL : pool d'identités de charge de travail utilisé pour valider les revendications.
  • PRIMUS_WIP_POROVIDER : fournisseur de pools d'identités de charge de travail qui inclut les conditions d'attributs à utiliser pour valider les jetons présentés par la charge de travail.
  • WORKLOAD_SERVICEACCOUNT : compte de service de la charge de travail.
gcloud compute instances create $WORKLOAD_VM \
 --confidential-compute-type=SEV \
 --shielded-secure-boot \
 --maintenance-policy=TERMINATE \
 --scopes=cloud-platform \
 --zone=${PRIMUS_PROJECT_ZONE} \
 --project=${PRIMUS_PROJECT_ID} \
 --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 ${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}"

Vérifier les résultats Cloud Storage

Vous pouvez afficher le reçu de la transaction dans Cloud Storage. Le démarrage de l'espace confidentiel et l'affichage des résultats peuvent prendre quelques minutes. Vous saurez que le conteneur est terminé lorsque la VM est à l'état arrêté.

  1. Accédez à la page du navigateur Cloud Storage.
  2. Cliquez sur $PRIMUS_RESULT_STORAGE_BUCKET.
  3. Cliquez sur le fichier transaction_receipt.
  4. Cliquez sur "Télécharger" pour télécharger et afficher la réponse de la transaction.

Vous pouvez également exécuter les commandes suivantes pour afficher le résultat.

gcloud config set project $PRIMUS_PROJECT_ID
gsutil cat gs://$PRIMUS_RESULT_STORAGE_BUCKET/transaction_receipt

Remarque : Si aucun résultat n'apparaît, vous pouvez accéder à $WORKLOAD_VM sur la page Compute Engine de la console Cloud et cliquer sur "Port série 1 (console)" pour afficher les journaux.

Vérifier la transaction Ganache Blockchain

Vous pouvez également consulter la transaction dans le journal de la chaîne de blocs.

  1. Accédez à la page Cloud Compute Engine.
  2. Cliquez sur ${ETHEREUM_NODE} VM.
  3. Cliquez sur SSH pour ouvrir la fenêtre SSH dans le navigateur.
  4. Dans la fenêtre SSH, saisissez sudo docker ps pour afficher le conteneur Ganache en cours d'exécution.
  5. Recherchez l'ID de conteneur pour trufflesuite/ganache:v7.7.3.
  6. Saisissez sudo docker logs CONTAINER_ID en remplaçant CONTAINER_ID par l'ID de trufflesuite/ganache:v7.7.3.
  7. Affichez les journaux de Ganache et vérifiez qu'une transaction y est répertoriée.

5. Effectuer un nettoyage

Voici le script qui peut être utilisé pour nettoyer les ressources que nous avons créées dans cet atelier de programmation. Dans le cadre de ce nettoyage, les ressources suivantes seront supprimées :

  • Bucket de stockage d'entrée utilisé pour stocker les partages de clés chiffrées ($PRIMUS_INPUT_STORAGE_BUCKET)).
  • Clé de chiffrement ($PRIMUS_KEY).
  • Compte de service utilisé pour accéder aux ressources protégées ($PRIMUS_SERVICEACCOUNT).
  • Pool d'identités de charge de travail ($PRIMUS_WORKLOAD_IDENTITY_POOL).
  • Compte de service de charge de travail ($WORKLOAD_SERVICEACCOUNT).
  • Instances de calcul de charge de travail ($WORKLOAD_VM et $ETHEREUM_NODE).
  • Bucket de stockage des résultats utilisé pour stocker le résultat de la transaction ($PRIMUS_RESULT_STORAGE_BUCKET).
  • Registre d'artefacts utilisé pour stocker l'image de charge de travail ($PRIMUS_ARTIFACT_REPOSITORY).
./cleanup.sh

Si vous avez terminé l'exploration, pensez à supprimer votre projet.

  • Accédez à la console Cloud Platform.
  • Sélectionnez le projet que vous souhaitez arrêter, puis cliquez sur "Supprimer" en haut de la page. Cette opération programme la suppression du projet.

Et ensuite ?

Découvrez quelques-uns de ces ateliers de programmation similaires :

Complément d'informations