Своя страница подписи

Vela разбирает каждую транзакцию до того, как вы её подтвердите, и это настоящая работа — но делает её то же приложение, которое эту транзакцию и собрало. Если приложение или путь, которым оно до вас доходит, подменили, оно может показать одно, а подписать другое. Именно это произошло с Bybit.

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

Что это такое

Одна папка — app-web/clearsigning в репозитории — которая одновременно и веб-страница, и расширение Chrome. Чистые HTML, CSS и JavaScript: ни фреймворка, ни сборщика, ни шага сборки, ни зависимостей и ни одного собственного сетевого запроса.

Получив запрос на подпись, она не верит присланной вместе с ним сводке. Она сама разбирает сырую calldata, сама считает дайджест, показывает, что подпись на самом деле разрешит, и только затем просит ваш passkey.

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

Какая копия может подписывать за ваш кошелёк

Passkey привязан к домену, на котором он создан. Ваши ключи Vela зарегистрированы под getvela.app, и браузер предложит их только странице, чья relying party — getvela.app. Это единственное правило и решает, какой способ запустить свою копию вам подходит.

Как расширение Chrome — именно этот вариант работает с вашим текущим кошельком. Relying party расширения — getvela.app, откуда бы ни взялась папка, поэтому ваши существующие ключи могут в нём подписывать, а исполняется тот самый код из папки, которую вы загрузили и осмотрели.

  1. Откройте chrome://extensions и включите режим разработчика.
  2. Загрузить распакованное расширение и выберите папку app-web/clearsigning.
  3. Иконка на панели откроет страницу во вкладке.

Как страница на вашем домене или на localhost. При раздаче по HTTP(S) relying party страницы — её собственное имя хоста, то есть подписывать она может ключами, зарегистрированными под этим хостом, а не ключами под getvela.app. Это правильный способ прогнать всю церемонию целиком, отработать десктопный сценарий и подписать за кошелёк, ключ которого создан на вашем домене. Но не способ подписать за уже существующий кошелёк getvela.app.

cd app-web/clearsigning
python3 -m http.server 8080   # → http://localhost:8080

Все пути в приложении относительные, поэтому подкаталог на существующем хосте тоже работает; открыть index.html прямо с диска (file://) годится, чтобы осмотреться, — без origin нет relying party, и подписать ничего нельзя.

Что она делает до подписи

  • Сама разбирает транзакцию. Что делает вызов, кому и на какую сумму — из calldata, включая вложенные вызовы внутри пакета.
  • Подписывает только тот дайджест, который вычислила сама. Дайджесты EIP-191, EIP-712, SafeOp и SafeMessage считаются прямо на странице и сверяются с vela-core — тем же кодом, что использует кошелёк. Дайджест, который посчитать не удалось, — это отказ, а не подпись.
  • Проверяет, что транзакция та самая, которую запросили. Вызов, о котором просил сайт, должен действительно находиться внутри подписываемой операции.
  • Отказывает в неограниченном разрешении. Не предупреждение — отказ, с указанием, что делать вместо этого.
  • Говорит, когда чего-то не может прочитать, вместо дружелюбной сводки, за которую не может отвечать.
  • Показывает адрес и идентикон аккаунта и не показывает имя получателя, присланное тем, кто просит подпись. Всё, чем управляет запрашивающая сторона, либо убирается, либо помечается как её слова.

Чего у неё намеренно нет

  • Никаких редакторов. Запрос фиксируется в момент прихода: вы его либо подписываете, либо нет. Выбор комиссии или редактор лимита переписали бы calldata, а это ровно та болезнь, ради которой страница и существует.
  • Никакого создания ключей. Страница подписи не может создать passkey. Создать его — значит создать другой аккаунт.
  • Никаких сетевых запросов. Если нечего запрашивать, нечего и перехватывать.

Как до неё доходит запрос

Кто запрашиваетКанал
Страница в том же браузереpostMessage
Страница того же браузера — расширениюПорт расширения
Десктопное приложение на той же машинеФрагмент URL + колбэк на loopback
Телефон или другой компьютерBluetooth LE (протокол реализован; радио на настоящем железе ещё не проверено)

Формат обмена, дайджесты и таблица, откуда берётся каждый элемент на экране, лежат в PROTOCOL.md рядом с кодом.

Когда ею пользоваться

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