00 · Orientation
先别问“哪一种更先进”
先问:一条链要用什么最小数据,证明价值没有被凭空复制?
“UTXO 模型”和“账户模型”不是两种界面,也不是钱包的两种皮肤。 它们是协议对当前状态是什么、一笔交易改了什么的两种回答。
一条价值网络至少要连续回答四个问题:现在谁有权花什么?一笔新请求是否得到授权? 同一份价值有没有被用过?按确定顺序处理后,新状态是什么? 比特币把答案组织成“仍未被花掉的交易输出”;以太坊把答案组织成“地址映射到的账户状态”。
谁能动用价值?
UTXO 看某个输出的解锁条件是否满足;以太坊通常从签名恢复交易发送者,再查该地址的账户状态。
怎样阻止重复使用?
UTXO 一经消费就从可花集合移除;账户交易必须使用发送者当前期待的 nonce。
价值从哪里到哪里?
UTXO 检查输入总额与输出总额;账户模型直接修改发送者、接收者及费用相关账户的状态。
节点如何核对结果?
节点按协议重算状态并核对区块承诺;模型不同,“相信提议者给答案”都不是验证。
UTXO 模型管理的是可花费对象的集合; 账户模型管理的是持久对象的当前状态。 后面所有差异,都可以从这句话推出来。
01 · UTXO model
比特币没有“从余额里扣一点”
它消费旧输出,再创建一组全新的输出。
UTXO 是 Unspent Transaction Output,即“未花费交易输出”。
一个输出包含价值数量与花费条件;它由上一笔交易的
txid 和输出序号 vout 唯一定位。
输入引用旧输出,并提供满足其锁定条件的数据。[1]
如果钱包说“你有 1.20”,协议并没有保存一行 Alice = 1.20。
钱包找到所有由你的密钥或脚本条件可以解锁的 UTXO,再把数额相加。
所谓“余额”是钱包从可花输出集合推导出的视图。
一笔 UTXO 交易的骨架
Inputs · 消费旧输出
Outputs · 创建新输出
Σ inputs 1.20 u− Σ explicit outputs 1.19 u= fee 0.01 u
为什么必须“整张花掉”?
一个 UTXO 是不可拆分地被引用和消费的对象。假设你只有一张 1.00 u 的输出,要付 0.60 u,
交易会消费整张 1.00 u,再创建“给对方 0.60 u”和“给自己找零(扣除费用后)”两个新输出。
原来的 1.00 u 输出不再可花;找零拥有新的 txid:vout。
输入必须指向当前仍存在的 UTXO。如果它已在规范历史中被消费,新交易就不能再次消费它。
解锁数据必须满足旧输出的花费条件。“控制地址”只是钱包层的简写,协议真正检查的是脚本条件。
普通交易不能让输出总额超过输入总额。输入减去输出的差额构成交易费。[2]
钱包要做 coin selection。它选择哪些 UTXO 作为输入,会影响费用、找零、隐私与以后可花输出的形状。
UTXO 不属于某个协议级账户对象。它是带花费条件的离散输出。 地址复用、钱包标签和“我的总余额”都是在这组输出之上的组织方式。
02 · Account model
以太坊保存的是一张“地址 → 状态”映射
账户会持续存在,交易直接更新它的当前字段。
以太坊执行层把世界状态抽象为 σ。给定一个地址
a,σ[a] 返回该地址当前的账户状态。
经典账户记录由 nonce、balance、storageRoot、codeHash
四个字段组成。[3]
对一个地址做“状态 X 光”
- nonce
- 7
- balance
- 2.100000 ETH
- storageRoot
- 0x56e8…b421 · empty
- codeHash
- 0xc5d2…a470 · keccak256(0x)
Interactive · account x-ray
点一个字段,看它解决什么问题
nonce · 账户顺序计数器
对普通外部账户,它约束下一笔可执行交易的序号。某个 nonce 在一条规范状态序列中只能被使用一次,因此旧签名不能无限重放。
最简单的 ETH 转账改了什么?
先忽略 Gas 的精确结算:发送者余额减少,接收者余额增加,发送者 nonce 增加。 它不是消费一张“2.10 ETH 输出”再创造找零;它是在同一张状态映射里更新几个账户记录。 真实交易还会检查签名、链标识、nonce、费用上限与余额,并按执行结果结算 Gas。 这些字段将在第 6、7 章完整展开。[4]
- Alice.balance
- 2.10
- Alice.nonce
- 7
- Bob.balance
- 0.35
- Alice.balance
- 1.29
- Alice.nonce
- 8
- Bob.balance
- 1.15
账户是链上状态实体;钱包是生成密钥、签名和展示资产的工具或界面。 一个钱包可以管理多个外部账户,也可以操作智能账户。把两者分开,后面理解助记词与合约钱包会更清楚。
Pectra 升级中的 EIP-7702 允许由密钥控制的账户把关联代码设置为一个委托指示器; 当目标地址存在代码时,调用可按该目标代码执行。 所以“EOA 的 codeHash 永远为空”已不再是绝对规则。它扩展的是账户执行能力, 并没有把以太坊改成 UTXO 模型;授权与安全边界留到本章后续账户课程再展开。 [7]
03 · Payment lab
拖动金额,看两种模型各自改哪里
最终可用价值可以相同,状态转换的路径完全不同。
Alice 起初有三枚可花 UTXO:0.40、0.70、1.00 u;在账户模型里,她的余额是 2.10 u。 Bob 起初有 0.35 u。每次实验把费用固定为 0.01 u,只隔离观察状态模型。
实验中的教学钱包先选择输入枚数最少的组合,再选择总额最接近付款需求的组合。 真实钱包的选币策略并不由比特币协议统一规定,还会权衡实际字节费用、隐私、确认状态与 UTXO 碎片。
Interactive · one payment, two states
Alice 向 Bob 支付
u 是教学单位。实际 BTC 以 satoshi、ETH 以 wei 记账;两条链的费用机制也不同。
UTXO · 选择并消费输出
input 1.005a…:0 0.70 u
91…:1 1.00 u
c8…:0
Account · 原地更新字段
fee 0.01你应该从实验里看见三件事
UTXO 会留下交易图。新输出明确引用旧输出形成的输入;价值沿 outpoint 关系流动。
账户模型会留下状态序列。同一个地址的余额与 nonce 随有序交易持续变化。
总额相同不代表数据相同。Alice 最终可用 1.29 u;一边由三枚 UTXO 的剩余集合推导,一边直接是账户余额字段。
04 · Validity
一个检查 outpoint,一个检查 nonce 与账户状态
两者都拒绝相互冲突的状态转换,但有效性条件不是一一对应。
双花不是“链上出现负余额”这么简单。它是两份候选交易试图让同一份旧授权产生两次有效后果。 UTXO 模型让冲突聚焦于同一个 outpoint;账户模型让冲突聚焦于同一发送者状态下的 nonce 与余额。
Interactive · collision
先执行 A,还是先执行 B?
UTXO conflict · 同一 outpoint
Account conflict · 同一 nonce
现实网络里,两份冲突交易可能暂时存在于不同节点的交易池、发生替换,或落在竞争分支。 关键不是“第二份永远不会传播”,而是同一条规范状态序列不能让它们依次都成功。 UTXO 被消费后不再存在;账户 nonce 前进后,旧 nonce 不再匹配。
| 验证问题 | 比特币 UTXO | 以太坊账户 |
|---|---|---|
| 授权对象 | 被输入引用的旧输出及其锁定条件 | 发送者地址恢复出的账户与交易签名 |
| 防重复 | outpoint 必须仍在 UTXO 集合中 | nonce 必须等于发送者当前期待值 |
| 余额检查 | 输入总额必须覆盖输出总额 | 发送者余额必须覆盖价值与协议要求的费用边界 |
| 失败后的对象 | 无效交易不会消费输入 | 已被区块纳入且执行回滚的交易通常仍消耗 Gas,发送者 nonce 仍前进 |
| 依赖关系 | 显式写在输入引用的 outpoint 上 | 隐含在账户 nonce、余额与合约读写状态中 |
它不表示交易几点发生,也不保证全球交易按地址排序。 它只在相关账户的同链状态转换中提供顺序与一次性约束;区块内的全局交易顺序仍由区块明确给出。 防止普通签名交易跨链重放还需要 chain ID,不能把所有重放保护都归功于 nonce。
05 · Contracts
账户模型为什么适合“持久程序”
合约地址像一个长期存在的对象:代码与存储可以被下一次调用继续读取。
以太坊不只转移 ETH。一个合约账户可以在地址上关联代码与持久存储; 交易调用它时,EVM 读取当前世界状态,执行代码,再把余额、存储、日志等结果写入新的世界状态。
这让“调用 A 合约,A 再调用 B,B 读取 C 的余额”可以在同一笔交易的原子执行里发生。 所有对象共享同一个执行状态语境,成功则一起提交,异常则按 EVM 规则回滚相应状态。 账户模型因此很自然地表达可组合的持久对象。
但不要得出“UTXO 不能有合约”
比特币输出本身就带脚本化花费条件;其他系统还发展出扩展 UTXO 等不同合约设计。 真正差异不是“能不能编程”,而是程序的状态放在哪里、下一次执行引用什么对象、 多个程序怎样组合。账户模型以持久地址和共享可变状态为中心;UTXO 风格以显式消费旧状态、创建新状态为中心。
第 8 章讲 EVM 时,你会看到代码如何操作 Stack、Memory 与 Storage; 第 9 章讲合约生命周期;第 11 章再拆世界状态与 trie。 本课只先回答:为什么这些持久状态天然被组织到“账户”上。
06 · Trade-offs
不是优劣榜,是一组工程取舍
对象边界、并行性、隐私、钱包复杂度与合约表达能力相互牵动。
UTXO 的自然优势
- 依赖显式:输入直接指出要消费哪些旧输出,互不重叠的交易更容易看出独立性。
- 局部证明清楚:验证焦点是特定 outpoint 是否存在、脚本是否满足、总额是否守恒。
- 可换地址:钱包可以把新输出发往新地址,减少长期复用单一地址;但交易图仍可能被聚类分析。
- 状态是一次性的:旧输出被消费后退出集合,不存在“原地修改同一枚输出”。
账户的自然优势
- 余额直观:协议状态直接记录地址的当前余额,简单转账不需要 coin selection 与找零输出。
- 持久对象自然:合约代码与存储附着在地址上,下一次调用可继续使用同一状态。
- 同步可组合:多个合约在同一交易中读写共享状态,易于表达 DeFi 等原子流程。
- 代价是争用:同一账户 nonce 和热门合约状态会形成顺序依赖,需要执行层精确管理读写冲突。
| 维度 | UTXO 模型 | 账户模型 |
|---|---|---|
| 当前状态 | 所有仍未花费输出的集合 | 地址映射到的账户及合约存储 |
| “余额” | 钱包对可控制 UTXO 求和得出 | 账户记录中的协议字段 |
| 付款动作 | 消费整枚旧输出,创建付款与找零输出 | 更新发送者、接收者和费用相关状态 |
| 顺序约束 | 输入必须引用尚未消费的 outpoint | 发送者交易 nonce 必须连续匹配 |
| 并行边界 | 不相交输入让独立性更显式,但不自动等于更高吞吐 | 不相交状态访问也可并行,但共享账户与存储带来冲突分析 |
| 隐私形态 | 新地址有帮助;找零与交易图启发式仍可关联 | 长期地址活动容易聚合;新地址也不自动切断资金图谱 |
| 合约状态 | 通常通过消费旧状态输出、创建新状态输出表达 | 代码与可变 storage 持久附着在地址上 |
| 钱包工作 | UTXO 发现、选币、找零、费用与碎片管理 | nonce 管理、Gas 估算、授权与合约交互 |
“UTXO 天生可以无限并行。”
不准确。互不引用同一输出让依赖更显式,但区块验证、脚本成本、父子交易与共识规则仍形成边界;模型本身不赠送无限吞吐。
“账户模型一定只能串行执行。”
也不准确。没有状态冲突的交易可以被并行化研究或实现;困难在于预先识别动态合约调用的真实读写集合,并保持与规范顺序完全相同的结果。
“UTXO 就匿名,账户就实名。”
两者通常都是假名系统。UTXO 的找零识别、共同输入等启发式会暴露关联;账户地址复用会聚合活动。隐私取决于完整使用方式,不取决于一个标签。
“账户余额简单,所以钱包安全也简单。”
账户模型省去了找零与选币心智负担,却引入 nonce、Gas、代币授权、合约调用与签名语义等新风险。界面简单不等于授权边界简单。
07 · Recap
把整课压缩成两句话
先抓住对象,再抓住状态转换。
- 01
UTXO 是一次性对象。输入消费旧输出,交易创建付款与找零等新输出。
- 02
UTXO 余额是推导值。钱包把自己能解锁的未花输出求和。
- 03
以太坊账户是持久状态。地址映射到 nonce、余额、存储根与代码哈希等字段。
- 04
账户交易原地更新逻辑记录。简单付款改变余额与发送者 nonce,不创建“找零账户”。
- 05
两者都防重复授权。UTXO 检查 outpoint 仍未花费;账户检查 nonce 与当前状态匹配。
- 06
账户模型利于持久合约组合。代码与 storage 附着于地址,可在同一原子交易中跨合约读写。
- 07
模型不是性能或隐私的单变量答案。真实结果还取决于执行、共识、钱包策略和使用习惯。
- 08
执行回滚不等于交易没发生。已纳入区块的有效账户交易即使调用回滚,发送者 nonce 通常仍前进并支付实际 Gas。
现在检查你的理解
1. 比特币钱包显示 1.20 BTC,协议层最准确的解释是什么?
2. 用 1.00 u 的 UTXO 支付 0.60 u 时,剩余价值通常怎样处理?
3. 账户交易的 nonce 主要解决什么?
4. 账户模型为什么自然适合以太坊合约?
5. “UTXO 依赖显式”能直接推出什么?
6. 一笔以太坊交易被区块纳入,但合约执行随后回滚,通常会怎样?
08 · Sources
术语与一手资料
先建立可靠心智模型,再进入地址、签名、交易与 Gas 的实现细节。
核心术语
UTXO UNSPENT TRANSACTION OUTPUT
尚未被任何规范交易输入消费的交易输出;包含价值数量与未来花费条件。
Outpoint TXID + VOUT
由交易标识与输出序号组成,唯一指向某笔旧交易里的具体输出。
找零输出 CHANGE OUTPUT
消费的 UTXO 超过付款与费用时,交易为付款者创建的新输出;它不是原 UTXO 的“剩余余额”。
世界状态 WORLD STATE
以太坊执行层在某一时刻的全部账户状态逻辑集合,包括余额、nonce、代码与合约存储承诺等。
Nonce ACCOUNT SEQUENCE
账户状态中的计数器。对普通 EOA,它约束下一笔可执行交易的序号并帮助防止签名交易被重复执行。
状态转换 STATE TRANSITION
节点按协议规则,从旧状态和有序交易输入计算新状态的过程。
官方一手资料
-
01
Bitcoin Developer Guide — Transactions 输入如何引用旧输出、输出怎样成为 UTXO,以及找零输出的基本机制。
-
02
Bitcoin Developer Guide — Block Chain UTXO / 已花输出分类、输入输出价值约束与费用差额。
-
03
ethereum.org — Ethereum accounts 账户类型、nonce、balance、storageRoot、codeHash 与钱包/账户边界。
-
04
ethereum.org — Transactions 签名交易字段、nonce、价值、费用参数与交易生命周期。
-
05
Ethereum Yellow Paper 账户状态四字段、交易有效性与执行状态转换的形式化基线;分叉细节应同时核对当前执行规范。
-
06
Ethereum Execution Layer Specification 当前执行层分叉规则与状态转换的可执行规范来源。
-
07
EIP-7702 — Set Code for EOAs 进阶注脚:为什么 Pectra 后不能再绝对假设密钥控制账户的代码字段为空。
本章下一课将把“外部账户 EOA:由谁控制、怎样主动发起交易”单独拆开。 到那时再深入私钥、签名恢复、地址与交易发起权;现在先确保你能用自己的话解释 “消费输出”与“更新账户”究竟差在哪里。