KAPU  

在比特币网络中,一笔交易是如何进行的?本文是笔者的理解,若有错误,欢迎批评指出 QQ:921658495

 

A要转给B十个ETH,首先A需要有10ETH,其次A需要有B的公钥HASH

为什么A需要B的公钥hash?这个问题我们待会再回答,我们先看一下转账是怎么回事.

 

在比特币系统中,是没有账户的概念的,余额没有存在账户中,而是一个叫UTXO的数据结构,

 

 

            UTXO的结构

 

 

  一个地址可以有多个UTXO,每个UTXO上有字段value,可以理解为每个UTXO上都有一个余额,而这个余额就是这个UTXO里有多少钱。

转帐前,我要先验证A确实有10ETH(矿工来验证),如何验证呢?

UTXO集合中是所有未花费输出,找到集合中addrA的地址的UTXO,然后将所有value加起来,就是A的总钱数。

 

 

 

转账时UTXO的变化?

 

  比如说A3张银行卡(3UTXO,每张卡里有50ETH(每个UTXO中的value50)。而A转给B时,并不是将一张银行卡中钱转出到B的银行卡,而是将A的这张卡销毁(UTXOspent字段设为TRUE,表示已花),然后再生成2个银行卡(一个是BUTXO,接受A转给他的10ETH;一个是AUTXO,接受找零的40ETH)。

 

为什么还需要生成一个AUTXO,直接将A之前的UTXO中减去10不行吗?

 

  比特币系统中花费UTXO时,必须一次性花完,花不完需要有一个找零地址,如果没有找零地址,找零的这部分钱就会作为交易费支付该矿工。下面第二个A就是一个找零地址

 

 

 

回到之前的问题,为什么AB转账需要B的公钥hash呢?

 

  刚才说了,转账时,生成目标地址的UTXO,花费转账方的UTXO。那么A如何花费它的UTXO时,是不是需要一些验证呢,如果没有验证,任何人都跑来花费AUTXO

 

那么,如何验证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(一个区块只能有一个)。

如果验证通过,则可以发布到区块链上。

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2020-07-07 15:10  Vegitable_Bird  阅读(2797)  评论(1编辑  收藏  举报