精通比特币(中)

本来想三篇文章来写完《精通比特币》的,没想到看书的进度有些落后。中篇看到第四章,这一篇的压力有些大。最近才看到第六章。所以,就有了这个中2篇,显得特别二了,哈哈。

第二版从第四章中把钱包这一部分分割出来并添加了一些知识点,成为了第五章 钱包。而我看的是第一版,所以,略有不同。以后有时间也可以看一下第二版来看下添加了哪些内容。

第五章 交易

由于这笔交易是经过签名且不含任何机密信息、私钥或密码,因此它可被任何潜在的便利网络公开地传播。信用卡交易包含敏感信息,而且依赖加密网络连接完成信息传输,但比特币交易可在任意网络环境下被发送。

[注] 这是由比特币的私钥公钥之间的非对称加密实现的:即交易记录中的地址(公钥)和签名都无法反向获取对应的私钥

一笔比特币交易甚至可被编为文字信息中的表情符号并被发表到在线论坛,或被发送成一条短信或一条Skype聊天信息。因为比特币将金钱变成了一种数据结构,所以在本质上是不可能阻止任何人创建并执行比特币交易的。

[注] 之前有将疫苗事件的文章(公众号文章被删)发布在区块链网络上,感觉就像这里介绍的,可以把交易编译成文本信息。不过看到后面的内容,认为是交易中包含了文本信息,而不是这里的把交易转换成文本信息。

交易结构

[注] 之前认为输入即发送方的地址,输出即接收方的地址。这里发现并不是这样。这里的输入和输出均是一些UXTO,后面的内容会介绍

交易的锁定时间

锁定时间定义了能被加到区块链里的最早的交易时间。在大多数交易里,它被设置成0,用来表示立即执行。如果锁定时间不是0并且小于5亿,就被视为区块高度,意指在这个指定的区块高度之前,该交易没有被包含在区块链里。如果锁定时间大于5亿,则它被当作是一个Unix纪元时间戳(从1970年1月1日以来的秒数),并且在这个指定时点之前,该交易没有被包含在区块链里。锁定时间的使用相当于将一张纸质支票的生效时间予以后延。

[问题] 这个时间与时间戳有没有关系,是不是同一个?通过这里的介绍感觉并不是同一个内容。感觉这里讲的是打入包的时间,而时间戳是记录交易的时间。

[注] UTXO脚本的结构:tx_hash:交易的哈希值(可以视为交易的ID)、tx_index:交易的索引值;tx_output_n:特定UTXO的索引值;value:比特币量(单位是聪);confirmations:确认次数;其他的一些参数,也不是很清楚,可能要学习过代码之后,才有了解其含义和用途吧。

一旦UTXO被选中,钱包会为每个UTXO生成包含签名的解锁脚本,由此让它们变得可以通过满足锁定脚本的条件来被支付。钱包把这些UTXO作为参考,并且连同解锁脚本一起作为输入加到交易中。

[注] 当用户有多笔UTXO,其进行交易时,需要对这些UTXO进行筛选,选出总和正好可以略多于输出的UTXO,即可能是多个UTXO。那么,这里就要为每个UTXO进行解锁,从而可以进行交易(即花费出去)

[思考] 比特币的交易是针对UTXO的,并且这里的UTXO是不可以切割的,除非像换零钱一样,和其他人交易,别人通过多个地址向我们付款获得多个UTXO。显然这是繁琐且不友好的,所以会被一些数字货币攻击说,这个UTXO不可分割,操作困难,可扩展性差。

交易输入的结构

[注] 交易的输入主要是解锁脚本,主要是说明这些UTXO是可以用这个来解锁,可以由该用户来花费的。

交易费基于交易的尺寸,用千字节来计算,而不是比特币的价值。交易费不是强制的,而且没有交易费的交易也许最终会被处理,但是,包含交易费将提高处理优先级。

[注] 与传统的手续费由交易金额决定不同。所以,如果有多个UTXO来作为输入,或多个地址作为输出,则所需要的字节就会变多,交易费也会变多。

如果你忘记了在手动构造的交易中增加找零的输出,系统会把找零当作交易费来处理。“不用找了!”也许不是你想要的结果。

[问题] 交易费是交易吗?如果是交易,它也形成交易并且被打包吗?如果不是交易,那也会有输出,产生UTXO,这个输出是指向挖出这个区块的矿工。那么这个UTXO结构里面的tx_hash是不是与普通的UTXO不同?

输入数量这么巨大(众多的UTXO)的交易会比一千字节要大,也许总尺寸会达到两至三千字节。结果是它需要更高的交易费来满足0.0001比特币的网络费。

[注] 之前的理解是输入时发送方的地址,这里其实是UTXO,并不单纯的是地址。所以,从UI上查看交易费还是很难清楚的知道的。因为UI上只会告知输入的地址(用户自己的地址,可能是多个),和输出的地址而已。

此类交易仅将比特币地址当作自由组合的20个字节而使用,进而会产生不能用于交易的UTXO。因为比特币地址只是被当作数据使用,并不与私钥相匹配,所以会导致UTXO不能被用于交易,因而是一种伪支付行为。这样的做法将使得内存中的UTXO不断增加,而且这些不能被用于交易的数据同样也不能被移除,因此比特币节点将永久性地担负这些数据,这无疑是代价高昂的。

[注] 比特币记录文本的一种形式,早期是将交易地址替换成要记录的文本,但是这样会导致自己的钱就支付给一个无法消费的地址(自己想要记录的文本)

在0.9版的比特币核心客户端上,通过采用OP_Return操作符最终实现了妥协。OP_Return允许开发者在交易输出上增加40字节的非交易数据。

*[注] 显然这里的40个字节也不足以用户记录信息,所以,一些记录信息的会使用到以太坊,比如如下的这个是记录疫苗事件的:

《兽爷,疫苗之王!》被永久记录于以太坊高度6007493之上。能删掉我直播喝农药详情点击以下链接:

https://etherscan.io/tx/0xb1ed364e4333aae1da4a901d5231244ba6a35f9421d4607f7cb90d60bf45578a

最下方的Input Data 选择 View Input As UTF8。

目前还没有学习以太坊,还不清楚具体的实现。可能以太坊上已有类似OP_Return的操作吧,只不过可扩展性要比OP_Return好的多,因为这里存储了一篇文章,而不仅仅是40个字节。

第6章 比特币网络

每个比特币节点都是路由、区块链数据库、挖矿、钱包服务的功能集合。

[注] 这里说的是比特币全节点,一些其他的客户端并不一定有这么全的功能。

节点通常采用TCP协议、使用8333端口(该端口号通常是比特币所使用的,除8333端口外也可以指定使用其他端口)与已知的对等节点建立连接。

虽然比特币网络中没有特殊节点,但是客户端会维持一个列表,那里列出了那些长期稳定运行的节点。这样的节点被称为“种子节点(seed nodes)”。新节点并不一定需要与种子节点建立连接,但连接到种子节点的好处是可以通过种子节点来快速发现网络中的其他节点。

[注] 由于比特币是分布式的,每个节点的网络环境、主观条件等因素可能不同,会产生一些节点的下线。这里是在这个非稳定可靠的网络中寻求一些较为稳定可靠的节点来加快新节点的连接速度。

节点必须持续进行两项工作:在失去已有连接时发现新节点,并在其他节点启动时为其提供帮助。节点启动时只需要一个连接,因为第一个节点可以将它引荐给它的对等节点,而这些节点又会进一步提供引荐。一个节点,如果连接到大量的其他对等节点,这既没必要,也是对网络资源的浪费。在启动完成后,节点会记住它最近成功连接的对等节点;因此,当重新启动后它可以迅速与先前的对等节点网络重新建立连接。如果先前的网络的对等节点对连接请求无应答,该节点可以使用种子节点进行重启动。

[注] 这里介绍了网络节点介入以及扩展网络的方法。

SPV节点只需下载区块头,而不用下载包含在每个区块中的交易信息。由此产生的不含交易信息的区块链,大小只有完整区块链的1/1000。SPV节点不能构建所有可用于消费的UTXO的全貌,这是由于它们并不知道网络上所有交易的完整信息。SPV节点验证交易时所使用的方法略有不同,这个方法需依赖对等节点“按需”提供区块链相关部分的局部视图。

[注] SPV节点是轻量级的钱包,不需要全部的交易记录。由于一个钱包代表一个用户,其对应的UTXO也不是全部网络的UTXO,其只需要维护自己用户对应的UTXO。且这里的UTXO是从网络中获取的?还是自己计算的?如果是自己计算,则需要这些UTXO中的所有的交易链,需要请求一些交易记录。这与SPV节点只需要下载区块头不一致。

简易支付验证是通过参考交易在区块链中的深度,而不是高度,来验证它们。一个拥有完整区块链的节点会构造一条验证链,这条链是由沿着区块链按时间倒序一直追溯到创世区块的数千区块及交易组成。而一个SPV节点会验证所有区块的链(但不是所有的交易),并且把区块链和有关交易链接起来。

[注] 即认为交易已经被确认这么多次了,每确认一些,全节点就会验证一次,那么,这个验证是通过的。这里的简易支付验证有点像抄学霸作业的感觉。

相反地,SPV节点会在该交易信息和它所在区块之间用merkle路径(见“7.7 Merkle 树”)建立一条链接。然后SPV节点一直等待,直到序号从300,001到300,006的六个区块堆叠在该交易所在的区块之上,并通过确立交易的深度是在第300,006区块~第300,001区块之下来验证交易的有效性。事实上,如果网络中的其他节点都接受了第300,000区块,并通过足够的工作在该块之上又生成了六个区块,根据代理网关协议,就可以证明该交易不是双重支付。

[注] 这是简易支付验证的一个具体的例子。

交易池和孤立交易池(如有实施)都是存储在本地内存中,并不是存储在永久性存储设备(如硬盘)里。更准确的说,它们是随网络传入的消息动态填充的。节点启动时,两个池都是空闲的;随着网络中新交易不断被接收,两个池逐渐被填充。

交易池和孤立交易池代表的是单个节点的本地视角。取决于节点的启动时间或重启时间,不同节点的两池内容可能有很大差别。

[思考] 交易池中的交易不同,也就是说打包的交易也不同,那么其挖矿的计算的难题会是相同的吗?还是说挖矿的难度系数相同,不同的节点根据各自节点的交易池中要进行打包的交易计算不同的难题?由于难题的计算与前一个区块有关,所以,当新产生一个区块时,难题要重新计算,不存在计算好一个难题后等在那里伺机作假超车的情况。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180812G13PAR00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券