Blockchain: ¿qué PoC deberíamos construir?

¡Tus ojos tienen miedo y te pican las manos!

En artículos anteriores, abordamos las tecnologías sobre las cuales se construyen las cadenas de bloques (¿Qué deberíamos construir una blockchain?) y casos que se pueden implementar con su ayuda (¿Por qué deberíamos construir un caso?). ¡Es hora de trabajar con las manos! Para implementar pilotos y PoC (Proof of Concept), prefiero usar las nubes, porque... se puede acceder a ellos desde cualquier parte del mundo y, a menudo, no es necesario perder tiempo en la tediosa instalación del entorno, porque Hay configuraciones preestablecidas. Entonces, hagamos algo simple, por ejemplo, una red para transferir monedas entre participantes y llamémosla modestamente Bitcoin. Para ello utilizaremos la nube de IBM y la blockchain universal Hyperledger Fabric. Primero, averigüemos por qué Hyperledger Fabric se llama blockchain universal.

Blockchain: ¿qué PoC deberíamos construir?

Hyperledger Fabric: una cadena de bloques universal

En términos generales, un sistema de información universal es:

  • Un conjunto de servidores y un núcleo de software que realiza la lógica empresarial;
  • Interfaces para la interacción con el sistema;
  • Herramientas para registro, autenticación y autorización de dispositivos/personas;
  • Base de datos que almacena datos operativos y de archivo:

Blockchain: ¿qué PoC deberíamos construir?

La versión oficial de qué es Hyperledger Fabric se puede leer en sitio weby, en resumen, Hyperledger Fabric es una plataforma de código abierto que le permite crear cadenas de bloques privadas y ejecutar contratos inteligentes arbitrarios escritos en los lenguajes de programación JS y Go. Veamos en detalle la arquitectura de Hyperledger Fabric y asegurémonos de que sea un sistema universal que solo tiene características específicas para almacenar y registrar datos. La especificidad es que los datos, como en todas las cadenas de bloques, se almacenan en bloques que se colocan en la cadena de bloques solo si los participantes llegan a un consenso y, después de registrarlos, los datos no pueden corregirse ni eliminarse silenciosamente.

Arquitectura de tejido Hyperledger

El diagrama muestra la arquitectura de Hyperledger Fabric:

Blockchain: ¿qué PoC deberíamos construir?

Organizaciones — las organizaciones contienen pares, es decir blockchain existe gracias al apoyo de las organizaciones. Diferentes organizaciones pueden formar parte de un mismo canal.

Channel — una estructura lógica que une a los pares en grupos, es decir Se especifica la cadena de bloques. Hyperledger Fabric puede procesar simultáneamente múltiples cadenas de bloques con diferente lógica empresarial.

Proveedor de servicios de membresía (MSP) es una CA (Autoridad de certificación) para emitir identidad y asignar roles. Para crear un nodo, debe interactuar con el MSP.

Nodos pares – verificar transacciones, almacenar la cadena de bloques, ejecutar contratos inteligentes e interactuar con aplicaciones. Los pares tienen una identidad (certificado digital), que es emitida por el MSP. A diferencia de la red Bitcoin o Etherium, donde todos los nodos tienen los mismos derechos, en Hyperledger Fabric los nodos desempeñan diferentes roles:

  • compañero tal vez compañero que respalda (EP) y ejecutar contratos inteligentes.
  • compañero comprometido (CP): solo guarda datos en la cadena de bloques y actualiza el "Estado mundial".
  • Compañero ancla (AP): si varias organizaciones participan en la cadena de bloques, se utilizan pares ancla para la comunicación entre ellas. Cada organización debe tener uno o más pares ancla. Al utilizar AP, cualquier par de una organización puede obtener información sobre todos los pares de otras organizaciones. Se utiliza para sincronizar información entre AP. protocolo de chismes.
  • Compañero líder — si una organización tiene varios pares, solo el líder del par recibirá bloques del servicio de pedidos y se los entregará al resto de los pares. El líder puede ser especificado estáticamente o seleccionado dinámicamente por sus pares en la organización. El protocolo de chismes también se utiliza para sincronizar información sobre los líderes.

Activos – entidades que tienen valor y están almacenadas en la cadena de bloques. Más específicamente, se trata de datos clave-valor en formato JSON. Son estos datos los que se registran en Blockchain. Tienen un historial, que se almacena en la cadena de bloques, y un estado actual, que se almacena en la base de datos "Estado mundial". Las estructuras de datos se completan arbitrariamente según las tareas comerciales. No hay campos obligatorios, la única recomendación es que los activos deben tener dueño y ser valiosos.

Libro mayor — consta de Blockchain y la base de datos de estado de Word, que almacena el estado actual de los activos. El estado mundial utiliza LevelDB o CouchDB.

Contrato inteligente — mediante contratos inteligentes, se implementa la lógica empresarial del sistema. En Hyperledger Fabric, los contratos inteligentes se denominan código de cadena. Utilizando código de cadena, se especifican los activos y las transacciones sobre ellos. En términos técnicos, los contratos inteligentes son módulos de software implementados en los lenguajes de programación JS o Go.

Política de respaldo — Para cada código de cadena, puedes establecer una política sobre cuántas confirmaciones de una transacción se deben esperar y de quién. Si no se establece la política, entonces el valor predeterminado es: "la transacción debe ser confirmada por cualquier miembro de cualquier organización en el canal". Ejemplos de políticas:

  • La transacción debe ser aprobada por cualquier administrador de la organización;
  • Debe ser confirmado por cualquier miembro o cliente de la organización;
  • Debe ser confirmado por cualquier organización paritaria.

servicio de pedidos — empaqueta transacciones en bloques y las envía a pares en el canal. Garantiza la entrega de mensajes a todos los pares de la red. Utilizado para sistemas industriales. corredor de mensajes de Kafka, para desarrollo y pruebas Solo.

flujo de llamadas

Blockchain: ¿qué PoC deberíamos construir?

  • La aplicación se comunica con Hyperledger Fabric mediante Go, Node.js o Java SDK;
  • El cliente crea una transacción de transmisión y la envía a sus pares que la respaldan;
  • El par verifica la firma del cliente, completa la transacción y envía la firma de respaldo al cliente. Chaincode se ejecuta solo en el par que lo respalda y el resultado de su ejecución se envía a todos los pares. Este algoritmo de trabajo se denomina consenso PBFT (Practical Byzantine Fault Tolerant). Difiere de BFT clásico el hecho de que el mensaje se envía y se espera confirmación no de todos los participantes, sino solo de un conjunto determinado;
  • Luego de que el cliente haya recibido el número de respuestas correspondientes a la póliza de respaldo, envía la transacción al servicio de Ordenamiento;
  • El servicio de pedidos genera un bloque y lo envía a todos los pares comprometidos. El servicio de pedidos garantiza el registro secuencial de los bloques, lo que elimina la llamada bifurcación del libro mayor (ver sección "Horquillas");
  • Los pares reciben un bloque, verifican nuevamente la política de respaldo, escriben el bloque en la cadena de bloques y cambian el estado en la base de datos "Estado mundial".

Aquellos. Esto da como resultado una división de roles entre los nodos. Esto garantiza que la cadena de bloques sea escalable y segura:

  • Los contratos inteligentes (código de cadena) realizan el respaldo de pares. Esto garantiza la confidencialidad de los contratos inteligentes, porque no lo almacenan todos los participantes, sino únicamente los pares que lo respaldan.
  • El pedido debería funcionar rápidamente. Esto está garantizado por el hecho de que Ordering solo forma un bloque y lo envía a un conjunto fijo de pares líderes.
  • Los pares comprometidos solo almacenan la cadena de bloques; puede haber muchos y no requieren mucha energía ni operación instantánea.

Puede encontrar más detalles sobre las soluciones arquitectónicas de Hyperledger Fabric y por qué funciona de esta manera y no de otra manera aquí: Orígenes de la arquitectura o aquí: Hyperledger Fabric: un sistema operativo distribuido para cadenas de bloques autorizadas.

Entonces, Hyperledger Fabric es un sistema verdaderamente universal con el que puedes:

  • Implementar lógica empresarial arbitraria utilizando el mecanismo de contrato inteligente;
  • Registre y reciba datos de la base de datos blockchain en formato JSON;
  • Conceda y verifique el acceso a la API mediante la autoridad certificadora.

Ahora que entendemos un poco los detalles de Hyperledger Fabric, ¡finalmente hagamos algo útil!

Implementando cadena de bloques

Formulación del problema

La tarea es implementar la red Citcoin con las siguientes funciones: crear una cuenta, obtener un saldo, recargar su cuenta, transferir monedas de una cuenta a otra. Dibujemos un modelo de objetos, que implementaremos en un contrato inteligente. Entonces, tendremos cuentas que están identificadas por nombres y contienen un saldo y una lista de cuentas. Las cuentas y una lista de cuentas son, en términos de activos de Hyperledger Fabric. En consecuencia, tienen una historia y un estado actual. Intentaré dibujar esto claramente:

Blockchain: ¿qué PoC deberíamos construir?

Las cifras superiores son el estado actual, que se almacena en la base de datos "Estado mundial". Debajo de ellos hay figuras que muestran el historial almacenado en la cadena de bloques. El estado actual de los activos cambia mediante las transacciones. El Activo cambia sólo en su totalidad, por lo tanto, como resultado de la transacción, se crea un nuevo objeto y el valor actual del activo pasa a la historia.

nube de ibm

Creamos una cuenta en Nube de IBM. Para utilizar la plataforma blockchain, se debe actualizar a Pay-As-You-Go. Este proceso puede no ser rápido, porque... IBM solicita información adicional y la verifica manualmente. Como nota positiva, puedo decir que IBM tiene buenos materiales de capacitación que le permiten implementar Hyperledger Fabric en su nube. Me gustó la siguiente serie de artículos y ejemplos:

Las siguientes son capturas de pantalla de la plataforma IBM Blockchain. Esta no es una instrucción sobre cómo crear una cadena de bloques, sino simplemente una demostración del alcance de la tarea. Entonces, para nuestros propósitos, formamos una Organización:

Blockchain: ¿qué PoC deberíamos construir?

Creamos nodos en él: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: ¿qué PoC deberíamos construir?

Creamos usuarios:

Blockchain: ¿qué PoC deberíamos construir?

Crea un canal y llámalo bitcoin:

Blockchain: ¿qué PoC deberíamos construir?

Básicamente, Channel es una cadena de bloques, por lo que comienza con el bloque cero (bloque Génesis):

Blockchain: ¿qué PoC deberíamos construir?

Escribir un contrato inteligente

/*
 * Citcoin smart-contract v1.5 for Hyperledger Fabric
 * (c) Alexey Sushkov, 2019
 */
 
'use strict';
 
const { Contract } = require('fabric-contract-api');
const maxAccounts = 5;
 
class CitcoinEvents extends Contract {
 
    async instantiate(ctx) {
        console.info('instantiate');
        let emptyList = [];
        await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(emptyList)));
    }
    // Get all accounts
    async GetAccounts(ctx) {
        // Get account list:
        let accounts = '{}'
        let accountsData = await ctx.stub.getState('accounts');
        if (accountsData) {
            accounts = JSON.parse(accountsData.toString());
        } else {
            throw new Error('accounts not found');
        }
        return accountsData.toString()
    }
     // add a account object to the blockchain state identifited by their name
    async AddAccount(ctx, name, balance) {
        // this is account data:
        let account = {
            name: name,
            balance: Number(balance),       
            type: 'account',
        };
        // create account:
        await ctx.stub.putState(name, Buffer.from(JSON.stringify(account)));
 
        // Add account to list:
        let accountsData = await ctx.stub.getState('accounts');
        if (accountsData) {
            let accounts = JSON.parse(accountsData.toString());
            if (accounts.length < maxAccounts)
            {
                accounts.push(name);
                await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(accounts)));
            } else {
                throw new Error('Max accounts number reached');
            }
        } else {
            throw new Error('accounts not found');
        }
        // return  object
        return JSON.stringify(account);
    }
    // Sends money from Account to Account
    async SendFrom(ctx, fromAccount, toAccount, value) {
        // get Account from
        let fromData = await ctx.stub.getState(fromAccount);
        let from;
        if (fromData) {
            from = JSON.parse(fromData.toString());
            if (from.type !== 'account') {
                throw new Error('wrong from type');
            }   
        } else {
            throw new Error('Accout from not found');
        }
        // get Account to
        let toData = await ctx.stub.getState(toAccount);
        let to;
        if (toData) {
            to = JSON.parse(toData.toString());
            if (to.type !== 'account') {
                throw new Error('wrong to type');
            }  
        } else {
            throw new Error('Accout to not found');
        }
 
        // update the balances
        if ((from.balance - Number(value)) >= 0 ) {
            from.balance -= Number(value);
            to.balance += Number(value);
        } else {
            throw new Error('From Account: not enought balance');          
        }
 
        await ctx.stub.putState(from.name, Buffer.from(JSON.stringify(from)));
        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
                 
        // define and set Event
        let Event = {
            type: "SendFrom",
            from: from.name,
            to: to.name,
            balanceFrom: from.balance,
            balanceTo: to.balance,
            value: value
        };
        await ctx.stub.setEvent('SendFrom', Buffer.from(JSON.stringify(Event)));
 
        // return to object
        return JSON.stringify(from);
    }
 
    // get the state from key
    async GetState(ctx, key) {
        let data = await ctx.stub.getState(key);
        let jsonData = JSON.parse(data.toString());
        return JSON.stringify(jsonData);
    }
    // GetBalance   
    async GetBalance(ctx, accountName) {
        let data = await ctx.stub.getState(accountName);
        let jsonData = JSON.parse(data.toString());
        return JSON.stringify(jsonData);
    }
     
    // Refill own balance
    async RefillBalance(ctx, toAccount, value) {
        // get Account to
        let toData = await ctx.stub.getState(toAccount);
        let to;
        if (toData) {
            to = JSON.parse(toData.toString());
            if (to.type !== 'account') {
                throw new Error('wrong to type');
            }  
        } else {
            throw new Error('Accout to not found');
        }
 
        // update the balance
        to.balance += Number(value);
        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
                 
        // define and set Event
        let Event = {
            type: "RefillBalance",
            to: to.name,
            balanceTo: to.balance,
            value: value
        };
        await ctx.stub.setEvent('RefillBalance', Buffer.from(JSON.stringify(Event)));
 
        // return to object
        return JSON.stringify(from);
    }
}
module.exports = CitcoinEvents;

Intuitivamente, aquí todo debería quedar claro:

  • Hay varias funciones (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) que el programa de demostración llamará utilizando la API Hyperledger Fabric.
  • Las funciones SendFrom y RefillBalance generan Eventos que recibirá el programa de demostración.
  • La función de creación de instancias se llama una vez cuando se crea una instancia de un contrato inteligente. De hecho, se llama no sólo una vez, sino cada vez que cambia la versión del contrato inteligente. Por lo tanto, inicializar una lista con una matriz vacía es una mala idea, porque Ahora, cuando cambiemos la versión del contrato inteligente, perderemos la lista actual. Pero está bien, recién estoy aprendiendo).
  • Las cuentas y una lista de cuentas son estructuras de datos JSON. JS se utiliza para la manipulación de datos.
  • Puede obtener el valor actual de un activo mediante la llamada a la función getState y actualizarlo mediante putState.
  • Al crear una Cuenta, se llama a la función AddAccount, en la que se realiza una comparación para el número máximo de cuentas en la blockchain (maxAccounts = 5). Y aquí hay un obstáculo (¿lo has notado?), que conduce a un aumento interminable en el número de cuentas. Estos errores deben evitarse)

A continuación, cargamos el contrato inteligente en el Canal y lo instanciamos:

Blockchain: ¿qué PoC deberíamos construir?

Veamos la transacción para instalar Smart Contract:

Blockchain: ¿qué PoC deberíamos construir?

Veamos los detalles sobre nuestro canal:

Blockchain: ¿qué PoC deberíamos construir?

Como resultado, obtenemos el siguiente diagrama de una red blockchain en la nube de IBM. El diagrama también muestra un programa de demostración que se ejecuta en la nube de Amazon en un servidor virtual (más sobre esto en la siguiente sección):

Blockchain: ¿qué PoC deberíamos construir?

Creación de una GUI para llamadas a la API de Hyperledger Fabric

Hyperledger Fabric tiene una API que se puede utilizar para:

  • Crear canal;
  • Conexiones de igual a canal;
  • Instalación e instanciación de contratos inteligentes en el canal;
  • Llamar transacciones;
  • Solicita información sobre la blockchain.

Desarrollo de aplicaciones

En nuestro programa de demostración usaremos la API solo para llamar transacciones y solicitar información, porque Ya hemos completado los pasos restantes utilizando la plataforma blockchain de IBM. Escribimos una GUI utilizando una pila de tecnología estándar: Express.js + Vue.js + Node.js. Puede escribir un artículo aparte sobre cómo empezar a crear aplicaciones web modernas. Aquí dejaré un enlace al ciclo de conferencias que más me gustó: Aplicación web de pila completa con Vue.js y Express.js. El resultado es una aplicación cliente-servidor con una interfaz gráfica familiar al estilo Material Design de Google. La API REST entre cliente y servidor consta de varias llamadas:

  • HyperledgerDemo/v1/init - inicializa la cadena de bloques;
  • HyperledgerDemo/v1/accounts/list: obtiene una lista de todas las cuentas;
  • HyperledgerDemo/v1/account?name=Bob&balance=100: crea una cuenta de Bob;
  • HyperledgerDemo/v1/info?account=Bob: obtiene información sobre la cuenta de Bob;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 - transfiere dos monedas de Bob a Alice;
  • HyperledgerDemo/v1/disconnect: cierra la conexión a la cadena de bloques.

Descripción de la API con ejemplos incluidos en Sitio web del cartero - un programa conocido para probar la API HTTP.

Aplicación de demostración en la nube de Amazon

Subí la aplicación a Amazon porque... IBM todavía no ha podido actualizar mi cuenta y permitirme crear servidores virtuales. Cómo agregar una cereza al dominio: www.citcoin.info. Mantendré el servidor encendido por un tiempo y luego lo apagaré, porque... los centavos de alquiler están goteando y las monedas de citocoin aún no cotizan en la bolsa de valores) Incluyo capturas de pantalla de la demostración en el artículo para que la lógica del trabajo quede clara. La aplicación de demostración puede:

  • Inicialice la cadena de bloques;
  • Cree una cuenta (pero ahora no puede crear una cuenta nueva porque se alcanzó el número máximo de cuentas especificadas en el contrato inteligente en la cadena de bloques);
  • Recibir una lista de Cuentas;
  • Transfiere monedas de bitcoin entre Alice, Bob y Alex;
  • Recibir eventos (pero ahora no hay forma de mostrar eventos, por lo que, para simplificar, la interfaz dice que los eventos no son compatibles);
  • Registrar acciones.

Primero inicializamos la cadena de bloques:

Blockchain: ¿qué PoC deberíamos construir?

A continuación, creamos nuestra cuenta, no pierdas tiempo con el saldo:

Blockchain: ¿qué PoC deberíamos construir?

Obtenemos una lista de todas las cuentas disponibles:

Blockchain: ¿qué PoC deberíamos construir?

Seleccionamos el remitente y el destinatario, y obtenemos sus saldos. Si el remitente y el destinatario son el mismo, se recargará su cuenta:

Blockchain: ¿qué PoC deberíamos construir?

En el registro monitoreamos la ejecución de las transacciones:

Blockchain: ¿qué PoC deberíamos construir?

En realidad, eso es todo con el programa de demostración. A continuación puede ver nuestra transacción en blockchain:

Blockchain: ¿qué PoC deberíamos construir?

Y la lista general de transacciones:

Blockchain: ¿qué PoC deberíamos construir?

Con esto, hemos completado con éxito la implementación del PoC para crear la red Bitcoin. ¿Qué más hay que hacer para que Citcoin se convierta en una red completa para transferir monedas? Muy poco:

  • En la etapa de creación de la cuenta, implemente la generación de una clave pública/privada. La clave privada debe almacenarse con el usuario de la cuenta, la clave pública debe almacenarse en la cadena de bloques.
  • Realice una transferencia de monedas en la que se utilice una clave pública, en lugar de un nombre, para identificar al usuario.
  • Cifre las transacciones que van del usuario al servidor con su clave privada.

Conclusión

Hemos implementado la red Citcoin con las siguientes funciones: agregar una cuenta, obtener un saldo, recargar su cuenta, transferir monedas de una cuenta a otra. Entonces, ¿cuánto nos costó construir una prueba de concepto?

  • Necesitas estudiar blockchain en general y Hyperledger Fabric en particular;
  • Aprenda a utilizar las nubes de IBM o Amazon;
  • Aprenda el lenguaje de programación JS y algún framework web;
  • Si es necesario almacenar algunos datos no en la cadena de bloques, sino en una base de datos separada, aprenda a integrarlos, por ejemplo, con PostgreSQL;
  • Y por último, pero no menos importante: ¡no se puede vivir en el mundo moderno sin conocimientos de Linux!)

Por supuesto, no es ninguna ciencia, ¡pero tendrás que trabajar duro!

Исходники en GitHub

fuentes puestas GitHub. Breve descripción del repositorio:
Catálogo «servidor» — Servidor Node.js
Catálogo «cliente» — Cliente Node.js
Catálogo «blockchain"(los valores de los parámetros y las claves, por supuesto, no funcionan y se dan sólo como ejemplo):

  • contrato - código fuente de contrato inteligente
  • billetera: claves de usuario para usar la API Hyperledger Fabric.
  • *.cds: versiones compiladas de contratos inteligentes
  • Archivos *.json: ejemplos de archivos de configuración para usar la API Hyperledger Fabric

¡Es solo el comienzo!

Fuente: habr.com

Añadir un comentario