В общем, я предполагаю, что события проходят от меньшего к большему номеру блока.
Пример:
contractDeployedBlockNumber = 10000
fromBlock: contractDeployedBlockNumber, toBlock: 'latest'
[В] Можно ли event watch()
перейти от 'latest'
номера блока к блоку с номером 0 (или блоку с меньшим номером)? это в основном операция обратного обхода, чтобы event
сначала поймать самое последнее и сломать, это поможет как можно быстрее получить последнее сгенерированное событие.
Функция смарт-контракта хранит информацию о зарегистрированных пользователях и обновляет ее с помощью registerUser()
функции.
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);
}
Я могу сохранить номер блока, в котором обновляется информация о пользователе, userLatestEmittedBlocNum[msg.sender]
и получить созданный журнал непосредственно из этого номера блока, но это будет стоить дополнительного хранилища и использования газа.
blockReadFrom = Example.functions. getUserLatestEmittedBlocNum(userAddress).call()
my_filter = Example.eventFilter('LogUser',{'fromBlock':int(blockReadFrom),'toBlock':int(blockReadFrom) + 1})
В результате нам нужно получить последнее событие для каждого пользователя для актуальной информации.
Может быть неэффективно выполнять итерацию от меньшего номера блока к последнему номеру блока (который также получит предыдущие обновленные события), а диапазон диапазона может быть очень большим. Вместо этого, если бы мы могли сканировать от последнего номера блока к маленькому номеру блока и прерывать итерацию при перехвате события, возможно, было бы быстрее найти последний сгенерированный журнал.
В смарт-контракте некоторая информация регистрируется и со временем может обновляться, поэтому latest
событие является действительным. Поэтому я хочу получить последнее событие в моем смарт-контракте, не запуская сканирование с гораздо меньшего номера блока, что занимает много времени и неэффективно. Таким образом, в основном, начиная с «последнего» номера блока до меньшего блока, и прерывайте эту итерацию, если я поймаю событие. В противном случае, если я начну с меньшего номера блока, несмотря ни на что, мне придется повторять до последнего номера блока.
Цель :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));
});
Я постараюсь, потому что щедрости. :-)
Технически нет, но вы можете создать подобный эффект.
Я говорю «нет», потому что блокчейн — это упорядоченный набор блоков, каждый из которых содержит упорядоченный набор транзакций. В более широком смысле блокчейн представляет собой хорошо упорядоченный набор транзакций, начиная с первой транзакции в или после блока 0.
Вот кикер.
Он предназначен для просмотра по порядку из-за того, что блоки после блока генезиса не могут быть проверены независимо без ссылки на предыдущий блок. Другими словами, чтобы знать, что вы смотрите на подлинный 50-й блок (согласно консенсусу), вы должны знать блок 49. Если вы начнете с конца, вы, как правило, будете либо рекурсивно применять логику вплоть до блока 0 или доверьтесь чему-то другому, кроме собственной независимой оценки.
Кроме того, вы никогда не узнаете, что у вас есть последний блок. Самое большее, что вы можете знать, это то, что у вас есть последний блок, о котором вы знаете (и, возможно, еще более новый на подходе). Что, будет первым в списке событий, начиная с самого нового? Это не продлится очень долго.
Чтобы выполнить что-то похожее на ваш вариант использования, похоже, подразумевается прослушивание всех известных событий и постоянная вставка новых «самых последних» блоков в начале списка. Или (вероятно, более эффективно) добавить самые новые в конец вашего собственного списка, а затем прочитать его в обратном порядке, когда вам нужно. Это, вероятно, будет связано с проблемами вне сети (пользовательский интерфейс, кеш, что-то еще ...) - возможно, моментальные снимки «на момент времени» или оперативные обновления по мере появления новых «самых последних» записей журнала.
Совершенно справедливо поддерживать свои собственные источники данных вне сети для повышения производительности и по другим причинам. Вы по-прежнему можете пользоваться преимуществами блокчейна, когда пользователи/клиенты могут проверять факты , если захотят , подтверждая факты своей собственной копией цепочки. Это примерно то, что происходит, когда вы используете онлайн-обозреватели блоков и другие приложения, которым требуется большая производительность, чем может обеспечить обычный узел. Вы можете сортировать такие вещи как угодно.
Надеюсь, это поможет.
ОБНОВИТЬ
Существует шаблон для эффективного выполнения этого , если вы разрабатываете контракт для его поддержки. Он использует очень простые хлебные крошки:
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;
}
}
На стороне клиента, когда lastEvent != 0
затем перейти к этому блоку и «прослушать» интересующие события. Это событие будет включать указатель на блок, содержащий предыдущее событие. Промыть и повторить. Когда вы нажимаете 0
, предыдущих событий нет.
Этот метод прост, и вы можете использовать отдельные указатели для отдельных журналов, отдельных пользователей и т. д., если это необходимо, чтобы клиенты могли быстро находить наиболее важную последнюю информацию.
Это позволяет клиенту начать с самого последнего и вернуться назад, насколько это необходимо. Шаблон можно использовать в проектах без сохранения состояния, когда данные находятся в журнале событий и, возможно, важна только самая последняя запись.
На всякий случай, если это не ясно, watch()
не идет в обратном направлении. Чтобы использовать это, вы должны watch()
только один блок (что было бы быстро), найти то, что вам нужно, а затем watch()
следующий отдельный блок интересов, следуя подсказкам в обратном порядке, которые вы составили для себя.
web3
библиотеку самостоятельно?web3
, могу ли я написать код на их github? Мое лучшее решение — хранить развернутые функции blockNumber и обновлять его, если есть обновление, которое будет указывать на точный номер блока обновленного события. @Роб Хитченсget
вместо watch
, для опроса, и если не получить уменьшите номер блока на единицу и повторите процесс, это увеличит затрачиваемое время, но избавит вас от необходимости добавлять что-либо в смарт-контракт. @alper Вам потребуются сложности либо на стороне клиента, либо намеренно структурированный контракт, чтобы достичь этого, афаик.uint lastEventBlock
вызовет дополнительное хранилище памяти. Я пытаюсь найти решение, при котором в контракте не будет дополнительного использования хранилища. @РобХитченс
Раджеш
latest
к этомуmindedBlockNumber
. Надеюсь, мне удалось дать вам некоторое представление. Пожалуйста, дайте мне знать, если мое понимание неверно.альпер
fromBlock: latest, toBlock: 0
@ Раджеш