Jak transakować zasoby cyfrowe z użyciem wielostronnego przetwarzania danych i przestrzeni poufnej

1. Omówienie

Zanim zaczniesz, warto zapoznać się z funkcjami i koncepcjami, które mogą okazać się przydatne w tym ćwiczeniu.

4670cd5427aa39a6.png

Czego się nauczysz

Ten moduł zawiera implementację referencyjną podpisywania blockchain zgodnego z MPC za pomocą Confidential Space. Aby zilustrować te zagadnienia, omówimy scenariusz, w którym firma Primus chce przenieść zasoby cyfrowe do firmy Secundus. W tym scenariuszu firma Primus korzysta z modelu zgodnego z MPC, co oznacza, że zamiast używać indywidualnych kluczy prywatnych, używa kluczy udostępnionych. Te klucze są udostępniane wielu stronom, w tym przypadku Alicji i Robertowi. Dzięki temu podejściu firma Primus może liczyć na kilka korzyści, w tym uproszczone wrażenia użytkowników, wydajność operacyjną i kontrolę nad kluczami prywatnymi.

Aby wyjaśnić podstawowe aspekty tego procesu, omówimy szczegółowo konfigurację techniczną i przeprowadzimy Cię przez proces zatwierdzania i podpisywania, który inicjuje przeniesienie zasobów cyfrowych z firmy Primus do firmy Secundus. Pamiętaj, że transakcja musi zostać zatwierdzona przez Roberta i Alicję, którzy są pracownikami firmy Primus.

Chociaż to implementacja referencyjna demonstruje operacje podpisywania, nie obejmuje ona wszystkich aspektów zarządzania kluczami MPC. Nie omawiamy na przykład generowania kluczy. Istnieją też alternatywne i uzupełniające podejścia, takie jak generowanie podpisów współdzielonych za pomocą usług innych niż Google Cloud lub tworzenie podpisów blockchain przez współpodpisujących w ich własnych środowiskach, co jest bardziej zdecentralizowaną architekturą. Mamy nadzieję, że ten moduł praktyczny zainspiruje Cię do stosowania różnych podejść do MPC w Google Cloud.

Będziesz pracować z prostym zadaniem, które podpisuje transakcję Ethereum w Confidential Space przy użyciu materiałów klucza współpodpisującego. Podpisywanie transakcji Ethereum to proces, dzięki któremu użytkownik może autoryzować transakcję w łańcuchu bloków Ethereum. Aby wysłać transakcję Ethereum, musisz ją podpisać kluczem prywatnym. Potwierdza to, że jesteś właścicielem konta i autoryzujesz transakcję. Proces podpisywania wygląda następująco:

  1. Nadawca tworzy obiekt transakcji, który określa adres odbiorcy, kwotę ETH do wysłania i inne odpowiednie dane.
  2. Klucz prywatny nadawcy służy do tworzenia hasz danych transakcji.
  3. Następnie hasz jest podpisywany kluczem prywatnym.
  4. Podpis jest dołączony do obiektu transakcji.
  5. Transakcja jest nadawana do sieci Ethereum.

Gdy węzeł w sieci odbiera transakcję, weryfikuje podpis, aby upewnić się, że został on złożony przez właściciela konta. Jeśli podpis jest prawidłowy, węzeł doda transakcję do blockchainu.

Na początek skonfiguruj niezbędne zasoby Cloud. Następnie uruchom zadanie w Poufnej przestrzeni. W tym ćwiczeniu z programowania znajdziesz te ogólne wskazówki:

  • Jak skonfigurować niezbędne zasoby Cloud do obsługi Confidential Space
  • Jak zezwolić na dostęp do zasobów chronionych na podstawie atrybutów:
  • Co: kontener zbioru zadań
  • Gdzie: środowisko poufnej przestrzeni (obraz poufnej przestrzeni na poufnej maszynie wirtualnej)
  • Kto: konto, na którym jest wykonywane zadanie.
  • Jak uruchomić zadanie w poufnej maszynie wirtualnej z obrazem maszyny wirtualnej Poufna przestrzeń

Wymagane interfejsy API

Aby wykonać czynności opisane w tym przewodniku, musisz włączyć te interfejsy API w określonych projektach.

Nazwa interfejsu API

Tytuł interfejsu API

cloudkms.googleapis.com

Cloud KMS

compute.googleapis.com

Compute Engine

confidentialcomputing.googleapis.com

Przetwarzanie poufne

iamcredentials.googleapis.com

Uprawnienia

artifactregistry.googleapis.com

Artifact Registry

2. Konfigurowanie zasobów Cloud

Zanim zaczniesz

  • Skopiuj to repozytorium, używając tego polecenia, aby pobrać wymagane skrypty używane w ramach tego Codelab.
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
  • Zmień katalog tego Codelab.
cd confidential-space/codelabs/digital_asset_transaction_codelab/scripts
  • Sprawdź, czy masz ustawione wymagane zmienne środowiskowe projektu, jak pokazano poniżej. Więcej informacji o konfigurowaniu projektu GCP znajdziesz w  tym CodeLab. Więcej informacji o tym, jak pobrać identyfikator projektu i czym różni się on od nazwy i numeru projektu, znajdziesz tutaj. .
export PRIMUS_PROJECT_ID=<GCP project id>
  • Włącz płatności w swoich projektach.
  • Włącz interfejs Confidential Computing API i te interfejsy API w obu projektach.
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
  • Aby ustawić zmienne dla nazw zasobów, możesz użyć tego polecenia. Pamiętaj, że spowoduje to zastąpienie nazw zasobów specyficznych dla Twojego projektu GCP w firmie A, np. export PRIMUS_INPUT_STORAGE_BUCKET='primus-input-bucket'
  • W projekcie GCP w firmie A możesz ustawić te zmienne:

$PRIMUS_INPUT_STORAGE_BUCKET

Zasób, w którym są przechowywane zaszyfrowane klucze.

$PRIMUS_RESULT_STORAGE_BUCKET

Zasobnik, który przechowuje wynik transakcji MPC.

$PRIMUS_KEY

Klucz KMS używany do szyfrowania danych przechowywanych w zasobniku $PRIMUS_INPUT_STORAGE_BUCKET dla Primus Bank.

$PRIMUS_KEYRING

Klucz KMS, który zostanie użyty do utworzenia klucza szyfrującego $PRIMUS_KEY dla Primus Bank.

$PRIMUS_WIP_PROVIDER

Dostawca puli tożsamości zadań, który zawiera warunek atrybutu do użycia w przypadku tokenów podpisanych przez usługę zbioru zadań MPC.

$PRIMUS_SERVICEACCOUNT

Konto usługi, którego używa $PRIMUS_WORKLOAD_IDENTITY_POOL do uzyskiwania dostępu do zasobów chronionych. To konto usługi będzie mieć uprawnienia do wyświetlania zaszyfrowanych kluczy przechowywanych w zasośniku $PRIMUS_INPUT_STORAGE_BUCKET.

$PRIMUS_ARTIFACT_REPOSITORY

Repozytorium artefaktów służące do przechowywania obrazu kontenera zadania.

$WORKLOAD_SERVICEACCOUNT

Konto usługi, które ma uprawnienia dostępu do maszyny wirtualnej poufnej, na której działa obciążenie.

$WORKLOAD_CONTAINER

Kontener Dockera, w którym jest wykonywane zadanie.

$WORKLOAD_IMAGE_NAME

Nazwa obrazu kontenera zbioru zadań.

$WORKLOAD_IMAGE_TAG

Tag obrazu kontenera zbioru zadań.

  • Uruchom poniższy skrypt, aby ustawić pozostałe nazwy zmiennych na wartości oparte na identyfikatorze projektu.
source config_env.sh

Konfigurowanie zasobów Cloud

W ramach tego kroku skonfigurujesz zasoby chmurowe wymagane do obliczeń wielostronnych. W tym laboratorium użyjesz tego klucza prywatnego: 0000000000000000000000000000000000000000000000000000000000000001

W środowisku produkcyjnym wygenerujesz własny klucz prywatny. Jednak na potrzeby tego laboratorium podzielimy ten klucz prywatny na 2 części i zaszyfrujemy każdą z nich. W wersji produkcyjnej kluczy nie należy nigdy przechowywać w plikach tekstowych. Klucz prywatny można wygenerować poza Google Cloud (lub całkowicie pominąć i zastąpić niestandardowym utworzeniem fragmentu klucza MPC), a następnie zaszyfrować, aby nikt nie miał dostępu do klucza prywatnego ani jego części. W tym module użyjemy interfejsu wiersza poleceń gcloud.

Aby skonfigurować wymagane zasoby w chmurze, uruchom ten skrypt. W ramach tych czynności zostaną utworzone wymienione poniżej zasoby:

  • Zasobnik Cloud Storage ($PRIMUS_INPUT_STORAGE_BUCKET) do przechowywania zaszyfrowanych udziałów klucza prywatnego.
  • Zasobnik Cloud Storage ($PRIMUS_RESULT_STORAGE_BUCKET) do przechowywania wyniku transakcji dotyczącej zasobu cyfrowego.
  • Klucz szyfrowania ($PRIMUS_KEY) i kluczyk ($PRIMUS_KEYRING) w KMS do szyfrowania udziałów klucza prywatnego.
  • Pula tożsamości zadań ($PRIMUS_WORKLOAD_IDENTITY_POOL) do weryfikowania roszczeń na podstawie warunków atrybutów skonfigurowanych w ramach dostawcy.
  • Konto usługi ($PRIMUS_SERVICEACCOUNT) przypisane do wspomnianej puli tożsamości zadań ($PRIMUS_WORKLOAD_IDENTITY_POOL) z tymi uprawnieniami dostępu IAM:
  • roles/cloudkms.cryptoKeyDecrypter, aby odszyfrować dane za pomocą klucza KMS.
  • objectViewer, aby odczytać dane z zasobnika Cloud Storage.
  • roles/iam.workloadIdentityUser do połączenia tego konta usługi z pulą tożsamości zadań.
./setup_resources.sh

3. Tworzenie zadań

Tworzenie konta usługi zadania

Teraz utwórz konto usługi dla zadania z wymaganymi rolami i uprawnieniami. Aby to zrobić, uruchom ten skrypt, który utworzy konto usługi obciążenia dla firmy A. To konto usługi będzie używane przez maszynę wirtualną, która wykonuje obciążenie.

Konto usługi związane z zadaniami ($WORKLOAD_SERVICEACCOUNT) będzie mieć przypisane te role:

  • confidentialcomputing.workloadUser, aby uzyskać token atestacji
  • logging.logWriter, aby zapisywać logi w Cloud Logging.
  • objectViewer do odczytu danych z zasobnika Cloud Storage $PRIMUS_INPUT_STORAGE_BUCKET.
  • objectUser, aby zapisać wyniki zbioru zadań w zasobniku Cloud Storage $PRIMUS_RESULT_STORAGE_BUCKET.
./create_workload_service_account.sh

Tworzenie zbioru zadań

Ten krok obejmuje utworzenie obrazu Dockera zadania. Zadania w tym CodeLab to prosta aplikacja MPC w Node.js, która podpisuje transakcje cyfrowe w celu przeniesienia zasobów za pomocą zaszyfrowanych udziałów klucza prywatnego. Tutaj znajdziesz kod projektu zadania. Projekt obciążenia zawiera te pliki:

package.json: ten plik zawiera listę pakietów, których należy używać w przypadku aplikacji MPC dotyczącej obciążenia. W tym przypadku używamy bibliotek @google-cloud/kms, @google-cloud/storage, ethers i fast-crc32c. Tutaj jest plik package.json, którego użyjemy w tym ćwiczeniu.

index.js: to punkt wejścia aplikacji zbioru zadań, który określa, jakie polecenia powinny być wykonywane podczas uruchamiania kontenera zbioru zadań. Dołączyliśmy też przykładową transakcję bez podpisu, która zwykle jest dostarczana przez nie zaufaną aplikację, która prosi użytkowników o podpis. Ten plik index.js importuje też funkcje z pliku mpc.js, który utworzymy później. Poniżej znajduje się treść pliku index.js, którą możesz też znaleźć tutaj.

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: tutaj odbywa się podpisywanie transakcji. Zaimportuje on funkcje z kms-decrypt i credential-config, które omówimy w następnym artykule. Poniżej znajduje się treść pliku mpc.js, który znajdziesz też tutaj.

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: ten plik zawiera kod do odszyfrowywania przy użyciu kluczy zarządzanych w KMS. Poniżej znajduje się treść pliku kms-decrypt.js. Możesz go też znaleźć tutaj.

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: plik przechowuje ścieżki do puli tożsamości zbiorów zadań i szczegóły dotyczące przyjęcia tożsamości konta usługi. Tutaj znajduje się plik credential-config.js, którego użyjemy w tym ćwiczeniu.

Dockerfile: na koniec utworzymy plik Dockerfile, który posłuży do skompilowania obrazu Dockera z obciążeniem. Plik Dockerfile definiuje tutaj.

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

Uwaga: etykieta „tee.launch_policy.allow_cmd_override”="true" w pliku Dockerfile to polityka uruchamiania określona przez autora obrazu. Umożliwia operatorowi zastąpienie CMD podczas wykonywania zadania. Domyślnie parametr allow_cmd_override ma wartość false. Etykieta „tee.launch_policy.allow_env_override” informuje Confidential Space, których zmiennych środowiskowych mogą używać użytkownicy obrazu .

Uruchom ten skrypt, aby utworzyć zadanie, w ramach którego wykonywane są te czynności:

  • Utwórz repozytorium Artifact Registry($PRIMUS_ARTIFACT_REPOSITORY), aby przechowywać obraz Dockera zadania.
  • Zaktualizuj kod zbioru zadań, podając nazwy wymaganych zasobów. Tutaj znajdziesz kod obciążenia użyty w tym ćwiczeniu.
  • Utwórz plik Dockerfile, aby skompilować obraz Dockera kodu zadania. Plik Dockerfile znajdziesz tutaj.
  • Utwórz i opublikuj obraz Dockera w repozytorium Artifact Registry ($PRIMUS_ARTIFACT_REPOSITORY) utworzonym w poprzednim kroku.
  • Przyznaj użytkownikowi $WORKLOAD_SERVICEACCOUNT uprawnienie do odczytu w przypadku zasobu $PRIMUS_ARTIFACT_REPOSITORY. Jest to konieczne, aby kontener zadania mógł pobrać obraz Dockera zadania z Artifact Registry.
./create_workload.sh

Tworzenie węzła blockchain

Ganache Ethereum Node

Zanim autoryzujemy obciążenie, musimy utworzyć instancję Ethereum Ganache. Podpisana transakcja zostanie przesłana do tej instancji Ganache. Zanotuj adres IP tej instancji. Po wykonaniu tego polecenia może być konieczne wpisanie y, aby włączyć interfejs 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. Autoryzowanie i uruchamianie zbioru zadań

Autoryzowanie zbioru zadań

W ramach tego kroku skonfigurujemy dostawcę puli tożsamości zadań w ramach puli tożsamości zadań ($PRIMUS_WORKLOAD_IDENTITY_POOL). W przypadku tożsamości zadań skonfigurowane są warunki atrybutów, jak pokazano poniżej. Jednym z warunków jest weryfikacja, czy obraz zadania jest pobierany z oczekiwanego repozytorium artefaktów.

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"

Uruchamianie zadania

W tej sekcji wyjaśniamy, jak uruchomić zadanie na poufnej maszynie wirtualnej. W tym celu przekażemy wymagane argumenty TEE za pomocą flagi metadanych. Dodatkowo ustawimy zmienne środowiskowe dla kontenera obciążenia za pomocą flagi „tee-env-*”. Obraz ma te zmienne:

  • NODE_URL: adres URL węzła Ethereum, który przetworzy podpisaną transakcję.
  • RESULTS_BUCKET: zasobnik, który przechowuje wynik transakcji MPC.
  • KEY_BUCKET: zasób, w którym przechowywane są klucze szyfrowania mpc.
  • PRIMUS_PROJECT_NUMBER: numer projektu używany w pliku konfiguracji danych logowania.
  • PRIMUS_PROJECT_ID: identyfikator projektu używany w pliku konfiguracji danych logowania. Wynik wykonania zbioru zadań zostanie opublikowany w $PRIMUS_RESULT_STORAGE_BUCKET.
  • PRIMUS_WORKLOAD_IDENTITY_POOL: pula tożsamości zadań używana do weryfikowania roszczeń.
  • PRIMUS_WIP_POROVIDER: dostawca puli tożsamości zadań, który zawiera warunki atrybutów służące do sprawdzania tokenów przedstawionych przez zadanie.
  • WORKLOAD_SERVICEACCOUNT: konto usługi obciążenia.
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}"

Sprawdzanie wyników Cloud Storage

Potwierdzenie transakcji możesz wyświetlić w Cloud Storage. Uruchomienie prywatnej przestrzeni może potrwać kilka minut, a wyświetlenie wyników może zająć jeszcze więcej czasu. Po zakończeniu tworzenia kontenera maszyna wirtualna jest w stanie zatrzymanym.

  1. Otwórz stronę Przeglądarka Cloud Storage.
  2. Kliknij $PRIMUS_RESULT_STORAGE_BUCKET.
  3. Kliknij plik transaction_receipt.
  4. Kliknij Pobierz, aby pobrać i wyświetlić odpowiedź na transakcję.

Aby wyświetlić wynik, możesz też uruchomić te polecenia.

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

Uwaga: jeśli wyniki się nie wyświetlają, możesz przejść na stronę $WORKLOAD_VM w konsoli Compute Engine Cloud i kliknąć „Port szeregowy 1 (konsola)”, aby wyświetlić dzienniki.

Sprawdzanie transakcji w Ganache Blockchain

Transakcję możesz też wyświetlić w dzienniku blockchain.

  1. Otwórz stronę Cloud Compute Engine.
  2. Kliknij ${ETHEREUM_NODE} VM.
  3. Kliknij SSH, aby otworzyć okno SSH w przeglądarce.
  4. W oknie SSH wpisz sudo docker ps, aby wyświetlić uruchomiony kontener Ganache.
  5. Znajdź identyfikator kontenera trufflesuite/ganache:v7.7.3
  6. Wpisz sudo docker logs CONTAINER_ID, zastępując CONTAINER_ID identyfikatorem trufflesuite/ganache:v7.7.3.
  7. Sprawdź dzienniki Ganache i potwierdź, że w nich znajduje się transakcja.

5. Czyszczenie danych

Tutaj znajdziesz skrypt, który możesz wykorzystać do wyczyszczenia zasobów utworzonych w ramach tego ćwiczenia. W ramach tego czyszczenia zostaną usunięte te zasoby:

  • Zasób pamięci wejściowej służący do przechowywania zaszyfrowanych udziałów klucza ($PRIMUS_INPUT_STORAGE_BUCKET).
  • Klucz szyfrowania ($PRIMUS_KEY).
  • Konto usługi używane do uzyskiwania dostępu do zasobów chronionych ($PRIMUS_SERVICEACCOUNT).
  • Pula tożsamości zadań ($PRIMUS_WORKLOAD_IDENTITY_POOL).
  • Konto usługi Workload Manager ($WORKLOAD_SERVICEACCOUNT).
  • Instancje obliczeniowe obciążenia ($WORKLOAD_VM i $ETHEREUM_NODE).
  • Zasobnik do przechowywania wyników służący do przechowywania wyniku transakcji ($PRIMUS_RESULT_STORAGE_BUCKET).
  • Repozytorium artefaktów służące do przechowywania obrazu zbioru zadań ($PRIMUS_ARTIFACT_REPOSITORY).
./cleanup.sh

Gdy skończysz eksplorować, możesz usunąć projekt.

  • Otwórz konsolę Cloud Platform.
  • Wybierz projekt, który chcesz zamknąć, a potem u góry kliknij „Usuń”. Spowoduje to zaplanowanie usunięcia projektu.

Co dalej?

Sprawdź te podobne laboratoria programistyczne...

Więcej informacji