Single Nominator Pool
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
Single Nominator – это простой брандмауэрный смарт-контракт TON, который обеспечивает безопасную валидацию блокчейна TON через холодный кошелек. Контракт предназначен для валидаторов TON, которые имеют достаточный объем средств для стейкинга и проведения самостоятельной валидации, не полагаясь на ставки сторонних номинаторов. Контракт предоставляет альтернативную упрощенную реализацию смарт-контракта Nominator Pool, который поддерживает только одного номинатора. Преимущество этой реализации в том, что она более безопасна, поскольку поверхность атаки значительно меньше. Это происходит благодаря значительному снижению сложности смарт-контракта пула номинаторов, который обычно поддерживает несколько сторонних номинаторов.
Подходящее решение для валидаторов
Этот смарт-контракт предназначен для валидаторов TON, которые имеют достаточный объем средств для стейкинга и самостоятельной валидации. Другими доступными альтернативами являются:
- использование горячего кошелька (небезопасно, поскольку холодный кошелек необходим для предотвращения кражи в случае взлома узла валидатора)
- использование restricted-кошелька (который не поддерживается и имеет нерешенные векторы атак, например, атаки на слив газа)
- использование Пула номинаторов с max_nominators_count = 1 (излишне сложно при большой площади атаки)
Смотрите более подробное сравнение существующих альтернатив.
Официальный хэш-код
Проверьте смарт-контракт на сайте https://verifier.ton.org, прежде чем отправлять средства на реальный контракт.
Single nominator v1.0:
pCrmnqx2/+DkUtPU8T04ehTkbAGlqtul/B2JPmxx9bo=
Single nominator v1.1 (с выводом средств через комментарий):
zA05WJ6ywM/g/eKEVmV6O909lTlVrj+Y8lZkqzyQT70=
Архитектура
Архитектура практически идентична смарт-контракту Nominator Pool:

Разделение на две роли
- Владелец – холодный кошелек (приватный ключ, не подключенный к интернету), который владеет средствами, используемыми для стейкинга, и выступает в качестве single nominator
- Валидатор – кошелек, чей приватный ключ находится на узле валидатора (может подписывать блоки, но не может украсть средства, используемые для ставки)
Рабочий процесс
- Владелец хранит средства для стейкинга ($$$) в своем защищенном холодном кошельке.
- Владелец вносит депозит ($$$) в контракт Single Nominator (этот контракт).
- MyTonCtrl запускается на узле валидатора, подключенном к интернету.
- MyTonCtrl использует кошелек Валидатора, чтобы дать указание Single Nominator восстановить ставку в следующем избирательном цикле.
- Single Nominator отправляет ставку ($$$) Избирателю на один цикл.
- Избирательный цикл закончился, ставка может быть восстановлена.
- MyTonCtrl использует кошелек Валидатора, чтобы дать указание Single Nominator восстановить ставку в следующем избирательном цикле.
- Single Nominator восстанавливает ставку ($$$) из предыдущего цикла у Избирателя.
- Шаги 4-8 повторяются до тех пор, пока Владелец будет готов продолжать валидацию.
- Владелец выводит средства ($$$) из контракта Single Nominator и забирает их.
Ослабление векторов атак
-
Для подписи новых блоков узлу-валидатору требуется горячий кошелек. Данный кошелек небезопасен по своей сути, поскольку его приватный ключ имеет доступ к интернету. Если этот ключ будет скомпрометирован, Валидатор не сможет извлечь средства, используемые для валидации. Только Владелец может вывести эти средства.
-
Даже если кошелек Валидатора скомпрометирован, Владелец может попросить Single Nominator изменить адрес валидатора. Это не позволит злоумышленнику в дальнейшем взаимодействовать с Single Nominator. Здесь нет состояния гонки, Владелец всегда будет иметь приоритет.
-
На балансе Single Nominator хранятся только основные средства для стейкинга – этот баланс не используется для затрат газа. Деньги на газ для начала избирательного цикла хранятся в кошельке Валидатора. Это решение не позволит злоумышленнику, скомпрометировавшему валидатора, слить средства для стейкинга с помощью атаки на трату газа.
-
Single Nominator проверяет формат всех операций, выполняемых Валидатором, чтобы убедиться, что он не передает недействительные сообщения Избирателю.
-
В случае необходимости, например, если контракт Избирателя был обновлен и изменил свой интерфейс, Владелец все еще может отправить любое необработанное сообщение как Single Nominator, чтобы вернуть ставку от Избирателя.
-
В случае крайней необходимости, Владелец может установить код Single Nominator и переопределить его текущую логику работы для устранения непредвиденных обстоятельств.
Некоторые из этих векторов атак невозможно ослабить с помощью обычного контракта Nominator Pool, поскольку это позволит человеку, управляющему валидатором, красть средства у своих номинаторов. Это не проблема с Single Nominator потому, что Владелец и Валидатор принадлежат одной и той же стор оне.
Аудиты безопасности
Полный аудит безопасности, проведенный компанией Certik, доступен в репозитории: Certik Audit.
Сравнение существующих альтернатив
Предполагая, что вы валидатор с достаточной ставкой для самостоятельной валидации, вот альтернативные настройки, которые вы можете использовать с MyTonCtrl:
1. Обычный горячий кошелек
Это простейшая настройка, при которой MyTonCtrl подключен к тому же standard wallet, на котором хранятся средства. Поскольку этот кошелек подключен к интернету, он считается горячим кошельком.

Использование небезопасно, так как злоумышленник может получить приватный ключ, поскольку кошелек подключен к интернету. С помощью приватного ключа злоумышленник может отправить средства в стейкинг кому угодно.
2. Restricted-кошелек
Эта настройка заменяет стандартный кошелек на restricted wallet, который позволяет отправлять исходящие транзакции только заранее определенным адресам назначения, таким как Избиратель и Владелец.

Данный тип кошелька не обслуживается (заменен на Пул номинаторо в) и имеет нерешенные векторы атак, например, атаки на трату газа. Поскольку в одном и том же кошельке на одном балансе хранятся и плата за газ и основная сумма ставки, злоумышленник, скомпрометировавший приватный ключ, может генерировать транзакции, что повлечет за собой значительные убытки. Кроме того, при попытке вывода средств злоумышленник и владелец могут столкнуться с состоянием гонки из-за коллизий seqno.
3. Пул номинаторов
Пул номинаторов первым ввел четкое разграничение между владельцами ставок (номинаторами) и валидатором, подключенным к интернету. Пул номинаторов поддерживает до 40 номинаторов, делающих ставки вместе на одном валидаторе.

Смарт-контракт пул номинаторов чрезмерно сложен из-за поддержки 40 одновременно работающих номинаторов. Также, контракт должен защ ищать номинаторов от диплоера контракта, поскольку это отдельные сущности. Такая схема считается нормальной, но ее очень сложно проверить полностью из-за размера поверхности атаки. Это решение имеет смысл в том случае, если валидатор не имеет достаточно средств на стейкинг для самостоятельной валидации или хочет разделить прибыль со сторонними стейкхолдерами.
4. Single nominator
Именно такая настройка реализована в этом репо. Это очень упрощенная версия пула номинаторов, которая поддерживает одного номинатора и не нуждается в защите этого номинатора от разработчика смарт-контракта, поскольку они являются одной и той же сущностью.

Если у вас есть single nominator, который располагает всеми ставками для валидации, это самая надежная схема, которую можно использовать. Помимо простоты, этот смарт-контракт позволяет использовать владельцу различные аварийные защитные функции, например, восстановление ставки при возможном сценарии обновления Избирателя, которое может разрушить интерфейс восстановления ставки.
Сообщения владельца
Владелец номинатора может выполнить 4 операции:
1. withdraw
Используется для вывода средств на кошелек владельца. Чтобы вывести средства, владелец должен отправить сообщение, содержащее: opcode=0x1000 (32 бита), query_id (64 бита) и сумму вывода (переменная coin). Смарт-контракт номинатора отправит средства с флагом BOUNCEABLE и mode=64.
Если владелец использует горячий кошелек (не рекомендуется), withdraw-deeplink.ts может использоваться для создания deeplink, чтобы инициировать вывод средств с кошелька tonkeeper.
Командная строка: ts-node scripts/ts/withdraw-deeplink.ts single-nominator-addr withdraw-amount, где:
- single-nominator-addr – адрес single nominator, с которого владелец хочет вывести средства.
- withdraw-amount – сумма вывода. Смарт-контракт номинатора оставит в контракте 1 TON, поэтому фактическая сумма, которая будет отправлена на адрес владельца, будет минимальной между запрошенной суммой и балансом контракта -1.
Владелец должен запустить deeplink с телефона с кошельком tonkeeper.
Если владелец использует холодный кошелек (рекомендуется), withdraw.fif может использоваться для создания тела boc, содержащего опкод withdraw и сумму для вывода.
Командная строка: fift -s scripts/fif/withdraw.fif withdraw-amount,
где withdraw-amount – сумма для вывода средств из контракта номинатора на кошелек владельца. Как указано выше, в контракте номинатора будет оставлено не менее 1 TON.
Этот скрипт сгенерирует тело boc (с именем withdraw.boc), которое должно быть подписано и отправлено с кошелька владельца.
С черного компьютера владелец должен запустить:
- создайте и подпишите tx:
fift -s wallet-v3.fif my-wallet single_nominator_address sub_wallet_id seqno amount -B withdraw.boc, где my-wallet – это pk-файл владельца (без расширения). Суммы 1 TON должно быть достаточно, чтобы оплатить комиссию (оставшаяся сумма будет возвращена владельцу). Файл withdraw.boc – это boc, сгенерированный выше. - с компьютера с доступом в интернет выполните следующие действия:
lite-client -C global.config.json -c 'sendfile wallet-query.boc', чтобы отправить boc-файл (wallet-query.boc), созданный на предыдущем шаге.
2. change-validator
Используется для изменения адреса валидатора. Валидатор может отправить избирателю только NEW_STAKE и RECOVER_STAKE. Если приватный ключ валидатора был скомпрометирован, адрес валидатора может быть изменен. Обратите внимание, что в этом случае средства находятся в безопасности, так как только владелец может вывести средства.
Если владелец использует горячий кошелек (не рекомендуется), change-validator-deeplink.ts может использоваться для создания deeplink, чтобы изменить адрес валидатора.
Командна я строка: ts-node scripts/ts/change-validator-deeplink.ts single-nominator-addr new-validator-address, где:
- single-nominator-addr – адрес single nominator.
- new-validator-address (по-умолчанию адрес ZERO) – это адрес нового валидатора. Если вы хотите сразу же отключить валидатора и установить нового позже, возможно, будет удобно установить в качестве адреса валидатора адрес ZERO. Владелец должен запустить deeplink с телефона с кошельком tonkeeper.
Если владелец использует холодный кошелек (рекомендуется), change-validator.fif может использоваться для создания тела boc, содержащего опкод change-validator и новый адрес валидатора.
Командная строка: fift -s scripts/fif/change-validator.fif new-validator-address.
Этот скрипт сгенерирует тело boc (с именем change-validator.boc), которое должно быть подписано и отправлено из кошелька владельца.
С черного компьютера владелец должен запустить:
- создайте и подпишите tx:
fift -s wallet-v3.fif my-wallet single_nominator_address sub_wallet_id seqno amount -B change-validator.boc, где my-wallet – это pk-файл владельца (без расширения). Суммы 1 TON должно быть достаточно, чтобы оплатить комиссию (оставшаяся сумма буде т возвращена владельцу). Файл change-validator.boc – это boc, сгенерированный выше. - с компьютера с доступом в интернет выполните следующие действия:
lite-client -C global.config.json -c 'sendfile wallet-query.boc', чтобы отправить boc-файл (wallet-query.boc), созданный на предыдущем шаге.
3. send-raw-msg
Этот опкод не предполагается для использования в обычных условиях.
Опкод предназначен для отправки любого сообщения из смарт-контракта номинатора (должно быть подписано и отправлено из кошелька владельца).
Вы можете использовать этот опкод, когда адрес смарт-контракта избирателя был неожиданно изменен, и средства все еще заблокированы у избирателя. В этом случае RECOVER_STAKE от валидатора не сработает, и владельцу придется создавать определенное сообщение.
Тело сообщения должно содержать: opcode=0x7702 (32 бита), query_id (64 бита), mode (8 бит), ссылку на ячейку msg, которая будет отправлена как необработанное сообщение.