Можно ли проверить, совпадает ли номер блока клиентского узла с лучшим (последним) номером блока блокчейна?

У меня есть отсортированный связанный список, содержащий около 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номер по-прежнему кажется на несколько блоков меньше, чем мой лучший номер блока в моей частной цепочке. Это нормальный случай?

Ответы (3)

Ethereum — вероятностная система.

На мой взгляд , просто невозможно быть уверенным, что вы смотрите на последний блок, который в конечном итоге превратится в самую длинную цепочку с исчезающе малой вероятностью того, что реорганизация цепочки изменит ситуацию. Поэтому я не думаю, что полагаться на свидетеля клиента — это хороший способ информировать процесс сортировки.

Я твердо верю в то, что смарт-контракт должен защищать целостность внутреннего хранилища данных. Если данные должны быть доступны в отсортированном порядке (не обязательно в цепочке), то порядок данных находится в рамках «гарантированной внутренней целостности».

Исходя из этого, опора на правильную информацию из того , что call()вы описываете, и потребность в ее актуальности должны исчезнуть . Это неприемлемая внешняя зависимость и, вероятно, не может быть удовлетворительно решена.

Рассмотрим три общих подхода

  • Вставьте "Боб"
  • Вставьте «Боб» после «Алиса».
  • Вставьте «Боб» рядом с «Алиса».

Первый может потребовать значительной глубины внутреннего поиска и не будет хорошо масштабироваться. Второй подход зависит от надежной информации извне; надежности мы, вероятно, не можем достичь. Третий подход опирается на подсказку об эффективности использования газа, но оставляет на усмотрение контракта принятие окончательного правильного решения.

«Рядом» — это, по сути, фора в процессе поиска. Важно отметить, что контракт завершит поиск и сделает собственные выводы о том, где и как вставить «Боб» с учетом текущего состояния упорядоченного списка. Любой список в любом состоянии в любом блоке любой цепочки должен быть правильно упорядочен, поскольку он не зависит от точного внешнего руководства.

В итоге:

Я бы сначала подумал, действительно ли сортировка должна быть в цепочке.

Если сортировка неизбежна, то организуйте в контракте сортированный связанный список или аналогичную схему индексации. Только контракт должен определять правильные точки вставки. «Подсказка» может сократить объем внутреннего поиска, необходимого для этого, тем самым снизив затраты на газ и помогая гарантировать, что процесс будет работать со списком любого размера.

Надеюсь, поможет.

Та же проблема, но с другим сценарием. Представьте, что на моем узле я купил предмет. В качестве метки времени я хочу использовать самый высокий номер блока. Узел назначит метку времени как blk.num, но его локальный номер блока может быть меньше, чем самый высокий номер блока. Таким образом, временная метка покупки может быть замечена раньше, поскольку blk.num узла отстает. В этом случае мой внешний алгоритм не может доверять метке времени как информации о номере блока в качестве времени покупки. В основном временная метка каждого узла как block.number будет отличаться друг от друга во время T, где временная метка blk.num не заслуживает доверия. @Rob Hitchens
Кажется, вы думаете об узле, действующем независимо и имеющем особые полномочия в отношении транзакции. Это не. Узел, используемый для отправки транзакции в сеть, является просто звеном в цепочке связи. Он не имеет особых привилегий или особого влияния на исход сделки. Номер блока не может быть неправильным. Он будет соответствовать номеру блока, когда транзакция обрабатывается сетью. Поскольку у майнеров есть некоторая свобода выбора, когда включать транзакцию, она слабо связана со временем отправки, но бесспорно верна с точки зрения того, что она представляет.
Независимо от транзакции, я хочу, чтобы только узел получал самый высокий номер блока из цепочки блоков вместо своего локального номера блока. web3.eth.syncing;не работает все время, и когда он не возвращает достоверную информацию, последний номер блокчейна также может измениться до тех пор, пока не будет возвращена достоверная информация. Ethereum — это вероятностная система, как вы сказали, я не могу дождаться точного времени ответа от сети, я думаю. извините за слишком много вопросов... @RobHitchens
Спасибо за этот пост. Это было полезно тем, что косвенно привело меня к другому выводу, и вам может быть интересна моя небольшая история отладки. Я написал об этом ветку твита здесь , которая оказалась неверной, а затем — следующую ветку твита здесь . Жизнь в качестве разработчика блокчейна, работающего с гейзенбагами в производстве! 😉
Не уверен, что это полезно или добавляет еще один слой путаницы. OP касается наблюдателя и предположения о состоянии при вставке транзакции в цепочку. Наблюдатель всегда будет знать только то, что он знает, и не будет знать того, чего он не знает. И состояние, возможно, изменится до того, как транзакция будет добыта. В цепочке в контрактах время всегда «сейчас», а состояние всегда текущее. Это выполняется в цепочках контрактов, вызывающих друг друга. Есть состояние, и вещи происходят в контексте этого состояния, но знания наблюдателей всегда отстают.

Да, можно проверить, совпадает ли номер блока с лучшим (последним) номером блока блокчейна.

Шаги будут

  1. Запросите общедоступный API блокчейна, чтобы получить последний номер блока
  2. Проверить против блока клиентов нет.

Часть отправки транзакции требует некоторых изменений на уровне ядра/API.

Как я могу запросить общедоступный API блокчейна? Через функцию контракта, если я вызываю функцию, которая возвращает block.number, насколько я понимаю, она должна возвращать последний номер блока. Я не понял, что вы имели в виду под «изменениями в уровне ядра/API». @niksmac
@Avatar etherscan.io/blocks — это общедоступная информационная доска, на этой странице показан самый высокий (лучший) блок с его точки зрения.
Я работаю над частной сетью, поэтому ссылка etherscan.io/blocks мне не поможет. Я также предпочитаю получать значение из вызова функции, не заглядывая в графический интерфейс. @Юаньфэй Чжу
может ли публичный API блокчейна быть постоянной или непостоянной функцией? Поскольку константа будет считываться из своих локальных данных, это не поможет. @никсмак
@ Аватар, как это может быть постоянным? это номер последнего блока, верно? Информация Юаньфэй Чжу верна.
Извините, я неправильно определил: функция вызова == константа* функция @niksmac
Лично я считаю очень важным проводить четкое различие между «можете ли вы это сделать» и «можете ли вы сделать это децентрализованным способом». В ответ на первый вопрос: «да, использовать общедоступный API обозревателя цепочки блоков» (хотя в данном случае это не работает). На второй вопрос (полностью децентрализованный) единственный ответ: «Самый высокий номер блока в полностью децентрализованном смысле БУДЕТ блоком, возвращаемым вашим локальным узлом». Меня беспокоит то, что такие ответы, как этот, полностью стирают это различие. Если кто-то собирается вернуться к централизованному решению, зачем вообще использовать блокчейн?
@Thomas Jay Rush: ваша точка зрения верна. В моем случае я использую частную цепочку с небольшим количеством узлов, что делает сеть очень хрупкой. Таким образом, узлы на несколько блоков отстают от самого высокого номера блока. Пожалуйста, смотрите здесь: ethereum.stackexchange.com/q/15310/4575

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
Просто сделайте это с узлом, которому, как вы доверяете, соответствует последний номер блока, и тогда вам будет с чем сравнивать. Это то, что я хотел сказать в своем первоначальном ответе.