logo NodeSeekbeta

BTC经典算法(UTXO交易模型)

本帖仅做科普向,不推荐任何人参与挖矿/区块链交易等行为

因为暂时还没找到稳定的图床,下面有一部分 类似于图的部分是使用gpt进行生成的,全文已经过人工校对,可放心食用

OK,之前我们了解了BTC链的交易结构,以及POW在其中的作用,那接下来我们来聊点 成人向的东西 ,比如这玩意的具体交易模型,以及这玩意为什么那么吸引大家参与进来

接下来我觉得很有必要和大家说清楚一个名词: 去中心化系统。

去中心化,意思是,整个系统中压根没有一个“负责人”这样的角色,举个反义词就是中心化系统,实际例子就比如我们天天都在刷的抖音、支付用的支付宝、以及各种各样的电商网站。在这些中心化系统中,往往是有一个绝对权威的机构来控制着每个用户的权限和数据,比如抖音能决定下一秒给你推送什么样的视频,支付宝里存着你的银行卡身份证等信息、电商网站有你的购买记录,和店家的聊天记录......在这些中心化的系统中,中心化的机构有权对数据进行直接修改,也可以手动收回用户的部分权限(参考抖音的禁言功能和删除违规视频功能)

那么很显然,去中心化系统就是上述中心化系统的反义词,简单来说,整个系统中不存在一个绝对的“负责人”(或者也可以叫做领导者),并且,参与者(也可以叫做节点)中允许存在想搞破坏的恶意节点,在这类系统中,一般想要正常稳定运行,离不开两样东西: 共识机制+数学信任,参与者和用户并非信任系统中的某个节点,而是信任的是整个系统中的运行算法,以及共识节点数量远多于异常节点。这点是和中心化系统最大的不同,中心化系统能够稳定运行靠的是用户对中心机构的信任(举个例子,如果第二天支付宝宣布自己想随便改几个用户的余额,那么大家肯定也不会再用支付宝了),在去中心化系统中,大家信任的是系统稳定运行的共识算法以及背后的数学定理。

当然,中心化和去中心化并非孰优孰劣,而是看取舍问题,举个最简单的例子(以村子中新开的银行为例):

中心化举例: 假设A村开了家银行,账本除了银行工作人员谁也看不着,村民们存款取款转账都通过柜台和手机银行进行,每次有转账消息,银行柜员处理速度很快就完成了账本上的记账工作,但是村民没有权限查看转账记录。有一天,银行柜员起了贪心,把村民B账上的10000元偷偷往自己账户转了100元,村民B也看不着账本,也只能听银行说,自己账上有多少就是多少了

去中心化举例: 假设B村开了家银行,B村银行把账单都分发给每个村民,村民A给村民B的时候需要向全村所有持有账本的人广播一条转账消息: 村民A向村民B转账xxx元,附带村民A和村民B的手印。然后全村每个人都去查看一下村民A和村民B的手印是否对得上转账消息中提到的手印信息,等待全村超过半数的村民都确认无误之后,此条转账消息才会被正式写入每个收到消息的村民的账本。假设某天银行柜员手里缺钱了,他在自己的账本上写“村民A向我转账100元”,但是在广播之后,所有村民验证消息中并没有村民A的手印,纷纷都拒绝记录了此次的转账请求,贪心的柜员最终还是没能成功修改账本

总结一下就是: 中心化系统的吞吐量一般会比去中心化的吞吐量高很多,但去中心化系统的数据有天然的防篡改优势。

讲了这么一堆,回到主题,其实去中心化系维持稳定性除了上文我们提到的,在逻辑方面需要有绝对的正确性,还需要另一件事: 吸引到足够多的节点加入进来维护整个网络。既然需要吸引节点(或者说吸引人)参与进来,那么最直接的方式往往是和利益挂钩,而这个机制后来在区块链中被称为奖励机制,我们今天以BTC的UTXO模型为例来深入讲讲。

在BTC中,每个地址有多少钱并不是像传统的银行账户那样,简单只表示一个数字,而是采用十分严谨的方法进行表示的: 你所拥有的钱=你能支配的所有没花费的UTXO的总值,其中每个UTXO的产生都是基于每次交易: 单次交易中,输入为支付方已解锁的UTXO(对没错,你可以把UTXO看做一组带着金额的脚本),输出为待解锁的UTXO

举个最简单的例子,假设现在A手里有一个价值10 BTC的UTXO,现在A想给B转3 BTC,那么A并不是像我们使用支付宝一样,在数据库中进行这么一个操作:

A.balance -= 3

B.balance += 3

而是会直接把自己手里这个10 BTC的UTXO整个花掉,然后产生两个新的UTXO:

UTXO 1: 3 BTC,解锁条件由B控制

UTXO 2: 7 BTC,解锁条件还是由A自己控制

第二个UTXO其实就是我们平时说的“找零”。当然实际交易中还需要考虑矿工费,所以严格来说第二个UTXO肯定会小于7 BTC,不过这里我们暂时先忽略手续费,免得刚开始就把事情搞得太复杂。所以一笔BTC交易的过程其实非常像你拿着一张100块的人民币去便利店买一瓶3块钱的可乐,你不会把这张100元纸币撕掉3%交给老板,然后把剩下97%的纸币揣回兜里,而是把整张100块交出去,然后老板再找给你97块。

UTXO也是类似的道理:

旧UTXO -> 被完整消费 -> 产生若干个新的UTXO

这里需要特别注意一个很容易产生误解的地方: UTXO并不能解决“双花竞争”本身。

比如A手里有一个10 BTC的UTXO,那么理论上A完全可以同时构造两笔交易:

交易1: 把这个10 BTC的UTXO支付给B

交易2: 把这个10 BTC的UTXO支付给C

这两笔交易单独拿出来看,签名都可能是完全正确的。

真正决定这10 BTC最终被谁拿走的,是我们之前聊过的区块链共识和交易顺序。假设交易1最终被打包进了被全网接受的链,那么这个10 BTC的旧UTXO就已经被标记为了“已花费”,交易2再想花它的时候,节点一查自己的UTXO Set:

这玩意呢?

哦,已经没了。

那你还花个锤子。

于是交易2自然就成了一笔无效交易。

所以大家千万不要把UTXO理解成一种“防止双花的黑科技”,它更像是BTC用来描述当前有哪些钱还可以被花的一种数据模型。

换句话来说,在BTC的世界里,并不存在一个叫做:

A的余额 = 10 BTC

这样的核心状态。

真正存在的是:

UTXO 1 = 2 BTC,A可以解锁

UTXO 2 = 3 BTC,A可以解锁

UTXO 3 = 5 BTC,A可以解锁

然后钱包软件帮你算了一下:

2 + 3 + 5 = 10 BTC

最后在钱包界面上非常贴心地显示:

余额: 10 BTC

所以你看到的“余额”,实际上只是钱包替你统计出来的结果。

那么到这里就出现了一个很有意思的问题:

既然一个UTXO一定来自某一笔交易的Output,那么最开始的那个UTXO是从哪来的?

这就有点像你问:

我手里的这100块是我老板发给我的;

老板的钱是客户付给他的;

客户的钱又是银行取出来的;

那么继续一路往前查,第一张钱到底是谁给的?

如果BTC里面每个UTXO都必须来自上一笔交易,那么我们沿着交易记录一路往前扒:

UTXO <- Transaction Output <- Transaction Input <- 更老的UTXO <- 更老的Transaction...

总得有个祖宗吧?

总不能中本聪在创世区块里面写一句:

余额初始化 = 2100万BTC

然后大家鼓掌通过。

实际上,这个“祖宗”就是一个非常特殊的交易:

Coinbase Transaction(Coinbase交易)。

注意这里说的Coinbase和那个叫Coinbase的加密货币交易所没有什么直接关系,只不过名字恰好一样而已。

每当矿工成功挖出一个新的区块时,这个区块里面都会存在一笔非常特殊的交易,一般位于区块交易列表的第一笔。

普通交易的结构大概是:

旧UTXO -> Input -> Transaction -> Output -> 新UTXO

但Coinbase交易就很离谱了,因为它没有正常意义上的“上一笔UTXO输入”。

也就是说,普通交易需要回答:

你这笔钱从哪来的?

而Coinbase交易可以非常嚣张地回答:

协议让我生成的。

当然,并不是说矿工想写多少就写多少。

矿工能够在Coinbase交易中领取的最大金额,本质上由两部分组成:

区块补贴 + 当前区块所有交易的手续费

其中区块补贴,就是BTC中新币进入流通的主要方式。

比如某个时期协议规定每挖出一个区块可以获得3.125 BTC的区块补贴,同时这个区块里面所有普通交易一共产生了0.2 BTC手续费,那么矿工最多就可以通过Coinbase交易产生:

3.125 + 0.2 = 3.325 BTC

的输出。

这里其实也顺便解释了BTC为什么能够吸引这么多人拿着真金白银买矿机、交电费,然后疯狂计算Hash。

因为你算赢了,不仅获得了记账权,还能按照协议规则获得BTC作为奖励。

而且这个奖励并不是某个“BTC公司”从自己的账户里面转给你的。

因为压根就没有什么BTC公司。

它是所有节点在验证区块时共同认可的一条规则:

只要你按照规则成功产生了合法区块,那么这个区块的Coinbase交易就允许产生规定数量的新BTC,并把它锁定到你指定的花费条件上。

于是一个全新的UTXO就这么诞生了。

所以如果我们一路追溯某一枚BTC的来源,会看到一个很有意思的结构。

假设现在你钱包里面有一个0.1 BTC的UTXO。

它可能来自别人给你的一笔转账,而别人当时花掉的UTXO又来自另一笔交易,再继续向前找,又能找到更早的交易……

一直追、一直追。

最终这条资金来源链条一定会落到某个历史区块中的Coinbase交易产生的输出上。

也就是说:

Coinbase Output

↓

被某人消费

↓

产生新的UTXO

↓

再次被消费

↓

产生新的UTXO

↓

......

↓

最终来到你的钱包

所以从这个角度来看,BTC里面的“钱”其实从来没有像银行账户余额一样被搬来搬去。

BTC真正不断发生的是:

旧UTXO被销毁,新的UTXO被创造。

而Coinbase交易,则是整条UTXO链条最开始那个允许“凭空产生”的特殊起点。

但是问题又来了。

既然矿工刚挖出区块,就已经通过Coinbase交易拿到了奖励,那矿工是不是下一秒就能把这笔BTC转到交易所,直接卖掉换台4090,然后美滋滋回家打游戏?

并不能。

BTC协议还专门给Coinbase交易产生的UTXO上了一把锁。

Coinbase产生的UTXO必须经过100个区块的成熟期之后,才能作为Input被后续交易消费。

这条规则一般被称为:

Coinbase Maturity。

为什么要这么干?

这里就引出经典的区块链分叉问题了。假设矿工A刚刚挖出了区块100:

Block 99 -> Block 100(A)

A非常开心,在Block 100的Coinbase交易里面获得了自己的挖矿奖励。

但是大家应该还记得,在去中心化网络里面,“你挖出了一个区块”和“这个区块永远成为历史”其实是两码事。

还记不记得,上一篇帖子中我们提到过,BTC的出块时间是10分钟左右?在顶级算力的加持下,可能同一时间窗口内,远在地球另一边的矿工B可能也挖出了另一个高度100的区块:

-> Block 100(A)

Block 99 ----|

-> Block 100(B)

这时候网络就出现了一个短暂分叉。

有些节点先收到A的区块,于是暂时沿着A继续挖。

有些节点先收到B的区块,于是暂时沿着B继续挖。

接下来如果B这条分支积累了更多工作量,最终成为节点接受的最佳链,那么A挖出来的Block 100就会被从当前主链历史中重组出去。

问题来了:

A那个Coinbase奖励怎么办?

答案很简单:

没了。

因为那笔Coinbase交易本来就是Block 100(A)的一部分。

现在Block 100(A)都不属于当前有效链了,它里面凭空创造出来的Coinbase UTXO自然也不能继续存在。

所以我们这时候再看,这时候假设BTC允许矿工刚挖出Coinbase就马上消费,会发生一种很麻烦的情况。

比如:

Block 100(A)

产生:

Coinbase UTXO = 3.125 BTC

然后A立刻花掉这3.125 BTC:

Coinbase UTXO -> 转给C

C又马上花:

C -> D

D又继续花:

D -> E

结果过了一会:

Block 100(A)

因为链重组被踢出去了。

那整个资金链最底下的祖宗突然没了。

既然最开始的Coinbase UTXO不存在,那么所有依赖它的后续交易自然也就失去了有效的资金来源。

于是:

Coinbase

↓

A -> C

↓

C -> D

↓

D -> E

这一串交易都会受到影响。

所以BTC干脆规定:

Coinbase刚出生的时候先别急着花,等它在链上待够100个区块再说。

注意,这里经常有人会说成“需要100次确认”,这么理解日常交流问题不大,但是如果严谨一点说,是Coinbase Output在满足协议规定的成熟高度之后才能被消费。

而且这个100并不是说:

等100个区块以后,这个区块就获得了数学意义上的绝对不可逆。

并不是。

只要发生足够深的链重组,理论上历史依然可能改变。(只不过这样花费的代价远高于收益)

100个区块的Coinbase成熟期,本质上是一条协议强制规定的安全缓冲区。

它把“刚刚产生、还处在比较容易受到链重组影响位置上的挖矿奖励”和“已经可以正常流通的UTXO”隔离开。

所以一个矿工刚挖出区块时,他实际上处于一种非常微妙的状态:

奖励已经属于这个区块

但:

暂时不能花

等后面继续出现:

Block N

↓

Block N+1

↓

Block N+2

↓

......

↓

Block N+100

随着这段历史不断被后续区块压在下面,这笔Coinbase Output才满足成熟条件,可以像普通UTXO一样被拿出来作为交易Input使用。

到这里,我们其实已经把BTC里面“钱从哪里来,又是怎么流动的”串起来了:

矿工通过POW竞争获得新区块的记账权

↓

新区块中的Coinbase交易按照协议规则产生新的UTXO

↓

Coinbase UTXO经过100个区块的成熟期

↓

成熟后的UTXO可以被矿工正常消费

↓

消费旧UTXO产生新的UTXO

↓

新UTXO继续被别人消费

↓

周而复始

所以BTC所谓的“转账”,从底层来看,其实压根不是:

把账户A里面的数字减掉,再给账户B里面的数字加上去

而更像是:

证明我有权花掉某几个现存的UTXO,然后销毁它们,再按照新的花费条件创造出一组新的UTXO。

而整个BTC网络维护的核心状态之一,就是:

现在到底还有哪些UTXO没有被花掉。

你钱包里面显示的“余额”,只是这些UTXO在人类世界中的一种更加方便理解的表现形式罢了。

至于每一个UTXO为什么能证明“这个钱归你控制”、所谓的“解锁脚本”到底解锁了个什么东西、以及BTC为什么可以做到没有账户、没有登录、没有服务器给你鉴权,却依然能够证明“这笔钱你能花,别人不能花”——简单来说就是基于我们第一篇讲的,非对称加密和数字签名了,

前面我们一直说,可以把UTXO理解成“一笔带着金额和解锁条件的钱”,这里所谓的解锁条件,实际上就是写在Transaction Output里面的一段程序,也就是我们经常说的锁定脚本(ScriptPubKey)。

一笔交易的Output大概可以理解成:

Output = 金额 + 锁定脚本

比如A给B转了一笔BTC,那么新产生的UTXO并不会简单写成:

这笔钱属于B

而是更加严谨地写成类似:

这里有1 BTC,任何想花掉它的人,都必须提供能够满足下面这段脚本的数据

这段脚本就是锁定脚本。

等到B未来想花掉这个UTXO的时候,就需要在新的交易Input中提供对应的解锁数据。对于传统的P2PKH交易来说,可以简单理解成提供:

数字签名 + 公钥

然后节点会把Input提供的数据和之前那个UTXO的锁定脚本放在一起验证,大概可以理解成:

解锁数据 + 锁定脚本 -> 执行Bitcoin Script -> True / False

如果最后执行结果为True:

✓ 你提供的公钥符合这个UTXO要求

✓ 你的数字签名能够被这个公钥验证

那么节点就认为:

OK,你满足这个UTXO规定的花费条件,这笔钱可以被你花掉。

反之,如果你只是看见链上有个价值100 BTC的UTXO,眼馋得不行,直接拿自己的私钥给交易签个名:

我宣布这100 BTC现在归我了.jpg

节点在验证的时候就会发现,你提供的公钥压根不满足这个UTXO原本规定的锁定条件,脚本最终执行失败,这笔交易自然也就是无效交易。

所以严格来说,BTC里面其实并不存在传统意义上的:

这个地址拥有1 BTC

更加准确的说法应该是:

链上存在一个价值1 BTC的UTXO,而某个人掌握着能够满足这个UTXO锁定条件所需要的私钥。

这也是为什么我们经常会听见一句话:

Not your keys, not your coins.

私钥本身并不是“BTC”,钱包里面也没有真的存着BTC。

真正的BTC状态记录在全网共同维护的区块链和UTXO Set里面,而你钱包真正需要替你保管的,是能够构造有效签名、从而满足这些UTXO花费条件的私钥。

当然,上面为了方便理解,把它描述成了“锁定脚本 + 解锁脚本”。BTC实际发展到今天以后,不同输出类型的具体结构已经有所区别,比如P2PKH、P2SH、SegWit以及Taproot在“我要提供什么数据才能花掉这个UTXO”这件事上的结构并不完全一样。

不过它们背后的核心思想其实没有变:

创建UTXO时:规定以后满足什么条件才能花

↓

消费UTXO时:提供满足这些条件的数据

↓

节点执行验证

↓

True -> 允许消费

False -> 拒绝交易

所以所谓的“这笔BTC属于你”,从BTC协议自己的视角来看,并不是链上某个数据库写了一行:

owner = 你的名字

而是:你拥有满足这笔钱花费条件的能力。

总结:

换句话说,在BTC的世界里,“拥有一笔钱”这件事,本质上并不是某个机构承认这笔钱属于你,而是你能够用密码学证明,自己确实有资格花掉它。

而当你真正花掉它以后,旧的UTXO消失,新的UTXO产生,所有节点按照同样的规则验证这次状态变化是否合法,然后等待矿工把它打包进新的区块。

这样一来,我们前面聊过的东西其实也就慢慢串起来了:矿工通过POW竞争新区块的记账权,通过Coinbase获得维持整个网络运行的经济奖励;UTXO负责描述BTC中的钱究竟以什么样的形式存在、又是怎么从一个人手里流转到另一个人手里;而非对称加密和数字签名,则负责证明“你到底有没有资格花掉这笔钱”。

整个过程中,并没有一个叫做“BTC银行”的中心服务器在后台维护每个人的账户余额,也没有哪个管理员负责审核你的转账。有的只是所有节点共同遵守的一套规则:

你的交易满足规则 -> 接受

你的交易不满足规则 -> 拒绝

至于你是谁、你叫什么名字、你住在哪里,协议压根不关心。它只关心一件事:

你能不能证明,这笔钱你有资格花。

而这,差不多就是BTC的UTXO模型想要解决的事情了。

到这里,我们也算是从一笔普通的BTC转账,一路顺着UTXO往前扒到了矿工的Coinbase,又从Coinbase绕回到了私钥和数字签名。

至于为什么后来有些区块链没有继续采用UTXO,而是选择了另一套完全不同的Account账户模型,以及这两套模型到底有什么区别——
那就是后面的事了。
这篇先到这里,收工。

  • 什么时候讲到 dapp ac13

  • 下一次可能就开始从ERC20和ERC721开始讲了,ETH的记账模型和Solana的底层可能得往后稍稍,已经尽力在把区块链的技术分析做得通俗易懂了,大家有什么不懂的也可以直接在帖子下留言捏,不过涉及到挖矿和币链交易的这些留言恕不回答,本帖只做技术交流答疑解惑用,不具有其他投资参考作用

  • @owowula2 #1 到时候看吧,这块涉及到预言机,链上链下交互的东西,要准备的东西有点多,准备到时候一起把defi讲了

  • ai总结?

  • @Mileszz #5 开头提到了捏,总结只是gpt帮忙分段,然后把部分流程图内容转换为md格式内容

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有72019位seeker

🎉欢迎新用户🎉