Me gustaría saber si es posible consultar valores de variables utilizando bloques más antiguos.
por ejemplo tengo
contract Simple {
string32 message public;
function Simple() {
message = msg.sender;
}
}
¿Es posible recuperar el valor del mensaje hace 1 mes? ¿Existe algún método que me permita inspeccionar dicha variable en una altura de bloque particular?
¿Existe algún método que recupere todos los valores diferentes que se encuentran en la cadena de bloques?
Muchísimas gracias.
No hay forma de que un contrato acceda a una variable que ya no se encuentra en el almacenamiento. Sin embargo, puede acceder a estas variables desde web3.
Recomendaría usar Events , que podría indexar por marca de tiempo para facilitar la búsqueda.
Con web3, hay una posible solución (probablemente no la más rápida ni la más elegante, pero es para mostrar cómo se puede hacer). Recuperamos la primera variable del contrato (índice 0), que es de tipo uint:
contract = "0x6d363cd2eb21ebd39e50c9a2f94a9724bf907d13";
maxBlocks = 1000;
startBlock = eth.blockNumber;
for (var i = 1; i < maxBlocks; i++) { /* Be careful: we go *back* in time */
current = web3.eth.getStorageAt(contract, 0, startBlock-i);
if (current != previous) {
/* TODO Where to find msg.sender? We probably have to loop
* over the transactions in the block can call
* web3.eth.getTransaction */
blockDate = new Date(web3.eth.getBlock(startBlock-i+1).timestamp*1000);
console.log("Block #" + (startBlock-i+1) + " (" + web3.eth.getBlock(startBlock-i+1).timestamp + " " + blockDate.toString()
+ ") : " + web3.toDecimal(previous));
/* What if there are two changes in a single block? The
* documentation of getStorageAt seems silent about that */
previous = current;
}
}
blockDate = new Date(web3.eth.getBlock(startBlock-maxBlocks).timestamp*1000);
console.log("Somewhere before block #" +(startBlock-maxBlocks) + " (block of " + blockDate.toString()
+ ") : " + web3.toDecimal(previous));
Puede probarlo en Testnet, donde se ha implementado el contrato con esta dirección.
En teoría, podría generar una prueba de Merkle increíblemente larga y compleja para demostrar a un contrato que una cuenta determinada tenía un valor particular en un número de bloque en particular, y podría aumentar bastante la eficiencia si tiene un contrato que almacena tantas cuentas anteriores bloquear hashes como sea posible; sin embargo, esto sería bastante difícil de implementar. Aparte de eso, la solución más simple a corto plazo puede ser averiguar exactamente a qué valores desea poder acceder de forma permanente desde el interior del contrato y mantenerlos almacenados de forma permanente en una matriz. Si solo desea acceder a valores pasados desde la interfaz, le recomiendo eventos como los mencionados en el póster anterior.
Depende de sus necesidades, pero supongo que algo como, digamos: debug.setHead(800000)
puede ayudar.
"Rebobina" el último bloque de su cadena de bloques para bloquear 800 000 (solo un ejemplo).
No sé si funciona para consultar contratos inteligentes anteriores, pero supongo que funcionará: a menudo lo he usado (en la consola geth JS) para consultar saldos anteriores para direcciones particulares.
El problema es que luego debe volver a sincronizar hasta el último bloque: es por eso que digo que depende de su caso de uso. La técnica no se escala, pero si sus requisitos son simples, puede ser suficiente.
Por ejemplo, si quiero consultar el saldo de una dirección (dirección que puede ser un contrato inteligente, por lo que es más avanzado que simplemente verificar la cantidad de ETH en una dirección "normal"), aproximadamente semanalmente, empiezo desde el bloque actual (el último one) luego debug.setHead(...) una semana antes de la fecha actual, luego una semana antes de eso, enjuague y repita. Eso es muy rápido. Pero al final necesitas volver a sincronizar desde donde hayas terminado.
ética