# 创建签名交易

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

## **生成签名消息**

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

* Aptos 节点的 REST API。 Aptos 节点将生成签名消息、交易签名并将签名的交易提交到 Aptos 区块链。但是，这种方法并不安全。请参阅以 BCS 与 JSON 提交交易。 - 另请参阅说明此方法的教程“您的首次交易”。
* 但是，您可能更希望您的客户端应用程序（例如硬件安全模块 (HSM)）负责生成签名交易。在这种方法中，在提交交易之前，客户必须： - 将交易序列化为字节，以及 - 使用帐户私钥对字节进行签名。有关帐户和私钥的工作原理，请参阅帐户。 本指南将介绍构建交易背后的概念，使用 BCS 序列化生成适当的签名消息，以及在 Aptos 中进行签名的各种方法。&#x20;

{% hint style="info" %}
我们强烈建议您使用 BCS 格式向 Aptos 区块链提交交易。
{% endhint %}

## 概述

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

1. 创建原始交易，`RawTransaction`，也称为未签名交易。
2. 生成包含适当盐（`prefix_bytes`）的签名消息，并使用客户端的私钥生成原始交易的签名。
3. 创建 `Authenticator` 和签名的交易，以及
4. BCS 序列化已签名的交易（未在概览部分的图表中显示）。

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

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

<figure><img src="/files/6CAwoDfEUJTabRsf5592" alt=""><figcaption></figcaption></figure>

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

## **关键概念**

### **原始交易**

原始交易由以下字段组成：&#x20;

* **sender（地址）：**&#x53D1;件人的帐户地址。 sequence\_number (uint64)：本次交易的序列号。这必须与交易执行时存储在发件人帐户中的序列号匹配。&#x20;
* **payload：**&#x41;ptos 区块链的指令，包括发布模块、执行脚本函数或执行脚本负载。 max\_gas\_amount (uint64)：此交易花费的最大总gas。账户必须有超过这个气体，否则交易将在验证期间被丢弃。
* &#x20;**gas\_unit\_price (uint64)：**&#x6BCF;个 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)：**&#x533A;块链将丢弃此交易的区块链时间戳。&#x20;
* **chain\_id (uint8)：**&#x8BE5;交易打算在其上运行的区块链的链 ID。

### BCS

BCS 二进制规范序列化 (BCS) 是一种应用于原始（未签名）交易的序列化格式。有关 BCS 设计目标的说明，请参阅 BCS。 BCS 不是一种自我描述的格式。因此，为了反序列化消息，必须提前知道消息类型和布局。 BCS 如何序列化字符串的示例如下所示：

{% code lineNumbers="true" %}

```
// 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]);
```

{% endcode %}

### **签名留言**

BCS 序列化原始交易的字节称为**签名消息**。 此外，在 Aptos 中，任何经过签名或散列的内容都会使用唯一的前缀进行加盐处理，以将其与其他类型的消息区分开来。这样做是为了确保内容只能在预期的场景中使用。 RawTransaction 的签名消息以`prefix_bytes`为前缀，即`sha3_256("APTOS::RawTransaction")`。所以： `signing_message = prefix_bytes | bcs_bytes_of_raw_transaction.`。 `|` 表示连接。

{% hint style="info" %}
前缀步骤未显示在概览部分的图表中。
{% endhint %}

### 签名

签名是使用客户端私钥对签名消息进行散列处理的结果。默认情况下，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 }; }
```

{% hint style="info" %}
上面代码中显示的 BCS 序列化与概述部分中显示的 BCS 序列化操作不同。
{% endhint %}

### 步骤 2. 创建签名消息并对其进行签名

1. 使用字符串 `APTOS::RawTransaction` 的 SHA3\_256 哈希字节生成前缀 (`prefix_bytes`)。
2. BCS 序列化 RawTransaction 的字节数。
3. 连接前缀和 BCS 字节。
4. 使用帐户私钥对字节进行签名

<figure><img src="/files/sY41EpuoMSyclWaGrNKT" alt=""><figcaption></figcaption></figure>

### 步骤 3. 创建 Authenticator 和 SignedTransaction

<figure><img src="/files/w9VdX9n9S0tTMq4Gy2bn" alt=""><figcaption></figcaption></figure>

### **步骤 4. 序列化 SignedTransaction**

{% hint style="info" %}
此步骤未显示在 \[概述] 部分的流程图中。
{% endhint %}

使用 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
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gushi10546.gitbook.io/aptos-kai-fa-zhe-wen-dang/guides-zhi-nan/chuang-jian-qian-ming-jiao-yi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
