bitcoin 源码解析 - 交易 Transaction(二) - 原理篇我超级懒的|向罪恶资本主义抗争的共产主义斗士 这篇文章我断断续续写了呃···· 应该快三个星期了? 所以前后的风格可能差别相当大。真是十分的怠惰啊··· 最近实在是不够努力。用python重写bitcoin的项目也卡在网络编程部分(这方面真是我的软肋) 这篇文章通篇都是文字-_-, 没有其他东西,这个样子给读者会造成很大的压力吧···· 虽然题目所说的是原理,但是实际上一部分原理已经在前面几篇文章都有过一些零散的说明了,感觉写出来又有点重复。。所以最好先读过前面几篇可能看起来更好点。。等我把所有的东西都写完后应该会重新整理,然后重新写一份更可读的吧(这是个flag) 该篇将会详细阐述 Bitcoin 的交易本质。同样,在本篇中不探讨区块,只讨论 Tx 在整个 bitcoin 系统中是如何运作的。本篇所用的术语承接于上一篇文章,并直接使用上一篇文章讨论的细节。 在整个bitcoin 的源码中,尤为重要的文件只有main.cpp/.h (还有script.cpp/.h)这个文件,其他部分都属于附属功能。在main.cpp/.h文件中,包含了在后续版本中称为“core”的代码。 我们都知道,bitcoin 系统中有2个核心概念,Tx和 Block。但是这两个概念联系的相当紧密,甚至难以分割。但是当我们单纯的说Tx的时候,下文会回避一些和Block相关的说明。 在bitcoin 系统中,所谓的交易应该包含2个过程: 产生交易->交易被(矿工)验证 我们可以看到在这个流程中,关联的人应该有3个:转账人,收款人,矿工(们) 接下来我们分别介绍其中运作的原理,并通过这两个流程作为切入点,展开我对bitcoin交易的理解。 Transaction 的产生现在我们概要性的描述一个交易产生的流程: A 想要转账 1 btc 给 B,那么流程如下(这部分代码实现位于 main.cpp CreateTransaction() 这个函数中): B 首先通过某种途径告诉了A自己的比特币地址(关于地址的介绍在其他文章中会详细描述) 然后A根据B给出的地址,并且附加上一些其他信息(非必要) 产生了scriptPubkey,这个scriptPubkey 就是前一篇文中所提到的“锁”。然后,根据要转账的金额 value, A就开始产生一个交易了:
Transaction 的验证现在描述一个Tx的验证过程。请注意,对于 Tx 的验证重点并不是交易的发起人对Tx进行验证,而是需要广大的矿工对该笔Tx进行验证,也就是我们说的狭义上的关于Tx的共识。本人对Tx的验证并没有什么用,只有整个系统中的大部分人都认同这个Tx的时候,这个Tx才算是成立。(准确的说应该是当Tx打包入Block,这个Block被广播后大多数节点认同他并添加到最长链上那么这个Tx才算是真正的成立,但是本文先不讨论block)。但是请注意,从这部分开始,在讨论的过程中请认清,对于发起交易的交易者A,和对这笔交易认证的广大矿工,分别是依据从哪里获得的信息进行验证的。 好我们继续上一节假设的场景,A转账了1 btc 给B,A 在检查了自己过去的Tx后依据自己保存的信息并认为这些信息合法后,创建了一个新的Tx,并将其通过某种方式进行广播(该部分会在网络相关的文中进行描述)。但矿工收到了这个Tx那么验证就可以开始了(接下来我们省略的主语都是矿工): 验证的部分位于 CTransaction::AcceptTransaction() 函数中。首先先明确一点,在bitcoin系统中,无论查询什么东西,都是基于这个东西的hash,也就是说我们一般认为一个hash是这个对象(实例,实体)的索引id
接下来这个Tx就存在于该矿工的内存池中了,这个矿工 可能会义务的 帮你把这个验证正确的交易广播给更多的人,其他矿工接收到也会进行在本地进行相同的验证流程并可能广播给更多的人。之后就等待这个矿工把这个交易打包进入区块,当这个区块被大部分矿工承认后这个交易就生效了。 简单分析上文的那两部分中我们详细的介绍了Tx的产生和验证,实际上真正的流程比上述复杂的多,有很多分支的处理。。。但是即便如此,上面所述若不对照相应的代码,估计任何初始者看了都是一头雾水。我只是把我认为比较重要的部分用黑体标识出来。其中我用黑体标识出的部分重点在于突出一个Tx到底是怎么在一个分布式环境中,即便各个节点是互不信任的,仍然可以接受别人产生的交易。在上面的那两个过程中:
若按照传统的流程(网上银行模型),这两个过程应该如下:ps(关于中央铸币节点的概念参考比特币白皮书的文章)
而在bitcoin的转账的整体流程中,这两个过程是不一样的,其中的交易发起者和交易接收者的角度是一致的,但是验证交易的角色由原来的“中央铸币节点”转变成为了“所有的矿工及接受包含这个Tx的区块的所有人”
其中最后一点提一下:如果一个矿工内存池中的Tx不多,或者他有选择的接受一些Tx而剔除一些Tx(比如给的交易费不够高),如果他很强大,能够一直获得打包区块的记账权,那么很可能有一些交易就永远都无法被打包,即便其他矿工打包了你的交易,但是只要这个这些其他矿工抢不过这个很厉害的矿工,那么你的交易仍然是无法生效的,因为“没有被记录进历史记录当中”,你想根据这个交易产生剩下的交易也是不行的。 总结经过上面的分析,从传统的方式和bitcoin的方式的比较可以得出,至少在我的观点中,最大的区别在于: 校验历史记录的这个过程被转移到了哪里 因为在保障交易流程的正确性中,关键点在于一个交易能够成功,是要依托于以前的交易是否是正确的,如:
而传统交易和 bitcoin 是有相当显著的区别的:
这就回到在分析章节提出的问题: 一个Tx到底是怎么在一个分布式环境中,即便各个节点是互不信任的,仍然可以接受别人产生的交易。 这个问题的答案很简单: 因为节点是互不信任的,所以他们信任的是自己,节点只相信自己的历史记录,只会根据自己的历史记录做出判断。那么问题就来了:自己的历史记录到底是对还是错呢?(这里的对错是相对的含义,应该说是不是和大部分人一致) 这个问题就涉及到了bitcoin的最高原则了,只认同工作量最长链为唯一公认的bitcoin链。 那么剩下的问题就会在block的部分继续进行分析。 下一篇bitcoin 源码解析 - 交易 Transaction(三) - Script 文章被以下专栏收录推荐阅读![]() bitcoin源码解析 - 交易 Transcation (一)bitcoin 源码解析 - 交易 Transaction(四) - Script2bitcoin 源码解析 - 交易 Transaction(四) - Script2现在发现写文章真是好没有什么动力··· 所以就写的简洁些吧·· 随心说一些最关键的点,细节就不强调了。接上一文的《bitcoin 源码解… ![]() 学习bitcoin源码--写在开头![]() 在win10 vs 2015 上编译运行bitcoin v0.1源码 (下)写下你的评论... 我现在就是很想搞清楚交易费的计算方式,特别是 bitcoin-core 那个 智能交易费 的计算方式,然后去github上看源码。。看的头疼(不会C++) 新的源码我没看过,不过为什么想搞懂手续费的计算方式?这块几乎可以忽略不计吧……手续费只会随着网络拥堵水涨船高的 也不是手续费计算方式,那个还是大概明白,就是想弄懂 智能推荐的交易费客户端是怎么计算出来的 大概多少手续费能够多久得到X个确认,难道是去取区块最近交易的平均值么 交易后的扫尾工作是把该交易中用到的UTXO标记成已花费?那这样的话就把原本区块链中的数据给改了。可是区块链又号称历史交易不可更改,这里不太明白。 这里改的是自己的本地存储数据,链上是没有这个东西的。也就是说一个交易是否是utxo实际上是这个节点自己知道的,不是从链上得到的。而比特币一个神奇之处就是,虽然这个东西不是从链上得到的,但是只要大家都走同一个链,那么从链上推演出来的本地数据都是一致的 啊,抱歉,这块我就不清楚了…没看过新的源码,不够你说的这个确实有点意思,以后有空就看 检查待认证交易的所有TxIn持有的Tx的指针(概念上的指针,这里说的是COutPoint,就是这个TxIn是来自哪个Tx的),如果这个指针已经在自己的一个缓存中(mapNextTx,使用COutPoint作为key,value是这个TxIn(之前已经出现过的)被包含的那个Tx(代表已经有Tx或收到同一个Tx)),先检查已在缓存的Tx和当前收到的这个Tx哪一个“更新”,更新的话就保留,否则就退出验证。……请问比较这个更新啥作用,靠什么表示时间,谢谢
|
|
7 条评论