В экосистеме TRON подпись сообщений является неотъемлемой частью рабочих процессов децентрализованных приложений (dApp). Она позволяет пользователям подтверждать свои намерения, авторизовывать действия и подписывать данные без необходимости отправки транзакций в сеть. API `signMessageV2`, поддерживаемый TronLink, реализует стандарт TRON TIP-191, обеспечивая единый и безопасный способ подписи сообщений. В этой статье рассматривается, как использовать `signMessageV2`, как проверять подписи вне блокчейна и как подтверждать их подлинность на блокчейне с помощью минимального смарт-контракта.
Понимание TIP-191
TRON использует TIP-191 для формата сообщений с персональной подписью. Каждое сообщение, подписанное с помощью `signMessageV2`, перед хешированием добавляется строковый префикс, гарантирующий невозможность использования подписей в качестве действительных транзакций. Этот префикс выглядит следующим образом:
“\x19TRON Signed Message:\n<длина>” + <содержимое сообщения>
Префикс привязывает контекст сообщения к сети TRON, предотвращая повторное воспроизведение или злоупотребление той же подписи в другом блокчейне.
Подписание сообщений вне сети
С TronWeb и TronLink подписать сообщение очень просто. Ниже приведён короткий пример, который подписывает полезную нагрузку и проверяет её локально, без обращения к блокчейну:
// Compute a payload hash (keccak256 of UTF-8 string)
const hexText = tronWeb.utils.ethersUtils.keccak256(
tronWeb.utils.ethersUtils.toUtf8Bytes(‘demo-payload’)
); // “0x” + 64 hex chars
// Request signature from TronLink wallet
const sig = await tronWeb.trx.signMessageV2(hexText);
// Verify off-chain using TronWeb
const who = await tronWeb.trx.verifyMessageV2(hexText, sig);
console.log(‘Recovered (off-chain):’, who);
Этот код генерирует детерминированную подпись, которую можно проверить где угодно, в том числе внутри смарт-контракта. TronLink автоматически применяет TRON-префикс сообщения, хеширует его содержимое и подписывает его, используя закрытый ключ кошелька.
Проверка в цепочке в Solidity
Для подтверждения подлинности подписи в цепочке ваш контракт должен воссоздать точный дайджест, создаваемый `signMessageV2`. В примере ниже показано, как проверить как необработанные 32-байтовые сообщения, так и сообщения в шестнадцатеричном формате.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
library TronMsg {
function digestForHex66(string memory hexText) internal pure returns (bytes32) {
require(bytes(hexText).length == 66, “hex length != 66”);
return keccak256(abi.encodePacked(“\x19TRON Signed Message:\n66”, hexText));
}
}
library SimpleECDSA {
bytes32 private constant _HALF_ORDER =
0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0;
function recover(bytes32 digest, bytes memory sig) internal pure returns (address) {
if (sig.length != 65) return address(0);
bytes32 r; bytes32 s; uint8 v;
assembly {
r := mload(add(sig, 0x20))
s := mload(add(sig, 0x40))
v := byte(0, mload(add(sig, 0x60)))
}
if (v < 27) v += 27;
if (v != 27 && v != 28) return address(0);
if (uint256(s) > uint256(_HALF_ORDER)) return address(0);
return ecrecover(digest, v, r, s);
}
}
contract TronSigVerifierLite {
function verifyHexText(bytes32 raw32, bytes calldata sig, address expected)
external pure returns (bool)
{
string memory hexText = toHexString(raw32);
bytes32 digest = TronMsg.digestForHex66(hexText);
address signer = SimpleECDSA.recover(digest, sig);
return signer != address(0) && signer == expected;
}
}
Контракт восстанавливает тот же префикс и дайджест, которые TronLink использовал вне блокчейна. Затем он вызывает `ecrecover`, чтобы получить адрес подписавшего и сравнить его с ожидаемым значением.
Интеграция проверки в веб-приложение
Включенная демонстрационная страница (index.html) демонстрирует полное взаимодействие между веб-клиентом и развёрнутым контрактом. После подписания сообщения страница вызывает `verifyHexText` для подтверждения валидности в блокчейне:
const c = await tw.contract().at(addr);
const ok = await c.verifyHexText(hexText, sig, tw.defaultAddress.hex).call();
console.log(‘verifyHexText (on-chain) =>’, ok);
Развертывание и тестирование
TronBox упрощает развертывание как в локальных, так и в тестовых сетях. Проект определяет две среды: Nile (тестовая сеть) и Development (локальная). Используйте следующие команды:
tronbox compile
tronbox migrate — network nile
После развертывания скопируйте T-адрес, напечатанный TronBox, и вставьте его в поле ввода на веб-странице. После этого вы сможете подписывать и проверять сообщения прямо из браузера.
Ключевые выводы
- `signMessageV2` обеспечивает единообразное подписание на всех кошельках TRON с использованием TIP‑191.
- Смарт-контракт должен точно соответствовать логике построения префикса и дайджеста.
- Проверка вне сети (`verifyMessageV2`) происходит мгновенно; проверка внутри сети детерминирована.
- Такая настройка обеспечивает основу для аутентификации и авторизации на основе сообщений в DApps.
Полезные ссылки
TIP-191 TRON Developer Hub signMessageV2 API TronBox Docs TRON Resource Model Repository