钱包、密钥
- 私钥衍生家族----适用于各种树形权限分配,比如企业钱包
交易
- 交易费按交易数据字节大小计算,交易费市场定价,与币值无关。矿工可按交易费排序优先级进行处理。
- 比特币以UTXO记录,UTXO如同金额不同的一张张支票,金额最小单位为“聪”
- 交易输入减输出即付给矿工的交易费,交易订单一般由钱包创建,手动创建时应避免付出天价交易费。(贪心算法挑选输入UTXO,解决背包问题常用的还有动态规划)
- 交易链条和孤立交易:父、子、孙订单在比特网络中传输可能出现不同时序。孤立交易会被放入一个大小有限的等待池。
- 类Forth脚本语言编写的脚本验证比特币交易:解锁脚本解锁输入UTXO集,锁定脚本指定输出UTXO集的解锁条件。脚本可表达出多到数不尽的条件变种。这也是比特币作为一种“可编程的货币”所拥有的权力。
- 并非所有解锁脚本都一定会包含签名。 有哪些特殊情形???
- 解锁脚本&锁定脚本,拼接执行
- 图灵非完备性,去除脚本复杂性,减少漏洞可能
- 标准交易:五大标准脚本分别为P2PKH、P2PK、MS(限15个密钥)、P2SH和OP_Return
- 多重签名,多个密钥联合管理资金,多重签名机制能为公司治理提供管控便利,同时也能有效防范盗窃、挪用和遗失。
- OP_RETURN的定义即显示不能赎回;请记住OP_RETURN不涉及可用于支付的解锁脚本的特点,OP_RETURN不能使用其输出中所锁定的资金,因此它也就没有必要记录在蕴含潜在成本的UTXO集中,所以OP_RETURN实际是没有成本的。
比特币网络
- 每个比特币节点都是路由、区块链数据库、挖矿、钱包服务的功能集合
- 对待节点区块数据同步,获取区块hash列表,再获取区块数据
- Bloom过滤器:增加SPV隐私性
- 交易池:节点们利用这个池来追踪记录那些被网络所知晓、但还未被区块链所包含的交易。
- UTXO池
区块链
- 区块头:1.引用父区块哈希值的数据,连接前一区块。 2.难度、时间戳和nonce,与挖矿竞争相关。3. merkle树根(一种用来有效地总结区块中所有交易的数据结构)
- 区块标识符:区块头哈希值和区块高度
Merkle 树
Merkle树被用来归纳一个区块中的所有交易,同时生成整个交易集合的数字指纹,且提供了一种校验区块是否存在某交易的高效途径。
- 生成一棵完整的Merkle树需要递归地对哈希节点对进行哈希,并将新生成的哈希节点插入到Merkle树中,直到只剩一个哈希节点,该节点就是Merkle树的根。在比特币的Merkle树中两次使用到了SHA256算法,因此其加密哈希算法也被称为double-SHA256。
- 当N个数据元素经过加密后插入Merkle树时,你至多计算2*log2(N)次就能检查出任意某数据元素是否在该树中,这使得该数据结构非常高效。 (为了证明区块中存在某个特定的交易,一个节点只需要计算log2(N)个32字节的哈希值,形成一条从特定交易到树根的认证路径或者Merkle路径即可。)
- Merkle树和简单支付验证(SPV):减少数据传输
挖矿与共识
- 矿工提供算力,矿工们在挖矿过程中会得到两种类型的奖励:创建新区块的新币奖励,以及区块中所含交易的交易费
去中心化共识
- ▷ 每个全节点依据综合标准对每个交易进行独立验证
- ▷ 通过完成工作量证明算法的验算,挖矿节点将交易记录独立打包进新区块,
- ▷ 每个节点独立的对新区块进行校验并组装进区块链
- ▷ 每个节点对区块链进行独立选择,在工作量证明机制下选择累计工作量最大的区块链
交易的独立校验
- 每一个节点在校验每一笔交易时,都需要对照一个长长的标准列表
- 在收到交易后,,每一个节点都会在全网广播前对这些交易进行校验,并以接收时的相应顺序,为有效的新交易建立一个池(交易池)。
挖矿节点
- 矿工间的竞争以新区块的传播而结束,如同宣布谁是最后的赢家。也是下一个区块竞赛的发令枪。
整合交易至区块
交易块龄,矿工费和优先级
- 交易的优先级是通过输入值和输入的“块龄”乘积之和除以交易的总长度得到的:
Priority = Sum (Value of input * Input Age) / Transaction Size - UTXO的“块龄”是自该UTXO被记录到区块链为止所经历过的区块数,即这个UTXO在区块链中的深度。交易记录的大小由字节来表示。
- 区块中用来存储交易的前50K字节是保留给较高优先级交易的。
创币交易
Coinbase奖励与矿工费
创币交易的结构
表8-1 “普通“交易输入的结构
长度 字段 描述
32 字节 交易哈希 指向包含有将要被花费UTXO的交易
4 字节 交易输出索引 UTXO在交易中的索引,0 从0开始计数
1-9 字节 解锁脚本长度 解锁脚本的长度
(VarInt) 可变长度 Unlocking-Script 一段脚本,用来解锁UTXO锁定脚本中的条件
4 bytes 顺序号 当前未启用的TX替换功能,设置为0xFFFFFFFF
表8-2 生成交易输入的结构
长度 字段 描述
32 字节 交易哈希 不引用任何一个交易,值全部为0
4 字节 交易输出索引 值全部为1
1-9 字节 Coinbase数据长度 coinbase数据长度
(VarInt) 可变长度 Coinbase数据 在v2版本的区块中,除了需要以区块高度开始外,其他数据可以任意填写,用于extra nonce和挖矿标签
4 bytes 顺序号 值全部为1,0xFFFFFFFF
构造区块头
表8-3 区块头的结构
长度 字段 描述
4 字节 版本 版本号,用来跟踪软件或协议的升级
32 字节 前区块哈希 链中前一个区块(父区块)的哈希值
32 字节 Merkle根 一个哈希值,表示这个区块中全部交易构成的merkle树的根
4 字节 时间戳 以Unix纪元开始到当下秒数记录的区块生成的时刻
4 bytes 难度目标 该区块的工作量证明算法难度目标
4 bytes Nonce 一个用于工作量证明算法的计数器
Proof Of Work
- 通过迭代 nonce 来生成不同哈希值的输出
- 目标阀值
难度表示
- 表示:系数/指数格式,前两位十六进制数字为幂,接下来得六位为系数。(如0x1903a30c,0x19为幂,而0x03a30c为系数)
- 计算难度目标的公式为: target = coefficient * 2^(8 * (exponent – 3))
难度目标与难度调整
- 比特币的区块平均每10分钟生成一个。这就是比特币的心跳,是货币发行速率和交易达成速度的基础。难度被动态设定在,无论挖矿总算力如何变化,新区块产生速率都保持在10分钟一个。
- 难度的调整是在每个完整节点中独立自动发生的。每2,016个区块中的所有节点都会调整难度。难度的调整公式是由最新2,016个区块的花费时长与20,160分钟(两周,即这些区块以10分钟一个速率所期望花费的时长)比较得出的。难度是根据实际时长与期望时长的比值进行相应调整的(或变难或变易)。简单来说,如果网络发现区块产生速率比10分钟要快时会增加难度。如果发现比10分钟慢时则降低难度。
- New Difficulty = Old Difficulty * (Actual Time of Last 2016 Blocks / 20160 minutes)
- 工作量证明的难度调整 源文件 pow.cpp 第43行函数 GetNextWorkRequired()
- 为了防止难度的变化过快,每个周期的调整幅度必须小于一个因子(值为4)。如果要调整的幅度大于4倍,则按4倍调整。
挖矿成功后立即进行扩散传播
校验新区块
- 行为不诚实的矿工所产生的区块将被拒绝
▷ 区块的数据结构语法上有效
▷ 区块头的哈希值小于目标难度(确认包含足够的工作量证明)
▷ 区块时间戳早于验证时刻未来两个小时(允许时间错误)
▷ 区块大小在长度限制之内
▷ 第一个交易(且只有第一个)是coinbase交易
▷ 使用检查清单验证区块内的交易并确保它们的有效性
▷ “交易的独立校验”一节已经讨论过这个清单。
区块链的组装与选择
- 比特币去中心化的共识机制的最后一步是将区块集合至有最大工作量证明的链中。一旦一个节点验证了一个新的区块,它将尝试将新的区块连接到到现存的区块链,将它们组装起来。
- 任何时候,主链都是累计了最多难度的区块链。在一般情况下,主链也是包含最多区块的那个链,除非有两个等长的链并且其中一个有更多的工作量证明。
- 节点维护三种区块:第一种是连接到主链上的,第二种是从主链上产生分支的(备用链),最后一种是在已知链中没有找到已知父区块的。在验证过程中,一旦发现有不符合标准的地方,验证就会失败,这样区块会被节点拒绝,所以也不会加入到任何一条链中。
- 选择了最大难度的区块链后,所有的节点最终在全网范围内达成共识。随着更多的工作量证明被添加到链中,链的暂时性差异最终会得到解决。挖矿节点通过“投票”来选择它们想要延长的区块链,当它们挖出一个新块并且延长了一个链,新块本身就代表它们的投票。
区块链分叉
- 链的重新共识
- 单区块分叉每周都会发生,而双块分叉则非常罕见。
挖矿和算力竞赛
下表表示了比特币网络开始运行后最初五年的总算力:
2009
0.5 MH/秒–8 MH/秒 (16倍增长)
2010
8 MH/秒–116 GH/秒 (14,500倍增长)
2011
16 GH/秒–9 TH/秒 (562倍增长)
2012
9 TH/秒–23 TH/秒 (2.5倍增长)
2013
23 TH/秒–10 PH/秒 (450倍增长)
2014
10 PH/秒–150 PH/秒 到8月为止 (15倍增长)
随机值升位方案
算力增加,难度增加,会导致随机数不够用(全部随机数尝试过还是不能获得满足难度的hash)
随机数升位扩展方案衍化:
- Nonce随机数
- Nonce + 时间戳延后(空间有限,如果把它移动得太远,会导致区块变为无效)
- Nonce + coinbase脚本变化(coinbase脚本可以储存2-100字节的数据,其变化导致merkle树根值变化,导致区块头变化,进行扩展随机区域)
如果未来矿工希望可以尝试更多的可能性,他们还可以通过修改时间戳来解决。同样,coinbase脚本中也有更多额外的空间可以为将来随机数的扩展做准备。
矿池:有趣,份额统计,工作量证明设计
让我们回到骰子游戏的比喻。如果骰子玩家的目标是扔骰子结果都小于4(整体网络难度),一个矿池可以设置一个更容易的目标,统计有多少次池中的玩家扔出的结果小于8。当池中的玩家扔出的结果小于8(矿池份额目标),他们得到份额,但他们没有赢得游戏,因为没有完成游戏目标(小于4)。但池中的玩家会更经常的达到较容易的矿池份额目标,规律地赚取他们的份额,尽管他们没有完成更难的赢得比赛的目标。
时不时地,池中的一个成员有可能会扔出一个小于4的结果,矿池获胜。然后,收益可以在池中玩家获得的份额基础上分配。尽管目标设置为8或更少并没有赢得游戏,但是这是一个衡量玩家们扔出的点数的公平方法,同时它偶尔会产生一个小于4的结果。
同样的,一个矿池会将矿池难度设置在保证一个单独的矿工能够频繁地找到一个符合矿池难度的区块头hash来赢取份额。时不时的,某次尝试会产生一个符合比特币网络目标的区块头hash,产生一个有效块,然后整个矿池获胜。
托管矿池
矿工连接到矿池服务器使用一个采矿协议比如Stratum (STM)或者 GetBlockTemplate (GBT)
STM和GBT协议都创建包含候选区块头模板的区块模板。矿池服务器通过聚集交易,添加coinbase交易(和额外的随机值空间),计算MERKLE根,并连接到上一个块hash来建立一个候选区块。这个候选区块的头部作为模板分发给每个矿工。矿工用这个区块模板在低于比特币网络的难度下采矿,并发送成功的结果返回矿池服务器赚取份额。
P2P矿池
P2Pool是一个点对点的矿池,没有中心管理人。
P2Pool通过将矿池服务器的功能去中心化,实现一个并行的类似区块链的系统,名叫份额链。
本质上说,比起用一个矿池服务器记录矿工的份额和奖励,份额链允许所有矿工通过类似比特币区块链系统的去中心化的共识机制跟踪所有份额。
共识攻击
- 比特币的共识机制依赖于这样一个前提,那就是绝大多数的矿工,出于自己利益最大化的考虑,都会通过诚实地挖矿来维持整个比特币系统。
- 共识攻击只能影响整个区块链未来的共识,或者说,最多能影响不久的过去几个区块的共识(最多影响过去10个块)。而且随着时间的推移,整个比特币块链被篡改的可能性越来越低。
- 区块链分叉/双重支付攻击指的是攻击者通过不承认最近的某个交易,并在这个交易之前重构新的块,从而生成新的分叉,继而实现双重支付。有了充足算力的保证,一个攻击者可以一次性篡改最近的6个或者更多的区块,从而使得这些区块包含的本应无法篡改的交易消失。值得注意的是,双重支付只能在攻击者拥有的钱包所发生的交易上进行,因为只有钱包的拥有者才能生成一个合法的签名用于双重支付交易。攻击者只能在自己的交易上进行双重支付攻击,但当这笔交易对应的是不可逆转的购买行为的时候,这种攻击就是有利可图的。
- 双重支付可以有两种方式:要么是在交易被确认之前,要么攻击者通过块链分叉来完成。进行51%攻击的人,可以取消在旧分叉上的交易记录,然后在新分叉上重新生成一个同样金额的交易,从而实现双重支付。
- 共识攻击中除了“双重支付”攻击,还有一种攻击场景就是拒绝对某个特定的比特币地址提供服务。
本质上来看,共识攻击,就像是系统中所有矿工的算力被分成了两组,一组为诚实算力,一组为攻击者算力,两组人都在争先恐后地计算块链上的新块,只是攻击者算力算出来的是精心构造的、包含或者剔除了某些交易的块。因此,攻击者拥有的算力越少,在这场决逐中获胜的可能性就越小。从另一个角度讲,一个攻击者拥有的算力越多,其故意创造的分叉块链就可能越长,可能被篡改的最近的块或者或者受其控制的未来的块就会越多。一些安全研究组织利用统计模型得出的结论是,算力达到全网的30%就足以发动51%攻击了。
竞争币和竞争块链的分类
元币平台
染色币:添加附加信息的币中币
万事达币
合约币
竞争币/山寨币
下面所列出的就是这些竞争币区别于比特币的三点主要不同:
▷ 货币策略不同
▷ 基于工作量证明的一致性机制不同
▷ 一些特殊的功能,比如更强的匿名性等等