Creación y despliegue del contrato inteligente

Para crear el contrato inteligente, necesitamos definir las entidades que se van a almacenar y gestionar en Blockchain como se muestra en el modelo de entidad de la siguiente imagen.


Descripción de oracle-blockchain-cms-entity.png a continuación
Descripción de la ilustración oracle-blockchain-cms-entity.png

Todas estas entidades y sus relaciones, toda la lógica necesaria para gestionar e interactuar con las entidades y también para mantenerlas en el libro mayor de blockchain se define en el contrato inteligente.

La carpeta se representa como un token NFT, por lo que se desarrollará e inicializará como un NFT. Las otras entidades dependientes (Documentos y Propiedades), son entidades estándar y son entidades secundarias de la carpeta, por lo que se desarrollarán como entidades estándar sin necesidad de inicialización.

Una vez creado el contrato inteligente, lo instalaremos y desplegaremos en Blockchain Network que hemos creado.

Crear contrato inteligente

Una vez que haya configurado Oracle Blockchain App Builder, puede crear el archivo de especificación. El archivo de especificación se puede crear como un archivo YAML simple que se muestra en el siguiente código.

Note:

También puede descargar este archivo de GitHub: Descargar archivo 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 

En este archivo de especificación, en la primera entidad definida (folderNFT), puede ver todas las secciones y atributos para la representación de un token de NFT. Descripción general de las secciones definidas en el archivo:

  • Activos: lugar donde se definen los diferentes activos (entidades estándar, transacciones financieras, transacciones de financiación de valores). Dentro de cada uno de los activos podemos distinguir diferentes secciones que pueden variar dependiendo del tipo de activo representado. Para las transacciones financieras y las transacciones financieras, estas son las distintas subsecciones:
    • Tipo/Símbolo/Estándar: especifique que este token se basa en el estándar ERC-721 y proporcione un identificador de símbolo único.
    • Anatomía: especifique que es un NFT y si se subdivide en fracciones más pequeñas (hoy en día, "entero" es la única opción para tokens NFT).
    • Comportamiento: define si el token se puede extraer y, en ese caso, cuál es el número máximo de tokens mintables. Aquí también debe indicar que es un token indivisible, si es singleton para cada clase, transferible y quemable que es similar a su eliminación (pero no desaparece, por lo que todavía está allí pero no se puede usar en absoluto). También en esta sección puede restringir el comportamiento del token a roles específicos.
    • Metadatos: define un tipo de propiedades que se deben definir durante la creación del token y que no se pueden cambiar en el futuro. Por lo tanto, su valor permanecerá inmutable durante toda la vida del token.
    • Propiedades: define atributos estándar del token que pueden variar durante la vida útil del token, como la matriz de documentos que componen la carpeta.
  • customMethods: ubicación en la que se debe definir la lista de nuestros métodos personalizados. Para esos métodos, Oracle Blockchain App Builder solo generará la firma del método, sin ninguna implementación en ellos. La implementación de estos métodos es el único código que puede ser implementado por el desarrollador.

En los siguientes enlaces se describe cómo configurar cualquier tipo de entidad (NFT, FT o entidades estándar) en función de las necesidades de su negocio:

Una vez creado el archivo de especificación, podemos ordenar a Oracle Blockchain App Builder que cree el andamio del proyecto siguiendo estos siguientes pasos.

  1. Si el archivo de especificación se ha creado fuera de Oracle Blockchain App Builder, debe importar el archivo de especificación a Oracle Blockchain App Builder. Haga clic en los puntos suspensivos junto al marco ESPECIFICACIONES y, en la ventana emergente, haga clic en Importar especificación.
  2. Seleccione el archivo de especificación y haga clic en Importar especificación.
  3. Para poder crear un nuevo proyecto de código de cadena basado en el archivo de especificación importado, haga clic en el icono + en la esquina superior derecha del marco CHAINCODES. Se abrirá el asistente Crear código de cadenas.
  4. En el asistente Crear código de cadena, debe especificar los siguientes detalles:
    • Nombre: nombre del proyecto.
    • Idioma: idioma para crear el andamio del proyecto. Solo puede seleccionar entre Typescript y GoLang. Como estamos utilizando Typescript en este manual de soluciones para la implementación de los métodos personalizados, recomendamos seleccionar Typescript.
    • Especificación: seleccione el archivo de especificación que acabamos de crear en los pasos anteriores.
    • Ubicación/Dominio: según el idioma seleccionado, se le pedirá que defina la ubicación en la que se colocará el proyecto para el idioma Typescript o el dominio para el idioma GoLang.
    Si todos los detalles son correctos, deberíamos ver un mensaje verde en el asistente. Si no es así, compruebe la salida generada durante la creación del andamio del proyecto.
  5. En la sección CHAINCODES, deberíamos ver el nuevo proyecto generado. Al hacer clic en el proyecto, vaya a la carpeta src dentro del proyecto, donde se ha generado el código fuente:
    • Dentro de la carpeta src/controller, veremos la clase principal que representa nuestro contrato inteligente, con todos los métodos generados automáticamente para gestionar nuestras entidades.
    • Dentro de la carpeta src/model, veremos la clase que representa la entidad NFT.
  6. Vaya a la carpeta src/controller y seleccione la clase de controlador. Veremos todo el código generado automáticamente por Oracle Blockchain App Builder. Al final del archivo, veremos todas las firmas de los métodos personalizados sin ninguna implantación en ellos.
  7. En este punto, debemos crear la implantación de los métodos personalizados. Para simplificar, hemos proporcionado todo el código de implementación para dichos métodos en el archivo CMS_customMethods.ts disponible en GitHub. Solo tiene que sustituir las firmas generadas automáticamente por Oracle Blockchain App Builder por el contenido del archivo de referencia.
La clase de controlador, líneas antes de los métodos personalizados, incluye todo el código generado automáticamente para gestionar el ciclo de vida de los tokens NFT. La siguiente imagen muestra las diferentes áreas cubiertas por dichos métodos.

oracle-blockchain-nft-token-oracle.zip

En este punto, el código de cadena está listo para su uso, por lo que podemos desplegarlo y probarlo localmente siguiendo las instrucciones de Prueba del código de cadena en una red local de Hyperledger Fabric.

Despliegue del contrato inteligente

Una vez que hayamos probado localmente el código de cadenas, proceda a desplegarlo en la red real creada previamente mediante la consola de servicio de Oracle Blockchain mediante:

  • Empaquetado del proyecto de código de cadenas.
  • Instalación y despliegue del paquete de código de cadenas en una única instancia (fundador).
En la siguiente sección se describen los pasos detallados para ejecutar el despliegue.
  1. Cree el paquete desplegable a partir del proyecto de código de cadenas. En Visual Studio, haga clic en el botón derecho en la parte superior del nombre del proyecto de código de cadenas, en el menú emergente seleccione la opción Paquete y seleccione el directorio para guardar el archivo de paquete de código de cadenas.
  2. Acceda a la consola de Oracle Blockchain Service para instalar y desplegar el paquete de código de cadenas en la instancia del fundador.
  3. Vaya al separador Código de cadena y haga clic en Desplegar un nuevo código de cadena.
  4. Seleccione la opción Despliegue avanzado.
  5. Defina todos los valores para instalar el paquete de código de cadenas en la instancia del fundador y haga clic en Siguiente.
    • Etiqueta de paquete: asigne un nombre que le ayude a identificar qué paquete está instalado en los diferentes canales existentes. Como puede tener más de una versión del mismo contrato inteligente desplegada en diferentes canales, es una buena práctica definir un nombre de etiqueta de paquete como:
      <smartContractName>_<channel>_<version>
      
    • Idioma de código de cadena: seleccione entre los distintos idiomas según el idioma en el que haya desarrollado el código de cadena.
    • Peers de destino: seleccione los peers en los que desea instalar el paquete de código de cadenas.
    • Código de cadena empaquetado: deje esta casilla de control sin seleccionar si está cargando un archivo zip. Seleccione la casilla de control para los archivos tar.gz.
    • Origen de código de cadena: haga clic en Cargar archivo de código de cadena y seleccione el archivo zip de código de cadena.
  6. Si la instalación se realiza correctamente, veremos el mensaje de que se ha realizado correctamente. El siguiente paso es el despliegue del código de cadenas en el canal seleccionado, por lo que debe definir todos los valores relacionados con la fase de despliegue y hacer clic en Siguiente.
    • Canal: seleccione el canal en el que desea desplegar el contrato inteligente.
    • Nombre de código de cadena: defina el nombre con el que se desplegará el contrato inteligente en el canal.
    • Versión: Asigne un número a este despliegue, que está alineado con el paquete instalado anteriormente. De esta forma, podrá correlacionar los paquetes instalados con los códigos de cadenas desplegados en diferentes canales.
    • Inicio necesario: seleccione esta casilla de control si se debe llamar al método init del código de cadena antes de permitir transacciones de usuario.
    • Política de endoso: especifique políticas de endoso durante el despliegue. En este ejemplo de manual de soluciones, no estamos utilizando políticas de endoso.
    • Recopilación de datos privada: defina recopilaciones de datos privadas si es necesario. En este ejemplo de manual de soluciones, no estableceremos la recopilación de datos privada.
Si el despliegue se realiza correctamente, después de cerrar la instalación y el despliegue, debe ver cómo se ha instalado el paquete en los dos pares de la instancia y también se ha instanciado en uno de los canales.

Inicialización del contrato inteligente

Cuando se trata de transacciones financieras y tokens NFT, hay un juego de acciones administrativas que se deben ejecutar antes de poder ejecutar los métodos de negocio. Con Oracle Blockchain, todas las tareas administrativas se pueden ejecutar como llamadas REST simples y reduce considerablemente el esfuerzo necesario para inicializar el contrato inteligente.

Note:

Antes de ejecutar cualquiera de los siguientes pasos, debemos crear enrollmentIDs en los proxies de REST para los usuarios a los que se les ha otorgado acceso a los métodos de contrato inteligente. La inscripción es una asignación entre el nombre de usuario que llama a la API de REST y las cuentas gestionadas internamente por blockchain a las que se asignarán tokens como se describe en el tema Creación de inscripciones en los nodos de proxy de REST.

Utilice la siguiente recopilación de Postman para inicializar fácilmente el contrato inteligente: Descargar recopilación de Postman

En la carpeta AdminSteps de esta recopilación de Postman, hay tres llamadas de solicitud que se deben ejecutar para la inicialización del contrato inteligente.

La colección Postman está lista para su uso, pero hay un conjunto de variables que se deben configurar adecuadamente para su propio entorno (contraseñas, URL, etc.). Estas variables se definen en el separador Variables de la recopilación Postman. La siguiente tabla muestra todas las variables que hemos definido y que deben adaptarse a su entorno.

Nombre de variable Valor de Variable
bc_founder_provider_url https://org1-w....
bc_timeout 60.000
bc_nft_founder_userid1 cmsleg001
bc_nft_founder_userid1_pwd contraseña
bc_nft_founder_userid2 cmsfin001
bc_nft_founder_userid2_pwd contraseña
bc_nft_founder_userid3 cmsrsk001
bc_nft_founder_userid4_pwd contraseña
bc_channel_name cuñas
bc_chaincode_name CUERO

Busque el punto final en el que se puede acceder a la API de REST desde la consola de servicio de blockchain.

  1. Acceda a la consola del servicio Blockchain a través de la consola de OCI.
  2. Vaya al separador Nodos. Se mostrarán todos los nodos que componen esta instancia y, en el nodo restproxy, verá la URL de punto final en la columna Ruta.
    Recuerde que las inscripciones se crean a nivel de instancia, no a nivel de red, por lo que la inscripción del usuario solo estará disponible a través de la URL de restproxy de la instancia de fundador, por lo que, si las nuevas instancias se unen a la red, con nuevos usuarios autorizados para acceder a la red, esos usuarios deberán existir en el arrendamiento adecuado y las inscripciones para esos usuarios también se deben crear en el resto del proxy de la instancia correspondiente.
Una vez que la colección Postman se haya configurado correctamente, podemos continuar con la inicialización del contrato inteligente. La inicialización de un contrato inteligente NFT es considerablemente más simple que la inicialización de un contrato inteligente FT, solo necesitamos ejecutar tres pasos:
  1. Inicialización de contrato inteligente (Cuentas de usuario de administración de inicialización).
  2. Creación de carteras para usuarios que pueden ser propietarios de los tokens NFT.
  3. Asigne un rol mínimo a los usuarios que deban tener ese privilegio.
Las siguientes llamadas REST de API corresponden a las llamadas a la carpeta AdminSteps de la recopilación Postman proporcionada.
  1. Inicialice el código de cadenas (Paso 0: Iniciar cuenta de usuario de administrador) que indica qué cuentas de usuario podrán ejecutar tareas administrativas. Es importante definir los argumentos del método init correctamente: 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. Cree cuentas de usuario para todos los usuarios que puedan ser responsables de los activos NFT que representan los activos físicos. Se puede realizar ejecutando la solicitud Postman Paso 1: Crear cuenta. Para los detalles de nuestro caso de uso, solo hay tres usuarios relacionados con la misma organización que pertenece a la red. Esta llamada se debe ejecutar tantas veces como usuarios para los que queremos crear una cuenta. En nuestro caso tres veces, cada uno con los siguientes parámetros:
    • "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. Defina qué usuario puede importar tokens, en este caso mint a token significa crear una nueva carpeta para contener un nuevo juego de documentos, de modo que pueda decidir cuál de los tres usuarios existentes (cmsleg001, cmsfin001 o cmsrsk001) puede ejecutar estas acciones y, para esos usuarios, ejecutar la solicitud Step-2: AddRole desde la recopilación Postman.
    
    {
        "chaincode": "{{bc_nft_chaincode_name}}", //Smartcontract name
        "args": [
            "addRole", //Method name
            "minter","org1","cmsleg001" //Role, OrgId, UserID
            ],
        "timeout": 60000,
        "sync": true
    }