¿Podría event watch () atravesar desde el último número de bloque (cola) hasta la cabeza?

En general, asumo que los eventos van de un número de bloque más pequeño a uno más grande.

Ejemplo:

contractDeployedBlockNumber = 10000
fromBlock: contractDeployedBlockNumber, toBlock: 'latest'

[P] ¿Podría event watch()atravesar desde 'latest'el número de bloque hasta el número de bloque 0 (o un número de bloque más pequeño)? esta es básicamente una operación de recorrido inverso para capturar eventprimero el último y romper, esto ayudará a recuperar el último evento emitido lo más rápido posible.


La función de contrato inteligente mantiene la información de los usuarios registrados y la actualiza usando la registerUser()función.

contract Example {
   mapping(address => uint) userLatestEmittedBlocNum;
   function registerUser(string memory userEmail,
                         string memory name,
                         string memory githubUserName) public
       returns (bool success)
   {
       userLatestEmittedBlocNum[msg.sender] = block.number;
       emit LogUser(msg.sender, userEmail, name, githubUserName);
       return true;
   }

   function getUserLatestEmittedBlocNum(address userAddress) public view
    returns(uint)
  {
      if (userLatestEmittedBlocNum[userAddress] != 0)
          return (userLatestEmittedBlocNum[userAddress]);
   }
   event LogUser(address userAddress, string userEmail, string name, string githubUserName);
 }

Puedo almacenar el número de bloque donde se actualiza la información del usuario userLatestEmittedBlocNum[msg.sender]y recuperar el registro emitido directamente desde ese número de bloque, pero esto costará almacenamiento adicional y uso de gas.

blockReadFrom = Example.functions. getUserLatestEmittedBlocNum(userAddress).call()
my_filter = Example.eventFilter('LogUser',{'fromBlock':int(blockReadFrom),'toBlock':int(blockReadFrom) + 1})

Como resultado, necesitamos recuperar el evento más reciente para cada usuario para obtener información actualizada.

Puede ser ineficiente iterar desde un número de bloque más pequeño hasta el número de bloque más reciente (que también obtendrá los eventos actualizados anteriores), y el rango de amplitud puede ser muy grande. En cambio, si pudiéramos escanear desde el último número de bloque hasta el número de bloque pequeño y romper la iteración cuando detectamos el evento, sería más rápido encontrar el último registro emitido.

En un contrato inteligente, se registra cierta información y, con el tiempo, puede actualizarse, por lo que el latestevento es válido. Así que quiero recuperar el evento más reciente en mi contrato inteligente, sin comenzar a escanear desde el número de bloque mucho más pequeño, lo que consume mucho tiempo y es ineficiente. Entonces, básicamente, comenzando desde el número de bloque 'más reciente' hasta el bloque más pequeño, y rompiendo esta iteración si atrapo el evento. De lo contrario, si empiezo desde un número de bloque más pequeño, pase lo que pase, tengo que iterar hasta el último número de bloque.


Meta :fromBlock: latest, toBlock: 0

blockNum = 0;
var contract = myContract.LogJob({}, { fromBlock: blockNum, toBlock: 'latest' });
var i = 0;
contract.watch(function (error, result) {
    console.log(i++ + ": " + JSON.stringify(result));
});
Sabrías cuándo tu contrato fue minado. Entonces, básicamente, necesitas iterar de latesta eso mindedBlockNumber. Espero haber podido darte alguna idea. Por favor, hágamelo saber si mi comprensión es incorrecta.
Pero no puedo iterar desde el último número de bloque hasta el más pequeño, no devuelve nada. fromBlock: latest, toBlock: 0@Rajesh

Respuestas (1)

Lo intentaré, porque las recompensas. :-)

Técnicamente, no, pero podrías crear un efecto similar.

Digo "no" porque la cadena de bloques es un conjunto bien ordenado de bloques, cada uno de los cuales contiene un conjunto bien ordenado de transacciones. Por extensión, la cadena de bloques es un conjunto bien ordenado de transacciones que comienza con la primera transacción en o después del bloque 0.

Aquí está el pateador.

Debe revisarse en orden debido al hecho de que un bloque después del bloque de génesis no se puede verificar de forma independiente sin hacer referencia al bloque anterior. En otras palabras, para saber que está viendo el bloque 50 auténtico (por consenso), debe tener conocimiento del bloque 49. Si comienza por el final, generalmente aplicará la lógica recursivamente hasta el bloque 0 , o deposite su confianza en algo que no sea su propia evaluación independiente.

Además, nunca puedes saber que tienes el último bloque. Lo máximo que puede saber es que tiene el último bloque que conoce (y probablemente haya uno aún más nuevo en camino). ¿Qué, sería el primero en una lista de eventos comenzando con el más nuevo primero? No duraría mucho.

Lograr algo similar a su caso de uso parece implicar escuchar todos los eventos conocidos e insertar continuamente nuevos bloques "más recientes" al comienzo de una lista. O (probablemente más eficiente) agregue el más nuevo al final de su propia lista y luego léalo al revés cuando lo necesite. Esto probablemente estaría relacionado con una preocupación fuera de la cadena (interfaz de usuario, caché, algo más...) - tal vez instantáneas de "punto en el tiempo" o actualizaciones en vivo a medida que se revelan nuevas entradas de registro "más recientes".

Es perfectamente justo mantener sus propias fuentes de datos fuera de la cadena por motivos de rendimiento y otros. Todavía puede obtener los beneficios de blockchain cuando los usuarios/clientes pueden verificar los hechos si así lo desean , confirmando los hechos contra su propia copia de la cadena. Esto es aproximadamente lo que sucede cuando usa exploradores de bloques en línea y otras aplicaciones que necesitan más rendimiento del que sería capaz de un nodo típico. Puedes ordenar ese tipo de cosas como quieras.

Espero eso ayude.

ACTUALIZAR

Existe un patrón para hacer esto de manera eficiente si diseña el contrato para respaldarlo. Utiliza migas de pan muy simples:

pragma solidity 0.5.1;

contract ReverseOrderEvents {

    uint lastEventBlock;

    event LogEvent(address sender, uint previousEvent);

    function doSomething() public {
        emit LogEvent(msg.sender, lastEventBlock);
        lastEventBlock = block.number;
    }
}

En el lado del cliente, cuando lastEvent != 0salte a ese bloque y "escuche" los eventos de interés. Este evento incluirá un puntero al bloque que contiene el evento anterior. Enjuague y repita. Cuando golpeas 0no hay eventos previos.

La técnica es simple y podría usar punteros separados para registros separados, usuarios separados, etc., según sea necesario para que los clientes puedan encontrar la información reciente más importante rápidamente.

Esto permite que un cliente comience con el más reciente y retroceda hasta donde esté interesado. El patrón se puede usar en diseños sin estado donde los datos están en el registro de eventos y posiblemente solo la entrada más reciente es importante.

En caso de que no quede claro, watch()no vaya al revés. Para usar esto, watch()solo necesitaría un bloque (que sería rápido), encontraría lo que necesita y luego watch()el siguiente bloque único de interés, siguiendo las pistas en orden inverso que estableció para usted mismo.

TY. Entendí tu punto, pero no estoy tratando de ver eventos. Debe ser un algoritmo muy simple. Solo quiero recuperar eventos del último número de bloque al más pequeño. Puedo registrarlos en mi máquina local pero no quiero hacer eso. ¿Por qué no podemos obtenerlos de más reciente a más pequeño, ya que podemos obtenerlos de menor a mayor? Todavía creo que esto podría implementarse en el lado web3 que en realidad es una función útil. @RobHitchens
Creo que expliqué por qué no está allí. ¿Sabías que puedes ampliar la web3biblioteca tú mismo?
¿Podría guiarme sobre la extensión de web3, podría hacer la codificación en su github? Mi mejor solución es almacenar el número de bloque de funciones implementadas y actualizarlo si hay una actualización, lo que apuntará al número de bloque exacto del evento actualizado. @RobHitchens
@RobHitchens Creo que un modelo completamente del lado del cliente funcionaría, ya que puede obtener el número de bloque conocido más reciente en el cliente, luego mediante programación, usando ese número de bloque, verifique la existencia del evento usando geten lugar de watch, para sondear, y si no obtener reduzca el número de bloque en uno y repita el proceso, esto aumenta el tiempo necesario, pero asegura que no es necesario agregar nada al contrato inteligente. @alper Necesitaría complicaciones ya sea del lado del cliente o un contrato estructurado intencionalmente para lograr esto afaik
Su respuesta actualizada es la solución que expliqué en mi pregunta ... uint lastEventBlockcausará almacenamiento de memoria adicional. Estoy tratando de encontrar una solución en la que no haya uso de almacenamiento adicional en el contrato. @RobHitchens