Все транзакции, выполняемые на блокчейне 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?