0% encontró este documento útil (0 votos)
25 vistas101 páginas

Intro CD BESv 4

El documento presenta una introducción a las cadenas de bloques, contratos inteligentes y aplicaciones descentralizadas (dApps), destacando su importancia en la tecnología descentralizada. Se discuten las características de las cadenas de bloques como bases de datos seguras y transparentes, así como el funcionamiento de los contratos inteligentes y su implementación en dApps. Además, se abordan temas como las finanzas descentralizadas, oráculos y sistemas de archivos descentralizados, proporcionando una visión general de las aplicaciones y beneficios de estas tecnologías emergentes.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
25 vistas101 páginas

Intro CD BESv 4

El documento presenta una introducción a las cadenas de bloques, contratos inteligentes y aplicaciones descentralizadas (dApps), destacando su importancia en la tecnología descentralizada. Se discuten las características de las cadenas de bloques como bases de datos seguras y transparentes, así como el funcionamiento de los contratos inteligentes y su implementación en dApps. Además, se abordan temas como las finanzas descentralizadas, oráculos y sistemas de archivos descentralizados, proporcionando una visión general de las aplicaciones y beneficios de estas tecnologías emergentes.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

See discussions, stats, and author profiles for this publication at: https://www.researchgate.

net/publication/370048207

Introducción a Blockchain, Contratos Inteligentes y Aplicaciones


Descentralizadas

Technical Report · April 2023

CITATIONS READS

0 1,769

1 author:

Manuel José Fernández Iglesias


atlanTTic - University of Vigo
251 PUBLICATIONS 1,524 CITATIONS

SEE PROFILE

All content following this page was uploaded by Manuel José Fernández Iglesias on 11 February 2024.

The user has requested enhancement of the downloaded file.


Introducción a Blockchain, Contratos Inteligentes y Aplicaciones
Descentralizadas
Versión 4.1/ES – Febrero 2024

Manuel José Fernández Iglesias


atlanTTic - Universidade de Vigo
Resumen

Las cadenas de bloques o blockchains, los contratos inteligentes y las aplicaciones descentraliza-
das (dApps) son tres componentes esenciales del campo emergente de la tecnología descentralizada.
Una cadena de bloques se puede ver como una base de datos descentralizada que permite registrar
transacciones seguras y transparentes entre pares sin necesidad de intermediarios. Los contratos in-
teligentes son programas de ordenador autoejecutables que aplican automáticamente los términos
de un acuerdo entre las partes, sin necesidad de intermediarios como entidades financieras o regula-
torias. Los contratos inteligentes se construyen utilizando lenguajes de programación como Solidity y
se despliegan en redes blockchain. Las dApps son aplicaciones descentralizadas que aprovechan la
tecnología blockchain y los contratos inteligentes para dar soporte a transacciones y servicios descen-
tralizados sin necesidad de un ente central de supervisión. Las dApps están diseñadas para funcionar
de forma autónoma, sin necesidad de una autoridad central, y pueden utilizarse para una amplia ga-
ma de aplicaciones en muy diversos ámbitos como las finanzas, la gestión de cadenas de suministro,
las redes sociales o los juegos. Combinados, las cadenas de bloques, los contratos inteligentes y las
dApps ofrecen una nueva y revolucionaria forma de orquestar y proveer servicios de forma descen-
tralizada, segura y transparente. Las cadenas de bloques como una tecnología más en la nube surgen
para apoyar el desarrollo y despliegue de dApps. La computación en nube proporciona a los desa-
rrolladores acceso a recursos informáticos escalables y flexibles que pueden utilizarse para ejecutar
dApps y almacenar datos en una red blockchain. Mediante el modelo de provisión en la nube, los de-
sarrolladores pueden crear y desplegar dApps sin necesidad de una inversión inicial significativa en
infraestructura o conocimientos técnicos, lo que facilita el acceso al mundo de las tecnologías des-
centralizadas y la adopción de soluciones basadas en dichas tecnologías, que a su vez son la base de
una nueva generación de servicios online basada en la descentralización: la Web3 o Web 3.0.

Bajo licencia Atribución-NoComercial-SinDerivadas 4.0 Internacional (CC BY-NC-ND 4.0) (la “Licen-
cia”). Puedes reutilizar este material sin coste alguno de acuerdo con la Licencia. Se puede distribuir libremente y sin coste
tal como está, en su lenguaje original (Ver licencia). De todos modos, si encuentras este contenido útil e interesante puedes
invitarme a un café: 0x932F438AC00eBF608142Bf0fB48Aba0B5fF4AF7d.
Citar como: Manuel J. Fernández Iglesias (2023) Introducción a Blockchain, Contratos Inteligentes y Aplicaciones Descen-
tralizadas, Ver 3.0/ES. Informe técnico. atlanTTIc, Universidade de Vigo.
DOI: 10.17605/OSF.IO/FQ3P9 .

Versión 4.1/ES. Maquetado: 11 de febrero de 2024, 17:36 CET.

1
2
Índice

1. Introducción 5

2. Tipos de cadenas de bloques 6


2.1. Cadenas públicas: criptomonedas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2. Cadenas privadas: cadenas empresariales . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3. Estructura y funcionamiento básicos de una cadena de bloques 8


3.1. Participantes en una red blockchain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2. Mecanismos de consenso de la cadena de bloques . . . . . . . . . . . . . . . . . . . . . 10
3.3. Creación de nuevos bloques: Minería y forja o acuñado . . . . . . . . . . . . . . . . . . . 11

4. Ventajas e inconvenientes de las cadenas de bloques 16


4.1. Aspectos de seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

5. Contratos inteligentes y dApps 20


5.1. Programación de contratos inteligentes y dApps . . . . . . . . . . . . . . . . . . . . . . . 21
5.2. Contratos inteligentes y criptomonedas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
5.3. Aspectos de seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.4. Tokens no fungibles o NFT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

6. Finanzas descentralizadas (DeFi) 39


6.1. Mercados financieros descentralizados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
6.2. Préstamos descentralizados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
6.3. Minería de liquidez . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
6.4. Derivados DeFi y gestión de activos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.5. Retos y consideraciones normativas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

7. Oráculos 46
7.1. Arquitecturas de oráculos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
7.2. Oráculos y DeFi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
7.3. Generación de números aleatorios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7.4. Redes de oráculos y oráculos entre cadenas . . . . . . . . . . . . . . . . . . . . . . . . . 64
7.5. Aspectos de seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

8. Sistemas de archivos descentralizados 66


8.1. Limitaciones de los sistemas de archivos tradicionales . . . . . . . . . . . . . . . . . . . 66
8.2. Fundamentos de los sistemas de archivos descentralizados . . . . . . . . . . . . . . . . 67

3
8.3. Arquitectura y funcionamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
8.4. InterPlanetary File System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
8.5. IPFS y las cadenas de bloques: casos de uso . . . . . . . . . . . . . . . . . . . . . . . . . 70
8.6. Otros sistemas de archivos descentralizados . . . . . . . . . . . . . . . . . . . . . . . . . 72

9. Blockchain como servicio (BaaS) 72

10. Conclusión 73
10.1. Para saber más . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

A. Criptografía de clave pública 81

B. Funciones hash 83

C. Árboles de Merkle 85

D. Prueba de participación en Ethereum 87

E. Redes peer-to-peer 88

Glosario 91

4
1. Introducción

Una cadena de bloques es un registro de información descentralizado y distribuido a lo largo y


ancho de un conjunto de nodos conectados en red. Cada bloque de la cadena registra un conjunto de
transacciones u operaciones, y una vez que un bloque se añade a la cadena, no puede alterarse sin el
consenso de la red. Es decir, una vez que una transacción se añade a la cadena de bloques, es perma-
nente e inmutable. Las transacciones representan transferencias de información, activos o valor entre
personas o entidades. Por tanto, una cadena de bloques se puede ver como una base de datos que
almacena todas las transacciones que se han producido en dicha red desde su creación. Otro símil
habitual para describir una cadena de bloques es el de un libro mayor de contabilidad (ledger), dis-
tribuido e inmutable, donde se recogen todas las transacciones realizadas. Las cadenas de bloques
utilizan técnicas criptográficas, como la criptografía de clave pública o las funciones hash (ver apén-
dices A y B), para asegurar la red y garantizar la privacidad y autenticidad de los datos almacenados
en ellas.
Los nodos de una red blockchain interactúan entre sí mediante un protocolo de red entre iguales o
protocolo peer-to-peer (P2P, ver apéndice E y figura 9). Cada nodo está conectado a varios nodos de la
red y puede enviar y recibir datos hacia y desde estos nodos. Cuando un nodo se une a la red, primero
tiene que encontrar otros nodos a los que conectarse. Para ello, puede utilizar un nodo de inicio, que
es un nodo bien conocido en la red que tiene una lista de otros nodos a los que el nuevo nodo puede
conectarse. Una vez que el nuevo nodo está conectado, puede utilizar un protocolo de descubrimiento
para encontrar otros nodos a los que conectarse. Una vez que un nodo está conectado a otros nodos,
puede intercambiar mensajes con ellos utilizando el protocolo P2P. Estos mensajes pueden incluir
transacciones, bloques y otros datos relacionados con la cadena de bloques. Cada nodo verifica los
datos que recibe de otros nodos para asegurarse de que son válidos y no han sido manipulados.
Los nodos también pueden comunicarse entre sí para llegar a un consenso sobre el estado de la
cadena de bloques. Para ello se utiliza un algoritmo de consenso, que garantiza que todos los nodos
están de acuerdo en el mismo conjunto de transacciones y bloques. Dependiendo del algoritmo de
consenso utilizado, los nodos pueden tener que realizar diferentes funciones, como validar transac-
ciones o fabricar nuevos bloques. En general, la interacción entre los nodos de una red blockchain es
esencial para mantener la integridad y la seguridad de la red, así como para garantizar que todos los
nodos tengan una visión coherente de la blockchain.
La naturaleza descentralizada de la cadena de bloques significa que no hay una autoridad central
que la controle, lo que la hace resistente a la piratería y la manipulación. En su lugar, cada nodo de la red
tiene una copia de la cadena completa. Esto garantiza que no haya un único punto de fallo en la red y
que la propia cadena de bloques sea resistente a la manipulación. Cada bloque de la cadena contiene
un conjunto de transacciones, y una vez que un bloque se añade a la cadena, no puede alterarse. Esto
también lo convierte en un sistema que no requiere una autoridad central de confianza, lo que significa
que los participantes pueden confiar en los datos almacenados en la cadena de bloques sin depender
de ningún intermediario. Como ya se ha dicho, la cadena de bloques utiliza en su lugar un mecanismo
de consenso para garantizar que todos los nodos de la red están de acuerdo sobre el estado de la
cadena.
Las cadenas de bloques ya se utilizan en muy diversas aplicaciones, como las criptomonedas,
la gestión de cadenas de suministro, la gestión de activos financieros, la educación (Delgado-von-
Eitzen, Anido-Rifón y Fernández-Iglesias, 2021b), la gestión de ecosistenas del Internet de las Cosas o
los sistemas de votación, entre muchas otras. La cadena de bloques más conocida es Bitcoin, que se
utiliza para almacenar y transferir la criptomoneda Bitcoin (BTC). Esta fue la cadena original propuesta
por Satoshi Nakamoto (2008), la persona o grupo de personas a las que se le atribuye la primera
aplicación exitosa de esta tecnología.

5
Otra cadena muy popular es Ethereum (Buterin, 2014), una cadena de bloques programable que
permite a los desarrolladores crear aplicaciones descentralizadas (dApps) mediante contratos inteli-
gentes. También dispone de su propia criptomoneda (Ethereum, ETH) y es la segunda mayor cadena
de bloques por capitalización bursátil, después de Bitcoin. Otras cadenas populares, con sus respecti-
vas criptomonedas, son Binance Smart Chain (BSC) (Chain, 2020), Cardano (ADA) (Hoskinson, 2017),
Polkadot (DOT) (Wood, 2016) o Solana (SOL) (Yakovenko, 2017).
La evolución y expansión del mundo de las cadenas de bloques, los contratos inteligentes y las
dApps han dado lugar a una amplia gama de tecnologías y aplicaciones que están transformando
diversos sectores de la sociedad. En este manual, exploraremos los fundamentos esenciales de las
cadenas de bloques, presentando los diferentes tipos de cadenas de bloques, su estructura y funcio-
namiento básicos, así como sus ventajas e inconvenientes. Además, profundizaremos en el mundo
de los contratos inteligentes y las dApps, hablando de su programación, seguridad y su relación con
las criptomonedas y los tokens no fungibles (NFTs). Exploraremos también el campo de las finanzas
descentralizadas o DeFi, que abarca desde los mercados financieros descentralizados hasta los prés-
tamos y la minería de liquidez. Adicionalmente, examinaremos los oráculos y los sistemas de archivos
descentralizados, así como el concepto de Blockchain como servicio (BaaS). Finalmente, concluire-
mos nuestro recorrido explorando los desarrollos más recientes en el ámbito de las blockchains y
ofreciendo recursos adicionales para aquellos interesados en profundizar en el tema.
Es importante señalar que el ecosistema blockchain evoluciona rápidamente, con continuos avan-
ces en tecnología, estándares y mejores prácticas. Del mismo modo, las herramientas de apoyo y las
bibliotecas utilizadas para desarrollar contratos inteligentes e interactuar con las redes blockchain
también evolucionan a un ritmo rápido. Como resultado, aunque el código proporcionado aquí es pre-
ciso y funcional en el momento de su redacción, puede requerir actualizaciones o correcciones en un
futuro próximo para seguir siendo compatible con las últimas versiones de las plataformas, bibliote-
cas y estándares de blockchain. Se recomienda a los desarrolladores que se mantengan informados
sobre los últimos avances en el ámbito del blockchain, que comprueben la compatibilidad del código
con las versiones actuales del software y que actúen con cautela al desplegar el código en entornos
de producción.

2. Tipos de cadenas de bloques

La clasificación más general de las cadenas de bloques se basa en los requisitos que se imponen
a los usuarios para poder realizar transacciones en ellas (Miller, 2019). En una red blockchain privada,
autorizada o permisionada (permissioned blockchain), el acceso a la red y la participación en la vali-
dación y verificación de las transacciones están restringidos a un grupo específico de participantes
autorizados. Estos participantes suelen ser identificados y verificados mediante algún tipo de proceso
de verificación de identidad. Las redes blockchain privadas se utilizan habitualmente en aplicaciones
empresariales o gubernamentales en las que la privacidad, la seguridad y el cumplimiento son requi-
sitos operativos fundamentales.
Por el contrario, una red blockchain sin permisos, no permisionada o pública(non-permissioned
blockchain) está abierta a cualquiera que desee participar en la misma, sin restricciones ni requisitos
de verificación de identidad. Estas redes se consideran generalmente más descentralizadas y ofre-
cen mayor transparencia, pero también pueden ser más susceptibles a ataques u otras actividades
maliciosas debido a su naturaleza abierta.
Las cadenas de bloques de criptomonedas son el ejemplo más claro de las redes públicas, mien-
tras que, como acabamos de indicar, las cadenas de bloques empresariales serían quizá el mejor
ejemplo de redes privadas. A continuación describimos las características más relevantes de estas
cadenas.

6
2.1. Cadenas públicas: criptomonedas

Una cadena de bloques de criptomonedas es una tecnología de libro mayor descentralizado y dis-
tribuido que se utiliza para rastrear y registrar transacciones en una moneda digital, como Bitcoin o
Ethereum. Permite transacciones entre pares sin necesidad de intermediarios, como bancos o insti-
tuciones financieras, y está diseñada para ser segura, transparente e inmutable. Las criptomonedas
tienen una gran popularidad entre inversores y usuarios como una tecnología que tiene el potencial
de revolucionar los sistemas financieros tradicionales y transformar la forma en que realizamos tran-
sacciones e intercambiamos valor.
En una cadena de bloques de criptomonedas, las transacciones se agrupan en bloques y se aña-
den a la cadena de bloques en orden cronológico. Como en toda cadena de bloques, cada bloque
contiene un hash criptográfico único que lo vincula al bloque anterior, creando un libro de contabilidad
inmutable, seguro y a prueba de manipulaciones. La seguridad y la integridad de una cadena de blo-
ques de criptomonedas se mantienen mediante un mecanismo de consenso, que es un conjunto de
reglas y protocolos que garantizan que todos los participantes de la red están de acuerdo en la validez
de las transacciones y el orden en que se añaden a la cadena de bloques (ver apartado 3.2). Al ser
públicas, las cadenas de bloques de criptomonedas están diseñadas para ser transparentes y audita-
bles públicamente, lo que significa que los detalles de las transacciones son visibles para cualquiera
en la red. En cuanto a su escalabilidad, las cadenas de bloques de criptomonedas pueden gestionar
un gran volumen de transacciones, pero también pueden experimentar problemas de escalabilidad
debido a mecanismos de consenso que consumen mucha energía como la prueba de trabajo.

2.2. Cadenas privadas: cadenas empresariales

En cambio, las cadenas de bloques empresariales están diseñadas para facilitar el intercambio
seguro y transparente de datos y la colaboración entre las distintas partes de una red empresarial, co-
mo proveedores, clientes, empleados y socios. Se trata de cadenas de bloques privadas que requieren
autorización de una entidad central para poder operar y están diseñadas para dar soporte a aplica-
ciones empresariales específicas. A diferencia de las cadenas de bloques públicas utilizadas para las
criptomonedas, las cadenas de bloques empresariales suelen estar diseñadas para ser utilizadas por
un grupo determinado de participantes y no están abiertas al público.
Las cadenas de bloques empresariales ofrecen varias ventajas a las empresas, como una mayor
transparencia, seguridad y eficiencia. Al utilizar una base de datos compartida y distribuida, los parti-
cipantes pueden acceder a los datos y verificarlos en tiempo real, lo que reduce el riesgo de errores,
fraudes y disputas. Además, las cadenas de bloques empresariales contribuyen a agilizar los procesos
empresariales y a reducir costes, eliminando intermediarios, automatizando el trasiego de información
y agilizando los procesos.
Entre los casos de uso comunes para las cadenas de bloques empresariales, podemos identificar
la gestión de cadenas de suministro, la verificación de la identidad digital, la financiación del comer-
cio y los pagos. Por ejemplo, una cadena de suministro blockchain podría permitir a los fabricantes,
distribuidores y minoristas rastrear el movimiento de mercancías desde su producción hasta la en-
trega al cliente, garantizando la transparencia y reduciendo el riesgo de falsificación de productos.
Del mismo modo, una cadena de bloques de identidad digital podría permitir la verificación segura y
eficiente de la identidad de particulares y empresas, reduciendo el riesgo de fraude y la usurpación de
identidad. En definitiva, las cadenas de bloques empresariales ofrecen a las empresas una forma de
aprovechar las ventajas de la tecnología de base de datos descentralizada, al tiempo que abordan los
retos y requisitos de casos de uso específicos.
Las cadenas de bloques empresariales pueden ofrecer mayor privacidad y confidencialidad, utili-
zando técnicas como el cifrado de datos o el intercambio selectivo de información. También suelen

7
escalar mejor, ya que pueden diseñarse con una aplicación concreta en mente y no necesitan soportar
el mismo volumen de transacciones que una cadena de bloques de criptomoneda.
En general, aunque tanto las cadenas de bloques privadas como las públicas utilizan la tecnolo-
gía de base de datos o libro mayor distribuido, tienen diferentes consideraciones de diseño y sirven a
diferentes propósitos. Las cadenas de bloques de públicas, como las de criptomonedas, priorizan la
descentralización, la transparencia y la seguridad para las transacciones entre pares, mientras que las
cadenas de bloques privadas priorizan la escalabilidad, la privacidad y la interoperabilidad para el in-
tercambio seguro y eficiente de datos dentro de una red compuesta por pares a los que explícitamente
se les da permiso para operar en la red.

3. Estructura y funcionamiento básicos de una cadena de bloques

Como hemos visto, una cadena de bloques está compuesta de una serie de bloques enlazados
unos con otros. Un bloque de la cadena de bloques es un conjunto de datos que empaqueta un grupo
de transacciones que han sido validadas y añadidas al libro mayor de la cadena de bloques. Cada
bloque está vinculado al bloque anterior, formando una cadena que contiene un historial completo e
inalterable de todas las transacciones realizadas en la red, desde su creación.
Como podemos ver en la figura 1, cada bloque comienza con una cabecera que contiene meta-
datos sobre el bloque, incluido el hash del bloque, el hash del bloque anterior, la marca de tiempo del
bloque y, de ser necesario, un nonce. El nonce es un valor aleatorio utilizado en el proceso de mine-
ría de las redes de prueba de trabajo, diferente para cada bloque minado, necesario para resolver el
desafío computacional de dicho mecanismo de consenso (Wang et al., 2019).

Figura 1: Ejemplo ilustrativo de la estructura de una cadena de bloques.

Además, cada bloque contiene una lista de transacciones validadas que se han incluido en el blo-
que. Para proteger este contenido frente a manipulaciones y otros ataques y garantizar su integridad
e inmutabilidad, el bloque también contiene una clave hash que resume todas las transacciones del
bloque. Dicha clave se corresponde con la raíz del árbol de Merkle de todas las transacciones del
bloque (ver apéndice C y figura 8).
El bloque tiene también un campo que indica el tamaño de bloque en bytes. Se trata de un elemento
importante en las redes blockchain con capacidad de almacenamiento limitada. Otro campo indica la
posición del bloque en la cadena de bloques, llamada altura del bloque. Cada bloque de la cadena de
bloques tiene una altura única, y la altura de cada bloque se basa en la altura del bloque anterior. El
campo de altura del bloque junto con el hash del bloque anterior y la marca temporal de la cabecera,
sirven para garantizar el ordenamiento de los bloques en la cadena y su inmutabilidad. El hash del
propio bloque sirve para garantizar que ninguno de los campos del bloque ha sido alterado.
Finalmente, en las redes de prueba de trabajo (ver apartado 3.2) se incluye un campo de dificultad
que indica el nivel de dificultad computacional requerido para minar el bloque. Este valor se ajusta
periódicamente para mantener un ritmo constante de creación de bloques en estas redes.

8
3.1. Participantes en una red blockchain

Los participantes clave en una red blockchain pueden variar en función del tipo de cadena de blo-
ques, pero los elementos comunes a la mayoría de ellas son los nodos de la red, los mineros o los
validadores en función del mecanismo de consenso, los usuarios, los desarrolladores y los regulado-
res.
Los nodos son ordenadores o servidores conectados a la red que desempeñan un papel crucial
en el funcionamiento de una red blockchain al validar las transacciones, mantener una copia del libro
mayor de la cadena y transmitir información a otros nodos de la red. Utilizan un protocolo P2P para
comunicarse entre ellos.
Cada nodo de la red blockchain tiene una dirección única que lo identifica dentro de la red. Además
de realizar las tareas indicadas para garantizar el buen funcionamiento de la cadena, comparte con
el resto de los nodos información sobre su estado y sus capacidades. Por ejemplo, la versión del
software cliente blockchain que está ejecutando el nodo es relevante porque los nodos que ejecutan
software obsoleto pueden correr el riesgo de sufrir vulnerabilidades y no poder participar en la red.
Además, lleva cuenta del número de bloques de la cadena que el nodo ha validado. Esto ayuda a otros
nodos de la red a determinar la validez y precisión de la cadena de bloques. La información sobre
el estado de conexión indica si el nodo está actualmente conectado a otros nodos de la red. Los
nodos que no están conectados a la red no pueden validar transacciones ni transmitir información.
La cantidad de memoria y almacenamiento disponibles en el nodo está relacionado directamente con
sus contribuciones a la red, ya que los nodos con memoria o capacidad de almacenamiento limitados
pueden no ser capaces de participar en ciertas funciones de la misma. Finalmente, la tasa de hash del
nodo indica la potencia computacional que el nodo está aportando a la red. Esto es particularmente
relevante en blockchains de prueba de trabajo, donde la minería requiere una potencia computacional
significativa.
Los mineros son aquellos nodos en una blockchain de prueba de trabajo que compiten para resol-
ver desafíos matemáticos complejos con el objetivo de añadir nuevos bloques a la cadena y con ello
ganar recompensas. Por su parte, los validadores son nodos de una cadena de bloques de prueba de
participación o de tolerancia a fallos bizantinos que se encargan de validar las transacciones y añadir
nuevos bloques a la cadena de bloques. Los validadores se eligen en función de su participación en la
red, medida habitualmente en función de la cuantía de un aval en criptomoneda, y también obtienen
recompensas por su participación.
Los usuarios son personas u organizaciones que utilizan la red blockchain para enviar y recibir tran-
sacciones. También pueden participar en el mecanismo de consenso de la red blockchain aportando
sus avales en una red de prueba de participación. Los usuarios participan libremente y de manera
anónima en las redes públicas y requieren de identificación y registro en la redes privadas.
Los desarrolladores son individuos u organizaciones que crean y mantienen el software blockchain
y las aplicaciones que se ejecutan en la capa superior de la red, como los contratos inteligentes y las
dApps.
Finalmente, los reguladores son agencias gubernamentales u otras organizaciones que supervi-
san y regulan el uso de la red blockchain, especialmente en los casos en los que implica el intercambio
de valores, materias primas u otros activos regulados. Su papel es más relevante en las redes empre-
sariales, sobre todo en aquellas que operan en mercados regulados.
En definitiva, los participantes en una red blockchain trabajan conjuntamente para garantizar la
seguridad, fiabilidad y funcionalidad de la red. Cada uno tiene sus funciones y responsabilidades, pero
entre todos desempeñan un papel crucial en el funcionamiento y el éxito de la cadena de bloques.

9
3.2. Mecanismos de consenso de la cadena de bloques

Como apuntábamos en la sección 2, los mecanismos de consenso son las reglas y procesos
utilizados para garantizar que todos los nodos de una red de cadena de bloques están de acuerdo
sobre el estado actual de la blockchain. Estos mecanismos sirven para resolver vulnerabilidades de
las redes blockchain como el problema de los generales bizantinos o los ataques de Sybil o del 51 %
(ver 4.1).
En la práctica se utilizan varios mecanismos de consenso, cada uno con sus propias ventajas e
inconvenientes. Los mecanismos de consenso más utilizados son la prueba de trabajo (proof-of-work,
PoW), la prueba de participación (proof-of-stake, PoS) y el algoritmo de tolerancia a fallos bizantinos,
en sus versiones clásica o práctica (BFT y PBFT). Cada mecanismo de consenso tiene sus propios
puntos fuertes y débiles, y la elección del mecanismo de consenso depende de las necesidades y
objetivos específicos de la red blockchain (Wang et al., 2019).
En una blockchain de prueba de trabajo, los nodos compiten para resolver problemas matemáti-
cos complejos utilizando potencia computacional. El primer nodo que resuelve el problema es recom-
pensado con criptomoneda y el derecho a crear el siguiente bloque de la cadena. Bitcoin utiliza un
mecanismo de consenso de prueba de trabajo (Nakamoto, 2008).
En una blockchain de prueba de participación, los nodos se seleccionan para crear nuevos bloques
en función de la cantidad de criptomoneda que ofrecen como aval. Los validadores se seleccionan
aleatoriamente para crear nuevos bloques y, si se descubre que actúan de forma maliciosa, se ejecuta
el aval. Ethereum pasó de usar un mecanismo de prueba de trabajo a uno de prueba de participación
en septiembre de 2022 (Buterin y Schneider, 2022). El apéndice D describe el mecanismo de consenso
actual de Ethereum.
La prueba de participación delegada (DPoS) es una variante del mecanismo PoS donde los posee-
dores de criptomonedas eligen a un grupo más reducido de validadores encargados de crear nuevos
bloques (Snider, Samani y Jain, 2018). A estos validadores se les paga por sus servicios y pueden ser
cesados de sus funciones si se descubre que actúan en contra de los intereses de la red. Las crip-
tomonedas EOS y Tron utilizan un mecanismo de consenso de prueba de participación delegada. La
principal diferencia entre PoS y DPoS es la forma en que se seleccionan los validadores. En una block-
chain PoS, los validadores se seleccionan en función de la cantidad de criptomoneda que poseen y
aportan como aval, mientras que en una blockchain DPoS, los validadores son elegidos por los titu-
lares de criptomoneda. Esto proporciona a estos últimos un control más directo sobre el proceso de
consenso y les permite responsabilizar a los validadores de sus acciones. Otra diferencia es el número
de validadores de la red. Las redes PoS pueden tener cientos o miles de validadores, mientras que las
redes DPoS suelen tener un número limitado de validadores. Esto puede hacer que las redes DPoS
sean más eficientes y rápidas que las redes PoS, ya que un menor número de validadores implica un
consenso más rápido.
En una cadena de bloques tolerante a fallos bizantinos (BFT), los nodos colaboran para ponerse
de acuerdo sobre el estado del libro mayor. Unos nodos se encargan de proponer nuevos bloques, y
otros nodos votan sobre la validez de los bloques propuestos. Si una mayoría absoluta (más del 51 %)
de nodos está de acuerdo con la validez de un bloque, se añade a la cadena de bloques. Hyperledger
Fabric utiliza un mecanismo de consenso tolerante a fallos bizantinos (Barger et al., 2021).
La tolerancia a fallos bizantinos práctica (PBFT) es una variante de BFT donde los nodos que
proponen bloques y los que validan los bloques propuestos se van turnando (Castro y Liskov, 2002).
Quorum, una plataforma de cadena de bloques basada en Ethereum, utiliza este mecanismo de con-
senso. Una de las principales diferencias entre BFT y PBFT es la forma en que los nodos validan las
transacciones y crean nuevos bloques. En una cadena de bloques BFT, los nodos proponen nuevos
bloques y otros nodos los validan ejecutando una serie de comprobaciones criptográficas. La acepta-
ción de un bloque se decide por mayoría absoluta del 51 %. En cambio, PBFT utiliza un proceso más

10
complejo en el que los nodos se turnan para proponer nuevos bloques, y otros nodos validan los blo-
ques propuestos antes de añadirlos a la blockchain. La PBFT exige que un nodo reciba un umbral de
votos de otros nodos para poder proponer un bloque. Este proceso garantiza que cada bloque sea
validado por varios nodos y ayuda a protegerse de los nodos maliciosos. Otra diferencia entre BFT y
PBFT es el número de nodos defectuosos o maliciosos que puede tolerar el mecanismo de consenso.
BFT requiere que al menos dos tercios de los nodos de la red sean honestos y estén de acuerdo en
la validez de un bloque para que se añada a la cadena de bloques, mientras que PBFT requiere que al
menos dos tercios de los nodos sean honestos, pero puede tolerar hasta un tercio de nodos desho-
nestos. Por último, generalmente se considera que la PBFT es más eficiente que la BFT en términos
de sobrecarga de la red. Esto se debe a que la PBFT utiliza un proceso de votación más complejo
que puede eliminar los mensajes duplicados y reducir la cantidad de datos que hay que transmitir
entre nodos. Tanto BFT como PBFT sólo funcionan en redes privadas, ya que es necesario conocer
la identidad de los nodos.
Otros mecanismos de consenso existentes son la prueba de autoridad (PoA), prueba de peso
(PoW), prueba de importancia (PoI), prueba de espacio y tiempo (PoST), prueba de cobertura (PoC) y
los grafos acíclicos dirigidos (DAG).

3.3. Creación de nuevos bloques: Minería y forja o acuñado

En una cadena de bloques de prueba de trabajo como Bitcoin, se denomina minería (mining) al
proceso de añadir definitivamente nuevos bloques a la cadena de bloques a través de un proceso
computacional que implica la resolución de problemas matemáticos complejos. Los mineros com-
piten para resolver un enigma criptográfico utilizando potencia de cálculo para encontrar una clave
hash específica para el nuevo bloque que cumpla un determinado requisito de dificultad. El primer
minero que encuentra la solución al enigma y la transmite a la red recibe una recompensa por el blo-
que así minado, que consiste generalmente en criptomoneda de nueva creación y/o comisiones por
cada transacción validada. Esta estrategia protege razonablemente a la cadena de bloques frente a
los ataques, ya que resultaría demasiado costoso involucrar a un número suficiente de mineros para
tener éxito.
El proceso de minado se desarrolla en varias etapas:
1. Validación de transacciones: Los mineros reciben nuevas transacciones de la red y las validan
para asegurarse de que son legítimas y cumplen las normas de la red.
2. Creación de un bloque: una vez que un minero ha validado un conjunto de transacciones, las
agrupa en un bloque y añade una transacción especial para cobrarse la recompensa por minar
el bloque y abonar dicha recompensa en la cartera del minero.
3. Resolución del reto: el minero utiliza su potencia de cálculo para intentar encontrar una solución
al enigma criptográfico asociado al bloque.
4. Difusión de la solución: una vez que un minero ha encontrado una solución válida, el bloque
recién minado se transmite a la red, y otros nodos de la red verifican que efectivamente dicha
solución es correcta.
5. Adición del bloque a la cadena de bloques: una vez que se verifica que la solución es válida, el
nuevo bloque se añade a la cadena de bloques y el minero recibe la recompensa por minar ese
bloque.
La dificultad del rompecabezas matemático se ajusta dinámicamente para garantizar que se aña-
den nuevos bloques a la cadena de bloques a un ritmo constante. El proceso de minería está diseñado
para ser computacionalmente intensivo y consumir muchos recursos para evitar el fraude y garantizar
la seguridad e integridad de la red de cadenas de bloques.

11
A continuación ilustramos con un ejemplo sencillo el minado mediante prueba de trabajo. Imagi-
nemos que en determinada red blockchain, para contribuir un nuevo bloque, se exige como reto que
la clave hash del mismo comience con un determinado número de bits a cero. La función siguiente
en JavaScript ilustra cómo se calcularía tal clave hash a partir de una cadena de datos.

1 //
2 // Función de ejemplo de un mecanismo sencillo de prueba de trabajo.
3 // La función findNonce devuelve una clave hash SHA-256
4 // para la cadena de caracteres ’payload’
5 // que cumple la condición de tener los ’n’ primeros bits a cero.
6 //
7 // La función devuelve un objeto con el nonce utilizado y el valor
8 // de la clave de hash. El valor del nonce devuelto
9 // es una indicación de la carga de trabajo necesaria
10 // (a mayor valor, mayor carga de trabajo).
11
12 // Usamos el módulo crypto para obtener la clave hash.
13 const crypto = require(’crypto’);
14
15 function findNonce(payload, n) {
16 let nonce = 0;
17 while (true) {
18 // creamos un objeto hash SHA-256 de crypto
19 const hash = crypto.createHash(’sha256’);
20 // concatenamos los datos de entrada con el nonce
21 const data = payload + nonce;
22 // calculamos la clave hash
23 hash.update(data);
24 const hex = hash.digest(’hex’);
25 // comprobamos si cumplimos la condición
26 if (hex.slice(0, n / 4) === ’0’.repeat(n / 4)) {
27 return { nonce, hash: hex };
28 }
29 // el valor del nonce se incrementa hasta que se obtiene
30 // una clave que cumple la condición.
31 nonce++;
32 }
33 }

Esta función añade a la cadena de entrada un valor (nonce) y calcula la clave hash del conjunto.
Va probando con sucesivos nonces hasta que consigue generar una clave con el número de ceros
requerido. Por ejemplo, si le pasamos la cadena Datos para prueba de trabajo con tres valores
de n diferentes (8, 16 y 20) y medimos los tiempos de ejecución en cada caso:

1 //
2 // Extracto de código para probar la función anterior
3 //
4 const st2 = new Date().getTime();
5 const r2 = findNonce(’Datos para prueba de trabajo’, 8);
6 const end2 = new Date().getTime();
7 console.log(‘Nonce: ${r2.nonce}, Hash: ${r2.hash}, Time: ${end2 - st2}ms‘);
8
9 const st3 = new Date().getTime();
10 const r3 = findNonce(’Datos para prueba de trabajo’, 16);
11 const end3 = new Date().getTime();
12 console.log(‘Nonce: ${r3.nonce}, Hash: ${r3.hash}, Time: ${end3 - st3}ms‘);
13
14 const st4 = new Date().getTime();
15 const r4 = findNonce(’Datos para prueba de trabajo’, 20);
16 const end4 = new Date().getTime();
17 console.log(‘Nonce: ${r4.nonce}, Hash: ${r4.hash}, Time: ${end4 - st4}ms‘);

12
Obtenemos los resultados del cuadro 1.

Cuadro 1: Carga de trabajo para distintos valores de ’n’ en ‘findNonce’.

n Nonce Hash Tiempo


8 10 0x006e957be2c1921... 1 ms
16 67777 0x0000515eb48b04d... 172 ms
20 233842 0x00000ff442811a1... 555 ms

Aunque el tiempo necesario para calcular el hash depende de la cadena de entrada, en promedio
el tiempo de cálculo, y por lo tanto el trabajo necesario para resolver el reto, crecerá exponencialmen-
te con el número de bits iniciales a cero requeridos. Ajustando el número de ceros modelamos la
dificultad del reto. La función siguiente ilustra el minado de un bloque mediante este sistema.

1 //
2 // Función ilustrativa de minado de un bloque mediante prueba de trabajo.
3 //
4 // Esta función utiliza la función findNonce() de los ejemplos anteriores
5 // para calcular el hash y el nonce del nuevo bloque.
6 // Toma cuatro parámetros:
7 // * transaction (la cadena que representa la transacción a incluir en el bloque),
8 // * prev_hash (el hash del bloque anterior),
9 // * height (la altura del bloque anterior),
10 // * diff (el parámetro n a pasar a la función findNonce()
11 // para encontrar el hash de este bloque).
12 //
13 // La función concatena los cuatro parámetros de entrada en una cadena y
14 // la pasa a findNonce() para encontrar el nonce y el hash del nuevo bloque.
15 // El tiempo necesario para encontrar el nonce y el hash también se registra
16 // utilizando new Date().getTime(). La transacción resultante, prev_hash,
17 // height, hash, nonce, diff, el tiempo requerido para encontrar el nonce
18 // y el hash se almacenan en un objeto blockNode y se devuelve.
19 //
20 const crypto = require(’crypto’);
21
22 function createBlockNode(transaction, prev_hash, height, diff) {
23 // momento del minado
24 const start = new Date().getTime();
25 // incrementamos la altura en 1.
26 height++;
27 // calculamos el hash con la dificultad pasada como parámetro
28 const { nonce, hash } = findNonce(transaction + prev_hash + height + diff, diff);
29 // momento de finalización del minado.
30 const end = new Date().getTime();
31 // tiempo necesario para el minado en milisegundos
32 const time = end - start;
33 // construimos el nuevo bloque
34 const blockNode = { height, nonce, diff, time, prev_hash, hash, transaction };
35 // devolvemos el bloque construído
36 return blockNode;
37 }

Si dos mineros minan simultáneamente un bloque válido, se crea una bifurcación temporal en la
cadena de bloques y la red tendrá dos versiones válidas de la cadena de bloques. El resto de los nodos
de la red añadirán el bloque que reciban primero a su copia local de la cadena de bloques y, a partir
de ahí, seguirán ampliando la cadena. Esto crea una situación en la que algunos nodos tienen una
versión de la cadena de bloques y otros nodos tienen la otra versión.

13
Más tarde o más temprano, la red convergerá eligiendo la cadena más larga, ya que los nodos
siempre deben elegir extender la cadena más larga que conozcan. Esto significa que uno de los dos
bloques en competencia será descartado, y la red seguirá construyendo sobre la cadena más larga.
En consecuencia, los mineros deben esperar a que su bloque sea confirmado por la red antes de dar
por hecho que se ha añadido definitivamente a la cadena de bloques. De lo contrario, se arriesgan a
malgastar recursos en un bloque que, en última instancia, puede ser descartado en favor de un bloque
competidor.
En una blockchainde prueba de participación, el proceso de creación de nuevos bloques es dife-
rente de la minería, y la mayoría de las veces se denomina simplemente creación de bloques aunque
también podemos encontrar expresiones como forging o minting. A diferencia de la prueba de traba-
jo, que se basa en la potencia computacional y la resolución de puzles criptográficos, la prueba de
participación se basa en un conjunto diferente de reglas para lograr el consenso y validar las tran-
sacciones. En este caso, los participantes que poseen una cierta cantidad de la criptomoneda nativa
de la cadena de bloques pueden convertirse en validadores. Los validadores son responsables de
verificar las transacciones y añadirlas a la cadena de bloques, y se seleccionan en función de su par-
ticipación, entendida como la cantidad de criptomoneda que depositan como garantía o la cantidad
de criptomoneda que poseen. Cuanta más criptomoneda posea o aporte un validador, mayores serán
sus posibilidades de ser seleccionado para construir el siguiente bloque.
El proceso de forjado en una blockchain de prueba de participación suele implicar los siguientes
pasos:

1. Depósito del aval: los validadores colocan una cierta cantidad de criptomoneda como aval, que
sirve como garantía e incentiva el buen comportamiento. Si se descubre que un validador actúa
de forma malintencionada, su aval puede ser ejecutado como penalización.
2. Selección: se seleccionan forjadores para crear un nuevo bloque en función de su participación,
y se convierten en responsables de verificar las transacciones y crear un bloque.
3. Forjado del bloque: los validadores seleccionados crean un nuevo bloque y lo transmiten a la red
para su verificación.
4. Verificación: otros validadores de la red verifican el bloque y lo añaden a la cadena de bloques
si es válido.

Al igual que en el caso anterior, los validadores que añaden con éxito un bloque a la cadena de
bloques son recompensados con comisiones por transacción y criptomoneda recién acuñada.
La prueba de participación se considera una alternativa más eficiente energéticamente que la prue-
ba de trabajo, ya que no requiere el mismo nivel de potencia de cálculo y consumo eléctrico. También
se considera más respetuosa con el medio ambiente, ya que no requiere hardware especializado co-
mo circuitos integrados específicos (ASIC) o procesadores gráficos (GPU). Por otra parte, el proceso
de selección de validadores evita en la mayoría de los casos la creación de bifurcaciones en la cadena
de bloques. De todos modos, la prueba de participación no está exenta de dificultades, como el riesgo
de centralización y el reto de garantizar que los validadores actúen en interés de la red y no en el suyo
propio.
En una cadena de bloques con tolerancia a fallos bizantinos (BFT), los nodos trabajan juntos para
acordar el estado de la red y crear nuevos bloques. El proceso de creación de nuevos bloques en una
cadena de bloques BFT consta de varios pasos:

1. Selección de nodos: en una blockchain BFT, se selecciona un subconjunto de nodos para pro-
poner nuevos bloques a la red. El número de nodos seleccionados y el proceso de selección de-
pende de la implementación específica del algoritmo de consenso, pero suele estar entre unas
docenas y unos cientos.
2. Propuesta: los nodos seleccionados forjan un nuevo bloque difundiéndolo a la red. El bloque
contiene una lista de transacciones que el nodo proponente ha considerado válidas.

14
3. Validación: una vez propuesto un bloque, los demás nodos de la red lo validan. Los nodos rea-
lizan una serie de comprobaciones criptográficas para asegurarse de que el bloque es válido y
de que las transacciones que contiene también lo son. Si el bloque no es válido, se rechaza y
comienza de nuevo el proceso de creación de un nuevo bloque.
4. Precompromiso: si la red considera válido un bloque, los nodos entran en una fase de precom-
promiso. Durante esta fase, los nodos señalan su intención de añadir o no el bloque a la cadena
de bloques emitiendo un mensaje a la red.
5. Compromiso: una vez que una supermayoría de nodos (normalmente dos tercios o más) ha
manifestado su intención de añadir el bloque a la cadena de bloques, el bloque se añade a la
cadena de bloques y los nodos pasan al siguiente bloque.
El código siguiente ilustra la evolución del algoritmo BFT con tres nodos. La función comienza ge-
nerando un mensaje inicial aleatorio para cada nodo, para indicar si ese nodo acepta el nuevo bloque.
Esa decisión puede ser honesta (el bloque es realmente válido o inválido, y el nodo dice la verdad)
o deshonesta (el nodo pretende engañar al resto de los nodos). A continuación, cada nodo envía su
mensaje a los demás nodos. Cada nodo recibe los mensajes de los otros nodos y decide un veredicto
final basado en los mensajes recibidos utilizando la función de ayuda decideMensaje. Por último, la
función comprueba si todos los nodos han acordado el mismo mensaje y muestra el resultado en la
consola.

1 //
2 // Esta función toma tres argumentos que representan los
3 // tres nodos del sistema. Se supone que cada nodo tiene
4 // un método de envío con dos argumentos (los dos mensajes
5 // a enviar a los otros dos nodos) y un método de recepción
6 // que recibe los mensajes de los otros nodos.
7 //
8 // Suponemos que los nodos que participarán en el consenso han
9 // sido seleccionados previamente (nodo1, nodo2 y nodo3) y
10 // que los nodos forjadores han propuesto un nuevo bloque.
11 //
12 function byzantineFaultTolerant(nodo1, nodo2, nodo3) {
13 // Comienzo de la fase de Validación. En este ejemplo
14 // cada nodo valida o no el bloque aleatoriamente
15 // con un mensaje inicial (0 o 1).
16 var nodo1Mensaje = Math.round(Math.random());
17 var nodo2Mensaje = Math.round(Math.random());
18 var nodo3Mensaje = Math.round(Math.random());
19
20 // y difunde su veredicto a la red, es decir,
21 // cada nodo envía su mensaje a los demás nodos.
22 nodo1.send(nodo2Mensaje, nodo3Mensaje);
23 nodo2.send(nodo1Mensaje, nodo3Mensaje);
24 nodo3.send(nodo1Mensaje, nodo2Mensaje);
25
26 // Cada nodo recibe los mensajes de los otros nodos
27 var nodo1MensajesRecibidos = [nodo2Mensaje, nodo3Mensaje]
28 var nodo2MensajesRecibidos = [nodo1Mensaje, nodo3Mensaje]
29 var nodo3MensajesRecibidos = [nodo1Mensaje, nodo2Mensaje];
30
31 // Fase de Precompromiso. Cada nodo expresa su intención
32 // de añadir o no el nuevo bloque, en función de los
33 // mensajes recibidos.
34 var nodo1MensajeFinal = decideMensaje(nodo1MensajesRecibidos);
35 var nodo2MensajeFinal = decideMensaje(nodo2MensajesRecibidos);
36 var nodo3MensajeFinal = decideMensaje(nodo3MensajesRecibidos);
37
38 // Fase de Compromiso. Si todos los nodos acuerdan añadir el
39 // bloque (acuerdo de mensaje 1), el nodo se añade a la red.
40 // Comprobamos si todos los nodos han acordado el mismo mensaje

15
41 // y que el mensaje es 1.
42 if (nodo1MensajeFinal === nodo2MensajeFinal
43 && nodo1MensajeFinal === nodo3MensajeFinal) {
44 if (nodo1MensajeFinal == 1) {
45 console.log("Bloque correcto. Añádase");
46 } else {
47 console.log("Bloque incorrecto. Descártese");
48 }
49 } else {
50 console.log("Bloque incorrecto. Descártese");
51 }
52 }
53
54 // Fase de Validación.
55 // Función para decidir un mensaje final en base
56 // a los mensajes recibidos.
57 function decideMensaje(mensajesRecibidos) {
58 // Cuenta el número de mensajes 0 y 1
59 var count0 = 0
60 var count1 = 0;
61 for (var mensaje of mensajesrecibidos) {
62 if (mensaje === 0) {
63 count0++;
64 } else if (mensaje === 1) {
65 count1++;
66 }
67 }
68
69 // Si hay más mensajes 0 que 1, nos decidimos por 0;
70 // En caso contrario, nos decidimos por 1
71 if (count0 > count1) {
72 return 0;
73 } else {
74 return 1;
75 }
76 }

Se trata de una versión simplificada del algoritmo BFT que no tiene en cuenta todos los escenarios
de fallo posibles. En la práctica, el algoritmo es bastante más complejo para garantizar la tolerancia
a fallos y la seguridad. Además, en este ejemplo sencillo consideramos que la mayoría para aceptar
el nuevo bloque se alcanza por consenso de todos los nodos (más exigente que la mayoría de 51 %
comentada antes).
El mecanismo de consenso BFT está diseñado para ser tolerante con los fallos bizantinos, que
son fallos que hacen que los nodos se comporten de forma inesperada o maliciosa. Al exigir que una
mayoría cualificada (generalmente dos tercios o más) de nodos se ponga de acuerdo sobre la validez
de un bloque, el consenso BFT es capaz de proteger frente a ataques en los que interviene un pequeño
número de nodos maliciosos.

4. Ventajas e inconvenientes de las cadenas de bloques

Las principales ventajas de la tecnología blockchain nacen de sus características distintivas: su


naturaleza descentralizada, su inmutabilidad, su transparencia, sus características de seguridad y su
eficiencia computacional.
La naturaleza descentralizada de la cadena de bloques significa que no necesita de una autoridad
central que la controle o la gestione, lo que la hace especialmente resistente a los ataques informá-

16
ticos y a la manipulación. Incluso en el caso de redes privadas, donde una autoridad central autoriza
a determinados perfiles de usuario a interactuar con la red, su naturaliza descentralizada la hace re-
sistente tanto a ataques internos como externos porque no existe un único punto de fallo o riesgo de
ataque.
La inmutabilidad de las cadenas de bloques implica que, una vez que un bloque se añade a la
cadena de bloques, no puede alterarse ni borrarse sin el consenso de la red. En caso de que se de-
cida modificar o eliminar un bloque o una transacción dentro de un bloque, la acción se materializa
mediante una nueva transacción o un nuevo bloque que declara inválida la transacción original o ma-
terializa la versión modificada de la transacción original. En otras palabras, los cambios en la red se
van apuntando en un libro mayor de manera incremental. Las entradas originales no se modifican.
Esto garantiza la integridad, la trazabilidad y la inmutabilidad de los datos almacenados en la cadena
de bloques.
Como consecuencia de lo anterior, dado que las cadenas de bloques son descentralizadas e inmu-
tables, no necesitan de un actor que aporte confianza, lo que significa que los participantes pueden
fiarse de los datos almacenados en la cadena de bloques sin depender de un intermediario de con-
fianza. Todas las transacciones en la cadena de bloques son transparentes y pueden rastrearse hasta
su origen, bien por el público en general en las redes públicas, bien por las entidades autorizadas a in-
teraccionar en el caso de las redes privadas (usuarios, reguladores, aplicaciones, oráculos, etc.). Esto
proporciona un nivel de transparencia y una capacidad de rendición de cuentas sin precedentes.
En cuanto a la seguridad, toda blockchain utiliza técnicas criptográficas avanzadas para asegurar
la red y garantizar la privacidad y seguridad de los datos almacenados en la blockchain.
En cuanto a la eficiencia operativa, la tecnología blockchain, al eliminarse los intermediarios y los
puntos singulares de control, se facilitan transacciones más rápidas y eficientes. Además, la tecno-
logía de cadenas de bloques puede reducir significativamente los costes operativos al eliminar la ne-
cesidad de intermediarios y reducir las comisiones por transacción. Finalmente, la aparición de los
contratos inteligentes (smart contracts) tratados en la sección 5, dan soporte a transacciones au-
tomatizadas y pueden utilizarse para una amplia gama de aplicaciones, aumentando la eficiencia y
reduciendo la posibilidad de errores o fraudes.
De todos modos, también podemos identificar algunos inconvenientes de las redes de cadenas
de bloques. Por ejemplo, la tecnología actual de blockchain puede ser lenta y tener una escalabilidad
limitada, lo que dificulta la gestión de un gran número de transacciones a la vez. Esto puede dar lugar
a tiempos de transacción más lentos y comisiones más elevadas, a pesar de los ahorros obtenidos
con la eliminación de los intermediarios y la simplificación de cada transacción.
Aunque las redes de cadenas de bloques suponen en general una mejora en la eficiencia operativa,
pueden no serlo tanto en cuanto a eficiencia energética. En el caso de las redes basadas en prueba
de trabajo, el proceso de minado de bloques puede llegar a requerir una cantidad significativa de elec-
tricidad, lo que resulta en un alto consumo de energía y rechazo social debido a su posible impacto
ambiental (Islam et al., 2023).
Las redes de cadenas de bloques también plantean importantes desafíos regulatorios. La natura-
leza descentralizada y anónima de las blockchains públicas, habituales en el campo de las criptomo-
nedas, puede dificultar a los reguladores la supervisión de las actividades y aplicación de las leyes.
Esta situación se hace más patente todavía debido a la actual falta de estandarización en la indus-
tria de blockchain, con diferentes plataformas que utilizan diferentes protocolos, lo que dificulta la
interoperabilidad entre diferentes blockchains, complica el desarrollo de aplicaciones y entorpece la
monitorización y vigilancia por parte del regulador.
Otro reto reside en el cumplimiento de los requisitos de las normas de protección de la informa-
ción personal, como la normativa europea de protección de datos (es decir, el Reglamento General de
Protección de Datos, RGPD). Derechos como el derecho de oposición al tratamiento de datos perso-

17
nales o el derecho al olvido en el mundo digital son difíciles de conseguir cuando se almacenan da-
tos personales en una blockchain, debido a sus características de inmutabilidad (Delgado-von-Eitzen,
Anido-Rifón y Fernández-Iglesias, 2021a).
La falta de estandarización junto con la complejidad de la tecnología blockchain, puede dificultar
su comprensión y uso efectivo por parte de usuarios no técnicos, lo que limita su potencial adopción
y aumenta los riesgos en cuanto a seguridad. Aunque la cadena de bloques se considera segura,
siempre existe el riesgo de que se produzcan ataques y fallos de seguridad debidos a vulnerabilidades
o errores de programación, sobre todo en las cadenas de bloques más nuevas o menos consolidadas.
Dedicamos el apartado siguiente a comentar los aspectos relativos a la seguridad más importantes.
Finalmente, la operación de todas las cadenas de bloques, dado su naturaleza distribuida, depen-
den de una buena conectividad a Internet, lo que puede suponer un reto en zonas con infraestructuras
deficientes o conectividad limitada.

4.1. Aspectos de seguridad

La seguridad de una red blockchain depende de diversos factores, como por ejemplo el mecanis-
mo de consenso utilizado, el tamaño y la distribución de la red, los algoritmos criptográficos utilizados
y el comportamiento de los participantes. Si una red blockchain utiliza un mecanismo de consenso
seguro y descentralizado como los del apartado 3.2, y cuenta con una red de nodos amplia y diversa,
puede considerarse relativamente segura. Si los algoritmos criptográficos utilizados siguen los están-
dares habituales y los participantes se comportan honestamente, la seguridad de la red se refuerza
todavía mas.
Sin embargo, ningún sistema es completamente inmune a los ataques, y las redes blockchain no
son una excepción. Por ejemplo, un atacante decidido y con recursos suficientes podría, al menos en
teoría, lanzar un ataque del 51 % a una red basada en prueba de trabajo o un ataque de largo alcance
a una red basada en prueba de participación, entre otros ataques. Hay varios tipos de ataques que
pueden dirigirse a una red blockchain. A continuación citamos los más habituales.
El ataque de los nodos bizantinos ocurre cuando un nodo malicioso (llamado nodo bizantino) pue-
de intentar interrumpir el proceso de consenso difundiendo un bloque diferente o reteniendo bloques.
Esto puede dar lugar a bifurcaciones en la cadena de bloques, donde diferentes nodos tienen dife-
rentes puntos de vista del estado de la cadena de bloques. El nombre proviene del problema de los
generales bizantinos formulado por Leslie Lamport, Robert Shostak y Marshall Pease (1982). El pro-
blema consiste en que un grupo de generales bizantinos acampados a las afueras de una ciudad,
cada uno al mando de una parte del ejército, deben coordinar su ataque o retirada sobre la ciudad,
pero sólo pueden comunicarse entre sí enviándose mensajes a través de mensajeros. Algunos de los
generales son traidores y pueden enviar mensajes contradictorios o falsos para confundir a los ge-
nerales leales. Los generales leales deben llegar a un consenso sobre si atacar o retirarse, incluso en
presencia de traidores. El problema tiene importantes implicaciones para los sistemas distribuidos
y las redes informáticas, donde los mensajes pueden perderse o corromperse, y los nodos pueden
fallar o comportarse maliciosamente.
El comentado ataque del 51 % se produce cuando una única entidad o grupo de entidades controla
el 51 % o más de la potencia de cálculo de la red de prueba de trabajo, lo que les permite manipular la
red creando transacciones fraudulentas, realizando un doble gasto o excluyendo a otros mineros de
la red (Shanaev et al., 2019).
Un ataque de largo alcance es un tipo de ataque que se basa en crear una nueva blockchain a partir
del bloque génesis, utilizando un histórico alternativo diferente del de la red original (Deirmentzoglou,
Papakyriakopoulos y Patsakis, 2019). Este tipo de ataque es posible porque la seguridad de muchas
redes blockchain, especialmente las redes de prueba de participación, se basa en la suposición de

18
que una gran proporción de los validadores tienen un historial largo y continuo de participación en la
red. Si un atacante puede obtener una cantidad significativa de participaciones o controlar un gran
número de nodos de la red, puede crear potencialmente una nueva cadena de bloques más larga que
la original y convertirse así en la cadena dominante.
El ataque de Sybil se produce cuando un único usuario crea múltiples identidades o nodos en
la red, lo que le permitiría controlar una parte significativa de los nodos avalistas o de la potencia
de cálculo de la red y manipular las transacciones. Este tipo de ataque es posible porque muchas
redes blockchain, especialmente las redes públicas que se basan en la prueba de trabajo o la prueba
de participación, no exigen ningún procedimiento de verificación de identidad o de conocimiento del
cliente para unirse a la red. Un atacante puede crear múltiples identidades o nodos falsos y utilizarlos
para obtener una influencia desproporcionada sobre la red, por ejemplo controlando el proceso de
consenso o censurando transacciones. El nombre de este ataque está inspirado en un libro de 1973
titulado Sybil, una mujer a la que se diagnostica un trastorno de identidad disociativo (Schreiber, 1973).
El ataque de eclipsado consiste en controlar la comunicación de red de un nodo víctima, de modo
que sólo reciba datos de un nodo malicioso, aislándolo de hecho del resto de la red (Yves-Christian et
al., 2018). Los ataques de eclipsado son posibles en las redes blockchain porque estas redes se basan
en un protocolo de comunicación peer-to-peer (P2P) para propagar información y transacciones entre
nodos. El protocolo P2P permite a cualquier nodo conectarse a cualquier otro nodo de la red, y no
existen mecanismos integrados para verificar la identidad o reputación de los nodos conectados.
Además, muchas redes blockchain, especialmente las que utilizan el consenso de prueba de trabajo,
dependen de un gran número de conexiones peer-to-peer para validar las transacciones y lograr el
consenso. Esto las hace vulnerables a los ataques de eclipsado, ya que un atacante puede controlar
una pequeña parte de los nodos de la red y manipular el flujo de información, dificultando que los
nodos objetivo reciban información correcta y participen en el proceso de consenso.
Los atacantes también pueden aprovechar vulnerabilidades o errores de programación en los con-
tratos inteligentes. Como veremos en el apartado 5 siguiente, Los contratos inteligentes son progra-
mas almacenados en la blockchain que pueden ejecutarse automáticamente cuando se cumplen de-
terminadas condiciones. Si un contrato inteligente contiene vulnerabilidades, los atacantes pueden
aprovecharlas para ejecutar código malicioso.
El ataque de secuestro de marca de tiempo o timejacking consiste en manipular la marca de tiem-
po de un bloque, lo que permitiría a un atacante manipular el orden de las transacciones o crear tran-
sacciones fraudulentas (Ma, Ge y Zhou, 2020).
Al igual que en cualquier sistema distribuido, los ataques de denegación de servicio (DoS) persi-
guen sobrecargar la red con un gran número de transacciones no válidas, dificultando o imposibili-
tando el procesamiento de las transacciones legítimas (Carl et al., 2006). Otro ataque genérico contra
sistemas distribuidos es el ataque de enrutamiento, que se produce cuando un atacante manipula
las tablas de enrutamiento de la red para redirigir el tráfico a un nodo malicioso, lo que en caso de
blockchain facilitaría la manipulación de transacciones o la sustracción de criptomonedas (Aggarwal
y Kumar, 2021).
Para mitigar estos ataques, las redes blockchain utilizan diversas medidas de seguridad, como
algoritmos de consenso, criptografía y supervisión de la red. Además, las actualizaciones periódicas
de software, las auditorías de código y las pruebas de penetración pueden ayudar a identificar y abor-
dar las vulnerabilidades de la red. En definitiva, es fundamental supervisar y mejorar continuamente la
seguridad de una red blockchain, a través de medidas como las auditorías periódicas, el establecimien-
to de recompensas por errores y vulnerabilidades encontradas y mediante actualizaciones frecuentes
del software y los protocolos utilizados.

19
5. Contratos inteligentes y dApps

En general, los contratos inteligentes se definen como contratos digitales autoejecutables en los
que los términos del acuerdo entre las partes firmantes del contrato se expresan directamente en
líneas de código software. En otras palabras, un contrato inteligente es un contrato que se puede acti-
var de manera automática que aplica las normas y condiciones de un acuerdo entre dos o más partes.
En el ámbito de las cadenas de bloques, se materializa en un programa informático almacenado en
un nodo de una red blockchain, que se ejecuta en dicha red, y que puede programarse para activar
automáticamente acciones, transacciones u otros eventos en función de condiciones predefinidas.
Los contratos inteligentes pueden utilizarse para una amplia gama de aplicaciones, como por
ejemplo las transacciones financieras, la gestión de cadenas de suministro, la creación y transferencia
de activos digitales o los sistemas de votación. Están diseñados para ser transparentes y seguros, y
pueden ayudar a reducir los costes de las transacciones, mejorar la eficiencia y aumentar la transpa-
rencia y la confianza entre los diferentes actores que participan en una blockchain.
Una dApp (decentralized Application, aplicación descentralizada) es una aplicación que se ejecuta
en una red blockchain y está diseñada para funcionar de forma descentralizada y autónoma, sin ne-
cesidad de intermediarios ni servidores centrales, lo que reduce el riesgo de fraude o manipulación.
En una dApp, la lógica de servidor de la aplicación se implementa como un contrato inteligente o un
conjunto de contratos inteligentes desplegados en una red blockchain. Los usuarios interactúan con
la dApp a través de una interfaz de usuario, habitualmente una aplicación web o una aplicación móvil
(ver figura 2).

Figura 2: Estructura típica de una dApp. El contenido estático y el código de la aplicación (p. ej., app móvil o código JavaScript
del cliente) se toma de un servidor de contenidos, mientras que la lógica se implementa mediante la orquestación de una
serie de contratos inteligentes en una blockchain.

Las dApps representan un nuevo paradigma para construir y desplegar aplicaciones descentrali-
zadas que explotan las ventajas de las redes blockchain para obtener una mayor seguridad, transpa-
rencia y fiabilidad, en comparación con las aplicaciones centralizadas tradicionales. Las dApps suelen
ser de código abierto, lo que significa que el código está disponible públicamente para que cualquie-
ra pueda verlo, usarlo y modificarlo. Además, las dApps no están controladas por ninguna autoridad
central, lo que las hace resistentes a la censura y la manipulación. Dada su naturaleza, los requisitos
de las dApps se materializan mediante contratos inteligentes, que son visibles y transparentes. Las

20
dApps están protegidas por la tecnología blockchain subyacente, que utiliza criptografía para proteger
la integridad de los datos y evitar accesos no autorizados.
Como ejemplo de dApp, podemos diseñar una plataforma de redes sociales completamente des-
centralizada y que utilice como soporte para la gestión de los datos de los usuarios una cadena de
bloques. Esta red social aprovecharía las ventajas de la tecnología blockchain para proporcionar una
plataforma segura, transparente y descentralizada para que los usuarios interactúen y compartan
contenidos. La plataforma permitiría a los usuarios crear perfiles, publicar contenidos e interactuar
con otros usuarios, como cualquier otra red social. Sin embargo, en lugar de estar controlada por una
autoridad central, la plataforma funcionaría almacenando la información en una blockchain, lo que a
su vez garantizaría la seguridad, la transparencia y la inmutabilidad. Cuando un usuario crea un perfil
en nuestra plataforma descentralizada de redes sociales, su información se almacena en la cadena
de bloques, lo que garantiza que la información está segura y no puede ser manipulada por nadie.
Cuando un usuario crea una publicación o interactúa con otro usuario, esta información también se
almacena en la blockchain, lo que proporciona un registro transparente e inmutable de toda la acti-
vidad en la plataforma. Dado que la plataforma está descentralizada, no existe una autoridad central
que la controle o pueda censurar contenidos. En su lugar, la plataforma funcionaría mediante un me-
canismo de consenso, en el que los usuarios deciden colectivamente qué contenidos son válidos y
cuáles no. Esto garantiza que la plataforma sea realmente abierta y accesible a todos los usuarios,
independientemente de su ubicación geográfica o sus opiniones políticas.
Las aplicaciones en el ámbito de las finanzas descentralizadas (DeFi, (Decentralized Finances)
también son buenos ejemplos de dApps. Se trata de un sector en rápido crecimiento que aprovecha la
tecnología blockchain para ofrecer servicios financieros sin necesidad de intermediarios tradicionales
como los bancos. Podemos imaginar una plataforma de préstamos construida sobre una red block-
chain que opera de forma descentralizada sin el control de las entidades financieras. La plataforma
permitiría a los usuarios prestar y tomar prestados activos digitales como criptomonedas, stableco-
ins, tokens no fungibles como los descritos en el apartado 5.4, . . . . Las stablecoins o criptomonedas
estables son criptomonedas indexadas a una moneda tradicional como el euro o el dólar, y por lo
tanto estables con relación a estas últimas. Cuando un usuario desea prestar activos digitales en la
plataforma, deposita sus activos en un contrato inteligente en la red blockchain. El contrato inteligente
empareja automáticamente a prestamistas con prestatarios en función de los tipos de interés y las
condiciones de préstamo deseados. Una vez concedido el préstamo, el prestatario recibe los activos
digitales y el prestamista recibe los intereses de su depósito. Dado que la plataforma de préstamos
se basa en una red blockchain, es transparente y segura. Todas las transacciones y actividades de
préstamo se registran en la cadena de bloques, proporcionando un registro transparente e inmutable
de todas las actividades de préstamo. Esto garantiza que la plataforma de préstamos sea fiable y fun-
cione de forma segura y transparente. Además, la plataforma de préstamos opera sin necesidad de
intermediarios, lo que puede reducir los costes de transacción y proporcionar una mayor accesibilidad
a los servicios financieros. Esto puede ser especialmente beneficioso para particulares y empresas
de países en desarrollo o para quienes no tienen acceso a los servicios bancarios tradicionales.
En los párrafos siguientes explicamos en líneas generales cómo abordar el desarrollo de contra-
tos inteligentes y dApps. A continuación, describimos los aspectos relacionados con la seguridad más
relevantes en el desarrollo de contratos inteligentes. Más adelante presentamos un caso de uso con-
creto muy populares en el mundo de los contratos inteligentes y dApps: los tokens no fungibles o
NFT.

5.1. Programación de contratos inteligentes y dApps

Los contratos inteligentes se construyen utilizando lenguajes de programación específicos como


Solidity, Vyper o Scilla, o lenguajes de propósito general como Rust, Go o Java Script. Cada blockchain

21
que soporta contratos inteligentes promueve su propio lenguaje de preferencia e incluso su propio
modelo de despliegue. Solidity (Chittoda, 2019a) es el lenguaje de programación más utilizado con di-
ferencia para desarrollar contratos inteligentes en la blockchain de Ethereum. Es similar a JavaScript
y está diseñado para ser fácil de aprender y usar. Vyper (Mahmoodi, 2020) es un lenguaje más recien-
te, también de Ethereum, diseñado para ser más seguro y fácil de auditar que Solidity. Rust (Klabnik
y Nichols, 2019) es un lenguaje de programación de sistemas ya consolidado que está ganando popu-
laridad para desarrollar contratos inteligentes en la blockchain Polkadot. Una versión modificada del
lenguaje Go es el lenguaje de Hyperledger Fabric para desarrollar sus contratos inteligentes, llamados
chaincodes (Abdelhady, 2019). Scilla es el lenguaje de la cadena de bloques Zilliqa para sus contratos
inteligentes (Zilliqa Team, 2019). Es un lenguaje diseñado para ser más seguro y más fácil de auditar
que Solidity, e incluye características como el análisis estático y la verificación formal.
Los contratos inteligentes, una vez programados y compilados se almacenan en una red block-
chain mediante una transacción específica, lo que los hace inmutables y a prueba de manipulaciones.
El código de los contratos inteligentes permite realizar transacciones automatizadas y sin supervi-
sión entre las partes, eliminando la necesidad de intermediarios, como la entidades financieras o los
reguladores.
En general, crear un contrato inteligente implica identificar el problema, elegir una plataforma
blockchain, escribir el código, probar y desplegar el contrato e interactuar con él en la red blockchain.
En primer lugar se trataría de identificar y caracterizar el problema o tarea que el contrato inteligen-
te pretende resolver, es decir, determinar las reglas y condiciones que regirán la ejecución del contrato.
Por ejemplo, en el contexto de la gestión de cadenas de suministro, nuestro reto puede consistir en
automatizar el seguimiento y la verificación de las mercancías a medida que avanzan por la cadena.
Podría programarse un contrato inteligente para liberar automáticamente el pago a un proveedor una
vez que el comprador haya recibido y verificado un envío de mercancías. Una vez que el contrato co-
nozca que la entrega de la mercancía ha sido verificada, el contrato puede realizar las transacciones
necesarias para transferir criptomonedas de la cartera del comprador al vendedor.
Una vez que hemos completado la fase anterior de caracterización del problema y captura de
requisitos, es necesario elegir una plataforma de cadena de bloques que admita contratos inteligentes,
intentando que sea la más adecuada a las características de nuestro caso de uso. Seleccionar la
cadena de bloques adecuada para desplegar nuestros contratos inteligentes puede ser una decisión
compleja, ya que las distintas cadenas de bloques tienen características y capacidades diferentes
que pueden ser más adecuadas para determinadas aplicaciones. La blockchain elegida debe tener
cierta reputación de fiabilidad y seguridad para garantizar la integridad de los contratos inteligentes
y evitar accesos o modificaciones no autorizadas. Debe tener además una estructura de gobierno
clara y cumplir con toda la normativa y los estándares industriales aplicables. Por otra parte, debe ser
capaz de manejar el número de transacciones y ejecuciones de contratos inteligentes suficiente para
nuestra aplicación. La interoperabilidad es otro criterio importante, ya que la cadena de bloques debe
ser capaz de integrarse con los sistemas y plataformas requeridos por nuestro caso de uso (p, ej.,
el sistema logístico existente en una cadena de suministro o determinados oráculos de los descritos
en el apartado 7). Finalmente, el coste de desplegar y ejecutar contratos inteligentes en la blockchain
debe ser razonable y competitivo en comparación con otras opciones.
Hay diversas formas de interaccionar con una blockchain. Lo más habitual es que no dispongamos
de un nodo de la red blockchain propio, por lo que tendremos que valernos de alguna plataforma
que nos ofrezca una interfaz del programador (API) que nos permita comunicarnos con la cadena
elegida sin tener que ejecutar nuestros propios nodos. Estas plataformas también suelen contar con
herramientas de desarrollo para el seguimiento y análisis de nuestros contratos inteligentes.
El siguiente paso consiste en configurar un entorno de desarrollo. Esto suele implicar la instalación
del software necesario y la configuración de una cartera para pruebas y despliegue. Como acabamos
de indicar, existen plataformas que proporcionar herramientas de desarrollo sólidas y una comuni-

22
dad activa para dar soporte al desarrollo y al despliegue de contratos inteligentes. Por ejemplo, Remix
(Towaha, 2019) es un IDE (Entorno de Desarrollo Integrado) basado en web para escribir, probar y des-
plegar contratos inteligentes en la red Ethereum. Proporciona una interfaz fácil de usar para compilar
y desplegar contratos inteligentes, y también incluye un marco de pruebas integrado. Truffle Suite
(Chittoda, 2019b) es otro marco de desarrollo para Ethereum que incluye herramientas para compilar,
probar y desplegar contratos inteligentes. Incluye Truffle CLI, que permite a los desarrolladores gestio-
nar sus contratos inteligentes desde la línea de comandos. Ganache (Singh, 2020) es una blockchain
personal para el desarrollo de Ethereum que permite a los desarrolladores probar sus contratos in-
teligentes en un entorno local. Hardhat (Infante, 2021) es un entorno de desarrollo para construir y
desplegar contratos inteligentes en Ethereum, Binance Smart Chain y otras plataformas blockchain.
Incluye una interfaz de línea de comandos para gestionar contratos, así como un marco de pruebas
integrado y soporte para el despliegue en redes de prueba y redes principales.
Una vez elegido el entorno de desarrollo, estamos en condiciones de escribir el código de nuestro
smart contract utilizando uno de los lenguajes de programación soportados por la cadena de bloques.
Esto implicará definir las funciones, los interfaces, las estructuras de datos y la lógica que rigen el
comportamiento del contrato, de acuerdo con los requisitos identificados en la fase de análisis del
problema. Para probar y validar el contrato desarrollado, lo más habitual es utilizar una blockchain de
prueba o testnet para asegurarse de que funciona según lo previsto. Esto suele implicar el uso de una
herramienta como Remix o Truffle para desplegar e interactuar con el contrato. Las pruebas en una
red de prueba garantizan que el contrato inteligente sea seguro y esté libre de vulnerabilidades antes
de desplegarlo en la red principal o mainnet. Esto ayuda a minimizar el riesgo de pérdidas económicas
o de exponer datos sensibles debido a problemas de seguridad.
Las pruebas en una testnet permiten además a los desarrolladores verificar que el contrato inteli-
gente funciona correctamente y cumple los requisitos del caso de uso previsto, y permite a los desa-
rrolladores recibir comentarios de la comunidad e identificar posibles problemas o áreas de mejora
antes de desplegar el contrato en la red principal. Esto ayuda a garantizar que el contrato funcionará
como se espera en la red principal. Por otra parte, probar en una testnet puede ahorrar costes al evitar
las tarifas asociadas al despliegue y la ejecución de contratos inteligentes en la red principal.
A modo de ejemplo, vamos a ver cómo desplegar un contrato inteligente sencillo en la testnet
Sepolia utilizando Hardhat. Se trata de un contrato inteligente que simplemente ofrece un mensaje
almacenado cuando se consulta, y permite actualizar dicho mensaje. Su código en Solidity sería el
siguiente:

1 // SPDX-License-Identifier: MIT
2 // Sencillo contrato inteligente que difunde un mensaje y permite su
3 // actualización.
4 //
5 // Especifica la versión de Solidity, utilizando el versionado semántico.
6 // Más información:
7 // https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma
8 pragma solidity ^0.8.18;
9
10 // Define un contrato llamado ‘BroadcastMessage‘.
11 // Un contrato es una colección de funciones y datos (su estado).
12 // Una vez desplegado, el contrato residirá en una dirección específica
13 // de una blockchain. En nuestro caso, en una testnet de Ethereum
14 // llamada Solidity.
15 // Más información:
16 // https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html
17 contract BroadcastMessage {
18
19 // Declara una variable de estado ‘mensaje‘ de tipo ‘string‘.
20 // Las variables de estado son atributos cuyos valores se guardan
21 // permanentemente en el almacenamiento del contrato.

23
22 // La palabra clave ‘public‘ hace que las variables sean accesibles
23 // desde fuera de un contrato y crea una función que otros contratos o
24 // clientes pueden llamar para acceder al valor.
25 string public mensaje;
26
27 // Similar a muchos lenguajes orientados a objetos basados en clases,
28 // un constructor es una función especial que sólo se ejecuta al crear
29 // el contrato.
30 // Los constructores se utilizan para inicializar los datos del contrato,
31 // en nuestro caso el valor inicial del mensaje.
32 // Más información:
33 // https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors
34 constructor(string memory initMensaje) {
35
36 // Acepta un argumento ‘initMensaje‘ que se usa para el valor
37 // inicial del atributo ‘mensaje‘ del contrato).
38 mensaje = initMensaje;
39 }
40
41 // Finalmente, el contrato inteligente ofrece una función pública que
42 // tiene como parámetro una cadena de caracteres
43 // y actualiza el atributo‘mensaje‘.
44 function actualiza(string memory nuevoMensaje) public {
45 mensaje = nuevoMensaje;
46 }
47 }

Para desplegar el contrato inteligente en la testnet Sepolia, necesitamos configurar Hardhat con
los detalles sobre la red necesarios para dicho despliegue. Esa información la recogemos en un fichero
en JavaScript denominado hardhat.config.js:

1 //
2 // Archivo de configuración de Hardhat para nuestro proyecto de contrato
3 // inteligente sencillo.
4 //
5 // Para desplegar un contrato inteligente escrito en Solidity, necesitamos
6 // este archivo y el archivo fuente (.sol) del contrato inteligente.
7 //
8 // Módulos de Node.js utilizados:
9 // - dotenv para disponer del archivo .env para proporcionar
10 // variables de configuración (líneas VARIABLE = "valor").
11 // - hardhat-toolbox es un plugin que agrupa paquetes y plugins de Hardhat
12 // de uso común. Muy recomendado para empezar a desarrollar con Hardhat.
13 // Entre otras cosas, permite desplegar e interactiar con
14 // contratos inteligentes utilizando la biblioteca ethers.js y
15 // el plugin hardhat-ethers.
16 require(’dotenv’).config();
17 require("@nomicfoundation/hardhat-toolbox");
18
19 // URL de la API de Alchemy que utilizaremos para acceder a la red Sepolia
20 // y clave privada de la cartera de criptomonedas que utilizaremos para
21 // cubrir los gastos del despliegue. Tomamos esta información del
22 // fichero de configuración .env. Es decir, el fichero .env contiene dos
23 // líneas con la forma:
24 //
25 // API_URL = "https://XXXXXXX"
26 // PRIVATE_KEY = "XXXXXXXXXX"
27 const { API_URL, PRIVATE_KEY } = process.env;
28
29 /**
30 * @type import(’hardhat/config’).HardhatUserConfig
31 */

24
32
33 module.exports = {
34 solidity: "0.8.18", // versión mínima de Solidity
35 defaultNetwork: "sepolia", // red utilizada (testnet Sepolia)
36 networks: {
37 hardhat: {},
38 sepolia: { // datos de conexión a Sepolia:
39 url: API_URL, // URL de la API y clave de la cartera
40 accounts: [‘0x${PRIVATE_KEY}‘]
41 }
42 }
43 };

Previamente, como no disponemos de nuestro nodo propio en la red Sepolia, hemos obtenido un
punto de acceso a dicha red a través de una plataforma de desarrollo de blockchain, en nuestro caso la
plataforma Alchemy. Este trámite requiere que nos registremos en Alchemy pero es gratuito. El punto
de acceso es una URL que podemos utilizar desde nuestro código para interaccionar con Sepolia.
Podemos utilizar el código siguiente en JavaScript para desplegar el contrato:

1 //
2 // Script de despliegue para el contrato inteligente del
3 // ejemplo.
4 //
5 // Comando de despliegue:
6 //
7 // npx hardhat run scripts/deploy.js --network sepolia
8 //
9
10 const { ethers } = require("hardhat");
11
12 async function main() {
13 // Una ContractFactory es una abstracción usada para desplegar
14 // nuevos contratos inteligentes, así que broadcastMessage
15 // es una fábrica para instancias de nuestro contrato
16 // BroadcastMessage. Cuando se usa ContractFactory y Contract
17 // del plugin toolbox de Hardhat, las instancias se conectan
18 // por defecto al primer firmante (el propietario).
19 // ethers.js (que ofrece el objeto ethers) es una librería que
20 // se carga con el toolbox de Hardhat.
21 const broadcastMessage = await ethers.getContractFactory("BroadcastMessage");
22
23 // Iniciamos el despliegue. deploy devuelve una promesa que
24 // se resuelve a un objeto Contract (bcm). Este objeto tendrá
25 // un método para cada una de las funciones y atributos visibles
26 // de nuestro contrato inteligente (en nuestro caso,
27 // el atributo mensaje y el método actualiza()).
28 // Pasamos a deploy los argumentos del constructor utilizado
29 // (en nuestro caso, el mensaje inicial)
30 const bcm = await broadcastMessage.deploy("Mensaje inicial");
31 console.log("Contrato desplegado en la dirección:", bcm.target);
32 }
33 // Llamada a main() para desplegar. Si todo va bien, salimos. Si no,
34 // sacamos el mensaje de error por consola.
35 main()
36 .then(() => process.exit(0))
37 .catch(error => {
38 console.error(error);
39 process.exit(1);
40 });

25
Para terminar con este ejemplo, presentamos a continuación un sencillo programa en JavaScript
para interaccionar con nuestro contrato.

1 // Interacción con el contrato inteligente creado previamente


2 //
3 // Pide al usuario que introduzca un mensaje y lo actualiza
4 // en el contrato inteligente BroadcastMessage. Finalmente,
5 // obtiene del contrato inteligente el (nuevo) mensaje
6 // y lo saca por pantalla.
7 //
8 // Las variables de entorno se obtienen del archivo .env
9 //
10
11 // Dirección de nuestro contrato inteligente. Se obtiene al desplegarlo.
12 const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS;
13
14 // Cargamos la ABI de nuestro contacto (Application Binary Interface)
15 // para interactuar con él. La ABI también se crea al desplegar el contrato
16 const contract =
17 require("../artifacts/contracts/BroadcastMessage.sol/BroadcastMessage.json");
18
19 // Firmante
20 // Una cuenta que tiene la capacidad de firmar transacciones
21 // En nuestro caso, una cartera creada con MetaMask
22 // on fondos de la testnet Sepolia suficientes para
23 // cubrir los gastos de la interacción.
24 const ownerAddress = process.env.PUBLIC_KEY;
25 const signer = ethers.provider.getSigner(ownerAddress);
26
27 // Contrato
28 // Un objeto ethers.js que representa el contrato específico
29 // desplegado en la cadena Sepolia (BroadcastMessage)
30 // Para crear el objeto, necesitamos la dirección del contrato, el ABI y la cuenta.
31 const bcContract = new ethers.Contract(CONTRACT_ADDRESS, contract.abi, signer);
32
33 // Ahora vamos a leer el mensaje almacenado en nuestro contrato inteligente
34 // e imprimirlo en la consola. También lo actualizaremos. En JavaScript,
35 // usamos funciones asíncronas para interactuar con blockchains.
36
37 console.log("");
38
39 async function main() {
40
41 // En primer lugar, vamos a obtener el valor del atributo ’mensaje’
42
43 const mensaje = await bcContract.mensaje();
44 console.log("El mensaje actual es: " + mensaje);
45
46 // Ahora actualicemos el mensaje usando el método proporcionado
47 // por el contrato inteligente (actualiza).
48 // Usamos el módulo Node.js prompt-sync para pedir texto por consola.
49 var prompt = require(’prompt-sync’)();
50
51 // Pedimos un nuevo mensaje por consola y
52 // lo actualizamos en el contrato inteligente
53 var nuevoMensaje = prompt(’Nuevo mensaje: ’);
54 console.log(’Actualizando mensae a ’ + nuevoMensaje + ’...’);
55 const tx = await bcContract.actualiza(nuevoMensaje);
56
57 // .wait() sobre el objeto de transacción devuelto asegura
58 // que nuestro programa espere a que la transacción sea
59 // forjada en la blockchain antes de continuar.
60 // Si omitiéramos esta línea, es posible que el nuevo

26
61 // valor no esté todavía disponible al solicitarlo (puede tardar
62 // unos segundos).
63
64 await tx.wait();
65
66 // Obtenemos el nuevo valor del atributo message
67
68 const mensajeActualizado = await bcContract.mensaje();
69 console.log("El nuevo mensaje es: " + mensajeActualizado);
70 }
71
72 // Vamos allá
73
74 main();

Una vez que el contrato funciona del modo esperado en la testnet, lo desplegaríamos en una red
pública de blockchain, como por ejemplo la mainnet de Ethereum o de Hyperledger Fabric, utilizan-
do una herramienta como Remix o Truffle. Esto suele implicar el pago de una tasa de transacción
en criptomoneda. Una vez desplegado el contrato inteligente, se puede interactuar con él enviándole
transacciones desde una cartera o dApp. El contrato se ejecutará automáticamente basándose en su
lógica programada, y los resultados se registrarán en la blockchain.
Podemos ver una dApp como la orquestación de un conjunto de contratos inteligentes para obte-
ner una funcionalidad compleja. Tras elegir la plataforma blockchain y el entorno de desarrollo, nuestro
primero objetivo sería diseñar la arquitectura de la dApp. Esto implica definir el modelo de datos, crear
o identificar los contratos inteligentes que necesitamos y decidir el diseño de la interfaz y la experien-
cia del usuario (UI/UX).
Una vez que hemos identificado o desarrollado los contratos inteligentes, debemos construir un
interfaz de usuario o front-end para la dApp. Esto implica crear un diseño UI/UX fácil de usar que
permita a los usuarios interactuar con la dApp. Hay varias tecnologías populares que los desarrolla-
dores para construir front-ends para aplicaciones descentralizadas. JavaScript es con diferencia la
opción más habitual para ello. Por ejemplo, React (Chinnathambi, 2018) es una popular biblioteca de
JavaScript para construir interfaces de usuario. Permite a los desarrolladores crear componentes de
interfaz de usuario reutilizables y proporciona una forma sencilla y eficiente de gestionar el estado
de la aplicación. Material UI (Schwarzmüller, 2018) es un conjunto de componentes de React que im-
plementan las directrices de Material Design de Google. Proporciona una serie de componentes de
interfaz de usuario, como botones, formularios, cuadros de diálogo, etc., que se pueden personalizar
y personalizar fácilmente.
Vue.js (Passaglia, 2017) es otro popular framework JavaScript para la construcción de interfaces
de usuario. Proporciona una sintaxis sencilla e intuitiva y ofrece funciones como la vinculación bidirec-
cional de datos y los componentes reactivos. Angular (Schwarzmüller, 2021) es un completo frame-
work JavaScript muy utilizado para construir aplicaciones web complejas. Ofrece una amplia gama
de funciones, como plantillas, enlace de datos, inyección de dependencias, etc. Web3.js (Adaś, 2021)
es una biblioteca JavaScript que permite a los desarrolladores interactuar con contratos inteligentes
basados en Ethereum y construir aplicaciones descentralizadas. Proporciona una forma sencilla y efi-
ciente de interactuar con la red Ethereum y gestionar transacciones y eventos. Bootstrap (Spurlock,
2021) es un popular marco CSS que proporciona una serie de componentes y estilos de interfaz de
usuario preconfigurados. Se puede combinar con las tecnologías anteriores para crear diseños de
interfaz de usuario responsivos y adaptados a dispositivos móviles para aplicaciones digitales.
Las pruebas son una parte fundamental del proceso de desarrollo de dApps para verificar que
funcionan según lo previsto. Esto implica probar los contratos inteligentes en busca de errores, probar
la interfaz de usuario para validar su usabilidad y probar el rendimiento general de la dApp.

27
Después de probar la dApp, el paso final es desplegarla en la blockchain elegida. Esto implica
desplegar los contratos inteligentes en la red blockchain, desplegar el front-end en el servidor o en
las tiendas de apps y poner la dApp a disposición de los usuarios. Al igual que ocurre con los con-
tratos inteligentes, existen plataformas que ayudan a simplificar el proceso de desarrollo de dApps
permitiendo que los desarrolladores se centren en crear la funcionalidad principal de sus aplicaciones
descentralizadas en lugar de preocuparse por la infraestructura de blockchain subyacente. También
proporcionan herramientas avanzadas de análisis y monitorización para ayudar a los desarrolladores
a optimizar el rendimiento de sus DApps. Por ejemplo, OpenZeppelin es una biblioteca de contratos
inteligentes reutilizables para Ethereum que proporciona una base segura y probada para construir
aplicaciones descentralizadas. Incluye una CLI para desplegar contratos en redes Ethereum, así co-
mo un IDE en línea para probar y desplegar contratos. Otro ejemplo es Alchemy, quizá la plataforma
de desarrollo más popular en estos momentos. Se trata de una plataforma que proporciona a los
desarrolladores las herramientas y la infraestructura necesarias para crear dApps en varias redes de
cadenas de bloques. Ofrece un conjunto de herramientas para desarrolladores, como una API, herra-
mientas de depuración y análisis para crear, probar y escalar aplicaciones. Soporta varias redes, como
Ethereum, Binance Smart Chain o Polygon, entre otras.

5.2. Contratos inteligentes y criptomonedas

Como hemos visto al principio de estas notas, la primera aplicación de las cadenas de bloques
fue la de dar soporte a un sistema de criptomonedas descentralizado. De hecho, muchas cadenas de
bloques tienen únicamente esa función. En el caso de Ethereum, además de dar soporte a contratos
inteligentes y DApps, ofrece su propia criptomoneda, el Ether (ETH). Aparte de poder hacer transfe-
rencias y adquirir bienes o servicios con dicha criptomoneda, como con cualquier otra, utilizando una
cartera electrónica, también es posible utilizar contratos inteligentes para realizar dichas transferen-
cias. Al igual que una cuenta de criptomoneda en la red Ethereum, los contratos inteligentes en dicha
red también se identifican con una dirección. Del mismo modo que podemos hacer transferencias de
criptomoneda desde o con destino a una cuenta de criptomoneda, también podemos hacer transfe-
rencia desde o hacia un contrato inteligente utilizando su dirección pública.
El ejemplo que proponemos a continuación ilustra como realizar estas transferencias. Se trata de
un contrato inteligente que permite acceder a un servicio previo pago de una tasa en criptomoneda.
El contrato, ServicePaymentContract, se inicializa con un coste de servicio cuando se despliega. La
dirección que desplegó el contrato se convierte en el dueño del contrato, y será la única dirección capaz
de recuperar los fondos almacenados en el mismo. Los usuarios pueden enviar Ether al contrato en
cualquier momento, representando el pago por un servicio. En este ejemplo, pueden hacerlo de dos
maneras:
Enviando criptomoneda directamente. La función receive es de una función especial (función
fallback o de alternativa) que gestiona las transacciones entrantes de Ether cuando se envía
Ether directamente al contrato sin invocar ninguna de sus funciones públicas o externas. Es de-
cir, si transferimos fondos al contrato directamente desde una cartera, poniendo como dirección
del destinatario de la transferencia la dirección del contrato, se ejecutará esta función. En nues-
tro caso, comprueba si el Ether enviado es suficiente para cubrir el coste del servicio, y cualquier
exceso de pago se devuelve al remitente.
Mediante la invocación de una función externa o pública del contrato declarada como paga-
ble. En nuestro ejemplo, definimos la función payForService como pagable. La palabra clave
payable en la declaración de la función permite que la función reciba Ether. Los usuarios deben
enviar al menos el coste del servicio especificado como Ether para pagar por el servicio. En es-
te ejemplo, nos quedamos con toda la criptomoneda que nos envíe la dirección que invocó la
función, sin devolver cualquier exceso.

28
La variable totalCollected lleva la cuenta del total de Ether recaudado de los usuarios. Para
recuperar los fondos almacenados en el contrato, la función redeemCollectedFunds permite al pro-
pietario del contrato canjear el total de fondos recaudados mediante la transferencia de dichos fondos
a su dirección. El contrato utiliza eventos para registrar los pagos y los reembolsos de fondos.

1
2 // SPDX-License-Identifier: MIT
3 //
4 // Ejemplo para ilustrar cómo un contrato inteligente
5 // puede implementar un servicio por una tarifa (a pagar en
6 // Ether), y cómo el proveedor del servicio (es decir, el
7 // propietario del contrato en nuestri casi), puede canjear
8 // los honorarios cobrados.
9 //
10 // Se trata de un ejemplo simplificado. En el mundo real
11 // es probable que la lógica de pago y canje sea más compleja,
12 // con medidas adicionales de seguridad y control de acceso.
13 pragma solidity ^0.8.18;
14
15 contract ServicePaymentContract {
16
17 // Variables globales para recoger información sobre el
18 // propietario del contrato, la tarifa de servicio y el
19 // importe cobrado hasta el momento.
20 address public owner;
21 uint256 public serviceCost;
22 uint256 public totalCollected;
23
24 // El contrato utiliza eventos para registrar pagos y reembolsos de fondos.
25 // Evento para indicar que alguna dirección ha pagado la cuota de servicio
26 event ServicePaid(address indexed payer, uint256 amount);
27
28 // Evento para indicar que el propietario ha cobrado el
29 // saldo del contrato
30 event EtherRedeemed(uint256 amount);
31
32 // Cuando se crea el contrato, se inicializa su propietario.
33 // El creador/propietario también establece la cuota de servicio en Wei.
34 constructor(uint256 cost) {
35 owner = msg.sender;
36 serviceCost = cost;
37 }
38
39 // Para acciones disponibles sólo para el propietario del contrato.
40 modifier onlyOwner() {
41 require(msg.sender == owner, "Solo el propietario puede hacer esto.");
42 _;
43 }
44
45 // Los usuarios pueden enviar Ether al contrato, representando el pago por
46 // un servicio. La función de recepción es una función especial (función
47 // fallback) que gestiona transacciones de Ether que no se corresponden con la
48 // invocación de una función pagable de un contrato (es decir, mediante
49 // el envío de Ether al contrato con "transfer", "send" o "call").
50 // msg.data tiene que estar vacío, de lo contrario se invocaría fallback()
51 // en su lugar.
52 // Nótese que tanto receive() como fallback() se definen sin la palabra clave
53 // function.
54 // En nuestro caso, la función comprueba si el Ether enviado es suficiente
55 // para cubrir el coste del servicio.
56 // Cualquier pago en exceso se devuelve al remitente.
57 receive() external payable {

29
58 require(msg.value >= serviceCost,
59 "Pago insuficiente para acceder al servicio.");
60 uint256 excessPayment = msg.value - serviceCost;
61 totalCollected += serviceCost;
62
63 // Emite un evento para registrar el pago.
64 emit ServicePaid(msg.sender, serviceCost);
65
66 // Devuelve cualquier exceso de pago al remitente.
67 // La función msg.sender.call envía el exceso de pago en Wei a
68 // a la dirección que accede al servicio y comprueba si
69 // la transacción se ha realizado correctamente.
70 if (excessPayment > 0) {
71 (bool success, ) = msg.sender.call{value: excessPayment}("");
72 require(success, "Error al recuperar el exceso de pago.");
73 }
74 }
75
76 // Esta función encapsula el servicio como una función pagable,
77 // haciendo más intuitivo para los usuarios pagar por el servicio
78 // que simplemente enviando Ether a la dirección del contrato.
79 // El propietario también puede canjear los fondos recaudados.
80 //
81 // La palabra clave payable en la declaración de la función permite
82 // que la función reciba Ether. Los usuarios deben enviar al menos el
83 // serviceCost en Ether para pagar por el servicio.
84 // La variable totalCollected lleva la cuenta del total
85 // de Ether recaudado de los usuarios.
86 function offerServiceForAFee() public payable {
87 require(msg.value >= serviceCost,
88 "Pago insuficiente para acceder al servicio.");
89 totalCollected += msg.value;
90
91 // Emite un evento para registrar el pago.
92 emit ServicePaid(msg.sender, msg.value);
93
94 // Implementación del servicio aquí.
95 }
96
97 // Función que permite al titular del contrato rescatar los fondos
98 // El propietario del contrato llamaría a esta función para retirar
99 // el saldo de Ether del contrato.
100 function redeemCollectedFunds() public onlyOwner {
101 require(totalCollected > 0, "No hay fondos disponibles.");
102 uint256 amountToRedeem = totalCollected;
103 totalCollected = 0;
104
105 // Transifere el saldo del contrato al propietario.
106 (bool success, ) = owner.call{value: amountToRedeem}("");
107 require(success, "Error al recuperar los fondos.");
108
109 // Emite un evento para registrar la transacción.
110 emit EtherRedeemed(amountToRedeem);
111 }
112 }

En general, los contratos inteligentes de Ethereum disponen de dos funciones fallback. La receive
comentada y otra llamada directamente fallback. Que se ejecute una o la otra depende de cómo se
interaccione con el contrato inteligente (ver Fig. 3):

La función receive() se ejecuta cuando el contrato recibe Ether sin ningún dato adicional o
llamada a una de sus funciones públicas o externas. Esta función puede utilizarse para manejar

30
transferencias de Ether sencillas asociadas a acciones sencillas, como simplemente almacenar
el Ether entrante o actualizar el estado del contrato.
La función fallback() se ejecuta cuando alguien envía Ether a la dirección del contrato junto
con algún dato que no coincide con la invocación de ninguna función del contrato. Sirve como
cajón de sastre o función alternativa para transacciones con datos no válidos o no reconocidos,
o incluso para implementar un comportamiento personalizado cuando se llama a una función
desconocida.

Figura 3: Invocación de fallback() o receive().

En la práctica, los desarrolladores suelen utilizar la función receive para gestionar el Ether en-
viado directamente a la dirección del contrato, que es un caso de uso común para recibir pagos o
donaciones. La función fallback se utiliza con menos frecuencia y suele emplearse para fines más
avanzados o específicos. De todos modos, como la función fallback acepta Ether, esencialmen-
te extiende el comportamiento de receive, gestionando tanto las transferencias de Ether como las
transacciones de datos no reconocidas.
La máquina virtual Ethereum (EVM) proporciona tres objetos para interaccionar con la cadena
de bloques, llamados block, msg y tx, que proporcionan información sobre la cadena de bloques, la
información enviada al contrato inteligente en la transacción activa y la propia transacción activa. Los
atributos más relevantes de estos objetos aparecen recogidos en el cuadro 2. Disponemos además
de las funciones siguientes:
blockhash(uint blockNumber) returns (bytes32): devuelve el hash del bloque pasado
como parámetro, si el bloque es uno de los 256 bloques más recientes. En otro caso devuel-
ve 0.
gasleft() returns (uint256): devuelve la cantidad de gas remanente en el contrato.

5.3. Aspectos de seguridad

Los contratos inteligentes se han convertido en un objetivo popular para los atacantes porque
pueden llevar asociados elementos de gran valor y suelen ser complejos, lo que los hace vulnerables
a varios tipos de amenazas. En este apartado describimos los ataques más relevantes a los contra-
tos inteligentes. El código de los contratos inteligentes puede ser complejo y difícil de analizar, y los
atacantes a menudo pueden encontrar fallos de programación que les permitan manipular el estado
del contrato o eludir las medidas de seguridad.
El ataque de reentrada es uno de los ataques más comunes y peligrosos contra los contratos
inteligentes. En este tipo de ataque, el atacante explota un fallo en el código del contrato que le permite
llamar repetidamente a la misma función antes de que la llamada anterior haya finalizado. Esto puede

31
Cuadro 2: Propiedades de los objetos block, msg y tx.

block.basefee (uint) Tarifa base del bloque actual.


block.chainid (uint) Identificador de la cadena actual.
block.coinbase (address payable) Dirección del validador del bloque actual
.
block.difficulty (uint) Dificultad del bloque actual (obsoleto).
Se comporta como block.prevrandao.
block.gaslimit (uint) Límite de gas del bloque actual.
block.number (uint) Número del bloque actual.
block.prevrandao (uint) Número aleatorio proporcionado por la
Beacon Chain (ver apéndice D).
block.timestamp (uint) Timestamp del bloque actual en segun-
dos desde unix epoch (00:00:00 UTC del
1 de enero de 1970).
msg.data (bytes calldata) Calldata completo del mensaje actual.
msg.sender (address) Dirección de llamada del mensaje actual.
msg.sig (bytes4) Cuatro primeros bytes del mensaje (i.e.
identificación de la función llamada).
msg.value (uint) Cantidad de cripto enviada con el men-
saje en Wei.
tx.gasprice (uint) Precio de la transacción en gas.
tx.origin (address) Origen de la transacción actual.

desencadenar, por ejemplo, la repetición de una transferencia de activos varias veces seguidas antes
de que la primera (y supuestamente única) de ellas haya sido consolidada en el libro mayor.
Otro ataque común es uno de los habituales en ingeniería de software: el desbordamiento y sub-
desbordamiento de enteros. Estos ataques se producen cuando el código del contrato no valida co-
rrectamente los valores de entrada, lo que provoca errores matemáticos que pueden ser aprovecha-
dos por los atacantes para manipular el estado del contrato y y conseguir realizar transacciones ilíci-
tas.
Un ataque específico de las cadenas de bloques es el llamado front running. Se produce cuando un
atacante utiliza su conocimiento de las transacciones pendientes para colocar su propia transacción
por delante de otras en el conjunto de transacciones, lo que le permite manipular el estado del contrato
y potencialmente conseguir que se comporte de manera no prevista.
Como todo sistema distribuido, los contratos inteligentes también están expuestos a ataques de
denegación de servicio (DoS), en los que un atacante inunda el contrato con transacciones o datos de
entrada con el fin de sobrecargarlo y hacer que deje de funcionar.
Los contratos inteligentes a menudo dependen de bibliotecas de terceros para implementar la fun-
cionalidad deseada, como podemos ver en los ejemplos de contratos inteligentes en este manual. Los
atacantes podrían crear y distribuir bibliotecas maliciosas diseñadas para explotar vulnerabilidades
en el código del contrato.
Para mitigar estos y otros posibles ataques, es fundamental que los desarrolladores revisen y
prueben cuidadosamente el código de sus contratos inteligentes y apliquen las mejores prácticas de
seguridad y gestión de riesgos. Esto incluye la realización de auditorías de código, pruebas de vulne-
rabilidades y el uso de prácticas de codificación seguras, como la validación de entradas y el control
de acceso. En la misma línea, es conveniente utilizar aritmética de enteros segura para evitar vulnera-

32
bilidades de desbordamiento y subdesbordamiento de enteros. Las funciones y versiones obsoletas,
en bibliotecas o contratos externos, son más vulnerables a los ataques, por lo que es mejor evitar su
uso y utilizar siempre la última versión.
Para evitar los ataques basados en bibliotecas maliciosas, es importante utilizar siempre que sea
posible bibliotecas de código abierto bien auditadas. Los contratos inteligentes pueden ser complejos,
y a menudo es más seguro utilizar bibliotecas bien probadas, auditadas y ampliamente utilizadas para
funciones básicas como la criptografía y la serialización de datos. Del mismo modo, los contratos in-
teligentes que dependen de contratos externos son más vulnerables a los ataques, por lo que es mejor
minimizar su uso y confiar únicamente en contratos externos de confianza y auditados. También es
una buena práctica incluir en el código controles de acceso para evitar que usuarios no autorizados
accedan a funciones o datos sensibles, como por ejemplo un control de acceso basado en roles y el
uso de mecanismos de autenticación adecuados.
Los desarrolladores de contratos inteligentes deben probar su código a fondo antes de desplegarlo
en una red activa (mainnet), incluyendo pruebas unitarias y pruebas de integración, así como pruebas
bajo diversas condiciones de carga, utilizando para ello una red de prueba de confianza. Deben im-
plementarse también mecanismos sólidos de gestión y registro de errores para ayudar a identificar y
solucionar problemas.
La simplicidad es clave cuando se trata del desarrollo de contratos inteligentes. Un código com-
plejo puede introducir riesgos innecesarios y vulnerabilidades potenciales. Además, documentar pro-
fusamente el código es esencial para garantizar que pueda entenderse correctamente y mantenerse
a lo largo del tiempo.

5.4. Tokens no fungibles o NFT

Un token no fungible (non-fungible token o NFT) es un tipo de activo digital que representa un ar-
tículo o contenido único, como una obra de arte, un objeto coleccionable o un bien inmueble virtual en
el metaverso. A diferencia de los tokens fungibles, como las criptomonedas, que son intercambiables
entre sí y siempre tienen el mismo valor intrínseco (todos los bitcoins valen lo mismo, por ejemplo),
cada NFT es único y tiene un valor distinto. Los NFT son un fenómeno característico de la tecnología
blockchain que permite la creación y propiedad de activos digitales únicos que anteriormente eran
difíciles de verificar y monetizar.
Los NFT basados en la tecnología blockchain facilitan una propiedad segura y transparente del
activo digital. Cada NFT se almacena en una red blockchain, que proporciona un registro público de
la propiedad y las transacciones, lo que permite verificar la autenticidad y la propiedad del NFT. Los
NFT han ganado popularidad en el mundo del arte y la cultura popular como una oportunidad para
monetizar obras digitales como piezas únicas, de manera que los coleccionistas puedan poseer e
intercambien estos activos digitales. También se han utilizado en juegos, en el intercambio de cromos,
o en el mercado de bienes inmuebles virtuales, facilitando poseer e intercambiar objetos y propiedades
únicos en el metaverso.
Para crear un NFT, el primer paso sería seleccionar una plataforma blockchain que admita la crea-
ción y propiedad de activos digitales. Las plataformas más populares para crear NFT son en estos
momentos Ethereum, Binance Smart Chain y Flow. A continuación tenemos que identificar o crear
el activo digital que queremos convertir en un NFT. Puede ser una obra de arte, un clip de música o
video, un cromo virtual o cualquier otro contenido digital. Una vez que hemos seleccionado nuestro
activo digital, tenemos que acuñar el NFT para el mismo. Esto implica crear un token único que repre-
sente el activo digital en la red blockchain elegida. Además de la identificación única del propio activo,
el NFT tendrá información sobre el mismo, como su nombre, descripción, creador, localización, etc.
Esta información configuraría los metadatos del NFT. También tendremos que fijar el precio y las con-

33
diciones para su transferibilidad. El precio puede ser una cantidad determinada o fijarse a través de
una subasta. También se pueden establecer royalties o regalías, que supondrán un porcentaje de las
futuras ventas del NFT.
Una vez creado y acuñado el NFT, lo pondríamos a la venta en un mercado que admita NFT. Algu-
nos mercados populares para NFT son OpenSea, Nifty Gateway y SuperRare. Una vez que un compra-
dor adquiere nuestro NFT, tendremos que transferirle la propiedad del mismo. Esto se hace a través
de una transacción que actualiza los registros de propiedad en la blockchain donde está depositado el
NFT. Cuando un comprador adquiere un NFT, el contrato inteligente puede programarse para transferir
automáticamente la propiedad al comprador y actualizar los registros de propiedad en la blockchain.
Los contratos inteligentes son el instrumento generalmente utilizado para automatizar la compra,
la venta y la transferencia de propiedad de los NFT y en general de los activos digitales. Pueden uti-
lizarse para automatizar las ventas, ya que un contrato inteligente puede programarse para vender
automáticamente un NFT al mejor postor en una subasta, o para vender un NFT a un precio fijo. Los
contratos inteligentes pueden utilizarse también para distribuir automáticamente royalties a los crea-
dores de un NFT. El contrato puede programarse para transferir automáticamente un porcentaje del
precio de venta al creador cuando el NFT se revenda en un mercado secundario. Finalmente, los con-
tratos inteligentes pueden utilizarse para definir condiciones y normas para los NFT. Por ejemplo, un
contrato inteligente puede programarse para restringir la reventa de un NFT durante un determinado
periodo de tiempo, o para exigir que se cumplan ciertas condiciones antes de poder transferir un NFT.
A continuación presentamos un ejemplo sencillo de acuñado de un NFT y su carga en la red de
prueba Sepolia. Nuestro activo digital es el representado en la figura 4. Los metadatos asociados al
mismo serían los recogidos en el registro JSON siguiente:

1 {
2 "attributes": [
3 {
4 "trait_type": "Location",
5 "value": "New York"
6 },
7 {
8 "trait_type": "Style",
9 "value": "Andy Warhol"
10 }
11 ],
12 "description": "My first NFT: A really cooooool hydrant.",
13 "image": "ipfs://QmfBhAcyKQSZJep6qYYcuDQP8hrFLo8yJYQN39UPuDVraQ",
14 "name": "CoolHydrant"
15 }

Podemos ver que la referencia al activo en los metadatos es un ID de contenido (CID) en IPFS,
almacenado en el campo image (ver apartado 8). A su vez, será el CID del registro JSON con los
metadatos lo que almacenaremos en la cadena de bloques al acuñar el NFT.
El código del contrato inteligente para acuñar nuestros NFT, escrito en Solidity, es el siguiente:

1 // SPDX-License-Identifier: MIT
2 // Creación de un NFT en la red de prueba Sepolia, según el tutorial Ethereum
3 // tutorial "Cómo escribir y desplegar un NFT"
4 //
5 // Basado en [https://docs.openzeppelin.com/contracts/3.x/erc721]
6 // (https://docs.openzeppelin.com/contracts/3.x/erc721)
7 //
8 //
9 // Versión de Solidity, utilizando el versionado semántico.
10 pragma solidity ^0.8.20;

34
Figura 4: Activo digital para crear un NFT.

11
12 // ERC721.sol contiene la implementación del estándar ERC-721, que
13 // nuestro contrato NFT heredará. Para ser un NFT válido, el contrato
14 // inteligente debe implementar todos los métodos del estándar ERC-721.
15 import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
16
17 // Ownable.sol establece el control de acceso a nuestro contrato inteligente,
18 // de modo que sólo el propietario del contrato inteligente pueda acuñar
19 // NFTs. EL control acceso es opcional. Si cualquiera pueda acuñar un NFT
20 // usando determinado contrato inteligente, omitiríamos la palabra Ownable
21 // en la línea 46 y onlyOwner en la línea 73.)
22 import "@openzeppelin/contracts/access/Ownable.sol";
23
24 // El contrato ERC721URIStorage es una implementación de ERC721 que incluye
25 // los metadatos estándar (IERC721Metadata), así como un mecanismo para definir
26 // metadatos para cada NFT. De ahí viene el método _setTokenURI: lo utilizamos
27 // para almacenar un metadato NFT fuera de la cadena, más concretamente en IPFS.
28 import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
29
30 // Así, el contrato utilizará almacenamiento externo para los metadatos del NFT
31 // y para el propio NFT. Como vimos, sólo puede ser invocado por su propietario.
32 // y utilizamos un contador para llevar la cuenta de NFT generados y garantizar
33 // que los NFT generados tienen todos ellos IDs únicos.
34 // Omite la referencia a la interfaz Ownable si quieres que cualquiera pueda
35 // acuñar NFT con este contrato.
36 contract MyNFT is ERC721URIStorage, Ownable {
37 using Counters for Counters.Counter;
38
39 // Nuestro contrato inteligente utiliza un contador (_tokenIds)
40 // para llevar la cuenta del número total de NFT acuñados y
41 // establecer el ID único de nuestro nuevo NFT.
42 // A cada NFT acuñado con un contrato inteligente se le debe asignar un
43 // ID único. En este caso, el ID único viene determinado por el número total
44 // de NFT creados con el contrato. Por ejemplo, el primer NFT acuñado con
45 // nuestro contrato inteligente tiene un ID de "1", el segundo "2", etc.)
46
47 uint256 private _tokenIds;
48

35
49 // El primer argumento del constructor de ER721 es el nombre del contrato
50 // inteligente, y el segundo es su símbolo. El constructor de nuestro
51 // contrato no solicita argumentos. También se inicializa el contrato
52 // Owbnable asignando como primer dueño el creador del contrato.
53 constructor() ERC721("MyNFT", "NFT") Ownable (msg.sender){_tokenIds = 0;}
54
55 // Esta es la verdadera (y única) función ofrecida por nuestro contrato
56 // inteligente: la capacidad de acuñar NFTs. Para el resto
57 // de métodos definidos en el estándar ERC721 utilizamos las
58 // implementaciones por defecto que proporciona ERC721.sol.
59 // Sólo puede ser invocada por el propietario del contrato inteligente.
60 // Omite onlyOwner si deseas que cualquiera pueda utilizarla.
61 //
62 // La función recibe como parámetros:
63 // (1) La cartera del receptor del NFT (el creador del contrato
64 // en nuestro caso).
65 // (2) El URI de los metadatos del token. Esta cadena debe resolver
66 // un documento JSON que describe los metadatos del NFT.
67 // Los metadatos de un NFT son realmente lo que le da vida,
68 // permitiéndole tener propiedades configurables, como un nombre,
69 // descripción, imagen y otros atributos.
70 // Devuelve un número que representa el ID del NFT recién acuñado.
71 function mintNFT(address recipient, string memory tokenURI)
72 public onlyOwner
73 returns (uint256)
74 {
75 // Incrementa el ID del NFT en uno para garantizar IDs únicos
76 // y obtiene el ID de este NFT.
77 _tokenIds++;
78 uint256 newItemId = _tokenIds;
79
80 // Vamos a acuñar el NFT. _mint() llama a ciertos métodos de
81 // la biblioteca ERC-721 heredada, y finalmente
82 // devuelve un número que representa el ID del NFT recién acuñado.
83 _mint(recipient, newItemId);
84
85 // Almacenamos de forma persistente el tokenURI que hace referencia
86 // a los metadatos de este NFT
87 _setTokenURI(newItemId, tokenURI);
88
89 return newItemId;
90 }
91 }

Como vamos a utilizar la testnet Sepolia, que es una testnet de Ethereum, basamos nuestros NFT
en el estándar ERC-721. Se trata de una interfaz estándar para NFT en la blockchain de Ethereum
definida en 2018 para normalizar la forma en que se crean, transfieren y gestionan los NFT en dicha
blockchain. Los tokens ERC-721 son únicos y cada token tiene su propio identificador y metadatos
que proporcionan información adicional sobre el activo que representa. El estándar ERC-721 ha sido
ampliamente adoptado por la comunidad Ethereum, y muchos mercados populares de NFT, como
OpenSea y Rarible, admiten tokens ERC-721.
Como todas las transacciones, la transacción para forjar un NFT lleva un coste asociado llamado
gas. Al solicitar la transacción, debemos indicar el límite de gas, es decir, el precio máximo que es-
tamos dispuestos a pagar expresado en weis (1 ETH = 101 8 weis), en nuestro caso 500.000 weis o
0,0000005 ETH.
El fragmento de código siguiente en Node.js se utilizaría para hacer efectivo el acuñado y envío a
Sepolia de nuestro NFT.

1 // Script para acuñar un NFT utilizando el contrato inteligente

36
2 // previamente desplegado con la función mintNFT.
3 //
4 // Uso: node scripts/mint-nft.js
5 //
6 // Las variables de entorno se obtienen del archivo .env
7
8 require("dotenv").config()
9 // URL de la API de la aplicación Alchemy
10 // creada para desplegar nuestro contrato. Alchemy nos
11 // proporciona un acceso a la testnet Sepolia, donde
12 // hemos desplegado nuestro contrato.
13 const API_URL = process.env.API_URL;
14
15 // Dirección de la cartera autorizada a acuñar NFTs con el contrato
16 // (lo diseñamos para que solo la cartera autorizada pueda crearlos)
17 const PUBLIC_KEY = process.env.PUBLIC_KEY;
18
19 // Clave privada de la cartera. Se utiliza para cargar
20 // los gastos de gas incurridos en el acuñado del NFT.
21 const PRIVATE_KEY = process.env.PRIVATE_KEY;
22
23 // Alchemy Web3 es una envoltura alrededor de Web3.js, la librería
24 // más popular, casi podemos decir que el estándar, para acceder a
25 // la Web3, que proporciona métodos API mejorados y otros elementos
26 // interesantes. Está diseñada para requerir una configuración mínima.
27 const { createAlchemyWeb3 } = require("@alch/alchemy-web3");
28
29 // Creamos un objeto Web3 (web3) para acceder a Sepolia a través de
30 // Alchemy.
31 const web3 = createAlchemyWeb3(API_URL);
32
33 // Tomemos la ABI (Application Binary Interface) de nuestro contrato
34 // para interactuar con él.
35 const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json")
36
37 // Dirección del contrato NFT creado
38 const contractAddress = process.env.CONTRACT_ADDRESS;
39
40 // Creamos un objeto Contract (nftContract) usando la ABI y la dirección.
41 const nftContract = new web3.eth.Contract(contract.abi, contractAddress);
42
43 // Definimos una función para llamar a la función de acuñado de nuestro contrato.
44 async function mintNFT(tokenURI) {
45 // Obtenemoso un nonce.
46 const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, ’latest’);
47
48 // Creamos la transacción de acuñado llamando al mintNFT de nuestro contrato)
49 const tx = {
50 ’from’: PUBLIC_KEY, // Creador: nosotros (nuestra cartera)
51 ’to’: contractAddress, // El contrato de forjado de NFTs
52 ’nonce’: nonce, // el nonce para la transacción
53 ’gas’: 500000, // Ofrecemos 500.000 wei (0,0000005 ETH)
54 ’data’: nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI()
55 }
56
57 // Ahora que hemos creado nuestra transacción, necesitamos firmarla
58 // para poder enviarla a la web3. Aquí es donde usaremos nuestra clave
59 // privada.
60 // web3.eth.sendSignedTransaction nos dará el hash de la transacción,
61 // que podemos usar para asegurarnos de que nuestra transacción fue
62 // forjada y no fue descartada por la red Sepolia.
63 // Como se puede ver en el código que sigue, en la sección de la
64 // transacción hemos añadido una comprobación de errores para saber

37
65 // si nuestra transacción se forjó correctamente.
66 const signPromise = web3.eth.accounts.signTransaction(tx, PRIVATE_KEY)
67 signPromise
68 .then((signedTx) => {
69 web3.eth.sendSignedTransaction(
70 signedTx.rawTransaction,
71 function (err, hash) {
72 if (!err) {
73 console.log(
74 "El hash de la transacción es: ",
75 hash,
76 "\nEstado de la transacción en el mempool de Alchemy."
77 )
78 } else {
79 console.log(
80 "Algo ha ido mal al forjar la transacción:",
81 err
82 )
83 }
84 }
85 )
86 })
87 .catch((err) => {
88 console.log(" signPromise falló:", err)
89 })
90 }
91
92 // Lanzamos el acuñado utilizando el CID en IPFS del JSON con los
93 // metadatos del NFT.
94 mintNFT("ipfs://QmfJQ4xLorVNXLQ3S8cSGKtpBVYs44WD63C4Bi7yoWKtR2")

El código anterior utiliza la librería Alchemy Web3, una envoltura alrededor de Web3.js, una ibrería
muy popular para acceder a la Web3, que proporciona métodos API mejorados y otros elementos
interesantes. Otra opción común es utilizar la librería ethers.js. El fragmento siguiente utiliza dicha
librería a través del Hardhat Toolbox.

1 // Script para acuñar un NFT utilizando el contrato inteligente


2 // previamente desplegado con la función mintNFT.
3 //
4 // Uso: node scripts/mint-nft.js
5 //
6 // Las variables de entorno se obtienen del archivo .env
7
8 require(’dotenv’).config()
9
10 // Dirección de la cartera autorizada a acuñar NFTs con el contrato
11 // (lo diseñamos para que solo la cartera autorizada pueda crearlos)
12 const PUBLIC_KEY = process.env.PUBLIC_KEY;
13
14 // Clave privada de la cartera. Se utiliza para cargar
15 // los gastos de gas incurridos en el acuñado del NFT.
16 const PRIVATE_KEY = process.env.PRIVATE_KEY;
17
18 // Clave de la API de la aplicación Alchemy
19 // creada para desplegar nuestro contrato. Alchemy nos
20 // proporciona un acceso a la testnet Sepolia, donde
21 // hemos desplegado nuestro contrato.
22 const API_KEY = process.env.API_KEY;
23
24 // Creamos un objeto Hardhat Runtime Envirnoment (hre) para acceder
25 // a Sepolia a través de Alchemy.
26 const hre = require("hardhat");

38
27 const provider = new hre.ethers.AlchemyProvider("sepolia", API_KEY);
28
29 // Tomemos la ABI (Application Binary Interface) de nuestro contrato
30 // para interactuar con él.
31 const abiJSON = require("../artifacts/contracts/MyNFT.sol/MyNFT.json");
32
33 // Dirección del contrato NFT creado
34 const contractAddress = process.env.CONTRACT_ADDRESS;
35
36 // Creamos un objeto Contract (nftContract) usando la ABI,
37 // la dirección y el provider (Alchemy).
38 const nftContract = new hre.ethers.Contract(contractAddress, abiJSON.abi, provider);
39
40 // Creamos un objeto Wallet (wallet) para cargar los gastos del minado del NFT.
41 const wallet = new hre.ethers.Wallet(PRIVATE_KEY, provider);
42
43 // Cagamos el URI del NFT (CID en IPFS del registro JSON con los metadatos)
44 const tokenURI = process.env.NFT_URI;
45
46 // Función para el acuñado de nuestro contrato.
47 async function main() {
48
49 //
50 // Se trata de una transacción que hace cambios en el
51 // contrato inteligente, por lo que tiene que ir firmada.
52 // Utilizamos para ello la cartera, que tiene información
53 // sobre la clave privada (para firmar)
54 const contractSigned = nftContract.connect(wallet);
55
56 // Llamamos a la función de minado del contrato inteligente.
57 // Le pasamos como parámetros la dirección del creador del contrato
58 // (único que puede minar) y el URI del NFT.
59 const tx = await contractSigned.mintNFT(PUBLIC_KEY, tokenURI);
60
61 // Sacamos por consola el hash de la transacción
62 console.log(tx.hash);
63
64 await tx.wait();
65 console.log ("Minado completado con éxito");
66 }
67
68 main()
69 .then(result => {
70 console.log(’OK: Minado.’);
71 })
72 .catch(error => {
73 console.error(’Error:’, error);
74 });

Tras ejecutar este programa (bien con la libreria web3 o la librería ethers), nuestro NFT estará
cargado en la red Sepolia. Si consultamos nuestra cartera, nos aparecerá en el apartado de NFT de
los que somos propietarios, como podemos ver en la figura 5.

6. Finanzas descentralizadas (DeFi)

Las finanzas descentralizadas (DeFi) se refieren al ecosistema financiero que opera en una red
descentralizada utilizando la tecnología de cadenas de bloques. Permite a los usuarios acceder a ser-
vicios financieros, como préstamos, empréstitos, mercados financieros e inversiones, sin necesidad
de intermediarios como la banca y otras instituciones financieras tradicionales.

39
Figura 5: NFT en nuestra cartera, en el apartado donde aparecen los NFT de los que somos propietarios en la red Sepolia.

Las Finanzas Descentralizadas (DeFi) se basan en tres principios fundamentales que las diferen-
cian de los sistemas financieros tradicionales: la descentralización, la transparencia y el acceso pú-
blico. DeFi opera en una red blockchain, por lo que no hay ninguna autoridad central o intermediario
que controle o supervise el sistema. En su lugar, los usuarios interactúan directamente entre sí a tra-
vés de contratos inteligentes (ver el apartado 5) para automatizar las transacciones financieras. Al
materializarse los contratos y transacciones directamente a través de lógica programada, no son ne-
cesarios agentes que materialicen dichos contratos y transacciones. Además, al almacenarse dichas
transacciones de manera persistente e inmutable en la blockchain, tampoco se necesitan agentes que
almacenen y mantengan dicha información. Esto elimina la necesidad de bancos u otras instituciones
financieras tradicionales y promueve un sistema financiero más democrático e inclusivo.
En cuanto a la transparencia, DeFi lo es porque todas las transacciones se registran en el libro
mayor público de la blockchain (ver el apartado 1), lo que facilita el seguimiento y la verificación de su
autenticidad. Los usuarios pueden ver exactamente cómo se utilizan sus fondos y asegurarse de que
el sistema funciona de forma justa e imparcial. Este nivel de transparencia fomenta la responsabilidad
y genera confianza entre los usuarios.
DeFi garantiza además el acceso público porque está abierta a cualquier persona con conexión a
Internet, independientemente de su ubicación o situación financiera. Al eliminarse los intermediarios,
se eliminan los costes asociados a dicha intermediación, costes que pueden resultar elevados hasta
el punto de constituir una barrera de entrada y excluir a determinados grupos sociales del acceso a los
servicios financieros. Al ofrecer una plataforma más inclusiva y accesible, DeFi promueve una mayor
equidad e igualdad de oportunidades en el sector financiero.
De hecho, el impacto de DeFi en los sistemas financieros tradicionales es muy significativo por-
que desafía el statu quo ofreciendo una alternativa más transparente, segura y accesible. Al eliminar
los intermediarios, DeFi permite reducir los costes operativos a la vez que mejora la eficiencia de las
transacciones financieras. Además, las plataformas DeFi ofrecen mayor flexibilidad y liquidez, per-

40
mitiendo a los usuarios acceder a los servicios financieros en cualquier momento y desde cualquier
lugar.
Sin embargo, DeFi también plantea retos diferentes a los de los sistemas financieros tradiciona-
les, ya que no se adapta de manera sencilla a los mismos marcos reguladores y mecanismos de
supervisión que rigen las instituciones financieras convencionales, lo que puede crear riesgos para
los inversores y suscitar preocupación por la seguridad y la estabilidad del sector financiero. En ge-
neral, si bien DeFi ofrece interesantes oportunidades de innovación y se puede considerar una opción
disruptiva para la operativa financiera, su impacto en los sistemas financieros tradicionales dependerá
de cómo evolucione y se adapte a los marcos normativos y a las demandas del mercado.
En los apartados siguientes vamos a presentar de manera sucinta los aspectos más relevantes
del ecosistema DeFi, comenzando por los mercados financieros descentralizados. Más adelante pre-
sentaremos las plataformas de préstamo descentralizadas y el concepto de minería de liquidez como
un instrumento para proporcionar liquidez a ambos tipos de plataformas. A continuación, haremos un
breve repaso de otros productos derivados y estrategias gestión de activos en el entorno DeFi. Com-
pletaremos esta prentación identificando algunos retos y consideraciones normativas relevantes.

6.1. Mercados financieros descentralizados

Las bolsas o mercados financieros descentralizados (decentralized exchanges o DEX) son merca-
dos digitales que permiten a los usuarios negociar criptomonedas u otros activos digitales de igual
a igual, sin necesidad de los intermediarios o brokers que operan en las bolsas y mercados centrali-
zados. Al funcionar sobre una blockchain, heredan las características de seguridad, transparencia y
autonomía para los usuarios de esta tecnología.
En un DEX, las órdenes se emparejan directamente entre compradores y vendedores a través de
contratos inteligentes, que automatizan el proceso de negociación y garantizan que todas las tran-
sacciones se ejecuten de forma justa e imparcial sin intermediarios o brokers. Por tanto, se reduce de
manera drástica el coste de las transacciones y se eliminan muchos de los requisitos y limitaciones
existentes en los mercados tradicionales. El DEX mantiene un libro de órdenes descentralizado acce-
sible públicamente en la blockchain donde se registran todas estas intenciones de compra y venta de
activos. Los usuarios crean pares de intercambio (trading pairs) mediante la vinculación de dos activos
diferentes (p. ej., un par de intercambio podría consistir en un criptoativo popular, como Ethereum o
Bitcoin, y otro criptoactivo diferente). Cuando un usuario coloca una orden de compra o venta, un con-
trato inteligente en el DEX intenta encajar automáticamente esa orden con otras órdenes registradas
en el libro de órdenes. Si hay una coincidencia, se ejecuta el intercambio de manera automática. Los
usuarios pueden interactuar con un DEX a través de sus billeteras de criptomonedas (wallets), y los
DEX a menudo proporcionan interfaces de usuario amigables e integraciones con diversas billeteras
para mejorar la experiencia del usuario.
Los DEX ofrecen varias ventajas sobre los mercados centralizados, como comisiones más bajas,
mayor liquidez, más control de los usuarios sobre sus activos y mayor privacidad al no ser necesario
el registro de los usuarios ante ninguna entidad. Además, al no depender de puntos únicos de fallo,
se reduce el riesgo de hackeos o fraudes.
Sin embargo, también presentan algunos inconvenientes, como la limitación de los activos que se
pueden negociar a los pares de negociación establecidos, la lentitud de las transacciones y las po-
sibles vulnerabilidades en el código de los contratos inteligentes que implementan la operativa. Por
otra parte, algunos DEX pueden tener una curva de aprendizaje más pronunciada para los usuarios no
técnicos en comparación con las plataformas centralizadas, que suelen ser más simples conceptual-
mente. Además, el hecho de depender de una entidad que las opera garantiza unos mínimos servicios
de apoyo y consultoría.

41
Uno de los DEX más populares y ampliamente utilizados es Uniswap. Uniswap opera en la red
Ethereum y ha sido pionero en el concepto de generación automática de mercado (automated mar-
ket maker, AMM), que permite a los usuarios intercambiar criptomonedas de manera descentralizada
sin la necesidad de un libro de órdenes tradicional. En su lugar, se utilizan contratos inteligentes y la
liquidez proporcionada por los propios usuarios para realizar los intercambios a través de los pools.
Un pool en Uniswap se refiere a una cartera que contiene diferentes pares de negociación de tokens
creados por los usuarios, que deciden depositar sus tokens en el pool y compartirlos con otros usua-
rios del sistema. Los pares de tokens pueden contener cualquier pareja de criptoactivos ERC-20 de
la red Ethereum, ya sea un token establecido (como el propio Ethereum) o uno nuevo en la escena
de las criptomonedas, y se crean automáticamente cuando los usuarios depositan sus tokens en el
pool y se ejecutan según las reglas del sistema Uniswap. Esto significa que los precios de los pares
de tokens se determinan de acuerdo con las reglas de oferta y demanda, sin intermediarios.
Los usuarios pueden retirar sus tokens de un pool en cualquier momento y recibir las cantidades
correspondientes del otro token del par. Esto permite a los usuarios negociar con flexibilidad y control
sobre sus activos digitales. Además, los pares de tokens se vuelven más líquidos cuando hay una
mayor oferta y demanda en el sistema.
Uniswap tiene un modelo de gobernanza descentralizada basada en un token propio llamado UNI,
que permite a sus titulares participar en decisiones importantes sobre el protocolo. Este token sirve
para múltiples propósitos dentro del ecosistema, además de la gobernanza, como el pago de comi-
siones y la incentivación a la participación de los usuarios. Como token de gobernanza, los titulares de
UNI pueden participar en los procesos de toma de decisiones relacionados con el desarrollo y la evo-
lución de la plataforma Uniswap, votando propuestas y actualizando parámetros, como por ejemplo
los importes de las comisiones o la creación de pools de liquidez. Además, los usuarios que propor-
cionan liquidez a los pools de Uniswap son recompensados con tokens UNI, lo que crea un incentivo
para la participación y ayuda a aumentar la liquidez general de la plataforma.
Otras plataformas DEX relevantes serían SushiSwap, un DEX construido sobre Uniswap con ca-
racterísticas añadidas, como recompensas de provisión de liquidez y gobernanza basada en NFT;
Balancer, otro creador de mercado automatizado (AMM) que admite múltiples pools, ponderaciones
de tokens personalizables y estructuras de tarifas flexibles para los proveedores de liquidez; o Curve
Finance, un DEX centrado en el comercio de stablecoin con pools de liquidez altamente eficientes y
oráculos de precios integrados para mantener la estabilidad.

6.2. Préstamos descentralizados

En el ecosistema DeFi, los préstamos descentralizados son una forma de prestar y recibir dinero
sin la necesidad de intermediarios financieros como la banca o las entidades de crédito. Al igual que
en el caso de los DEX, estos préstamos utilizan la tecnología blockchain para garantizar la seguridad,
transparencia y autonomía de prestamistas y prestatarios.
Los préstamos descentralizados pueden tomar las mismas formas que los préstamos tradiciona-
les, incluyendo préstamos con intereses variables o fijos, préstamos en criptomonedas o en moneda
convencional, préstamos instantáneos, préstamos avalados o sin aval y préstamos para diferentes
propósitos (inversión, consumo, hipotecarios, etc.). Los prestamistas pueden obtener rentabilidad al
prestar su dinero a otros usuarios, mientras que los prestatarios pueden acceder a financiación más
barata y con menos trámites y requisitos que a través de fuentes tradicionales.
Los protocolos de préstamo y endeudamiento también se implementan a través de contratos inteli-
gentes que ejecutan automáticamente las transacciones y garantizan la seguridad del proceso. Estos
protocolos pueden tomar diversas formas, dependiendo del tipo de préstamo, existiendo contratos
inteligentes específicos para cada modalidad de préstamo. Estos contratos reflejan las condiciones

42
específicas del préstamo, como el tiempo de vencimiento, el interés a pagar, el tipo y cuantía del aval
requerido y las penalizaciones por el retraso en el pago.
Los usuarios pueden acceder a los servicios de préstamo y endeudamiento mediante plataformas
específicas. Una plataforma popular en este ámbito es Compound. Se trata de una plataforma DeFi
que permite a los usuarios prestar y pedir prestado criptomonedas sin necesidad de intermediarios,
basada en un algoritmo de cálculo de tipos de interés dinámicos de acuerdo con las leyes de la oferta
y la demanda, donde dichos tipos se ajustan automáticamente en función de la oferta y la demanda
de cada activo. Compound opera en la cadena de bloques de Ethereum, donde los préstamos se per-
feccionan mediante contratos inteligentes que garantizan la transparencia de las operaciones. Los
usuarios se convierten en prestamistas depositando criptomoneda en Compound (Ethereum, BAT,
DAI, ESDC, etc.), por la que reciben cantidades de un token específico a cambio, llamado COMP. Es-
tos tokens representan su participación y generan intereses en tiempo real. Los prestatarios toman
prestado a cambio de un interés, también calculado en tiempo real.
Compound es una plataforma DeFi de préstamos anónimos, es decir, sin requisitos de tipo know
your customer (KYC), lo que significa que los usuarios pueden participar sin tener que pasar por un
proceso de verificación de identidad. La gobernanza en Compound se lleva a cabo a través de un
sistema de votación descentralizado en el que los titulares de tokens COMP pueden proponer cambios
en los parámetros del protocolo, como los tipos de interés, los límites de préstamo o los tipos de
garantía. Estas propuestas se someten a la votación de la comunidad y, si reciben suficiente apoyo
de otros titulares de COMP, se implementan en la plataforma.
Otras plataformas relevantes en el mundo de los préstamos DeFi son la ya comentada Uniswap,
y Aave, MakerDAO o Yearn Finance, cada una con sus características específicas. Todas estas plata-
formas ofrecen una experiencia de uso amigable y permiten a los usuarios prestar o recibir dinero sin
la necesidad de conocimientos técnicos avanzados sobre blockchain o criptomonedas.

6.3. Minería de liquidez

La minería de liquidez o yield farming se refiere a la práctica de proporcionar liquidez a un DEX o


plataforma de préstamo como las comentadas previamente, a cambio de obtener recompensas en
forma de tokens, como por ejemplo comisiones por cada transacción, pagos de intereses o nuevos
tokens que se crean a través del proceso de minería. Consiste en aportar activos digitales (p. ej., crip-
tomonedas) a un fondo común, que luego se utilizan para facilitar las operaciones entre compradores
y vendedores en la plataforma. Como hemos visto en los apartados anteriores, los mineros de liquidez
también pueden recibir como recompensa tokens de gobernanza de la plataforma correspondiente,
que representan una participación en su gobierno. La minería de liquidez incentiva a los usuarios a
aportar sus activos a la plataforma, lo que ayuda a aumentar su liquidez y su valor global.
Se trata de un componente importante de los ecosistemas DeFi porque fomenta la participación y
el compromiso de los usuarios. Al ofrecer recompensas por aportar liquidez, las plataformas pueden
atraer a más usuarios y crear una comunidad más amplia en torno a sus ofertas. Además, la mine-
ría de liquidez ayuda a garantizar que siempre haya suficientes activos disponibles en la plataforma,
lo que es esencial para mantener su funcionalidad y estabilidad. De todos modos, las tasas de ren-
dimiento en la minería de liquidez pueden ser altamente variables y dependen de factores como la
demanda de liquidez en el protocolo y las recompensas ofrecidas. Los mineros buscan maximizar
sus rendimientos eligiendo los pools que ofrecen las mejores tasas.
Además de las recompensas y la participación en la gobernanza, algunas plataformas DeFi ofre-
cen la opción de bloquear los tokens recibidos como recompensa en un proceso denominado (sta-
king). Al bloquear estos tokens en contratos de staking, los usuarios pueden seguir obteniendo ren-
dimientos adicionales, e incluso en algunos casos se permiten estrategias más elaboradas, como

43
la creación de estrategias de minería de liquidez compuesta, donde los rendimientos obtenidos se
reinvierten automáticamente para maximizar los ingresos.
Aunque la minería de liquidez puede llegar a convertirse en una actividad lucrativa, también con-
lleva riesgos. Los protocolos DeFi pueden ser propensos a bugs o ataques, y las tasas de rendimiento
pueden cambiar rápidamente, volatilidad que afecta directamente a los rendimientos esperados.

6.4. Derivados DeFi y gestión de activos

En el contexto de DeFi, se crean a menudo activos sintéticos y productos financieros complejos


aprovechando la flexibilidad que proporciona la lógica programada en los contratos inteligentes. Estos
instrumentos financieros derivados se caracterizan porque su valor está asociado al de un activo o
activos subyacentes, en muchos casos de un modo muy elaborado. Entre los más representativos
están los activos sintéticos, las opciones, los futuros, los índices sintéticos y los tokens apalancados
e inversos.
Los activos sintéticos son representaciones o gemelos digitales de activos del mundo real. De
todos modos, estos activos no están directamente respaldados por el activo subyacente, sino que
se crean sintéticamente a través de contratos inteligentes. Un ejemplo de activo sintético podría ser
un token indexado al precio del oro o de una materia prima. A través de contratos inteligentes, los
usuarios pueden poseer un token que refleje el valor del oro sin poseer físicamente nada de dicho
metal precioso.
Las opciones son contratos derivados que otorgan al titular el derecho (pero no la obligación) de
comprar o vender un activo subyacente a un precio específico en una fecha determinada. Las opcio-
nes no son exclusivas del mundo DeFi, pero en este contexto los contratos de opciones, en realidad
programas software más que contratos en sí, pueden utilizarse para crear estrategias complejas, co-
mo estrangulamientos o spreads de estrategia, que se aplican automáticamente y que permiten a los
usuarios gestionar el riesgo y buscar rendimientos en diferentes escenarios de mercado. Los contra-
tos de futuros, que tampoco son específicos del mundo DeFi, son acuerdos para comprar o vender un
activo subyacente en una fecha futura a un precio acordado. Los futuros permiten a los participantes
apostar sobre el precio futuro de un activo, y en DeFi se utilizan muchas veces para crear productos
que permitan a los usuarios apostar sobre el precio futuro de criptomonedas, índices u otros activos.
Los índices sintéticos se crean a menudo mediante la combinación de varios activos subyacentes
o la exposición a diversos activos. Estos índices no necesariamente replican índices tradicionales,
sino que se construyen sintéticamente mediante la lógica de un contrato inteligente. Por ejemplo, un
índice sintético podría seguir el rendimiento combinado de varias criptomonedas. Los participantes
pueden obtener exposición diversificada a través de un token que represente este índice sintético.
Los tokens apalancados e inversos proporcionan exposición apalancada o inversa a un activo sub-
yacente. Pueden utilizarse para estrategias de apalancamiento o cobertura. Una estrategia de apalan-
camiento implica el uso de capital prestado para realizar inversiones, mientras que una estrategia de
cobertura implica proteger una posición existente o anticiparse a pérdidas potenciales mediante la
adopción de una posición compensatoria en otro activo o instrumento financiero. Por ejemplo, un to-
ken apalancado 3x puede conseguir el triple del rendimiento diario de un activo subyacente. Por otro
lado, un token inverso podría buscar obtener el inverso del rendimiento diario para compensar posibles
pérdidas. Las permutas de tasas de interés son contratos derivados que permiten el intercambio de
flujos de efectivo asociados a tasas de interés. En DeFi, se pueden implementar permutas de tasas de
interés para gestionar riesgos asociados con tasas de interés variables en protocolos de préstamos
y liquidez.
En cualquier caso, hay que tener en cuenta que los derivados y productos financieros complejos
presentan riesgos significativos, tanto en el mundo físico como en el mundo DeFi, por lo que su uso

44
requiere un conocimiento profundo de los mismos y en general de la operativa financiera de productos
complejos. La naturaleza descentralizada de DeFi no elimina en absoluto los riesgos asociados con
estos instrumentos financieros. Los usuarios deben comprender completamente los productos en los
que participan y sopesar cuidadosamente los riesgos y beneficios antes de involucrarse en estrategias
DeFi complejas.
Un ejemplo relevante en la gestión de activos DeFi es Yearn Finance. Se trata de un protocolo y
plataforma DeFi que opera en la cadena de bloques de Ethereum y que se ha convertido en uno de los
proyectos DeFi más conocidos. La misión principal de Yearn Finance es optimizar y automatizar los
rendimientos de las inversiones en el espacio DeFi, utilizando estrategias avanzadas para maximizar
los rendimientos de sus usuarios mediante la optimización de la colocación de fondos en diferentes
protocolos DeFi. Yearn Finance busca proporcionar una experiencia de inversión sencilla y eficiente
para los usuarios, permitiéndoles depositar fondos en el protocolo y dejar que los algoritmos gestionen
automáticamente las inversiones oportunas para obtener los mejores rendimientos posibles.
Yearn Finance opera bóvedas (vaults), que son pools de liquidez gestionados de manera proactiva.
Los usuarios pueden depositar fondos en estos Vaults, y el protocolo utiliza estrategias automatizadas
para maximizar los rendimientos. Para ello, proporciona dos funciones clave: earn (ganar) y zap. La
función earn permite a los usuarios depositar stablecoins y otros activos en Yearn Finance para ganar
intereses, mientras que Zap permite a los usuarios realizar transacciones más eficientes y optimiza-
das al combinar múltiples operaciones en una sola transacción, buscando las mejores oportunidades
de rendimiento en cada caso. Además, Yearn Finance permite la participación de estrategas externos
que pueden proponer y gestionar estrategias de inversión en el protocolo.
El token nativo de Yearn Finance es YFI, que inicialmente se distribuyó de manera justa a la comu-
nidad y permite a los poseedores participar en la gobernanza del protocolo, proponer y votar sobre
cambios.

6.5. Retos y consideraciones normativas

DeFi ha surgido como una de las aplicaciones más prometedoras de la tecnología blockchain, ya
que las plataformas DeFi permiten a los usuarios realizar actividades financieras de cualquier tipo sin
intermediarios. Sin embargo, estas plataformas también presentan desafíos únicos en lo que respec-
ta a la escalabilidad, las vulnerabilidades de seguridad y los riesgos asociados relacionados con los
exploits de contratos inteligentes.
Uno de los principales problemas de las plataformas DeFi es su incapacidad para gestionar gran-
des volúmenes de transacciones simultáneamente, lo que puede llegar a congestionar la red y ralen-
tizar los tiempos de procesamiento y respuesta para los usuarios, algo que puede ser crítico en el
mundo de las finanzas. Además, a medida que se desarrollan contratos inteligentes más complejos,
aumenta el riesgo de que se introduzcan vulnerabilidades que puedan ser explotadas por agentes
malintencionados. Hay que tener en cuenta que el código informático de los contratos inteligentes es
público y puede ser analizado por cualquiera.
Otra preocupación relacionada con las plataformas DeFi es su susceptibilidad a las brechas de
seguridad debido a su dependencia de blockchains públicas y código fuente abierto. De hecho, los
piratas informáticos han atacado con éxito estos sistemas en el pasado, provocando pérdidas signifi-
cativas para los usuarios. Por último, los exploits de contratos inteligentes suponen un riesgo impor-
tante para las plataformas DeFi, ya que pueden provocar resultados inesperados o incluso la pérdida
total de los fondos de los usuarios si no se diseñan e implementan correctamente. A pesar de estos
retos, DeFi sigue creciendo rápidamente con el lanzamiento continuo de nuevos proyectos. A medida
que el sector madura, se espera que los desarrolladores sigan abordando estos problemas mediante
mejores prácticas de codificación, mejores medidas de seguridad y protocolos de prueba más sólidos.

45
Sin embargo, esta rápida expansión también ha suscitado inquietud entre los reguladores, que de-
baten sobre cómo supervisar estas plataformas y proteger a los consumidores de posibles riesgos.
Uno de los principales retos a los que se enfrenta la regulación de las DeFi es la naturaleza descen-
tralizada de estas plataformas blockchain, que dificulta la aplicación de los marcos reguladores tra-
dicionales, ya que no existe una autoridad central que controle la red o a sus participantes. Además,
muchos proyectos DeFi se ubican formalmente en jurisdicciones con normas laxas o poco claras
en torno a las criptomonedas y los activos digitales, lo que dificulta la aplicación de las normas de
cumplimiento.
Otro problema relacionado con la regulación de las DeFi es la falta de transparencia que rodea
a estas plataformas. Debido a su estructura descentralizada, puede ser difícil para los reguladores
obtener información sobre las actividades de los usuarios o identificar posibles riesgos, lo que ha
llevado a algunos países a considerar la aplicación de requisitos más estrictos de conocimiento del
cliente (KYC) y de lucha contra el blanqueo de dinero con el fin de aumentar la supervisión de estas
plataformas.
Por último, se plantean cuestiones jurisdiccionales en relación con la regulación de la propia fi-
nanciación de los proyectos, ya que muchos de ellos operan en varios países y serían competencia de
diversos organismos reguladores, en función de dónde se encuentren los usuarios o los proveedores
de servicios, lo que a su vez crea confusión y posibles conflictos entre los distintos marcos jurídicos.
A pesar de estos retos, se han producido algunos avances en el desarrollo de un enfoque más
coherente de la regulación de las DeFi, con iniciativas como la del Grupo de Acción Financiera Interna-
cional (Financial Action Task Force, FATF), que ha publicado orientaciones sobre los activos digitales
(FATF, 2012-2023), y reguladores como la Comisión del Mercado de Valores de Estados Unidos (SEC),
que ha emprendido acciones contra determinados proyectos por supuestas infracciones de la legis-
lación sobre valores. A medida que el sector siga evolucionando, es probable que surja más claridad
sobre cómo deben regularse las plataformas DeFi para equilibrar la innovación con la protección del
inversor.

7. Oráculos

En la tecnología blockchain, un oráculo es un servicio de terceros que proporciona datos o eventos


externos a un contrato inteligente en una blockchain. Los oráculos permiten a los contratos inteligen-
tes interactuar con el mundo exterior y ejecutar acciones basadas en eventos del mundo real.
Los oráculos (ver figura 6) son contratos inteligentes que actúan como intermediarios entre otros
contratos inteligentes y las fuentes de datos externas, proporcionando datos como precios, informes
meteorológicos o resultados deportivos al contrato inteligente. También pueden proporcionar datos
sobre eventos en otras blockchains o datos que no están disponibles de forma nativa en la blockchain,
como datos financieros fuera de la cadena o datos de sensores del Internet de las cosas (IoT).
Los sistemas de oráculos pueden clasificarse a grandes rasgos de acuerdo con dos criterios en
función de su arquitectura y funcionalidad: oráculos basados en software o en hardware, dependiendo
del origen de los datos gestionados; y oráculos centralizados o descentralizados, dependiendo de si
el oráculo monitoriza una sola entidad o si busca obtener datos de múltiples fuentes independientes.
Cada tipo tiene sus propias características, casos de uso y diferencias.
Los oráculos basados en software son implementaciones de software que proporcionan datos a
los contratos inteligentes. Pueden extraer información de fuentes en línea, APIs, bases de datos, etc.
Son flexibles y pueden adaptarse fácilmente a diferentes casos de uso. Sin embargo, su principal de-
safío es garantizar la integridad y confiabilidad de los datos que proporcionan. Típicamente se utilizan
para realizar predicciones de mercados financieros, proporcionar información meteorológica, tasas

46
Figura 6: Ejemplo de red blockchain a la que se conectan oráculos a alguno de sus nodos. Dichos nodos proporcionan
aplicaciones del programador (APIS) para acceder a la información. El acceso a la información se realiza mediante contratos
inteligentes.

de cambio, etc. Por ejemplo, si un contrato inteligente necesita conocer el precio actual del Bitcoin
para ejecutar una operación, puede hacer uso de un oráculo basado en software que extraiga esa
información de múltiples plataformas de criptomonedas y la proporcione al contrato. Normalmente
se accede a ellos a través de una interfaz de programador (API) desde cualquier aplicación. Algunos
ejemplos serían CoinGecko API (información sobre precios, volumen y capitalización de criptomone-
das), Alpha Vantage API (datos financieros, incluyendo tasas de cambio, precios de acciones, y datos
de indicadores técnicos) u OpenWeatherMap API (datos meteorológicos e información del clima en
tiempo real).
Los oráculos basados en hardware utilizan sensores físicos o dispositivos de hardware para pro-
porcionar datos del mundo real sobre variables como la temperatura, humedad, ubicación geográfica,
etc. Ofrecen una fuente de datos más directa y confiable que los oráculos software, pero pueden ser
más costosos de implementar y mantener en comparación con los oráculos basados en software.
Parte del ecosistema de Internet de las Cosas (IoT), son habituales en la monitorización ambiental,
control de cadenas de frío, o en aplicaciones de seguridad y vigilancia. Por ejemplo, en un sistema
de monitoreo ambiental para una cadena de suministro de productos perecederos, se podría utilizar
un sensor de temperatura conectado a la blockchain a través de un oráculo basado en hardware. El
sensor podría generar información en tiempo real sobre la temperatura de un contenedor de carga y
enviar esos datos a la blockchain, donde un contrato inteligente implementaría la lógica correspon-
diente basada en estos datos, como por ejemplo para activar una alerta si la temperatura supera cierto
umbral.
Los oráculos centralizados obtienen datos de una única fuente central, que puede ser una empre-
sa, una interfaz centralizada, o cualquier entidad que proporcione información. Son más simples de
implementar pero pueden ser vulnerables a ataques y manipulaciones, ya que dependen de una sola
entidad. Los podemos encontrar proporcionando precios de activos, información financiera centrali-
zada, eventos específicos de una fuente confiable, etc.
Los oráculos descentralizados obtienen datos de múltiples fuentes independientes, con lo que se
reduce la dependencia de una sola entidad y se mejora la resistencia a la manipulación. Por tanto,
ofrecen una mayor robustez y resistencia a la censura que los centralizados, ya que no dependen de
una sola fuente. Son habituales en la monitorización de datos de procesos electorales, monitorización
de resultados deportivos en sistemas de apuestas, o en la provisión de información descentralizada de
mercados financieros. Dentro de los oráculos descentralizados, tendríamos los oráculos basados en
consenso, que obtienen datos de varias fuentes y utilizan algoritmos de consenso para determinar el

47
valor correcto y garantizar la integridad de los datos en entornos donde la información puede cambiar
de manera rápida o inesperada.
Un ejemplo de un oráculo descentralizado es Chainlink (ver 7.2), una plataforma que facilita la co-
nexión entre contratos inteligentes y fuentes de datos externas de manera descentralizada. Chainlink
utiliza una red de nodos oráculo para proporcionar información del mundo real a contratos inteligen-
tes en diversas blockchains. Estos nodos comparten y validan la información utilizando contratos
inteligentes en la propia red Chainlink, asegurando un consenso descentralizado. Cuando un contrato
inteligente necesita conocer un dato de los monitorizados por Chainlink (p. ej., la tasa de cambio de
determinada criptomoneda), envía una solicitud a la red Chainlink a la que responden varios nodos
oráculo con la información solicitada. La respuesta se compara y se utiliza un algoritmo o una fun-
ción de consenso (p. ej., el cálculo de la mediana de los valores devueltos) para determinar el valor
final que se proporcionará al contrato inteligente.
Los oráculos son importantes en las aplicaciones de blockchain que requieren datos externos para
activar la ejecución de contratos inteligentes, como en muchas aplicaciones DeFi (ver apartado 6), los
mercados de predicción y los sistemas de gestión de la cadena de suministro. Al proporcionar una
vía para que los contratos inteligentes accedan a datos externos, los oráculos permiten el desarrollo
de aplicaciones blockchain más complejas y sofisticadas.

7.1. Arquitecturas de oráculos

Los dos modelos principales de arquitecturas de oráculos son el modelo solicitud-respuesta (mo-
delo pull) y el modelo publicación-suscripción (modelo push). Cada uno tiene sus propias característi-
cas y se adapta a diferentes casos de uso en el contexto de las blockchains y los contratos inteligentes.
En el modelo solicitud-respuesta, también conocido como pull, el contrato inteligente realiza acti-
vamente una solicitud para obtener datos del oráculo cuando los necesita, es decir, cuando se activa
una condición específica en el contrato. El oráculo responde a la solicitud proporcionando los datos
solicitados.
Con este modelo, el contrato inteligente tiene un mayor control sobre cuándo y qué datos solicitar,
por lo que resulta más eficiente ya que los recursos del oráculo se utilizan solo cuando se necesitan
datos. Sin embargo, puede haber cierto retraso entre la activación del contrato y la obtención de datos,
ya que la solicitud se realiza solo cuando se considera necesaria sin conocer el estado de la fuente de
datos.
En el modelo publicación-suscripción, también conocido como push, el oráculo proporciona acti-
vamente datos al contrato inteligente cuando ocurren eventos definidos con anterioridad. El contrato
inteligente se suscribe previamente a ciertos eventos o tipos de datos proporcionados por el oráculo.
A partir de ese momento, el oráculo envía datos automáticamente al contrato cuando se producen
los eventos de interés, sin que el contrato lo solicite activamente, utilizando una función de callback
definida durante el proceso de suscripción.
En este modelo, los datos pueden llegar de inmediato al contrato tan pronto como estén disponi-
bles, a la vez que se reduce la complejidad al no ser necesario que el contrato inteligente inicie acti-
vamente peticiones de datos. Sin mebargo, los oráculos basados en este modelo pueden consumir
más recursos, ya que están continuamente enviando datos, incluso si no son necesarios.
La elección entre los modelos pull y push dependerá del caso de uso específico y de los requisitos
del contrato inteligente (p. ej., frecuencia de actualización requerida por el caso de uso, importancia
de la inmediatez de los datos o requisitos de eficiencia en el uso de recursos en la red blockchain).
Algunos casos de uso pueden beneficiarse de la inmediatez del modelo basado en suscripción, mien-
tras que otros pueden preferir el control y la eficiencia del modelo basado en peticiones y respuestas.
Por ejemplo, el uso del modelo pull es habitual en la obtención de tasas de cambio o información del

48
clima, mientras que el modelo push es más apropiado para la monitorización continua de sensores
IoT o cuando se necesita actualizaciones en tiempo real de eventos específicos.

7.2. Oráculos y DeFi

Veamos cómo un oráculo puede proporcionar precios de acciones a un contrato inteligente en una
plataforma DeFi que permite a los usuarios crear y negociar activos sintéticos que siguen el precio
de las acciones. En este ejemplo, un servicio de oráculo se encargaría de proporcionar al contrato
inteligente datos sobre el precio de las acciones en tiempo real procedentes de una fuente de datos
de confianza, como una bolsa de valores. El contrato inteligente utilizaría estos datos para calcular el
precio del activo sintético y ejecutar operaciones entre usuarios.
Por ejemplo, supongamos que un usuario quiere crear un activo sintético que siga el precio de las
acciones de Tesla. Para ello, enviaría una solicitud al contrato inteligente, que a su vez enviaría una
solicitud al oráculo para conocer el precio actual de las acciones de Tesla. El oráculo proporcionaría al
contrato inteligente el precio actual de las acciones, y el contrato inteligente utilizaría estos datos para
calcular el valor del activo sintético. Si otro usuario desea negociar este activo sintético, el contrato
inteligente volvería a solicitar el precio actual de las acciones al oráculo para garantizar que la ope-
ración se ejecuta al precio de mercado actual. Una vez ejecutada la operación, el contrato inteligente
actualizará la propiedad del activo sintético y transferirá los fondos involucrados en la operación.
En este ejemplo, el oráculo actúa como una fuente fiable de datos sobre el precio de las acciones en
tiempo real que permite al contrato inteligente fijar con precisión el precio y ejecutar operaciones con
activos sintéticos que siguen el precio de las acciones. Esto permite a los usuarios negociar activos
sintéticos que representan activos del mundo real, sin depender de intermediarios centralizados o
instituciones financieras tradicionales.
A continuación ofrecemos un ejemplo sencillo de contrato inteligente que contacta con un oráculo
para obtener la tasa de conversión entre Bitcoin (BTC) y el dólar estadounidense (USD). Para ello ello
utilizamos la plataforma Chainlink, que entre otros servicios ofrece oráculos (data feeds) para aplica-
ciones DeFi. Para acceder a estas fuentes de datos, utilizamos oráculos desplegados por Chainlink
en diversas redes.

1 // SPDX-License-Identifier: MIT
2 // Contrato inteligente para probar un oráculo (data feed) de Chainlink
3 // El oráculo proporciona la tasa de conversión BTC/USD.
4 //
5 // Versión de Solidity utilizada
6 pragma solidity ^0.8.20;
7
8 // Importa una interfaz de Chainlink llamada AggregatorV3Interface.
9 // Las interfaces definen funciones sin su implementación, lo que
10 // deja a los contratos que implementan la interface que definan
11 // la implementación ellos mismos.
12 // En este caso, AggregatorV3Interface define, entre otras funciones,
13 // la signatura de la función latestRoundData que vamos a utilizar.
14 import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
15
16 // Usaremos la función toString del kit de herramientas Hardhat para
17 // convertir los datos devueltos por el oráculo (a través de su contrato
18 // inteligente proxy) en cadenas de caracteres,
19 // para con ello construir la cadena JSON devuelta como resultado por
20 // nuestro contrato inteligente.
21 import "@openzeppelin/contracts/utils/Strings.sol";
22
23 // Definimos el contrato
24 contract BTCUSDRateJSON {

49
25
26 // Declaramos una variable para almacenar la dirección del
27 // oráculo Chainlink
28 AggregatorV3Interface internal _priceFeed;
29
30 // El constructor de nuestro contrato simplemente invoca el
31 // constructor del oráculo. Este, a su vez, sólo establece
32 // la dirección del oráculo Chainlink en la red Sepolia.
33 //
34 // Se inicializa un objeto de interfaz llamado _priceFeed
35 // que utiliza AggregatorV3Interface para conectarse al
36 // oráculo que ofrece la tasa de conversión BTC/USD,
37 // ya desplegado en la dirección
38 // 0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43
39 // de la red Sepolia.
40 //
41 // La interfaz permite a nuestro contrato ejecutar funciones
42 // en ese contrato proxy ya desplegado.
43 constructor() {
44 // Se puede sustituir la dirección por la dirección de cualquier
45 // otro proxy de cualquier otro data feed Chainlink.
46 // Esta es la dirección del contrato de oráculo en la testnet Sepolia
47 // que proporciona tasas de conversión BTC / USD.
48 _priceFeed = AggregatorV3Interface(
49 0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43
50 );
51 }
52
53 // Función para devolver el tipo de cambio BTC/USD.
54 // Esta función utiliza el objeto _priceFeed
55 // para ejecutar la función latestRoundData() del oráculo.
56 // Cuando el contrato se despliega, inicializa el objeto
57 // _priceFeed para que apunte al contrato inteligente en
58 // 0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43 a través
59 // del constructor (ver más arriba).
60 //
61 // La función devuelve una cadena JSON con toda la información.
62 function getConversionRateBTCUSD() public view returns (string memory) {
63 // Obtenemos la última tasa de conversión a través del oráculo
64 // llamando a la función latestRoundData de _priceFeed.
65 // Esta función devuelve la información de conversión fijada en la
66 // última ronda disponible.
67 (
68 uint80 roundID,
69 int256 price,
70 uint256 startedAt,
71 uint256 timeStamp,
72 uint80 answeredInRound
73 ) = _priceFeed.latestRoundData();
74
75 // La respuesta del agregador incluye varias variables: ID de la ronda
76 // donde se fijó el valor; tasa de conversión; marca de tiempo de
77 // cuando comenzó la ronda; marca de tiempo de cuando se actualizó
78 // la ronda; ID de la ronda en la que se calculó la tasa.
79 // Las usamos para construir un registro JSON y devolverlo.
80 string memory JsonString =
81 string.concat(’{"RoundID":"’,
82 Strings.toString(roundID),
83 ’","Price":"’,
84 Strings.toString(uint256(price)),
85 ’","startedAt":"’,
86 Strings.toString(startedAt),
87 ’","TimeStamp":"’,

50
88 Strings.toString(timeStamp),
89 ’","answeredInRound":"’,
90 Strings.toString(answeredInRound),
91 ’"}’);
92
93 return JsonString;
94 }
95 }

Este contrato ofrece una función getConversionRateBTCUSD que devuelve una cadena JSON con
toda la información relevante sobre la tasa de conversión: su valor y cuándo y cómo se fijó dicha tasa.
A continuación ofrecemos un pequeño programa en JavaSCript para interaccionar con dicho contrato
y sacar por pantalla la información de la tasa de conversión.

1
2 //
3 // Interacción con el contrato inteligente de conversión de tipos
4 // de cambio comentado anteriormente.
5 //
6 // Devuelve el tipo de conversión BTC/USD, junto con otra información.
7 //
8 // Para ejecutar esto: npx hardhat run scripts/interacct.js
9
10 // Dirección de nuestro contrato inteligente, obtenida tras el despliegue
11 // y almacenada en el archivo .env
12 const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS_JSON;
13
14 // Toma la ABI (Application Binary Interface) de nuestro contrato
15 // para interactuar con él.
16 const contract =
17 require("../artifacts/contracts/test-oracle.sol/StockMarketValueJSON.json");
18
19 // Firmante
20 // Una cartera (wallet) que tiene la capacidad de firmar transacciones.
21 // En nuestro caso, creada con MetaMask.
22 // Para identificarla, necesitamos la clave pública de la cartera (de .env).
23 // Para poder pagar con esta cartera, el archivo hardhat.config.js
24 // tiene información sobre la clave privada
25 // y la red utilizada (Sepolia testnet en nuestro caso).
26 const ownerAddress = process.env.PUBLIC_KEY;
27 const signer = ethers.provider.getSigner(ownerAddress);
28
29 // Contrato
30 // Un objeto de la biblioteca ethers.js que representa un contrato
31 // específico desplegado en la cadena.
32 // En nuestro caso, nuestro contrato BTCUSDRateJSON
33 // Para identificarlo, necesitamos la dirección del contrato, la ABI y la cartera.
34 const financeContract = new ethers.Contract(CONTRACT_ADDRESS, contract.abi, signer);
35
36 // Ahora vamos a contactar con nuestro contrato inteligente para obtener
37 // el tipo de conversión BTC/USD junto con la información adicional
38 // proporcionada por el oráculo.
39 // Como ya vimos en otro ejemplo, en JavaScript, usamos funciones asíncronas
40 // para interactuar con redes blockchain.
41 async function main() {
42
43 try {
44 // Obtiene el último valor de la tasa de conversión BTC/USD.
45 // El método devuelve una cadena JSON.
46 const presentValue = await financeContract.getConversionRateBTCUSD();
47
48 // Vamos a parsear (convertir) la cadena JSON a un objeto

51
49 const valObj = JSON.parse(presentValue);
50
51 // Mostramos la información por consola utilizando el objeto
52 // que acabamos de crear. Acondicionamos los valores devueltos
53 // para hacerlos más legibles a los humanos: convertimos el
54 // precio a dólares y los timestamps a fechas y horas.
55 console.log("ID de la ronda: " + valObj.RoundID);
56 console.log("Tasa de conversión: " + valObj.Price / 10**8 + " USD/BTC");
57 console.log("Comienzo: " + new Date(valObj.startedAt * 1000));
58 console.log("Finalización: " + new Date(valObj.TimeStamp * 1000));
59 console.log("Ronda final: " + valObj.answeredInRound);
60 } catch (error) {
61 // No deberíamos llegar aquí
62 console.log("ERROR FOUND");
63 console.error(error);
64 }
65
66 }
67
68 // ¡Vamos!
69
70 main();

Si ejecutamos este programa con:


npx hardhat run scripts/interact.js -network sepolia

obtenemos por ejemplo:


ID de la ronda: 18446744073709553674
Tasa de conversión: 28399.39341 USD/BTC
Comienzo: Sun Apr 02 2023 12:18:00 GMT+0200
Finalización: Sun Apr 02 2023 12:18:00 GMT+0200
Ronda final: 18446744073709553674

7.3. Generación de números aleatorios

Generar números verdaderamente aleatorios en un contrato inteligente no es una tarea sencilla, ya


que los contratos inteligentes en redes blockchain operan en un entorno determinista, lo que significa
que dadas las mismas entradas y condiciones, se producirán siempre los mismos resultados. Este
determinismo es un aspecto fundamental de la tecnología blockchain, ya que por ejemplo garantiza
que todos los nodos de la red puedan llegar a un consenso sobre el estado de la cadena de bloques.
Sin embargo, la verdadera aleatoriedad es, por definición, impredecible, lo que entra en conflicto con
la naturaleza determinista de las cadenas de bloque y por lo tanto de los contratos inteligentes. Para
complicar aún más las cosas, los contratos inteligentes tienen un acceso limitado a información ex-
terna, y no pueden interactuar directamente con fuentes de datos fuera de la cadena o con el mundo
físico. De hecho, esta característica es la verdadera razón de ser de los oráculos.
En consecuencia, los generadores de números pseudoaleatorios que utilizan la información dis-
ponible en un contrato inteligente como semilla, pueden ser predecibles si un atacante conoce el valor
de la semilla o el estado interno de la cadena de bloques, y por lo tanto podrían ser vulnerables a la
manipulación. Además, la generación de números pseudoaleatorios es comparativamente costosa
computacionalmente. El coste de ejecutar cálculos complejos en una blockchain tendrá que ser cu-
bierto por el creador o los usuarios del contrato, por lo que implementar una generación de números
pseudoaleatorios compleja y costosa puede hacer que los contratos inteligentes sean prohibitivamen-
te caros de usar.

52
Un método habitual para generar números aleatorios en una cadena de bloques consiste en ge-
nerar un hash de una secuencia de bytes compuesta por ciertos valores extraídos de la cadena de
bloques, en principio difíciles de predecir, como por ejemplo el número de bloque, la marca temporal
del bloque, el valor de dificultad del minado del mecanismo de consenso de prueba de trabajo, el valor
de Randao (ver apéndice D) generado por los validadores de bloques en el mecanismo de prueba de
participación (Kalinin y Ryan, 2021), la cantidad de gas remanente en el contrato, o la dirección que
invocó el contrato.
El código siguiente genera un número pseudoaleatorio entre 1 y 100 utilizando tres de los valores
anteriores en una cadena Ethereum:

1 pragma solidity ^0.8.18;


2
3 contract RandomNumberGenerator {
4 function generateRandomNumber() public view returns (uint) {
5 // Obtenemos la marca de tiempo de este bloque y prevrandao.
6 // prevrandao es el valor de Randao de la última actualización
7 // de Randao, es decir, la última ranura en la que alguien
8 // actualizó realmente el Randao y produjo un nuevo bloque.
9 // También usamos la dirección que invoca este contrato.
10 uint seed = uint(keccak256(abi.encodePacked(
11 block.timestamp,
12 block.prevrandao,
13 msg.sender)));
14
15 // Generamos un número pseudoaleatorio entre 1 y 100.
16 uint randomNum = (seed % 100) + 1;
17
18 return randomNum;
19 }
20 }

En el ejemplo anterior, el uso de block.timestamp puede ser controlado por los validadores hasta
cierto punto, ya que aunque la marca de tiempo del bloque actual debe ser estrictamente mayor que
la marca de tiempo del último bloque, la única garantía que podemos tener es que su valor estará
en algún punto entre las marcas de tiempo de dos bloques consecutivos en la cadena canónica. Un
validador malicioso podría hacerle tomar cualquier valor siempre que se cumpla la condición anterior.
Del mismo modo, block.prevrandao es manipulable en cierta medida ya que un validador malicioso
pude omitir un bloque si el valor que resulta no le es favorable, aunque puede ser una solución intere-
sante en muchas aplicaciones porque se genera mediante un algoritmo criptográficamente seguro y
es único para cada bloque.
Debido a estos problemas de sesgo y coste, muchos desarrolladores y proyectos de cadenas de
bloques recurren a servicios de oráculo externos, como la función aleatoria verificable (Verifiable Ran-
dom Function, VRF) de Chainlink (Blaut, Ma y Wolter, 2023). VRF se basa en un proceso criptográfico
para generar un número del que se puede garantizar su aleatoriedad. El proceso comienza con un
valor semilla, proporcionado por el usuario, el contrato inteligente, o la aplicación que solicita el nú-
mero aleatorio. Al hacer la solicitud, el nodo Chainlink genera un número aleatorio fuera de la cadena
de bloques y se compromete con dicho número realizando un cálculo conocido como compromiso
criptográfico. Este compromiso permanece oculto y nadie conoce el valor real del número aleatorio
en esta fase más allá del nodo que lo generó.
Tras un periodo de espera indicado por el contrato que solicitó el número aleatorio (p. ej., tras com-
pletarse el minado de un determinado número de bloques o tras que ocurra determinado evento), el
nodo Chainlink revela públicamente el número aleatorio comprometido junto con una prueba cripto-
gráfica que sirve para garantizar que el número se ha generado correctamente. El contrato inteligente
o la aplicación que solicitó el número aleatorio comprueba la prueba criptográfica para verificar que el

53
número revelado se generó de forma justa y segura, y que el número es impredecible y no fue mani-
pulado. Las técnicas criptográficas utilizadas para el compromiso y la generación de pruebas suelen
implicar algoritmos como la criptografía de curva elíptica (ECC) y el uso de pruebas de conocimiento
cero. Estos métodos criptográficos están bien establecidos y son ampliamente reconocidos por su
seguridad y fiabilidad.
En la práctica, para generar un número aleatorio instanciamos un contrato envoltorio del gene-
rador VRF. Por ejemplo, para generar números aleatorios sin necesidad de suscribirse a Chainlink
pagándolos por adelantado, instanciaríamos el contrato VRFV2WrapperConsumerBase. Después de
financiar nuestro contrato e inicializar algunas variables (p. ej., cuántos números deseamos generar,
el gas máximo que estamos dispuestos a pagar al VRF para que nos devuelva los números, el núme-
ro de confirmaciones de bloque que VRF tiene que esperar, o ciertas direcciones utilizadas por VRF),
lanzaríamos un procedimiento asíncrono para completar la generación:
1. Llamaríamos a la función requestRandomness del VRF para solicitar los números. Dicha función
devuelve inmediatamente un identificador de solicitud.
2. Cuando el generador VRF termine su tarea, invocará la función fulfillRandomWords pasándo-
le como parámetros el identificador de solicitud de la fase anterior y una cadena en memoria
con los números aleatorios generados. Nosotros reescribiremos el código de dicha función en
nuestro contrato para utilizar los números calculados de la manera que queramos. Lo más ha-
bitual es guardar esos valores o pasarlos a otras funciones de nuestro contrato y/o emitir un
evento indicando que los números están disponibles.
En el contrato de ejemplo CardDeks que aparece más adelante tenemos un ejemplo de este pro-
ceso:

1 function resetRandomSeed() external {


2 // Pide al wrapper que genere una palabra aleatoria. Parámetros:
3 // - callbackGasLimit: La cantidad máxima de gas a pagar
4 // para completar la función VRF callback. Si no es suficiente,
5 // se revertirá.
6 // - requestConfirmations: El número de confirmaciones de bloque
7 // que el servicio VRF esperará para responder.
8 // - numwords: El número de números aleatorios a solicitar (1).
9 // La función devuelve un requestId.
10 // Este contrato paga al wrapper el precio calculado de la solicitud.
11 uint256 requestId = requestRandomness(
12 callbackGasLimit,
13 requestConfirmations,
14 1
15 );
16
17 // Llamada a la función del wrapper calculateRequestPrice
18 // para estimar el coste total de la transacción
19 // e inicializar el ID de la petición.
20 // El resto de los campos RequestStatus se inicializaron
21 // al crear el contrato.
22 _request.request = requestId;
23 _request.paid = VRF_V2_WRAPPER.calculateRequestPrice(callbackGasLimit);
24 }
25
26 // Función de callback. El wrapper la llama cuando ha terminado, pasando
27 // como parámetros el _requestId correspondiente y la lista
28 // de palabras aleatorias generadas (una sola palabra en nuestro caso).
29 // En este ejemplo, recibe un número aleatorio y lo almacena en _nonce.
30 // En general, se sobreescribiría para implementar la lógica para
31 // manejar los valores aleatorios después de ser devueltos al contrato.
32 function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords)
33 internal override {
34 require(_request.paid > 0, "Solicitud VRF no encontrada.");

54
35 _request.fulfilled = true;
36 _request.randomSeed = _randomWords[0];
37 _nonce = _randomWords[0];
38
39 emit randomSeedAvailable(_requestId, _request.randomSeed, _request.paid);
40 }

La generación de números aleatorios no predecibles o reproducibles es crucial para situaciones


en las que la imparcialidad y la imprevisibilidad son esenciales, como en los juegos, las apuestas y
otras aplicaciones como la gestión de cadenas de suministros, las aplicaciones estadísticas o ciertas
aplicaciones de finanzas descentralizadas. En el ejemplo siguiente presentamos un contrato inteli-
gente para ofrecer un servicio de gestión de barajas de cartas. En este ejemplo, utilizamos VRF para
obtener un nonce para la generación de cartas, en concreto, los números VRF se usan para iniciali-
zar un generador de cartas pseudoaleatorias (PCG). Cualquiera puede invocar el generador VRF de
Chainlink a través de este contrato (función resetRandomSeed si el contrato tiene suficiente LINK pa-
ra cubrir los gastos de generación de números aleatorios VRF. LINK es una criptomoneda propietaria
de Chainlink utilizada para pagar por sus servicios. Inicialmente, el nonce del PCG se inicializa con
las existencias de gas del contrato, pero puede ser reseteado en cualquier momento con un número
aleatorio verificable.
Dicho de otro modo, el PCG se basa en el método clásico de generar números pseudoaleatorios
en contratos inteligentes de una blockchain Ethereum (es decir, a partir del hash SHA-256 del valor del
último Randao de la prueba de participación, la marca temporal, la dirección que invoca la función y el
nonce). El nonce se actualiza en cada generación para pseudoaleatorizar la generación de la siguien-
te carta. De todos modos, en cualquier momento cualquiera puede financiar el contrato con LINK y
renovar el nonce con un número VRF (p. ej., al crear una nueva baraja, al comenzar una nueva partida
con una baraja existente, etc.
Como se puede ver en el contrato, en este ejemplo también se ilustra el establecimiento de una ta-
rifa para la dirección que ofrece el servicio de gestión de barajas. Para ello, las funciones createDeck y
addPlayer se declaran como payable, y se establece como requisito que el valor de msg.value tiene
que ser mayor o igual que la tarifa de baraja establecida (originalmente 10.000 wei en este ejemplo). El
dueño del contrato puede actualizar este valor en cualquier momento mediante la función updateFee.
Además de la tarifa, el contrato sólo permite al dueño del contrato recuperar los remanentes de LINK
de la generación de números VRF, mediante la función withdraw. Esta sería una segunda fuente de
ingresos.

1 // SPDX-License-Identifier: MIT
2 //
3 // Contrato para implementar una colección de barajas de cartas. Utiliza la función
4 // Función Aleatoria Verificada (Verified Random Function, VRF) de Chainlink
5 // para generar un nonce para la generación de cartas.
6 //
7 // - Para obtener una nueva baraja, invoca la función createDeck(). Devuelve un ID de baraja.
8 // - Para obtener una carta nueva de un mazo, invoca la función dealCard(deckId). También
9 // es posible obtener una carta y el nombre simbólico de acuerdo con el
10 // estándar de las cartas (ver más abajo). También hay funciones públicas para obtener
11 // n cartas o para obtener todas las cartas restantes del mazo (ver más abajo, sólo índices,
12 // sin nombres simbólicos).
13 // - Para obtener la lista de todas las cartas repartidas hasta el momento, invoca
14 // cardsDealt(deckId).
15 // - Para reiniciar el mazo (es decir, para devolver todas las cartas repartidas al mazo)
16 // invoca resetDeck(deckId).
17 // - Para obtener la lista de cartas repartidas hasta el momento de una baraja:
18 // cardsDealt(deckID).
19 //
20 // Las funciones para reiniciar un mazo, ver todas las cartas repartidas o

55
21 // repartir todas las cartas restantes sólo pueden ser invocadas por el creador de la baraja.
22 //
23 // El coste de crear un mazo o añadir un jugador a un mazo/partida existente
24 // se indica mediante la constante _PRICE.
25 //
26 // El propietario del contrato tiene una función para retirar el ETH recaudado del contrato
27 // para la creación de mazos y jugadores.
28 //
29 // Los números VRF se usanpara inicializar el generador de cartas pseudoaleatorias (PCG).
30 // Cualquiera puede invocar el generador VRF de Chainlink si el contrato tiene
31 // suficiente LINK para cubrir los gastos de generación de números aleatorios VRF.
32 // Para ello, cualquiera puede invocar la función resetRandomSeed().
33 //
34 // Inicialmente, el PCG se inicializa con las existencias de gas del contrato, pero
35 // puede ser reseteado en cualquier momento con un número VRF.
36 //
37
38 pragma solidity ^0.8.20;
39
40 // Importaciones necesarias en este ejemplo:
41 // - ConfirmedOwner: Un contrato con helpers para la propiedad básica del contrato.
42 // - VRFV2WrapperConsumerBase: Crea peticiones VRF V2 sin necesidad de
43 // gestión de suscripciones. En lugar de crear y financiar una suscripción VRF V2
44 // es posible utilizar este wrapper para crear una solicitud,
45 // pagando por adelantado. Esta opción permite a cualquiera
46 // inicializar el PCG.
47 import "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol";
48 import "@chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol";
49
50 //
51 // Para solicitar testnet LINK y ETH: https://faucets.chain.link/
52 // Encuentra información sobre LINK Token Contracts y obtén las últimas ETH y
53 // LINK aquí: https://docs.chain.link/docs/link-token-contracts/
54 //
55
56 // Una vez desplegado este contrato, tienes que financiarlo con LINK para
57 // poder obtener números aleatorios. Para ello, tienes que:
58 //
59 // 1. Comprar Chainlink LINK para la red donde desplegaste tu contrato.
60 // 2. Obtener la dirección de tu contrato (puedes obtenerla una vez desplegado).
61 // 3. Transferir LINK desde tu monedero a la dirección del contrato.
62 //
63 // Dado que el precio se determina utilizando el precio del gas de la transacción,
64 // elwrapper cobra una prima adicional al gas de callback, además de algunos gastos
65 // generales adicionales asociados al contrato VRFV2Wrapper.
66 //
67 // Para estimar los costes: https://docs.chain.link/vrf/v2/estimating-costs
68
69 // Los contratos llamantes deben heredar de VRFV2WrapperConsumerBase y
70 // deben estar financiado con LINK suficiente para realizar la petición,
71 // de lo contrario las peticiones se revertirán.
72 //
73 // Se invoca la función ’requestRandomness’ con los parámetros
74 // deseados. Esta función se encarga de pagar por la petición según el precio en
75 // cada momento, detrayendo fondos del contrato (LINK / gas).
76
77 contract CardDeks is ConfirmedOwner, VRFV2WrapperConsumerBase {
78
79 // ESTRUCTURAS VRF
80
81 // Estructura para seguir el estado de la solicitud VRF:
82 // ID de la solicitud, importe pagado, si ya se ha completado
83 // o no, número aleatorio si se ha cumplido.

56
84 struct RequestStatus {
85 uint256 request; // requestId
86 uint256 paid; // importe pagado en LINK, 0 si no se ha solicitado
87 bool fulfilled; // si la petición se ha cumplido con éxito
88 uint256 randomSeed; // cuando se cumple la solicitud, número generado.
89 }
90
91 RequestStatus internal _request;
92
93 // Gas máximo que estamos dispuestos a pagar al VRF.
94 // Depende del número de valores solicitados a enviar a la
95 // función fulfillRandomWords(). Se prueba y justa este límite
96 // en función de la red, el tamaño de la petición y el procesamiento
97 // de la llamada callback en la función fulfillRandomWords()
98 // Si el callbackGasLimit no es suficiente, el callback fallará y
99 // se cobrará el trabajo realizado para generar
100 // los valores aleatorios solicitados.
101 uint32 callbackGasLimit = 400000;
102
103 // Cuántas confirmaciones de bloque hay que esperar antes de responder.
104 // Cuanto más espere el nodo, más seguro será el valor aleatorio.
105 // El valor por defecto es 3. El mínimo y el máximo
106 // de confirmaciones para cada red se pueden encontrar aquí:
107 // https://docs.chain.link/vrf/v2/direct-funding/supported-networks/#configurations
108 uint16 requestConfirmations = 3;
109
110 // Dirección LINK para Sepolia. Actualizable por el propietario del contrato.
111 address internal _linkAddress = 0x779877A7B0D9E8603169DdbD7836e478b4624789;
112
113 // Dirección WRAPPER para Sepolia. Actualizable por el propietario del contrato.
114 address internal _wrapperAddress = 0xab18414CD93297B0d12ac29E63Ca20f515b3DB46;
115
116 // Tarifa para crear una baraja o añadir jugadores a una baraja.
117 uint256 private _deckFee;
118
119 // Número máximo de jugadores por baraja.
120 uint256 private constant _MAX_PLAYERS = 16;
121
122 // Número de cartas en una baraja
123 uint32 private constant _N_CARDS = 40;
124
125 // Nonce para la generación de números pseudoaleatorios
126 uint256 private _nonce;
127
128 // Estructura de la baraja. Recoge los elementos básicos de una baraja.
129 struct Deck {
130 address creator; // Creador del mazo
131 bool[] generatedCards; // Cartas generadas hasta el momento para este mazo
132 uint32 cardCount; // Número de cartas generadas para este maz
133 address[] players; // Jugadores que pueden jugar con este mazo
134 uint32 nplayers; // Número de jugadores activos
135 }
136
137 // ESTRUCTURA DE MAZOS
138
139 // Lista de mazos creados
140 Deck[] private _decks;
141
142 // Número de mazos creados
143 uint256 private _ndecks;
144
145 // Modificador para las operaciones que requieren un repartidor.
146 modifier onlyDealer(uint256 deckid) {

57
147 require(msg.sender == _decks[deckid].creator,
148 "Solo el creador de este mazo puede hacer esto."
149 );
150 _;
151 }
152
153 // Modificador para las operaciones que requieren un jugador.
154 modifier onlyPlayer(uint256 deckid) {
155 require(isPlayer(deckid, msg.sender),
156 "Solo un jugador registrado en este mazo puede hacer esto."
157 );
158 _;
159 }
160
161 // Evento para señalar que la petición VRF requestId se ha completado.
162 // La palabra aleatoria generada
163 // se almacena en la estructura _request, y payment informa sobre el coste
164 // del proceso.
165 event randomSeedAvailable (
166 uint256 requestId,
167 uint256 randomWord,
168 uint256 payment
169 );
170
171 // Se inicializa el propietario del contrato, la tarifa de baraja, el
172 // número de barajas creadas hasta el momento y el
173 // nonce para calcular números pseudoaleatoriosm a la cantidad de gas
174 // en este contrato. Además, invoca los constructores de ConfirmedOwner
175 // y RFV2WrapperConsumerBase.
176 constructor() ConfirmedOwner(msg.sender)
177 VRFV2WrapperConsumerBase(_linkAddress, _wrapperAddress) {
178 _deckFee = 10000 wei;
179 _ndecks = 0;
180 _nonce = gasleft(); // Usamos el gas disponible como nonce inicial.
181 }
182
183 // Genera un número pseudoaleatorio a partir del último Randao,
184 // la marca de tiempo del contrato y un nonce, que a su vez
185 // se inicializa al resto gas para este contrato.
186 // El nonce también puede ser inicializado a un número VRF bajo petición.
187 function _computeSeed() internal returns (uint256) {
188 uint256 randomSeed = uint256(keccak256(abi.encodePacked(
189 block.prevrandao,
190 block.timestamp, msg.sender,
191 _nonce))
192 );
193 _nonce++;
194 return randomSeed;
195 }
196
197 // FUNCIONES DE VRF
198
199 // Función para obtener un número VRF para resetear el nonce,
200 // utilizado para la generación de cartas, a un número VRF. Se
201 // solicita la generación de números aleatorios por el contrato VRF V2
202 // Chainlink wrapper contract. Se solicitará un solo número.
203 //
204 // Para ejecutar esta función el contrato tiene que tener LINK
205 // suficiente como para generar el número VRF. OJO: el LINK que sobre
206 // sólo podrá ser retirado por el dueño del contrato.
207 function resetRandomSeed() external {
208 // Pide al wrapper que genere una palabra aleatoria. Parámetros:
209 // - callbackGasLimit: La cantidad máxima de gas a pagar

58
210 // para completar la función VRF callback. Si no es suficiente,
211 // se revertirá.
212 // - requestConfirmations: El número de confirmaciones de bloque
213 // que el servicio VRF esperará para responder.
214 // - numwords: El número de números aleatorios a solicitar (1).
215 // La función devuelve un requestId.
216 // Este contrato paga al wrapper el precio calculado de la solicitud.
217 uint256 requestId = requestRandomness(
218 callbackGasLimit,
219 requestConfirmations,
220 1
221 );
222
223 // Llamada a la función del wrapper calculateRequestPrice
224 // para estimar el coste total de la transacción
225 // e inicializar el ID de la petición.
226 // El resto de los campos RequestStatus se inicializaron
227 // al crear el contrato.
228 _request.request = requestId;
229 _request.paid = VRF_V2_WRAPPER.calculateRequestPrice(callbackGasLimit);
230 }
231
232 // Función de callback. El wrapper la llama cuando ha terminado, pasando
233 // como parámetros el _requestId correspondiente y la lista
234 // de palabras aleatorias generadas (una sola palabra en nuestro caso).
235 // En este ejemplo, recibe un número aleatorio y lo almacena en _nonce.
236 // En general, se sobreescribiría para implementar la lógica para
237 // manejar los valores aleatorios después de ser devueltos al contrato.
238 function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords)
239 internal override {
240 require(_request.paid > 0, "Solicitud VRF no encontrada.");
241 _request.fulfilled = true;
242 _request.randomSeed = _randomWords[0];
243 _nonce = _randomWords[0];
244
245 emit randomSeedAvailable(_requestId, _request.randomSeed, _request.paid);
246 }
247
248 // Obtiene el estado de la inicialización del nonce.
249 function getRandomSeedStatus() external view returns (bool) {
250 require(_request.paid > 0, "Solicitud VRF no encontrada.");
251 return (_request.fulfilled);
252 }
253
254 // Actualiza la dirección del wrapper Chainlink.
255 function updateVRFWrapper(address newAddress) external onlyOwner {
256 _wrapperAddress = newAddress;
257 }
258
259 // Actualiza la dirección LINK de Chainlink.
260 function updateVRFLinkaddress(address newAddress) external onlyOwner {
261 _linkAddress = newAddress;
262 }
263
264 // FUNCIONES DE LA BARAJA
265
266 // Devuelve un nuevo índice de carta aleatorio entre 1 y 40.
267 // Se genera a partir de un nonce,
268 // el timestap y la dirección del emisor.
269 function _getCardIndex() internal returns (uint32) {
270 // Generate a random number between 1 and _N_CARDS
271 uint32 carIndex = uint32((_computeSeed() % _N_CARDS) + 1);
272

59
273 return carIndex;
274 }
275
276 // Función de decremento seguro para enteros positivos de 32 bits.
277 function _dec(uint32 a) internal pure returns (uint32) {
278 assert(a > 0);
279 return a - 1;
280 }
281
282 // Reparte una carta nueva de una baraja. Las cartas serán diferentes,
283 // y es posible obtener cartas siempre que el mazo no esté agotado.
284 function dealCard(uint256 deckid) public onlyPlayer(deckid) returns (uint32) {
285 require(deckid < _ndecks, "Esta baraja no existe.");
286 require(_decks[deckid].cardCount < _N_CARDS, "Baraja agotada.");
287 uint32 card;
288
289 // Sigue generando cartas hasta que se genere una carta no repartida ya.
290 do {
291 card = _getCardIndex();
292 } while(_decks[deckid].generatedCards[_dec(card)]);
293
294 // Tenemos una nueva carta. Aumentamos el número de cartas y
295 // almacenar la carta.
296 _decks[deckid].cardCount++;
297 _decks[deckid].generatedCards[_dec(card)] = true;
298
299 return card;
300 }
301
302 // Igual que la anterior, sólo que devuelve el nombre simbólico de la carta.
303 function dealCardSym(uint256 deckid) external onlyPlayer(deckid)
304 returns (string memory) {
305 require(deckid < _ndecks, "Esta baraja no existe.");
306 return uintToCard(dealCard(deckid));
307 }
308
309 // Reparte n cartas de una baraja. Las cartas repartidas serán diferentes,
310 // y se pueden obtener cartas mientras el mazo no se agote.
311 function dealCards(uint256 deckid, uint32 n) external onlyPlayer(deckid)
312 returns(uint32[] memory) {
313 require(deckid < _ndecks, "Esta baraja no existe.");
314 require(_decks[deckid].cardCount <= (_N_CARDS - n),
315 "No hay cartas suficientes en este mazo.");
316
317 uint32[] memory cards = new uint32[](n);
318 for (uint32 i=0; i < n; i++)
319 cards[i] = dealCard(deckid);
320
321 return cards;
322 }
323
324 // Reparte todas las cartas restantes de una baraja. Solo para el creador
325 // de esta baraja.
326 function depleteDeck(uint deckid) external onlyDealer(deckid)
327 returns(uint32[] memory) {
328 require(deckid < _ndecks, "Esta baraja no existe.");
329 require(_decks[deckid].cardCount<_N_CARDS,
330 "La baraja ya no tiene cartas.");
331
332 uint32 cardsToDeal = _N_CARDS - _decks[deckid].cardCount;
333 uint32[] memory cards = new uint32[](cardsToDeal);
334
335 for (uint32 i=0; i < cardsToDeal; i++)

60
336 cards[i] = dealCard(deckid);
337
338 return cards;
339 }
340
341 // Devuelve un array con todas las cartas repartidas de una baraja.
342 function cardsDealt(uint256 deckid) external view onlyDealer(deckid)
343 returns(uint32[] memory) {
344 require(deckid < _ndecks, "Esta baraja no existe.");
345 uint32[] memory cards = new uint32[](_decks[deckid].cardCount);
346 uint32 j = 0;
347
348 for (uint32 i=0; i < _N_CARDS; i++)
349 if (_decks[deckid].generatedCards[i]) cards[j++] = i + 1;
350
351 return cards;
352 }
353
354 // Reinicializa una baraja
355 function resetDeck(uint deckid) external onlyDealer(deckid) {
356 require(deckid < _ndecks, "Esta baraja no existe.");
357 for (uint32 i = 0; i < _N_CARDS; i++)
358 _decks[deckid].generatedCards[i] = false;
359 _decks[deckid].cardCount = 0;
360 }
361
362 // Función para convertir un número de carta en una carta, según el
363 // estándar de la baraja española de 40 cartas.
364 // Las cartas se ordenan normalmente en orden ascendente como sigue:
365 //
366 // Oros
367 // 1, 2, 3, 4, 5, 6, 7, 10 (Sota), 11 (Caballo), 12 (Rey).
368 //
369 // Copas:
370 // 1, 2, 3, 4, 5, 6, 7, 10 (Sota), 11 (Caballo), 12 (Rey).
371 //
372 // Espadas:
373 // 1, 2, 3, 4, 5, 6, 7, 10 (Sota), 11 (Caballo), 12 (Rey).
374 //
375 // Bastos:
376 // 1, 2, 3, 4, 5, 6, 7, 10 (Sota), 11 (Caballo), 12 (Rey).
377 //
378 function uintToCard(uint32 cardNumber) public pure returns (string memory) {
379 require(cardNumber >= 1 && cardNumber <= _N_CARDS,
380 "El valor de la carta tiene que estar entre 1 y 40.");
381
382 string[10] memory ranks = ["1", "2", "3", "4", "5", "6", "7",
383 "10", "11", "12"];
384 string[4] memory suits = ["Oros", "Copas", "Espadas", "Bastos"];
385
386 uint32 suitIndex = (cardNumber - 1) / 10;
387 uint32 rankIndex = (cardNumber - 1) % 10;
388
389 string memory card = string(abi.encodePacked(ranks[rankIndex],
390 " de ", suits[suitIndex]));
391
392 return card;
393 }
394
395 // Función para añadir un mazo a la lista de _decks, con nPlayers jugadores.
396 // Devuelve el ID del nuevo mazo.
397 // Además, inicializa las propiedades del mazo.
398 function createDeck(uint32 nPlayers) external payable returns (uint) {

61
399 require(msg.value >= _deckFee, "Fondos insuficientes para esta compra.");
400 require(nPlayers <= _MAX_PLAYERS, "Demasiados jugadores para este mazo" );
401
402 // Crea un nuevo objeto de mazo con 0 cartas repartidas,
403 // y se añade al array _decks.
404 _decks.push(Deck(
405 msg.sender,
406 new bool[](_N_CARDS),
407 0,
408 new address[](nPlayers),
409 1));
410 uint256 newId = _decks.length - 1;
411 // Añadimos al creador del mazo como primer jugador del mismo.
412 _decks[newId].players[0] = msg.sender;
413 // Incrementamos el número de mazos creados.
414 _ndecks++;
415
416 // Devuelve el nuevo ID
417 return newId;
418 }
419
420 // Añadimos un nuevo jugador a un mazo.
421 function addPlayer(uint256 deckid, address newPlayer) external payable
422 onlyDealer(deckid) {
423 require(deckid < _ndecks, "Esta baraja no existe.");
424 require(_decks[deckid].nplayers < _MAX_PLAYERS, "Table already full.");
425 require(msg.value >= _deckFee, "Fondos insuficientes para esta compra.");
426
427 // Añade el nuevo jugador a la lista de jugadores de esta baraja.
428 _decks[deckid].players[_decks[deckid].nplayers++] = newPlayer;
429 }
430
431 // Obtiene la lista de jugadores del mazo deckid.
432 function getPlayersList(uint256 deckid) external view onlyPlayer(deckid)
433 returns (address[] memory) {
434 require(deckid < _ndecks, "Esta baraja no existe.");
435
436 uint32 np = _decks[deckid].nplayers;
437 address[] memory plist = new address[](np);
438
439 for (uint i= 0; i < np; i++)
440 plist[i] = _decks[deckid].players[i];
441
442 return plist;
443 }
444
445 // Comprueba si una dirección es un jugador registrado para una baraja.
446 function isPlayer(uint256 deckid, address player) public view returns (bool) {
447 require(deckid < _ndecks, "Esta baraja no existe.");
448 address[] memory plist = _decks[deckid].players;
449 uint32 np = _decks[deckid].nplayers;
450
451 for (uint i= 0; i < np; i++)
452 if (plist[i] == player) return true;
453
454 return false;
455 }
456
457 // Función para actualizar la tasa de creación del mazo / nuevo jugador.
458 function updateFee(uint256 newFee) external onlyOwner {
459 _deckFee = newFee;
460 }
461

62
462 // Función de recaudación de los ingresos del contrato, tanto
463 // por la tarifa de baraja como por remanentes de LINK.
464 // Solo el dueño del contrato puede recuperar los remanentes
465 // de aleatorizar con VRF la generación de cartas. Se
466 // trata de un ingreso adicional para el creador del contrato.
467 function withdraw() external onlyOwner {
468 payable(owner()).transfer(address(this).balance);
469 }
470
471
472 }

Figura 7: Nuestro servicio de generación de barajas trabaja con barajas como esta (Autor: Basquetteur, licencia CC BY-SA
3.0).

Este servicio de barajas está pensado para servir barajas españolas de 40 cartas (ver Fig. 7). Podría
actualizarse fácilmente para servir barajas francesas de 52 cartas sin más que redefinir la constante
_N_CARDS para que tome el valor 52 y definir una nueva función uintToCard, como por ejemplo:

1 // Function to convert a card number from a 52-card deck


2 // to a card, according to the standard
3 // poker ordering. Ranks are typically numbered in ascending order as follows:
4 //
5 // Hearts:
6 // 2, 3, 4, 5, 6, 7, 8, 9, 10, J (Jack), Q (Queen), K (King), A (Ace)
7 //
8 // Diamonds:
9 // 2, 3, 4, 5, 6, 7, 8, 9, 10, J (Jack), Q (Queen), K (King), A (Ace)
10 //
11 // Clubs:
12 // 2, 3, 4, 5, 6, 7, 8, 9, 10, J (Jack), Q (Queen), K (King), A (Ace)
13 //
14 // Spades:
15 // 2, 3, 4, 5, 6, 7, 8, 9, 10, J (Jack), Q (Queen), K (King), A (Ace)
16 //
17 function uintToCard(uint32 cardNumber) public pure returns (string memory) {
18 require(cardNumber >= 1 && cardNumber <= 52,
19 "Card number must be between 1 and 52.");
20
21 string[13] memory ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "10",
22 "J", "Q", "K", "A"];
23 string[4] memory suits = ["Hearts", "Diamonds", "Clubs", "Spades"];

63
24
25 uint32 suitIndex = (cardNumber - 1) / 13;
26 uint32 rankIndex = (cardNumber - 1) % 13;
27
28 string memory card = string(abi.encodePacked(ranks[rankIndex],
29 " of ", suits[suitIndex]));
30
31 return card;
32 }

7.4. Redes de oráculos y oráculos entre cadenas

Una red de oráculos es un sistema descentralizado que proporciona a los contratos inteligentes en
una blockchain acceso a fuentes de datos y servicios externos. Como hemos visto (ver apartado 5), los
contratos inteligentes son programas autoejecutables diseñados para ejecutarse automáticamente
cuando se cumplen determinadas condiciones. Los contratos inteligentes suelen estar limitados a los
datos y eventos que están disponibles dentro de la propia red blockchain. Las redes de oráculos son
redes descentralizadas, típicamente P2P, proporcionan a los contratos inteligentes acceso a fuentes
de datos externas a través de oráculos, como feeds de precios, datos meteorológicos y otra informa-
ción fuera de la cadena, actuando como intermediarios entre la blockchain y el mundo exterior. Las
redes de oráculos utilizan una arquitectura descentralizada que garantiza la seguridad y fiabilidad de
los datos que proporcionan. Esto significa que los datos obtenidos por la red de oráculos son valida-
dos y verificados por múltiples nodos de la propia red, reduciendo el riesgo de datos fraudulentos o
inexactos.
El uso de redes de oráculos permite a los contratos inteligentes interactuar con el mundo real de
forma segura y fiable, lo que los hace más potentes y versátiles. De hecho, existe ya un número im-
portante de redes de oráculos asociadas a las redes blockchain más populares. Como hemos visto
en los ejemplos anteriores, Chainlink es una red de oráculos descentralizada que permite a los con-
tratos inteligentes acceder a fuentes de datos fuera de la cadena, API y otros recursos. Es el servicio
de oráculos más utilizado en Ethereum y soporta una amplia gama de fuentes de datos y protocolos.
Band Protocol es otra red de oráculos descentralizada que permite a los contratos inteligentes acceder
a datos fuera de la cadena. Utiliza un mecanismo de consenso de prueba delegada de participación
(DPoS) y admite una serie de fuentes de datos, como precios de criptomonedas, datos meteoroló-
gicos y resultados deportivos. Binance Smart Chain Oracle es una red de oráculos que proporciona
acceso seguro y fiable a datos fuera de la cadena para contratos inteligentes en Binance Smart Chain.
Otras redes de oráculos populares son TRON Oracle en la red TRON; Provable y Tellor para varias pla-
taformas blockchain; Augur como plataforma de predicción descentralizada que utiliza oráculos para
resolver e informar de resultados de eventos, como elecciones o eventos deportivos; o MakerDAO y
Uniswap en los mercados de criptomonedas.
Los oráculos entre cadenas, también conocidos como oráculos intercadena o cross-chain ora-
cles en inglés, son sistemas diseñados para proporcionar información y facilitar la interoperabilidad
entre diferentes cadenas de bloques. En esencia, en un contexto fragmentado con múltiples block-
chains donde cada una opera independientemente de las demás, estos oráculos permiten que dichas
blockchains se comuniquen entre sí y compartan datos del mundo real o información sobre eventos
específicos, como por ejemplo información sobre activos, estados de contratos, eventos, etc.
Los oráculos entre cadenas proporcionan una capa de interoperabilidad entre blockchains, per-
mitiendo que una blockchain obtenga y utilice información de otra blockchain de manera segura y
confiable. Esta comunicación puede ser bidireccional, es decir, que la información fluya en ambas di-
recciones entre las cadenas, lo cual es esencial para aplicaciones que requieren coordinación entre
múltiples blockchains y donde la seguridad y la confianza son aspectos críticos. Los oráculos entre

64
cadenas deben garantizar que los datos transferidos entre blockchains sean precisos y no manipula-
dos.
Estos oráculos se pueden utilizar, por ejemplo, para la transferencia segura de activos digitales
entre diferentes blockchains o para desplegar contratos inteligentes interoperables que operan en
diferentes blockchains. Para lograr una interoperabilidad efectiva, a menudo se utilizan estándares y
protocolos específicos de puente que permiten la interoperabilidad entre blockchains, como Polkadot
o Cosmos.
La implementación exitosa de oráculos entre cadenas es esencial para el desarrollo de ecosiste-
mas blockchain más amplios y conectados, permitiendo que las aplicaciones y activos digitales se
muevan sin problemas a través de diferentes blockchains de manera segura y confiable.

7.5. Aspectos de seguridad

Aunque los oráculos desempeñan un papel importante a la hora de permitir que las aplicaciones
descentralizadas interactúen con datos del mundo real, también introducen varios retos de seguridad
y potenciales vulnerabilidades. Los oráculos pueden ser vulnerables a la manipulación de datos, ya sea
a través de un nodo comprometido o de un actor malicioso que proporcione datos falsos. Esto puede
dar lugar a que se proporcionen datos inexactos a un contrato inteligente, dando lugar a una ejecución
incorrecta del contrato. Los oráculos centralizados pueden convertirse además en un único punto de
fallo, lo que significa que si el oráculo falla, toda la aplicación blockchain puede verse afectada. Esto
puede dar lugar a importantes pérdidas financieras u otras consecuencias negativas.
Los oráculos pueden ser vulnerables a accesos no autorizados, ya sea a través de un nodo com-
prometido o a través de una conexión insegura. Esto puede dar lugar a que datos sensibles queden
expuestos o sean manipulados por partes no autorizadas. Por otra parte, los oráculos pueden utilizar-
se como vector de ataque para explotar vulnerabilidades en los contratos inteligentes. Por ejemplo,
un actor malicioso podría utilizar un oráculo para proporcionar datos falsos que activen un exploit en
el contrato inteligente, lo que le permitiría robar fondos o ejecutar acciones no autorizadas. Los orácu-
los pueden ser vulnerables también a ataques de red como los ataques distribuidos de denegación de
servicio (DDoS), que pueden interrumpir la capacidad del oráculo para proporcionar datos precisos.
Para mitigar estos problemas de seguridad, es importante aplicar medidas de seguridad adecua-
das cuando se trabaja con oráculos, como la implementación de múltiples oráculos para la redundan-
cia, el uso de oráculos descentralizados, el cifrado de datos y conexiones, la realización de auditorías
periódicas y el uso de mecanismos seguros de autenticación y autorización. También es importante
considerar cuidadosamente los riesgos y las posibles vulnerabilidades asociadas a los oráculos a la
hora de diseñar e implementar aplicaciones descentralizadas.
En otras palabras, trabajar con oráculos en la tecnología blockchain requiere seguir ciertas bue-
nas prácticas para garantizar la fiabilidad, seguridad e integridad de los datos que se proporcionan al
contrato inteligente. A la hora de seleccionar un proveedor de oráculos, es importante elegir uno con
un historial probado de suministro de datos fiables y precisos. El proveedor elegido debería contar
también con mecanismos transparentes para verificar la autenticidad y exactitud de los datos que
proporciona. Para garantizar la fiabilidad y seguridad de los datos proporcionados, se recomienda in-
cluso utilizar múltiples oráculos que proporcionen datos redundantes. Esto puede ayudar a prevenir
cualquier punto único de fallo o manipulación por parte de un único oráculo. Es importante implemen-
tar mecanismos de gestión de errores y de retroceso (rollback en el contrato inteligente para manejar
situaciones en las que los datos proporcionados por el oráculo son inexactos o no están disponibles.
Los oráculos descentralizados o redes de oráculos que dependen de una red de nodos indepen-
dientes proporcionan mayor seguridad y resistencia a la manipulación que los oráculos centralizados.

65
Los oráculos descentralizados también proporcionan un mayor nivel de transparencia y responsabili-
dad, ya que los datos ofrecidos son verificados por múltiples fuentes independientes.
Para evitar manipulaciones y garantizar la autenticidad de los datos, se recomienda utilizar méto-
dos criptográficos como firmas digitales o funciones hash para verificar los datos que proporciona el
oráculo. Además, las auditorías periódicas del proveedor del oráculo y del contrato inteligente pueden
ayudar a garantizar la fiabilidad y seguridad de los datos que se proporcionan. Las auditorías también
pueden ayudar a identificar cualquier vulnerabilidad o debilidad potencial en el oráculo o el contrato
inteligente.

8. Sistemas de archivos descentralizados

Los sistemas de archivos peer-to-peer (P2P) o sistemas de archivos descentralizados son siste-
mas de archivos distribuidos que permiten a los usuarios compartir archivos directamente entre sí
sin depender de un servidor centralizado. Se construyen sobre una red P2P (ver apéndice E) donde
cada usuario aporta al sistema una parte de su espacio de almacenamiento y del ancho de banda de
la red. Los archivos se almacenan por lo general en varios nodos de la red. Estos sistemas de almace-
namiento utilizan algoritmos criptográficos para proteger y cifrar los datos, algoritmos de dispersión
para mantener su integridad y disponibilidad, algoritmos de consenso para garantizar la coherencia
entre nodos y autenticación descentralizada para verificar a las personas usuarias. Como consecuen-
cia, disponemos de una solución de almacenamiento más robusto y eficiente que los sistemas de
archivos tradicionales, que permite compartir y acceder a datos de manera segura, rápida y fiable sin
depender de un proveedor centralizado.
Al igual que las redes sobre las que se construyen, los sistemas de archivos P2P utilizan por lo
general una tabla hash distribuida (DHT) para indexar y localizar los archivos en la red. Cuando un
usuario quiere acceder a un archivo, puede localizarlo a través de algún nodo que tenga una copia de
la DHT y descargarlo directamente del usuario o usuarios que lo alojan en ese momento.
Los sistemas de archivos P2P tienen varias ventajas sobre los sistemas de archivos cliente-servidor
tradicionales, heredadas de las redes P2P. Son más resistentes a los fallos y pueden seguir funcionan-
do aunque algunos nodos de la red se desconecten. También proporcionan velocidades de descarga
más rápidas, ya que los archivos pueden descargarse de múltiples fuentes simultáneamente. Ade-
más, los sistemas de archivos P2P suelen garantizar mejor la privacidad y seguridad de los datos, ya
que los archivos no se almacenan en un servidor centralizado que podría ser vulnerable a ataques.
Algunos ejemplos populares de sistemas de archivos P2P son BitTorrent, eDonkey y Gnutella. Estos
sistemas se utilizan habitualmente para compartir archivos de gran tamaño, como películas, músi-
ca y software, pero también pueden emplearse para compartir otros tipos de información, como por
ejemplo conjuntos de datos científicos (datasets) o copias de seguridad.
En los párrafos siguientes analizaremos brevemente los fundamentos y principios clave de estos
sistemas de archivos, así como su arquitectura y funcionamiento. Nos centraremos en el sistema de
archivos IPFS (Interplanetary File System), un sistema de almacenamiento descentralizado que se
ha convertido en una referencia para proporcionar almacenamiento persistente en el ámbito de las
cadenas de bloques. Antes de nada, analizaremos brevemente las limitaciones de los sistemas de
archivos tradicionales en el contexto de las cadenas de bloques.

8.1. Limitaciones de los sistemas de archivos tradicionales

Los sistemas de archivos tradicionales presentan diferencias clave con los sistemas de archivos
P2P en cuanto a su arquitectura y funcionamiento. En los sistemas centralizados los datos se alma-

66
cenan en un único lugar controlado por una entidad proveedora de servicios (p. ej., un conjunto de
servidores o un servicio de almacenamiento en la nube), lo que implica dependencia de esta enti-
dad para la gestión y acceso a dichos datos. Estas soluciones suelen ser propietarias y vulnerables
a ataques cibernéticos o pérdida de información debido a errores humanos o fallos en el hardware.
Conceptualmente, un sistema de almacenamiento en la nube tradicional no deja de ser un sistema
de archivo centralizado, ya que la gestión de la información almacenada depende exclusivamente del
proveedor de servicios en la nube.
Los sistemas de archivos tradicionales presentan varias limitaciones en términos de seguridad,
accesibilidad y puntos de fallo en comparación con los sistemas de archivos descentralizados. Por
ejemplo, en los sistemas de archivos centralizados, la gestión del acceso a los recursos se realiza
mediante permisos y grupos de usuarios. Este sistema de permisos por tipo de usuario es vulnerable
a ataques de suplantación o ataques tipo phishing ya que, si se produce un acceso no autorizado a las
credenciales de un usuario, se dispone acceso a toda la información accesible para dicho usuario, lo
cual permitiría a un atacante eliminar, modificar, cifrar o almacenar nueva información no autorizada.
En cambio, los sistemas de archivos descentralizados disponen de mecanismos para garantizar la
inmutabilidad de la información almacenada y utilizan técnicas criptográficas de forma nativa para
proteger y cifrar los datos, lo que reduce drásticamente el riesgo de robo o alteración de información.
Además, los sistemas de archivos tradicionales suelen ser propietarios y centralizados, lo que
significa que una única entidad controla todo el acceso a los datos almacenados, generalmente la
entidad que opera los servidores donde se almacenan los datos o el servicio de almacenamiento en
la nube. Esto puede limitar la capacidad de las personas usuarias para compartir o colaborar libre-
mente en proyectos, especialmente si se trata de organizaciones globales con usuarios dispersos
geográficamente. Por otro lado, los sistemas de archivos descentralizados, debido a la arquitectura
P2P subyacente, permiten a los usuarios compartir y acceder a datos evitando un control centralizado.
Por otro lado, en los sistemas de archivos tradicionales existen varios puntos de fallo críticos que
pueden llegar a comprometer la integridad de la información de forma catastrófica, como la pérdida de
datos por errores humanos, fallos en el hardware o errores en el sistema operativo o las aplicaciones
de gestión de la información. Además, estos sistemas suelen ser propensos a ataques cibernéticos
y robo de información debido a sus vulnerabilidades en seguridad. Los sistemas de archivos descen-
tralizados reducen drásticamente la probabilidad de pérdida de datos, ya que se distribuyen entre los
nodos de la red P2P.

8.2. Fundamentos de los sistemas de archivos descentralizados

Un sistema de archivos descentralizado se basa en tres principios fundamentales: el direcciona-


miento por contenido, la descentralización y la tolerancia a fallos. En un sistema de ficheros tradicional
podemos localizar un contenido a partir de un identificador de fichero y de la ruta de acceso a dicho
fichero, mientras que en los sistemas descentralizados localizamos un contenido a partir de una clave
única que se calcula a partir del propio contenido, de manera que dos contenidos diferentes no pue-
den compartir la misma clave. Cuando queremos obtener un contenido almacenado, en vez de indicar
dónde está localizado (ruta de acceso y nombre de fichero) indicamos directamente qué contenido
queremos obtener.
La descentralización implica que los datos se trocean en fragmentos pequeños que se almacenan
de manera distribuida entre múltiples nodos de la red P2P, lo que reduce la dependencia del proveedor
centralizado y aumenta la resistencia a puntos de fallo. Esta distribución de datos entre nodos permite
recuperar fácilmente cualquier fragmento perdido o dañado para reconstruir el archivo original. La to-
lerancia a fallos se logra mediante algoritmos de dispersión y consenso que mantienen la coherencia
y consistencia en una red descentralizada, evitando conflicto entre diferentes versiones del mismo
archivo y preservando la integridad de los datos.

67
Estos sistemas suelen utilizar además algoritmos de cifrado para proteger y garantizar la segu-
ridad de los datos almacenados, reduciendo el riesgo de robo o alteración de información. Por otra
parte, la autenticación de los usuarios se realiza a través de protocolos descentralizados, como por
ejemplo mediante criptografía de clave pública o firmas digitales, lo que evita depender de un provee-
dor centralizado para la verificación del usuario.
En definitiva, los sistemas de archivos descentralizados, al basarse en una red P2P donde los datos
se almacenan y distribuyen entre múltiples nodos, eliminan la dependencia del proveedor centralizado
y mejoran su robustez frente a puntos de fallo, a la vez que se da soporte a la replicación automática
y transparente para el usuario para garantizar la disponibilidad del contenido incluso si algunos no-
dos fallan. La distribución de datos garantiza que los archivos se dividan en fragmentos pequeños
para su almacenamiento entre nodos, permitiendo recuperar fácilmente cualquier fragmento perdido
o dañado para reconstruir el archivo original, y los algoritmos de dispersión y consenso mantienen
la coherencia y consistencia en una red descentralizada, evitando conflictos entre diferentes versio-
nes del mismo archivo y preservando la integridad de los datos. En resumen, un sistema de archivos
descentralizado es una solución más segura, eficiente y resistente a fallos que se basa en principios
como la descentralización, distribución de datos y tolerancia a fallos.

8.3. Arquitectura y funcionamiento

Una arquitectura de sistema de archivos descentralizado se basa en un conjunto de nodos co-


nectados a una red P2P. Estos nodos se dividen en varios tipos, en función en su rol dentro de la
red, aunque un nodo concreto puede asumir varios roles. Por ejemplo, los nodos de almacenamiento
proporcionan almacenamiento físico para almacenar fragmentos de contenidos o proporcionar alma-
cenamiento persistente; los nodos de búsqueda mantienen copias de las tablas DHT para identificar
la localización de los contenidos a partir de sus identificadores, y los nodos de direccionamiento dan
soporte al enrutado de las solicitudes de contenido y su entrega desde los nodos de almacenamiento
a los usuarios.
Como indicamos antes, una característica fundamental de los sistemas de almacenamiento P2P
es que la información almacenada se identifica por su contenido y no por su ubicación, como ocurre
en los sistemas de almacenamiento tradicionales. El direccionamiento por contenido es un proceso
mediante el cual se localiza y accede a contenidos específicos almacenados en la red y no a deter-
minados archivos, utilizando el protocolo P2P para encontrar rutas óptimas para transferir datos. Las
claves para identificar contenidos concretos son en realidad claves de hash generadas a partir del
contenido de un archivo o bloque de datos que queremos almacenar, que se utilizan para identificar
y verificar la integridad de los datos almacenados en la red, evitando así posibles problemas como el
robo de datos o alteración indebidamente del contenido.
En caso de pérdida de datos, los algoritmos descentralizados identificarán automáticamente y
recuperarán contenidos a partir de las copias existentes en la red. La comunicación entre nodos se
realiza mediante hashes únicos que permiten verificar la integridad del contenido antes de transferirlo,
lo cual evita posibles problemas como el robo de datos o alteración indebidamente del contenido. En
resumen, la replicación y recuperación de datos se basan en la colaboración entre nodos de la red
para garantizar una mayor resistencia a fallos, seguridad y acceso rápido a contenidos previamente
almacenados. Por otra parte, los algoritmos descentralizados no permiten cambios en el contenido
de un archivo una vez que ha sido almacenado, lo que garantiza la inmutabilidad e integridad.

68
8.4. InterPlanetary File System

El Sistema de Archivos Interplanetario (IPFS) es un protocolo y una red diseñados para crear un
método peer-to-peer para almacenar y compartir contenido de cualquier tipo en un sistema de ar-
chivos descentralizado, siendo su objetivo principal el de mejorar la eficiencia, resistencia a fallos y
privacidad de los sistemas de archivos tradicionales. Fue diseñado inicialmente por Juan Benet (Be-
net, 2014), y ahora es un proyecto de código abierto desarrollado con ayuda de la comunidad.
IPFS está diseñado para sustituir a la arquitectura tradicional cliente-servidor de la World Wide
Web, creando un método distribuido y descentralizado de compartir archivos. IPFS es compatible con
cualquier tipo de archivo y permite el acceso rápido a contenidos previamente almacenados en la red,
independientemente de su ubicación geográfica o la capacidad del nodo local. Este sistema ofrece
una alternativa descentralizada y eficiente a los sistemas centralizados tradicionales como FTP, HTTP
o SMB.
En lugar de recuperar contenidos de un único servidor, IPFS los recupera de una red de pares
que almacenan los mismos contenidos. Esto crea un sistema más sólido y resistente a la censura,
ya que el contenido no está ligado a un único punto de fallo. Para ello, IPFS utiliza un sistema de
direccionamiento único, denominado almacenamiento direccionable por contenido o content-addres-
sable storage (CAS). En IPFS, cada contenido recibe un hash único que se utiliza como dirección en la
red. Cuando un usuario solicita un contenido, IPFS busca otros nodos de la red que tengan el mismo
contenido y lo recupera de ellos. Esto también significa que si un contenido ya está en la red, no se
duplicará, lo que ahorra espacio y reduce el uso de ancho de banda.
Cuando se envía un archivo a un nodo IPFS, el nodo almacena una copia del archivo en su alma-
cenamiento local y crea una clave de hash del contenido, denominada CID (content identifier), que
representa el contenido del archivo. Este hash puede utilizarse para recuperar el archivo desde cual-
quier otro nodo IPFS de la red. El fragmento de código siguiente ilustra el almacenamiento de un
fichero en un nodo IPFS.

1 // La función almacenaFicheroIPFS toma dos argumentos: la dirección del nodo IPFS


2 // (por ejemplo, ’http://localhost:5001’) y el nombre del archivo
3 // (por ejemplo, ’ejemplo.txt’).
4 //
5 // La función crea una instancia de cliente IPFS utilizando la dirección
6 // de nodo pasada como parámetro. Luego utiliza el método ipfs.add
7 // para agregar el archivo a IPFS. El CID (hash identificativo) del archivo
8 // almacenado se muestra en la consola si la operación tiene éxito.
9 //
10 // Un ejemplo de llamada sería:
11 //
12 // almacenaFicheroIPFS(’http://localhost:5001’, ’ejemplo.txt’);
13 //
14 // Utilizamos el módulo ipfs-http-client y el módulo fs para manejar
15 // ficheros. Para instalar ipfs-http-client:
16 //
17 // npm install --save ipfs-http-client
18 //
19 const clienteIPFS = require(’ipfs-http-client’);
20 const fs = require(’fs’);
21
22 async function almacenaFicheroIPFS(dirNodoIPFS, fichero) {
23 // crear una instancia de cliente IPFS. El constructor recibe
24 // la URI del nodo utilizado.
25 const ipfs = clienteIPFS(dirNodoIPFS);
26
27 try {
28 // añade el archivo a IPFS
29 const result = await ipfs.add({

69
30 path: fichero,
31 content: fs.createReadStream(fichero)
32 });
33
34 // saca por pantalla el CID del fichero añadido
35 console.log(’Archivo almacenado en IPFS con CID: ${result.cid.toString()}’);
36 } catch (error) {
37 console.error(’Error al añadir archivo a IPFS: ${error}’);
38 }
39 }

El nodo IPFS también divide el archivo en trozos más pequeños, llamados bloques, y crea un grafo
acíclico dirigido de Merkle (DAG, ver apéndice C) que representa la estructura del archivo. Cada bloque
del DAG de Merkle se identifica con su propio hash, y los hashes de los bloques se utilizan para crear
el hash de la raíz del grafo, que a su vez es el identificador único o CID del archivo. A continuación, el
nodo IPFS transmite el CID del archivo a otros nodos, permitiéndoles descubrir y recuperar el archivo
cuando lo soliciten. El archivo se almacena de forma distribuida en la red IPFS, lo que significa que
pueden almacenarse varias copias del archivo en diferentes nodos, incrementando así la redundancia
y la tolerancia a fallos. Cuando un usuario solicita un archivo por su clave hash (es decir, por su CID),
el cliente IPFS envía una solicitud del archivo a la red IPFS. A continuación, la red IPFS utiliza el CID
para localizar un nodo que tenga una copia del archivo y lo devuelve al cliente IPFS del usuario. A
continuación, el cliente vuelve a ensamblar el archivo a partir de los bloques devueltos por la red y se
lo presenta al usuario.
En resumen, al enviar un archivo a un nodo IPFS se crea un identificador único de contenido para
el archivo y se almacena de forma distribuida en la red IPFS, lo que permite recuperarlo fácilmente
desde cualquier otro nodo de la red. De todos modos, en IPFS también es posible anclar contenidos,
es decir, garantizar que un contenido específico, normalmente un archivo o un conjunto de archivos,
se almacena de forma permanente o semipermanente y está disponible en un nodo de la red IPFS
concreto. Cuando un contenido está anclado (pinned), significa que el nodo retiene una copia de ese
contenido, impidiendo que el recolector de basura de IPFS lo elimine. IPFS dispone de un mecanismo
de recogida de basura (garbage collection) para recuperar espacio de almacenamiento eliminando
el contenido que no se utiliza o al que no se hace referencia. Anclar contenido asegura que no será
enviado a la basura, lo que permite que sea accesible de forma fiable y permanente. Los usuarios
pueden anclar y desanclar contenidos manualmente, según sus preferencias, y algunos nodos IPFS
también admiten el anclado automático o dinámico en función de patrones o políticas de uso. Como el
anclado tiene costes de almacenamiento y ancho de banda asociados, algunos servicios de anclado
pueden cobrar una tasa por prestar dichos servicios de almacenamiento persistente.
IPFS es una potente herramienta para el desarrollo de la Web3, ya que facilita la creación de
una web distribuida y descentralizada, más resistente, rápida y segura que las arquitecturas cliente-
servidor tradicionales. Tiene muchos usos posibles, como crear un método más eficaz y seguro de
compartir archivos de gran tamaño o incluso una versión de Internet resistente a la censura.

8.5. IPFS y las cadenas de bloques: casos de uso

Las cadenas de bloques están diseñadas principalmente para manejar transacciones rápidas y
eficientes en lugar de almacenar grandes volúmenes de datos de manera persistente, por lo que, si
se utilizan como sistemas de archivos, la capacidad de procesamiento y el rendimiento disminuirán
significativamente. En consecuencia, no se plantea almacenar grandes cantidades de información
persistente en una cadena de bloques debido a los costos computacionales, la disminución de la efi-
ciencia y el problema de escalabilidad que ello conlleva. En su lugar, es preferible utilizar sistemas
descentralizados como IPFS, que están diseñados específicamente para almacenar y gestionar ar-

70
chivos de gran tamaño de manera descentralizada, eficiente y escalable. Además, al basarse en el
direccionamiento por contenido, es posible garantizar la inmutabilidad de los datos si así se desea.
Por ello, IPFS y blockchain suelen utilizarse juntos para crear aplicaciones descentralizadas que
aprovechan los puntos fuertes de ambas tecnologías. Puede utilizarse para almacenar grandes can-
tidades de datos, incluidos archivos inmutables, y proporciona una forma de direccionar estos datos
mediante un hash único que puede utilizarse para recuperar los datos desde cualquier nodo de la red.
El anclado permite además disponer de contenidos en un nodo IPFS concreto, mejorando la disponibi-
lidad y el tiempo de acceso. Blockchain, por su parte, permite crear un libro de contabilidad distribuido
que puede utilizarse para almacenar y verificar datos de forma segura e inmutable. Combinando estas
tecnologías, los desarrolladores pueden crear aplicaciones descentralizadas capaces de almacenar
y compartir datos de gran tamaño de forma segura y resistente a la censura. Por ejemplo, una plata-
forma de redes sociales Web3 basada en la cadena de bloques podría utilizar IPFS para almacenar
contenidos generados por los usuarios, como fotos y vídeos, al tiempo que utiliza la cadena de blo-
ques para verificar la autenticidad de los contenidos y proporcionar un método descentralizado de
verificación de la identidad de los usuarios.
Otro caso de uso es la creación de una plataforma descentralizada de intercambio de archivos de
cualquier tipo (imágenes, clips multimedia, aplicaciones informáticas, historiales médicos, . . . ), en la
que IPFS puede utilizarse para almacenar los archivos, mientras que la cadena de bloques se utiliza
para gestionar las transacciones entre usuarios, garantizando la trazabilidad total de dichas transac-
ciones, y en general todas las propiedades asociadas a la tecnología de cadenas de bloques.
IPFS también se utiliza a menudo junto con los NFT como una forma de almacenar el activo digital
o los metadatos asociados al NFT. Al almacenar el activo o los metadatos en IPFS, el NFT se vuelve
descentralizado, inmutable y más seguro. Un modo habitual de utilizar IPFS con NFT consiste en al-
macenar los metadatos en IPFS y, a continuación, crear un NFT que haga referencia al CID de IPFS.
De este modo, cualquiera que posea el NFT puede utilizar el hash para recuperar los metadatos sub-
yacentes desde IPFS, y a partir de los metadatos el propio activo, incluso si el creador original del NFT
ya no está disponible. El activo digital también se puede almacenar en IPFS. Por ejemplo, tal como
indicamos en el apartado 5.4, un artista digital puede crear una obra de arte única y almacenarla en
IPFS, junto con metadatos sobre la obra como el título, el nombre del artista, la fecha de creación, y el
propio CID de la obra de arte. A continuación, podría crear un NFT que hiciera referencia al CID de los
metadatos, que a su vez incluye el CID de la obra, lo que permitiría a posibles compradores verificar
la autenticidad y la propiedad de la obra de arte.
Filecoin es una red de almacenamiento descentralizado basada en el protocolo IPFS que ofrece
servicios de almacenamiento y acceso a datos en la nube sin depender de un proveedor centralizado.
Filecoin dispone de su propia cadena de bloques para garantizar la integridad, seguridad y transparen-
cia del proceso de almacenamiento y reembolso de recursos por parte de los nodos que participan en
la red. En Filecoin, los usuarios pueden almacenar archivos en el sistema utilizando tokens de pago
(FIL) para compensar a los proveedores de almacenamiento que ofrecen espacio en sus dispositivos.
Estos proveedores se encargan de mantener la disponibilidad y persistencia de los datos, garantizan-
do su acceso rápido y seguro para todos los usuarios. La red Filecoin es eficiente, resistente a fallos
y ofrece una alternativa descentralizada al modelo centralizado de servicios de almacenamiento en
la nube como Amazon S3 o Google Cloud Storage. Gracias a su base de código abierto y comunidad
globalmente dispersa, Filecoin promueve el acceso universal a datos y la creación de aplicaciones
descentralizadas para una variedad de escenarios, desde contenido multimedia hasta registros de
propiedad digital.
Sia (Simplified Internet Access) es una plataforma descentralizada de almacenamiento en la nube
que utiliza blockchain y contratos inteligentes para crear un mercado para proveedores y usuarios de
almacenamiento. Los usuarios pueden alquilar espacio de almacenamiento a hosts de la red utilizan-
do Siacoin (SC) como criptomoneda nativa.

71
8.6. Otros sistemas de archivos descentralizados

Además de IPFS y de los sistemas de almacenamiento descentralizado comentados en el aparta-


do anterior, existen varias iniciativas comerciales para explotar el concepto de almacenamiento des-
centralizado, cada una con su propio modelo de negocio y enfoque de almacenamiento distribuido y
de recuperación de datos. Swarm, Storj y Maidsafe estarían entre los sistemas de archivos descen-
tralizados comerciales más destacados.
Swarm es una plataforma de almacenamiento y distribución de contenidos descentralizada desa-
rrollada como parte del ecosistema Ethereum. Permite el alojamiento descentralizado de sitios web
y el almacenamiento distribuido de archivos. Swarm está diseñado para integrarse con Ethereum, lo
que le permite gestionar contenidos dirigidos por aplicaciones basadas en Ethereum.
Storj es un sistema de almacenamiento descentralizado basado en el protocolo IPFS que bus-
ca proporcionar una solución eficiente y segura para el almacenamiento, acceso y compartición de
datos. Utiliza un enfoque diferente a Filecoin, ya que no requieren de proveedores de espacio de alma-
cenamiento dedicados; en cambio, cualquier usuario con una conexión a Internet puede convertirse
en proveedor de almacenamiento y recibir recompensas por ello. Los datos se dividen en bloques o
shards que se distribuyen entre nodos de la red, garantizando así una mayor resistencia a fallos y se-
guridad contra ataques cibernéticos o pérdida de información. La comunicación entre los usuarios y
proveedores de almacenamiento se encripta para proteger la privacidad y el contenido del archivo.
La Red Maidsafe pretende crear una Internet descentralizada y autónoma combinando un siste-
ma descentralizado de almacenamiento de archivos con una red de comunicación entre pares. Está
diseñada para ser autogestionable, autorreparable y resistente a la censura.
Estas soluciones ofrecen una alternativa descentralizada a servicios como Dropbox o Google Dri-
ve, permitiendo un acceso rápido y seguro a datos previamente almacenados en la red sin depender
de proveedores centralizados. Ambos disponen de una comunidad e usuarios dedicada al desarrollo
de herramientas y soluciones descentralizadas para una variedad de escenarios, desde alojamiento
web hasta intercambio de archivos multimedia.

9. Blockchain como servicio (BaaS)

Blockchain como servicio (Blockchain as a Service, BaaS) es un servicio basado en la nube que
proporciona a los clientes una plataforma para desarrollar, desplegar y gestionar sus aplicaciones
blockchain, sin necesidad de configurar y mantener su propia infraestructura de cadena de bloques.
Los proveedores de BaaS ofrecen un entorno de blockchain preconstruido que los clientes pueden
utilizar para crear, probar y desplegar sus propias aplicaciones descentralizadas, a menudo a través
de una interfaz web fácil de usar.
Los proveedores de BaaS suelen ofrecer una gama de protocolos de cadena de bloques entre
los que elegir, incluidas cadenas de bloques públicas como Ethereum o Bitcoin, así como cadenas
de bloques privadas como Hyperledger Fabric o R3 Corda. También proporcionan funciones como
la gestión de nodos, algoritmos de consenso, gestión de identidades y almacenamiento de datos, lo
que facilita que los clientes se centren en desarrollar sus propias dApps lugar de dedicar recursos y
tiempo a la gestión de la infraestructura.
BaaS es cada vez más popular, ya que ofrece varios beneficios a las empresas y organizaciones
que buscan adoptar la tecnología blockchain y en general entrar en la Web 3.0. Estas ventajas incluyen
la reducción de costes, una puesta en producción más rápida, una mayor escalabilidad y una seguri-
dad mejorada. BaaS también permite a las empresas experimentar con la tecnología blockchain antes
de realizar inversiones significativas en su propia infraestructura blockchain.

72
En definitiva, BaaS es una opción atractiva para las empresas que quieren aprovechar las venta-
jas de la tecnología blockchain sin tener que realizar grandes inversiones en el desarrollo y la gestión
de una infraestructura blockchain propia. Entre los actores más relevantes del mercado de BaaS se
encuentra Microsoft con su plataforma Azure. Microsoft Azure ofrece una gama de soluciones block-
chain, incluidas plataformas BaaS para Ethereum, Hyperledger Fabric y Corda. La plataforma ofrece
una serie de herramientas y servicios para desarrolladores, lo que facilita la creación, prueba y des-
pliegue de aplicaciones blockchain. Amazon, con su plataforma AWS, también ofrece una variedad
de servicios de blockchain, incluidas las plataformas BaaS para Ethereum e Hyperledger Fabric. IBM
ofrece su propia gama de soluciones blockchain, incluidas las plataformas BaaS para Hyperledger
Fabric y Corda, mientras que Oracle ofrece una plataforma BaaS llamada Oracle Blockchain para Hy-
perledger Fabric. SAP también se ha sumado a esta tendencia con SAP Blockchain para Hyperledger
Fabric.
Otros actores relevantes en el mercado de BaaS son Huawei, Baidu, Alibaba Cloud y Tencent Cloud,
que ofrecen sus propias plataformas BaaS para diversos protocolos de blockchain.

10. Conclusión

La tecnología blockchain, los contratos inteligentes y las aplicaciones descentralizadas están trans-
formando rápidamente la forma en que interactuamos entre nosotros, trabajamos, hacemos nego-
cios e incluso nos divertimos. La tecnología blockchain ofrece una forma segura y transparente de
almacenar y compartir datos sin necesidad de intermediarios, mientras que los contratos inteligen-
tes permiten automatizar procesos empresariales complejos. Las dApps también están cambiando
la forma en que utilizamos la tecnología, permitiéndonos interactuar entre nosotros de una manera
más descentralizada y democrática.
Para muchos, la generalización del uso de las aplicaciones descentralizadas y la tecnología de
cadenas de bloques supone el nacimiento de la tercera generación de de la World Wide Web, llama-
da Web3 o Web 3.0. Esta nueva web se caracterizaría por basarse en un conjunto de tecnologías y
protocolos que permiten la creación de aplicaciones descentralizadas que pueden ejecutarse sobre
redes blockchain. Estas aplicaciones se construyen normalmente utilizando contratos inteligentes,
que son programas informáticos autoejecutables que pueden automatizar el intercambio de valor e
información entre diferentes partes.
Además de los contratos inteligentes, Web3 también incluye otras tecnologías como el almacena-
miento descentralizado, la gestión de identidades y los protocolos de comunicación descentralizados
como los protocolos P2P. Estas tecnologías permiten crear aplicaciones descentralizadas más segu-
ras, transparentes y fiables que las aplicaciones centralizadas tradicionales.
La Web3 es considerada por muchos como la próxima evolución de Internet, ya que ofrece una
nueva forma de crear aplicaciones e interactuar con ellas, más democrática, descentralizada y abierta.
El objetivo de Web3 es crear un mundo digital más transparente y equitativo, en el que los usuarios
tengan más control sobre sus datos e interacciones en línea.
De todos modos, las tecnologías en las que se basa la Web3 son aún relativamente nuevas y, como
hemos visto, existen varios riesgos asociados a su uso. Las aplicaciones Web3 se construyen sobre
redes blockchain, que generalmente se consideran seguras. Sin embargo, los contratos inteligentes
que alimentan estas aplicaciones todavía pueden ser vulnerables a la piratería informática u otras
amenazas de seguridad, lo que podría resultar en la pérdida de fondos u otros activos. En la misma
línea, las aplicaciones descentralizadas de la Web3 pueden ser complejas y difíciles de construir y
mantener, lo que puede aumentar el riesgo de errores o fallos en el código. Las aplicaciones Web3
se encuentran todavía en las primeras fases de desarrollo y adopción, y existe el riesgo de que no
consigan una adopción o uso generalizados.

73
Por otra parte, el panorama regulatorio para las aplicaciones Web3 aún está evolucionando, y exis-
te el riesgo de que vayan apareciendo normas o leyes que puedan restringir el uso o desarrollo de es-
tas aplicaciones. También existen dudas sobre la interoperabilidad de las distintas propuestas. Existen
muchas redes y protocolos de blockchain diferentes, lo que puede dificultar que las aplicaciones Web3
puedan interaccionar entre sí.
Aunque todavía quedan muchos retos por superar, como la escalabilidad, la interoperabilidad y
la incertidumbre normativa, los beneficios potenciales de estas tecnologías son evidentes. Desde la
reducción del fraude y el aumento de la transparencia hasta la habilitación de nuevos modelos de
negocio y el empoderamiento de las personas, blockchain, los contratos inteligentes y las aplicaciones
descentralizadas tienen el potencial de revolucionar la forma en que vivimos y trabajamos.
A medida que estas tecnologías continúan evolucionando y madurando, es importante que los
desarrolladores, las empresas y los gobiernos se mantengan informados y comprometidos con los
últimos desarrollos. Trabajando juntos, podemos liberar todo el potencial de la cadena de bloques, los
contratos inteligentes y las aplicaciones descentralizadas y crear un futuro más equitativo, seguro y
descentralizado.

10.1. Para saber más

Dada la popularidad que está alcanzando la tecnología blockchain y los rápidos avances en su
desarrollo, podemos encontrar un número importante de publicaciones sobre el tema. A continua-
ción enumeramos algunas de ellas que consideramos interesantes. Estos libros ofrecen una buena
introducción a la tecnología blockchain y sus posibles aplicaciones en diversos sectores, así como un
análisis crítico de sus ventajas y limitaciones.
Mastering Blockchain: Unlocking the Power of Cryptocurrencies, Smart Contracts, and Decentrali-
zed Applications, de Lorne Lantz y Daniel Cawrey (2020), ofrece una introducción completa a la
tecnología blockchain y sus aplicaciones, cubriendo temas como Bitcoin, Ethereum, contratos
inteligentes y aplicaciones descentralizadas.
The Internet of Money, de Andreas M. Antonopoulos (2016), es una recopilación de charlas impar-
tidas por el autor sobre Bitcoin y la tecnología blockchain. Ofrece una introducción accesible al
tema y explora las posibles implicaciones de esta tecnología en nuestros sistemas financieros.
Blockchain Basics: A Non-Technical Introduction in 25 Steps, de Daniel Drescher (2017), ofrece
una introducción no técnica a la tecnología blockchain, explorando los fundamentos de su fun-
cionamiento y sus aplicaciones potenciales en diversos sectores.
Blockchain Revolution: How the Technology Behind Bitcoin is Changing Money, Business, and the
World, de Don Tapscott y Alex Tapscott (2018), explora el impacto potencial de la tecnología
blockchain en diversos sectores, desde las finanzas hasta la sanidad y la administración pública.
The Truth Machine: The Blockchain and the Future of Everything, de Paul Vigna y Michael J. Casey
(2019), explora las posibles implicaciones de la tecnología blockchain en diversos aspectos de
la sociedad, como las finanzas, la identidad y la gobernanza, y ofrece un análisis crítico de sus
posibles beneficios y limitaciones.
Obviamente, también tenemos a nuestra disposición innumerables tutoriales online sobre el tema
con recursos para que cualquiera pueda adquirir un conocimiento más profundo de la tecnología
blockchain y de cómo desarrollar aplicaciones utilizando plataformas de cadenas de bloques. Entre
los más relevantes y asentados están:
Los tutoriales de Solidity en el sitio web de Ethereum. Ethereum es una de las plataformas block-
chain más populares, y Solidity es el lenguaje de programación utilizado para escribir contratos
inteligentes en la red Ethereum. Los tutoriales de Solidity en el sitio web de Ethereum propor-

74
cionan una guía paso a paso para aprender Solidity y desarrollar contratos inteligentes en la red
Ethereum.
IBM Blockchain 101. Este tutorial de IBM ofrece una introducción a la tecnología blockchain,
cubriendo temas como las redes descentralizadas, los contratos inteligentes y los mecanismos
de consenso. El tutorial también incluye un ejercicio práctico que permite a los alumnos crear
una red blockchain sencilla utilizando Hyperledger Fabric.
Fundamentos de Blockchain en Coursera. Este curso, ofrecido por la Universidad de Buffalo,
proporciona una introducción a la tecnología blockchain, cubriendo temas como la historia de
blockchain, Bitcoin, Ethereum y contratos inteligentes. El curso incluye videoconferencias y ejer-
cicios prácticos de programación.
Documentación sobre Hyperledger Fabric. Hyperledger Fabric es una plataforma blockchain que
se utiliza ampliamente en aplicaciones empresariales. La documentación de Hyperledger Fabric
proporciona una guía completa para que los desarrolladores aprendan a desarrollar e implemen-
tar aplicaciones blockchain utilizando esta plataforma.
ConsenSys Academy ofrece una serie de cursos en línea sobre tecnología blockchain, que abar-
can temas como Ethereum, Solidity y el desarrollo de aplicaciones descentralizadas. Los cursos
están diseñados tanto para principiantes como para desarrolladores experimentados, e incluyen
tanto clases en vídeo como ejercicios prácticos.

75
76
Referencias
Abdelhady, Mohamed Ahmed (2019). Hands-On Smart Contract Development with Hyperledger Fabric.
Packt Publishing.
Adaś, Patryk (2021). Mastering Web3.js. Packt Publishing.
Aggarwal, Shubhani y Neeraj Kumar (2021). “Chapter Twenty - Attacks on blockchain”. En: The Block-
chain Technology for Secure and Smart Applications across Industry Verticals. Editado por Shubha-
ni Aggarwal, Neeraj Kumar y Pethuru Raj. Volumen 121. Advances in Computers. Elsevier, pági-
nas 399-410. DOI: https://doi.org/10.1016/bs.adcom.2020.08.020. URL: https://www.
sciencedirect.com/science/article/pii/S0065245820300759.
Antonopoulos, Andreas M. (2016). The Internet of Money. CreateSpace Independent Publishing Plat-
form.
Barger, Artem et al. (2021). “A Byzantine Fault-Tolerant Consensus Library for Hyperledger Fabric”.
En: 2021 IEEE International Conference on Blockchain and Cryptocurrency (ICBC), páginas 1-9. DOI:
10.1109/ICBC51069.2021.9461099.
Benet, Juan (2014). “IPFS - Content Addressed, Versioned, P2P File System”. En: arXiv preprint ar-
Xiv:1407.3561.
Blaut, Gabriel, Xuyang Ma y Katinka Wolter (2023). “Exploring Randomness in Blockchains”. En: 2023
IEEE International Conference on Blockchain and Cryptocurrency (ICBC), páginas 1-5. DOI: 10.1109/
ICBC56567.2023.10174962.
Buterin, Vitalik (2014). Ethereum: A Next-Generation Smart Contract and Decentralized Application Plat-
form. ethereum.org.
Buterin, Vitalik y Nathan Schneider (2022). Proof of Stake: The Making of Ethereum and the Philosophy
of Blockchains. Seven Stories Press.
Carl, G. et al. (2006). “Denial-of-service attack-detection techniques”. En: IEEE Internet Computing 10.1,
páginas 82-89. DOI: 10.1109/MIC.2006.5.
Castro, Miguel y Barbara Liskov (nov. de 2002). “Practical Byzantine Fault Tolerance and Proactive
Recovery”. En: ACM Trans. Comput. Syst. 20.4, páginas 398-461. ISSN: 0734-2071. DOI: 10.1145/
571637.571640. URL: https://doi.org/10.1145/571637.571640.
Chain, Binance (2020). Binance Smart Chain: A Parallel Binance Chain to Enable Smart Contracts. Bi-
nance Chain.
Chinnathambi, Kirupa (2018). Learning React: A Hands-On Guide to Building Web Applications Using
React and Redux. Addison-Wesley Professional.
Chittoda, J. (2019a). Mastering Blockchain Programming with Solidity: Write production-ready smart
contracts for Ethereum blockchain with Solidity. Packt Publishing. ISBN: 9781839218637. URL: https:
//books.google.es/books?id=wWOnDwAAQBAJ.
Chittoda, Jitendra (2019b). Mastering Blockchain Development with Solidity and Truffle. Packt Publishing.
Deirmentzoglou, Evangelos, Georgios Papakyriakopoulos y Constantinos Patsakis (2019). “A Survey
on Long-Range Attacks for Proof of Stake Protocols”. En: IEEE Access 7, páginas 28712-28725.
DOI: 10.1109/ACCESS.2019.2901858.
Delgado-von-Eitzen, Christian, Luis Anido-Rifón y Manuel J. Fernández-Iglesias (2021a). “Application of
Blockchain in Education: GDPR-Compliant and Scalable Certification and Verification of Academic
Information”. En: Applied Sciences 11.10. ISSN: 2076-3417. DOI: 10.3390/app11104537. URL: https:
//www.mdpi.com/2076-3417/11/10/4537.
— (2021b). “Blockchain Applications in Education: A Systematic Literature Review”. En: Applied Scien-
ces 11.24. ISSN: 2076-3417. DOI: 10.3390/app112411811. URL: https://www.mdpi.com/2076-
3417/11/24/11811.
Drescher, Daniel (2017). Blockchain Basics: A Non-Technical Introduction in 25 Steps. Apress.
FATF (2012-2023). International Standards on Combating Money Laundering and the Financing of Te-
rrorism & Proliferation. Paris, France: FATF.
Hoskinson, Charles (2017). Why we are Building Cardano. INPUT | OUTPUT.

77
Infante, Roberto (2021). Building Ethereum DApps: Decentralized Applications on the Ethereum Block-
chain with Solidity and Hardhat. Apress.
Islam, Nazrul et al. (2023). “Is BlockChain Mining Profitable in the Long Run?” En: IEEE Transactions on
Engineering Management 70.2, páginas 386-399. DOI: 10.1109/TEM.2020.3045774.
Kalinin, Mikhail y Danny Ryan (2021). Supplant DIFFICULTY opcode with PREVRANDAO Expose beacon
chain randomness in the EVM by supplanting DIFFICULTY opcode semantics. Ethereum Improve-
ment Proposals EIP-4399. Ethereum.
Klabnik, Steve y Carol Nichols (2019). The Rust Programming Language. No Starch Press.
Lamport, Leslie, Robert Shostak y Marshall Pease (jul. de 1982). “The Byzantine Generals Problem”. En:
ACM Trans. Program. Lang. Syst. 4.3, páginas 382-401. ISSN: 0164-0925. DOI: 10.1145/357172.
357176. URL: https://doi.org/10.1145/357172.357176.
Lantz, Lorne y Daniel Cawrey (2020). Mastering Blockchain: Unlocking the Power of Cryptocurrencies,
Smart Contracts, and Decentralized Applications. O’Reilly Media.
Ma, Guangkai, Chunpeng Ge y Lu Zhou (2020). “Achieving reliable timestamp in the bitcoin platform”.
En: Peer-to-Peer Networking and Applications 13.6, páginas 2251-2259. DOI: 10 . 1007 / s12083 -
020-00905-6.
Mahmoodi, Sina (2020). Vyper Smart Contract Programming. Packt Publishing.
Merkle, Ralph C. (1990). “A Certified Digital Signature”. En: Advances in Cryptology — CRYPTO’ 89 Pro-
ceedings. Editado por Gilles Brassard. New York, NY: Springer New York, páginas 218-238. ISBN:
978-0-387-34805-6.
Miller, Andrew (2019). “Permissioned and permissionless blockchains”. En: Blockchain for distributed
systems security. Editado por Sachin Shetty, Charles A. Kamhoua y Laurent L. Njilla. IEEE Press,
páginas 193-204.
Nakamoto, Satoshi (2008). Bitcoin: A Peer-to-Peer Electronic Cash System. www.bitcoin.org.
Passaglia, Andrea (2017). Vue.js 2 Cookbook. Packt Publishing.
Schreiber, Flora Rheta (1973). Sybil: The Classic True Story of a Woman Possessed by Sixteen Separate
Personalities. Grand Central Publishing.
Schwarzmüller, Maximilian (2018). Material-UI: React components for faster and easier web develop-
ment. Packt Publishing Ltd.
— (2021). Angular 12: The Complete Guide. Packt Publishing.
Shanaev, Savva et al. (2019). “Cryptocurrency Value and 51 % Attacks: Evidence from Event Studies”.
En: The Journal of Alternative Investments 22.3, páginas 65-77. ISSN: 1520-3255. DOI: 10 . 3905 /
jai.2019.1.081. eprint: https://jai.pm-research.com/content/22/3/65.full.pdf. URL:
https://jai.pm-research.com/content/22/3/65.
Singh, Niharika (2020). Ganache: Personal Blockchain for Ethereum Development. Packt Publishing.
Snider, Myles, Kyle Samani y Tushar Jain (2018). “Delegated Proof of Stake: Features and Tradeoffs”.
En: Multicoin Capital March 2, 2018.
Spurlock, Jake (2021). Bootstrap 5: Building Responsive Layouts with HTML and CSS. Packt Publishing.
Tapscott, Don y Alex Tapscott (2018). Blockchain Revolution: How the Technology Behind Bitcoin is
Changing Money, Business, and the World. Portfolio.
Towaha, Syed Omar Faruk (2019). Learn Ethereum DApp Development with Remix. Packt Publishing.
Vigna, Paul y Michael J. Casey (2019). The Truth Machine: The Blockchain and the Future of Everything.
Picador.
Wang, Wenbo et al. (2019). “A Survey on Consensus Mechanisms and Mining Strategy Management
in Blockchain Networks”. En: IEEE Access 7, páginas 22328-22370. DOI: 10.1109/ACCESS.2019.
2896108.
Wood, Gavin (2016). Polkadot: Vision for a Heterogeneous Multi-chain Framework. Polkadot.
Yakovenko, Anatoly (2017). Solana: A new architecture for a high performance blockchain. Solana.
Yves-Christian, Adja Elloh et al. (2018). “Total Eclipse: How To Completely Isolate a Bitcoin Peer”. En:
2018 Third International Conference on Security of Smart Cities, Industrial Control System and Com-
munications (SSIC), páginas 1-7. DOI: 10.1109/SSIC.2018.8556790.

78
Zilliqa Team (2019). Scilla: A Smart Contract Intermediate Level Language. Zilliqa Research Pte. Ltd.

79
80
Apéndices

A. Criptografía de clave pública

La criptografía de clave pública, también conocida como criptografía asimétrica, es una técnica
criptográfica que utiliza un par de claves, una pública y otra privada, para cifrar y descifrar datos. La
clave pública se utiliza para cifrar los datos, mientras que la privada se utiliza para descifrarlos. En la
criptografía de clave pública, la clave pública puede distribuirse libremente, mientras que el propietario
mantiene en secreto la clave privada. Cuando un usuario quiere enviar datos cifrados a otra persona,
utiliza la clave pública del destinatario para cifrar los datos. El destinatario utiliza entonces su clave
privada para descifrar los datos.
La criptografía de clave pública se considera más segura que la criptografía simétrica, en la que
se utiliza la misma clave para cifrar y descifrar, porque aunque se intercepte la clave pública, los datos
no pueden descifrarse sin la clave privada.
La criptografía de clave pública se utiliza en una amplia gama de aplicaciones, como la comunica-
ción segura, las firmas digitales y el acceso seguro a sitios web y servicios en línea. Es un componente
fundamental de muchas tecnologías modernas, como SSL/TLS, PGP y SSH. Todos los entornos de
programación habituales, incluidos los utilizados para desarrollar la tecnología blockchain, disponen
de bibliotecas criptográficas que entre otras muchas funciones proporcionan elementos para firmar,
cifrar y descifrar mensajes utilizando criptografía de clase pública. Por ejemplo, el código JavaScript
siguiente ilustra el uso de dicha biblioteca.

1 // Ejemplo de cifrado y descifrado mediante criptografía de clave


2 // pública (PKI). Utilizamos el módulo crypto de Node.js.
3 //
4 const crypto = require(’crypto’);
5
6 // Función para cifrar un mensaje utilizando una clave pública
7 function cifra(message, publicKey) {
8
9 // Creamos un búfer a partir del mensaje para pasárselo
10 // a la función de cifrado de la librería crypto.
11 const buffer = Buffer.from(message, ’utf8’);
12
13 // Ciframos el mensaje. El método publicEncrypt cifra
14 // un buffer de bytes con la clave pública pasada como
15 // parámetro. Devuelve un buffer con el contenido original
16 // cifrado.
17 const encrypted = crypto.publicEncrypt(publicKey, buffer);
18
19 // Convertimos el buffer devuelto por la función en una
20 // cadena de caracteres y lo devolvemos
21 return encrypted.toString(’base64’);
22 }
23
24 // Función para descifrar un mensaje utilizando la clave privada
25 function descifra(encryptedMessage, privateKey) {
26
27 // Creamos un búfer a partir del mensaje para pasárselo
28 // a la función de descifrado de la librería crypto.
29 const buffer = Buffer.from(encryptedMessage, ’base64’);
30

81
31 // Desciframos el mensaje
32 const decrypted = crypto.privateDecrypt(privateKey, buffer);
33
34 // convertimos el buffer devuelto por la función en una
35 // cadena de caracteres y lo devolvemos
36 return decrypted.toString(’utf8’);
37 }

El segmento de código siguiente ilustra el uso de las funciones cifra y descifra anteriores.

1 // Ejemplo de uso de las funciones cifra y descifra definidas


2 // anteriormente
3 //
4 // Generamos un nuevo par de claves pública/privada con la
5 // librería crypto. Utilizamos el algoritmo RSA, con claves
6 // de 2048 bits
7 const { publicKey, privateKey } = crypto.generateKeyPairSync(’rsa’, {
8 modulusLength: 2048,
9 });
10
11 // Cifra un mensaje utilizando la clave pública generada
12 const message = ’Este es mi mensaje secreto’;
13 const encryptedMessage = cifra(message, publicKey);
14 console.log(‘Mensaje cifrado: ${encryptedMessage}‘);
15
16 // Descifra el mensaje cifrado utilizando la clave privada generada
17 // El mensaje final será el mismo que el del principio.
18 const decryptedMessage = descifra(encryptedMessage, privateKey);
19 console.log(‘Mensaje en claro: ${decryptedMessage}‘);

La criptografía de clave pública también se puede utilizar para firmar contenidos digitales y con
ello garantizar la autoría y la no repudiación de un contenido. Básicamente, para firmar un contenido
digital, se calcula una clave hash del mismo (ver apéndice B más adelante) y se dicha clave cifra con
la clave privada. El resultado se puede utilizar como firma, es decir, como garantía de que el contenido
original fue firmado por el propietario de la clave privada. Para comprobarlo, un receptor del docu-
mento original puede calcular la clave hash del mismo y descifrar la firma con la clave pública del
firmante. Si ambos valores coinciden, podemos asegurar que el documento original fue firmado por
el propietario de la clave privada, ya que es la única persona que la conoce.
El ejemplo siguiente presenta una función en JavaScript para firmar un fichero.

1 // Ejemplo de firma mediante criptografía de clave


2 // pública (PKI). Definición de una función de firma.
3 //
4 // Utilizamos el módulo crypto y el módulo fs
5 // de Node.js.
6 //
7 const fs = require(’fs’);
8 const crypto = require(’crypto’);
9
10 // La función toma dos parámetros: la referencia a un fichero que
11 // almacena la clave privada y la referencia al fichero que
12 // queremos firmar. Como resultado, devuelve la firma.
13 function signFileWithPKI(privateKeyPath, dataPath) {
14 // leemos la clave privada del fichero
15 const privateKey = fs.readFileSync(privateKeyPath, ’utf8’);
16 // leemos el contenido a firmar
17 const data = fs.readFileSync(dataPath, ’utf8’);
18
19 // Creamos un objeto de firma utilizando un hash SHA-256.

82
20 const sign = crypto.createSign(’SHA256’);
21 // Añadimos los datos a firmar al objeto.
22 sign.write(data);
23 // Cerramos el objeto.
24 sign.end();
25
26 // Firmamos el objeto con la clave privafa
27 // y devolvemos una cadena codificada en base64
28 const signature = sign.sign(privateKey, ’base64’);
29 return signature;
30 }

Y el extracto de código siguiente ilustra la firma de un fichero y la verificación de dicha firma.

1 // Ejemplo de firmado de un fichero y de comprobación


2 // de la firma usando PKI.
3 // Utilizamos el módulo crypto y el módulo fs de Node.js.
4 //
5 const fs = require(’fs’);
6 const crypto = require(’crypto’);
7
8 // Generamos un par de claves pública-privada aptas para firmar
9 const { privateKey, publicKey } = crypto.generateKeyPairSync(’rsa’, {
10 modulusLength: 2048,
11 publicKeyEncoding: { type: ’spki’, format: ’pem’ },
12 privateKeyEncoding: { type: ’pkcs8’, format: ’pem’ },
13 });
14
15 // Guardamos las claves pública y privada en sendos ficheros
16 fs.writeFileSync(’private_key.pem’, privateKey);
17 fs.writeFileSync(’public_key.pem’, publicKey);
18
19 // Llamamos a la función anterior para firmar un fichero
20 // llamado ’data.txt’
21 const signature = signFileWithPKI(’private_key.pem’, ’data.txt’);
22
23 // A continuación vamos a verificar la firma.
24 // Creamos un objeto de verificación SHA-256 (el mismo
25 // protocolo que utilizamos en la firma)
26 const verify = crypto.createVerify(’SHA256’);
27 // almacenamos el fichero en el objeto
28 verify.write(fs.readFileSync(’data.txt’, ’utf8’));
29 // y lo cerramos
30 verify.end();
31
32 //
33 // Utilizamos la clave pública para verificar la firma.
34 // La codificación utilizada es la misma que utilizamos para codificar
35 // la firma.
36 const isVerified = verify.verify(publicKey, signature, ’base64’);
37
38 // Imprimimos el resultado en la consola (true o false)
39 console.log(’Firma verificada:’, isVerified);

B. Funciones hash

Una función hash es una función matemática que toma datos de entrada de cualquier tamaño y
produce una salida de tamaño fijo llamada hash. La función hash genera una huella digital única de

83
los datos de entrada, que suele ser una cadena de caracteres o bytes. Las funciones hash se utilizan
habitualmente en criptografía para garantizar la integridad y seguridad de los datos. Comparando el
hash de los datos originales con el hash de los datos recibidos, se puede determinar si los datos han
sido alterados o manipulados en tránsito.
Las funciones hash están diseñadas para ser funciones unidireccionales, lo que significa que es
inviable desde el punto de vista computacional determinar los datos de entrada originales a partir de
la salida hash. Esta propiedad de las funciones hash las hace útiles en muchas aplicaciones, como las
firmas digitales, el almacenamiento de contraseñas y la validación de datos. Las funciones hash tam-
bién se utilizan en la tecnología blockchain para crear un libro de transacciones seguro y a prueba de
manipulaciones. Cada bloque de la cadena de bloques contiene un hash del bloque anterior, creando
una cadena de bloques que no puede alterarse sin invalidar toda la cadena.
Algunas funciones hash comunes son SHA-256 y MD5, aunque la elección de la función hash de-
pende de la aplicación específica y del nivel de seguridad requerido. El segmento de código JavaScript
siguiente ilustra el cálculo de una clave de hash SHA-256 utilizando el módulo Crypto de Node.js.

1 //
2 // Ejemplo de generación de un hash SHA-256 de una
3 // cadena de caracteres
4 //
5 // Utilizamos la librería crypto de Node.js
6 //
7 const crypto = require(’crypto’);
8 //
9 // la función sha256 toma una cadena de texto como argumento
10 // y devuelve el valor SHA-256 de esa cadena como un
11 // valor hexadecimal.
12 //
13 // La función utiliza el módulo crypto incorporado en Node.js,
14 // que proporciona una variedad de funciones criptográficas,
15 // incluyendo la función de hash SHA-256.
16 function sha256(text) {
17
18 // Creamos una instancia de un objeto hash SHA-256
19 const hash = crypto.createHash(’sha256’);
20
21 // Actualiza mos el el hash almacenado en el objeto hash
22 // con la cadena de texto pasada como parámetro
23 hash.update(text);
24
25 // Devolvemos el valor de la clave de hash (digest) almacenada
26 // en el objeto como resultado.
27 return hash.digest(’hex’);
28 }

Para calcular una clave SHA-256 de una imagen almacenada en un fichero utilizaríamos el frag-
mento de código siguiente:

1 const fs = require(’fs’);
2
3 const nomFichero = ’Imagen.png’;
4
5 // Lleemos el fichero
6 const fileContents = fs.readFileSync(nomFichero);
7
8 // Invocamos nuestra función sha256
9 const sha256Value = sha256(fileContents);
10
11 console.log(‘La clave SHA-256 del fichero ${nomFichero} es: ${sha256Value}‘);

84
C. Árboles de Merkle

Un árbol de Merkle, también conocido como árbol hash, es una estructura de datos utilizada en
informática y criptografía para verificar eficazmente la integridad de grandes conjuntos de datos. Debe
su nombre a su inventor, Ralph Merkle (Merkle, 1990).
Un árbol de Merkle es un árbol binario en el que cada nodo que no es hoja está etiquetado con el
hash de las etiquetas de sus nodos hijos. Cada nodo hoja del árbol representa un único dato, y el valor
hash de cada nodo hoja se calcula utilizando una función hash criptográfica, como SHA-256. El árbol
se construye mediante el hash recursivo de pares de nodos hijos, hasta que se produce un único hash
raíz.
El hash raíz de un árbol de Merkle también se conoce como raíz de Merkle y sirve como resumen
de todo el conjunto de datos. Al comparar la raíz Merkle de un conjunto de datos recibidos con una
raíz Merkle acordada previamente, un receptor puede verificar que el conjunto de datos no ha sido
manipulado ni modificado. Para ello, se solicitan al remitente los hashes de un subconjunto de nodos
hoja y sus correspondientes nodos padre, y se utilizan dichos hashes para verificar la autenticidad de
la raíz de Merkle.

Figura 8: Ejemplo de árbol de Merkle de cuatro transacciones. La raíz del árbol es lo que se almacenaría en un bloque para
validar las transacciones.

Los árboles de Merkle se utilizan habitualmente en la tecnología blockchain para verificar eficaz-
mente la integridad de las transacciones de un bloque. Utilizando un árbol de Merkle, los nodos de la
red blockchain pueden verificar rápidamente que un bloque de transacciones no ha sido manipulado
ni modificado. Además, los árboles de Merkle pueden ayudar a reducir la cantidad de datos que deben
transmitirse y almacenarse en la red blockchain, haciéndola más eficiente y escalable.
El fragmento de código siguiente ilustra el cálculo de un árbol de Merkle a partir de una lista de
transacciones.

1 //
2 // Este script utiliza el módulo crypto integrado en Node.js para calcular
3 // hashes SHA-256 de cada transacción. Luego construye el
4 // árbol Merkle de abajo hacia arriba combinando hashes adyacentes y
5 // combinándolos hasta que se obtiene un único hash raíz. La función
6 // calculaRaizMerkle() toma una matriz de transacciones, representadas mediante
7 // cadenas de caracteres, y devuelve el hash del nodo raíz del árbol de Merkle.
8 //
9 // Para probar el script, definimos un array de transacciones de ejemplo

85
10 // y llamamos a la función calculaRaizMerkle() con ellas. El hash raíz
11 // se muestra en la consola.
12 //
13 const crypto = require(’crypto’);
14
15 function calculaRaizMerkle(transacciones) {
16 // Convierte cada cadena de transacción en un hash
17 const transactionHashes = transacciones.map((transaccion) => {
18 return crypto.createHash(’sha256’).update(transaccion).digest(’hex’);
19 });
20
21 // Construir el árbol de Merkle de abajo hacia arriba
22 let nivel = transactionHashes;
23 while (nivel.length > 1) {
24 const siguienteNivel = [];
25 for (let i = 0; i < nivel.length; i += 2) {
26 const izquierda = nivel[i];
27 const derecha = i + 1 < nivel.length ? nivel[i + 1] : ’’;
28 const combinado =
29 crypto.createHash(’sha256’).update(izquierda + derecha).digest(’hex’);
30 siguienteNivel.push(combinado);
31 }
32 nivel = siguienteNivel;
33 }
34
35 // Devuelve la raíz del árbol Merkle
36 return nivel[0];
37 }
38
39 // Ejemplo de uso
40 const transacciones =
41 [’transacción 1’, ’transacción 2’, ’transacción 3’, ’transacción 4’];
42 const raizMerkle = calculaRaizMerkle(transacciones);
43 console.log(’Raíz Merkle:’, raizMerkle);

Un grafo dirigido acíclico de Merkle o DAG (Directed Acyclic Graph) de Merkle, es una estructura
de datos más general en la que cada nodo puede tener múltiples nodos hijos, y cada nodo representa
el hash de sus nodos hijos. La estructura es acíclica dirigida, lo que significa que no hay ciclos en el
grafo. Los DAG de Merkle se utilizan en IPFS para representar la estructura de datos de direcciones
de contenido utilizada para almacenar y recuperar datos.
Una diferencia clave entre ambas estructuras es que los árboles de Merkle suelen ser árboles
binarios, en los que cada nodo tiene dos nodos hijos, mientras que los DAG de Merkle pueden tener
cualquier número de nodos hijos. Además, los DAG de Merkle son más flexibles y pueden utilizarse
para representar estructuras de datos más complejas que los árboles de Merkle. Otra diferencia es
que, en un árbol de Merkle, todos los nodos hoja están en el mismo nivel y suelen estar dispuestos en
un árbol binario equilibrado. En un DAG de Merkle, los nodos hoja pueden estar en cualquier nivel y la
estructura puede ser más compleja y variada.
En general, tanto los árboles de Merkle como los DAG de Merkle son estructuras de datos impor-
tantes que se utilizan para verificar la integridad de grandes conjuntos de datos mediante la creación
de un resumen basado en hash de los datos. La elección entre ambos depende del caso de uso es-
pecífico y de la complejidad de la estructura de datos que se represente.

86
D. Prueba de participación en Ethereum

Los validadores implementan la prueba de participación (proof-of-stake) en Ethereum de acuerdo


con los pasos siguientes:
1. Aportación de Ether. Los validadores deben aportar al menos 32 ETH para participar en el pro-
ceso de consenso. Este Ether se bloquea en un contrato de depósito, y se utiliza para incentivar
a los validadores a actuar con honestidad.
2. Propuesta de bloques. Los validadores se seleccionan aleatoriamente para proponer nuevos
bloques a la red. Un bloque propuesto contiene una lista de transacciones que el validador ha
verificado.
3. Validación de bloques. Otros validadores verifican el bloque propuesto y votan si lo aceptan. Si
más del 50 % de los validadores votan a favor, el bloque se añade a la cadena de bloques.
4. Pago de recompensas. Los validadores son recompensados con Ether por proponer y validar
bloques. También se les penaliza por proponer o validar bloques no válidos.
Este proceso se repite continuamente, añadiéndose nuevos bloques a la cadena de bloques cada
12 segundos (en octube de 2023).
Los validadores se seleccionan para proponer bloques mediante un proceso llamado Randao (Ran-
dom Number Authority Oracle), consistente en la generación de números aleatorios criptográficamen-
te seguros que garantizan que todos los validadores tengan las mismas posibilidades de ser selec-
cionados. Randao funciona mediante la recopilación de contribuciones de múltiples participantes que
bloquean una cantidad de ether en un contrato inteligente. Luego, estos participantes envían valores
hash de sus contribuciones y, finalmente, revelan la información original. El valor hash agregado de
todas las contribuciones se utiliza para generar un número aleatorio.
Cada validador genera un número aleatorio utilizando su clave secreta y luego publica un hash de
ese número. A continuación, todos los hash se combinan para crear un único valor. En consecuencia,
el valor de Randao así calculado es característico del bloque validado.
Randao está diseñado para ser resistente a la manipulación por parte de validadores individuales.
Esto se debe a que incluso si un pequeño número de validadores intenta manipular el valor de Ran-
dao, sus esfuerzos se verán contrarrestados por los números aleatorios generados por los demás
validadores.
Uno de los usos clave del número Randao en Ethereum PoS es seleccionar aleatoriamente a los
validadores que son elegibles para crear nuevos bloques o proponer bloques. El Randao se utiliza
para asignar a los validadores responsabilidades específicas, como proponer bloques o dar fe de la
validez de los bloques. La aleatoriedad que proporciona Randao ayuda a garantizar que la selección
de validadores sea impredecible y reduce el riesgo de colusión o centralización, así como la equidad
y la seguridad en la red.
Además de para seleccionar validadores que propongan y validen bloques, también se utiliza para
generar recompensas por bloque. Cuanto más Ether haya apostado un validador, más probabilidades
tendrá de ser seleccionado para proponer y validar bloques, y mayor será su parte de la recompensa
del bloque.
Cuando un validador propone un bloque, también incluye una firma para demostrar que el validador
ha apostado la cantidad necesaria de Ether y que ha verificado el bloque. Otros validadores verifican
el bloque propuesto comprobando la firma y asegurándose de que todas las transacciones del bloque
son válidas. Una vez que un bloque ha sido verificado y aceptado por la mayoría de los validadores,
se añade a la cadena de bloques.
Se recompensa a los validadores con Ether por proponer y validar bloques con una cantidad de
Ether proporcional a la participación del validador, y del mismo modo se penaliza a los validadores

87
si proponen o validan bloques inválidos con una penalización proporcional a la gravedad de la infrac-
ción. El Randao también puede utilizarse para determinar las penalizaciones, contribuyendo a que las
condiciones de penalización no sean predecibles de antemano.
Este proceso se desarrolla en una cadena paralela a la cadena principal llamada Cadena Centinela
o Beacon Chain. Esta cadena es responsable de implementar el consenso de prueba de participación,
coordinar a los validadores y mejorar la escalabilidad y la eficiencia en la cadena de bloques de Ethe-
reum, ya que la Beacon Chain es la base de las cadenas de fragmentos, que dividirán la red Ethereum
en bloques más pequeños y manejables. La Beacon Chain se lanzó en diciembre de 2020, y se fusionó
con la cadena de prueba de trabajo original de Ethereum en septiembre de 2022.
Randao en Ethereum es un intento de garantizar la aleatoriedad en un entorno donde las transac-
ciones y la ejecución de contratos inteligentes son deterministas y transparentes. Sin embargo, es
importante recordar que, en algunos casos, la aleatoriedad de Randao puede verse comprometida si
la mayoría de los participantes actúan de manera maliciosa. Por lo tanto, siempre es esencial conside-
rar la seguridad y las implicaciones al utilizar sistemas de generación de números aleatorios basados
en Randao en aplicaciones descentralizadas.

E. Redes peer-to-peer

Una red entre iguales o red peer-to-peer (P2P) es un tipo de red descentralizada en la que todos
los participantes tienen los mismos privilegios y responsabilidades. En una red P2P, cada nodo (o
participante) de la red puede actuar como cliente y como servidor, y puede comunicarse e intercambiar
datos directamente con otros nodos sin necesidad de intermediarios. En una red P2P no hay una
autoridad central o un servidor que controle la red, sino que cada nodo contribuye a la funcionalidad
de la red compartiendo sus recursos, como su potencia de cálculo, capacidad de almacenamiento o
ancho de banda. Esto permite que las redes P2P sean más tolerantes a fallos, ya que no dependen
de un único punto de fallo y pueden seguir funcionando aunque algunos nodos de la red fallen o se
desconecten.
Las redes peer-to-peer generalmente implementan alguna forma de red virtual superpuesta sobre
la topología de Internet, donde los nodos de la superposición se corresponden con un subconjunto de
los nodos de la red física. Los datos se siguen intercambiando directamente a través de la red Inter-
net subyacente, pero en la capa de aplicación los pares pueden comunicarse entre sí directamente,
a través de los enlaces lógicos de superposición, cada uno de los cuales corresponde a una ruta a
través de la red física subyacente. Los enlaces superpuestos se utilizan para la indexación y el descu-
brimiento de pares, y hacen que el sistema P2P sea independiente de la topología de la red física. En
función de cómo se vinculan los nodos entre sí dentro de la red superpuesta, y de cómo se indexan y
localizan los recursos, podemos clasificar las redes como no estructuradas o estructuradas, o como
un híbrido entre ambas.
Las redes peer-to-peer no estructuradas no imponen una estructura particular en la red superpues-
ta, sino que están formadas por nodos que forman conexiones al azar entre sí. Dado que no hay una
estructura impuesta globalmente, las redes no estructuradas son fáciles de construir y permiten opti-
mizar los recursos de manera local en diferentes regiones de la superposición. Además, dado que el
papel de todos los pares en la red es el mismo, las redes no estructuradas son muy robustas cuando
un gran número de pares se unen y abandonan la red con frecuencia.
Sin embargo, las principales limitaciones de las redes no estructuradas surgen precisamente de
esta falta de estructura. En concreto, cuando un usuario quiere encontrar una información concreta
en la red de pares, la consulta de búsqueda se debe diseminar a través de toda la red para encontrar
tantos pares como sea posible que compartan esa información. Esta diseminación por toda la red
de pares provoca una cantidad muy elevada de tráfico de señalización en la red, utiliza más recursos

88
Figura 9: Red entre pares o red peer-to-peer (P2P). Cuando un nodo se una a la red, establece conexiones con alguno de los
nodos existentes. El protocolo de la red garantiza que todos los nodos participantes pueden compartir información entre
ellos.

de cálculo al requerir que cada par procese todas las consultas de búsqueda, y no garantiza que los
datos se acaben localizando siempre. Además, como no hay correlación entre un par y el contenido
que ese par gestiona, no hay garantía de que la diseminación de la búsqueda encuentre un usuario
que tenga los datos deseados. Es probable que los contenidos populares estén disponibles en varios
pares y que cualquier par que los busque acabe encontrándolos, pero si un usuario busca datos poco
frecuentes, compartidos sólo por unos pocos usuarios, es muy poco probable que la búsqueda tenga
éxito.
En las redes estructuradas peer-to-peer, la superposición de nodos se organiza en una topología
específica, y el protocolo garantiza que cualquier nodo pueda buscar eficientemente determinado ar-
chivo o recurso compartido en la red, incluso si el recurso es extremadamente poco frecuente. El tipo
más común de redes P2P estructuradas implementa una tabla de hash distribuida en la que se asig-
na cada archivo o recurso a un peer concreto. Esto permite a los usuarios buscar recursos en la red
utilizando dicha tabla. En otras palabras, las relaciones entre usuarios y recursos asignados se alma-
cenan en una tabla compartida, y cualquier usuario de la red P2P puede recuperar eficientemente el
recurso asociado a un usuario determinado.
De todos modos, para enrutar el tráfico de forma eficiente a través de la red, los nodos de una
superposición estructurada deben mantener listas de vecinos que satisfagan criterios específicos.
Esto los hace menos robustos en redes con un alto índice de rotación, es decir, con un gran número
de usuarios que se unen y abandonan la red con frecuencia.
Las redes P2P pueden utilizarse para diversas aplicaciones, como el intercambio de archivos, la
mensajería o las llamadas de voz y vídeo. Un ejemplo popular de red P2P es BitTorrent, una red de
intercambio de archivos en la que los usuarios comparten archivos directamente entre sí, en lugar de
descargarlos de un servidor central. Las redes P2P también resuelven muchos problemas a los que
se enfrentan diversos sectores como las instituciones públicas, las entidades financieras, los merca-
dos de capitales, las compañías de seguros, las cadenas de suministro, la mensajería instantánea,
la comunicación de voz, la transmisión de medios, la colaboración, la ciencia y la investigación, y la
computación de alto rendimiento, por nombrar sólo algunos.
Últimamente, las redes peer-to-peer han experimentado un resurgir más allá del intercambio de
recursos multimedia: las criptomonedas basadas en cadenas de bloques. Por ejemplo, la criptomo-
neda Bitcoin es en definitiva una red peer-to-peer construida sobre la propia Internet. Está gestionada
y controlada por todos los pares que aceptan participar. Todos los nodos están conectados en una
topología plana, lo que significa que no hay jerarquía, servicios centralizados, o cualquier cosa que im-

89
plique una autoridad central gracias al modelo descentralizado de las redes peer-to-peer. Una red des-
centralizada presenta aspectos valiosos que resultaron fundamentales para la consolidación de estas
criptomonedas. Para empezar, en general son tecnologías robustas, gratuitas y de acceso abierto, de
manera que cualquiera pueda unirse a ellas y desarrollar nuevos contenidos y aplicaciones. Además
son seguras e inmutables, y son abiertas y transparentes al tiempo que proporcionan anonimato.

90
Glosario
acuñado
Proceso de creación de nuevos tokens, especialmente tokens no fungibles (NFT). El término
también se utiliza para referirse al proceso de creación de nuevas unidades de una criptomone-
da.
algoritmo hash seguro (SHA)
Algoritmo criptográfico utilizado para generar valores hash únicos y garantizar la integridad y
autenticidad de los datos en la cadena de bloques.
almacenamiento en frío
La práctica de mantener criptomonedas fuera del mundo digital, en un entorno seguro, para
protegerlas contra la piratería o el robo.
altcoin
Cualquier criptomoneda distinta de Bitcoin.
altura
Posición de un bloque en la red blockchain, determinada por el número de bloques que se han
añadido a la blockchain desde el bloque génesis.
aplicación descentralizada (dApp)
Aplicación que se ejecuta en una red blockchain y no está controlada por ninguna autoridad
central.
árbol de Merkle
Estructura de datos utilizada en la cadena de bloques para organizar y resumir las transacciones
o datos de un bloque, basándose en una serie de cálculos hash.
ataque de adelanto
Tipo de ataque en el que un atacante tiene conocimiento avanzado de una transacción pendiente
y puede manipular el orden de las transacciones en su beneficio.
ataque de eclipsado
Tipo de ataque en el que un atacante toma el control de la conexión de una víctima a la red para
manipular su visión de la red.
ataque de largo alcance
Tipo de ataque en el que un atacante se hace con el control de todo o gran parte del historial de
una blockchain, lo que le permite reescribir transacciones.
ataque de reentrada
Tipo de ataque en el que un atacante explota un contrato inteligente que hace múltiples llamadas
a otros contratos, permitiéndole ejecutar su propio código múltiples veces y drenar los fondos
del contrato.
ataque de Sybil
Tipo de ataque en el que un atacante crea múltiples identidades falsas en una red con el fin de
obtener el control sobre ella.
ataque del 51 %
Tipo de ataque a una red blockchain en el que una sola entidad o grupo de entidades controla
más del 50 % de los recursos de la red (por ejemplo, potencia de cálculo, nodos, criptomone-
da. . . ). Con este control mayoritario, el atacante puede potencialmente manipular la red impi-
diendo confirmaciones de transacciones, cometiendo doble gasto o reescribiendo el historial
de transacciones.
autoridad de certificación
Tercero de confianza que emite y verifica los certificados digitales utilizados para la comunica-
ción segura.

91
Bitcoin
La primera y más conocida criptomoneda, creada en 2009. Su símbolo es BTC.
blockchain
Tecnología descentralizada y distribuida que permite transacciones seguras y transparentes en-
tre pares.
bloque
Conjunto de transacciones verificadas que se añaden a la cadena de bloques.
bloque canónico
Bloque más reciente que es aceptado como válido por todos los nodos de la red.
bloque génesis
Primer bloque de la cadena de bloques, creado por el fundador o fundadores de la red y que
contiene una transacción especial que genera el suministro inicial de la criptomoneda.

cartera
Aplicación que permite a los usuarios almacenar, gestionar y transferir criptomonedas en una
red blockchain.
circuito integrado de aplicación específica (ASIC)
Chip informático especializado, diseñado específicamente para minar criptomonedas.
clave pública
Clave criptográfica utilizada para cifrar datos y verificar firmas digitales en la cadena de bloques,
a menudo asociada con un monedero o dirección específica.
coin
Unidad de criptomoneda.
coinbase
La primera transacción en un bloque que crea nueva criptomoneda y recompensa al minero que
resolvió el bloque.
colisión hash
Situación en la que dos entradas diferentes producen el mismo valor hash, lo que es muy raro y
se considera un riesgo de seguridad en la cadena de bloques.
confirmación
El proceso de verificar una transacción en la cadena de bloques para asegurar que es válida y
está registrada en el libro mayor.
consenso
Acuerdo general entre todos los nodos de la cadena de bloques sobre el estado del libro mayor
y la validez de las transacciones.
contrato inteligente
Código autoejecutable que aplica automáticamente los términos de un contrato entre partes en
una red blockchain.
criptografía
La práctica de usar algoritmos matemáticos y protocolos para asegurar y verificar transacciones
en la cadena de bloques.
criptomoneda
Moneda digital o virtual que utiliza criptografía para la seguridad y opera independientemente
de un banco central.
código abierto
Tipo de software que está disponible libremente y puede ser modificado y distribuido por cual-
quiera, a menudo utilizado para proyectos blockchain para fomentar la colaboración y la inno-
vación.

DeFi
Sistemas financieros construidos sobre tecnología blockchain que operan de manera descen-
tralizada sin intermediarios tradicionales.

92
denegación de servicio (DoS)
Tipo de ataque en el que un atacante inunda una red o servidor con tráfico, haciendo que no esté
disponible para los usuarios legítimos.
desbordamiento de entero
Condición que ocurre cuando el resultado de una operación aritmética excede el tamaño máxi-
mo que puede ser representado por un tipo entero.
descentralización
El principio de distribuir el control y la autoridad sobre una red blockchain entre muchos nodos
diferentes, en lugar de depender de una autoridad central.
DEX
Intercambio descentralizado. Plataforma de intercambio que opera sin una entidad central y
permite a los usuarios comerciar directamente entre sí.
dificultad
Medida de los recursos necesarios para minar un nuevo bloque en la cadena de bloques. Se
ajusta periódicamente para mantener una tasa constante de producción de bloques.
dirección
Identificador único en una blockchain que representa la ubicación de una cartera, NFT o contrato
inteligente.
doble gasto
Acto de intentar gastar la misma criptomoneda más de una vez, lo que se impide en la cadena
de bloques mediante consenso y protocolos criptográficos.

entorno de desarrollo integrado (IDE)


Aplicación que proporciona amplias facilidades a los programadores informáticos para el desa-
rrollo de software.
entre pares (P2P)
Tipo de arquitectura de red en la que los nodos se comunican y realizan transacciones directa-
mente entre sí, sin necesidad de intermediarios o autoridades centrales, a menudo utilizada en
redes blockchain.
escalabilidad
Capacidad de la red blockchain para manejar un creciente volumen de transacciones y nuevos
usuarios sin comprometer el rendimiento o la seguridad. Un reto clave para los desarrolladores
de blockchain.
Ether
Criptomoneda nativa de la cadena de bloques Ethereum, utilizada para pagar las tasas de las
transacciones y la ejecución de contratos inteligentes. Su símbolo es ETH.
Ethereum
Plataforma blockchain descentralizada que permite la creación de contratos inteligentes y apli-
caciones descentralizadas (dApps).
exchange
Plataforma donde los usuarios pueden comprar, vender e intercambiar criptomonedas con otros
usuarios o con la propia plataforma.

finanzas descentralizadas (DeFi)


Uso de la tecnología blockchain para crear aplicaciones financieras descentralizadas abiertas,
transparentes y accesibles a todo el mundo.
firma digital
Esquema matemático utilizado para verificar la autenticidad e integridad de un mensaje, tran-
sacción o documento en la cadena de bloques.

93
fork
División en la red blockchain que crea dos versiones separadas del libro mayor. Esto puede de-
berse a condiciones de carrera en la creación de bloques, diferencias en las reglas de consenso
o actualizaciones del protocolo.

gas
Unidad de medida utilizada para calcular el coste de ejecución de una transacción o contrato
inteligente en la blockchain de Ethereum.
generales bizantinos
Término utilizado para describir un escenario en el que un grupo de generales debe coordinar
un ataque, pero algunos de ellos pueden ser traidores que enviarán mensajes falsos.
gobernanza
Proceso mediante el cual los titulares de tokens participan en la toma de decisiones sobre el
desarrollo y cambios en el protocolo.
grafo acíclico dirigido (DAG)
Estructura de datos utilizada en la tecnología blockchain y en los sistemas de archivos descen-
tralizados para organizar y resumir conjuntos de datos.
gráfico acíclico dirigido de Merkle (DAG)
DAG utilizado en IPFS en el que cada nodo está etiquetado con el hash de sus datos y el hash
de sus hijos, formando una estructura similar al árbol de Merkle.

halving
Reducción programada de la recompensa por minar un nuevo bloque en la cadena de bloques,
que se produce periódicamente para mantener una oferta finita y deflacionaria de la criptomo-
neda.
hard fork
División permanente en la red blockchain que crea una nueva versión del libro mayor, a menudo
causada por cambios fundamentales en las reglas de consenso o actualizaciones de protocolo.
hash
Función matemática que toma una entrada (datos) y produce una salida de tamaño fijo (valor o
clave hash), utilizada para identificar datos de forma única en la blockchain.
holdear
Estrategia consistente en mantener una criptomoneda durante un largo periodo de tiempo, nor-
malmente con la esperanza de obtener importantes ganancias en un futuro.
Hyperledger
Plataforma blockchain de código abierto mantenida por la Fundación Linux, diseñada para uso
empresarial y centrada en la privacidad, la escalabilidad y la interoperabilidad.

infraestructura de clave pública (PKI)


Sistema que utiliza claves privadas y públicas para asegurar y autenticar transacciones y datos
en la cadena de bloques, a menudo utilizado para la gestión de la identidad digital.
inmutabilidad
Propiedad de una blockchain de que una vez que una transacción o dato se ha añadido la misma,
no puede ser modificado o borrado, asegurando la integridad y autenticidad del libro mayor.

libro mayor
Sistema de registro que rastrea las transacciones y los datos en la cadena de bloques, mante-
nido por los nodos de la red.
liquidez
Facilidad con la que un activo DeFi puede ser comprado o vendido en el mercado sin afectar
significativamente su precio.

94
mainnet
Versión viva y operativa de la red blockchain que está abierta al público y se utiliza para transac-
ciones reales y almacenamiento de datos.
manipulaciones, a prueba de
Propiedad de un sistema que deja claro cuándo se ha intentado modificarlo o manipularlo.
manipulaciones, resistente a
Propiedad de un sistema que impide la modificación o manipulación no autorizada.
MetaMask
Extensión del navegador y aplicación móvil que permite a los usuarios interactuar con aplica-
ciones descentralizadas (dApps) en la cadena de bloques Ethereum y otras redes compatibles.
También sirve como monedero para esas redes.
metaverso
Universo o mundo virtual, normalmente creado y gestionado por una plataforma basada en
blockchain. El metaverso es un espacio virtual compartido en el que los usuarios pueden in-
teractuar entre sí, explorar entornos digitales y participar en diversas actividades como juegos,
socialización y comercio. El metaverso se concibe a menudo como una versión inmersiva y
descentralizada de Internet, con su propia economía y sistemas de gobernanza.
minero
Participante en la red blockchain que utiliza potencia computacional para validar transacciones,
crear nuevos bloques y obtener recompensas en forma de criptomoneda.
minería
Proceso de utilizar potencia computacional para validar transacciones, crear nuevos bloques y
ganar recompensas en forma de criptomoneda en una red blockchain.
minería de liquidez
En el contexto DeFi, se refiere a la obtención de tokens mediante la participación en protocolos
que distribuyen recompensas.
multifirma
Tipo de firma digital que requiere que varias partes firmen una transacción o autoricen una trans-
ferencia de fondos en la cadena de bloques, utilizada con fines de seguridad y gestión de riesgos.
máquina de estados
Modelo matemático utilizado para describir el comportamiento de un sistema, como una red
blockchain.
máquina virtual
Entorno de software que emula un sistema informático y permite la ejecución de contratos in-
teligentes en una red blockchain.

nodo
Participante en la red blockchain que valida las transacciones, mantiene una copia del libro de
contabilidad y se comunica con otros nodos para garantizar la seguridad e integridad de la red.
nodo completo
Nodo en la red blockchain que almacena una copia completa del libro mayor y participa en la
verificación y validación de transacciones.
nodo ligero
Nodo en la red blockchain que almacena sólo una copia parcial del libro mayor, confiando en los
nodos completos para la verificación y validación de las transacciones.
nonce
Número incremental o aleatorio generado por un minero durante el proceso de minado de un
bloque en la blockchain, utilizado para crear un valor hash único que cumpla el objetivo de difi-
cultad.

95
organización autónoma descentralizada (DAO)
Una organización dirigida por código informático en una red blockchain, en lugar de por gestores
o líderes humanos.
oráculo
Servicio o mecanismo de terceros que proporciona datos del mundo real a la blockchain, a me-
nudo utilizado para facilitar la ejecución de contratos inteligentes y la toma de decisiones en la
blockchain.

pool de transacciones
Conjunto de transacciones no confirmadas a la espera de ser procesadas y añadidas a una red
blockchain.
precio del gas
La cantidad de Ether necesaria para pagar cada unidad de gas utilizada en una transacción o
ejecución de contrato inteligente en la blockchain de Ethereum.
privada (blockchain)
Tipo de red blockchain en la que el acceso y la participación están restringidos a participantes o
entidades autorizados, a menudo utilizada para aplicaciones empresariales y gubernamentales.
profundidad
Número de bloques que se añadieron a la cadena de bloques después de una transacción con-
creta, utilizado para medir el nivel de confirmación o seguridad de las transacciones.
protección contra repeticiones
Mecanismo para evitar que actores maliciosos reproduzcan o dupliquen transacciones válidas
en la cadena de bloques, a menudo utilizado en hard forks y actualizaciones de la red.
prueba de autoridad (PoA)
Mecanismo de consenso en el que los validadores se seleccionan para validar transacciones
basándose en su identidad o reputación, a menudo utilizado en blockchains privadas o empre-
sariales.
prueba de cobertura (PoC)
Mecanismo de consenso en el que los validadores demuestran que tienen la cobertura de se-
guro necesaria para respaldar sus transacciones o actividades en la blockchain, utilizado en las
industrias financiera y de seguros.
prueba de espacio y tiempo (PoSaT)
Mecanismo de consenso en el que los validadores demuestran su compromiso de espacio de
almacenamiento y recursos de red, utilizado en la cadena de bloques Chia..
prueba de importancia (PoI)
Mecanismo de consenso en el que los validadores demuestran su importancia y contribución
a la red basándose en su historial de transacciones y otros factores, utilizado en la cadena de
bloques NEM.
prueba de liquidez (PoL)
Mecanismo de consenso en el que los validadores demuestran su liquidez y capacidad para
aportar fondos o activos suficientes a la red, utilizado en mercados digitales descentralizados y
fondos de liquidez.
prueba de Merkle
Prueba criptográfica que permite a un nodo de la red blockchain verificar la inclusión de una
transacción o datos en un bloque sin tener que descargar y validar el bloque completo.
prueba de participación (PoS)
Mecanismo de consenso en el que los validadores avalan con criptomoneda su capacidad para
validar transacciones, utilizada en Ethereum 2.0 y otras cadenas de bloques.
prueba de participación delegada (DPoS)
Algoritmo de consenso utilizado en algunas redes blockchain, donde los poseedores de crip-
tomoneda pueden votar para seleccionar un conjunto de delegados que son responsables de
verificar las transacciones y añadir nuevos bloques a la cadena.

96
prueba de peso (PoW)
Mecanismo de consenso en el que los validadores demuestran su reputación e importancia en
la red en función de su contribución y actividad, utilizado en la cadena de bloques Algorand.
prueba de trabajo (PoW)
Mecanismo de consenso en el que los validadores resuelven complejos problemas matemáti-
cos para validar transacciones y obtener recompensas, utilizado en Bitcoin y otras cadenas de
bloques.
préstamo instantáneo
Un tipo de préstamo DeFi que permite a los usuarios pedir prestado y devolver una cantidad de
fondos en una sola transacción.
pérdida impermanente
La pérdida de valor que los proveedores de liquidez pueden experimentar debido a la volatilidad
en los precios de los activos.
pública (blockchain)
Tipo de red blockchain en la que el acceso y la participación están abiertos a cualquiera, sin
necesidad de aprobación o autenticación, a menudo utilizada para aplicaciones de criptomone-
das.

raíz de Merkle
Hash del nodo principal de un árbol de Merkle, que resume todas las transacciones o datos de
un bloque y se incluye en la cabecera del bloque.
recompensa
Incentivo o compensación que obtienen los validadores por su contribución a la red, a menudo
en forma de criptomoneda o tokens.
red
Conjunto de nodos y participantes conectados a la cadena de bloques, que juntos validan las
transacciones, mantienen el libro mayor y garantizan la seguridad e integridad de la red.
reversión
La reversión de uno o más bloques en la cadena. Esto puede ocurrir debido a un error de softwa-
re, un ataque a la red, u otros eventos inesperados que causan una divergencia entre el estado
real de la cadena de bloques y lo que la mayoría de los nodos creen. Las reversiones pueden
tener graves consecuencias para la integridad y fiabilidad de la cadena de bloques.

security token
Token criptográfico que representa un activo, como acciones de una empresa, y está sujeto a la
normativa sobre valores.
sin confianza
Propiedad de una red blockchain que permite a las partes realizar transacciones entre sí sin
depender de la confianza en una autoridad central o intermediario.
Solidity
Lenguaje de programación utilizado para escribir contratos inteligentes en la blockchain Ethe-
reum.
stablecoin
Token estable. Tipo de criptomoneda diseñada para mantener un valor estable frente a una
moneda fiduciaria u otro activo (por ejemplo, el euro o el dólar estadounidense).
subdesbordamiento de enteros
Condición que ocurre cuando el resultado de una operación aritmética es menor que el tamaño
mínimo que puede ser representado por un tipo entero.

tabla de hash distribuida (DHT)


Sistema descentralizado para almacenar y recuperar pares clave-valor. En una DHT, los nodos
se organizan en una red P2P, y cada nodo es responsable de almacenar y servir un subconjunto
de claves. Cuando un nodo necesita recuperar un valor para una clave dada, utiliza una función

97
hash para determinar qué nodo es responsable de esa clave y, a continuación, envía una solicitud
a ese nodo.
Tangle
Tecnología de libro mayor distribuido utilizada por la red IOTA que utiliza un grafo acíclico dirigido
(directed acyclic graph, DAG) en lugar de una cadena de bloques..
tarifa de transacción
Tasa pagada por el remitente de una transacción para incentivar a los participantes de la red a
procesar y validar la transacción.
tasa de hash
Velocidad a la que un minero puede realizar cálculos hash en el proceso de minería de cripto-
moneda en la cadena de bloques.
testnet
Red blockchain utilizada para pruebas y desarrollo, separada de la red blockchain principal.
token
Unidad de valor que se crea y gestiona en una red blockchain (NFT, criptomoneda. . . .
token no fungible (NFT)
Tipo de activo digital en la blockchain que es único y no puede ser intercambiado por otros
tokens o activos uno por el otro, a menudo utilizado para coleccionables, juegos y arte.
tokenización
Proceso de conversión de un activo físico o digital en un token en una red blockchain.
tolerancia a fallos bizantinos (BFT)
Capacidad de un sistema de seguir funcionando aunque algunos de sus componentes fallen
o se comporten de forma inesperada. También, un algoritmo de consenso que es tolerante a
fallos y seguro contra un cierto número de nodos bizantinos (es decir, maliciosos).
tolerancia práctica a fallos bizantinos (PBFT)
Algoritmo de consenso que permite a una red distribuida de nodos ponerse de acuerdo sobre
el estado de un sistema, incluso si algunos nodos fallan o se comportan maliciosamente. Una
variación más eficiente de la tolerancia a fallos bizantinos en la que los nodos se turnan para
crear y validar bloques.
transacción
Transferencia de valor entre dos partes en una red de cadena de bloques.

unidad de procesamiento gráfico (GPU)


Chip informático especializado diseñado para el procesamiento eficiente y de alta velocidad de
gráficos y otros datos complejos, a menudo utilizado en la minería de criptomoneda.

web3
Web 3.0, la próxima generación de Internet, que se concibe como una red descentralizada y
distribuida de aplicaciones y servicios que utilizan la tecnología blockchain y otros protocolos
descentralizados.
wei
La unidad más pequeña de Ether (ETH), la criptomoneda utilizada en la blockchain de Ethereum.
1 Ether equivale a 1018 wei. Esta unidad se utiliza para representar cantidades muy pequeñas de
Ether. Por ejemplo, si el precio del gas para una transacción es de 20 gwei, significa que el coste
de ejecutar esa transacción es de 20 × 106 wei o 0,00000002 ETH.

yield farming
Minería de liquidez. Estrategia que implica proporcionar liquidez a protocolos DeFi a cambio de
recompensas, como tokens o intereses.

98

View publication stats

También podría gustarte