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 event
primero 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 latest
evento 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));
});
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 != 0
salte 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 0
no 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.
web3
biblioteca tú mismo?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. @RobHitchensget
en 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 afaikuint lastEventBlock
causará almacenamiento de memoria adicional. Estoy tratando de encontrar una solución en la que no haya uso de almacenamiento adicional en el contrato. @RobHitchens
Rajesh
latest
a esomindedBlockNumber
. Espero haber podido darte alguna idea. Por favor, hágamelo saber si mi comprensión es incorrecta.alper
fromBlock: latest, toBlock: 0
@Rajesh