Cardano

Administración y mantenimiento de un nodo Cardano

Administración y mantenimiento de un nodo Cardano

Las siguientes tareas las llevaremos a cabo mediante las herramientas de CNTOOLS. Se trata de operaciones rutinarias relativamente sencillas que implican transacciones. Por lo tanto, requerirán del uso de claves de firma que, por precaución, nunca deberían guardarse en el nodo. Existen dos modos de llevar a cabo este tipo de tareas.

  • Modo online: si disponemos de todas las claves en el nodo. Es la manera más cómoda de operar, aunque también la más arriesgada. Si realizamos operaciones en este modo, es importante conservar las claves en el nodo únicamente el tiempo imprescindible para realizar la operación.
  • Modo híbrido: La transacción se prepara en el nodo, se pasa a un entorno frío en el cual se encuentran las claves de firma y, una vez firmada, se lleva de vuelta al nodo para enviarla a la red.

En esta entrada, por simplicidad, nos referiremos al modo online y haremos referencia a las claves necesarias para cada operación. Dichas claves deberían conservarse en una unidad externa cifrada y ser copiadas temporalmente al nodo durante los minutos que dura la operación. A continuación deberán ser borradas con un programa de borrado seguro.

Rotación de claves

Hay ocasiones en las que un servidor es puesto en funcionamiento y posteriormente desatendido e incluso olvidado. Contrariamente a lo que se pudiera pensar, un servidor en estas condiciones puede mantenerse en funcionamiento durante mucho tiempo sin que nadie se ocupe de él e, incluso, sin que sea fácil siquiera acceder a su ubicación para retirarlo de la circulación. Esto no resulta tan raro si pensamos en servidores virtuales o servicios en funcionamiento alojados en servidores más grandes que están suministrando otros servicios de manera simultánea. Esto explicaría por qué el servidor físico sigue recibiendo mantenimiento por parte de responsables que pueden llegar a ignorar durante años la existencia de servicios «fantasma» ejecutándose en sus máquinas.

Sin ir más lejos, yo mismo me he encontrado con esta circunstancia al menos en dos ocasiones. En ambos casos se trataba de páginas web profesionales que habían sido puestas en funcionamiento en servidores compartidos por responsables que luego desaparecieron del mapa. Las páginas pronto quedaron obsoletas sin que fuera posible acceder a ellas para desactivarlas o actualizarlas.

Pues bien. Para evitar que los nodos de Cardano puedan llegar a convertirse en nodos fantasma, degradando así el funcionamiento de la red, los operadores tienen la obligación de renovar unas claves cada tres meses para que el nodo siga teniendo la capacidad de firmar bloques. A este proceso se le llama rotación.

Claves necesarias: cold.skey

ruta: $CNODE_HOME/priv/pool/<pool_name>/

Retiro de recompensas

Las recompensas obtenidas tras la firma de bloques se van depositando en una dirección específica dentro de nuestra billetera. Estas recompensas son delegadas en el «pool» de manera automática, por lo que si no queremos disponer de ellas no es necesario realizar ninguna acción. Sin embargo, estrictamente no forman parte de los fondos de la billetera propiamente dicha, así que no nos servirían para cumplir con el «pledge», en caso de que quisiéramos aumentarlo. En cualquier caso, bien porque queramos elevar el «pledge», bien porque queramos transferirlas a otra dirección, antes o después necesitaremos retirarlas.

Importante: Los gestores de billeteras tipo Daedalus o Yoroi incorporan una opción para retirar las recompensas directamente. Esto está muy bien si estamos delegando en cualquier «pool» que no sea el nuestro o siempre que se trate de una billetera diferente de la utilizada para crear el nodo. Sin embargo, si durante la creación del nodo decidimos incorporar una billetera externa generada con Yoroi o Daedalus es muy importante que no realicemos el retiro de las recompensas desde ninguno de estos programas externos, ya que en este caso se rompería la sincronización entre el saldo real y el mostrado en la billetera. Una billetera de este tipo debería utilizarse solamente como herramienta de monitorización. Cualquier transacción deberá realizarse directamente con las herramientas de cliente del nodo.

Claves necesarias: payment.skey, stake.skey

ruta: $CNODE_HOME/priv/wallet/<wallet_name>/

Listado de claves

A modo de chuleta, aquí dejo una tabla con el listado de claves del nodo y donde podemos encontrar cada una de ellas.

Para el pool

Clave hot node cold node
cold.skey X
cold.vkey X X
hot.vkey X X
hot.skey X X
vrf.vkey X X
vrf.skey X X

Para la billetera

Clave hot node cold node
base.addr X X
reward.addr X X
payment.addr X X
payment.vkey X X
payment.skey X
stake.vkey X X
stake.skey X
stake.cert X
delegation.cert X
Publicado por David en Cardano, 0 comentarios
Visualización de métricas con Prometheus y Grafana

Visualización de métricas con Prometheus y Grafana

¿Prometheus, Grafana o los dos?

Grafana es una de las herramientas más extendidas y populares para visualizar datos de manera gráfica. Además, estos datos pueden ser adquiridos en tiempo real de sistemas en funcionamiento, lo que permite controlarlos y monitorizarlos con detalle.

La verdad es que a poco que nos hayamos movido por el entorno de Cardano seguro que ya nos hemos encontrado con Grafana, ya que se trata de la opción más extendida y recomendada cuando se trata de supervisar un nodo de la red. No obstante, sus aplicaciones son prácticamente ilimitadas, y en mi caso concreto también me resulta muy útil como panel de control del sistema domótico Openhab.

Grafana puede conectarse a varias fuentes de datos. Una de las más populares, por ser la utilizada por Cardano, es Prometheus. También puede conectarse a InfluxDB, lo cual es muy conveniente, al ser una de las opciones más comunes de entre las disponibles en Openhab.

Prometheus es un software que tiene algunos puntos en común con Grafana. Por sí sólo también es capaz de recolectar datos y mostrarlos en forma de gráficas, aunque sus posibilidades en este sentido son mucho más limitadas. En realidad, sólo con Prometheus ya podríamos realizar la monitorización de un sistema, incluyendo el nodo de Cardano, pero Grafana añade una capa de funcionalidad y prestaciones que resultan muy convenientes. De ahí que, a menudo, en todos los artículos referidos a la monitorización en Cardano aparezcan juntos.

A efectos prácticos utilizaremos Prometheus como un sistema para recolectar y recopilar las métricas que nos interese monitorizar y Grafana como una capa adicional para transformar y visualizar estos datos de la manera que nos resulte más conveniente.

Empecemos por Prometheus

Prometheus recolecta métricas a partir de lo que llama end-points, los cuales no son sino puntos de conexión mediante el protocolo http en los que se encuentran expuestas dichas métricas en un formato XML entendible por Prometheus.

Configuración

La configuración es sencilla, pero si no queremos desorganizar demasiado los scripts de inicio del servicio systemd conviene hechar un vistazo al contenido de éste:

sudo nano /lib/systemd/system/prometheus.service
...
EnvironmentFile=/etc/default/prometheus
ExecStart=/usr/bin/prometheus $ARGS
...

Por cierto, si quieres recordar cómo encontrar la ubicación de los scripts de servicio, echa un vistazo a esta entrada.

En este archivo vemos que el ejecutable es invocado con una variable de entorno $ARGS que contiene los argumentos que se pasan al programa. Vemos también la ubicación del archivo de entorno donde encontraremos la asignación de dicha variable. Si editamos dicho archivo:

sudo nano /etc/default/prometheus

# Set the command-line arguments to pass to the server.
ARGS=""

# Prometheus supports the following options:
#  --config.file="/etc/prometheus/prometheus.yml"
#                             Prometheus configuration file path.
#  --web.listen-address="0.0.0.0:9090"
...

Observamos que la variable de entorno está vacía, lo que nos indica que se toman los argumentos por defecto. Vemos también, comentados, todos los argumentos que pueden ser pasados al ejecutable. Una opción sería especificar dichos parámetros directamente en el archivo de servicio donde se llama al ejecutable, eliminando la variable de entorno $ARGS. Sin embargo, una opción más elegante es colocar dicho parámetro dentro de la cadena $ARGS y permitir que para el resto de parámetros no especificados se apliquen los valores por defecto. Por ejemplo, para modificar el puerto al 9095 podríamos dejar el archivo así (observar las secuencias de escape para las dobles comillas):

sudo nano /etc/default/prometheus

# Set the command-line arguments to pass to the server.
ARGS="--web.listen-address=\"0.0.0.0:9095\""

# Prometheus supports the following options:
#  --config.file="/etc/prometheus/prometheus.yml"
#                             Prometheus configuration file path.
#  --web.listen-address="0.0.0.0:9090"
...

Para configurar los endpoints a los que conectarse, editar el archivo:

sudo nano /etc/prometheus/prometheus.yml

Métricas de Cardano

El software cardano-node ofrece, de manera nativa, un end-point con las métricas de funcionamiento del nodo. En el archivo de configuración de cardano-node encontraremos un apartado donde configurar el número de puerto (por si necesitáramos cambiarlo) y las direcciones desde las cuales es posible conectarse al end-point (punto importante cuando el servidor Prometheus está en una máquina diferente). Concretamente, esta sección tiene el siguiente aspecto:

"hasPrometheus": [
    "127.0.0.1",
    12798
  ]

Ésta es la configuración por defecto. Indica que la conexión sólo es posible desde la máquina local y en el puerto 12798. Si necesitamos conectarnos desde otra máquina, deberemos especificar, o bien la dirección IP de la misma, o bien «0.0.0.0» para la conexión desde cualquier dirección IP. No olvidemos que, en este caso, además deberemos habilitar este puerto en el firewall.

Si queremos echar un vistazo a los datos en crudo ofrecidos por el end-point de nuestro nodo bastará con dirigir nuestro navegador a la dirección:

http://<ip_nodo>:12798/metrics

Obviamente, el end-point deberá ser accesible desde la máquina en la que tengamos el navegador. Como es posible que eso no coincida con la configuración que estamos planeando, y para no andar toqueteando aquí o alla, una buena alternativa al navegador es el comando curl en la misma máquina en la que se encuentre el end-point:

curl -s http://localhost:12798/metrics

Métricas del nodo

Otro conjunto de datos que suele resultar interesante para comprobar el buen desempeño de una máquina es el relacionado con el correcto funcionamiento y rendimiento del hardware y del sistema operativo: temperaturas, carga de la CPU, uso de memoria, etc. Estas métricas pueden obtenerse instalando el software prometheus-node-exporter, el cual recopila todos estos parámetros y los expone en un nuevo end-point en el puerto 9100. Como antes, para comprobar el buen funcionamiento del end-point:

curl -s http://<ip_nodo>:9100/metrics

Aunque parezca una trivialidad, no está de más no confundir el software prometheus-node-exporter, el cual sólo crea un end-point donde exponer métricas de funcionamiento de la máquina, con el servidor Prometheus, que es el que se encarga de recopilar y almacenar todos los datos obtenidos de los diferentes end-points. Aunque a menudo se instalen a la vez, son piezas de software diferentes y ni siquiera es necesario que vayan juntos.

Métricas de dispositivos de red

El protocolo SNMP (Simple Network Management Protocol) permite el intercambio de información entre dispositivos conectados a una misma red. Entre sus usos más frecuentes se encuentra la configuración automática de routers o firewalls por parte de aquellos programas que lo necesiten. Sin embargo, también es posible utilizarlo para obtener métricas de dispositivos de red y mostrarlas en Grafana. Por ejemplo, podemos monitorizar el router y comprobar el buen funcionamiento de nuestra conexión a internet.

Necesitaremos dos cosas:

  • Que nuestro router sea compatible con SNMP y que éste se encuentre habilitado
  • Tener instalado prometheus-snmp-exporter en nuestro servidor. Este software es capaz de comunicar con dispositivos que hablen SNMP y de ofrecer las métricas así obtenidas exponiendo un end-point para Prometheus. Este software se puede instalar directamente desde los repositorios de Ubuntu o bien descargándolo desde github, concretamente, aquí.

Su configuración se encuentra en el archivo:

sudo nano /etc/prometheus/snmp.yml
# Due to licensing reasons, it is not possible to ship a ready-to-use snmp.yml
# config file.
#
# See /usr/share/doc/prometheus-snmp-exporter/README.Debian for instructions
# on using prometheus-snmp-generator to create a suitable snmp.yml config.

En el que nos encontramos este curioso mensaje. La lectura del archivo README.Debian tampoco proporciona mucha más información.

La manera de proceder es sencilla. En github, que es donde se aloja el proyecto, viene un archivo snmp.yml por defecto que en la mayoría de las ocasiones nos funcionará correctamente, así que podemos, simplemente, descargarlo en el directorio arriba mencionado.

Importante: dependiendo del método escogido para instalar prometheus-snmp-exporter nos encontraremos con una versión u otra. Normalmente, las versiones disponibles en los repositorios oficiales de Ubuntu suelen estar algo desfasadas con respecto a la última versión disponible en GitHub. Esto es importante, porque si el software instalado y el archivo de configuración descargado corresponden a versiones diferentes, podría no funcionar.

Por ejemplo, en el momento de escribir esta entrada, la versión instalada a partir de los repositorios de Ubuntu es la v0.16.1, bastante anterior a la versión actual de GitHub, que es la v0.20.0. Por lo tanto necesitamos buscar el archivo de configuración de la versión adecuada, lo que conseguimos tecleando:

sudo wget https://raw.githubusercontent.com/prometheus/snmp_exporter/v0.16.1/snmp.yml

Si todo va bien, podemos observar las métricas en el endpoint correspondiente:

curl http://<server_ip>:9116/snmp?target=<router_ip>

Visualizando con Prometheus

Como decíamos, Prometheus por sí mismo puede ser utilizado como herramienta de monitorización y visualización. Para ello, sólo hay que conectarse desde un navegador a la dirección de la máquina donde se esté ejectuando el servidor:

http://<nodo_prometheus>:9010

Y veremos algo como esto:

Prometheus

En esta página disponemos de algunas opciones que nos permiten ir añadiendo gráficas y seleccionando las métricas deseadas.

Y sigamos con Grafana

Grafana suele ser instalada en la misma máquina en la que tenemos el servidor Prometheus pero, en realidad, podría estar en cualquier otro. Dispone de la posibilidad para conectar con diferentes fuentes de datos, entre ellas, como ya hemos comentado, con Prometheus y con InfluxDB.

Contrariamente a lo que pensé en un principio, Grafana no es capaz de conectar directamente con los end-points que proporcionan los datos para Prometheus, sino sólo con éste último. Es decir, que para monitorizar un nodo de Cardano, Grafana nos la podríamos ahorrar, pero Prometheus no.

Base de datos

Grafana utiliza una base de datos de tipo SQLite ubicada en /var/lib/grafana/grafana.db

  • Si en algún momento metemos la pata y deseamos deshacer el desaguisado manualmente, siempre podemos descargar el archivo y editarlo manualmente con esta excelente herramienta de código abierto: DB Browser for SQLite
  • No está de más incluir este archivo entre aquellos de los que solemos hacer copia de seguridad.
Publicado por David en Cardano, Domótica, Linux, 0 comentarios

Tipos de direcciones en Cardano

Explicado de una manera muy sencilla, una dirección en Cardano es básicamente un número que puede contener fondos. En este sentido, podríamos verlo como el número de cuenta bancaria en la cual mantenemos nuestro dinero. Los fondos pueden transferirse entonces de unas direcciones a otras mediante unas operaciones llamadas transacciones (el equivalente a una transferencia bancaria)

La cadena de bloques sería la base de datos en la cual quedan registradas de manera inalterable todas las transacciones en que las distintas direcciones se ven implicadas. De esta manera, consultando la cadena de bloques es posible conocer el saldo de cualquier dirección, así como todo el histórico de transferencias

En Cardano existen básicamente dos tipos de direcciónes, a las que nos referiremos como direcciones de pago (payment) y de stake.

Cada uno de este tipo de dirección está asociada a un par de claves, una pública y otra privada. A la dirección pública la llamamos de verificación y a la privada de firma.

La clave de verificación, abreviadamente vkey (que es pública), es la que permite que cualquiera pueda verificar su existencia y su saldo en la cadena de bloques. La clave de firma, abreviada como skey (que es privada) servirá para firmar las transacciones que permiten transferir fondos de una dirección a otra.

Generación de claves y direcciones

El proceso de generación de cualquiera de las claves es muy similar: Primero se solicita a la herramienta cardano-cli la creación del par de claves, vkey y skey, y, a partir de la primera, se genera la clave en cuestión.

Generación de las claves y la dirección de payment:

cardano-cli address key-gen \
--verification-key-file payment.vkey \
--signing-key-file payment.skey

A partir de la clave de verificación generamos la dirección:

cardano-cli address build \
--payment-verification-key-file payment.vkey \
--out-file payment.addr \
--testnet-magic $MAGIC_NUM

Generación de las claves y la dirección de stake:

cardano-cli stake-address key-gen \
--verification-key-file stake.vkey \
--signing-key-file stake.skey

A partir de la clave de verificación generamos la dirección::

cardano-cli stake-address key-gen \
--verification-key-file stake.vkey \
--testnet-magic $MAGIC_NUM

Un par de observaciones:

  • Las claves son generadas con independencia de la red en la cual vayan a ser utilizadas. Sin embargo, para generar la dirección, es necesario especificar a qué red va a pertenecer (testnet o mainnet)
  • Aunque cada dirección lleva asociadas dos claves, una pública y otra privada, la generación de la dirección se realiza utilizando únicamente la clave pública.

Diferencias entre claves de payment y de stake

  • La clave de payment es una clave que sirve, básicamente, para almacenar, recibir y transferir fondos.
  • La clave de stake sirve para tomar el control en la participación en el protocolo. Permite delegar fondos en los diferentes Stake Pools y también es donde se reciben las recompensas por ello. Será necesaria, también, si queremos crear nuestro propio Stake Pool. No es posible, sin embargo, transferir fondos a una dirección de Stake, aunque sí lo es transferir las recompensas recibidas hacia otras direcciones, evidentemente.

Es importante señalar que una clave de payment generada como hemos visto, aunque perfectamente funcional, no permite la delegación de fondos en un stake pool. Para que esta delegación sea posible, será necesario que la dirección de payment se encuentre vinculada a una dirección de stake, la cual, a su vez, será la que nos permitirá realizar la delegación. Este procedimiento será el que estudiaremos en detalle en las próximas entradas.

Publicado por David en Cardano, 0 comentarios

Registrar Stake Pool

En primer lugar, podemos ya probar a ejecutar nuestro stake pool con las claves y el certificado:

cardano-node run \
--topology testnet-topology.json \
--database-path ./db \
--socket-path ./db \
--host-addr 127.0.0.1 \
--port 3000 \
--config testnet-config.json \
--shelley-kes-key kes.vkey \
--shelley-vrf-key vrf.vkey \
--shelley-operational-certificate node.cert

Si bien la salida que obtendremos no será más que un conjunto de mensajes no demasiado reveladores, sí que podremos comprobar que cuando se ejecutan el productor y algún relé simultáneamente, realmente se están comunicando entre sí. Si queremos ver algo más descriptivo de cómo está funcionando nuestro nodo necesitaremos instalar alguna de las herramientas proporcionadas por GUILD Operators, concretamente, gLiveView.

  • Crear certificados

Crear el archivo de metadatos

blah, blah

Crear el certificado de registro

cardano-cli stake-pool registration-certificate \
    --cold-verification-key-file node.vkey \
    --vrf-verification-key-file vrf.vkey \
    --pool-pledge 1000000000 \
    --pool-cost 345000000 \
    --pool-margin 0.01 \
    --pool-reward-account-verification-key-file stake.vkey \
    --pool-owner-stake-verification-key-file stake.vkey \
    --testnet-magic $MAGIC_NUM \
    --single-host-pool-relay <rele.dominio.net> \
    --pool-relay-port 3000 \
    --metadata-url https://miweb.net/metadata \
    --metadata-hash <metadatahash> \
    --out-file pool-registration.cert

Aquí hemos definido algunos parámetros básicos, como la cantidad que estamos dispuestos a comprometer en nuestro pool (1000A), el margen de ganancias (1%), el coste de operación (345A). También pondremos la IP pública (o el nombre de dominio) y el puerto público al que conectarse. Si estamos detrás de un router NAT no olvidemos redirigir este puerto a nuestra IP privada.

También vemos que la dirección de stake para recibir recompensas y para la delegación de los propietarios (que no es otra cosa que la delegación necesaria para cubrir el pledge), son la misma, si bien podrían ser direcciones diferentes. A este respecto, señalar que para proporcionar fondos para el pledge es necesario transferir los mismos a la dirección payment.addr asociada a esta dirección de stake. Para ello creamos el siguiente…

Certificado de delegación

cardano-cli stake-address delegation-certificate \
--stake-verification-key-file stake.vkey \
--cold-verification-key-file cold.vkey \
--out-file pool-delegation.cert

Esto crea un certificado que delega los fondos de la dirección asociada a stake.vkey al pool asociado a la clave node.vkey

  • Registrar el Stake Pool

Este paso consiste en realizar la transacción que enviará nuestros certificados de registro y de delegación a la cadena de bloques. Se trata de una transacción en la que, además de la tarifa ordinaria, deberemos incluir el depósito de registro del pool. Sucesivos re-registros (para cambiar parámetros como el pledge o el archivo de metadatos) requerirán una transacción similar pero sin incluir este depósito.

Borrador de la transacción

cardano-cli transaction build-raw \
--tx-in <TxHash>#<TxIx> \
--tx-out $(cat payment.addr)+0 \
--invalid-hereafter 0 \
--fee 0 \
--out-file tx.draft \
--certificate-file pool-registration.cert \
--certificate-file pool-delegation.cert

Es similar al borrador de una transacción estándar salvo que en las últimas líneas especifican las opciones para incluir los certificados.

Cálculo de la tarifa mínima

cardano-cli transaction calculate-min-fee \
--tx-body-file tx.draft \
--tx-in-count 1 \
--tx-out-count 1 \
--witness-count 3 \
--byron-witness-count 0 \
--mainnet \
--protocol-params-file protocol.json

Igual que siempre

Cálculo del cambio

En este caso, para calcular el cambio debemos deducir, no sólo la tarifa, sino también el depósito de registro. Dicho depósito lo obtenemos de los parámetros del protocolo (esos que antes hemos obtenido y guardado convenientemente en un archivo llamado protocol.json). Como no recuerdo exactamente el nombre del parámetro, que además va cambiando de una versión a otra, tecleo…

cat protocol.json | grep Deposit
    "stakePoolDeposit": 500000000,
    "stakeAddressDeposit": 2000000,

En este caso, el valor que nos interesa es el primero: 500 A

Ya sólo nos queda calcular el cambio como <Balance de UTxO> – tarifa – 500

Construir transacción preliminar

cardano-cli transaction build-raw \
--tx-in <TxHash>#<TxIx> \
--tx-out $(cat payment.addr)+<Cambio> \
--invalid-hereafter <ttl> \
--fee <tarifa> \
--out-file tx.raw \
--certificate-file pool-registration.cert \
--certificate-file pool-delegation.cert

Firmarla

cardano-cli transaction sign \
--tx-body-file tx.raw \
--signing-key-file payment.skey \
--signing-key-file stake.skey \
--signing-key-file cold.skey \
--mainnet \
--out-file tx.signed

Y enviarla

cardano-cli transaction submit \
--tx-file tx.signed \
--testnet-magic $MAGIC_NUM
Publicado por David en Cardano, 0 comentarios