> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 私有状态和 UTXO

> 了解 UTXO 如何存储代币和私有状态。

<a id="private-solana-token-accounts" />

私有余额存储在 UTXO（未花费交易输出）中。
你可以将 UTXO 理解为私有 SPL 代币账户，但它们有两个核心区别：

1. UTXO 不是 Solana 账户，因此无需免租。
2. 它的余额在链上加密。

UTXO 的数据布局与 SPL 代币账户类似：

* **所有者** – Solana 密钥对、PDA 或 P-256 密钥。
* **资产** – 铸币（SOL、SPL 或 Token-2022）。
* **数量** – `asset` 的单位数量，以其最小单位计。
* **数据** – UTXO 可以存储任意数据，例如托管代币的所有者。
* **程序和策略数据** – 可选的已配置 Ring 合规信息。

<Tabs>
  <Tab title="Diagram">
    <img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/account-comparison-private.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=4143bb77db4e5ff44225882d571b8830" alt="一个私有 Solana 代币账户。Solana 隐私程序拥有一个私有代币账户，该账户展开后显示其 UTXO 字段：所有者、资产、数量、数据、策略数据和策略程序 ID。" width="1080" height="590" data-path="images/privacy/account-comparison-private.svg" />
  </Tab>

  <Tab title="Code">
    为每个私有 Solana 代币账户存储的完整记录是一个扁平 UTXO：

    ```rust theme={"system"}
    struct Utxo {
        /// Constant separating UTXOs from other Poseidon-hashed data.
        domain: u16,
        /// Recipient's `owner_hash` from their Shielded Address.
        /// Senders write this value directly; the spender supplies the preimage
        /// components as proof witness.
        owner: [u8; 32],
        /// Asset mint. SOL is Address::default().
        asset: Address,
        /// Amount in the smallest unit of `asset`.
        amount: u64,
        /// Random bytes ensuring distinct UTXO hashes for equal
        /// `(owner, asset, amount)` triples.
        blinding: [u8; 31],
        /// Arbitrary program data.
        program_data: Option<Vec<u8>>,
        /// Arbitrary policy data.
        policy_data: Option<Vec<u8>>,
        /// The policy program that authorizes spends of this UTXO.
        policy_program_id: Option<Address>,
    }
    ```
  </Tab>
</Tabs>

<Info>
  查看源代码：[规范](https://github.com/helius-labs/zolana/blob/680667f27cf9ba4203a0b69284f4c304b874092f/docs/spec.md#utxo) · [sdk-libs/transaction/src/utxo/note.rs](https://github.com/helius-labs/zolana/blob/680667f27cf9ba4203a0b69284f4c304b874092f/sdk-libs/transaction/src/utxo/note.rs#L16)
</Info>

<Accordion title="View Solana token account">
  <Tabs>
    <Tab title="Diagram">
      <img src="https://mintcdn.com/helius/KNGZoSuCXDUVm6yU/images/privacy/account-comparison-solana.svg?fit=max&auto=format&n=KNGZoSuCXDUVm6yU&q=85&s=89ff901091255f2038972208fcb5d538" alt="Solana 代币账户。" width="1080" height="462" data-path="images/privacy/account-comparison-solana.svg" />
    </Tab>

    <Tab title="Code">
      ```rust theme={"system"}
      pub struct Account {
          /// The mint associated with this account
          pub mint: Pubkey,
          /// The owner of this account.
          pub owner: Pubkey,
          /// The amount of tokens this account holds.
          pub amount: u64,
          /// If `delegate` is `Some` then `delegated_amount` represents
          /// the amount authorized by the delegate
          pub delegate: COption<Pubkey>,
          /// The account's state
          pub state: AccountState,
          /// If is_native.is_some, this is a native token, and the value logs the
          /// rent-exempt reserve. An Account is required to be rent-exempt, so
          /// the value is used by the Processor to ensure that wrapped SOL
          /// accounts do not drop below this threshold.
          pub is_native: COption<u64>,
          /// The amount delegated
          pub delegated_amount: u64,
          /// Optional authority to close the account.
          pub close_authority: COption<Pubkey>,
      }
      ```
    </Tab>
  </Tabs>
</Accordion>

<a id="private-wallet-balance" />

## 私有余额

私有余额是私有钱包所拥有的某项资产的所有 UTXO 之和。
无论私有余额由一个还是多个 UTXO 组成，
钱包都只显示一个余额。
一次私有转账可以同时花费多个 UTXO。

<img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/utxo-set-to-wallet.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=398e39f96fc52325c895e512a9b09dc7" alt="一个私有钱包通过虚线连接到多个 UTXO，每个 UTXO 都持有某项资产的一定数量。钱包余额是这些 UTXO 的总和。" width="700" height="276" data-path="images/privacy/utxo-set-to-wallet.svg" />

## 私有转账

使用 UTXO 的私有转账与使用 SPL 代币账户的公开转账工作方式不同：

* 从 SPL 代币账户转账时，会更新 `amount`。
* 使用 UTXO 进行私有转账时，不会更新 UTXO 的 `amount`。
  相反，私有转账会花费现有 UTXO，
  并为接收方以及发送方的剩余余额创建新的 UTXO。

不过对用户而言，使用 Solana 代币账户进行的公开转账
与使用 UTXO 进行的私有转账体验相似。

例如，Alice 有 50 USDC，并向 Bob 发送 35 USDC。

* 使用 SPL 代币账户时，Alice 的 `amount` 从 50 减少到 15，而 Bob 的增加 35。
* 使用 UTXO 时，Alice 持有一个包含 50 USDC 的 UTXO。交易会花费现有 UTXO，并创建两个新 UTXO：一个为 Bob 持有 35 USDC，另一个为 Alice 持有 15 USDC。

<Tabs>
  <Tab title="Transfer with one UTXO">
    <img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/spend-comparison.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=c25d35501ca9fcff9b4c0c7c8654dd73" alt="花费一个 UTXO" width="1016" height="240" data-path="images/privacy/spend-comparison.svg" />
  </Tab>

  <Tab title="Transfer with multiple UTXOs">
    <img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/spend-comparison-multi.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=c35ec9ab7c87c8d3cdb9e3d1caaf7742" alt="花费多个 UTXO" width="1016" height="240" data-path="images/privacy/spend-comparison-multi.svg" />
  </Tab>
</Tabs>

| | Solana 代币账户 | 私有 Solana 代币账户（UTXO） |
| - | - | - |
| 余额 | 账户中的 `amount` | 所有未花费 UTXO 的总和，每个 UTXO 都包含某项资产的固定数量 |
| 花费 | 更新 `amount` 字段 | 使已花费的 UTXO 失效并创建新的 UTXO |
| 可见性 | 链上公开 | 链上加密 |

### UTXO 选择

对于私有转账，SDK 会选择足以覆盖你要转账金额的未花费 UTXO。

UTXO 选择算法会在每次转账中尽可能少地花费 UTXO：

1. SDK 按待发送的资产筛选你的 UTXO，并按数量对其排序。
2. SDK 会选择足够覆盖转账金额的 UTXO。
   它会优先选择最大的 UTXO，直到覆盖转账金额。

例如，Alice 向 Bob 发送 80 USDC。她最大的三个 UTXO 足以覆盖这笔转账：

<img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/utxo-selection.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=07ed7a4483eee5a3605ceb08291d5e02" alt="Alice 发送 80 USDC。她的 UTXO 按从大到小排序：40、25、20、10 和 5 USDC。SDK 选择 40、25 和 20 USDC，足以覆盖 80 USDC，并保留 10 和 5 USDC 不选。" width="770" height="140" data-path="images/privacy/utxo-selection.svg" />

使用较少的 UTXO 可以减小交易大小。
每个被花费的 UTXO 都会增加 66 字节，用于创建一个无效化标记账户，以将该 UTXO 标记为已花费。
该账户可防止 UTXO <Tooltip tip="The nullifier account is temporary. Asynchronously, the Forester inserts the nullifier into the nullifier Merkle tree, which records the UTXO as spent permanently. The Forester then closes the account and reclaims the rent-exemption.">被再次花费</Tooltip>。

以下是不含额外数据或其他指令的私有转账示例：

| 花费的 UTXO | 交易大小 | 账户数 |
| - | - | - |
| 2 | 927 字节 | 6 |
| 5 | 1,125 字节 | 9 |
| 36 | 3,055 字节 | 40 |

### 交易变体

每次私有转账都会使用一种交易变体，其中包含固定数量的槽位，分别用于待花费的 UTXO 和待创建的新 UTXO。

各变体支持花费 1 至 36 个 UTXO，并且每种变体都有自己的 ZK 电路。
该电路会证明被花费的 UTXO 有效，并且新 UTXO 持有的总金额相同。
如果一次转账需要超过 36 个 UTXO，请[先合并它们](#合并-utxo)。

SDK 会选择适合该转账的变体，并使用虚拟 UTXO 填充未使用的槽位。
虚拟 UTXO 不包含任何价值，在链上看起来与真实 UTXO 相同。

<Tabs>
  <Tab title="1 spent, 2 new">
    Alice 向 Bob 发送 30 USDC。她最大的 UTXO 足以覆盖这笔转账。

    <img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/utxo-variant-1-2.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=728d31824165d27d6fd5f98704431f5e" alt="Alice 的 40 USDC UTXO 被花费，而她的 25、20、10 和 5 USDC UTXO 保持未花费状态。该交易为 Bob 创建 30 USDC，并为 Alice 创建 10 USDC。" width="520" height="286" data-path="images/privacy/utxo-variant-1-2.svg" />
  </Tab>

  <Tab title="2 spent, 2 new">
    Alice 向 Bob 发送 60 USDC。她最大的两个 UTXO 足以覆盖这笔转账。

    <img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/utxo-variant-2-2.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=75d3804ee8a731e2b213dcbda9f3edbc" alt="Alice 的 40 和 25 USDC UTXO 被花费，而她的 20、10 和 5 USDC UTXO 保持未花费状态。该交易为 Bob 创建 60 USDC，并为 Alice 创建 5 USDC。" width="520" height="286" data-path="images/privacy/utxo-variant-2-2.svg" />
  </Tab>

  <Tab title="3 spent, 3 new">
    Alice 向 Bob 发送 80 USDC。她最大的三个 UTXO 足以覆盖这笔转账。SDK 使用一个虚拟 UTXO 填充未使用的槽位。

    <img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/utxo-variant-3-3.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=7cb4508367f8caaa674bd419719aec0b" alt="Alice 的 40、25 和 20 USDC UTXO 被花费，而她的 10 和 5 USDC UTXO 保持未花费状态。该交易为 Bob 创建 80 USDC，为 Alice 创建 5 USDC，并在未使用的槽位中创建一个 0 USDC 的虚拟 UTXO。" width="520" height="286" data-path="images/privacy/utxo-variant-3-3.svg" />
  </Tab>

  <Tab title="4 spent, 3 new">
    Alice 向 Bob 发送 95 USDC。她最大的四个 UTXO 足以覆盖这笔转账。SDK 使用虚拟 UTXO 填充两个未使用的槽位。

    <img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/utxo-variant-4-3.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=cf9bdd94965b8861ca25247bbe078c1c" alt="Alice 的 40、25、20 和 10 USDC UTXO 被花费，而她的 5 USDC UTXO 保持未花费状态。该交易为 Bob 创建 95 USDC，并在未使用的槽位中创建两个 0 USDC 的虚拟 UTXO。" width="520" height="286" data-path="images/privacy/utxo-variant-4-3.svg" />
  </Tab>
</Tabs>

<Accordion title="Supported transaction variants">
  | 花费的 UTXO | 新 UTXO |
  | - | - |
  | 1 | 1、2 或 8 |
  | 2 | 2 或 3 |
  | 3 | 3 |
  | 4 | 3 或 4 |
  | 5 | 3 或 4 |
  | 36 | 2 |

  <Info>
    查看源代码：[规范](https://github.com/helius-labs/zolana/blob/a3ddedda42b40d4951ae8fcdde2500374c4f2125/docs/spec.md#circuit-variants) · [支持的变体](https://github.com/helius-labs/zolana/blob/a3ddedda42b40d4951ae8fcdde2500374c4f2125/program-libs/interface/src/shape.rs)
  </Info>
</Accordion>

## 合并 UTXO

在只接收大量转账而不花费的情况下，私有余额可能会分散到许多 UTXO 中。

如果一次转账需要超过 36 个 UTXO，请先合并它们，以便用户可以在一次转账中花费全部余额。
由于一次转账最多可以花费 36 个 UTXO，因此大多数用户很少会遇到余额碎片化的情况。

* 合并会将所有者和资产相同的 UTXO 合并成一个总价值相同的 UTXO。
* 合并操作不能花费资金或更改所有者。
* 合并可以在底层自动完成，不会影响最终用户的体验。

<img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/utxo-merge.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=2fb4f8d2bad662806127ff1c4fb7687f" alt="一次合并会花费 Alice 的五个 UTXO，每个包含 1 USDC，并为 Alice 创建一个包含 5 USDC 的新 UTXO。" width="520" height="270" data-path="images/privacy/utxo-merge.svg" />

要通过一次转账花费全部余额，所需的合并次数取决于该余额包含多少个 UTXO：

| 余额中的 UTXO | 转账前的合并操作 | 转账 |
| - | - | - |
| 1 至 36 | 无 | 一次转账花费所有 UTXO |
| 37 | 合并 2 个 UTXO，执行 1 次 | 使用 36 个 UTXO 的一次转账 |
| 100 | 并行执行 2 次合并，每次合并 36 个 UTXO | 使用 30 个 UTXO 的一次转账 |
| 1,296 | 并行执行 36 次合并，每次合并 36 个 UTXO | 使用 36 个 UTXO 的一次转账 |

每次合并都是一笔带有 ZK 证明的 Solana 交易，最多可将 36 个 UTXO 合并为一个。
由于合并结果是确定性的，因此可以并行生成合并证明和转账证明。

### 合并指令用法示例

你的应用可以在两个时机执行合并：

* \*\*同步私有余额时：\*\*解锁钱包、打开私有钱包、恢复应用、重新连接网络、出现流缺口或恢复钱包时。
* \*\*转账前：\*\*转账需要超过 36 个 UTXO 时。

<Info>
  合并操作无需用户签名即可运行。自定义 Ring 可以设置自己的合并权限。
  使用嵌入式私有钱包时，合并操作会在底层自动为你完成。
</Info>

<Accordion title="Example for Merge">
  例如，一个私有钱包在收到 1,296 笔各为 1 USDC 的私有转账后，在 1,296 个 UTXO 中持有 1,296 USDC。
  一次转账最多可以花费 36 个 UTXO，因此钱包分两个阶段花费余额：

  1. 并行运行 36 笔合并交易，并创建 36 个各含 36 USDC 的 UTXO。
  2. 一笔包含 36 个输入的转账会花费全部 1,296 USDC 余额。

  <Info>
    查看示例代码：[sdk-tests/client/rust/optimized\_merge\_transfer.rs](https://github.com/helius-labs/zolana/blob/1be5fe5c8865badd2852617d18a8f5ca06b592f1/sdk-tests/client/rust/optimized_merge_transfer.rs) · [sdk-tests/client/typescript/optimized-merge-transfer.test.ts](https://github.com/helius-labs/zolana/blob/1be5fe5c8865badd2852617d18a8f5ca06b592f1/sdk-tests/client/typescript/optimized-merge-transfer.test.ts)
  </Info>
</Accordion>

<a id="latency-and-concurrency" />

## UTXO 并发

交易最终确认后，用户即可花费私有余额。

当私有余额分散在多个 UTXO 中时，可以并发花费。每个 UTXO 可以同时在不同的交易中花费。例如，由三个各含 100 USDC 的 UTXO 构成的余额，可以同时为三笔最高 100 USDC 的转账提供资金。钱包会选择要花费的 UTXO。

<img src="https://mintcdn.com/helius/ITnDOhn5GRfQ1FQW/images/privacy/utxo-concurrency.svg?fit=max&auto=format&n=ITnDOhn5GRfQ1FQW&q=85&s=5888bf355ed8aef63ea7cb43c63f0bcd" alt="Alice 的三个 UTXO 各含 100 USDC，可同时为三笔转账提供资金，每笔转账使用一个 UTXO。" width="420" height="200" data-path="images/privacy/utxo-concurrency.svg" />

单个 UTXO 只能花费一次。

有关协议的吞吐量限制，请参阅[状态 Merkle 树和 Forester](/docs/zh/privacy/concepts/architecture#状态-merkle-树和-forester)。

## 了解更多

<CardGroup cols={2}>
  <Card title="Overview" icon="book" href="/docs/zh/privacy/concepts/overview">
    Ring、隐私保证和交易流程。
  </Card>

  <Card title="Architecture" icon="diagram-project" href="/docs/zh/privacy/concepts/architecture">
    钱包、RPC 服务和 Solana 程序如何交互。
  </Card>

  <Card title="Encryption and Privacy Guarantees" icon="key" href="/docs/zh/privacy/concepts/encryption">
    资产的加密方式以及隐私密钥对的作用。
  </Card>

  <Card title="Custom Enterprise Rings" icon="building" href="/docs/zh/privacy/integration/enterprise">
    了解如何配置自定义 Ring。
  </Card>
</CardGroup>

## 没找到您要找的？

<Callout type="info">
  联系我们！[Telegram](https://t.me/tilo_light) | [电子邮件](mailto:sales@helius.xyz) | [联系](https://www.helius.dev/contact)
</Callout>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.