Después de ver en el primer capítulo la instalación de todas las herramientas básicas que iremos necesitando durante nuestra aventura, vamos a empezar con la puesta en marcha de un nodo Hornet para tener nuestra red shimmer local.
Hornet, es un software desarrollado por la Fundación IOTA, escrito en Go y es el nodo que implementa la funcionalidad completa de los últimos avances de la red, como es actualmente la actualización Stardust
.
Puesta en marcha del nodo Hornet local
Lo primero vamos a crear un espacio de trabajo para todos los ficheros de configuración de nuestra red privada.
~$ mkdir ~/iota-dev/private-network
dentro de ese directorio iremos creando todos los ficheros de configuración para poder tener nuestro nodo hornet operativo.
./config.json
Ese fichero contiene toda la configuración para nuestro nodo hornet, dejo por aquí el enlace a la wiki de iota con todos los parámetros de configuración posibles, también podemos hacer un hornet -h --full
y obtenemos un listado de todos los parámetros posibles actualizados.
{
"node": {
"alias": "ALVAROGAR DEV"
},
"protocol": {
"targetNetworkName": "alvarogar-dev",
"milestonePublicKeyCount": 2,
"baseToken": {
"name": "TestCoin",
"tickerSymbol": "TEST",
"unit": "TEST",
"subunit": "testies",
"decimals": 6,
"useMetricPrefix": false
},
"publicKeyRanges": [
{
"key": "ed3c3f1a319ff4e909cf2771d79fece0ac9bd9fd2ee49ea6c0885c9cb3b1248c",
"start": 0,
"end": 0
},
{
"key": "f6752f5f46a53364e2ee9c4d662d762a81efd51010282a75cd6bd03f28ef349c",
"start": 0,
"end": 0
}
]
},
"participation": {
"db": {
"path": "participationdb"
}
},
"db": {
"path": "privatedb"
},
"p2p": {
"db": {
"path": "p2pstore"
}
},
"snapshots": {
"fullPath": "snapshots/full_snapshot.bin",
"deltaPath": "snapshots/delta_snapshot.bin",
"downloadURLs": []
},
"restAPI": {
"publicRoutes": [
"/health",
"/api/*"
],
"protectedRoutes": [],
"pow": {
"enabled": true
}
}
}
./Dockerfile
Este fichero es el que se encarga de crear la imagen con todos los plugins de hornet, se pueden modificar las versiones de las imágenes usadas para hornet y los plugins inx.
FROM iotaledger/hornet:2.0.0-rc.4 AS hornet
FROM iotaledger/inx-indexer:1.0-rc AS indexer
FROM iotaledger/inx-faucet:1.0-rc AS faucet
FROM iotaledger/inx-dashboard:1.0-rc AS dashboard
FROM iotaledger/inx-mqtt:1.0-rc AS mqtt
FROM iotaledger/inx-spammer:1.0-rc AS spammer
FROM iotaledger/inx-coordinator:1.0-rc AS coordinator
FROM iotaledger/inx-poi:1.0-rc AS poi
FROM iotaledger/inx-participation:1.0-rc AS participation
FROM debian:11
# hornet-1 API
EXPOSE 14265/tcp
# hornet-1 dashboard
EXPOSE 8081/tcp
# hornet-1 INX
EXPOSE 9029/tcp
# faucet
EXPOSE 8091/tcp
RUN mkdir /app
WORKDIR /app
# Prepare supervisor
RUN apt update && apt install -y supervisor parallel
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Copy the inx apps dir into HORNET image
COPY --from=hornet /app /app/hornet-1
COPY --from=hornet /app /app/hornet-2
COPY --from=indexer /app /app/indexer
COPY --from=faucet /app /app/faucet
COPY --from=dashboard /app /app/dashboard
COPY --from=mqtt /app /app/mqtt
COPY --from=spammer /app /app/spammer
COPY --from=coordinator /app /app/coordinator
COPY --from=poi /app /app/poi
COPY --from=participation /app /app/participation
# Overwrite default config
COPY config.json /app/hornet-1/config.json
COPY config.json /app/hornet-2/config.json
# Create snapshots
COPY protocol_parameters.json /app/protocol_parameters.json
RUN mkdir /app/hornet-1/snapshots
RUN /app/hornet-1/hornet tool snap-gen \
--protocolParametersPath=/app/protocol_parameters.json \
--mintAddress=tst1qq2kvnu9pqzptkggrpqrvltvagccsh6aj2fkdhla7p3lrsy9dwhdzu5l2ye \
--outputPath=/app/hornet-1/snapshots/full_snapshot.bin
RUN cp -R /app/hornet-1/snapshots /app/hornet-2/
# Bootstrap network
RUN mkdir /app/coordinator/state
RUN COO_PRV_KEYS=651941eddb3e68cb1f6ef4ef5b04625dcf5c70de1fdc4b1c9eadb2c219c074e0ed3c3f1a319ff4e909cf2771d79fece0ac9bd9fd2ee49ea6c0885c9cb3b1248c,0e324c6ff069f31890d496e9004636fd73d8e8b5bea08ec58a4178ca85462325f6752f5f46a53364e2ee9c4d662d762a81efd51010282a75cd6bd03f28ef349c /app/hornet-1/hornet tool bootstrap-private-tangle \
--configFile=/app/hornet-1/config.json \
--snapshotPath=/app/hornet-1/snapshots/full_snapshot.bin \
--databasePath=/app/hornet-1/privatedb \
--cooStatePath=/app/coordinator/state/coordinator.state
CMD ["/usr/bin/supervisord"]
./protocol_parameters.json
Este fichero lo vamos a usar para generar un snapshot para la red privada mediante hornet tool snap-gen
. Si se ejecuta un nodo Hornet por primera vez, se necesita iniciarlo con una instantánea completa. Hornet la descarga automáticamente de fuentes de confianza. Para este caso vamos a generarla con la herramienta snap-gen
. más info
{
"version": 2,
"networkName": "alvarogar-dev",
"bech32HRP": "tst",
"minPoWScore": 0,
"belowMaxDepth": 15,
"rentStructure": {
"vByteCost": 500,
"vByteFactorData": 1,
"vByteFactorKey": 10
},
"tokenSupply": "2779530283277761"
}
./supervisord.conf
Este es el fichero de configuración para supervisor
, es un gestor de procesos que facilita el manejo de procesos en ejecución por largo tiempo, en este caso lo usamos para gestionar los logs e inicializar hornet y todos sus plugins.
[unix_http_server]
file=/var/run/supervisor.sock
[supervisord]
logfile=/var/log/supervisor/supervisord.log
logfile_maxbytes=50MB
logfile_backups=10
loglevel=error
pidfile=/var/run/supervisord.pid
user=root
nodaemon=true
minfds=8192
childlogdir=/var/log/supervisor/
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
[program:hornet-1]
command=/app/hornet-1/hornet -c config.json --p2p.bindMultiAddresses=/ip4/0.0.0.0/tcp/15600 --restAPI.bindAddress=0.0.0.0:14265 --p2p.identityPrivateKey=1f46fad4f538a031d4f87f490f6bca4319dfd0307636a5759a22b5e8874bd608f9156ba976a12918c16a481c38c88a7b5351b769adc30390e93b6c0a63b09b79 --p2p.peers=/ip4/127.0.0.1/tcp/15601/p2p/12D3KooWCKwcTWevoRKa2kEBputeGASvEBuDfRDSbe8t1DWugUmL --p2p.peerAliases=hornet-2 --inx.enabled=true --inx.bindAddress=0.0.0.0:9029
directory = /app/hornet-1
stdout_logfile=/var/log/supervisor/hornet-1.log
redirect_stderr=true
priority=1
[program:hornet-2]
command=/app/hornet-2/hornet -c config.json --p2p.bindMultiAddresses=/ip4/0.0.0.0/tcp/15601 --restAPI.bindAddress=0.0.0.0:14266 --p2p.identityPrivateKey=a06b288ce7fc3b6f1e716f6f7d72050b53417aae4b305a68883550a3bb28597f254b082515a79391a7f13009b4133851a0c4d48e0e948809c3b46ff3e2500b4f --p2p.peers=/ip4/127.0.0.1/tcp/15600/p2p/12D3KooWSagdVaCrS14GeJhM8CbQr41AW2PiYMgptTyAybCbQuEY --p2p.peerAliases=hornet-1
directory = /app/hornet-2
stdout_logfile=/var/log/supervisor/hornet-2.log
redirect_stderr=true
priority=2
[program:inx-coordinator]
command=/app/coordinator/inx-coordinator --coordinator.stateFilePath=state/coordinator.state --coordinator.interval=1s --coordinator.blockBackups.enabled=false
environment=COO_PRV_KEYS="651941eddb3e68cb1f6ef4ef5b04625dcf5c70de1fdc4b1c9eadb2c219c074e0ed3c3f1a319ff4e909cf2771d79fece0ac9bd9fd2ee49ea6c0885c9cb3b1248c,0e324c6ff069f31890d496e9004636fd73d8e8b5bea08ec58a4178ca85462325f6752f5f46a53364e2ee9c4d662d762a81efd51010282a75cd6bd03f28ef349c"
directory = /app/coordinator
stdout_logfile=/var/log/supervisor/inx-coordinator.log
redirect_stderr=true
priority=3
[program:inx-spammer]
command=/app/spammer/inx-spammer --spammer.autostart=true --spammer.bpsRateLimit=5
autorestart=true
startsecs=10
directory = /app/spammer
stdout_logfile=/var/log/supervisor/inx-spammer.log
redirect_stderr=true
priority=4
[program:inx-dashboard]
command=/app/dashboard/inx-dashboard --dashboard.bindAddress=0.0.0.0:8081 --dashboard.auth.passwordHash=577eb97f8faf2af47ff957b00827d6bfe9d05b810981e3073dc42553505282c1 --dashboard.auth.passwordSalt=e5d8d0bd3bb9723236177b4713a11580c55b69a51e7055dd11fa1dad3b8f6d6c
autorestart=true
startsecs=10
directory = /app/dashboard
stdout_logfile=/var/log/supervisor/inx-dashboard.log
redirect_stderr=true
priority=5
[program:inx-faucet]
command=/app/faucet/inx-faucet --faucet.bindAddress=0.0.0.0:8091 --faucet.amount=100000000000 --faucet.smallAmount=10000000000 --faucet.maxAddressBalance=200000000000 --faucet.rateLimit.enabled=false
environment=FAUCET_PRV_KEY="887844b1e6bf9ca9e0b57584656add4370dbb49a8cb79e2e3032229f30fd80359e3df559ad0de8e5fa019b9ea46d1ee40879f3f3f74594a3306de9dfd43dcd25"
autorestart=true
startsecs=10
directory = /app/faucet
stdout_logfile=/var/log/supervisor/inx-faucet.log
redirect_stderr=true
priority=6
[program:inx-indexer]
command=/app/indexer/inx-indexer
autorestart=true
startsecs=10
directory = /app/indexer
stdout_logfile=/var/log/supervisor/inx-indexer.log
redirect_stderr=true
priority=7
[program:inx-mqtt]
command=/app/mqtt/inx-mqtt
autorestart=true
startsecs=10
directory = /app/mqtt
stdout_logfile=/var/log/supervisor/inx-mqtt.log
redirect_stderr=true
priority=8
[program:inx-poi]
command=/app/poi/inx-poi
autorestart=true
startsecs=10
directory = /app/poi
stdout_logfile=/var/log/supervisor/inx-poi.log
redirect_stderr=true
priority=9
[program:inx-participation]
command=/app/participation/inx-participation
autorestart=true
startsecs=10
directory = /app/participation
stdout_logfile=/var/log/supervisor/inx-participation.log
redirect_stderr=true
priority=11
# This a workaround to label all the logs to be able to have
# a single log-stream in docker and know from which service it came
[program:hornet-logging]
command=parallel --tagstring "{/.}:" --line-buffer tail -f {} ::: hornet-1.log hornet-2.log inx-coordinator.log
user=root
directory=/var/log/supervisor/
startsecs=10
autostart=true
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
[program:inx-logging]
command=parallel --tagstring "{/.}:" --line-buffer tail -f {} ::: inx-indexer.log inx-spammer.log inx-faucet.log inx-mqtt.log inx-poi.log inx-participation.log
user=root
directory=/var/log/supervisor/
startsecs=10
autostart=true
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
./docker-compose.yml
Este es el fichero que docker compose
va a utilizar para levantar nuestros servicios dockerizados, concretamente nuestra imagen de hornet creada a partir del Dockerfile
anterior. También exponemos una serie de puertos para poder conectarnos desde fuera del container, concretamente son:
- API 14265/tcp
- Dashboard 8081/tcp
- INX 9029/tcp
- Faucet 8091/tcp
version: "3.9"
services:
hornet:
container_name: hornet
build:
dockerfile: Dockerfile
image: hornet:dev
stop_grace_period: 5m
ports:
- "14265:14265/tcp"
- "8081:8081/tcp"
- "8091:8091/tcp"
- "9029:9029/tcp"
Incializando nuestro nodo hornet
Una vez hemos creado todos esos ficheros dentro de nuestra carpeta /private-network
y teniendo docker y docker compose
instalado ejecutamos dentro de ese directorio lo siguiente:
~$ docker compose up
este comando lo que va a hacer es construir la imagen de nuestro hornet y va a levantar un contenedor con esa imagen y toda la configuración que le hemos dicho mediante el fichero Dockerfile
, podemos comprobar que todo funciona correctamente accediendo al dashboard en http://localhost:8081
o a la faucet en http://localhost:8091
o podemos conectar nuestra firefly a través del Hornet API en el host http://localhost:14265
.
Si hacemos cualquier cambio en cualquiera de los ficheros deberemos parar el contenedor y ejecutar docker compose build
para volver a crear la imagen con los nuevos cambios.
Espero que os haya gustado y sobre todo que os haya servido, para el próximo capítulo veremos como crear un cluster de 2 nodos wasp formando un committee y dentro de poco smart contracts!!.
Dejad vuestros comentarios y aprendamos juntos. Gracias!
Top comments (2)
Muchas Gracias por el articulo, hasta aqui, todo funcionando como se dice. Saludos
Muchas gracias, muy bien explicado.
Deseando ver el siguiente capitulo de los nodos wasp