Smart Contract erstellen und bereitstellen

Für die Erstellung des Smart Contracts müssen wir die Entitäten definieren, die in Blockchain gespeichert und verwaltet werden sollen, wie im Entitätsmodell des folgenden Bildes dargestellt.


Beschreibung von oracle-blockchain-cms-entity.png folgt
Beschreibung der Abbildung oracle-blockchain-cms-entity.png

Alle diese Entitys und ihre Beziehungen, die gesamte Logik, die zum Verwalten und Interagieren mit den Entitys sowie zum Persistieren im Blockchain-Ledger erforderlich ist, ist im Smart Contract definiert.

Der Ordner wird als NFT-Token dargestellt und wird daher als NFT entwickelt und initialisiert. Die anderen abhängigen Entitys (Dokumente und Eigenschaften) sind Standardentitys und untergeordnete Entitys des Ordners. Daher werden sie als Standardentitys ohne Initialisierung entwickelt.

Sobald der Smart-Vertrag erstellt ist, werden wir ihn in dem von uns erstellten Blockchain-Netzwerk installieren und bereitstellen.

Smart Contract erstellen

Nachdem Sie Oracle Blockchain App Builder konfiguriert haben, können Sie die Spezifikationsdatei erstellen. Die Spezifikationsdatei kann als einfache YAML-Datei erstellt werden, die im folgenden Code dargestellt wird.

Hinweis:

Sie können diese Datei auch von GitHub herunterladen: YAML-Datei herunterladen.
#
# Token asset to manage the complete lifecycle of a non-fungible token representing a folder to hold docuements. 
# This specification file will generate an Smartcontract project with a non-fungible token for the folders to be maintained by the users.
#
assets:
    - name: folderNFT
      type: token
      symbol: eDocs
      standard: erc721+
      anatomy: 
        type: nonfungible
        unit: whole
      behavior:
        - indivisible
        - singleton
        - mintable:
        - transferable
        - burnable
        - roles:
            minter_role_name: minter
      properties:
          - name: folderHASH
            type: string
          - name: documents
            type: document[]
      metadata:
          - name: folderID
            type: string
            mandatory: true
            id: true
          - name: folderType
            type: string
            mandatory: true
      methods:
        crud: [create, getById, update, delete]
        others: [getHistoryById, getByRange]
    - name: document
      properties:
        - name: docName
          type: string
          mandatory: true
          id: true
        - name: docURL
          type: string
          mandatory: true
        - name: docHASH
          type: string
          mandatory: true
        - name: docType
          type: string
          mandatory: true
        - name: docProperties
          type: docProperty[]
      methods:
        crud: [create, getById, update, delete]
        others: [getHistoryById, getByRange]
    - name: docProperty
      type: embedded
      properties:
          - name: propName
            type: string
            mandatory: true
          - name: propValue
            type: string
            mandatory: true
      methods:
        crud: [create, getById, update, delete]
        others: [getHistoryById, getByRange]
customMethods:
    - executeQuery
    - "attachDocument(tokenId: string, docName: string, docURL: string, docHASH: string, docType: string, docProps: string[], docVals: string[])" # Attach a document to an existing folder. 
    - "retrieveDocuments(tokenId: string)" # Retrieve Documents of an folder. 
    - "transferFolder(tokenId: string, fromOrgId: string, fromUserId: string, toOrgId: string, toUserId: string)" # Transfer the folder among participants. 
    - "updateFolderHASH(tokenId: string, newHash: string)" # Update HASH folder 
    - "getFolderHASH(tokenId: string)" # Check HASH folder 

In dieser Spezifikationsdatei werden in der ersten definierten Entity (folderNFT) alle Abschnitte und Attribute für die Darstellung eines NFT-Tokens angezeigt. Übersicht über die in der Datei definierten Abschnitte:

  • Vermögensgegenstände: Ort, an dem die verschiedenen Vermögensgegenstände (Standardentitäten, Finanztransaktionen, NFTs) definiert sind. Innerhalb jedes der Assets können wir verschiedene Abschnitte unterscheiden, die je nach Art des dargestellten Assets variieren können. Für NFTs und FTs sind dies die verschiedenen Unterabschnitte:
    • Typ/Symbol/Standard: Geben Sie an, dass dieses Token auf dem ERC-721-Standard basiert, und geben Sie ihm einen eindeutigen Symbolbezeichner.
    • Anatomie: Geben Sie an, ob es sich um eine NFT handelt und ob sie in kleinere Brüche unterteilt ist (heute ist "ganz" die einzige Option für NFT-Token).
    • Verhalten: Definiert, ob das Token geprägt werden kann, und in diesem Fall, wie viele Münztoken maximal zulässig sind. Hier müssen Sie auch angeben, dass es sich um ein unteilbares Token handelt, wenn es Singleton für jede Klasse ist, übertragbar und brennbar, das seiner Löschung ähnlich ist (aber nicht verschwindet, also ist es immer noch da, aber überhaupt nicht verwendbar). Außerdem können Sie in diesem Abschnitt das Tokenverhalten auf bestimmte Rollen beschränken.
    • Metadaten: Definiert eine Art von Eigenschaften, die bei der Tokenerstellung festgelegt werden müssen und in Zukunft nicht mehr geändert werden können. So wird sein Wert für das ganze Leben des Tokens unveränderlich bleiben.
    • Eigenschaften: Definiert Standardattribute des Tokens, die während der Lebensdauer des Tokens variieren können, wie das Array der Dokumente, aus denen der Ordner besteht.
  • customMethods: Speicherort, an dem die Liste der benutzerdefinierten Methoden definiert werden muss. Bei diesen Methoden generiert Oracle Blockchain App Builder nur die Signatur der Methode, ohne dass sie implementiert wird. Die Implementierung dieser Methoden ist der einzige Code, der vom Entwickler implementiert werden kann.

Die folgenden Links beschreiben, wie Sie jede Art von Entity (NFT-, FT- oder Standard-Entitys) basierend auf Ihren Geschäftsanforderungen konfigurieren:

Nachdem die Spezifikationsdatei erstellt wurde, können wir Oracle Blockchain App Builder auffordern, das Gerüst des Projekts zu erstellen, indem wir die folgenden nächsten Schritte ausführen.

  1. Wenn die Spezifikationsdatei außerhalb von Oracle Blockchain App Builder erstellt wurde, müssen Sie die Spezifikationsdatei in Oracle Blockchain App Builder importieren. Klicken Sie auf die Auslassungspunkte neben dem SPECIFICATIONS-Frame, und klicken Sie im Popup-Fenster auf Spezifikation importieren.
  2. Wählen Sie die Spezifikationsdatei aus, und klicken Sie auf Spezifikation importieren.
  3. Um ein neues Chaincode-Projekt basierend auf der importierten Spezifikationsdatei erstellen zu können, klicken Sie auf das Symbol + in der oberen rechten Ecke des CHAINCODES-Frame. Der Assistent Chaincode erstellen wird geöffnet.
  4. Im Assistenten Chaincode erstellen müssen Sie die folgenden Details angeben:
    • Name: Name für das Projekt.
    • Sprache: Sprache zum Erstellen des Gerüsts des Projekts. Sie können nur zwischen Typescript und GoLang wählen. Da wir Typescript in diesem Lösungs-Playbook für die Implementierung der benutzerdefinierten Methoden verwenden, empfehlen wir die Auswahl von Typescript.
    • Spezifikation: Wählen Sie die Spezifikationsdatei aus, die Sie gerade in den vorherigen Schritten erstellt haben.
    • Speicherort/Domain: Je nach ausgewählter Sprache werden Sie aufgefordert, den Speicherort für das Projekt für die Typescript-Sprache oder die Domain für die Sprache GoLang zu definieren.
    Wenn alle Details korrekt sind, sollte im Assistenten eine grüne Meldung angezeigt werden. Ist dies nicht der Fall, überprüfen Sie die bei der Erstellung des Gerüsts des Projekts erzeugte Ausgabe.
  5. Im Abschnitt CHAINCODES sollte das neu generierte Projekt angezeigt werden. Wenn Sie auf das Projekt klicken, navigieren Sie zum Ordner src im Projekt, in dem der Quellcode generiert wurde:
    • Im Ordner src/controller wird die Hauptklasse für unseren Smart Contract mit allen automatisch generierten Methoden zur Verwaltung unserer Entitäten angezeigt.
    • Im Ordner src/model wird die Klasse angezeigt, die für die NFT-Entity steht.
  6. Navigieren Sie zum Ordner src/controller, und wählen Sie die Controllerklasse aus. Der von Oracle Blockchain App Builder automatisch generierte Code wird angezeigt. Am Ende der Datei werden alle Signaturen der benutzerdefinierten Methoden ohne Implementierung angezeigt.
  7. An dieser Stelle sollten wir die Implementierung der benutzerdefinierten Methoden erstellen. Der Einfachheit halber haben wir alle Implementierungscodes für solche Methoden in der Datei CMS_customMethods.ts bereitgestellt, die in GitHub verfügbar ist. Sie müssen nur die von Oracle Blockchain App Builder automatisch generierten Signaturen durch den Inhalt in der referenzierten Datei ersetzen.
Die Controller-Klasse, Zeilen vor den benutzerdefinierten Methoden, enthält den gesamten automatisch generierten Code zur Verwaltung des Lebenszyklus der NFT-Token. Das folgende Bild zeigt die verschiedenen Bereiche, die von solchen Methoden abgedeckt werden.

oracle-blockchain-nft-token-oracle.zip

Jetzt kann der Chaincode verwendet werden. Daher können wir den Chaincode lokal bereitstellen und testen, indem wir die Anweisungen unter Test Your Chaincode on a Local Hyperledger Fabric Network befolgen.

Smart Contract bereitstellen

Nachdem wir den Chaincode lokal getestet haben, stellen Sie ihn in dem realen Netzwerk bereit, das zuvor mit der Oracle Blockchain Service Console erstellt wurde. Gehen Sie dazu wie folgt vor:

  • Verpackung des Chaincode-Projekts.
  • Chaincode-Package in der Einzelinstanz (Gründer) installieren und bereitstellen
Im folgenden Abschnitt werden die detaillierten Schritte zur Ausführung des Deployments beschrieben.
  1. Erstellen Sie das bereitstellbare Package aus dem Chaincode-Projekt. Klicken Sie in Visual Studio auf die rechte Schaltfläche über dem Chaincode-Projektnamen, wählen Sie im Popup-Menü die Option Package aus, und wählen Sie das Verzeichnis aus, in dem die Chaincode-Packagedatei gespeichert werden soll.
  2. Rufen Sie die Oracle Blockchain Service Console auf, um das Chaincode-Package in der Gründerinstanz zu installieren und bereitzustellen.
  3. Navigieren Sie zur Registerkarte Chaincode, und klicken Sie auf Neuen Chaincode bereitstellen.
  4. Wählen Sie die Option Erweitertes Deployment aus.
  5. Legen Sie alle Werte fest, um das Chaincode-Package in der Gründerinstanz zu installieren, und klicken Sie auf Weiter.
    • Packagelabel: Geben Sie einen Namen an, mit dem Sie ermitteln können, welches Package in den verschiedenen vorhandenen Kanälen installiert ist. Da mehrere Versionen desselben Smart Contracts in verschiedenen Kanälen bereitgestellt werden können, empfiehlt es sich, einen Paketlabelnamen festzulegen, wie:
      <smartContractName>_<channel>_<version>
      
    • Chaincode-Sprache: Wählen Sie eine der verschiedenen Sprachen aus, je nachdem, in welcher Sprache Sie den Chaincode entwickelt haben.
    • Ziel-Peers: Wählen Sie die Peers aus, in denen Sie das Chaincode-Package installieren möchten.
    • Is Packaged Chaincode: Lassen Sie dieses Kontrollkästchen deaktiviert, wenn Sie eine ZIP-Datei hochladen. Aktivieren Sie das Kontrollkästchen für tar.gz-Dateien.
    • Chaincodequelle: Klicken Sie auf Chaincode-Datei hochladen, und wählen Sie die Chaincode-ZIP-Datei aus.
  6. Wenn die Installation erfolgreich verläuft, wird die Erfolgsmeldung angezeigt. Der nächste Schritt ist das Deployment des Chaincodes im ausgewählten Kanal. Sie müssen also alle Werte für die Deployment-Phase festlegen und auf Weiter klicken.
    • Kanal: Wählen Sie den Kanal aus, in dem Sie den Smart Contract bereitstellen möchten.
    • Chaincode-Name: Legen Sie den Namen fest, mit dem der Smart Contract im Kanal bereitgestellt wird.
    • Version: Weisen Sie diesem Deployment eine Nummer zu, die an dem zuvor installierten Package ausgerichtet ist. Auf diese Weise können Sie Pakete korrelieren, die mit Chaincodes installiert sind, die in verschiedenen Kanälen bereitgestellt werden.
    • Erforderlich: Aktivieren Sie dieses Kontrollkästchen, wenn die Methode init des Chaincodes aufgerufen werden muss, bevor Benutzertransaktionen zugelassen werden können.
    • Bestätigungs-Policy: Geben Sie während des Deployments Bestätigungs-Policys an. In diesem Lösungs-Playbook-Beispiel verwenden wir keine Bestätigungsrichtlinien.
    • Private Datenerfassung: Legen Sie bei Bedarf private Datenerfassung fest. In diesem Lösungsbeispiel werden wir die private Datenerfassung nicht einstellen.
Wenn das Deployment erfolgreich verläuft, sollten Sie nach dem Schließen der Installation und des Deployments sehen, wie das Package in den beiden Peers der Instanz installiert und auch in einem der Kanäle instanziiert wurde.

Smart Contract initialisieren

Wenn Sie sich mit FTs und NFT-Token befassen, müssen Sie eine Reihe administrativer Aktionen ausführen, bevor Sie Ihre Geschäftsmethoden ausführen können. Mit Oracle Blockchain können alle administrativen Aufgaben als einfache REST-Aufrufe ausgeführt werden. Dadurch wird der Aufwand für die Initialisierung des Smart Contracts erheblich reduziert.

Hinweis:

Bevor Sie einen der folgenden Schritte ausführen, müssen Sie die enrollmentIDs in den REST-Proxys für die Benutzer erstellen, denen Zugriff auf die Smart Contract-Methoden erteilt wurde. Die Registrierung ist eine Zuordnung zwischen dem Benutzernamen, der die REST-API aufruft, und den Accounts, die intern von der Blockchain verwaltet werden, denen Token zugewiesen werden, wie im Thema Anmeldungen in den REST-Proxyknoten erstellen beschrieben.

Verwenden Sie die folgende Postman-Sammlung, um den Smart Contract einfach zu initialisieren: Postman-Sammlung herunterladen

Im Ordner AdminSteps dieser Postman-Collection müssen drei Anforderungsaufrufe für die Smart Contract-Initialisierung ausgeführt werden.

Die Postman-Sammlung kann verwendet werden, aber es gibt eine Reihe von Variablen, die an Ihre eigene Umgebung angepasst werden müssen (Passwörter, URLs usw.). Diese Variablen werden in der Registerkarte Variablen der Postman-Collection festgelegt. Die folgende Tabelle zeigt alle Variablen, die wir definiert haben und an Ihre Umgebung angepasst werden müssen.

Variablenname Variabler Wert
bc_founder_provider_url https://org1-w....
bc_timeout 60.000
bc_nft_founder_userid1 cmsleg001
bc_nft_founder_userid1_pwd Kennwort
bc_nft_founder_userid2 cmsfin001
bc_nft_founder_userid2_pwd Kennwort
bc_nft_founder_userid3 cmsrsk001
bc_nft_founder_userid4_pwd Kennwort
bc_channel_name Wedocms
bc_chaincode_name WEDOCMS

Suchen Sie den Endpunkt, in dem die REST-API über die Blockchain Service-Konsole zugänglich ist.

  1. Greifen Sie über die OCI-Konsole auf die Blockchain Service-Konsole zu.
  2. Gehen Sie zur Registerkarte Knoten. Es werden alle Knoten angezeigt, aus denen diese Instanz besteht. Im Restproxyknoten wird die Endpunkt-URL in der Spalte Route angezeigt.
    Beachten Sie, dass Anmeldungen auf Instanzebene und nicht auf Netzwerkebene erstellt werden. Daher ist die Registrierung für den Benutzer nur über die Restproxy-URL der Gründerinstanz verfügbar. Wenn also neue Instanzen dem Netzwerk beitreten, Wenn neue Benutzer Zugriff auf das Netzwerk haben, müssen diese Benutzer im richtigen Mandanten vorhanden sein, und die Anmeldungen für diese Benutzer sollten auch im Restproxy der entsprechenden Instanz erstellt werden.
Nachdem die Postman-Sammlung ordnungsgemäß konfiguriert wurde, können wir mit der Smart Contract-Initialisierung fortfahren. Die Initialisierung eines NFT Smart Contracts ist wesentlich einfacher als die Initialisierung eines FT Smart Contracts, wir müssen nur drei Schritte ausführen:
  1. Intelligente Vertragsinitialisierung (Admin-Benutzerkonten starten).
  2. Erstellung von Wallets für Benutzer, die Eigentümer der NFT-Token sein können.
  3. Untergeordnete Rolle für Benutzer zuweisen, die über diese Berechtigung verfügen sollten.
Die folgenden API-REST-Aufrufe entsprechen den Aufrufen im Ordner AdminSteps aus der angegebenen Postman-Collection.
  1. Initialisieren Sie den Chaincode (Step-0: Admin-Benutzerkonto initialisieren), der angibt, welche Benutzerkonten zur Ausführung administrativer Aufgaben berechtigt sind. Es ist wichtig, die Argumente der Methode init korrekt festzulegen: args: Scaped array of user_ids with their org_ids.
    
    {
        "chaincode": "{{bc_nft_chaincode_name}}",
        "args": [
            "init",
            "[{\"orgId\":\"org1\",\"userId\":\"cmsleg001\"},{\"orgId\":\"org1\",\"userId\":\"cmsfin001\"},{\"orgId\":\"org1\",\"userId\":\"cmsrsk001\"}]"
        ],
        "timeout": {{bc_timeout}},
        "isInit": true,
        "sync": true
    }
    
  2. Erstellen Sie Benutzeraccounts für alle Benutzer, die Verwahrer der NFT-Assets für die physischen Assets sein können. Sie können dazu die Postman-Anforderung Step-1: Create account ausführen. Für die Einzelheiten unseres Anwendungsfalls gibt es nur drei Benutzer, die sich auf dieselbe einzelne Organisation beziehen, die zum Netzwerk gehört. Dieser Aufruf muss so oft ausgeführt werden wie Benutzer, für die wir ein Konto erstellen möchten. In unserem Fall dreimal mit jeweils folgenden Parametern:
    • "createAccount", "org1", "cmsleg001", "nonfungible"
    • "createAccount", "org1", "cmsfin001", "nonfungible"
    • "createAccount", "org1", "cmsrsk001", "nonfungible"
    
    {
        "chaincode": "{{bc_nft_chaincode_name}}", //Smartcontract name
        "args": [
            "createAccount", "org1","cmsleg001","nonfungible" //Method, OrgID, UserID, fungible for FT / nonfungible for NFT
        ],
        "timeout": 60000,
        "sync": true
    }
    
  3. Legen Sie fest, welcher Benutzer Token mint darf. In diesem Fall bedeutet Token mint, einen neuen Ordner für eine neue Gruppe von Dokumenten zu erstellen. Sie können also entscheiden, welcher der drei vorhandenen Benutzer (cmsleg001, cmsfin001 oder cmsrsk001) diese Aktionen ausführen kann, und für diese Benutzer die Anforderung Schritt-2: AddRole aus der Postman-Collection ausführen.
    
    {
        "chaincode": "{{bc_nft_chaincode_name}}", //Smartcontract name
        "args": [
            "addRole", //Method name
            "minter","org1","cmsleg001" //Role, OrgId, UserID
            ],
        "timeout": 60000,
        "sync": true
    }