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

1. Przegląd

Zanim zaczniemy, warto zapoznać się z tymi funkcjami i pojęciami, choć nie jest to konieczne.

4670cd5427aa39a6.png

Czego się nauczysz

W tym module znajdziesz implementację referencyjną podpisywania blockchaina zgodnego z MPC za pomocą Confidential Space. Aby zilustrować te koncepcje, przeanalizujemy scenariusz, w którym firma Primus chce przenieść zasoby cyfrowe do firmy Secundus. W tym scenariuszu firma Primus używa modelu zgodnego z MPC, co oznacza, że zamiast używać poszczególnych kluczy prywatnych, używa rozproszonych udziałów w kluczu. Te udziały klucza są przechowywane przez wiele podmiotów, w tym przypadku Alicję i Roberta. To podejście zapewnia firmie Primus kilka korzyści, w tym uproszczone wrażenia użytkownika, wydajność operacyjną i kontrolę nad kluczami prywatnymi.

Aby wyjaśnić podstawowe aspekty tego procesu, omówimy szczegółowo konfigurację techniczną oraz proces zatwierdzania i podpisywania, który inicjuje przeniesienie zasobów cyfrowych z firmy Primus do firmy Secundus. Pamiętaj, że Robert i Alicja, którzy są pracownikami firmy Primus, muszą zatwierdzić transakcję.

Chociaż ta implementacja referencyjna demonstruje operacje podpisywania, nie obejmuje 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 używanie usług innych niż Google Cloud do generowania współpodpisów lub tworzenie podpisów blockchain przez współpodpisujących w ich własnych środowiskach, co stanowi bardziej zdecentralizowaną architekturę. Mamy nadzieję, że ten moduł zainspiruje Cię do wypróbowania różnych podejść do MPC w Google Cloud.

Będziesz pracować z prostym obciążeniem, które podpisuje transakcję Ethereum w przestrzeni poufnej przy użyciu materiałów klucza współsygnatariusza. Podpisywanie transakcji w Ethereum to proces, w ramach którego użytkownik może autoryzować transakcję w blockchainie Ethereum. Aby wysłać transakcję Ethereum, musisz podpisać ją 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, ilość ETH do wysłania i inne istotne dane.
  2. Klucz prywatny nadawcy służy do tworzenia skrótu danych transakcji.
  3. Następnie hasz jest podpisywany kluczem prywatnym.
  4. Podpis jest dołączony do obiektu transakcji.
  5. Transakcja jest rozgłaszana w sieci Ethereum.

Gdy węzeł w sieci otrzyma 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 blockchaina.

Na początek skonfiguruj niezbędne zasoby w chmurze. Następnie uruchomisz zadanie w Poufnej przestrzeni. W tym ćwiczeniu z programowania wykonasz te czynności:

  • Konfigurowanie zasobów Cloud niezbędnych do uruchomienia przestrzeni poufnej
  • Jak autoryzować dostęp do chronionych zasobów 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 uruchomiony zbiór zadań.
  • Jak uruchomić zadanie na poufnej maszynie wirtualnej z obrazem maszyny wirtualnej Poufnej przestrzeni

Wymagane interfejsy API

Aby móc 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 w chmurze

Zanim zaczniesz

  • Sklonuj to repozytorium za pomocą poniższego polecenia, aby uzyskać wymagane skrypty używane w tym laboratorium.
git clone https://github.com/GoogleCloudPlatform/confidential-space.git
  • Zmień katalog tego ćwiczenia.
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 samouczku. 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 w obu projektach interfejs Confidential Computing API i te interfejsy API:
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 dla firmy A, np. export PRIMUS_INPUT_STORAGE_BUCKET='primus-input-bucket'
  • W projekcie GCP firmy A można ustawić te zmienne:

$PRIMUS_INPUT_STORAGE_BUCKET

Bucket, w którym są przechowywane zaszyfrowane klucze.

$PRIMUS_RESULT_STORAGE_BUCKET

Zasobnik, w którym przechowywane są wyniki transakcji MPC.

$PRIMUS_KEY

Klucz KMS używany do szyfrowania danych przechowywanych w $PRIMUS_INPUT_STORAGE_BUCKET na potrzeby Primus Bank.

$PRIMUS_KEYRING

Pęk kluczy KMS, który zostanie użyty do utworzenia klucza szyfrowania $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ę zadań MPC.

$PRIMUS_SERVICEACCOUNT

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

$PRIMUS_ARTIFACT_REPOSITORY

Repozytorium artefaktów do przechowywania obrazu kontenera zbioru zadań.

$WORKLOAD_SERVICEACCOUNT

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

$WORKLOAD_CONTAINER

Kontener Dockera, w którym jest uruchomiony zbiór zadań.

$WORKLOAD_IMAGE_NAME

Nazwa obrazu kontenera zadania.

$WORKLOAD_IMAGE_TAG

Tag obrazu kontenera zbioru zadań.

  • Uruchom ten skrypt, aby ustawić pozostałe nazwy zmiennych na wartości oparte na identyfikatorze projektu w przypadku nazw zasobów.
source config_env.sh

Konfigurowanie zasobów Cloud

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

W środowisku produkcyjnym wygenerujesz własny klucz prywatny. Na potrzeby tego modułu podzielimy jednak ten klucz prywatny na 2 części i zaszyfrujemy każdą z nich. W scenariuszu produkcyjnym klucze nigdy nie powinny być przechowywane w plikach tekstowych. Zamiast tego klucz prywatny można wygenerować poza Google Cloud (lub całkowicie pominąć i zastąpić niestandardowym tworzeniem fragmentów klucza MPC), a następnie zaszyfrować, aby nikt nie miał dostępu do klucza prywatnego ani do fragmentów klucza. Na potrzeby tego modułu będziemy używać interfejsu wiersza poleceń gcloud.

Uruchom ten skrypt, aby skonfigurować wymagane zasoby w chmurze. W ramach tych działań zostaną utworzone te zasoby:

  • Zasobnik Cloud Storage ($PRIMUS_INPUT_STORAGE_BUCKET) do przechowywania zaszyfrowanych udziałów klucza prywatnego.
  • zasobnik Cloud Storage ($PRIMUS_RESULT_STORAGE_BUCKET) do przechowywania wyników transakcji dotyczącej zasobów cyfrowych;
  • Klucz szyfrowania ($PRIMUS_KEY) i pęk kluczy ($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 u jej dostawcy.
  • Konto usługi ($PRIMUS_SERVICEACCOUNT) dołączone do wspomnianej powyżej puli tożsamości obciążeń ($PRIMUS_WORKLOAD_IDENTITY_POOL) z następującym dostępem do uprawnień:
  • roles/cloudkms.cryptoKeyDecrypter – odszyfrowanie danych za pomocą klucza KMS.
  • objectViewer – odczytywanie danych 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 zadania

Tworzenie konta usługi zadania

Teraz utworzysz konto usługi dla obciążenia 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ą, na której działa obciążenie.

Konto usługi zadania ($WORKLOAD_SERVICEACCOUNT) będzie miało przypisane te role:

  • confidentialcomputing.workloadUser, aby uzyskać token atestu.
  • logging.logWriter – zapisywanie logów w Cloud Logging.
  • objectViewer – odczytywanie danych z zasobnika Cloud Storage $PRIMUS_INPUT_STORAGE_BUCKET.
  • objectUser – zapisanie wyniku zbioru zadań w $PRIMUS_RESULT_STORAGE_BUCKET zasobniku Cloud Storage.
./create_workload_service_account.sh

Tworzenie zadania

Ten krok obejmuje utworzenie obrazu Dockera zbioru zadań. Obciążenie w tym samouczku to prosta aplikacja MPC w Node.js, która podpisuje transakcje cyfrowe dotyczące przenoszenia zasobów przy użyciu zaszyfrowanych udziałów klucza prywatnego. Tutaj znajdziesz kod projektu zadania. Projekt zadań zawiera te pliki:

package.json: ten plik zawiera listę pakietów, które powinny być używane w aplikacji MPC w przypadku obciążenia. W tym przypadku używamy bibliotek @google-cloud/kms, @google-cloud/storage, ethers i fast-crc32c. Tutaj znajdziesz plik package.json, którego będziemy używać w tym ćwiczeniu z programowania.

index.js: to punkt wejścia aplikacji zbioru zadań, który określa, jakie polecenia mają być uruchamiane podczas uruchamiania kontenera zbioru zadań. Dołączyliśmy też przykładową niepodpisaną transakcję, która zwykle jest dostarczana przez niezaufaną aplikację proszącą użytkowników o podpis. Ten plik index.js importuje też funkcje z pliku mpc.js, który utworzymy w następnym kroku. Poniżej znajdziesz zawartość pliku index.js. Możesz ją 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: w tym miejscu następuje podpisywanie transakcji. Importuje funkcje z plików kms-decrypt i credential-config, które omówimy w dalszej części. Poniżej znajdziesz zawartość pliku mpc.js. Możesz go też znaleźć 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 za pomocą kluczy zarządzanych w KMS. Poniżej znajdziesz zawartość 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 puli tożsamości zbiorów zadań i szczegóły dotyczące przyjęcia tożsamości konta usługi. Tutaj znajdziesz plik credential-config.js, którego będziemy używać w tych ćwiczeniach z programowania.

Dockerfile: na koniec utworzymy plik Dockerfile, który będzie używany do tworzenia obrazu Dockera obciążenia. Definiuje plik Dockerfile zgodnie z opisem 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: LABEL „tee.launch_policy.allow_cmd_override”=„true” w pliku Dockerfile to zasada uruchamiania ustawiona przez autora obrazu. Umożliwia operatorowi zastąpienie CMD podczas wykonywania zadania. Domyślnie parametr allow_cmd_override jest ustawiony na 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 którym wykonane zostaną te czynności:

  • Utwórz 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 do utworzenia obrazu Dockera z kodem zadania. Plik Dockerfile znajdziesz tutaj.
  • Utwórz obraz Dockera i opublikuj go w Artifact Registry ($PRIMUS_ARTIFACT_REPOSITORY) utworzonym w poprzednim kroku.
  • Przyznaj usłudze $WORKLOAD_SERVICEACCOUNT uprawnienia do odczytu $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

Węzeł Ethereum Ganache

Zanim autoryzujemy obciążenie, musimy utworzyć instancję Ethereum Ganache. Podpisana transakcja zostanie przesłana do tej instancji Ganache. Zanotuj adres IP tej instancji. Po uruchomieniu poniższego 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 zadania

W ramach tego kroku skonfigurujemy dostawcę puli tożsamości zadań w puli tożsamości zadań ($PRIMUS_WORKLOAD_IDENTITY_POOL). Dla tożsamości zadań skonfigurowane są warunki atrybutów, jak pokazano poniżej. Jednym z warunków jest sprawdzenie, 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 opisano, jak uruchomić zadanie na poufnej maszynie wirtualnej. Aby to zrobić, 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, w którym przechowywane są wyniki transakcji MPC.
  • KEY_BUCKET: zasobnik, w którym są przechowywane zaszyfrowane klucze MPC.
  • PRIMUS_PROJECT_NUMBER: Numer projektu użyty w pliku konfiguracyjnym danych logowania.
  • PRIMUS_PROJECT_ID: Identyfikator projektu używany w pliku konfiguracyjnym danych logowania. Wynik wykonania zadania 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 do weryfikacji tokenów przedstawianych przez zadanie.
  • WORKLOAD_SERVICEACCOUNT: konto usługi zbioru zadań.
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 przestrzeni poufnej i wyświetlenie wyników może potrwać kilka minut. Gdy maszyna wirtualna będzie w stanie zatrzymania, kontener będzie gotowy.

  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ę.

Możesz też uruchomić te polecenia, aby wyświetlić wynik.

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

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

Sprawdzanie transakcji w blockchainie Ganache

Możesz też wyświetlić transakcję 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. Znajdowanie identyfikatora 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. Wyświetl logi Ganache i sprawdź, czy jest w nich wymieniona transakcja.

5. Czyszczenie danych

Tutaj znajdziesz skrypt, którego możesz użyć do usunięcia zasobów utworzonych w ramach tego ćwiczenia z programowania. W ramach tego czyszczenia zostaną usunięte te zasoby:

  • Wejściowy zasobnik pamięci używany do przechowywania zaszyfrowanych części klucza ($PRIMUS_INPUT_STORAGE_BUCKET).
  • Klucz szyfrowania ($PRIMUS_KEY).
  • Konto usługi używane do uzyskiwania dostępu do chronionych zasobów ($PRIMUS_SERVICEACCOUNT).
  • Pula tożsamości zadań ($PRIMUS_WORKLOAD_IDENTITY_POOL).
  • Konto usługi obciążenia ($WORKLOAD_SERVICEACCOUNT).
  • Instancje obliczeniowe obciążeń ($WORKLOAD_VM$ETHEREUM_NODE).
  • Zasobnik na dane z wynikami używany do przechowywania wyników transakcji ($PRIMUS_RESULT_STORAGE_BUCKET).
  • Rejestr artefaktów używany do przechowywania obrazu zbioru zadań ($PRIMUS_ARTIFACT_REPOSITORY).
./cleanup.sh

Jeśli skończysz eksplorowanie, rozważ usunięcie projektu.

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

Co dalej?

Wypróbuj te podobne codelaby:

Więcej informacji