Все транзакции, выполняемые на блокчейне Aptos, должны быть подписаны. Это требование вводится сетью из соображений безопасности.
Генерирование сообщения для подписи
Первым шагом в подписании транзакции является создание сообщения для подписания транзакции. Чтобы сгенерировать такое сообщение для подписи, вы можете использовать:
REST API ноды Aptos. Нода Aptos сгенерирует сообщение для подписи, подпись транзакции и отправит подписанную транзакцию в блокчейн Aptos. Однако такой подход небезопасен. См. раздел Отправка транзакций в BCS против JSON.
Также смотрите руководство "Ваша первая транзакция", в котором объясняется этот подход.
Однако вы можете предпочесть, чтобы за создание подписанной транзакции отвечало ваше пользовательское приложение, например, аппаратный модуль безопасности . При таком подходе перед отправкой транзакций пользователь должен:
Сериализовать транзакции в байты, и
Подписать байты закрытым ключом учетной записи. Как работает учетная запись и закрытый ключ, смотрите в разделе Учетные записи.
В этом руководстве мы познакомимся с концепциями построения транзакции, генерации соответствующего сообщения для подписи с помощью BCS-сериализации, а также с различными методами подписи в Aptos.
СОВЕТ
Мы настоятельно рекомендуем вам использовать формат BCS для отправки транзакций в блокчейн Aptos.
Обзор
Создание транзакции, готовой к исполнению на блокчейне Aptos, требует выполнения следующих четырех шагов:
- Создайте необработанную транзакцию,
RawTransaction
, также называемую неподписанной транзакцией. - Сгенерируйте сообщение для подписи, содержащее соответствующее - (
prefix_bytes
), и создайте подпись необработанной транзакции с помощью закрытого ключа пользователя. - Создайте
Authenticator
и подписанную транзакцию, и - BCS-сериализация подписанной транзакции (не показана на диаграмме в разделе "Обзор").
ИНФОРМАЦИЯ
Примеры кода в этом разделе написаны на языке Typescript.
Беззнаковые транзакции известны как RawTransactions
. Они содержат всю информацию о том, как выполнить операцию над учетной записью в Aptos. Но им не хватает соответствующей авторизации с помощью подписи или Authenticator
.
В блокчейне Aptos все данные кодируются как BCS (Binary Canonical Serialization).
Aptos поддерживает множество различных подходов к подписанию транзакции, но по умолчанию используется подпись одного лица, использующего Ed25519.
Authenticator
, созданный во время подписания транзакции, дает разрешение блокчейну Aptos на выполнение транзакции от имени владельца учетной записи.
Основные понятия
Необработанная транзакция состоит из следующих полей:
- sender (Адрес): Адрес учетной записи отправителя.
- sequence_number (uint64): Порядковый номер данной транзакции. Он должен совпадать с номером последовательности, хранящимся на учетной записи отправителя на момент выполнения транзакции.
- payload: Инструкции для блокчейна Aptos, включая публикацию модуля, выполнение функции скрипта или выполнение полезной нагрузки скрипта.
- max_gas_amount (uint64): Максимальная общая сумма газа, которую можно потратить на эту транзакцию. На учетной записи должно быть больше этой суммы газа, иначе транзакция будет отклонена при проверке.
- gas_unit_price (uint64): Цена, которая будет уплачена за единицу газа. Во время выполнения транзакции
total_gas_amount
, рассчитываемая следующим образом:total_gas_amount = total_gas_units_consumed * gas_unit_price
, не должна превышатьmax_gas_amount
, иначе транзакция будет прервана во время выполнения.total_gas_units_consumed
представляет собой общее количество единиц газа, потребленных во время выполнения транзакции. - expiration_timestamp_secs (uint64): Временная метка блокчейна, по истечении которой блокчейн отменит эту транзакцию.
- chain_id (uint8): Идентификатор сети блокчейн, на которой должна быть выполнена данная транзакция.
BCS
Binary Canonical Serialization (BCS) - это формат сериализации, применяемый к необработанной ( неподписанной) транзакции. Описание целей разработки BCS см. в разделе BCS.
BCS не является самоописывающимся форматом. Поэтому, чтобы десериализовать сообщение, необходимо заранее знать его тип и структуру.
Пример того, как BCS сериализует строку, показан ниже:
// A string is serialized as: byte length + byte representation of the string. The byte length is required for deserialization. Without it, no way the deserializer knows how many bytes to deserialize. const bytes: Unint8Array = bcs_serialize_string("aptos"); assert(bytes == [5, 0x61, 0x70, 0x74, 0x6F, 0x73]);
Сообщение для подписи
Байты BCS-сериализованной необработанной транзакции называются сообщением для подписи.
Кроме того, в Aptos любое содержимое, которое подписывается или хэшируется, солят уникальным префиксом, чтобы отличить его от других типов сообщений. Это делается для того, чтобы гарантировать, что содержимое может быть использовано только в предусмотренных скриптах. Сообщение для подписи RawTransaction имеет префикс prefix_bytes
, который равен sha3_256("APTOS::RawTransaction")
. Поэтому:
signing_message = prefix_bytes|bcs_bytes_of_raw_transaction.
. |
обозначает конкатенацию.
Подпись
Подпись - это результат хэширования подписываемого сообщения с помощью закрытого ключа пользователя. По умолчанию Aptos использует схему Ed25519 для генерации подписи необработанной транзакции.
- Подписывая сообщение подписи закрытым ключом, клиенты доказывают Aptos Blockchain, что они разрешили выполнение транзакции.
- Aptos Blockchain проверит подпись с помощью открытого ключа учетной записи пользователя, чтобы убедиться, что представленная транзакция действительно подписана пользователем.
Подписанная транзакция
Подписанная транзакция состоит из:
- необработанной транзакции и
- аутентификатор. Аутентификатор содержит открытый ключ пользователя и подпись необработанной транзакции.
Эта подписанная транзакция далее BCS-сериализуется , после чего подписанная транзакция готова к передаче в интерфейс Aptos REST.
Транзакции с несколькими подписями
Блокчейн Aptos поддерживает несколько методов подписания транзакций, включая однократную подпись, K-of-N multisig и другие.
Транзакция с несколькими подписями K-of-N означает, что для выполнения такой транзакции необходимо, чтобы по крайней мере K из N авторизованных подписантов подписали транзакцию и прошли проверку, проводимую в сети.
Подписи транзакций обернуты в Authenticator
. Блокчейн Aptos проверяет транзакции, представленные пользователями, используя данные Authenticator
. См. несколько примеров ниже:
На языке Typescript вот как выглядит аутентификатор с одной подписью:
interface Authenticator { public_key: Uint8Array, signature: Uint8Array }
Пример с несколькими подписями аутентификатора показан ниже:
interface MultiEd25519PublicKey { // A list of public keys public_keys: Uint8Array[], // At least `threshold` signatures must be valid threshold: Uint8, } interface MultiEd25519Signature { // A list of signatures signatures: Uint8Array[], // 4 bytes, at most 32 signatures are supported. // If Nth bit value is `1`, the Nth signature should be provided in `signatures`. Bits are read from left to right bitmap: Uint8Array, } interface MultisigAuthenticator { public_key: MultiEd25519PublicKey, signature: MultiEd25519Signature }
Детальные шаги
- Создание транзакции RawTransaction.
- Подготовка сообщения для подписи и его подписание.
- Создание аутентификатора и подписанной транзакции.
- Сериализация SignedTransaction.
Шаг 1. Создание транзакции RawTransaction
В приведенном ниже примере предполагается, что транзакция имеет полезную нагрузку в виде функции скрипта.
interface AccountAddress { // 32-byte array address: Uint8Array } interface ModuleId { address: AccountAddress, name: string } interface ScriptFunction { module: ModuleId, function: string, ty_args: string[], args: Uint8Array[] } interface RawTransaction { sender: AccountAddress, sequence_number: number, payload: ScriptFunction, max_gas_amount: number, gas_unit_price: number, expiration_timestamp_secs: number, chain_id: number, } function createRawTransaction(): RawTransaction { const payload: ScriptFunction = { module: { address: hexToAccountAddress("0x01"), name: "AptosCoin" }, function: "transfer", ty_args: [], args: [ BCS.serialize(hexToAccountAddress("0x02")), // receipient of the transfer BCS.serialize_uint64(2), // amount to transfer ] } return { "sender": hexToAccountAddress("0x01"), "sequence_number": 1n, "max_gas_amount": 2000n, "gas_unit_price": 1n, // Unix timestamp, in seconds + 10 minutes "expiration_timestamp_secs": Math.floor(Date.now() / 1000) + 600, "payload": payload, "chain_id": 3 }; }
ПРИМЕЧАНИЕ
СериализацияBCS
, показанная в приведенном выше коде, не совпадает с операцией сериализации BCS, показанной в разделе "Обзор".
Шаг 2. Создание сообщения для подписи и его подписание
- Сгенерируйте префикс (
prefix_bytes
) с SHA3_256 хэшем байтов строкиAPTOS::RawTransaction
. - Байты BCS сериализованной RawTransaction.
- Конкатенация префикса и байтов BCS.
- Подписание байтов закрытым ключом учетной записи.
import * as Nacl from "tweetnacl"; function hashPrefix(): Buffer { let hash = SHA3.sha3_256.create(); hash.update(`APTOS::RawTransaction`); return Buffer.from(hash.arrayBuffer()); } function bcsSerializeRawTransaction(txn: RawTransaction): Buffer { ... } // This will serialize a raw transaction into bytes function serializeRawTransaction(txn: RawTransaction): Buffer { // Generate a hash prefix const prefix = hashPrefix(); // Serialize txn with BCS const bcsSerializedTxn = bcsSerializeRawTransaction(txn); return Buffer.concat([prefix, bcsSerializedTxn]); } const rawTxn = createRawTransaction(); const signature = Nacl.sign(hashRawTransaction(rawTxn), ACCOUNT_PRIVATE_KEY);
Шаг 3. Создание аутентификатора и подписанной транзакции
interface Authenticator { public_key: Uint8Array, signature: Uint8Array } interface SignedTransaction { raw_txn: RawTransaction, authenticator: Authenticator } const authenticator = { public_key: PUBLIC_KEY, signature: signature } const signedTransaction: SignedTransaction = { raw_txn: rawTxn, authenticator: authenticator };
Шаг 4. Сериализация SignedTransaction
Сериализация SignedTransaction в байты с помощью BCS.
const signedTransactionPayload = bcsSerializeSignedTransaction(signedTransaction);
Отправка подписанной транзакции
Наконец, отправка транзакции с обязательным заголовком "Content-Type".
Чтобы отправить подписанную транзакцию в формате BCS, пользователь должен передать специальный заголовок, как показано в примере ниже:
curl -X POST -H "Content-Type: application/x.aptos.signed_transaction+bcs" --data-binary "@path/to/file_contains_bcs_bytes_of_signed_txn" https://some_domain/transactions
Top comments (1)
What's the point you just copied the whole doc?