¿Cómo encuentra un nodo una transacción en la cadena de bloques?

Si un cliente SPV (ligero) solicita a un nodo completo la sucursal de Merkle que contiene una transacción específica (o el valor de una dirección), ¿cómo encuentra el nodo completo esta transacción (o los UTXO) en la cadena de bloques? ¿El nodo completo escanea linealmente a través de toda la cadena de bloques o hay una forma más rápida de vincular transacciones y bloques?

Me encanta tu pregunta, nunca pensé en eso en detalle. Como no estoy seguro en absoluto, y más bien solo especulo, estoy publicando esto como un comentario (quizás alguien pueda usarlo como punto de partida para una respuesta): los clientes de SPV en su mayoría preguntan a los nodos sobre patrones como un filtro de floración que se resuelve en pagos realizados a sus direcciones. Dado que los clientes de SPV están interesados ​​​​exclusivamente en las monedas que aún existen (o están a punto de existir), toda esta información se encontrará buscando en el conjunto UTXO o en el grupo de memoria. -Fin de las especulaciones-.
@Murch El UTXO no contiene raíces merkle para demostrar que existe una salida, en ese modelo el nodo podría inventar tonterías. Sin embargo, tiene razón en que el UTXO se puede buscar en milisegundos, pero esto no obtendría ningún historial para la conexión del cliente.

Respuestas (2)

Puede leer la especificación bip37 para todos los detalles arenosos.

¿Cómo encuentra el nodo completo esta transacción (o los UTXO) en la cadena de bloques?

El cliente crea un filtro que contiene lo que le interesa, ya sea un script de salida (direcciones), claves públicas o TXID. Luego envían esto al nodo al que están conectados. Cuando solicitan datos para un bloque en particular, el nodo los filtra para que solo contengan cosas que coincidan con el filtro de floración de los clientes y se los envía. Para encontrar todo su UTXO no gastado, solicitan cada bloque de la cadena por turno y buscan cosas que podrían ser suyas. Como ha descubierto en su mayoría, esto implica para cada cliente que el nodo cargue 80 GB de bloques del disco y realice operaciones de filtrado extremadamente costosas en ellos.

Los nodos modernos reconocen cuán terrible es esta idea y permiten a los usuarios deshabilitar la funcionalidad por completo debido a la carga masiva y el riesgo de denegación de servicio involucrado. Con transacciones especialmente diseñadas, un par remoto con un solo comando de menos de 50 bytes puede hacer que un nodo cargue un bloque de 1 MB del disco, lo haga un millón de veces y luego no devuelva nada.

¿No piden simplemente los datos de los bloques de los que todavía no tienen información? Es decir, si se creó una billetera en el bloque 423,000, solo solicitaría bloques posteriores. Y luego, ¿ya que sabrá que alcanzó 430,000 la última vez solo bloques más nuevos después de eso?
Sí. También pueden omitir bloques que saben que ocurrieron antes de la "fecha de nacimiento" de las billeteras, ya que no es posible que haya transacciones desde ese momento que puedan gastar. Esto no ayuda mucho en la práctica porque la mayor parte del tamaño de la cadena se encuentra en los últimos meses.

Por lo general, el cliente ligero pregunta "¿está esta transacción en este bloque?" y no "en qué bloque está esta transacción". Esto último se puede hacer sin demasiados problemas si hay un txindex (índice de transacciones), que es algo para lo que bitcoind tiene una opción.

¡Gracias por tu respuesta! Aún así, un par de cosas no me quedan claras: (1) ¿Cómo determina el cliente SPV X en la pregunta "Esta transacción está en el bloque X"? ¿Al respaldar todos los bloques (digamos que acabo de instalar un nuevo cliente SPV y debería determinar cuánto bitcoin poseo en función de mis direcciones públicas)? (2) ¿Cómo funciona en el caso de un filtro Bloom? Según tengo entendido, ¿el nodo completo tiene que calcular los hashes de todas las transacciones y compararlos con el filtro? Esto parece demasiado lento para más de 80 GB de datos.
Los nodos no mantienen un txindexvalor predeterminado porque crecería constantemente y tendría un costo prohibitivo (habilitar esta opción reduce significativamente la velocidad de inserción de bloques y aumenta las escrituras en disco).