Créer et déployer un contrat intelligent

Pour créer le contrat intelligent, nous devons définir les entités à stocker et à gérer dans Blockchain, comme indiqué dans le modèle d'entité de l'image suivante.


Voici la description d'oracle-blockchain-cms-entity.png
Description de l'illustration oracle-blockchain-cms-entity.png

Toutes ces entités et leurs relations, toute la logique requise pour gérer et interagir avec les entités, ainsi que pour les rendre persistantes dans le registre de chaîne de blocs, est définie dans le contrat intelligent.

Le dossier est représenté en tant que jeton NFT, il sera donc développé et initialisé en tant que NFT. Les autres entités dépendantes (Documents et Propriétés) sont des entités standard et sont des entités enfant du dossier. Elles seront donc développées en tant qu'entités standard sans nécessiter d'initialisation.

Une fois le contrat intelligent créé, nous l'installerons et le déployerons dans le réseau Blockchain que nous avons créé.

Créer le contrat intelligent

Une fois que vous avez configuré Oracle Blockchain App Builder, vous pouvez créer le fichier de spécification. Le fichier de spécification peut être créé sous la forme d'un fichier YAML simple affiché dans le code suivant.

Remarques :

Vous pouvez également télécharger ce fichier à partir de GitHub : Télécharger le fichier YAML.
#
# 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 

Dans ce fichier de spécification, dans la première entité définie (folderNFT), vous pouvez voir toutes les sections et tous les attributs pour la représentation d'un jeton NFT. Présentation des sections définies dans le fichier :

  • Immobilisations : Emplacement où les différentes immobilisations (entités standard, TF, NFT) sont définies. À l'intérieur de chacun des actifs, nous pouvons distinguer différentes sections qui peuvent varier en fonction du type d'actif représenté. Pour les NFT et les TF, voici les différentes sous-sections :
    • Type/Symbole/Standard : indiquez que ce jeton est basé sur la norme ERC-721 et donnez-lui un identificateur de symbole unique.
    • Anatomie : indiquez s'il s'agit d'un NFT et s'il est subdivisé en fractions plus petites (aujourd'hui, "whole" est la seule option pour les jetons NFT).
    • Comportement : définit si le jeton peut être extrait et, dans ce cas, quel est le nombre maximal de jetons mini-table. Ici, vous devez également déclarer que c'est un jeton indivisible, s'il est singleton pour chaque classe, transférable et brûlable qui est similaire à sa suppression (mais ne disparaissant pas, donc il est toujours là mais pas utilisable du tout). Cette section permet également de limiter le comportement des jetons à des rôles spécifiques.
    • Métadonnées : définit un type de propriété qui doit être défini lors de la création du jeton et ne peut pas être modifié ultérieurement. Sa valeur restera donc immuable pendant toute la durée de vie du jeton.
    • Propriétés : définit les attributs standard du jeton qui peuvent varier pendant la durée de vie du jeton, comme le tableau de documents qui composent le dossier.
  • customMethods : emplacement où la liste de nos méthodes personnalisées doit être définie. Pour ces méthodes, Oracle Blockchain App Builder générera uniquement la signature de la méthode, sans aucune implémentation. L'implémentation de ces méthodes est le seul code qui peut être implémenté par le développeur.

Les liens suivants expliquent comment configurer tout type d'entité (NFT, TF ou entités standard) en fonction des besoins de votre entreprise :

Une fois le fichier de spécification créé, nous pouvons demander à Oracle Blockchain App Builder de créer l'échafaudage du projet en suivant les étapes suivantes.

  1. Si le fichier de spécification a été créé en dehors d'Oracle Blockchain App Builder, vous devez importer le fichier de spécification dans Oracle Blockchain App Builder. Cliquez sur les points de suspension en regard du cadre SPECIFICATIONS et, dans la fenêtre contextuelle, cliquez sur Importer la spécification.
  2. Sélectionnez le fichier de spécification et cliquez sur Importer la spécification.
  3. Pour créer un projet de code chaîne basé sur le fichier de spécification importé, cliquez sur l'icône + dans l'angle supérieur droit du cadre CHAINCODES. Elle ouvrira l'assistant Créer un code chaîne.
  4. Dans l'assistant Créer un code chaîne, vous devez indiquer les détails suivants :
    • Nom : nom du projet.
    • Langue : langue de création de l'échafaudage du projet. Vous pouvez uniquement sélectionner entre Typescript et GoLang. Comme nous utilisons Typescript dans ce guide de la solution pour l'implémentation des méthodes personnalisées, nous vous recommandons de sélectionner Typescript.
    • Spécification : sélectionnez le fichier de spécification que nous venons de créer dans les étapes précédentes.
    • Emplacement/Domaine : selon la langue sélectionnée, vous serez invité à définir l'emplacement où le projet sera placé pour la langue Typescript ou le domaine pour la langue GoLang.
    Si tous les détails sont corrects, nous devrions voir un message vert dans l'assistant. Si ce n'est pas le cas, vérifiez la sortie générée lors de la création de l'échafaudage du projet.
  5. Dans la section CHAINCODES, nous devons voir le nouveau projet généré. Cliquez sur le projet, accédez au dossier src dans le projet, où le code source a été généré :
    • Dans le dossier src/controller, la classe main représente notre contrat intelligent, avec toutes les méthodes générées automatiquement pour gérer nos entités.
    • Dans le dossier src/model, la classe représentant l'entité NFT apparaît.
  6. Accédez au dossier src/controller et sélectionnez la classe de contrôleur. Tout le code généré automatiquement par Oracle Blockchain App Builder apparaît. A la fin du fichier, toutes les signatures des méthodes personnalisées sont affichées, sans aucune implémentation.
  7. A ce stade, nous devons créer l'implémentation des méthodes personnalisées. Pour plus de simplicité, nous avons fourni tout le code d'implémentation de ces méthodes dans le fichier CMS_customMethods.ts disponible dans GitHub. Il vous suffit de remplacer les signatures générées automatiquement par Oracle Blockchain App Builder par le contenu du fichier référencé.
La classe Controller, lignes avant les méthodes personnalisées, inclut tout le code généré automatiquement pour gérer le cycle de vie des jetons NFT. L'image suivante illustre les différentes zones couvertes par ces méthodes.

oracle-blockchain-nft-jeton-oracle.zip

A ce stade, le code chaîne est prêt à être utilisé. Nous pouvons donc déployer et tester le code chaîne localement en suivant les instructions de test du code chaîne sur un réseau Hyperledger Fabric local.

Déployer le contrat intelligent

Une fois le code chaîne testé localement, déployez-le sur le réseau réel créé précédemment à l'aide de la console de service Oracle Blockchain en procédant comme suit :

  • Empaquetage du projet de code chaîne.
  • Installation et déploiement du package de code chaîne dans l'instance unique (instance fondatrice).
La section suivante décrit les étapes détaillées d'exécution du déploiement.
  1. Créez le package déployable à partir du projet de code chaîne. Dans Visual Studio, cliquez sur le bouton droit en haut du nom du projet de code chaîne, sélectionnez l'option Package dans le menu contextuel et sélectionnez le répertoire dans lequel enregistrer le fichier de package de code chaîne.
  2. Accédez à la console de service Oracle Blockchain pour installer et déployer le package de code chaîne dans l'instance fondatrice.
  3. Accédez à l'onglet Code chaîne et cliquez sur Déployer un nouveau code chaîne.
  4. Sélectionnez l'option Déploiement avancé.
  5. Définissez toutes les valeurs pour installer le package de code chaîne dans l'instance fondatrice, puis cliquez sur Suivant.
    • Etiquette de package : attribuez un nom qui peut vous aider à identifier le package installé dans les différents canaux existants. Etant donné que plusieurs versions du même contrat intelligent peuvent être déployées sur différents canaux, il est recommandé de définir un nom de libellé de package comme suit :
      <smartContractName>_<channel>_<version>
      
    • Langue de code chaîne : sélectionnez l'une des différentes langues en fonction de la langue dans laquelle vous avez développé le code chaîne.
    • Pairs cible : sélectionnez les pairs dans lesquels installer le package de code chaîne.
    • Est un code chaîne packagé : ne cochez pas cette case si vous téléchargez un fichier ZIP. Cochez la case pour les fichiers tar.gz.
    • Source de code chaîne : cliquez sur Télécharger le fichier de code chaîne et sélectionnez le fichier ZIP de code chaîne.
  6. Si l'installation réussit, le message de réussite s'affiche. L'étape suivante consiste à déployer le code chaîne dans le canal sélectionné. Vous devez donc définir toutes les valeurs associées à la phase de déploiement, puis cliquer sur Suivant.
    • Canal : sélectionnez le canal dans lequel déployer le contrat intelligent.
    • Nom de code chaîne : définissez le nom avec lequel le contrat intelligent sera déployé sur le canal.
    • Version : affectez un numéro à ce déploiement, qui est aligné sur le package installé précédemment. Vous pourrez ainsi corréler les packages installés avec les codes chaîne déployés sur différents canaux.
    • Init requis : cochez cette case si la méthode init du code chaîne doit être appelée avant d'autoriser les transactions utilisateur.
    • Stratégie d'approbation : indiquez les stratégies d'approbation lors du déploiement. Dans cet exemple de guide stratégique de solution, nous n'utilisons pas de stratégies d'approbation.
    • Collecte de données privées : définissez des collections de données privées si nécessaire. Dans cet exemple de livre de jeux de solution, nous ne définirons pas la collecte de données privée.
Si le déploiement réussit, après avoir fermé l'installation et le déploiement, vous devez voir comment le package a été installé dans les deux homologues de l'instance et instancié dans l'un des canaux.

Initialiser le contrat intelligent

Lorsque vous traitez des TF et des jetons NFT, il existe un ensemble d'actions d'administration à exécuter avant de pouvoir exécuter vos méthodes métier. Avec Oracle Blockchain, toutes les tâches administratives peuvent être exécutées sous forme d'appels REST simples et cela réduit considérablement les efforts nécessaires à l'initialisation du contrat intelligent.

Remarques :

Avant d'exécuter l'une des étapes suivantes, nous devons créer enrollmentIDs dans les proxies REST pour les utilisateurs disposant d'un accès aux méthodes de contrat intelligent. L'inscription est une correspondance entre le nom utilisateur qui appelle l'API REST et les comptes gérés en interne par la chaîne de blocs auxquels des jetons seront affectés, comme décrit dans la rubrique Créer des inscriptions aux noeuds de proxy REST.

Utilisez la collection Postman suivante pour initialiser facilement le contrat intelligent : Télécharger la collection Postman

Dans le dossier AdminSteps de cette collection Postman, trois appels de demande doivent être exécutés pour l'initialisation du contrat intelligent.

La collection Postman est prête à être utilisée, mais il existe un ensemble de variables qui doivent être configurées en fonction de votre propre environnement (mots de passe, URL, etc.). Ces variables sont définies dans l'onglet Variables de la collection Postman. Le tableau suivant présente toutes les variables que nous avons définies et qui doivent être adaptées à votre environnement.

Nom de variable Valeur de variable
bc_founder_provider_url https://org1-w....
bc_timeout 60 000
bc_nft_founder_userid1 cmsleg001
bc_nft_founder_userid1_pwd mot de passe
bc_nft_founder_userid2 cmsfin001
bc_nft_founder_userid2_pwd mot de passe
bc_nft_founder_userid3 cmsrsk001
bc_nft_founder_userid4_pwd mot de passe
bc_channel_name Mariages
bc_chaincode_name MARIAGES

Recherchez l'adresse dans laquelle l'API REST est accessible à partir de la console de service Blockchain.

  1. Accédez à la console du service Blockchain via la console OCI.
  2. Accédez à l'onglet Noeuds. Elle affiche tous les noeuds qui composent cette instance. Dans le noeud restproxy, l'URL endpoint apparaît dans la colonne Route.
    N'oubliez pas que les inscriptions sont créées au niveau de l'instance et non au niveau du réseau, de sorte que l'inscription de l'utilisateur ne sera disponible que via l'URL restproxy de l'instance fondatrice. Par conséquent, si de nouvelles instances rejoignent le réseau, avec les nouveaux utilisateurs autorisés à accéder au réseau, ces utilisateurs devront exister dans la location appropriée et les inscriptions pour ces utilisateurs doivent également être créées dans le restproxy de l'instance correspondante.
Une fois la collection Postman correctement configurée, nous pouvons procéder à l'initialisation du contrat intelligent. L'initialisation d'un contrat intelligent NFT est considérablement plus simple que l'initialisation d'un contrat intelligent FT, il suffit d'exécuter trois étapes :
  1. Initialisation du contrat intelligent (Init Admin User Accounts).
  2. Création de portefeuilles pour les utilisateurs qui peuvent posséder les jetons NFT.
  3. Affectez le rôle minter aux utilisateurs qui doivent disposer de ce privilège.
Les appels REST d'API suivants correspondent aux appels dans le dossier AdminSteps de la collection Postman fournie.
  1. Initialisez le code chaîne (Step-0 : Init Admin User Account) en indiquant les comptes utilisateur autorisés à exécuter des tâches d'administration. Il est important de définir correctement les arguments de la méthode init : 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. Créez des comptes utilisateur pour tous les utilisateurs qui peuvent être dépositaires des immobilisations NFT représentant les immobilisations physiques. Pour ce faire, exécutez la demande Postman Step-1 : Create account. Pour les spécificités de notre cas d'utilisation, il n'y a que trois utilisateurs liés à la même organisation unique appartenant au réseau. Cet appel doit être exécuté autant de fois que les utilisateurs pour lesquels nous voulons créer un compte. Dans notre cas trois fois, chacun avec les paramètres suivants :
    • "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. Définissez l'utilisateur autorisé à utiliser les jetons, dans ce cas mint a token signifie créer un dossier pour contenir un nouvel ensemble de documents. Vous pouvez donc décider lequel des trois utilisateurs existants (cmsleg001, cmsfin001 ou cmsrsk001) peut exécuter ces actions et, pour ces utilisateurs, exécutez la demande Step-2 : AddRole de la collection Postman.
    
    {
        "chaincode": "{{bc_nft_chaincode_name}}", //Smartcontract name
        "args": [
            "addRole", //Method name
            "minter","org1","cmsleg001" //Role, OrgId, UserID
            ],
        "timeout": 60000,
        "sync": true
    }