¿Es posible verificar que el número de bloque del nodo del cliente coincida con el mejor (último) número de bloque de la cadena de bloques?

Tengo una lista ordenada ordenada que contiene alrededor de 1000 artículos. Cuando recibo un artículo nuevo, mi objetivo es empujar el artículo a la lista manteniendo el orden ordenado. Entonces, si recibo un valor muy pequeño, debo iterar toda la lista para encontrar la cola de la lista. Sugerí que podría recuperar el índice a través de la función constante y mi función de transacción podría usar el valor del índice devuelto para empujar el elemento a la ubicación correcta sin gastar gasolina para iterar la lista.

Mi objetivo es seguir esta guía ( https://ethereum.stackexchange.com/a/13855/4575 ) para llamar a una función constante y enviar su valor de retorno a una función de transacción.

getIndex() => constant 
setArray() => transaction

setArray( getIndex() );

Surge la pregunta de que: cuando llamo a una función constante en mi nodo cliente, ¿es posible verificar si el número de bloque de mi nodo cliente es el mejor número de bloque o está detrás? Si está atrasado, la función constante puede devolver información incorrecta.

Por ejemplo, el mejor bloque de blockchain es 100. Pero mi nodo se encuentra actualmente en blockNumber 90 (básicamente detrás de blockchain). Entonces, cuando el nodo del cliente obtiene el índice de la lista hasta los primeros 90 bloques y pierde los elementos generados en los 10 bloques restantes.

[P] ¿Es posible verificar que el número de bloque del nodo del cliente coincida con el mejor número de bloque de la cadena de bloques, que es el último número de bloque?

Como puede ver en la imagen de ejemplo, el número de bloque en los nodos del cliente puede variar. El mejor número de bloque es 1 002 312, pero el número de bloque es 1 002 304 en el nodo superior. Pero a veces todos los nodos están en el último número de bloque. Por lo tanto, es difícil confiar en el comportamiento del nodo.

ingrese la descripción de la imagen aquí

La siguiente respuesta parece funcionar:

web3.eth.syncing;
sync.highestBlock

Pero el número devuelto highestBlocktodavía parece un número de bloques más pequeño que en mi mejor número de bloque en mi cadena privada. ¿Es un caso normal?

Respuestas (3)

Ethereum es un sistema probabilístico.

En mi opinión , simplemente no hay forma de estar seguro de que uno está mirando el último bloque que finalmente lo convertirá en la cadena más larga con una probabilidad mínimamente pequeña de que una reorganización de la cadena reorganice las cosas. Por lo tanto, no creo que confiar en un testigo del cliente sea una buena forma de informar un proceso de clasificación.

Creo firmemente en el principio de que un contrato inteligente debe salvaguardar la integridad del almacenamiento interno de datos. Si los datos deben ser accesibles en orden ordenado (no necesariamente una preocupación en la cadena), entonces el orden de los datos se encuentra dentro del alcance de la "integridad interna garantizada".

Por esa razón, debe desaparecer la confianza en la información correcta de lo call()que usted describe y la necesidad de que sea actual . Es una dependencia externa inaceptable y probablemente no solucionable satisfactoriamente.

Considere tres enfoques generales

  • Inserta "Bob"
  • Inserte "Bob" después de "Alice"
  • Inserte "Bob" cerca de "Alice"

El primero puede requerir una profundidad considerable en la búsqueda interna y no escalará bien. El segundo enfoque depende de información confiable del exterior; confiabilidad que probablemente no podamos lograr. El tercer enfoque se basa en una pista sobre la eficiencia del gas, pero deja que el contrato tome la decisión final y correcta.

"Cerca" es básicamente una ventaja en el proceso de búsqueda. Es importante destacar que el contrato completará la búsqueda y llegará a sus propias conclusiones sobre dónde y cómo insertar "Bob" dado el estado actual de la lista ordenada. Cualquier lista en cualquier estado en cualquier bloque en cualquier cadena tendría que estar correctamente ordenada, debido a que no depende de una guía externa precisa.

En resumen:

Primero consideraría si el tipo realmente necesita estar en la cadena.

Si la clasificación es inevitable, organice una lista ordenada ordenada o un esquema de índice similar en el contrato. El contrato por sí solo debe determinar los puntos de inserción correctos. Una "pista" puede reducir la búsqueda interna necesaria para hacerlo, lo que reduce el costo del gas y ayuda a garantizar que el proceso funcione en una lista de cualquier tamaño.

Espero eso ayude.

El mismo problema pero con un escenario diferente. Imagine en mi nodo que compré un artículo. Como marca de tiempo, quiero usar el número de bloque más alto. El nodo asignará la marca de tiempo como blk.num, pero su número de bloque local podría ser más pequeño que el número de bloque más alto. Por lo tanto, la marca de tiempo de la compra se puede ver antes, ya que el blk.num del nodo está atrasado. En este caso, mi algoritmo externo no puede confiar en la marca de tiempo como información del número de bloque como tiempo de compra. Básicamente, la marca de tiempo de cada nodo como block.number será diferente entre sí en el momento T, donde la marca de tiempo de blk.num no es confiable.@Rob Hitchens
Parece estar pensando en que el nodo actúa de forma independiente y tiene poderes especiales sobre la transacción. No es asi. El nodo utilizado para enviar la transacción a la red es simplemente un eslabón en una cadena de comunicación. No tiene privilegios especiales ni influencia especial sobre el resultado de la transacción. El número de bloque no puede estar equivocado. Coincidirá con el número de bloque cuando la red extraiga la transacción. Dado que los mineros tienen cierta libertad sobre cuándo incluir una transacción, solo está vagamente relacionado con el tiempo de envío, pero es indiscutiblemente correcto en términos de lo que representa.
Independientemente de una transacción, solo quiero que el nodo obtenga el número de bloque más alto de la cadena de bloques en lugar de su número de bloque local. web3.eth.syncing;no funciona todo el tiempo y cuando no devuelve información válida, el último número de blockchain también puede cambiar hasta que se devuelva una información válida. Ethereum es un sistema probabilístico, como dijiste, supongo que no puedo esperar la hora exacta en que responda desde la red. perdón por tantas preguntas... @RobHitchens
Gracias por esta publicación. Fue útil porque indirectamente me llevó a otra conclusión, y puede que encuentres interesante mi pequeña historia de depuración. Escribí un hilo de tweet aquí , que encontré que era incorrecto, luego un hilo de tweet de seguimiento aquí . ¡La vida como desarrollador de blockchain lidiando con heisenbugs en producción! 😉
No estoy seguro si es útil o agrega otra capa de confusión. El OP se trata de un observador y asume cosas sobre el estado al insertar una transacción en la cadena. El observador siempre sabrá solo lo que sabe y no sabrá lo que no sabe. Y, el estado posiblemente cambiará antes de que se extraiga una transacción. En la cadena, en los contratos, el tiempo siempre es "ahora" y el estado siempre es actual. Esto se sostiene en cadenas de contratos llamándose unos a otros. Hay un estado y las cosas suceden en el contexto de ese estado, pero el conocimiento de los observadores siempre se queda atrás.

Sí, es posible comprobar si el número de bloque coincide con el mejor (último) número de bloque de la cadena de bloques.

Los pasos serían

  1. Consulta una API pública de blockchain para obtener el último número de bloque
  2. Verifique contra el bloque de clientes no.

La parte de la transacción de envío requiere algunos cambios en la capa central/api.

¿Cómo podría consultar una API pública de blockchain? A través de la función de un contrato, si llamo a una función que devuelve block.number como entiendo, debería devolver el último número de bloque. No entendí lo que quisiste decir con "cambios en la capa core/api".@niksmac
@Avatar etherscan.io/blocks aquí hay un tablero de información pública, esta página muestra el bloque más alto (mejor) desde su perspectiva.
Estoy trabajando en una cadena privada, por lo que el enlace etherscan.io/blocks no me ayudará. También prefiero obtener el valor de una llamada de función, sin mirar una interfaz gráfica de usuario. @Yuanfei Zhu
¿Podría la API pública de blockchain ser una función constante o no constante? Dado que la constante leerá de sus datos locales, no ayudará. @niksmac
@Avatar, ¿cómo podría ser eso constante? ese es el número del último bloque, ¿verdad? La información de Yuanfei Zhu es correcta.
Lo siento, identifiqué incorrectamente: función de llamada == función constante * @niksmac
Personalmente, creo que es muy importante hacer una distinción clara entre "puedes hacerlo" y "puedes hacerlo de forma descentralizada". En respuesta a la primera pregunta: "sí, use la API pública de un explorador de cadena de bloques" (aunque esto no funciona en este caso). A la segunda pregunta (totalmente descentralizada), la única respuesta es "el número de bloque más alto en un sentido totalmente descentralizado ES el bloque devuelto por su nodo local". Mi preocupación es que respuestas como esta eliminen por completo esta distinción. Si uno va a recurrir a una solución centralizada, ¿por qué usar una cadena de bloques?
@Thomas Jay Rush: tu punto es correcto. En mi caso estoy usando una cadena privada que tiene pocos nodos y obliga a que la red sea muy frágil. Entonces nodos mis pocas cuadras detrás del número de bloque más alto. Consulte aquí: ethereum.stackexchange.com/q/15310/4575

La API de RPC te respalda.

Simplemente use esta función para verificar su último bloque y el del cliente. Dependiendo de cuánto desee confiar en el cliente, puede comparar los valores del lado del cliente o asegurarse de que se le transfieran sin manipulación.

Función para obtener el último bloque:

web3.currentProvider.sendAsync({
  method: "eth_blockNumber",
  params: [],
  jsonrpc: "2.0",
  id: 83
} function (error, result) {...})

Más detalles sobre la API JSON RPC y cómo puede usarla de muchas maneras diferentes (con curl, por ejemplo): Aquí

Puede usar curl, por cierto, para verificar el bloqueo actual de los clientes de forma remota, si su configuración de nodo y firewall permite la conexión.

Por supuesto, no olvide convertir el resultado en un número decimal, parseInt(value, 16).

Puede encontrar un ejemplo de cómo implementar tales funciones web3 aquí.

Probé su sugerencia. curl --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":83}' -X POST localhost:8545Esto también devuelve el número de bloque actual del nodo, no el número de bloque más alto alcanzado. Obtener el número de bloque del cliente no es el problema, pero puede estar detrás del número de bloque más alto. @NikitaFuchs
Simplemente haga esto con un nodo en el que confíe para estar en el último número de bloque, entonces tendrá algo con lo que comparar. Eso es lo que quise decir en mi respuesta original.