创建签名交易

在 Aptos 区块链上执行的所有交易都必须经过签名。出于安全原因,此要求由链强制执行。

生成签名消息

签署交易的第一步是从交易中生成签名消息。要生成这样的签名消息,您可以使用:

  • Aptos 节点的 REST API。 Aptos 节点将生成签名消息、交易签名并将签名的交易提交到 Aptos 区块链。但是,这种方法并不安全。请参阅以 BCS 与 JSON 提交交易。 - 另请参阅说明此方法的教程“您的首次交易”。

  • 但是,您可能更希望您的客户端应用程序(例如硬件安全模块 (HSM))负责生成签名交易。在这种方法中,在提交交易之前,客户必须: - 将交易序列化为字节,以及 - 使用帐户私钥对字节进行签名。有关帐户和私钥的工作原理,请参阅帐户。 本指南将介绍构建交易背后的概念,使用 BCS 序列化生成适当的签名消息,以及在 Aptos 中进行签名的各种方法。

我们强烈建议您使用 BCS 格式向 Aptos 区块链提交交易。

概述

创建准备在 Aptos 区块链上执行的交易需要以下四个步骤:

  1. 创建原始交易,RawTransaction,也称为未签名交易。

  2. 生成包含适当盐(prefix_bytes)的签名消息,并使用客户端的私钥生成原始交易的签名。

  3. 创建 Authenticator 和签名的交易,以及

  4. BCS 序列化已签名的交易(未在概览部分的图表中显示)。

信息 本节中的代码示例在 Typescript 中。

请参阅下面的高级流程图,显示原始交易如何成为签名交易:

未签名的交易称为“RawTransaction”。它们包含有关如何在 Aptos 中对帐户执行操作的所有信息。但他们缺乏带有签名或“身份验证器”的适当授权。 在 Aptos 区块链中,所有数据都被编码为 BCS(二进制规范序列化)。 Aptos 支持许多不同的方法来签署交易,但默认为使用 Ed25519 的单一签名者。 在交易签名期间产生的“Authenticator”授权 Aptos 区块链代表账户所有者执行交易。

关键概念

原始交易

原始交易由以下字段组成:

  • sender(地址):发件人的帐户地址。 sequence_number (uint64):本次交易的序列号。这必须与交易执行时存储在发件人帐户中的序列号匹配。

  • payload:Aptos 区块链的指令,包括发布模块、执行脚本函数或执行脚本负载。 max_gas_amount (uint64):此交易花费的最大总gas。账户必须有超过这个气体,否则交易将在验证期间被丢弃。

  • gas_unit_price (uint64):每个 gas 单位要支付的价格。在执行期间,total_gas_amount 的计算公式为:total_gas_amount = total_gas_units_consumed * gas_unit_price,不得超过 max_gas_amount,否则交易将在执行期间中止。 total_gas_units_consumed 表示执行交易时消耗的气体总单位。

  • expire_timestamp_secs (uint64):区块链将丢弃此交易的区块链时间戳。

  • chain_id (uint8):该交易打算在其上运行的区块链的链 ID。

BCS

BCS 二进制规范序列化 (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 区块链证明他们已授权执行交易。

  • Aptos Blockchain 将使用客户账户的公钥验证签名,以确保提交的交易确实由客户签名。

签名交易

签名交易 签署的交易包括:

  • 原始交易,以及

  • 身份验证器。身份验证器包含客户的公钥和原始交易的签名。 此已签名交易进一步 BCS 序列化(未在概览部分的图表中显示),之后已签名交易准备好提交到 Aptos REST 接口。

多重签名交易

Aptos 区块链支持多种交易签名方法,包括单一签名、K-of-N 多重签名等。 K-of-N 多重签名交易意味着要执行这样的交易,N 个授权签名者中至少有 K 个已经签署了该交易并通过了链的检查。 交易签名包含在 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
}

详细步骤

  1. 创建一个 RawTransaction。

  2. 准备要签名的消息并签名。

  3. 创建一个 Authenticator 和一个 SignedTransaction。

  4. 序列化 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. 创建签名消息并对其进行签名

  1. 使用字符串 APTOS::RawTransaction 的 SHA3_256 哈希字节生成前缀 (prefix_bytes)。

  2. BCS 序列化 RawTransaction 的字节数。

  3. 连接前缀和 BCS 字节。

  4. 使用帐户私钥对字节进行签名

步骤 3. 创建 Authenticator 和 SignedTransaction

步骤 4. 序列化 SignedTransaction

此步骤未显示在 [概述] 部分的流程图中。

使用 BCS 将 SignedTransaction 序列化为字节。

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

Last updated