Si quieres hacer arbitraje relacionado con DEX (como arbitraje entre cadenas, DeFi o entre DEX y CEX), comprender a fondo los protocolos de las cadenas es un conocimiento imprescindible. Esta serie de artículos empezará con el clásico Bitcoin y explicará, de forma gradual y clara, los protocolos de las principales cadenas.

Cuando transfieres dinero a alguien desde la aplicación de un banco, el resultado más evidente es que cambian los saldos de ambas partes. Lo que lo hace posible es el libro contable que mantiene el banco: quién pagó cuánto y quién recibió cuánto. Bitcoin también busca llevar las cuentas; la dificultad es que no tiene un banco.

En este escenario, podemos empezar con una pregunta más sencilla: ¿qué problemas debe resolver un sistema contable? ¿Cómo los resuelven los bancos? Si prescindimos de los bancos, ¿qué problemas aún se pueden resolver y cuáles quedan bloqueados? La blockchain está diseñada precisamente para resolver estos últimos. Una vez claros los conceptos, construiremos una Toy Blockchain con pseudocódigo para comprender a fondo los mecanismos fundamentales de Bitcoin.

El texto completo sigue este orden:

Los cinco problemas que debe resolver el libro mayor

Libro mayor centralizado: delegar el problema en una institución de confianza

Libro mayor descentralizado: el orden de las transacciones es el obstáculo

Blockchain: lograr que todos los nodos acuerden un mismo historial

Construyamos una Toy BlockChain con pseudocódigo

Implementación real de Bitcoin: firmas y direcciones, UTXO, árbol de Merkle, bloques candidatos, prueba de trabajo, propagación P2P, gestión de bifurcaciones, SPV y riesgo de las confirmaciones

De extremo a extremo: unir con un diagrama de secuencia y pseudocódigo todo el proceso de gastar un UTXO

Los cinco problemas que debe resolver el libro mayor

Dejemos por un momento las criptomonedas. Unos amigos suelen adelantarse dinero para pagar las comidas y, en vez de transferirse dinero cada vez, podrían llevar un libro mayor compartido, anotar cada pago y saldar las cuentas a fin de mes. Aquí recomendamos un vídeo educativo de 3B1B: 3Blue1Brown: Cómo funciona Bitcoin

#1 Alice paga a Bob 20

#2 Bob paga a Carol 40

#3 Carol paga a Alice 30

El registro solo ocupa unas líneas, pero en cuanto cualquiera puede escribir en él, empiezan los problemas.

Los dos primeros problemas se limitan a una sola transacción; el problema del orden exige comparar varias transacciones. El problema de la inmutabilidad tiene que ver con el tiempo: ¿seguirá considerándose válido mañana el historial confirmado hoy? El problema de la emisión determina cómo cambia el importe total registrado en el libro mayor.

El tercer problema es especialmente difícil para las monedas digitales. Un billete de papel no puede entregarse a dos personas al mismo tiempo, pero un registro digital puede copiarse casi sin coste y enviarse por separado a dos personas. Gastar el mismo dinero dos veces se llama doble gasto (double spending). Al explicar el protocolo de Bitcoin, Michael Nielsen lo considera, junto con la falsificación, uno de los dos primeros problemas que hay que superar para «usar información como dinero». How the Bitcoin protocol actually works

Libro mayor centralizado: delegar el problema en una institución de confianza

Los bancos mantienen un único libro mayor oficial y procesan todas las transferencias.

Este sistema es muy eficiente y resuelve casi de paso el problema del orden: hay un solo libro mayor y una sola entidad que lleva las cuentas, así que ella decide qué va antes y qué va después.

El precio es la confianza. Todo el mundo debe confiar en que el banco lleva las cuentas correctamente, que su sistema no se cae y que sus empleados no cometen fraude. El banco también puede congelar cuentas, incluso a petición del gobierno. Apuntes de Rutgers: Bitcoin. En la introducción de su artículo, Satoshi Nakamoto escribió que las instituciones financieras no pueden evitar mediar en las disputas, por lo que las transacciones pueden revertirse. El coste de esa mediación aumenta las comisiones, y los comerciantes deben pedir más información a sus clientes para protegerse del fraude. Libro blanco de Bitcoin

Los primeros sistemas de dinero digital también siguieron este camino: establecieron una entidad emisora de confianza que comprobaba si cada transacción implicaba un doble gasto y, después de cada operación, recibía las monedas para cambiarlas por otras nuevas. Según el artículo, la suerte de todo el sistema monetario queda en manos de la empresa que gestiona la entidad emisora; todas las transacciones deben pasar por ella, igual que en un banco. Libro blanco de Bitcoin

Así que la pregunta pasa a ser: ¿podemos prescindir de esta autoridad central?

Libro mayor descentralizado: alcanzar un consenso sobre el orden de las transacciones es difícil

La solución más directa es eliminar el libro mayor central y hacer que cada participante conserve una copia completa. Cuando alguien quiera pagar, transmite la transacción; todos la comprueban por su cuenta y la anotan en su propio libro mayor. 3Blue1Brown: Cómo funciona Bitcoin

En Bitcoin, los ordenadores que ejecutan el software de Bitcoin y participan en la comunicación de la red se llaman nodos. Entre ellos, los nodos completos comprueban el contenido del libro mayor conforme a todas las reglas y mantienen el estado del libro mayor que consideran válido. Cuando un nodo recibe datos nuevos, los comprueba y los reenvía a sus vecinos, de modo que los registros se propagan por la red salto a salto. Bitcoin.org: Cómo funciona Bitcoin

Sin una autoridad central, volvamos a los cinco problemas mencionados al principio.

La autorización sigue teniendo solución. Los bancos verifican la identidad con contraseñas; los libros mayores descentralizados, con firmas digitales. Cada persona tiene un par de claves: guarda en privado la clave privada, que sirve para firmar, y hace pública la clave pública, con la que cualquiera puede verificar la firma. La firma depende tanto de la clave privada como del contenido firmado; si se traslada a otra transacción, no supera la verificación. Así que no hace falta un banco: cada nodo puede determinar por sí solo si el pagador autorizó un pago. Sin embargo, si se vuelve a enviar exactamente la misma transacción firmada, la firma sigue siendo válida. Por eso, la transacción también necesita información única que permita distinguirla de las demás. El modelo UTXO de Bitcoin resuelve este problema de paso; lo veremos más adelante.

Los saldos también tienen solución, a costa de conservar todo el historial. Sin un banco que lleve la cuenta de tu saldo, los nodos reproducen todas las transacciones desde el primer registro y calculan por sí mismos cuánto dinero tiene cada persona. Para validar una transacción nueva, necesitan conocer todo el historial anterior. 3Blue1Brown: Cómo funciona Bitcoin. Esto también significa que poseer bitcoins consiste en que el libro mayor registre ciertos importes y en que tú tengas las claves privadas necesarias para gastarlos.

El orden es el obstáculo. Supongamos que Alice solo tiene una cantidad de dinero, pero firma dos transacciones: tx1 paga a Bob y tx2 paga a Carol. Envía tx1 a un lado de la red y tx2 al otro. El nodo 1 recibe primero tx1; la firma y el saldo son válidos, así que la registra. Después recibe tx2, descubre que el dinero ya se gastó y la rechaza. Al nodo 2 le ocurre justo lo contrario.

Cada nodo ha aplicado las reglas rigurosamente, pero el resultado son dos versiones del libro mayor. Las firmas solo demuestran que Alice autorizó ambas transacciones; la comprobación del saldo solo puede realizarse siguiendo un orden determinado. Ninguna de las dos indica cuál ocurrió primero. Los retrasos de la red hacen que los nodos vean los mensajes en órdenes distintos, y Alice incluso puede amplificar deliberadamente esas diferencias.

El artículo plantea el problema sin rodeos: para confirmar que una transacción no tiene una transacción conflictiva anterior, la única manera es conocer todas las transacciones. Sin una parte de confianza, las transacciones deben difundirse públicamente, y los participantes también necesitan un mecanismo para acordar un mismo historial de su orden. Libro blanco de Bitcoin

Votar tampoco funciona. Una idea natural sería que votaran los nodos y que se diera por primera la transacción que la mayoría dice haber recibido antes. El problema es que crear identidades en la red prácticamente no cuesta nada. Alice puede crear mil millones de identidades falsas y decirles por separado a Bob y a Carol: «La mayoría ya ha confirmado tu transacción». How the Bitcoin protocol actually works. El artículo también señala que, si se cuenta «un voto por dirección IP», cualquiera que pueda asignar muchas direcciones IP puede manipular el resultado. Libro blanco de Bitcoin. El poder de voto debe estar vinculado a algún recurso escaso difícil de falsificar.

La inmutabilidad y la emisión también se quedan sin fundamento. Cada persona tiene una copia del libro mayor; cualquiera puede modificar la suya y afirmar que es la verdadera. Sin auditores, hay que lograr que la manipulación del historial pueda detectarse técnicamente y resulte costosa económicamente. Sin un banco central, las reglas de emisión de dinero nuevo deben incorporarse a un protocolo que todos los nodos ejecuten en común.

Blockchain: lograr que todos los nodos acuerden un mismo historial

El problema se reduce a una pregunta: ¿cómo pueden un grupo de nodos que desconfían unos de otros, pueden falsificar sus identidades y reciben los mensajes en órdenes distintos, ponerse de acuerdo sobre el orden de las transacciones? La respuesta de Bitcoin puede dividirse en cuatro pasos. 3Blue1Brown: Cómo funciona Bitcoin; Libro blanco de Bitcoin

Primer paso: ordenar por lotes, no transacción por transacción. En vez de llegar a un acuerdo sobre cada transacción por separado, se agrupan varias en un bloque. Quien propone el bloque decide el orden dentro de él; la red solo tiene que acordar cuál será el siguiente bloque. La hora de llegada deja de determinar el orden: este depende del bloque en que esté la transacción y de su posición dentro del bloque.

Segundo paso: enlazar los bloques mediante hashes. Un hash es un resumen de longitud fija calculado a partir de unos datos: los mismos datos siempre producen el mismo resumen, pero un pequeño cambio en el contenido produce uno casi completamente distinto. Puede entenderse como la huella digital de los datos. Cada bloque contiene el hash del bloque anterior. Si seguimos estas referencias hacia atrás, llegamos al primer bloque: el bloque génesis. Esta estructura de datos formada por referencias entre bloques es la cadena de bloques (blockchain).

Si alguien modifica el pago en A, cambia el hash de A y deja de coincidir con el hash antiguo guardado en B. Si también cambia la referencia en B, el hash de B volverá a cambiar y afectará a C, y así sucesivamente. La cadena de hashes permite detectar manipulaciones. A la inversa, aceptar un bloque implica aceptar todo el historial anterior, porque su hash ya fija indirectamente cada bloque precedente. Estructura de datos de la cadena de bloques

Tercer paso: encarecer la propuesta de bloques. La cadena de hashes solo permite detectar modificaciones, no impedirlas: cualquiera puede cambiar los datos y volver a calcular todos los hashes posteriores a un coste ínfimo. Por eso, Bitcoin exige que cada bloque incluya una prueba de trabajo (Proof of Work, PoW): hay que encontrar un número que haga que el hash del bloque cumpla una condición difícil de alcanzar, por ejemplo, que sus primeros 30 bits sean todos 0. El resultado de un hash no se puede predecir; no queda otra que probar valores uno por uno. La probabilidad de acertar en un intento es de 1 entre 2³⁰, aproximadamente una entre mil millones. En cambio, verificarlo solo requiere calcular un hash. 3Blue1Brown: Cómo funciona Bitcoin

Este paso resuelve dos cosas a la vez. Primero, quién propone el siguiente bloque: todos los que quieran calcular lo intentan simultáneamente y quien lo consigue primero obtiene el derecho a proponerlo. Es como un sorteo ponderado por capacidad de cálculo; crear más identidades falsas no aumenta las probabilidades de ganar. El artículo lo llama «un CPU, un voto». Segundo, el coste de reescribir el historial: modificar un bloque obliga a rehacer la prueba de trabajo de ese bloque y de todos los posteriores. Libro blanco de Bitcoin

Cuarto paso: en caso de conflicto, seguir la cadena con más trabajo acumulado. Si dos mineros encuentran un bloque casi al mismo tiempo, la red tendrá temporalmente dos ramas. La regla es seguir, entre todas las cadenas válidas, la que tenga más trabajo acumulado; si la dificultad no cambia, será la cadena más larga. Los bloques nuevos se añaden a una de las ramas, que toma la delantera, y los demás nodos cambian a ella. Si un atacante quiere sustituirla por otro historial, tendrá que lograr que su rama supere a la cadena actual en trabajo acumulado. Con menos de la mitad de la capacidad de cálculo, solo puede confiar en la suerte; cuanto más atrás quede, menores serán sus probabilidades.

Queda una pregunta: ¿por qué alguien querría gastar electricidad en estos cálculos? La primera transacción de cada bloque puede otorgar al creador del bloque una recompensa creada de la nada, además de las comisiones de las transacciones incluidas en él. Esto también resuelve el problema de la emisión: las monedas nuevas entran en circulación mediante recompensas por bloque, al ritmo establecido por el protocolo, sin necesidad de una entidad emisora. Los participantes que ensamblan bloques y buscan pruebas de trabajo se llaman mineros. Libro blanco de Bitcoin

Volvamos al doble gasto de Alice. tx1 y tx2 se propagan por la red y cada minero elige entre ellas. Si un minero incluye tx1 en un bloque y encuentra primero la prueba de trabajo, los demás nodos validan el bloque y descubren que el dinero de Alice ya se gastó; tx2 pasa a ser inválida. Si aparecen casi al mismo tiempo dos bloques, uno con tx1 y otro con tx2, los bloques posteriores decidirán cuál de las dos ramas prevalece.

Cuando el bloque que contiene el pago se añade a la cadena, el pago recibe una confirmación; cada bloque posterior suma otra. Si Bob espera a que se añadan varios bloques después del que contiene tx1, la probabilidad de que se revoque ese pago ya es muy baja. A eso se refiere «esperar confirmaciones»; en la última sección calcularemos la probabilidad concreta.

Construyamos una Toy BlockChain con pseudocódigo

Empecemos por un libro mayor centralizado. Con un único responsable de llevar las cuentas, una transferencia solo requiere unas pocas líneas:

balance = Map # saldos oficiales en la base de datos del banco

log = [] # historial que conserva el propio banco

function transfer(from, to, amount, credential):

require authenticate(from, credential) # autorización: consultar la base de contraseñas del banco

require balance[from] >= amount # saldo: el estado oficial lo determina el banco

balance[from] -= amount

balance[to] += amount

log.append({from, to, amount}) # inmutabilidad: confiar en que el banco no altere el historial

# Orden: el banco ejecuta todas las llamadas en serie; la segunda transacción conflictiva se rechaza por falta de saldo

Cada línea depende del banco: authenticate consulta su base de contraseñas, el banco determina el balance, la ejecución en serie depende de su sistema y la fiabilidad de log depende de que el banco sea honesto. Si eliminamos el banco, hay que sustituir una por una todas estas garantías implícitas.

El siguiente Toy Model conserva los saldos de las cuentas, calcula el hash del bloque entero y representa la dificultad mediante el número de ceros iniciales. H representa una función hash criptográfica, || representa la concatenación, require significa que se rechaza si falla una comprobación, y las claves inexistentes de Map se leen como 0. Primero, definamos las transacciones y los bloques:

Tx = {from_key, to_key, amount, seq, signature} # seq: número de transacción del pagador

Block = {prev_hash, transactions, nonce}

DIFFICULTY = 30 # los primeros 30 bits del hash del bloque deben ser 0

REWARD = 50 # recompensa por crear un bloque

function block_hash(block):

return H(block.prev_hash || serialize(block.transactions) || block.nonce)

function has_work(block):

return leading_zero_bits(block_hash(block)) >= DIFFICULTY

Las cuentas se representan directamente con claves públicas. La firma cubre todos los campos excepto la propia firma; seq hace que las transacciones de cada pagador sean distintas, y evita que el reenvío exacto de una transacción antigua sea aceptado, porque su número de secuencia no coincidirá. Si Alice usa el mismo número de secuencia en tx1 y tx2, una de ellas puede añadirse a la cadena y la otra fallará por no coincidir el número. Aunque use números distintos, la comprobación del saldo impedirá la segunda transacción.

Los nodos completos no conservan una tabla de saldos de confianza: reproducen toda la cadena desde el bloque génesis. Si falla una sola comprobación, la cadena entera es inválida:

State = {balance: Map, next_seq: Map}

function apply_block(state, block):

s = copy(state)

reward = block.transactions[0] # primera transacción: recompensa por crear el bloque, sin pagador

require reward.amount == REWARD

s.balance[reward.to_key] += REWARD

for tx in block.transactions[1:]:

require verify(tx.from_key, digest(tx), tx.signature) # autorización: la firma sustituye a la base de contraseñas

require tx.seq == s.next_seq[tx.from_key] # evita la repetición

require s.balance[tx.from_key] >= tx.amount # saldo: se comprueba según el historial de esta cadena

s.balance[tx.from_key] -= tx.amount

s.balance[tx.to_key] += tx.amount

s.next_seq[tx.from_key] += 1

return s

function replay(chain):

state = empty_state()

for i in indices(chain):

if i > 0:

require chain[i].prev_hash == block_hash(chain[i - 1]) # inmutabilidad: cadena de hashes

require has_work(chain[i]) # inmutabilidad: prueba de trabajo

state = apply_block(state, chain[i])

return state

La comprobación del saldo sigue existiendo; lo que cambia es que ahora se comprueba contra «el estado reconstruido al reproducir esta cadena», en lugar de «la base de datos del banco». El resto del trabajo de los nodos consiste en recibir transacciones, elegir una cadena y minar:

my_chain = [GENESIS]

pending = set() # transacciones recibidas que aún no se han añadido a la cadena

function total_work(chain): # con dificultad fija, el trabajo por bloque es igual y el trabajo acumulado es proporcional al número de bloques

return len(chain) * 2^DIFFICULTY

function on_transaction(tx):

pending.add(tx)

broadcast(tx)

function on_chain(candidate): # orden: solo se acepta la cadena válida con más trabajo acumulado

if total_work(candidate) <= total_work(my_chain):

return

if try_replay(candidate) is invalid: # igual que replay; devuelve invalid si falla cualquier require

return # una cadena que infringe las reglas no se acepta, por mucha capacidad de cálculo que tenga

my_chain = candidate

broadcast(my_chain)

function mine_one_block(my_key):

tip = last(my_chain)

state = replay(my_chain)

block = {prev_hash: block_hash(tip),

transactions: [reward_to(my_key)] + valid_subset(pending, state),

nonce: 0}

while not has_work(block): # no hay atajos: solo queda probar uno por uno

if last(my_chain) != tip:

return # alguien creó un bloque antes: abandonar y empezar de nuevo desde la nueva punta de la cadena

block.nonce += 1

my_chain.append(block)

broadcast(my_chain)

valid_subset selecciona en orden las transacciones que siguen siendo válidas en el estado actual; solo puede elegir tx1 o tx2. Para simplificar, se omite aquí el paso de eliminar de pending las transacciones que ya se añadieron a la cadena.

Apliquemos el ejemplo del doble gasto anterior: en el conjunto pending del minero A está primero tx1, y en el del minero B está primero tx2; ambos empiezan a calcular. A obtiene primero el resultado y lo difunde. Los demás nodos reproducen la cadena de A, la validan y se cambian a ella. B ve que la punta de la cadena ha cambiado, abandona su bloque y, al volver a ensamblarlo sobre la nueva cadena, descubre que tx2 ya no supera la comprobación de secuencia o de saldo. El libro mayor vuelve a tener una sola versión.

Este Toy Model puede ejecutarse, pero aún le falta bastante para ser Bitcoin. La tabla siguiente enumera las principales diferencias entre ambos y también el orden de las secciones que vienen a continuación.

A continuación veremos la implementación real de Bitcoin. Los importes se expresan en satoshis: 1 BTC equivale a 100.000.000 satoshis.

Carteras, claves privadas, claves públicas y firmas

El Toy Model representa cada cuenta con una clave pública. Bitcoin en realidad divide esta función entre varios elementos: los usuarios envían y reciben dinero mediante una cartera, que es un software para gestionar claves, generar direcciones de recepción y construir transacciones.

Por ejemplo, en una cartera cuyas claves controla el propio usuario, la cartera administra un conjunto de claves. La clave privada es un valor secreto que la cartera usa para firmar los pagos; la clave pública se deriva de ella y sirve para verificar las firmas. La clave pública puede hacerse pública: quien la tenga puede verificar firmas, pero no puede deducir la clave privada ni firmar pagos nuevos en nombre de su titular a un coste computacional viable. Claves públicas, claves privadas y firmas

Como ya dijimos, una firma digital depende tanto de la clave privada como del contenido firmado; no es una misma imagen de firma que se pega en cada ocasión. Lo que Alice firma incluye las condiciones de recepción de Bob y el importe. Si ese contenido cambia, la firma original ya no supera la verificación.

La firma, por sí sola, se puede resumir en tres pasos:

# La cartera obtiene la clave pública a partir de la clave privada

public_key = derive_public_key(private_key)

# Al pagar, se firma con la clave privada el resumen del contenido acordado de la transacción

signature = sign(private_key, transaction_digest)

# Los demás nodos verifican la firma con la clave pública; nunca necesitan obtener la clave privada

valid = verify(public_key, transaction_digest, signature)

La firma demuestra que hubo autorización; el contenido de la transacción sigue siendo público. Aquí la clave pública sirve para verificar, no para cifrar el contenido del pago y convertirlo en un mensaje que solo pueda leer el destinatario.

Para recibir un pago, lo habitual es que Bob le envíe una dirección a Alice. La dirección codifica las condiciones de recepción en una cadena que la cartera puede reconocer, y permite al pagador especificar cómo podrá gastarse ese dinero en el futuro. La clave pública sirve para verificar la firma; la dirección expresa las condiciones de recepción. No son el mismo dato. Los distintos formatos de dirección expresan esas condiciones de maneras diferentes.

Cuando Alice paga a Bob, utiliza la clave privada de Alice, porque está gastando dinero que ella controla. La dirección de Bob determina las condiciones que regirán el nuevo importe recibido. Cuando Bob quiera gastar ese dinero, será él quien firme con su propia clave privada. Autorización de transacciones y condiciones de recepción

La cartera guarda las claves o permite utilizarlas; la titularidad de los importes queda registrada en la cadena. Cuando una cartera muestra un saldo, busca en los registros de la cadena los importes que puede gastar. Por eso, con una dirección de recepción se puede enviar dinero a alguien; con una clave privada se obtiene la capacidad de gastar los fondos correspondientes. Cómo funcionan las carteras

Como en el ejemplo anterior del doble gasto, la firma no decide qué pago va primero. Las firmas de dos pagos en conflicto pueden ser ambas de Alice; los nodos deben consultar los registros existentes en el libro mayor para determinar qué transacción sigue teniendo derecho a gastar ese dinero.

¿Qué cambia una transacción?

El Toy Model asigna un saldo a cada clave pública y usa un número de secuencia para impedir repeticiones. Bitcoin no mantiene saldos de cuentas: aunque la cartera muestra una cifra de saldo, lo que verifican los nodos completos son registros concretos de fondos gastables. Estos registros se llaman UTXO, siglas de Unspent Transaction Output, es decir, salidas de transacción no gastadas. Una transacción normal consume una o varias salidas antiguas y crea otras nuevas, cada una con un importe y unas condiciones de gasto.

Así, impedir repeticiones y evitar el doble gasto se convierten en una misma regla: cada salida solo puede gastarse una vez. Cuando una transacción gasta una salida, esta desaparece del conjunto de fondos gastables. Si se vuelve a enviar la transacción exactamente igual, o se firma otra que hace referencia a la misma salida, ambas fallan porque ya no la encuentran. UTXO es una decisión de diseño de Bitcoin, no un requisito de la descentralización; Ethereum, por ejemplo, usa un modelo de saldos de cuentas. Apuntes de Rutgers: Bitcoin

Podemos imaginar una salida como un vale con condiciones de cobro. Tiene un importe y unas condiciones de bloqueo; la siguiente transacción hace referencia a ella y presenta pruebas de que cumple esas condiciones. El conjunto UTXO que mantienen los nodos completos registra qué vales de la cadena siguen disponibles. El saldo que muestra la cartera es la suma de los importes de las salidas que puede gastar. Una salida se identifica de forma única mediante (txid, índice de salida): el identificador de transacción txid indica qué transacción es, y el índice indica cuál de sus salidas, numeradas desde 0. Esta pareja se llama outpoint. Estructura de las transacciones y UTXO

Supongamos que Alice tiene una salida de 100.000 satoshis y quiere pagarle 60.000 satoshis a Bob, con una comisión de 1.000 satoshis para el minero. La transacción tendría este aspecto.

La entrada consume una salida antigua entera. El cambio se crea como una salida nueva; la comisión es la diferencia entre el total de las entradas y el total de las salidas.

El siguiente pseudocódigo usa pagos de una sola clave y deja el resumen de la firma, el script y las condiciones de bloqueo a cargo de funciones con nombre. require significa que se rechaza si falla una comprobación; range(a, b) incluye a y excluye b; ^ representa una potencia.

Outpoint = (txid, output_index)

Output = {value, locking_condition}

Coin = {output, created_height, is_coinbase} # el último campo indica si procede de una recompensa por bloque

UTXO = Map

tx.inputs = [{previous_output: (A, 0)}]

tx.outputs = [

{value: 60_000, locking_condition: pay_to(Bob)},

{value: 39_000, locking_condition: pay_to(Alice_change_key)}

]

previous = lookup_previous_outputs(tx)

for i in indices(tx.inputs):

# Se firma el contenido de este gasto; la clave privada no se incluye en el registro de la transacción

digest = signature_digest(tx, i, previous, mode=ALL)

tx.inputs[i].authorization = sign(Alice_private_key, digest)

Aquí, ALL significa que la firma compromete a quien firma con las referencias de las entradas de este pago, todas las salidas y otros contenidos. Si alguien sustituye la salida de recepción de Bob por una suya, la verificación de la firma fallará.

Al verificar una transacción normal, el trabajo esencial de un nodo completo consiste en comprobar que las referencias y las autorizaciones sean válidas y que los importes cuadren. La siguiente función solo calcula los cambios de estado; estos se aplican a UTXO únicamente después de superar todas las comprobaciones. Si una falla a mitad del proceso, no queda un estado parcial en el que «ya se haya descontado el dinero».

function check_regular_transaction(tx, view, context):

require not is_coinbase(tx) # las transacciones de recompensa por bloque se tratan aparte

require valid_structure_and_money_ranges(tx)

require inputs_are_unique(tx)

require locks_are_satisfied(tx, view, context)

previous = []

for input in tx.inputs:

coin = view.get(input.previous_output)

require coin exists # las salidas ya gastadas no están aquí

if coin.is_coinbase: # hay que esperar a que maduren las salidas de recompensas por bloque antes de gastarlas

require context.height - coin.created_height >= 100

previous.append(coin)

# Generar los cambios del libro mayor solo después de validar todas las autorizaciones de las entradas

for i in indices(tx.inputs):

require verify_spend(tx, i, previous, context)

input_value = checked_sum(coin.output.value for coin in previous)

output_value = checked_sum(output.value for output in tx.outputs)

require input_value >= output_value

delta = {

remove: all input.previous_output,

add: each (txid(tx), i) -> Coin(tx.outputs[i], context.height, false)

}

return {delta, fee: input_value - output_value}

result = check_regular_transaction(tx, view, context)

view.apply_atomically(result.delta)

view es una vista de un estado concreto de la cadena. Al comprobar un bloque nuevo, parte del estado UTXO del bloque padre y se actualiza siguiendo el orden de las transacciones del bloque. Por eso, una transacción puede gastar una salida de una transacción normal anterior del mismo bloque; una vez gastada una salida, la segunda referencia a ella falla. Para consultar los detalles de las comprobaciones de límites de importe, entradas duplicadas y período de maduración de coinbase, véanse las comprobaciones de estructura de transacción y de entradas de Core.

Alice aún puede crear otra transacción que haga referencia a A:0 y transfiera el dinero a sí misma. Si se verifican sus firmas por separado, ambas transacciones son válidas. El conflicto solo aparece cuando se comprueban dentro de un mismo estado UTXO que se va actualizando. Por eso Bitcoin necesita que toda la red comparta un historial común. El proceso completo, desde que la cartera firma esta transacción hasta que un bloque la confirma, se describe más adelante en «De extremo a extremo: el proceso completo de gastar un UTXO».

Cómo fija un bloque un lote de transacciones

El Toy Model calcula el hash del bloque entero. En Bitcoin, el bloque se divide en dos partes: el cuerpo guarda la lista de transacciones y la cabecera guarda un resumen de ese lote y el hash de la cabecera del bloque anterior. Tanto la minería como el enlace entre bloques se basan únicamente en la cabecera de 80 bytes; por muchas transacciones que haya, la entrada de cada cálculo de hash tiene el mismo tamaño. ¿Cómo se resume la lista de transacciones? Bitcoin usa un árbol de Merkle, cuyo hash raíz se llama Merkle root.

A continuación, H(x) representa SHA256(SHA256(x)), es decir, el doble SHA-256 que Bitcoin utiliza para las cabeceras de bloque y para el árbol de Merkle de esta sección; a || b representa la concatenación de bytes.

Las hojas del árbol de Merkle son los identificadores de las transacciones; los nodos padres son los hashes de la concatenación de sus nodos hijos izquierdo y derecho. Supongamos que el bloque contiene cuatro transacciones:

h0 = txid(tx0)

Sígueme para no perderte la próxima lectura rápida del mercado.