¿Sería posible agregar una llamada RPC para poder determinar si un nodo está completamente sincronizado?

Después de leer esta respuesta , donde Peter Wuille habla sobre cómo un nodo realmente no puede saber si está sincronizado o no, me hizo preguntarme si hay alguna manera en que podamos saber que un nodo está tan sincronizado como posiblemente puede ser dado el compañeros a los que está conectado.

¿Podríamos agregar una llamada RPC como getsyncstatusesa para que el nodo pregunte a sus pares por sus bloques más altos conocidos y si la mayoría (o algún porcentaje) de sus pares están todos de acuerdo con la altura de bloque más conocida, entonces podría usar esa información para poder decir (sin una confiabilidad perfecta) qué tan sincronizado está el nodo?

Entonces, por ejemplo, si un nodo tiene 8 pares, y 7 de ellos regresan 330448como la mejor altura de bloque, y el cliente tiene información sobre el bloque 330448, entonces podría dar un código de estado y un mensaje que indica que está actualizado. Si los pares dan respuestas diferentes (lo que podría suceder si se conecta a un nodo malicioso que informa falsamente su altura más conocida O si otros pares no están completamente sincronizados), entonces podría dar un código de estado y un mensaje que indica que la búsqueda fue inconcluso y deben volver a intentarlo más tarde. Y, por último, si el 87,5 % de los nodos están diciendo 330448y el nodo solo está sincronizado para bloquear 1000, entonces puede dar un código de estado y un mensaje que indica que es probable que el nodo no esté lo suficientemente sincronizado.

Creo que esto sería útil principalmente como una forma de determinar si los servidores están lo suficientemente sincronizados con la red para usar en alguna aplicación. Las respuestas a esta pregunta describen una forma de ver si los nodos están actualizados, pero todos parecen un poco raros y no estoy seguro de que sean lo suficientemente confiables.

Respuestas (4)

Métodos existentes

El cliente de Bitcoin tiene una forma de detectar si no está lo suficientemente sincronizado. Sin embargo, que yo sepa, no está realmente expuesto a RPC de una manera agradable.

Se llama IsInitialBlockDownload(), y se considerará no sincronizado si se cumple alguna de las siguientes condiciones:

  • El cliente está importando desde bootstrap.dat o reindexando los bloques que tiene.
  • El cliente no ha llegado a todos sus puntos de control de bloqueo .
  • El cliente ha recibido y verificado un bloque en los últimos 10 segundos Y ese bloque tiene una marca de tiempo de hace más de 24 horas.

Puede llamar getblocktemplatey, si IsInitialBlockDownload()es cierto, volverá con un error de RPC_CLIENT_IN_INITIAL_DOWNLOAD(o -10).

inconvenientes

  • Si su nodo de Bitcoin está inactivo durante menos de 24 horas, esto no detectará nada malo cuando vuelva a funcionar.
  • es un poco feo
  • Cuando su cliente llegue dentro de las 24 horas del bloque actual, pensará que está actualizado, cuando probablemente necesite obtener ~144 bloques.
  • Si su cliente deja de descargar bloques mientras aún se está sincronizando, esto no detectará nada incorrecto.

Nueva llamada RPC

Supongamos que estamos diseñando una nueva llamada RPC desde cero. Como han señalado otros carteles, no es posible determinar esto perfectamente en presencia de actores malintencionados. ¿Qué factores podríamos medir para hacer una conjetura educada?

  • Tiempo de actividad del nodo. ¿El nodo ha estado activo durante al menos cinco minutos?
  • Tiempo de inactividad del nodo. ¿Se ha caído el nodo recientemente? Si es así, tome la cantidad de tiempo que estuvo inactivo y divídalo por mil. Si su nodo no ha estado activo al menos tanto tiempo, entonces no está sincronizado.
  • Marca de tiempo del bloque. La red es bastante liberal en cuanto a hacer cumplir esta regla, pero mi suposición no científica es que generalmente es dentro de media hora más o menos. Podría utilizar esta información de forma similar a como lo IsInitialBlockDownload()hace.
  • Altura del bloque del nodo central. Esta es la solución "Mira blockheight of blockexplorer" mencionada en la otra pregunta.
  • Su método probablemente funcionaría. El único problema que se me ocurre es que si te conectas a otro nodo que todavía se está sincronizando, fallarás.
¿Qué pasa si el cliente ha recibido un bloque recientemente pero no ha terminado de procesarlo, qué hará getblocktemplateen este caso?
@StephenM347 Mira cuando terminó de validar la punta de la mejor cadena de bloques. (Por lo tanto, no tiene en cuenta los bloques que no han sido validados).
Bien gracias. Desearía que esto se expusiera en la interfaz RPC de una manera menos pirateada.
Entonces, ¿no fallará este método si el cliente se sincroniza más allá de todos los puntos de control, pero ha estado desconectado durante aproximadamente 8 horas?
@ StephenM347 Bueno, no fallará. :) Con toda seriedad, tienes razón.
Entonces, desafortunadamente esto realmente no resuelve el problema entonces... :/
Pero responde a mi pregunta, así que si lo actualiza para incluir lo que me dijo en este comentario, lo marcaré como la respuesta correcta. Y agregar una nueva llamada RPC podría solucionar esto, crees, ¿verdad?

No, no hay forma de saberlo, porque no existe una definición de "estar sincronizado". ¿Sigues sincronizado en el momento en que un minero encuentra un nuevo bloque? ¿Cómo sabrías?

Lo que describe no tiene ningún beneficio sobre los métodos ya implementados para detectar si el nodo está muy atrasado (también ya está implementado como explica Pieter Wuille en la respuesta que vinculó, aunque no está disponible en la API).

¿Qué es exactamente qué tratar de lograr con esta información? ¿Por qué necesitas saber si un servidor está suficientemente sincronizado? Encontrará los bloques reales mucho antes de que cualquier atacante razonable pueda generarlos.

Ejemplo de uso: tiene una aplicación de procesamiento de pagos y desea que se deshabilite sola si la descarga de la cadena de bloques no está actualizada, en lugar de que algunas características no funcionen misteriosamente.
Como dijo Nick.
@StephenM347 ¿Cuántas aplicaciones de procesamiento de pagos no se ejecutan continuamente? Incluso entonces, puede verificar la marca de tiempo en el último bloque y compararla con la hora del sistema. No veo la ventaja.
Esas marcas de tiempo en bloques son bastante poco confiables, por lo que no creo que sea una posibilidad. Tenemos en mente un caso de uso más complicado, pero realmente no quiero profundizar demasiado en él. Lo que realmente queremos es una forma de saber si un servidor está demasiado atrasado para ser confiable.
E incluso si se ejecuta continuamente, debe saber cuándo estará listo después de la descarga inicial.
@ StephenM347 ¿Por qué no son confiables? Son al menos igual de confiables que consultar nodos aleatorios no verificables para conocer la altura de su bloque.
No son confiables porque los mineros los cambian con frecuencia para obtener más trabajo, y la red permite cierta flexibilidad al interpretar estos tiempos de bloqueo. No creo que sean tan confiables como consultar los nodos a los que está conectado, ya que Bitcoin solo funciona si la mayoría de los nodos son nodos honestos.

Bueno, bitcoind es de código abierto , por lo que es completamente posible que intente integrar algo así usted mismo. Sin embargo, en lugar de realizar cambios en el código base, es posible que pueda obtener una funcionalidad similar utilizando las llamadas rpc que ya están implementadas. Esencialmente, el cliente de bitcoin ya hace algo de lo que estás explicando. Cuando te conectas con un compañero, parte del proceso de negociación es compartir el bloque actual de cada uno; si uno es más alto que el otro y es válido, el otro comienza a descargarse desde el par más actual. Si observa el archivo debug.log, puede ver que esto sucede, junto con un campo de "progreso" en ejecución que se registra y le muestra el porcentaje que ha descargado.

Sin embargo, para su idea, donde agrega información, puede intentar usar la llamada rpc "getpeerinfo". Puede tomar la información de allí y analizarla de la forma que desee sin tener que hacer una llamada rpc nativa.

Puede o no ser útil para usted, pero solo para verificar, a veces tengo una pequeña secuencia de comandos/página web que obtiene la altura del bloque actual de cada uno de mis nodos bitcoind; si alguno de ellos es más bajo que la mayoría, entonces no están sincronizados. . Obviamente, necesitaría nodos en diferentes redes y máquinas; de lo contrario, un error podría significar que todos los nodos no están sincronizados. Sin embargo, funciona para mí, es simple y usa una llamada RPC existente.