У меня есть отсортированный связанный список, содержащий около 1000 элементов. Когда я получаю новый элемент, моя цель - добавить его в список, сохраняя порядок сортировки. Поэтому, если я получаю очень маленькое значение, мне нужно перебрать весь список, чтобы найти конец списка. Я предположил, что могу восстановить индекс с помощью постоянной функции, и моя функция транзакции может использовать возвращенное значение индекса, чтобы переместить элемент в правильное местоположение, не тратя газ на итерацию списка.
Моя цель — следовать этому руководству ( https://ethereum.stackexchange.com/a/13855/4575 ), чтобы вызвать константную функцию и отправить ее возвращаемое значение в функцию транзакции.
getIndex() => constant
setArray() => transaction
setArray( getIndex() );
Возникает вопрос: когда я вызываю константную функцию на моем клиентском узле, можно ли проверить, является ли номер блока моего клиентского узла лучшим номером блока или он отстает. Если он отстает, константная функция может вернуть неверную информацию.
Например, лучший блок блокчейна — 100. Но мой узел в настоящее время находится в блоке с номером 90 (в основном позади блокчейна). Поэтому, когда клиентский узел получает индекс списка до первых 90 блоков и пропускает элементы, сгенерированные в оставшихся 10 блоках.
[В] Можно ли проверить, соответствует ли номер блока клиентского узла лучшему блок-цепочке, который является последним номером блока?
Как видно на примере изображения, номер блока на клиентских узлах может отличаться. Лучший номер блока — 1 002 312, но номер блока — 1 002 304 на узле вверху. Но иногда все узлы находятся на последнем номере блока. Поэтому трудно доверять поведению узла.
Следующий ответ кажется рабочим:
web3.eth.syncing; sync.highestBlock
Но возвращенный highestBlock
номер по-прежнему кажется на несколько блоков меньше, чем мой лучший номер блока в моей частной цепочке. Это нормальный случай?
Ethereum — вероятностная система.
На мой взгляд , просто невозможно быть уверенным, что вы смотрите на последний блок, который в конечном итоге превратится в самую длинную цепочку с исчезающе малой вероятностью того, что реорганизация цепочки изменит ситуацию. Поэтому я не думаю, что полагаться на свидетеля клиента — это хороший способ информировать процесс сортировки.
Я твердо верю в то, что смарт-контракт должен защищать целостность внутреннего хранилища данных. Если данные должны быть доступны в отсортированном порядке (не обязательно в цепочке), то порядок данных находится в рамках «гарантированной внутренней целостности».
Исходя из этого, опора на правильную информацию из того , что call()
вы описываете, и потребность в ее актуальности должны исчезнуть . Это неприемлемая внешняя зависимость и, вероятно, не может быть удовлетворительно решена.
Рассмотрим три общих подхода
Первый может потребовать значительной глубины внутреннего поиска и не будет хорошо масштабироваться. Второй подход зависит от надежной информации извне; надежности мы, вероятно, не можем достичь. Третий подход опирается на подсказку об эффективности использования газа, но оставляет на усмотрение контракта принятие окончательного правильного решения.
«Рядом» — это, по сути, фора в процессе поиска. Важно отметить, что контракт завершит поиск и сделает собственные выводы о том, где и как вставить «Боб» с учетом текущего состояния упорядоченного списка. Любой список в любом состоянии в любом блоке любой цепочки должен быть правильно упорядочен, поскольку он не зависит от точного внешнего руководства.
В итоге:
Я бы сначала подумал, действительно ли сортировка должна быть в цепочке.
Если сортировка неизбежна, то организуйте в контракте сортированный связанный список или аналогичную схему индексации. Только контракт должен определять правильные точки вставки. «Подсказка» может сократить объем внутреннего поиска, необходимого для этого, тем самым снизив затраты на газ и помогая гарантировать, что процесс будет работать со списком любого размера.
Надеюсь, поможет.
Шаги будут
Часть отправки транзакции требует некоторых изменений на уровне ядра/API.
API RPC поддержал вас.
Просто используйте эту функцию, чтобы проверить свой последний блок и последний блок клиента. В зависимости от того, насколько вы хотите доверять клиенту, вы можете сравнить значения на стороне клиента или убедиться, что они будут переданы вам обратно без манипуляций.
Функция для получения последнего блока:
web3.currentProvider.sendAsync({
method: "eth_blockNumber",
params: [],
jsonrpc: "2.0",
id: 83
} function (error, result) {...})
Подробнее о JSON RPC API и о том, как его можно использовать разными способами (например, с помощью curl): здесь .
Кстати, вы можете использовать curl для удаленной проверки текущего блока клиентов, если его настройки узла и брандмауэра разрешают подключение.
Конечно, не забудьте преобразовать результат в десятичное число, parseInt(value, 16)
.
Вы можете найти пример того, как реализовать такие функции web3 здесь.
curl --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":83}' -X POST localhost:8545
. Это также возвращает текущий номер блока узла, а не самый высокий достигнутый номер блока. Получить номер блока клиента не проблема, но он может отставать от самого большого номера блока. @NikitaFuchs
альпер
Роб Хитченс
альпер
web3.eth.syncing;
не работает все время, и когда он не возвращает достоверную информацию, последний номер блокчейна также может измениться до тех пор, пока не будет возвращена достоверная информация. Ethereum — это вероятностная система, как вы сказали, я не могу дождаться точного времени ответа от сети, я думаю. извините за слишком много вопросов... @RobHitchensНео
Роб Хитченс