Я хотел бы знать, возможно ли запросить значения переменных, используя старые блоки.
Например, у меня есть
contract Simple {
string32 message public;
function Simple() {
message = msg.sender;
}
}
Можно ли получить значение сообщения 1 месяц назад? Есть ли метод, который позволяет мне проверять такую переменную на определенной высоте блока?
Существует ли метод, который извлекает все различные значения, найденные в блокчейне?
Большое спасибо.
Контракт не может получить доступ к переменной, которая больше не находится в хранилище. Однако вы можете получить доступ к этим переменным из web3.
Я бы порекомендовал использовать Events , которые вы можете индексировать по отметке времени, чтобы упростить поиск.
С web3 есть возможное решение (вероятно, не самое быстрое или самое элегантное, но оно должно показать, как это можно сделать). Мы получаем первую переменную контракта (индекс 0), которая имеет тип 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));
Вы можете попробовать это в Testnet, где был развернут контракт с этим адресом.
Теоретически вы могли бы придумать невероятно длинное и сложное доказательство Меркла, чтобы доказать контракту, что данная учетная запись имеет определенное значение в определенном номере блока, и вы могли бы немного повысить эффективность, если бы у вас был контракт, в котором хранится столько же предыдущих максимально блокировать хэши; однако это было бы довольно громоздко реализовать. Помимо этого, самым простым краткосрочным решением может быть просто выяснить, к каким именно значениям вы хотите иметь постоянный доступ из контракта, и просто постоянно хранить их в хранилище в массиве. Если вы просто хотите получить доступ к прошлым значениям из интерфейса, я рекомендую события, как упоминалось выше.
Это зависит от ваших потребностей, но я так понимаю, что-то вроде: debug.setHead(800000)
может помочь.
Он «перематывает» последний блок вашего блокчейна до блока 800 000 (просто пример).
Он не знает, работает ли он для запроса прошлых смарт-контрактов, но я полагаю, что он будет работать: я часто использовал его (в консоли geth JS) для запроса прошлых балансов для определенных адресов.
Проблема в том, что тогда вам нужно повторно синхронизировать до последнего блока: вот почему я говорю, что это зависит от вашего варианта использования. Этот метод не масштабируется, но если ваши требования просты, этого может быть достаточно.
Например, если я хочу запросить баланс адреса (адрес, который может быть смарт-контрактом, так что это более сложно, чем просто проверка количества ETH в «обычном» адресе), примерно раз в неделю я начинаю с текущего блока (последнего one), затем я отлаживаю.setHead(...) за неделю до текущей даты, затем за неделю до этого, промываю и повторяю. Это очень быстро. Но в конце вам нужно повторно синхронизироваться с того места, где вы оказались.
эт