Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
dinc
6 лет назад

Проблемы с Значением Nonce в Ethereum (Kin)

Мы ожидаем, что пользователи будут отправлять несколько транзакций в Kin  - подряд. Мы не хотим,  чтобы пользователи понимали суть блокчейна и мониторили свои транзакции вручную. При тестировании нашего кошелька SDK Kin (на Android и iOS) у нас была проблема с отправкой нескольких транзакций одна за другой. В определенный период времени все наши транзакции застревали и мы не могли видеть, что они находятся в режиме ожидания, в конце концов они отменялись. Как оказалось, транзакции имели одинаковые значение nonce для нескольких транзакций.

(* Чтобы проще понимать что такое nonce  в криптографии это одноразовый код, выбранный случайным или псевдослучайным образом, который используется для безопасной передачи основного пароля, предотвращая атаку повторного воспроизведения)


           Что такое nonce?

Nonce может означать две вещи в Эфириуме:

  • Доказательство работы nonce: бессмысленное значение в блоке, которое можно отрегулировать, чтобы попытаться удовлетворить  условие "proof of work". В этом суть майнинга и в какой-то степени алгоритма "proof of work".
  •  Account nonce: счетчик транзакций в каждом аккаунте, который предотвращает повторные атаки (double-spend). Например, транзакция, отправляющая 20 монет от A до B, может повторяться снова и снова аккаунтом B, чтобы постоянно сливать монеты с баланс A.


Наша проблема связана с последним nonce - счетчиком транзакций. При совершении транзакции в сети Ethereum к каждой транзакции в той же учетной записи должен быть присвоен последовательный номер. Каждая нода обрабатывает транзакции с определенного адреса  в строгом порядке в соответствии со значением его nonce.


Следовательно, при неправильном приращении этого значения могут возникнуть различные ошибки. К примеру, скажем,  что последняя транзакция nonce была равна 121:

  •  Повторное использование nonce: если мы отправим новую транзакцию для одного и того же аккаунта с номером nonce-121 или ниже, нода отклонит эту транзакцию.
  •  «Пробелы» : если мы отправим новую транзакцию с номером nonce-123 или выше, транзакция не будет обработана до тех пор, пока этот разрыв не будет закрыт, то есть до тех пор, пока транзакция с nonce-122 не будет обработана.


Определение nonce для транзакций

Как уже упоминалось ранее, мы заметили, что мы отправляем транзакции с одинаковыми значениями nonce. Чтобы объяснить, как это произошло, давайте сначала поймем, как мы увеличиваем значение nonce в наших мобильных SDK. Мы используем метод Geth (EthereumClient.getPendingNonceAt), который принимает общедоступный адрес аккаунта в качестве параметра. Этот метод в конечном итоге сопоставляется с API-интерфейсом eth_getTransactionCount JSON-RPC с  параметром «pending». Помните, что nonce - это количество транзакций в этом контексте.

Ожидаемый блок является текущим блоком, который сейчас добывается, и будет подтвержден , добавлен в blockchain. Блоки ограничены по размеру, поэтому, когда ожидающий блок заполнен, любые другие транзакции, которые поступают к  ноде, будут храниться в специальной области памяти этой ноды, также известной как пул транзакций или txpool.

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

Теперь нам стало ясно, что вызвало проблему - мы столкнулись с пиком пропускной способности тестовой сети Ethereum. Наши транзакции были поставлены в очередь в txpool, и мы долго не могли отправить их в ожидающий блок. В конце концов, когда наши транзакции продвигались в очереди txpool и были обработаны, они были отклонены, так как использовали тоже самое значение для nonce.


     Возможные Решения

1. Выполнение тяжелой работы на стороне клиента: Поиск последнего подходящее значения nonce на стороне клиента.

Используя Ethereum JSON-RPC, самый близкий способ получить ожидающую транзакцию - получить отложенный блок с использованием eth_getBlockByNumber и итерировать по всем транзакциям. Этот метод не имеет фильтра, поэтому мы должны искать транзакции с нашего адреса. Оставим в стороне тот факт, что он может включать в себя десятки транзакций (которые мы должны скачать и разобрать в мобильном клиенте). Мы просто получим такой  же результат, что и при использовании eth_getTransactionCount, поскольку мы мониторим только ожидающий блок.

Другим вариантом получения истинного значения nonce, является доступ ко всему txpool, поиск соответствующих транзакций там и выводить правильное значения  следующего nonce. Для этого мы можем использовать специальные API-интерфейсы Ethereum, связанные с txpool, называемые «API управления».

2. Усовершенствование серверной части (ноды): изменить логику на стороне сервера, чтобы просматривать весь txpool вместо ожидающего блока.

На гитахабе в go-ethereum есть открытая заяка, чтобы изменить это поведение, а в ноде есть собственное решение - нестандартное API parity_nextNonce, которое возвращает следующий доступный nonce как от ожидающего блока, так и от txpool. 

   Вывод

Хоть это и похоже на разумное решение, использование nonce, полученного из txpool,  несет в себе свои собственные риски. В случае, где мы отправляем несколько транзакций, мы можем перейти в состояние, в котором существует несколько транзакций в txpool. Если одна из этих транзакций недействительна и нода отклоняет ее, могут быть созданы "дыры" в подсчете транзакций. Это может привести к висячим транзакциям, которые не обрабатываются до тех пор, пока мы не заполним этот пробел. Так же это может быть очень сложно обнаружить и решить на стороне клиента.

Другая не определенная область - это то, что произойдет, когда ноды синхронизируются. Когда ноды объявляют новые транзакции другим узлам, а другие узлы объединяют эту новую информацию в свой собственный пул, что происходит с последним значенем nonce? Что произойдет, когда одна транзакция будет отправлена ​​на узел A, а вторая - в узел B? Последствия неясны. В отношении этих проблем, будущее решение может включать в себя - механизм дросселирования, который не позволит клиенту отправлять дополнительные транзакции при выполнении определенных условий.

Учитывая наш ассортимент продукции для IPLv2 (абстрагирование сложных деталей, когда пользователю - ему или ей не нужно знать, что такое nonce, для работы с нашим продуктом), мы решили не решать эти проблемы, пока не получим больше времени на создание оптимального решение.


Оригинальная статья  - тут

8
2.208 GOLOS
На Golos с May 2017
Комментарии (1)
Сортировать по:
Сначала старые