
Si necesita implementar una red privada de Ethereum basada en Geth, esto puede hacerse, por ejemplo, creando nodos de red en servidores físicos o máquinas virtuales. Sin embargo, es mucho más fácil usar contenedores Geth desde el repositorio de Docker Hub. En este caso, puede instalar una red completa de nodos, incluso en una máquina virtual o en un servidor físico.
En este artículo le diremos cómo instalar Docker en un servidor que ejecuta Debian 9 (virtual o físico), cómo crear varios contenedores con Geth en ejecución y combinarlos en una red privada. Le daremos un script de ejemplo para Node.js que accede a los nodos Geth que funcionan en contenedores.
Instalar Docker
La instalación de Docker se describe en el sitio web oficial. Para Debian 9 y 10, encontrará instrucciones detalladas en
https://docs.docker.com/install/linux/docker-ce/debian/ .
Instalar DockerEn primer lugar, actualice los paquetes:
Luego, instale los paquetes necesarios con el siguiente comando:
Agregue la clave GPG oficial:
Asegúrese de obtener la clave con la huella digital 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88:
Agregue un repositorio estable de Docker:
Actualice los paquetes e instale Docker:
Ahora solo queda verificar que todo esté hecho correctamente. Para hacer esto, ejecute la imagen (Imagen) hello-world:
Este comando descargará la imagen deseada y la ejecutará para su ejecución. Como era de esperar, verá el mensaje "¡Hola desde Docker!" En la consola.
Como puedes ver, ¡nada complicado! Ahora puede comenzar a crear una red privada Geth con nodos que se ejecutan en contenedores.
Crea usuarios, directorios y archivos
Cree un libro en el servidor del usuario y los siguientes subdirectorios en su directorio de inicio:
/home/book/dock-test /home/book/dock-test/distr
A continuación, en el directorio / home / book / dock-test, cree un Dockerfile:
Listado 1. File / home / book / dock-test / Dockerfile FROM ubuntu:16.04 LABEL version="1.0" LABEL maintainer="alexandre@frolov.pp.ru" ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install --yes software-properties-common RUN add-apt-repository ppa:ethereum/ethereum RUN apt-get update && apt-get install --yes geth RUN adduser --disabled-login --gecos "" eth_book COPY distr /home/eth_book/distr RUN chown -R eth_book:eth_book /home/eth_book/distr USER eth_book WORKDIR /home/eth_book RUN geth --nousb init distr/genesis.json ENTRYPOINT bash
Este archivo se usará al crear contenedores Docker.
También deberá crear el archivo /home/book/dock-test/distr/genesis.json, necesario para inicializar los nodos de red Ethereum:
Listado 2. Archivo /home/book/dock-test/distr/genesis.json { "config": { "chainId": 98760, "homesteadBlock": 0, "eip150Block": 0, "eip155Block": 0, "eip158Block": 0 }, "difficulty": "10", "gasLimit": "5100000", "alloc": {} }
Aquí configuramos el identificador de nuestra red privada en 98760. Para facilitar la extracción, especificamos 10 en el parámetro de dificultad, lo que nos permitirá trabajar en máquinas virtuales con una cantidad relativamente pequeña de memoria (por ejemplo, 4 GB).
Crear una red y contenedores
Para que nuestros nodos intercambien datos entre sí, crearemos una red entre contenedores:
A continuación, debe crear el directorio actual / home / book / dock-test, en el que se encuentra el Dockerfile. Luego cree el número requerido de contenedores, por ejemplo, tres:
Crear el primer contenedor lleva un tiempo relativamente largo, porque Necesitas descargar las imágenes necesarias. Pero los siguientes contenedores se crean casi instantáneamente: compárelos con la velocidad de crear máquinas virtuales, incluso a través de la clonación.
Ahora abra las cuatro ventanas de la consola. En tres de ellos, trabajaremos con contenedores, y en el cuarto, recibiremos los datos que necesitamos sobre contenedores y la red.
En la primera ventana de consola, emita el siguiente comando:
Verá un mensaje como:
eth_book@304bf4f09063:~$
En las ventanas de la segunda y tercera consola, ingrese los siguientes comandos, respectivamente:
Creación de nodos y cuentas de red privada de Ethereum
Por el momento, tenemos tres contenedores con Geth. Creemos en cada uno de ellos el nodo de nuestra red y cuenta privada de Ethereum.
Ingrese el comando en las tres primeras ventanas de la consola:
$ geth account new
Necesitará ingresar una contraseña. Para simplificar, use la misma contraseña en cada nodo para las pruebas, pero escríbala en alguna parte. Si olvida la contraseña, no funcionará de ninguna manera para recuperarse.
Después de crear las cuentas en la consola, aparecerán direcciones de clave pública similares a estas:
Public address of the key: 0xc5Df10a76Bb559332c385F8cA789C0F37dD77A54 Public address of the key: 0x0C976006a5762779bA36AC590D1D8Ebac1Ca2981 Public address of the key: 0xaB627feab4e962222a3333F3b09182dF68bB9422
Guarde las direcciones (tendrá otras), como los necesitamos para ejecutar los nodos.
Ahora necesita comenzar la inicialización de los nodos. Esto se hace usando el comando:
$ geth --nousb init distr/genesis.json
Ingrese este comando en todas las ventanas de consola de nuestros contenedores. La opción --nousb deshabilita todas las comunicaciones con dispositivos USB.
Ejecución de nodos geth
Ahora abra cada una de las ventanas de la consola y ejecute Geth usando los comandos a continuación.
Primera ventana:
$ geth --identity="Node01" --etherbase "0xc5Df10a76Bb559332c385F8cA789C0F37dD77A54" --mine --minerthreads 1 --verbosity 3 --networkid 98760 --rpc --rpcaddr 127.0.0.1 --nousb --rpcapi="db,eth,net,web3,personal,web3" console
Segunda ventana:
$ geth --identity="Node02" --etherbase "0x0C976006a5762779bA36AC590D1D8Ebac1Ca2981" --mine --minerthreads 1 --verbosity 3 --networkid 98760 --rpc --rpcaddr 127.0.0.1 --rpcport=8546 --nousb --rpcapi="db,eth,net,web3,personal,web3" console
Tercera ventana:
$ geth --identity="Node03" --etherbase "0xaB627feab4e962222a3333F3b09182dF68bB9422" --mine --minerthreads 1 --verbosity 3 --networkid 98760 --rpc --rpcaddr 127.0.0.1 --rpcport=8547 --nousb --rpcapi="db,eth,net,web3,personal,web3" console
En cada una de las ventanas abiertas, aparecerán mensajes sobre la generación de DAG:
… INFO [12-19|17:57:44.072] Generating DAG in progress epoch=0 percentage=34 elapsed=29.740s INFO [12-19|17:57:44.898] Generating DAG in progress epoch=0 percentage=35 elapsed=30.566s INFO [12-19|17:57:45.671] Generating DAG in progress epoch=0 percentage=36 elapsed=31.339s …
Espere hasta que se complete la generación. Después de eso, eth.hashrate y eth.blockNumber serán diferentes de 0:
> eth.hashrate 4 > eth.blockNumber 2
Puede consultar el saldo de la cuenta corriente de la siguiente manera:
> web3.fromWei( eth.getBalance(eth.coinbase) )
Para que no le molesten los mensajes sobre la creación de nuevos bloques y otros mensajes en las ventanas de la consola, salga de Geth con el comando de salida y reinicie nuevamente con el parámetro de verbosidad establecido en 1.
Nodos de red
Para comenzar, veremos la lista de contenedores en ejecución. Emita el siguiente comando desde la cuarta ventana de la consola:
Aquí, para cada contenedor, se muestran su identificador, nombre de imagen, nombre del contenedor y otra información.
Para unir contenedores en una red, necesitará las direcciones IP de los contenedores en nuestra red privada PRIVATENET. Puede obtener estas direcciones por ID de contenedor, por ejemplo, de la siguiente manera:
También puede utilizar el comando de inspección de red de Docker PRIVATENET:
red de docker inspeccionar PRIVATENET [ { "Name": "PRIVATENET", "Id": "576ec7edba5b4c228740deaf7fabb5e2ba003d310086153dd7f15e2c7de0c1b2", "Created": "2019-12-20T11:52:07.90695857+03:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.21.0.0/16", "Gateway": "172.21.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "49a028744b4b6073f6dbca23e78625bc58fc0cdacadec7cded4bb0e888c7e37b": { "Name": "reverent_wescoff", "EndpointID": "11006b596b5a46df9bf9f95a9456784795d333a3e6901b15bd2db746fd4b5513", "MacAddress": "02:42:ac:15:00:03", "IPv4Address": "172.21.0.3/16", "IPv6Address": "" }, "5a9ade2947ebd8e55594ede9763aac71f5e6529c03e762ef723adb2c592c5ccd": { "Name": "clever_ellis", "EndpointID": "41ef69a0a93b5b1de495836028bac1742c303de92ffe42a0855ed32c93c28953", "MacAddress": "02:42:ac:15:00:02", "IPv4Address": "172.21.0.2/16", "IPv6Address": "" }, "fa70a54186185de01db3647e7333bf6c71250162fafefb78dbe9998e5ac93f34": { "Name": "gifted_curran", "EndpointID": "d368c032bc0886c27ad4895d1856e4f00cf1b25ce040f3b42393dbff778c18e5", "MacAddress": "02:42:ac:15:00:04", "IPv4Address": "172.21.0.4/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
Comparando los datos recibidos por estos comandos, haremos una lista de direcciones IP para nuestros contenedores:
node01 - 172.21.0.2 node02 - 172.21.0.3 node03 - 172.21.0.4
Por supuesto, tendrá una lista diferente, y cuando reinicie los contenedores, estas direcciones pueden cambiar.
Después de recibir la lista de direcciones, reinicie geth en todos los contenedores, especificando la dirección de su contenedor en el parámetro --rpcaddr. Por supuesto, puede establecer la dirección 0.0.0.0, pero esto es malo desde el punto de vista de la seguridad: cualquiera o cualquier cosa puede conectarse al nodo. Por ejemplo, pueden ser bots que intentan "retirar" todos los fondos de estos nodos, esperando que el nodo se desbloquee.
Para fusionar los nodos, deberá usar el comando admin.addPeer. Como parámetro de este comando, debe pasar la URL en formato enode. Obtenga esta URL para cada contenedor utilizando el comando admin.nodeInfo.enode:
> admin.nodeInfo.enode "enode://0a84e562c9b22e43269b7dca215cf2ed8c20bbf35da67bae8d5ee81b36d8bbb69e3ec704b9b6f7501059fe861843a836b2fbab641f36616cdd77365b1a522d5b@62.152.63.28:30303?discport=1350" "enode://ee49f69e25c068e006fec4a8d74370370b1d2be9715b86eddd99f97a3a5a9c692a265ab7d01fb36410d59c3f6e2b253a22f652ecbf1941eef0b3f1d30b19a535@62.152.63.28:30303?discport=1345" "enode://156d43648b47078439c7481e54f697bbf1c6b6e762029ba2969f1556ceb94e51ad03f8bd2bed35f466073165810600f52925d155f0fceef832ae86fc39a8c135@62.152.63.28:30303?discport=1348"
Direcciones recibidas guardar.
Para conectar un nodo a otro, abra la ventana de consola del primer nodo e ingrese el siguiente comando allí:
> admin.addPeer( "enode://0a84e562c9b22e43269b7dca215cf2ed8c20bbf35da67bae8d5ee81b36d8bbb69e3ec704b9b6f7501059fe861843a836b2fbab641f36616cdd77365b1a522d5b@172.21.0.3:30303")
Aquí pasamos la dirección URL, indicando en ella la dirección IP del host conectado. Siga el mismo procedimiento en otros nodos de red.
Para verificar que la conexión esté establecida, use el comando admin.peers. Si no hay conexiones, el comando devolverá un resultado vacío:
> admin.peers []
En nuestro caso, el comando muestra que el primer nodo con la dirección 172.21.0.2 está conectado a los nodos con las direcciones 172.21.0.3 y 172.21.0.4:
Ver el resultado cuando hay conexiones > admin.peers [{ caps: ["eth/63", "eth/64"], enode: "enode://156d43648b47078439c7481e54f697bbf1c6b6e762029ba2969f1556ceb94e51ad03f8bd2bed35f466073165810600f52925d155f0fceef832ae86fc39a8c135@172.21.0.4:30303", id: "4dac1d10cb6ae8bfc1fdebd3f5334b24ee62ec38a50bc92c89104cfc3251b5fc", name: "Geth/Node03/v1.9.9-stable-01744997/linux-amd64/go1.13.4", network: { inbound: false, localAddress: "172.21.0.2:40652", remoteAddress: "172.21.0.4:30303", static: true, trusted: false }, protocols: { eth: { difficulty: 98414119, head: "0x6b31a5bb9cde06fab5a8cc1ae9b18bada30de0d1b76cb3286c1081e76dbf5b83", version: 64 } } }, { caps: ["eth/63", "eth/64"], enode: "enode://ee49f69e25c068e006fec4a8d74370370b1d2be9715b86eddd99f97a3a5a9c692a265ab7d01fb36410d59c3f6e2b253a22f652ecbf1941eef0b3f1d30b19a535@172.21.0.3:30303", id: "b74277d278c15317fa7f7fa492daca60492ea22053bfc53281dd0071eba1c16b", name: "Geth/Node02/v1.9.9-stable-01744997/linux-amd64/go1.13.4", network: { inbound: false, localAddress: "172.21.0.2:42576", remoteAddress: "172.21.0.3:30303", static: true, trusted: false }, protocols: { eth: { difficulty: 99041423, head: "0x0ec44735bbb425cb8db96103f52300dfaae1147ba0e03aa4892d041250ce4408", version: 64 } } }]
Tenga en cuenta que después de que los nodos se combinen y sincronicen con éxito, el comando eth.blockNumber devolverá el mismo valor cuando se inicie en cualquiera de nuestros tres contenedores.
El comando web3.fromWei (eth.getBalance (eth.coinbase)), por el contrario, mostrará un equilibrio diferente en diferentes nodos, porque cada nodo tiene su propia cuenta.
Trabajar con hosts usando Node.js
En el Listado 3, presentamos un script simple que ejecuta Node.js que muestra en la consola una lista de cuentas para el nodo especificado y el saldo de cada uno de ellos:
Listado 3. Archivo / home / book / list_accounts.js var Web3 = require('web3') var web3 = new Web3(new Web3.providers.HttpProvider("http://172.21.0.2:8545")); web3.eth.getAccounts() .then(accList => { return accList; }) .then(function (accounts) { var balancePromeses = []; for(let i = 0; i < accounts.length; i++) { balancePromeses[i] = web3.eth.getBalance(accounts[i]); } Promise.all(balancePromeses).then(values => { for(let i = 0; i < values.length; i++) { console.log('Account: ', accounts[i], 'balance: ', values[i], 'wei, ', web3.utils.fromWei(values[i], 'ether'), 'ether'); } }); }) .catch(function (error) { console.error(error); });
Puede ejecutar esta secuencia de comandos por separado, por ejemplo, en la cuarta ventana de la consola:
Que sigue
El tema del desarrollo de software para las criptomonedas en general y para Ethereum en particular es bastante fascinante. Si después de leer este artículo tiene preguntas y desea saber más, lea mi libro
"Creación de contratos inteligentes de Solidez para la cadena de bloques Ethereum. Guía práctica " , que fue publicado por
Liters Publishing House.
También es posible que necesite una buena
hoja de trucos de Docker .
¡Le agradecería cualquier comentario y adiciones al artículo y al libro!