En artículos anteriores se ha comprobado que Python cuenta con herramientas suficientemente versátiles como para poder desarrollar una ÐApp contra RSK. En el caso que nos ocupa se hace un planteamiento de concepción, desarrollo y despliegue de una web ÐApp basado en Quorum con RAFT sobre Angular y Python+Flask+CherryPy.
Siguiendo indicaciones de Alfonso de la Rocha en su reciente presentación de HarvardIT , lo primero sería identificar el problema. A muchos nos ha pasado que al prestar libros, vinilos o DVD a nuestros amigos o conocidos se les pierde la pista para siempre cayendo en el olvido. Como prueba de concepto, nos planteamos crear una web ÐApp que permita la gestión de dichos libros que se prestan entre amigos para que no nos digan 'Ya te lo devolví' o 'Nunca me lo dejaste'. Con una blockchain que refleje todos los préstamos realizados el único problema que quedará será la voluntad o posibilidad de devolver el préstamo, que quedaría fuera del ámbito tecnológico.
En esta serie de artículos se describirá los pasos seguidos para el desarrollo de la ÐApp así como la configuración de los nodos de la red permisionada basada en Quorum .
Despliegue de web ÐApp con Quorum+Angular+Python+Flask en un VPS con Ubuntu 16.04 [1] [Quorum] [2] [ Solidity] [3] [ Python]
La información descrita en este artículo diferirá de la mostrada en el repositorio GiveLibAck en tanto en cuanto aquí se muestran pasos intermedios que pueden saltarse bajándose el contenido del repositorio como por ejemplo los binarios de Ubuntu o la estructura de directorios de los nodos junto con los keystores de las cuentas.
Procesos de negocio
Para la prueba de concepto se definen una serie de acciones que los usuarios pueden realizar y que posteriormente se deben mapear en los contratos y el backend.
Básicamente los usuarios pueden
- registrarse y registrar libros
- actualizar algunos datos de los libros registrados
- pedir el préstamos de libros o su retorno si están en préstamo
- dejar libros en préstamo o retornar los libros prestados
- identificar quién tiene un libro, qué libros ha creado en el sistema un usuario y qué libros tiene actualmente en posesión (de su creación o prestados) un usuario
Solución tecnológica
Como topología se escoge una red permisionada basada en Quorum, con metología de consenso RAFT y tokens ERC721 para la identificación única de cada uno de los activos (libros). Se desplegarán varios nodos siendo cada nodo representante de cada usuario que interactúa con la aplicación.
Como backend se usa Python 3.5 (necesario para poder interactuar con el módulo web3) que tendrá activos endpoints del servidor web (WSGI) de Flask y gestionado por la capa WSGI de CherryPy para dotar de envergadura al servidor HTTP.
Como frontend se usa Angular desplegando el framework directamente interactuando con Python a con CORS.
Instalación de la infraestructura y desarrollo
A partir de ese momento se puede empezar creando un esqueleto de lo que será el proyecto en un repositorio abierto en GitHub siguiendo la filosofía de transparencia y compartición de conocimiento.
El entorno de uso puede ser tanto un servidor dedicado con una versión de Ubuntu 16.04 como una imagen virtual de la misma versión para ordenadores de sobremesa como los disponibles en osboxes tanto para VirtualBox como para VMWare . En este caso se documenta la instalación y configuración en una imagen de osboxes como paso previo a la migración a producción en un servidor.
Backend
El backend estará basado en un entorno virtual con Python 3.5 (por las dependencias del módulo web3) y una serie de nodos instanciados en diferentes máquinas creando una constelación Quorum.
Backend - Quorum
El objetivo de la red de nodos es que sea permisionada y que cada usuario tenga un nodo. Como herramienta se decide por Quorum con dos nodos. Como metodología para el consenso, Quorum acepta tanto RAFT como Istanbul BFT. En este ejemplo se implementará con RAFT sin uso de comunicación privada.
Instalación
En los documentos informativos de Quorum, se recomienda usar unas imágenes con configuraciones hechas disponibles en Vagrant aunque en este caso se ha preferido la compilación en local para no añadir más capas de virtualización de entornos más allá del de Python. De la misma manera, para este ejemplo se ha decidido crear la configuración de la red desde cero sin basarse en el conocido y disponible ejemplo de 7 nodos con el fin de enseñar los pasos para la instalación y configuración de los nodos y una red.
Para ello se necesita descargar el repositorio de
Quorum y el compilador de Go superior a la versión 1.6.3 (disponible en Ubuntu 16.04) y que requiere de un respositorio externo. Los binarios que se compilan se copian en un directorio que bien puede ser
/usr/lib/bin o en caso de ser otro directorio que no esté en el $PATH deben añadirse. Se puede añadir el $PATH en
.bashrc y cargarlo con
source ~/.bashrc
.
osboxes@osboxes:~$ mkdir Desktop/giveliback
osboxes@osboxes:~$ cd Desktop/giveliback
osboxes@osboxes:~/Desktop/giveliback$ git clone https://github.com/jpmorganchase/quorum.git
osboxes@osboxes:~/Desktop/giveliback$ sudo add-apt-repository ppa:gophers/archive
osboxes@osboxes:~/Desktop/giveliback$ sudo apt-get update
osboxes@osboxes:~/Desktop/giveliback$ sudo apt-get install golang-1.10-go
osboxes@osboxes:~/Desktop/giveliback$ PATH=$PATH:/usr/lib/go-1.10/bin
osboxes@osboxes:~/Desktop/giveliback$ go version
go1.10 linux/amd64
Disponiendo del repositorio de Quorum y del compilador Go , se procede a la compilación del repositorio ( make all). Los binarios resultantes se localizan en quorum/build/bin. Se puede realizar la comprobación de la cimpilación con ( make test). Se añaden los binarios compilados en el $PATH habiendo creado un enlace simbólico ( quorum_bin) en el repositorio giveliback. Esos serán los binarios a utilizar para la configuración e inicialización de los nodos.
osboxes@osboxes:~/Desktop/giveliback$ $ cd quorum
osboxes@osboxes:~/Desktop/giveliback/quorum$ make all
...
Se puede optar también por usar la última distribución disponible, en la redacción de este artículo es la
2.0.2. y realizar el mismo proceso de compilación de los binarios.
wget https://github.com/jpmorganchase/quorum/archive/v2.0.2.tar.gz
tar -xzvf v2.0.2.tar.gz
cd quorum.2.0.2
make all
Una vez descargados los ficheros, se procede a la compilación de los binarios y añadirlos a través de un directorio simbólico al $PATH.
osboxes@osboxes:~/Desktop/giveliback/quorum$ cd ..
osboxes@osboxes:~/Desktop/giveliback$ ln -s quorum/build/bin/ quorum_bin
osboxes@osboxes:~/Desktop/giveliback$ PATH=$PATH:/home/osboxes/Desktop/giveliback/quorum_bin
osboxes@osboxes:~/Desktop/giveliback$ which geth
/home/osboxes/Desktop/giveliback/quorum_bin/geth
Configuración del nodo
La configuración de un nodo se puede guardar en un archivo tipo TOML con los parámetros que sean necesarios para poder instanciar cómodamente las siguientes veces. Bien se puede guardar el contenido mostrado anteriormente en un archivo ( config.toml) y modificar su contenido con un editor de texto o bien se puede generar dicho contenido con los parámetros de interés de origen.
En este caso se definen tanto los directorios de datos ( datadir) como los módulos a cargar (entre ellos quorum) así como los puertos de conectividad en el fichero config.toml. La contraseña se referencia en un archivo ( password.txt) para dotar de comodidad. Dicho archivo puede estar vacío pero debe tener el mismo contenido que la contraseña usada al crear las cuentas. En este caso la contraseña es 'password'. Permissioned forzará el parámetro de aprobación de nodos previo a la inclusion del cluster.
Usando como parámetro dumpconfig, muestra en pantalla los valores de inicialización de la cadena de bloques. EnableNodePermission se tipifica como afirmativa.
osboxes@osboxes:~/Desktop/giveliback$ echo "password" > password.txt
osboxes@osboxes:~/Desktop/giveliback$ head password.txt
password
osboxes@osboxes:~/Desktop/giveliback$ geth --datadir=qdata/node1 --rpc --rpcaddr 0.0.0.0 --rpcapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum --permissioned --nodiscover --rpcport 22000 --port 21000 dumpconfig > config.toml
WARN [07-05|18:45:10] No etherbase set and no accounts found as default
El contenido del fichero de configuración config.toml contiene los parámetros asignados.
En la creación del fichero de configuración, también se crea el directorio que albergará el nodo ( node1) con un subdirectorio para las cuentas (keystore) actualmente vacío. Muestra una alerta al no estar definidas las cuentas de inicio ni definirse el bloque génesis. Se subsanará dicha situación más adelante.
osboxes@osboxes:~/Desktop/giveliback$ ls qdata/node1
keystore
osboxes@osboxes:~/Desktop/giveliback$ ls qdata/node1/keystore/
osboxes@osboxes:~/Desktop/giveliback$
En caso de querer levantar un nodo con la configuración guardada, se referencia dicho fichero de configración al instanciar el nodo. En caso de levantar el nodo sin tener ningún fichero de permissioned-nodes.json, el nodo correrá sin conexión alguna a otros nodos. Una vez se configuren los nodos se puede modificar el archivo para añadir los nodos que a los que se permite conectar.
Creación de cuentas
Entre las dos formas más comunes de inicar un nodo con cuentas con saldo, una propone crear las cuentas sin tener el nodo iniciado para poder generar el bloque genesis y en la otra se levanta el nodo y se crean las cuentas interactivamente desde la consola. Aunque el resultado es el mismo, la segunda requiere del borrado de la cadena de bloques del nodo previa a la inicialización del bloque génesis debido a su inicialización previa.
En caso de querer configurar las cuentas antes de levantar por pimera vez el nodo, geth permite la interacción contra un nodo en modo offline para la creación de cuentas. En este caso se procede a la creación de cuatro cuentas.
osboxes@osboxes:~/Desktop/giveliback$ geth --datadir=qdata/node1 --password password.txt account new
newWARN [07-05|18:46:34] No etherbase set and no accounts found as default
Address: {3b6927fe4a4a4d44c3445292d375542cf299661c}
osboxes@osboxes:~/Desktop/giveliback$ geth --datadir=qdata/node1 --password password.txt account new
Address: {513f15ec9fc190cbc2ac25c6d6acdb58253f80d7}
osboxes@osboxes:~/Desktop/giveliback$ geth --datadir=qdata/node1 --password password.txt account new
Address: {5030a651df562c629cfc92928210a51d2e688d6d}
osboxes@osboxes:~/Desktop/giveliback$ geth --datadir=qdata/node1 --password password.txt account new
Address: {00d631971be081c4de18fb6fca0c2723782299f7}
A partir de este momento, se han creado cuatro cuentas (wallets) en el directorio
/node1/keystore que coinciden con los nombres de los archivos (uno por cuenta).
osboxes@osboxes:~/Desktop/giveliback$ls -la /home/osboxes/Desktop/giveliback/qdata/node1/keystore/
total 24
drwx------ 2 osboxes osboxes 4096 jul 05 18:46 .
drwx------ 4 osboxes osboxes 4096 jul 05 18:47 ..
-rw------- 1 osboxes osboxes 491 jul 05 18:46 UTC--2018-07-05T18-46-07.617126785Z--3b6927fe4a4a4d44c3445292d375542cf299661c
-rw------- 1 osboxes osboxes 491 jul 05 18:47 UTC--2018-07-05T18-47-06.750007367Z--513f15ec9fc190cbc2ac25c6d6acdb58253f80d7
-rw------- 1 osboxes osboxes 491 jul 05 18:47 UTC--2018-07-05T18-47-20.325374470Z--5030a651df562c629cfc92928210a51d2e688d6d
-rw------- 1 osboxes osboxes 491 jul 05 18:47 UTC--2018-07-05T18-47-35.049413162Z--00d631971be081c4de18fb6fca0c2723782299f7
Una vez se han creado las cuentas necesarias, se define el bloque de génesis con algunas cuentas tomando como ejemplo
el documento de Quorum.
A modo ilustrativo y divulgativo, se muestra la alternativa del segundo método con la creación de cuentas con un nodo activo con la interacción con la consola Javascript de geth y que requerirá el borrado de la cadena de bloques. Estos pasos son opcionales. Al iniciarse el nodo, muestra la conocida alerta de que no hay cuentas.
osboxes@osboxes:~/Desktop/giveliback$ geth --config config.toml
INFO [07-05|18:49:46] Starting peer-to-peer node instance=Geth/v1.7.2-stable-df4267a2/linux-amd64/go1.10
INFO [07-05|18:49:46] Allocated cache and file handles database=/home/osboxes/Desktop/giveliback/qdata/node1/geth/chaindata cache=128 handles=1024
INFO [07-05|18:49:46] Writing default main-net genesis block
INFO [07-05|18:49:47] Initialised chain configuration config="{ChainID: 1 Homestead: 1150000 DAO: 1920000 DAOSupport: true EIP150: 2463000 EIP155: 2675000 EIP158: 2675000 Byzantium: 4370000 IsQuorum: false Engine: ethash}"
INFO [07-05|18:49:47] Disk storage enabled for ethash caches dir=/home/osboxes/Desktop/giveliback/qdata/node1/geth/ethash count=3
INFO [07-05|18:49:47] Disk storage enabled for ethash DAGs dir=/home/osboxes/.ethash count=2
INFO [07-05|18:49:47] Initialising Ethereum protocol versions="[63 62]" network=1
INFO [07-05|18:49:47] Loaded most recent local header number=0 hash=d4e567…cb8fa3 td=17179869184
INFO [07-05|18:49:47] Loaded most recent local full block number=0 hash=d4e567…cb8fa3 td=17179869184
INFO [07-05|18:49:47] Loaded most recent local fast block number=0 hash=d4e567…cb8fa3 td=17179869184
INFO [07-05|18:49:47] Regenerated local transaction journal transactions=0 accounts=0
INFO [07-05|18:49:47] Starting P2P networking
INFO [07-05|18:49:47] HTTP endpoint opened: http://0.0.0.0:22000
INFO [07-05|18:49:47] RLPx listener up self="enode://7b09227fe9bd9596708e455355f6e8b183910b8275b18d56c3a105f7053688d1e9a4e39cad334f9041f0c26b16d3c5bac23c8740da55661bf15873d66ba223fe@[::]:21000?discport=0"
INFO [07-05|18:49:47] IPC endpoint opened: /home/osboxes/Desktop/giveliback/qdata/node1/geth.ipc
Con otro terminal se realiza una conexión al nodo activo y en marcha mediante IPC (Inter-process Communications). Dicha sesión requiere de acceso a los valores del $PATH definidos anteriormente para poder acceder a los binarios de go y geth. Se puede conectar al nodo local también por http://ip:puerto o ws://ip:puerto.
La creación de cuentas se realiza a través del módulo personal (
personal.newAccount()) que recibe como dirección
0x3b6927fe4a4a4d44c3445292d375542cf299661c
aunque sin ethers en dicha cuenta ni en las cuatro creadas anteriormente a la espera del bloque génesis. Para salir de la consola se usa el comando exit.
osboxes@osboxes:~$ geth attach ipc:/home/osboxes/Desktop/giveliback/qdata/node1/geth.ipc
Welcome to the Geth JavaScript console!
instance: Geth/v1.7.2-stable-df4267a2/linux-amd64/go1.10
coinbase: 0x3b6927fe4a4a4d44c3445292d375542cf299661c
at block: 0 (Thu, 01 Jan 1970 01:00:00 CET)
datadir: /home/osboxes/Desktop/giveliback/qdata/node1
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> eth.accounts
["0x3b6927fe4a4a4d44c3445292d375542cf299661c", "0x513f15ec9fc190cbc2ac25c6d6acdb58253f80d7", "0x5030a651df562c629cfc92928210a51d2e688d6d", "0x00d631971be081c4de18fb6fca0c2723782299f7"]
> personal.newAccount()
Passphrase:
Repeat passphrase:
"fafcf76cd2dfb68425475b6a42c23a7bb97ce8ba"
> eth.accounts
["0x3b6927fe4a4a4d44c3445292d375542cf299661c", "0x513f15ec9fc190cbc2ac25c6d6acdb58253f80d7", "0x5030a651df562c629cfc92928210a51d2e688d6d", "0x00d631971be081c4de18fb6fca0c2723782299f7", "fafcf76cd2dfb68425475b6a42c23a7bb97ce8ba"]
> eth.getBalance(eth.coinbase)
0
> exit
osboxes@osboxes:~$
En la versión 2 de Quorum la API para quorum ya no está disponibe y, por ende, la funcionalidad de privateFor para transacciones privadas. Es por eso que en el listado de módulos no aparece 'quorum:1.0' como debiera y genera un error al invocar 'privateFor' en las transacciones.
En este segundo método, para la generación del bloque génesis, se necesita borrar el contenido de los directorios creados de la cadena de bloque y de los nodos. Parando el servicio del nodo y borrando la base de datos, el nodo se inicializará de nuevo.
osboxes@osboxes:~/Desktop/giveliback$ ls -la qdata/node1
total 16
drwx------ 4 osboxes osboxes 4096 jul 5 18:50 .
drwx------ 12 osboxes osboxes 4096 jul 5 18:50 ..
drwx------ 3 osboxes osboxes 4096 jul 5 18:50 geth
drwx------ 2 osboxes osboxes 4096 jul 5 18:46 keystore
osboxes@osboxes:~/Desktop/giveliback$ ls -la qdata/node1/geth/
total 16
drwx------ 3 osboxes osboxes 4096 jul 5 18:46 .
drwx------ 4 osboxes osboxes 4096 jul 5 18:47 ..
drwxr-xr-x 2 osboxes osboxes 4096 jul 5 18:46 chaindata
-rw-r--r-- 1 osboxes osboxes 0 jul 3 18:46 LOCK
-rw------- 1 osboxes osboxes 64 jul 3 18:46 nodekey
-rwxr-xr-x 1 osboxes osboxes 0 jul 3 18:46 transactions.rlp
osboxes@osboxes:~/Desktop/giveliback$rm -rf qdata/node1/geth
osboxes@osboxes:~/Desktop/giveliback$
A partir de este momento, el nodo está en las mismas condiciones que si se hubiera usado sólo el primer método de creación de cuentas.
Se han creado cinco cuentas (wallets) en al directorio /node1/keystore que coinciden con los nombres de los archivos (uno por cuenta) y que se definirán en el archivo de génesis.
osboxes@osboxes:~$ ls -la /home/osboxes/Desktop/giveliback/qdata/node1/keystore/
total 28
drwx------ 2 osboxes osboxes 4096 jul 05 18:46 .
drwx------ 4 osboxes osboxes 4096 jul 05 18:47 ..
-rw------- 1 osboxes osboxes 491 jul 05 18:46 UTC--2018-07-05T18-46-07.617126785Z--3b6927fe4a4a4d44c3445292d375542cf299661c
-rw------- 1 osboxes osboxes 491 jul 05 18:47 UTC--2018-07-05T18-47-06.750007367Z--513f15ec9fc190cbc2ac25c6d6acdb58253f80d7
-rw------- 1 osboxes osboxes 491 jul 05 18:47 UTC--2018-07-05T18-47-20.325374470Z--5030a651df562c629cfc92928210a51d2e688d6d
-rw------- 1 osboxes osboxes 491 jul 05 18:47 UTC--2018-07-05T18-47-35.049413162Z--00d631971be081c4de18fb6fca0c2723782299f7
-rw------- 1 osboxes osboxes 491 jul 05 12:42 UTC--2018-07-05T18-50-39.250076751Z--fafcf76cd2dfb68425475b6a42c23a7bb97ce8ba
Bloque génesis
Se procede a la definición del bloque de génesis con algunas cuentas tomando como ejemplo el documento de Quorum.
En el fichero genesis.json se definen las cuentas, sus balances así como la operativa de la cadena de bloques.
Al estar presentes los ficheros de las cuentas en el directorio keystore, se asignarán los fondos según el fichero de configuración. La salida se guarda en un nuevo archivo de log ( node1.log).
osboxes@osboxes:~/Desktop/giveliback$ geth --datadir qdata/node1 init genesis.json 2>>qdata/logs/node1.log
El resultado de la ejecución anterior confirma la creación de bloque inicial.
INFO [07-05|18:54:18] Allocated cache and file handles database=/home/osboxes/Desktop/giveliback/qdata/node1/geth/chaindata cache=16 handles=16
INFO [07-05|18:54:18] Writing custom genesis block
INFO [07-05|18:54:18] Successfully wrote genesis state database=chaindata hash=64e3f2…8aeb0e
INFO [07-05|18:54:18] Allocated cache and file handles database=/home/osboxes/Desktop/giveliback/qdata/node1/geth/lightchaindata cache=16 handles=16
INFO [07-05|18:54:18] Writing custom genesis block
INFO [07-05|18:54:18] Successfully wrote genesis state database=lightchaindata
Levantando el nodo de nuevo una vez se ha escrito el bloque génesis.
osboxes@osboxes:~/Desktop/giveliback$ geth --config config.toml 2>>qdata/logs/node1.log
Muestra en el log:
INFO [07-05|19:00:42] Starting peer-to-peer node instance=Geth/v1.7.2-stable-df4267a2/linux-amd64/go1.10
INFO [07-05|19:00:42] Allocated cache and file handles database=/home/osboxes/Desktop/giveliback/qdata/node1/geth/chaindata cache=128 handles=1024
WARN [07-05|19:00:42] Upgrading database to use lookup entries
INFO [07-05|19:00:42] Initialised chain configuration config="{ChainID: 10 Homestead: <nil> DAO: <nil> DAOSupport: false EIP150: 1 EIP155: 0 EIP158: 1 Byzantium: 1 IsQuorum: true Engine: unknown}"
INFO [07-05|19:00:42] Disk storage enabled for ethash caches dir=/home/osboxes/Desktop/giveliback/qdata/node1/geth/ethash count=3
INFO [07-05|19:00:42] Disk storage enabled for ethash DAGs dir=/home/osboxes/.ethash count=2
INFO [07-05|19:00:42] Initialising Ethereum protocol versions="[63 62]" network=1
INFO [07-05|19:00:42] Loaded most recent local header number=0 hash=64e3f2…8aeb0e td=0
INFO [07-05|19:00:42] Loaded most recent local full block number=0 hash=64e3f2…8aeb0e td=0
INFO [07-05|19:00:42] Loaded most recent local fast block number=0 hash=64e3f2…8aeb0e td=0
INFO [07-05|19:00:42] Regenerated local transaction journal transactions=0 accounts=0
INFO [07-05|19:00:42] Starting P2P networking
INFO [07-05|19:00:42] HTTP endpoint opened: http://0.0.0.0:22000
INFO [07-05|19:00:42] Database deduplication successful deduped=0
INFO [07-05|19:00:42] RLPx listener up self="enode://97df36859bcce4b644464f748b29dc433fa3bc142d2e00fe29834758d82576db6933ec1af1f92bbb5dcee5a5891a3124a7f32faf2657f62630ddf75bf9194ddf@[::]:21000?discport=0"
INFO [07-05|19:00:42] IPC endpoint opened: /home/osboxes/Desktop/giveliback/qdata/node1/geth.ipc
La cadena de bloques se ha identificado como 10 para diferenciarla del resto de redes existentes y, por lo tanto, por defecto convertirse en una red privada identificándose como Quorum y prescindiendo de muchas de las características de los nodos públicos.
Accediendo de nuevo a la consola de Javascript de geth en otro terminal, éstas no están a cero.
osboxes@osboxes:~$ geth attach ipc:/home/osboxes/Desktop/giveliback/qdata/node1/geth.ipc
Welcome to the Geth JavaScript console!
instance: Geth/v1.7.2-stable-df4267a2/linux-amd64/go1.10
coinbase: 0x3b6927fe4a4a4d44c3445292d375542cf299661c
at block: 0 (Thu, 01 Jan 1970 01:00:00 CET)
datadir: /home/osboxes/Desktop/giveliback/qdata/node1
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
> eth.accounts
["0x3b6927fe4a4a4d44c3445292d375542cf299661c", "0x513f15ec9fc190cbc2ac25c6d6acdb58253f80d7", "0x5030a651df562c629cfc92928210a51d2e688d6d", "0x00d631971be081c4de18fb6fca0c2723782299f7", "0xfafcf76cd2dfb68425475b6a42c23a7bb97ce8ba"]
> eth.getBalance(eth.coinbase)
1e+27
> web3.fromWei(eth.getBalance(eth.coinbase),"ether")
1000000000
Se dispone de un nodo con cinco cuentas con suficientes fondos. Se para el nodo para realizar la configuración del consenso. En el terminal al parar el proceso con Ctrl+C emite las líneas de salida en el log.
INFO [07-05|19:01:56] Got interrupt, shutting down...
INFO [07-05|19:01:56] HTTP endpoint closed: http://0.0.0.0:22000
INFO [07-05|19:01:56] IPC endpoint closed: /home/osboxes/Desktop/giveliback/qdata/node1/geth.ipc
INFO [07-05|19:01:56] Blockchain manager stopped
INFO [07-05|19:01:56] Stopping Ethereum protocol
INFO [07-05|19:01:56] Ethereum protocol stopped
INFO [07-05|19:01:56] Transaction pool stopped
INFO [07-05|19:01:56] Database closed database=/home/osboxes/Desktop/giveliback/qdata/node1/geth/chaindata
Consenso
Quorum permite la configuración del consenso basándose en RAFT como Istanbul BFT .
En los despliegues con RAFT uno de los nodos de la red se elige como nodo líder. El nodo líder es el que gestiona las peticiones y coordina al resto de nodos. En caso de que no esté disponible el nodo líder, se elige otro de entre los nodos disponibles. Como ventajas, RAFT permite la creación de bloques bajo demanda y aumenta la velocidad de generación de bloques al estar enfocado a trnsacciones.
Istanbul BFT (Istanbul byzantine fault tolerant consensus protocol),realizado por AMIS , está inspirado en PBFT (Practical byzantine fault tolerant consensus protocol) de Miguel Castro y Barbara Liskov y también está enfocado a transacciones.
Los nodos permisionados serán aquellos que tengan acceso a la red y se comuniquen con sus nodos. Se dispone del primer nodo, con lo que sería posible editar el archivo permissioned-nodes.json para asignarle los valores del nodo. Ese mismo archivo es el que se asignará al nodo (node1) como static-nodes.json para el consenso basado en RAFT.
La identificación del nodo es
enode://97df36859bcce4b644464f748b29dc433fa3bc142d2e00fe29834758d82576db6933ec1af1f92bbb5dcee5a5891a3124a7f32faf2657f62630ddf75bf9194ddf@[::]:21000&discport=0
Esa identificación del nodo será usada para la gestión de nodos conformantes de la red. El listado de nodos contempla actualmente sólo el que se ha configurado en el array añadiéndole el puerto dónde se comunicará por RAFT (
&raftport=50401
).
[
"enode://97df36859bcce4b644464f748b29dc433fa3bc142d2e00fe29834758d82576db6933ec1af1f92bbb5dcee5a5891a3124a7f32faf2657f62630ddf75bf9194ddf@0.0.0.0:21000?discport=0&raftport=50401"
]
Se incluye este array en el archivo permissioned-nodes.json. Se pone una copia de permissioned-nodes.json y de static-nodes.json antes de la ejecución del nodo con RAFT. Los parámetros que se le añaden a la ejecución del nodo son relativos a la configuración de RAFT.
osboxes@osboxes:~/Desktop/giveliback$ cp permissioned-nodes.json qdata/node1/static-nodes.json
osboxes@osboxes:~/Desktop/giveliback$ cp permissioned-nodes.json qdata/node1
osboxes@osboxes:~/Desktop/giveliback$ geth --datadir=qdata/node1 --raft --emitcheckpoints --raftport 50401 --unlock 0 --password password.txt --config config.toml 2>>qdata/logs/node1.log
Al iniciar de nuevo el nodo con la configuración RAFT, éste se convierte en MINTER al no haber más nodos y finalmente desbloquea la primera cuenta.
INFO [07-05|19:09:28] Starting peer-to-peer node instance=Geth/v1.7.2-stable-df4267a2/linux-amd64/go1.10
INFO [07-05|19:09:28] Allocated cache and file handles database=/home/osboxes/Desktop/giveliback/qdata/node1/geth/chaindata cache=128 handles=1024
INFO [07-05|19:09:28] Initialised chain configuration config="{ChainID: 10 Homestead: DAO: DAOSupport: false EIP150: 1 EIP155: 0 EIP158: 1 Byzantium: 1 IsQuorum: true Engine: unknown}"
INFO [07-05|19:09:28] Disk storage enabled for ethash caches dir=/home/osboxes/Desktop/giveliback/qdata/node1/geth/ethash count=3
INFO [07-05|19:09:28] Disk storage enabled for ethash DAGs dir=/home/osboxes/.ethash count=2
INFO [07-05|19:09:28] Initialising Ethereum protocol versions="[63 62]" network=1
INFO [07-05|19:09:28] Loaded most recent local header number=0 hash=64e3f2…8aeb0e td=0
INFO [07-05|19:09:28] Loaded most recent local full block number=0 hash=64e3f2…8aeb0e td=0
INFO [07-05|19:09:28] Loaded most recent local fast block number=0 hash=64e3f2…8aeb0e td=0
INFO [07-05|19:09:28] Loaded local transaction journal transactions=0 dropped=0
INFO [07-05|19:09:28] Regenerated local transaction journal transactions=0 accounts=0
INFO [07-05|19:09:28] Starting P2P networking
INFO [07-05|19:09:28] starting raft protocol handler
INFO [07-05|19:09:28] loaded the latest applied index lastAppliedIndex=0
INFO [07-05|19:09:28] replaying WAL
INFO [07-05|19:09:28] RLPx listener up self="enode://97df36859bcce4b644464f748b29dc433fa3bc142d2e00fe29834758d82576db6933ec1af1f92bbb5dcee5a5891a3124a7f32faf2657f62630ddf75bf9194ddf@[::]:21000?discport=0"
INFO [07-05|19:09:28] loading WAL term=0 index=0
INFO [07-05|19:09:28] startRaft raft ID=1
INFO [07-05|19:09:28] starting a new raft log initial cluster size of=1
raft2018/07/05 19:09:28 INFO: 1 became follower at term 0
raft2018/07/05 19:09:28 INFO: newRaft 1 [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0]
raft2018/07/05 19:09:28 INFO: 1 became follower at term 1
INFO [07-05|19:09:28] IPC endpoint opened: /home/osboxes/Desktop/giveliback/qdata/node1/geth.ipc
INFO [07-05|19:09:28] HTTP endpoint opened: http://0.0.0.0:22000
INFO [07-05|19:09:28] ignoring expected ConfChangeAddNode for initial peer raft id=1
INFO [07-05|19:09:28] start snapshot applied index=0 last snapshot index=0
INFO [07-05|19:09:28] compacted log index=0
INFO [07-05|19:09:28] persisted the latest applied index index=1
raft2018/07/05 19:09:29 INFO: 1 is starting a new election at term 1
raft2018/07/05 19:09:29 INFO: 1 became candidate at term 2
raft2018/07/05 19:09:29 INFO: 1 received MsgVoteResp from 1 at term 2
raft2018/07/05 19:09:29 INFO: 1 became leader at term 2
raft2018/07/05 19:09:29 INFO: raft.node: 1 elected leader 1 at term 2
INFO [07-05|19:09:29] persisted the latest applied index index=2
INFO [07-05|19:09:29] QUORUM-CHECKPOINT name=BECAME-MINTER
INFO [07-05|19:09:29] Not minting a new block since there are no pending transactions
INFO [07-05|19:09:37] Unlocked account address=0x3b6927fe4A4A4D44C3445292d375542CF299661C
En otro terminal se observa que no hay otros nodos conectados mediante admin.peers.
osboxes@osboxes:~$ geth attach ipc:/home/osboxes/Desktop/giveliback/qdata/node1/geth.ipc
Welcome to the Geth JavaScript console!
instance: Geth/v1.7.2-stable-df4267a2/linux-amd64/go1.10
coinbase: 0x3b6927fe4a4a4d44c3445292d375542cf299661c
at block: 0 (Thu, 01 Jan 1970 01:00:00 CET)
datadir: /home/osboxes/Desktop/giveliback/qdata/node1
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 raft:1.0 rpc:1.0 txpool:1.0 web3:1.0
> admin.peers
[]
Constelaciones
Las constelaciones son gestores de transacciones cuya función principal es implementar el "motor de privacidad" en Quorum. Está escrito en Haskell , lanza un daemon o servicio que implementa una red P2P. Descrubre automáticamente otros nodos en la red después de sincronizar con otro host. Sincroniza un directorio de claves públicas asignadas a los hosts receptores con otros nodos en la red para asegurar la privacidad. Expone una API pública que permite a otros nodos enviar cadenas de bytes encriptadas a su nodo y sincronizar, recuperando información sobre los nodos que su nodo conoce. También expone una API privada que permite el cifrado de la información a transmitir. Admite backends de almacenamiento como LevelDB, BerkeleyDB y SQLite.
Quorum Constellation Diagram - Credit Quorum
Los pasos siguientes, pues, son los de instalación y configuración de la constelación. Para Ubuntu se necista la presencia de varias aplicaciones. Las constelaciones compiladas están publicadas en el repositorio, siendo la más reciente la 0.3.2.. Una vez descomprimida, los binarios se copian al directorio quorum_bin junto con geth, bootnode y demás. La generación de las claves (pública y privada) requiere de una contraseña que se puede dejar vacía. En este caso es 'password' igual que la usada en las cuentas y disponible en password.txt. En caso de haber usado una contraseña, es posible que la ejecución se demore.
Las claves se colocan en el directorio de ejecución de la constelación del nodo1 ( qdata/node1) y deben protegerse contra accesos no deseados. Se hace lo mismo con la contraseña usada ( password.txt) para su desbloqueo al instanciar la constelación.
Para levantar la constelación, se pueden pasar los parámetros en el mismo comando o bien usando un archivo de configuración con una estructura como la del ejemplo de Quorum.
osboxes@osboxes:~/Desktop/giveliback$ apt-get install libdb-dev libleveldb-dev libsodium-dev zlib1g-dev libtinfo-dev
...
osboxes@osboxes:~/Desktop/giveliback$ wget https://github.com/jpmorganchase/constellation/releases/download/v0.3.2/constellation-0.3.2-ubuntu1604.tar.xz ... (giveliback) osboxes@osboxes:~/Desktop/giveliback$ tar -xf constellation-0.3.2-ubuntu1604.tar.xz (giveliback) osboxes@osboxes:~/Desktop/giveliback$ cp constellation-0.3.2-ubuntu1604/constellation-node quorum_bin
osboxes@osboxes:~/Desktop/giveliback$ tar -xf constellation-0.3.2-ubuntu1604.tar.xz
osboxes@osboxes:~/Desktop/giveliback$ cp constellation-0.3.2-ubuntu1604/constellation-node quorum_bin
osboxes@osboxes:~/Desktop/giveliback$ cd qdata/node1
osboxes@osboxes:~/Desktop/giveliback/qdata/node1$ constellation-node --generatekeys=node
Lock key pair node with password [none]: ********
osboxes@osboxes:~/Desktop/giveliback/qdata/node1$ ls -la node.*
-rw------- 1 osboxes osboxes 293 jul 05 19:11 node.key
-rw-rw-r-- 1 osboxes osboxes 44 jul 05 19:09 node.pub
osboxes@osboxes:~/Desktop/giveliback/qdata/node1$ head node.key
{"data":{"aopts":{"variant":"id","memory":1048576,"iterations":10,"parallelism":4,"version":"1.3"},"snonce":"0RpcpqkhDQr1KB/x0TLSKdt+mQhZoONR","asalt":"y9zT+03Ho3T3QLm/oQpPHhwO9mCxTsLe2BLGjvanhas=","sbox":"U63457+8Xx8OenKl4w9pfU6Vopynhdy1NQFGo1ImZPb7DLRD+I9/WuFoXDz9O7w+"},"type":"argon2sbox"}
osboxes@osboxes:~/Desktop/giveliback/qdata/node1$ head node.pub
soPCt8hAExYRgUouXLy59SiYGgxP3vj670PiAYx/wF4=
osboxes@osboxes:~/Desktop/giveliback/qdata/node1$ chmod 600 node.key
osboxes@osboxes:~/Desktop/giveliback/qdata/node1$ cd ../..
osboxes@osboxes:~/Desktop/giveliback$ cp password.txt qdata/node1
osboxes@osboxes:~/Desktop/giveliback$ constellation-node --url=https://127.0.0.1:9001/ --port=9001 --workdir=qdata/node1 --socket=constellation.ipc --publickeys=node.pub --privatekeys=node.key --othernodes=https://127.0.0.1:9001/ --password=password.txt 2>>qdata/logs/constellation1.log
Unlocking node.key
Unlocked node.key
Se debe instanciar la constelación en cada nodo y en este caso, el nodo 1 será el nodo de referencia. De igual manera que en la creación de las claves, la liberación de la clave puede tardar unos segundos.
En el archivo del log se aprecia que está en marcha y que ha generado certificados TLS.
19:10:40 [INFO] Log level is LevelWarn
19:11:53 [WARN] No TLS certificate or key found; generating tls-client-cert.pem/tls-client-key.pem
19:11:55 [WARN] No TLS certificate or key found; generating tls-server-cert.pem/tls-server-key.pem
Se deben proteger también estos archivos para otros usuarios así como se ha hecho con la llave del nodo.
osboxes@osboxes:~/Desktop/giveliback$ chmod 600 qdata/node1/*.pem
En el directorio de la constelación del nodo 1 se aprecian los archivos creados para los certificados TLS así como el ipc para la conexión del mismo.
osboxes@osboxes:~/Desktop/giveliback$ ls -la qdata/node1/
total 44
drwxrwxr-x 3 osboxes osboxes 4096 jul 05 19:10 .
drwx------ 6 osboxes osboxes 4096 jul 05 19:13 ..
...
srw------- 1 osboxes osboxes 0 jul 05 19:11 constellation.ipc
-rw------- 1 osboxes osboxes 293 jul 05 19:11 node.key
-rw-rw-r-- 1 osboxes osboxes 44 jul 05 19:11 node.pub
drwxrwxr-x 3 osboxes osboxes 4096 jul 05 19:11 storage
-rw-rw-r-- 1 osboxes osboxes 1887 jul 05 19:12 tls-client-cert.pem
-rw------- 1 osboxes osboxes 3243 jul 05 19:12 tls-client-key.pem
-rw-rw-r-- 1 osboxes osboxes 19 jul 05 19:11 tls-known-clients
-rw-rw-r-- 1 osboxes osboxes 19 jul 05 19:11 tls-known-servers
-rw-rw-r-- 1 osboxes osboxes 1887 jul 05 19:12 tls-server-cert.pem
-rw------- 1 osboxes osboxes 3243 jul 05 19:12 tls-server-key.pem
Levantando el nodo1 estaría la configuración completa del nodo. Para poder comprobar el correcto funcionamiento de la red Quorum, se crean un par de nodos más siguiendo las instrucciones anteriores. Todos los nodos compartirán cierta información como son las cuentas, los nodos permitidos y los nodos estáticos. Esos ficheros de configuración, pues, deberán estar presentes en todas las instancias. Las cuentas (wallets) y certificados, serán exclusivos de cada nodo y por lo tanto generados exprofeso para cada uno. Así pues, las cuentas existentes en el bloque genesis estarán físicamente en diferentes nodos.
Publicado del blog de ibón: https://ibón.es/2018/07/06/despliegue-de-web-dapp-con-quorumangularpythonflask-en-un-vps-con-ubuntu-16-04/
Hi! I am a robot. I just upvoted you! I found similar content that readers might be interested in:
https://xn--ibn-hna.es/2018/07/06/despliegue-de-web-dapp-con-quorumangularpythonflask-en-un-vps-con-ubuntu-16-04/
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
✅ @nosoccomtothom, I gave you an upvote on your post! Please give me a follow and I will give you a follow in return and possible future votes!
Thank you in advance!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit