# 交易如何运作

<div data-with-frame="true"><figure><img src="/files/dc8f9274ed5e1e2e8361cc917ce557753adc3a99" alt=""><figcaption></figcaption></figure></div>

### 简介

交易是 Stacks 中执行的基本单位。每笔交易都源自一个 Stacks 账户，并会永远保留在 Stacks 网络历史中。本指南将帮助你理解 Stacks 交易。

### 生命周期

交易在最终确认之前会经历多个阶段。

<div data-with-frame="true"><figure><img src="/files/2bb25686d422f250c55e3f9b46898a4205e9f493" alt=""><figcaption></figcaption></figure></div>

{% stepper %}
{% step %}
**生成**

交易会按照编码规范进行组装。
{% endstep %}

{% step %}
**验证并签名**

交易会经过验证，以确认其格式正确。所需签名会被补齐。
{% endstep %}

{% step %}
**广播**

交易会发送到节点。
{% endstep %}

{% step %}
**登记**

矿工接收交易，进行验证，并将其添加到内存池中，内存池是所有待处理交易的暂存区。
{% endstep %}

{% step %}
**处理**

矿工会查看内存池，并为下一个要挖出的区块选择交易。根据交易类型，在此步骤中可能会发生不同操作。例如，可能会验证代币转账的后置条件，铸造智能合约定义的代币，或者尝试调用现有的智能合约方法。
{% endstep %}

{% step %}
**确认**

矿工成功提出包含一组交易的区块。当堆叠者批准这些区块后，其中的交易就会成功传播到网络中。
{% endstep %}
{% endstepper %}

{% hint style="info" %}
一笔交易在登记后可以处于以下三种状态之一： `待处理`, `成功`，或 `失败`.
{% endhint %}

### 类型

Stacks 支持多种不同的交易类型：

| **类型**   | **值**                     | **描述**                                                                                                   |
| -------- | ------------------------- | -------------------------------------------------------------------------------------------------------- |
| 任期变更     | `TenureChange`            | 任期变更是现有 Stacks 区块链中的一种事件，当一名矿工接替另一名矿工，负责创建新的 stacks 区块时，就会发生这种事件。当通过加密抽签发现一个 Stacks 区块时，就会发生任期变更。由堆叠者执行。 |
| 发现任期变更区块 | `TenureChange-BlockFound` | A `TenureChange-BlockFound` 交易由一次获胜的抽签触发。这会导致新矿工开始出块，并阻止当前矿工继续出块。                                        |
| 任期变更延展   | `TenureChange-Extend`     | A `TenureChange-Extend`由堆叠者触发，会重置当前任期正在进行的执行预算，从而允许矿工继续出块。                                               |
| 代币转账     | `token_transfer`          | 从发送方到接收方的资产转移                                                                                            |
| 合约部署     | `smart_contract`          | 合约实例化                                                                                                    |
| 合约调用     | `contract_call`           | 对一个公开的、非只读函数进行的合约调用                                                                                      |

## 手续费

手续费用于激励矿工在 Stacks 区块链上确认交易。手续费根据估算费率和原始交易的字节大小计算。费率是市场决定的变量。在测试网中，它设为 1 micro-STX。

## Nonce

每个账户都有一个 [nonce 属性](https://en.wikipedia.org/wiki/Cryptographic_nonce) ，用于指示该账户已处理的交易数量。Nonce 是一次性代码，从 `0` 开始用于新账户，并在每笔交易后递增 1。

Nonce 会添加到所有交易中，并帮助按顺序识别它们，以确保交易按顺序处理并避免重复处理。

{% hint style="info" %}
共识机制还通过两种方式确保交易不会被“重放”。首先，节点会查询其未花费交易输出（UTXO），以满足新交易中的花费条件。其次，节点之间发送的消息会检查序列号。
{% endhint %}

当构造一笔新的代币转账交易时，需要获取并设置该账户最新的 nonce。

### 如何检测并解决 nonce 缺口

Stacks 交易必须按照 **严格的 nonce 顺序**执行。当提交的交易 nonce 高于预期时，网络 **不会** 直接拒绝它——相反，它会跟踪这个缺口并等待缺失的 nonce 到来。

下面是一个概念性演示，并附有来自 API 的可视化响应，说明当 nonce 按错误顺序提交时系统会如何表现。

{% stepper %}
{% step %}
**初始状态（无待处理交易）**

```json
{
  last_mempool_tx_nonce: null,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 242,
  detected_missing_nonces: [],
  detected_mempool_nonces: []
}
```

**解读**

* 直到 nonce `241` 的所有交易都已执行
* 网络期望 nonce `242` 下一个
* 当前内存池中没有交易在等待
* 不存在 nonce 缺口
  {% endstep %}

{% step %}
**提交一个未来的 nonce（`245`)**

```json
{
  last_mempool_tx_nonce: 245,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 246,
  detected_missing_nonces: [244, 243, 242],
  detected_mempool_nonces: []
}
```

**解读**

* 一笔 nonce 为 `245` 的交易现在已在内存池中
* Nonce `242`, `243`，以及 `244` 缺失
* 在这些 nonce 提交之前，执行无法继续
* `possible_next_nonce` 反映的是已观察到的最高 nonce + 1
  {% endstep %}

{% step %}
**提交一个部分缺口（`243`)**

```json
{
  last_mempool_tx_nonce: 245,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 246,
  detected_missing_nonces: [244, 242],
  detected_mempool_nonces: [243]
}
```

**解读**

* Nonce `243` 现在已存在于内存池中
* Nonce `242` 和 `244` 仍然缺失
* 执行仍然被阻塞
* API 区分以下两者：
  * `detected_mempool_nonces` → 已存在但尚未执行
  * `detected_missing_nonces` → 必需但尚未看到
    {% endstep %}

{% step %}
**填补更多缺口（`244`)**

```json
{
  last_mempool_tx_nonce: 245,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 246,
  detected_missing_nonces: [242],
  detected_mempool_nonces: [243, 244]
}
```

**解读**

* Nonce `243` 和 `244` 都在内存池中等待
* Nonce `242` 仍然缺失
* 执行仍暂停在 `241`
  {% endstep %}

{% step %}
**所有必需的 nonce 都已存在（`242`)**

```json
{
  last_mempool_tx_nonce: 245,
  last_executed_tx_nonce: 241,
  possible_next_nonce: 246,
  detected_missing_nonces: [],
  detected_mempool_nonces: [242, 243, 244]
}
```

**解读**

* 所有必需的 nonce（`242–245`）现在都可用
* 不再有缺口
* 网络可以按顺序执行交易
  {% endstep %}

{% step %}
**执行完成后**

```json
{
  last_mempool_tx_nonce: null,
  last_executed_tx_nonce: 245,
  possible_next_nonce: 246,
  detected_missing_nonces: [],
  detected_mempool_nonces: []
}
```

**解读**

* 所有待处理交易都已执行
* 账户 nonce 已推进到 `245`
* 下一个有效 nonce 现在是 `246`
* 内存池状态再次变为干净
  {% endstep %}
  {% endstepper %}


---

# 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://docs.stacks.co/learn/zh/transactions/how-transactions-work.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.
