Come eseguire transazioni di asset digitali con il calcolo a parti multiple e Confidential Space

1. Panoramica

Prima di iniziare, anche se non è del tutto necessario, una conoscenza pratica delle seguenti funzionalità e concetti si rivelerà utile in questo codelab.

4670cd5427aa39a6.png

Obiettivi didattici

Questo lab fornisce un'implementazione di riferimento per l'esecuzione della firma blockchain conforme al calcolo multiparte sicuro utilizzando Confidential Space. Per illustrare i concetti, esamineremo uno scenario in cui la società Primus vuole trasferire risorse digitali alla società Secundus. In questo scenario, Company Primus utilizza un modello conforme al calcolo multiparte, il che significa che, anziché utilizzare singole chiavi private, utilizza quote di chiavi distribuite. Queste quote della chiave sono detenute da più parti, in questo caso Alice e Bob. Questo approccio offre a Company Primus diversi vantaggi, tra cui un'esperienza utente semplificata, efficienza operativa e controllo sulle chiavi private.

Per spiegare gli aspetti fondamentali di questa procedura, descriveremo la configurazione tecnica e ti guideremo attraverso la procedura di approvazione e firma che avvia il trasferimento delle risorse digitali dalla società Primus alla società Secundus. Tieni presente che Roberto e Alice, entrambi dipendenti di Company Primus, devono approvare la transazione.

Sebbene questa implementazione di riferimento mostri le operazioni di firma, non copre tutti gli aspetti della gestione delle chiavi MPC. Ad esempio, non parliamo della generazione di chiavi. Inoltre, esistono approcci alternativi e complementari, come l'utilizzo di servizi non Google Cloud per generare co-firme o la creazione di firme blockchain da parte dei co-firmatari nei propri ambienti, che è un'architettura più decentralizzata. Ci auguriamo che questo lab ti ispiri approcci diversi all'MPC su Google Cloud.

Lavorerai con un semplice workload che firma una transazione Ethereum in Confidential Space utilizzando i materiali della chiave del co-firmatario. La firma delle transazioni Ethereum è un processo mediante il quale un utente può autorizzare una transazione sulla blockchain Ethereum. Per inviare una transazione Ethereum, devi firmarla con la tua chiave privata. In questo modo dimostri di essere il proprietario dell'account e autorizzi la transazione. La procedura di firma è la seguente:

  1. Il mittente crea un oggetto transazione che specifica l'indirizzo del destinatario, l'importo di ETH da inviare e qualsiasi altro dato pertinente.
  2. La chiave privata del mittente viene utilizzata per eseguire l'hashing dei dati della transazione.
  3. L'hash viene quindi firmato con la chiave privata.
  4. La firma è allegata all'oggetto della transazione.
  5. La transazione viene trasmessa alla rete Ethereum.

Quando un nodo della rete riceve una transazione, ne verifica la firma per assicurarsi che sia stata firmata dal proprietario dell'account. Se la firma è valida, il nodo aggiungerà la transazione alla blockchain.

Per iniziare, configura le risorse cloud necessarie. Poi, eseguirai il carico di lavoro in Confidential Space. Questo codelab ti guiderà attraverso i seguenti passaggi di alto livello:

  • Come configurare le risorse cloud necessarie per eseguire Confidential Space
  • Come autorizzare l'accesso alle risorse protette in base agli attributi di:
  • Cosa: il contenitore del carico di lavoro
  • Dove: l'ambiente Confidential Space (l'immagine Confidential Space su Confidential VM)
  • Chi: l'account che esegue il carico di lavoro
  • Come eseguire il workload in una Confidential VM che esegue l'immagine VM Confidential Space

API obbligatorie

Per poter completare questa guida, devi abilitare le seguenti API nei progetti specificati.

Nome API

Titolo dell'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. Configurare le risorse cloud

Prima di iniziare

  • Clona questo repository utilizzando il comando riportato di seguito per ottenere gli script richiesti utilizzati in questo codelab.
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
  • Modifica la directory per questo codelab.
cd confidential-space/codelabs/digital_asset_transaction_codelab/scripts
  • Assicurati di aver impostato le variabili di ambiente del progetto richieste come mostrato di seguito. Per saperne di più sulla configurazione di un progetto Google Cloud, consulta questo codelab. Puoi fare riferimento a questo articolo per scoprire come recuperare l'ID progetto e in che modo è diverso dal nome e dal numero del progetto. .
export PRIMUS_PROJECT_ID=<GCP project id>
  • Abilita la fatturazione per i tuoi progetti.
  • Abilita l'API Confidential Computing e le seguenti API per entrambi i progetti.
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
  • Per impostare le variabili per i nomi delle risorse, puoi utilizzare il seguente comando. Tieni presente che questo sostituirà i nomi delle risorse specifici del tuo progetto GCP per la società A, ad esempio export PRIMUS_INPUT_STORAGE_BUCKET='primus-input-bucket'
  • Per il tuo progetto GCP in Azienda A possono essere impostate le seguenti variabili:

$PRIMUS_INPUT_STORAGE_BUCKET

Il bucket che archivia le chiavi criptate.

$PRIMUS_RESULT_STORAGE_BUCKET

Il bucket che archivia il risultato della transazione MPC.

$PRIMUS_KEY

La chiave KMS utilizzata per criptare i dati archiviati in $PRIMUS_INPUT_STORAGE_BUCKET per Primus Bank.

$PRIMUS_KEYRING

Il keyring KMS che verrà utilizzato per creare la chiave di crittografia $PRIMUS_KEY per Primus Bank.

$PRIMUS_WIP_PROVIDER

Il provider di pool di identità del workload che include la condizione dell'attributo da utilizzare per i token firmati dal servizio di workload MPC.

$PRIMUS_SERVICEACCOUNT

Il service account utilizzato da $PRIMUS_WORKLOAD_IDENTITY_POOL per accedere alle risorse protette. Questo service account avrà l'autorizzazione per visualizzare le chiavi criptate archiviate nel bucket $PRIMUS_INPUT_STORAGE_BUCKET.

$PRIMUS_ARTIFACT_REPOSITORY

Il repository di artefatti per l'archiviazione dell'immagine container del carico di lavoro.

$WORKLOAD_SERVICEACCOUNT

Il service account che dispone dell'autorizzazione per accedere alla VM confidenziale che esegue il workload.

$WORKLOAD_CONTAINER

Il container Docker che esegue il carico di lavoro.

$WORKLOAD_IMAGE_NAME

Il nome dell'immagine container del workload.

$WORKLOAD_IMAGE_TAG

Il tag dell'immagine container del workload.

  • Esegui il seguente script per impostare i nomi delle variabili rimanenti su valori basati sull'ID progetto per i nomi delle risorse.
source config_env.sh

Configura le risorse cloud

Nell'ambito di questo passaggio, configurerai le risorse cloud necessarie per il calcolo multiparte. Per questo lab, utilizzerai la seguente chiave privata: 0000000000000000000000000000000000000000000000000000000000000001

In un ambiente di produzione, genererai la tua chiave privata. Tuttavia, ai fini di questo lab, divideremo questa chiave privata in due parti e le criptiamo. In uno scenario di produzione, le chiavi non devono mai essere archiviate in file di testo non crittografato. La chiave privata può essere generata al di fuori di Google Cloud (o ignorata completamente e sostituita con la creazione di shard di chiavi MPC personalizzati) e poi criptata in modo che nessuno abbia accesso alla chiave privata o alle condivisioni di chiavi. Ai fini di questo lab, utilizzeremo gcloud CLI.

Esegui il seguente script per configurare le risorse cloud richieste. Nell'ambito di questi passaggi, verranno create le risorse menzionate di seguito:

  • Un bucket Cloud Storage ($PRIMUS_INPUT_STORAGE_BUCKET) per archiviare le condivisioni della chiave privata criptata.
  • Un bucket Cloud Storage ($PRIMUS_RESULT_STORAGE_BUCKET) per archiviare il risultato della transazione di asset digitali.
  • Una chiave di crittografia ($PRIMUS_KEY) e un portachiavi ($PRIMUS_KEYRING) in KMS per criptare le condivisioni della chiave privata.
  • Un pool di identità del workload ($PRIMUS_WORKLOAD_IDENTITY_POOL) per convalidare le rivendicazioni in base alle condizioni degli attributi configurate nel relativo fornitore.
  • Un service account ($PRIMUS_SERVICEACCOUNT) collegato al pool di identità del workload ($PRIMUS_WORKLOAD_IDENTITY_POOL) menzionato sopra con il seguente accesso IAM:
  • roles/cloudkms.cryptoKeyDecrypter per decriptare i dati utilizzando la chiave KMS.
  • objectViewer per leggere i dati dal bucket Cloud Storage.
  • roles/iam.workloadIdentityUser per connettere questo service account al pool di identità del workload.
./setup_resources.sh

3. Crea workload

Crea un service account del workload

Ora creerai un service account per il workload con i ruoli e le autorizzazioni richiesti. Per farlo, esegui il seguente script, che creerà un service account del workload per la società A. Questo service account verrà utilizzato dalla VM che esegue il workload.

Il service account del workload ($WORKLOAD_SERVICEACCOUNT) avrà i seguenti ruoli:

  • confidentialcomputing.workloadUser per ottenere un token di attestazione
  • logging.logWriter per scrivere i log in Cloud Logging.
  • objectViewer per leggere i dati dal bucket Cloud Storage $PRIMUS_INPUT_STORAGE_BUCKET.
  • objectUser per scrivere il risultato del workload nel bucket Cloud Storage $PRIMUS_RESULT_STORAGE_BUCKET.
./create_workload_service_account.sh

Crea workload

Questo passaggio prevede la creazione di un'immagine Docker del workload. Il workload in questo codelab è una semplice applicazione MPC Node.js che firma transazioni digitali per il trasferimento di asset utilizzando condivisioni di chiavi private criptate. Qui è riportato il codice del progetto del carico di lavoro. Il progetto del workload include i seguenti file.

package.json::questo file contiene l'elenco dei pacchetti da utilizzare per l'applicazione MPC del workload. In questo caso, utilizziamo le librerie @google-cloud/kms, @google-cloud/storage, ethers e fast-crc32c. Qui trovi il file package.json che utilizzeremo per questo codelab.

index.js::questo è un punto di ingresso dell'applicazione del carico di lavoro e specifica quali comandi devono essere eseguiti all'avvio del container del carico di lavoro. Abbiamo incluso anche una transazione non firmata di esempio che normalmente verrebbe fornita da un'applicazione non attendibile che chiede agli utenti la loro firma. Questo file index.js importa anche funzioni da mpc.js, che creeremo in seguito. Di seguito è riportato il contenuto del file index.js, che puoi trovare anche qui.

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::qui avviene la firma della transazione. Importa le funzioni da kms-decrypt e credential-config, che tratteremo in seguito. Di seguito è riportato il contenuto del file mpc.js, che puoi trovare anche qui.

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: questo file contiene il codice per la decriptazione utilizzando le chiavi gestite in KMS. Di seguito è riportato il contenuto del file kms-decrypt.js, che puoi trovare anche qui.

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:il file memorizza i percorsi e i dettagli del pool di identità per i workload per la simulazione dell'identità del service account. Qui trovi il file credential-config.js che utilizzeremo per questo codelab.

Dockerfile: infine, creeremo il nostro Dockerfile che verrà utilizzato per creare l'immagine Docker del workload. Definisce il Dockerfile come specificato qui.

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" nel Dockerfile è una policy di avvio impostata dall'autore dell'immagine. Consente all'operatore di eseguire l'override del comando quando esegue il workload. Per impostazione predefinita, allow_cmd_override è impostato su false. L'etichetta "tee.launch_policy.allow_env_override" indica a Confidential Space quali variabili di ambiente possono utilizzare gli utenti delle immagini .

Esegui il seguente script per creare un carico di lavoro in cui vengono eseguiti i seguenti passaggi:

  • Crea Artifact Registry($PRIMUS_ARTIFACT_REPOSITORY) per archiviare l'immagine Docker del workload.
  • Aggiorna il codice del workload con i nomi delle risorse richieste. Qui trovi il codice del workload utilizzato per questo codelab.
  • Crea Dockerfile per creare un'immagine Docker del codice del workload. Puoi trovare il Dockerfile qui.
  • Crea e pubblica l'immagine Docker in Artifact Registry ($PRIMUS_ARTIFACT_REPOSITORY) creato nel passaggio precedente.
  • Concedi l'autorizzazione di lettura $WORKLOAD_SERVICEACCOUNT per $PRIMUS_ARTIFACT_REPOSITORY. Ciò è necessario affinché il container del workload possa estrarre l'immagine Docker del workload da Artifact Registry.
./create_workload.sh

Crea il nodo blockchain

Nodo Ethereum Ganache

Prima di autorizzare il workload, dobbiamo creare l'istanza di Ethereum Ganache. La transazione firmata verrà inviata a questa istanza Ganache. Prendi nota dell'indirizzo IP di questa istanza. Dopo aver eseguito il comando riportato di seguito, potrebbe essere necessario inserire y per abilitare 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. Autorizza ed esegui il workload

Autorizza il workload

Nell'ambito di questo passaggio, configureremo il fornitore del pool di identità del workload nel pool di identità del workload ($PRIMUS_WORKLOAD_IDENTITY_POOL). Sono configurate condizioni degli attributi per l'identità del workload, come mostrato di seguito. Una delle condizioni è convalidare che l'immagine del workload venga estratta dal repository di artefatti previsto.

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"

Esegui workload

Questa sezione spiega come eseguire il workload su Confidential VM. A questo scopo, trasmetteremo gli argomenti TEE richiesti utilizzando il flag dei metadati. Inoltre, imposteremo le variabili di ambiente per il container del workload utilizzando il flag "tee-env-*". L'immagine ha le seguenti variabili:

  • NODE_URL: l'URL del nodo Ethereum che elaborerà la transazione firmata.
  • RESULTS_BUCKET: Il bucket che archivia il risultato della transazione MPC.
  • KEY_BUCKET: Il bucket che archivia le chiavi criptate MPC.
  • PRIMUS_PROJECT_NUMBER: il numero di progetto utilizzato per il file di configurazione delle credenziali.
  • PRIMUS_PROJECT_ID: L'ID progetto utilizzato per il file di configurazione delle credenziali. Il risultato dell'esecuzione del workload verrà pubblicato in $PRIMUS_RESULT_STORAGE_BUCKET.
  • PRIMUS_WORKLOAD_IDENTITY_POOL: Il pool di identità del workload utilizzato per convalidare le rivendicazioni.
  • PRIMUS_WIP_POROVIDER: il fornitore di pool di identità del workload che include le condizioni degli attributi da utilizzare per la convalida dei token presentati dal workload.
  • WORKLOAD_SERVICEACCOUNT: Il service account del workload.
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}"

Controlla i risultati di Cloud Storage

Puoi visualizzare la ricevuta della transazione in Cloud Storage. Potrebbero essere necessari alcuni minuti prima che Confidential Space venga avviato e che vengano visualizzati i risultati. Saprai che il contenitore è pronto quando la VM è nello stato Arrestato.

  1. Vai alla pagina Browser Cloud Storage.
  2. Fai clic su $PRIMUS_RESULT_STORAGE_BUCKET.
  3. Fai clic sul file transaction_receipt.
  4. Fai clic su Scarica per scaricare e visualizzare la risposta alla transazione.

In alternativa, puoi eseguire i seguenti comandi per visualizzare il risultato.

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

Nota:se i risultati non vengono visualizzati, puoi andare a $WORKLOAD_VM nella pagina Compute Engine Cloud Console e fare clic su "Porta seriale 1 (console)" per visualizzare i log.

Controlla la transazione blockchain di Ganache

Puoi anche visualizzare la transazione nel log della blockchain.

  1. Vai alla pagina Cloud Compute Engine.
  2. Fai clic su ${ETHEREUM_NODE} VM.
  3. Fai clic su SSH per aprire la finestra SSH nel browser.
  4. Nella finestra SSH, inserisci sudo docker ps per visualizzare il container Ganache in esecuzione.
  5. Trova l'ID contenitore per trufflesuite/ganache:v7.7.3
  6. Inserisci sudo docker logs CONTAINER_ID sostituendo CONTAINER_ID con l'ID di trufflesuite/ganache:v7.7.3.
  7. Visualizza i log di Ganache e verifica che sia presente una transazione elencata nei log.

5. Esegui la pulizia

Qui trovi lo script che può essere utilizzato per eseguire la pulizia delle risorse che abbiamo creato nell'ambito di questo codelab. Nell'ambito di questa pulizia, verranno eliminate le seguenti risorse:

  • Bucket di archiviazione di input utilizzato per archiviare le condivisioni di chiavi criptate ($PRIMUS_INPUT_STORAGE_BUCKET).
  • Chiave di crittografia ($PRIMUS_KEY).
  • Service account utilizzato per accedere alle risorse protette ($PRIMUS_SERVICEACCOUNT).
  • Pool di identità del workload ($PRIMUS_WORKLOAD_IDENTITY_POOL).
  • Service account del workload ($WORKLOAD_SERVICEACCOUNT).
  • Istanze di calcolo del workload ($WORKLOAD_VM e $ETHEREUM_NODE).
  • Bucket di archiviazione dei risultati utilizzato per archiviare il risultato della transazione.($PRIMUS_RESULT_STORAGE_BUCKET).
  • Registro Artifact utilizzato per archiviare l'immagine del workload ($PRIMUS_ARTIFACT_REPOSITORY).
./cleanup.sh

Se hai terminato l'esplorazione, valuta la possibilità di eliminare il progetto.

  • Vai alla console di Cloud Platform.
  • Seleziona il progetto che vuoi chiudere, poi fai clic su "Elimina" in alto. In questo modo, l'eliminazione del progetto viene pianificata.

Passaggi successivi

Dai un'occhiata ad alcuni di questi codelab simili...

Further reading