From 84ffed6e30857e361dae404cb3af264167442c95 Mon Sep 17 00:00:00 2001 From: munapower Date: Thu, 16 Jan 2025 16:22:56 -0300 Subject: [PATCH] translated into spanish the Fabric Gateway section and minor corrections Signed-off-by: munapower --- full-stack-asset-transfer-guide/README.md | 12 +- .../ApplicationDev/01-FabricGateway-ES.md | 76 ++++++++++ .../docs/ApplicationDev/01-FabricGateway.md | 2 +- .../02-Exercise-RunApplication-ES.md | 43 ++++++ .../03-ApplicationOverview-ES.md | 132 ++++++++++++++++++ .../04-Exercise-AssetTransfer-ES.md | 31 ++++ .../04-Exercise-AssetTransfer.md | 8 +- .../ApplicationDev/05-ChaincodeEvents-ES.md | 20 +++ .../docs/ApplicationDev/05-ChaincodeEvents.md | 2 +- .../06-Exercise-ChaincodeEvents-ES.md | 46 ++++++ .../06-Exercise-ChaincodeEvents.md | 12 +- 11 files changed, 366 insertions(+), 18 deletions(-) create mode 100644 full-stack-asset-transfer-guide/docs/ApplicationDev/01-FabricGateway-ES.md create mode 100644 full-stack-asset-transfer-guide/docs/ApplicationDev/02-Exercise-RunApplication-ES.md create mode 100644 full-stack-asset-transfer-guide/docs/ApplicationDev/03-ApplicationOverview-ES.md create mode 100644 full-stack-asset-transfer-guide/docs/ApplicationDev/04-Exercise-AssetTransfer-ES.md create mode 100644 full-stack-asset-transfer-guide/docs/ApplicationDev/05-ChaincodeEvents-ES.md create mode 100644 full-stack-asset-transfer-guide/docs/ApplicationDev/06-Exercise-ChaincodeEvents-ES.md diff --git a/full-stack-asset-transfer-guide/README.md b/full-stack-asset-transfer-guide/README.md index 2d886005..f289730d 100644 --- a/full-stack-asset-transfer-guide/README.md +++ b/full-stack-asset-transfer-guide/README.md @@ -87,12 +87,12 @@ We'll create a digital representation of these cards on the blockchain ledger. T ## Client Application Development -- [Fabric Gateway](docs/ApplicationDev/01-FabricGateway.md) -- **Exercise:** [Run the client application](docs/ApplicationDev/02-Exercise-RunApplication.md) -- [Application overview](docs/ApplicationDev/03-ApplicationOverview.md) -- **Exercise:** [Implement asset transfer](docs/ApplicationDev/04-Exercise-AssetTransfer.md) -- [Chaincode events](docs/ApplicationDev/05-ChaincodeEvents.md) -- **Exercise:** [Use chaincode events](docs/ApplicationDev/06-Exercise-ChaincodeEvents.md) +- [Fabric Gateway](docs/ApplicationDev/01-FabricGateway.md) [Español](docs/ApplicationDev/01-FabricGateway-ES.md) +- **Exercise:** [Run the client application](docs/ApplicationDev/02-Exercise-RunApplication.md) [Español](docs/ApplicationDev/02-Exercise-RunApplication-ES.md) +- [Application overview](docs/ApplicationDev/03-ApplicationOverview.md) [Español](docs/ApplicationDev/03-ApplicationOverview-ES.md) +- **Exercise:** [Implement asset transfer](docs/ApplicationDev/04-Exercise-AssetTransfer.md) [Español](docs/ApplicationDev/04-Exercise-AssetTransfer-ES.md) +- [Chaincode events](docs/ApplicationDev/05-ChaincodeEvents.md) [Español](docs/ApplicationDev/05-ChaincodeEvents-ES.md) +- **Exercise:** [Use chaincode events](docs/ApplicationDev/06-Exercise-ChaincodeEvents.md) [Español](docs/ApplicationDev/06-Exercise-ChaincodeEvents-ES.md) ## Cloud Native Fabric diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/01-FabricGateway-ES.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/01-FabricGateway-ES.md new file mode 100644 index 00000000..394d75b5 --- /dev/null +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/01-FabricGateway-ES.md @@ -0,0 +1,76 @@ +# Fabric Gateway + +Desde Fabric v2.4, la [Fabric Gateway client API](https://hyperledger.github.io/fabric-gateway/) es la API recomendada para construir aplicaciones clientes. Existen implementaciones en Go, Node (TypeScript / JavaScript) y Java, cada uno provee identicas capacidades y comportamientos. La API cliente hace uso de un servicio de Fabric Gateway embebido en los peers de Fabric v2.4+. Este topico describe el modelo de Fabric Gateway y las consideraciones para su implementacion en entornos productivos. + +Los conceptos que aqui se describen se corresponden directamente a los métodos provistos por el API del cliente, y te ayudaran comprender el comportamiento del API del cliente. Si cuentas con un claro entendimiento del flujo de transacciones en Fabric, puedes considerar este tópico como material de referencia. + +## Background + +Para comprender como funciona Fabric Gateway, es necesario entender el flujo de las transacciones submit (y evaluate) de Fabric. Este sección provee una breve recapitulación del flujo de transacciones en Fabric desde la perspectiva de un cliente. + +### Flujo de transacción de submit + +Submit representa una actualización al ledger. En el siguiente diagrama, las lineas sólidas anaranjadas representan interacciones entre el cliente y los nodos de la red, mientras que las líneas entrecortadas verdes representan las interacciones entre los nodos de la red. + +![Flujo de transacción submit](../images/ApplicationDev/transaction-submit-flow.png) + +1. **Endosar:** el cliente envía la propuesta de la transacción a los peers para su endoso. + - El peer ejecuta la función de la transacción en el contrato inteligente contra el estado *actual* del ledger para producir un conjunto de lectura/escritura y un valor de retorno para la transacción. + - Los endosos exitosos deben ser reunidos de una cantidad suficiente de organizaciones para alcanzar los requerimientos de endoso, que puede requerir contemplar las politicas de endoso de chaincode y basada en estado, las invocaciones chaincode-to-chaincode, y las colecciones de datos privados accedidas por la función de la transacción; sino la transacción fallará la *validación* mas adelante. +2. **Submit:** el cliente envía la transacción endosada a un ordenador para que sea incluida en un bloque +3. Los Ordenadores distribuyen los bloques validados a todos los peers de la red, que validan las transacciones contra el estado *actual* de su ledger. + - Las transacciones válidas tienen sus conjuntos de lectura/escritura aplicados para actualizar el ledger. + - Las transacciones invalidas son marcadas con un código apropiado de validación y no actualizan el ledger. + - Un motivo común para un error de validación es MVCC_READ_CONFLICT, que significa que las llaves del ledger accedidas por la transacción fueron modificadas entre el endoso y la validación. Esto es recuperable ejecutando el flujo de Submit nuevamente. +4. **Commit:** el cliente obtiene el status de confirmación para las transacciones enviadas desde los peers e informa el éxito o fallo de las transacciones enviadas dependiendo del código de validación de la transacción. + +### Flujo de Evaluación de las Transacciones + +Evaluate representa una consulta o query y es esencialmente solo el paso de *endosar* del flujo de submit de una transacción. + +1. **Evaluate:** el cliente envía una propuesta de transacción a un peer idóneo para endoso y obtiene un valor de retorno. + - El valor de retorno esta basado en el estado *actual* del ledger del peer que hace el endoso. + - Las políticas de endoso no tienen que ser satisfechas ya que la transacción no esta siendo enviada para actualizar el ledger. + - El acceso a las colecciones de data privada debe ser considerado al seleccionar el peer. + +## Legacy client SDKs + +El siguiente diagrama demuestra como es ejecutada el flujo de envío de una transacción para un cliente que utiliza alguna de las SDK legacy. Las líneas sólidas de color naranja representan transacciones entre el cliente y los nodos de la red, que deben cruzar el firewall en el límite de la red desplegada. Las líneas verdes entrecortadas representan interacciones entre nodos de la red. + +Nota que el cliente potencialmente necesita interactuar directamente con alguno o todos los nodos de la red. + +![Modelo Legacy SDK](../images/ApplicationDev/legacy-sdk-model.png) + +Para que las aplicaciones cliente operen efectivamente, deben hacer uso del servicio de descubrimiento provisto por los peers de la red. Esto requiere interacciones de red adicionales, mas allá de las mostradas en el flujo de envío de transacciones, para: + +- Identificar nodos de la red disponibles. +- Obtener un plan de endoso basado en los requerimientos de endoso provistos por el cliente. + +## API cliente de Fabric Gateway + +El siguiente diagrama demuestra, para el flujo de envío de transacciones, como es ejecutado para un cliente utilizando el API cliente de Fabric Gateway. Las líneas sólidas naranjas representan intercciones entre el cliente y un peer de tipo Gateway, que debe cruzar el firewall en el límite de la red desplegada. Las líneas verdes entrecortadas representan interacciones entre nodos de la red. + +Ten en consideración que el cliente solo necesita interactuar directamente con el peer de tipo Gateway. El peer Gateway opera como un cliente dirigiendo el flujo de envío de transacción dentro de la red desplegada en nombre de la aplicación cliente. + +![Modelo con Fabric Gateway](../images/ApplicationDev/fabric-gateway-model.png) + + Como el Gateway es en si mismo un peer, tiene acceso directo a su ledger e información de descubrimiento de servicio. Esto le permite al cliente evitar usar el servicio de descubrimiento y transaccionar utilizando solamente una dirección de punto de entrada del Gateway. El peer Gateway generalmente puede determinar automáticamente un plan de endoso apropiado, evitando que el cliente necesite conocer los requisitos de endoso. + + Como referencia, se puede encontrar una descripción más detallada del servicio Fabric Gateway y su comportamiento en la [documentación de Fabric](https://hyperledger-fabric.readthedocs.io/en/release-2.4/gateway.html). + +## Despliegue en Producción de Fabric Gateway + +Por seguridad, las aplicaciones cliente deberían conectarse solamente a peers Gateway dentro de su propia organización o, si la organización cliente no aloja sus propios peers, a peers Gateway de una organización de confianza. + +El siguiente diagrama demuestra la práctica recomendada para habilitar el acceso a un clúster de una organización a través de una única dirección de punto de entrada, manteniendo alta disponibilidad. Este uso de un balanceador de carga o controlador de ingreso como proxy frente a un conjunto de puntos de entrada internos es usado comúnmente al desplegar servidores Web o de Aplicaciones, por lo que este patrón está bien establecido. La comunicación gRPC entre el cliente y el Gateway en realidad utiliza HTTP/2 como su transporte. + +![Despliegue de Fabric Gateway](../images/ApplicationDev/fabric-gateway-deployment.png) + +Un enfoque alternativo (o complementario) que se puede emplear es asignar múltiples registros a un único nombre DNS de Gateway. Esto permite que los clientes seleccionen de un conjunto de direcciones IP de peers Gateway asociadas con un único punto de entrada del Gateway. + +Es importante tener en cuenta que los peers deben incluir la dirección del punto de entrada visible externamente en sus certificados TLS para que los clientes puedan completar con éxito el handshake TLS. + +Como referencia, se puede encontrar más información en la documentación de gRPC: + +- [Balanceo de carga gRPC](https://grpc.io/blog/grpc-load-balancing/). +- [Resolución de nombres gRPC](https://grpc.github.io/grpc/core/md_doc_naming.html). diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/01-FabricGateway.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/01-FabricGateway.md index 8ad2273e..328b4938 100644 --- a/full-stack-asset-transfer-guide/docs/ApplicationDev/01-FabricGateway.md +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/01-FabricGateway.md @@ -48,7 +48,7 @@ In order for the client application to operate effectively, it must make use of ## Fabric Gateway client API -The following diagram demonstrates for the transaction subsmit flow is executed for a client using the Fabric Gateway client API. Solid orange lines represent interactions between the client and a Gateway peer, which must cross the firewall at the boundary of the network deployment. Dashed green lines represent interactions between network nodes. +The following diagram demonstrates for the transaction submit flow how it is executed for a client using the Fabric Gateway client API. Solid orange lines represent interactions between the client and a Gateway peer, which must cross the firewall at the boundary of the network deployment. Dashed green lines represent interactions between network nodes. Notice that the client only needs to interact directly with the Gateway peer. The Gateway peer operates as a client driving the transaction submit flow from within the network deployment on behalf of the client application. diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/02-Exercise-RunApplication-ES.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/02-Exercise-RunApplication-ES.md new file mode 100644 index 00000000..73196989 --- /dev/null +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/02-Exercise-RunApplication-ES.md @@ -0,0 +1,43 @@ +# Ejercicio: Ejecutar la aplicación cliente + +> **Nota:** Este ejercicio requiere que la red de Fabric y el chaincode desplegado en los ejercicios de [Desarrollo de Contratos Inteligentes](../SmartContractDev/) estén en funcionamiento. + +Asegurémonos de que podemos ejecutar correctamente la aplicación cliente y familiarizarnos con su uso. + +En una ventana de terminal, navega al directorio [applications/trader-typescript](../../applications/trader-typescript/). Luego completa los siguientes pasos: + +1. Instalar dependencias y compilar la aplicación cliente. + ```bash + npm install + ``` + +1. Definir variables de entorno que apuntan a recursos requeridos por la aplicación. + ```bash + export ENDPOINT=org1peer-api.127-0-0-1.nip.io:8080 + export MSP_ID=org1MSP + export CERTIFICATE=../../_cfg/uf/_msp/org1/org1admin/msp/signcerts/cert.pem + export PRIVATE_KEY=../../_cfg/uf/_msp/org1/org1admin/msp/keystore/cert_sk + ``` + +1. Ejecutar el comando **getAllAssets** para verificar que activos existen actualmente en el ledger (si hay alguno). + ```bash + npm start getAllAssets + ``` + +1. Ejecutar el comando **transact** para crear (y actualizar / eliminar) algunos activos ejemplos adicionales. + ```bash + npm start transact + ``` + +1. Ejecutar el comando **getAllAssets** de nuevo para ver los nuevos activos registrados en el ledger. + ```bash + npm start getAllAssets + ``` + +Estos comandos de aplicación CLI representan una aplicación simplificada que realiza una acción por llamada. Tenga en cuenta que las aplicaciones del mundo real generalmente serán de larga duración y realizarán llamadas a un contrato de parte de las solicitudes de los usuarios. + +## Pasos Opcionales + +Intenta utilizar los comandos **create**, **read** y **delete** para trabajar con activos específicos. + +Ver el [Readme](../../applications/trader-typescript/README.md) de la aplicación para detalles de cómo usar los comandos. diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/03-ApplicationOverview-ES.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/03-ApplicationOverview-ES.md new file mode 100644 index 00000000..51944d5d --- /dev/null +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/03-ApplicationOverview-ES.md @@ -0,0 +1,132 @@ +# Descripción General de la Aplicación + +Este tema describe las partes clave de la aplicación cliente y cómo utiliza la API del cliente Fabric Gateway para interactuar con la red. Este conocimiento le permitirá extender la aplicación en los temas siguientes. + +## Conectarse al Servicio Gateway + +La conexión al servicio peer Gateway está controlada por la función **runCommand()** en [app.ts](../../applications/trader-typescript/src/app.ts). Esta llama a otras dos funciones para realizar las dos tareas necesarias antes de que la aplicación cliente pueda realizar transacciones con la red Fabric: + +1. **Crear conexión gRPC al punto de entrada del peer Gateway** - esto es realizado en la función **newGrpcConnection()** en [connect.ts](../../applications/trader-typescript/src/connect.ts): + ```typescript + const tlsCredentials = grpc.credentials.createSsl(tlsRootCert); + return new grpc.Client(GATEWAY_ENDPOINT, tlsCredentials); + ``` + La conexión cliente gRPC es establecida utilizando el [gRPC API](https://grpc.io/docs/) y es manejada por la aplicación cliente. La aplicación puede utilizar la misma conexión gRPC connection para transaccionar en nombre de muchas identidades de clientes. + +1. **Crear conexión con peer Gateway** - esto es realizado en la función **newGatewayConnection()** en [connect.ts](../../applications/trader-typescript/src/connect.ts): + ```typescript + return connect({ + client, + identity: await newIdentity(), + signer: await newSigner(), + // Default timeouts for different gRPC calls + evaluateOptions: () => { + return { deadline: Date.now() + 5000 }; // 5 seconds + }, + endorseOptions: () => { + return { deadline: Date.now() + 15000 }; // 15 seconds + }, + submitOptions: () => { + return { deadline: Date.now() + 5000 }; // 5 seconds + }, + commitStatusOptions: () => { + return { deadline: Date.now() + 60000 }; // 1 minute + }, + }); + ``` + La conexión **Gateway** es establecida invocando la función de factoría [connect()](https://hyperledger.github.io/fabric-gateway/main/api/node/functions/connect.html) con una [identidad](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Identity.html) cliente (certificado X.509 del usuario) y una [implementación de firma](https://hyperledger.github.io/fabric-gateway/main/api/node/functions/signers.newPrivateKeySigner.html) (basado en la llave privada del usuario). Le permite a un usuario especifico interactuar con una red Fabric utilizando la conexión gRPC creada previamente. Una configuración opcional también puede ser suministrada, y es muy recomendado incluir tiempos de espera por defecto para las operaciones. + +## Comandos de Aplicación CLI + +Todas las implementaciones de los comandos CLI están ubicados dentro del directorio [commands](../../applications/trader-typescript/src/commands/). Los comandos son expuestos a [app.ts](../../applications/trader-typescript/src/app.ts) por [commands/index.ts](../../applications/trader-typescript/src/commands/index.ts). + +Cuando es invocado, el comando recibe la instancia **Gateway** que debe utilizar para interactuar con la red Fabric. Para hacer un trabajo útil, la implementación de los comandos típicamente realizan estos pasos: + +1. **Obtener una Red** - esto representa una red de nodos Fabric que perteneces a un canal específico de Fabric: + ```typescript + const network = gateway.getNetwork(CHANNEL_NAME); + ``` + +1. **Obtener un Contrato** - esto representa un contrato inteligente específico desplegado en la **Red**: + ```typescript + const contract = network.getContract(CHAINCODE_NAME); + ``` + +1. **Crear un adaptador del contrato inteligente** - esto provee una vista del contrato inteligente y las funciones de la transacción de una manera que es fácil de usar para la lógica de negocio de la aplicación cliente: + ```typescript + const smartContract = new AssetTransfer(contract); + ``` + +1. **Invocar las funciones de la transacción en un chaincode desplegado** - por ejemplo: + - Crear un activo en [commands/create.ts](../../applications/trader-typescript/src/commands/create.ts) + ```typescript + await smartContract.createAsset({ + ID: assetId, + Owner: owner, + Color: color, + Size: 1, + AppraisedValue: 1, + }); + ``` + - Leer todos los activos en [commands/getAllAssets.ts](../../applications/trader-typescript/src/commands/getAllAssets.ts) + ```typescript + const assets = await smartContract.getAllAssets(); + ``` + +Los comandos CLI de la aplicación representan una aplicación simplificada que realiza una acción por llamada. Tenga en cuenta que las aplicaciones del mundo real generalmente serán de larga duración y reutilizarán una conexión al servicio peer Gateway cuando realicen solicitudes de transacciones en nombre de las aplicaciones cliente. La conexión puede utilizar una única identidad de organización en nombre de varias solicitudes de usuario. + +## Invocaciones al Gateway API + +La clase **AssetTransfer** en [contract.ts](../../applications/trader-typescript/src/contract.ts) presenta al contrato inteligente en un formato apropiado para la aplicación de negocio. Internamente, utiliza la API del cliente Fabric Gateway para invocar funciones de transacción y se encarga de la traducción entre la aplicación de negocio y la representación de parámetros y valores de retorno de la API. + +Para mas detalles de las invocaciones disponibles se puede consultar la [documentación de la API de Contratos](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Contract.html). + +### Transacción submit + +La función de submit de transacciones enviará la solicitud al servicio peer Gateway. El servicio peer Gateway invocará el chaincode y recopilará los endosos necesarios de los peers de diferentes organizaciones para cumplir con la política de endosos del contrato. Luego enviará la transacción al servicio de ordenamiento en nombre de la aplicación cliente, para que el ledger de blockchain pueda ser actualizado. + +Un ejemplo de envío de transacciones se encuentra en el método **createAsset()**: + +```typescript +await this.#contract.submit('CreateAsset', { + arguments: [JSON.stringify(asset)], +}); +``` + +### Transacción evaluate + +La función de evaluación de transacciones solicitará al servicio peer Gateway que invoque el chaincode y devuelva los resultados al cliente, sin enviar una transacción al servicio de ordenamiento. Utilice la función de evaluación para consultar el estado del ledger de blockchain. + +Un ejemplo de evaluación de una transacción se encuentra en el método **getAllAssets()**: +```typescript +const result = await this.#contract.evaluate('GetAllAssets'); +``` + +## Reintentos de la transacción submit + +La naturaleza del flujo de envío de transacciones en Fabric implica que pueden ocurrir fallos en diferentes puntos del flujo. Para ayudar al cliente a gestionar los fallos, la API de Gateway genera errores de tipos específicos para indicar el punto en el flujo donde ocurrió el fallo. La función **submitWithRetry()** en [contract.ts](../../applications/trader-typescript/src/contract.ts) reintenta las transacciones que no logran confirmarse exitosamente: + +```typescript +let lastError: unknown | undefined; + +for (let retryCount = 0; retryCount < RETRIES; retryCount++) { + try { + return await submit(); + } catch (err: unknown) { + lastError = err; + if (err instanceof CommitError) { + // Transaction failed validation and did not update the ledger. Handle specific transaction validation codes. + if (err.code === StatusCode.MVCC_READ_CONFLICT) { + continue; // Retry + } + } + break; // Failure -- don't retry + } +} + +throw lastError; +``` + +Ver la [documentación de la API de submit()](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Contract.html#submit) para conocer los otros tipos de errores que puede arrojar. + +Para algunos casos puede ser más útil reintentar solo un paso especifico dentro del flujo de envío de transacciones. La API de Gateway proporciona un flujo detallado para permitir esto. Ver la [documentación de la API de Contratos](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Contract.html) para encontrar ejemplos de este flujo detallado. diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/04-Exercise-AssetTransfer-ES.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/04-Exercise-AssetTransfer-ES.md new file mode 100644 index 00000000..49d0098b --- /dev/null +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/04-Exercise-AssetTransfer-ES.md @@ -0,0 +1,31 @@ +# Ejercicio: Implementar transferencia de activos + +Actualmente, nuestra aplicación de comerciante solo puede crear, leer y eliminar activos invocando las funciones de chaincode CreateAsset(), ReadAsset(), and DeleteAsset(). Para ser realmente útil, necesita poder transferir activos a nuevos propietarios invocando la función de chaincode TransferAsset(). + +Ya existe un comando **transfer** implementado en [transfer.ts](../../applications/trader-typescript/src/commands/transfer.ts), que invoca al método `transferAsset()` en nuestra clase **AssetTransfer**. Desafortundamente, esto no ha sido implementado aún y no hace nada. + +1. Escribe una implementación para el método `transferAsset()` en [contract.ts](../../applications/trader-typescript/src/contract.ts). Revisa la [documentación de la API para Contratos](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Contract.html) y los otros métodos en la clase **AssetTransfer** para ideas de como seguir. + +2. Recompila la aplicación de tu TypeScript actualizado: + ```bash + npm install + ``` + > **Consejo:** Puedes dejar también ejecutándose `npm run build:watch` en una ventana de terminal para reconstruir automáticamente tu aplicación ante cualquier cambio en el código. + +3. Si estas utilizando una nueva ventana de terminal, recuerda definir las variables de entorno para que apunten a los recursos requeridos por la aplicación. + ```bash + export ENDPOINT=org1peer-api.127-0-0-1.nip.io:8080 + export MSP_ID=org1MSP + export CERTIFICATE=../../_cfg/uf/_msp/org1/org1admin/msp/signcerts/cert.pem + export PRIVATE_KEY=../../_cfg/uf/_msp/org1/org1admin/msp/keystore/cert_sk + ``` + +4. ¡Pruébalo! Utiliza el comando **transfer** para transferir activos a nuevos propietarios con el mismo ID de MSP. + +5. ¿Qué sucede si intentas manipular (transferir, eliminar) un activo después de transferirlo a otro ID de MSP? + +El contrato inteligente contiene lógica que solo permite a los usuarios de la organización propietaria modificar activos. Esto se logra verificando que el ID del Proveedor de Servicios de Membresía (MSP) de la identidad del cliente que invoca la transacción coincida con el ID de MSP de la organización propietaria del activo. Si no habías notado esto antes, quizás quieras revisar el código del contrato inteligente para ver cómo se implementa. + +## Pasos Opcionales + +Implementar un comando **update** en la aplicación cliente que permita modificar propiedades de un activo. diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/04-Exercise-AssetTransfer.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/04-Exercise-AssetTransfer.md index 00b6beb1..a8e55140 100644 --- a/full-stack-asset-transfer-guide/docs/ApplicationDev/04-Exercise-AssetTransfer.md +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/04-Exercise-AssetTransfer.md @@ -6,13 +6,13 @@ There is already a **transfer** command implemented in [transfer.ts](../../appli 1. Write an implementation for the `transferAsset()` method in [contract.ts](../../applications/trader-typescript/src/contract.ts). Look at the [API documentation for Contract](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Contract.html) and other methods within the **AssetTransfer** class for ideas on how to proceed. -1. Recompile the application from your updated TypeScript: +2. Recompile the application from your updated TypeScript: ```bash npm install ``` > **Tip:** You can also leave `npm run build:watch` running in a terminal window to automatically rebuild your application on any code change. -1. If you are using a new terminal window, set environment variables to point to resources required by the application. +3. If you are using a new terminal window, set environment variables to point to resources required by the application. ```bash export ENDPOINT=org1peer-api.127-0-0-1.nip.io:8080 export MSP_ID=org1MSP @@ -20,9 +20,9 @@ There is already a **transfer** command implemented in [transfer.ts](../../appli export PRIVATE_KEY=../../_cfg/uf/_msp/org1/org1admin/msp/keystore/cert_sk ``` -1. Try it out! Use the **transfer** command to transfer assets to new owners with the same MSP ID. +4. Try it out! Use the **transfer** command to transfer assets to new owners with the same MSP ID. -1. What happens if you try to manipulate (transfer, delete) an asset after transferring it to another MSP ID? +5. What happens if you try to manipulate (transfer, delete) an asset after transferring it to another MSP ID? The smart contract contains logic that only allows users in the owning organization to modify assets. It does this by checking that the Member Services Provider (MSP) ID for the client identity invoking the transaction matches the organization MSP ID of the asset owner. If you didn't notice this before, you might want to check out the smart contract code to see how this is implemented. diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/05-ChaincodeEvents-ES.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/05-ChaincodeEvents-ES.md new file mode 100644 index 00000000..9ae2c256 --- /dev/null +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/05-ChaincodeEvents-ES.md @@ -0,0 +1,20 @@ +# Eventos de Chaincode + +Una función de transacción de un contrato inteligente puede emitir un evento de chaincode para comunicar eventos de negocio. Estos eventos se emiten solo después de que una transacción se confirma con éxito y actualiza el ledger. Las transacciones que no pasan la validación no emiten eventos de chaincode. + +Las aplicaciones cliente pueden escuchar eventos de chaincode y desencadenar procesos de negocio externos en respuesta a actualizaciones del ledger. Un ejemplo podría ser programar la recogida de un paquete después de recibir una orden de entrega. Los eventos pueden reproducirse desde cualquier punto en la blockchain o recibirse en tiempo real. + +Al emitir un evento de chaincode, el contrato inteligente puede especificar un **payload** arbitrario para incluir en el evento. El **payload** se utiliza para comunicar el contexto de negocio a las aplicaciones cliente que reciben los eventos de chaincode. + +El objeto de [Red](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Network.html) en la API de Gateway provee métodos para obtener los eventos de chaincode. + +Para garantizar el correcto funcionamiento de los procesos de negocio, es importante que cada evento de chaincode se reciba exactamente una vez. ¡No queremos recoger el mismo paquete dos veces ni dejar de recoger un paquete! + +La API de Gateway permite usar un [Checkpointer](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Checkpointer.html) para rastrear (o marcar) los eventos procesados con éxito, y reanudar los eventos exactamente después del último evento marcado si ocurre un fallo o un reinicio de la aplicación. + +Para mayor comodidad, la API de Gateway proporciona dos implementaciones de checkpointer: + +1. [Checkpointer de Archivo](https://hyperledger.github.io/fabric-gateway/main/api/node/functions/checkpointers.file.html) that persists its state to the file-system. This can be used to resume eventing, even after an application restart. +2. [Checkpointer en memoria](https://hyperledger.github.io/fabric-gateway/main/api/node/functions/checkpointers.inMemory.html) that stores its state only in-memory. This can be used to recover from transient failures, such as a network communication error, during a single application run. + +Las aplicaciones cliente también pueden utilizar sus propias implementaciones de checkpointer, que persisten su estado en un almacenamiento adecuado, como una base de datos, siempre que cumplan con la interfaz simple de [Checkpoint](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Checkpoint.html). diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/05-ChaincodeEvents.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/05-ChaincodeEvents.md index 56ee296b..1b2d96ea 100644 --- a/full-stack-asset-transfer-guide/docs/ApplicationDev/05-ChaincodeEvents.md +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/05-ChaincodeEvents.md @@ -15,6 +15,6 @@ The Gateway API allows a [Checkpointer](https://hyperledger.github.io/fabric-gat For convenience, the Gateway API provides two checkpointer implementations: 1. [File checkpointer](https://hyperledger.github.io/fabric-gateway/main/api/node/functions/checkpointers.file.html) that persists its state to the file-system. This can be used to resume eventing, even after an application restart. -1. [In-memory checkpointer](https://hyperledger.github.io/fabric-gateway/main/api/node/functions/checkpointers.inMemory.html) that stores its state only in-memory. This can be used to recover from transient failures, such as a network communication error, during a single application run. +2. [In-memory checkpointer](https://hyperledger.github.io/fabric-gateway/main/api/node/functions/checkpointers.inMemory.html) that stores its state only in-memory. This can be used to recover from transient failures, such as a network communication error, during a single application run. Client applications can also use their own checkpointer implementations, which persist their state in suitable storage such as a database, provided they conform to the simple [Checkpoint](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Checkpoint.html) interface. diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/06-Exercise-ChaincodeEvents-ES.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/06-Exercise-ChaincodeEvents-ES.md new file mode 100644 index 00000000..b7f9c009 --- /dev/null +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/06-Exercise-ChaincodeEvents-ES.md @@ -0,0 +1,46 @@ +# Ejercicio: Usar eventos de chaincode + +Primero, intentemos escuchar los eventos de chaincode para ver qué información se incluye en los eventos emitidos por las funciones de la transacción del contrato inteligente. + +En una nueva ventana de terminal, navega al directorio [applications/trader-typescript](../../applications/trader-typescript/) para que puedas ejecutar a la aplicación de escucha. +Se asume que ya has compilado la aplicación en pasos previos. + +1. Si estas utilizando una nueva ventana de terminal, define a las variables de entorno para que apunten a las recursos requeridos por la aplicación. + ```bash + export ENDPOINT=org1peer-api.127-0-0-1.nip.io:8080 + export MSP_ID=org1MSP + export CERTIFICATE=../../_cfg/uf/_msp/org1/org1admin/msp/signcerts/cert.pem + export PRIVATE_KEY=../../_cfg/uf/_msp/org1/org1admin/msp/keystore/cert_sk + ``` + +2. Ejecuta el comando **listen** para escuchar las actualizaciones del ledger. El comando listen retornará eventos previos y también esperará por eventos futuros. + ```bash + npm start listen + ``` + +3. Una vez que hayas recibido los eventos disponibles, interrumpe la aplicación utilizando `Control-C`. + +4. Ejecuta el comando **listen** nuevamente. ¿Qué es lo que observas esta vez? + +En la segunda corrida del comando **listen**, deberías haber observado exactamente la misma salida que en la primera ejecución. Esto se debe a que cada ejecución del comando **listen** recupera todos los eventos de chaincode desde el inicio de la blockchain. Eso no es muy útil si queremos invocar procesos de negocio externos en respuesta a eventos de chaincode. Sería mucho mejor si cada evento se recibiera exactamente una vez, independientemente de si la aplicación cliente se reinicia.. + +Implementemos el checkpointing para asegurarnos de que no haya eventos duplicados ni perdidos. + +5. Implementa checkpointing para la lectura de eventos de chaincode en [listen.ts](../../applications/trader-typescript/src/commands/listen.ts). Revisa la [documentación de la API de Red](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Network.html) para obtener ideas de como proceder. ¡Asegúrate de marcar los eventos como checkpoint solo *después* de que se hayan procesado con éxito! + +6. Después de asegurarte que tus cambios fueron compilados, ejecuta el comando **listen** con la variable de entorno SIMULATED_FAILURE_COUNT seteada para simular un error aplicativo durante el procesamiento de un evento de chaincode: + ```bash + SIMULATED_FAILURE_COUNT=3 npm start listen + ``` + +7. Ejecuta el comando **listen** nuevamente. Deberías ver que la escucha de eventos se reanuda desde el mismo evento de chaincode que la aplicación no pudo procesar en la ejecución anterior. + +> **Nota:** El checkpointer guarda su posición actual de escucha en un archivo `checkpoint.json`. Si deseas eliminar el estado almacenado del checkpointer y comenzar a escuchar desde el bloque definido en `startBlock` nuevamente, elimina el archivo `checkpoint.json` mientras el checkpointer no esté en uso. + +## Pasos Opcionales + +Hasta ahora hemos estado reproduciendo eventos de chaincode emitidos previamente. Usemos el comando **listen** para notificarnos en tiempo real cuando tomemos posesión de activos. + +8. Modifica la función **onEvent()** en [listen.ts](../../applications/trader-typescript/src/commands/listen.ts) para notificarte cuando pases a ser el propietario de un activo nuevo (evento `CreateAsset`) o transferido (evento `TransferAsset`). Ten en cuenta que la propiedad `payload` del evento es un [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) que contiene el [JSON](https://en.wikipedia.org/wiki/JSON) emitido por el contrato inteligente. Consulta el método **readAsset()** en [contract.ts](../../applications/trader-typescript/src/contract.ts) para obtener ideas sobre cómo convertir esto en un objeto JavaScript y poder inspeccionar su propiedad `Owner`. + +9. Intenta ejecutar el comando **listen** en una ventana de terminal mientras utilizas otra ventana de terminal para crear y transferir activos. diff --git a/full-stack-asset-transfer-guide/docs/ApplicationDev/06-Exercise-ChaincodeEvents.md b/full-stack-asset-transfer-guide/docs/ApplicationDev/06-Exercise-ChaincodeEvents.md index 9140e6f8..5ca5c2a2 100644 --- a/full-stack-asset-transfer-guide/docs/ApplicationDev/06-Exercise-ChaincodeEvents.md +++ b/full-stack-asset-transfer-guide/docs/ApplicationDev/06-Exercise-ChaincodeEvents.md @@ -13,14 +13,14 @@ It is assumed that you have already built the application in prior steps. export PRIVATE_KEY=../../_cfg/uf/_msp/org1/org1admin/msp/keystore/cert_sk ``` -1. Run the **listen** command to listen for ledger updates. The listen command will return prior events and also wait for future events. +2. Run the **listen** command to listen for ledger updates. The listen command will return prior events and also wait for future events. ```bash npm start listen ``` -1. Once you have received the available events, interrupt the application using `Control-C`. +3. Once you have received the available events, interrupt the application using `Control-C`. -1. Run the **listen** command again. What do we see this time? +4. Run the **listen** command again. What do we see this time? On the second run of the **listen** command, you should have seen exactly the same output as the first run. This is because each run of the **listen** command retrieves all chaincode events from start of the blockchain. That's not so useful if we want to invoke external business processes in response to chaincode events. It would be much better if each event was received exactly once, regardless of whether the client application is restarted. @@ -28,12 +28,12 @@ Let's implement checkpointing to ensure there are no duplicate or missed events. 5. Implement checkpointing for the reading of chaincode events in [listen.ts](../../applications/trader-typescript/src/commands/listen.ts). Look at the [API documentation for Network](https://hyperledger.github.io/fabric-gateway/main/api/node/interfaces/Network.html) for ideas on how to proceed. Be sure to only checkpoint events *after* they are successfully processed! -1. Ensure your changes are compiled, then run the **listen** command with the SIMULATED_FAILURE_COUNT environment variable set to simulate an application error during the processing of a chancode event: +6. Ensure your changes are compiled, then run the **listen** command with the SIMULATED_FAILURE_COUNT environment variable set to simulate an application error during the processing of a chancode event: ```bash SIMULATED_FAILURE_COUNT=3 npm start listen ``` -1. Run the **listen** command again. You should see event listening resume from the same chaincode event that the application failed to process on the previous run. +7. Run the **listen** command again. You should see event listening resume from the same chaincode event that the application failed to process on the previous run. > **Note:** The checkpointer persists its current listening position in a `checkpoint.json` file. If you want to remove the checkpointer's stored state and start listening from the `startBlock` again, remove the `checkpoint.json` file while the checkpointer is not in use. @@ -43,4 +43,4 @@ So far we have been replaying previously emitted chaincode events. Let's use the 8. Modify the **onEvent()** function in [listen.ts](../../applications/trader-typescript/src/commands/listen.ts) to notify you if you become the owner of a new (`CreateAsset` event) or transferred (`TransferAsset` event) asset. Note that the `payload` property of the event is a [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) containing the [JSON](https://en.wikipedia.org/wiki/JSON) emitted by the smart contract. Look at the **readAsset()** method in [contract.ts](../../applications/trader-typescript/src/contract.ts) for ideas on how to convert this into a JavaScript object so you can inspect its `Owner` property. -1. Try running the **listen** command in one terminal window while using another terminal window to create and transfer assets. +9. Try running the **listen** command in one terminal window while using another terminal window to create and transfer assets.