VEX中文网!

比特币交易流程:交易生成、验证、打包、发布

VEX中文网

栏目分类
VEX中文网
DAR中文网
你的位置:VEX中文网 > DAR中文网 >
比特币交易流程:交易生成、验证、打包、发布
发布日期:2025-01-04 18:05    点击次数:175
在比特币网络中,一笔交易是如何进行的?本文是笔者的理解,若有错误,欢迎批评指出 QQ:921658495   A要转给B十个ETH,首先A需要有10ETH,其次A需要有B的公钥HASH 为什么A需要B的公钥hash?这个问题我们待会再回答,我们先看一下转账是怎么回事.   在比特币系统中,是没有账户的概念的,余额没有存在账户中,而是一个叫UTXO的数据结构,                 UTXO的结构       一个地址可以有多个UTXO,每个UTXO上有字段value,可以理解为每个UTXO上都有一个余额,而这个余额就是这个UTXO里有多少钱。 转帐前,我要先验证A确实有10ETH(矿工来验证),如何验证呢? UTXO集合中是所有未花费输出,找到集合中addr为A的地址的UTXO,然后将所有value加起来,就是A的总钱数。       转账时UTXO的变化?     比如说A有3张银行卡(3个UTXO),每张卡里有50ETH(每个UTXO中的value为50)。而A转给B时,并不是将一张银行卡中钱转出到B的银行卡,而是将A的这张卡销毁(UTXO中spent字段设为TRUE,表示已花),然后再生成2个银行卡(一个是B的UTXO,接受A转给他的10ETH;一个是A的UTXO,接受找零的40ETH)。   为什么还需要生成一个A的UTXO,直接将A之前的UTXO中减去10不行吗?     比特币系统中花费UTXO时,必须一次性花完,花不完需要有一个找零地址,如果没有找零地址,找零的这部分钱就会作为交易费支付该矿工。下面第二个A就是一个找零地址       回到之前的问题,为什么A给B转账需要B的公钥hash呢?     刚才说了,转账时,生成目标地址的UTXO,花费转账方的UTXO。那么A如何花费它的UTXO时,是不是需要一些验证呢,如果没有验证,任何人都跑来花费A的UTXO。   那么,如何验证A花费的是属于它的UTXO呢?(涉及到P2PKH)     这里涉及到锁定脚本和解锁脚本,每个UTXO在生成时,都会用这个UTXO的拥有者A的公钥(实际是公钥HASH)进行锁定,比如说A在花费它的UTXO时,A需要用自己的公钥明文和签名进行解锁。解锁过程分两步:1、解锁脚本中A的公钥明文经过HASH160加密后,是否与锁定脚本中A的公钥HASH相等 2、公钥验证通过后,公钥验证解锁脚本中A的签名。如果能解锁成功,说明这个UTXO确实是A的,那么A就可以花这个UTXO了。     到这里A转账给B时为什么需要B的公钥HASH,已经解决,那么问题又来了:A如何获取B的公钥HASH?     我们都知道每笔交易打包时都需要在链上广播,而广播时不就知道B的公钥明文或者hash了吗,确实!但是如果B是新生成的地址,从未进行过任何交易,也从未进行过任何广播,那么A怎样才能知道B的公钥HASH呢?B的地址就是B的公钥HASH的编码,地址和公钥hash是可以相互转换。我们可以看一下地址是如何生成的:       1、随机生成私钥   2、进行SHA256和RIPEMD160两次加密(不可逆)   3、截取前20BYTES得到公钥HASH   4、公钥经过BASE58编码得到地址(类似BASE64,可逆的)   我们看一下一笔交易中的代码体现: 这里的两个输出:实际上是生成了两个UTXO,上面体现的好像不是很明显,下图是在比特币浏览器上截的图       不知道大家有没有注意到,上面验证A是否可以花费这个UTXO时,验证了解锁脚本中的签名,问签名的内容是什么?     签名的内容是这笔交易的内容,ScriptSig是解锁脚本,签名+公钥+指令应该放到这个ScriptSig里面,但是这个键本身就属于交易的一部分,那么岂不是矛盾了吗?看到一个大佬的博客后恍然大悟,签名的内容确实是这笔交易,但签名时把ScriptSig替换成B(接收方)的锁定脚本的内容,然后再对整个交易进行签名,最后再把签名+公钥+指令编码后放在ScriptSig中                     签名前的交易               Scriptsig进行填充,对填充后的交易签名                 签名后,替换到ScriptSig   交易部分基本结束,现在我们知道一笔交易是如何让验证,如何签名,UTXO是如何变化的了。 上面篇幅已经讲了交易生成,接下来将交易打包到区块。 注意,这里不是两个独立的概念,下图中粗略展示了交易和区块的关系     注意:区块链的是不可篡改的分布式账本,他的目的是为了记账,也就是把交易打包到区块链中。 打包过程: A要转给B十个ETH,这笔交易被广播到比特币网络上,所有矿工节点接收到后,先对这笔交易进行合法性验证,也就是上文中的签名,脚本等。 验证通过的话,将这笔交易放在矿工本地的chainstate中(可以理解为临时存放区),然后矿工从chainstate中挑选出一些交易,优先挑选交易费高的,但不能太多,区块容量不能超出1M。 然后将这些交易构造成merkel tree,计算出这颗tree的root hash,再加上version、previous_hash(前一个区块头Hash)、target(目标阈值)、timestamp(时间戳)还有nonce(随机数),上面这6个值一起进行HASH运算,要求得到的运算出的HASH<=target,如果不满足,变换nonce,继续进行HASH运算,这个过程就成为挖矿。 直到满足HASH<=target,说明找到了满足要求的nonce,也就是挖到矿了。 然后矿工节点将上面这些数据按照区块的数据结构打包成一个区块,广播至其他节点进行验证,其他节点验证时主要验证块结构、是否满足挖矿难度、时间戳、merkel tree root hash、块大小、coinbase(一个区块只能有一个)。 如果验证通过,则可以发布到区块链上。