区块链的起源
创始者介绍
姓名:中本聪(英语:SatoshiNakamoto),自称日裔美国人,日本媒体常译为中本哲史,此名是比特币协议及其相关软件Bitcoin-Qt的创造者,但真实身份未知。
中本聪于2008年发表了一篇名为《比特币:一种点对点式的电子现金系统》(Bitcoin: A Peer-to-Peer Electronic Cash System)的论文,描述了一种被他称为“比特币”的电子货币及其算法。2009年,他发布了首个比特币软件,并正式启动了比特币金融系统。
2009年1月3日,比特币的创始人中本聪在创世区块里留下一句永不可修改的话:
“The Times 03/Jan/2009 Chancellor on brink of second bailout for banks(2009年1月3日,财政大臣正处于实施第二轮银行紧急援助的边缘)。2010年,他逐渐淡出并将项目移交给比特币社区的其他成员.
中本聪生日八卦
注册生日:1975年4月5日
4月5号在货币史上是具有重要意义的一天。在1933年的这一天,美国总统弗兰克林·罗斯福签署了政府法令6102,法令规定所有美国公民持有黄金是非法的。
1975年,福特总统签署“黄金合法化”法案,美国人可以再一次合法地拥有黄金。
先有区块链还是先有比特币?
比特币面世之初是没有区块链的概念的,但比特币确确实实是基于底层区块链实现的。区块链是后来人们对于比特币底层的认可而提取出来的概念。
从技术上看区块链
- 任何人都可以看到所有的源码。tips:比特币源码Github地址
- 任何人都可以下载完整的账本。
- 整套系统没有任何防火墙。
- 即使全世界大部分的网络出现了故障,仍然可以运行。
区块链运行机制(未总结)
tips:1字节=8位二进制=2位16进制
哈希算法
特点
- 输入长度不固定,输出出长度固定:任意长度的输入,都将会得到固定长度。
- 输入敏感:原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。
- 逆向困难:给定(若干) hash 值,基本不可能逆推出明文。
- 冲突避免:很难找到两段内容不同的明文,使得它们的 hash 值一致(发生冲突)。
- 用于信息压缩,并判断信息是否变化
常用哈希算法
- MD4, MD5.
- SHA-1, SHA-2.
- RIPEMD-160.
SHA256
SHA256简介
SHA256算法中SHA256是SHA-2下细分出的一种算法
SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发,属于SHA算法之一,是SHA-1的后继者。
SHA-2下又可再分为六个不同的算法标准
包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。
这些变体除了生成摘要的长度、循环运行的次数等一些微小差异外,算法的基本结构是一致的。
回到SHA256上,说白了,它就是一个哈希函数。
哈希函数,又称散列算法,是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值(或哈希值)的指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表。
对于任意长度的消息,SHA256都会产生一个256bit长的哈希值,称作消息摘要。
这个摘要相当于是个长度为32个字节的数组,通常用一个长度为64的十六进制字符串来表示
比如:
挣钱养家,改变世界
这句话,经过sha256加密后就是酱紫:2aa26a143a7ac201a7358eb089a91372a626031d17abe19af52d41d8c249e3f1
查看加解密网站点我
原理详解
为了更好的理解SHA256的原理,这里首先将算法中可以单独抽出的模块,包括
常量的初始化
、信息预处理
、使用到的逻辑运算
分别进行介绍,甩开这些理解上的障碍后,一起来探索SHA256算法的主体部分,即消息摘要是如何计算的。常量初始化
SHA256算法中用到了8个哈希初值以及64个哈希常量
其中,SHA256算法的8个哈希初值如下:
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19
这些初值是对自然数中前8个质数(2,3,5,7,11,13,17,19)的平方根的小数部分取前32bit而来
举个例子来说,√2小数部分约为0.414213562373095048,而
0.414213562373095048≈6∗16−1+a∗16−2+0∗16−3+...
于是,质数2的平方根的小数部分取前32bit就对应出了0x6a09e667
在SHA256算法中,用到的64个常量如下:
428a2f98 71374491 b5c0fbcf e9b5dba5
3956c25b 59f111f1 923f82a4 ab1c5ed5
d807aa98 12835b01 243185be 550c7dc3
72be5d74 80deb1fe 9bdc06a7 c19bf174
e49b69c1 efbe4786 0fc19dc6 240ca1cc
2de92c6f 4a7484aa 5cb0a9dc 76f988da
983e5152 a831c66d b00327c8 bf597fc7
c6e00bf3 d5a79147 06ca6351 14292967
27b70a85 2e1b2138 4d2c6dfc 53380d13
650a7354 766a0abb 81c2c92e 92722c85
a2bfe8a1 a81a664b c24b8b70 c76c51a3
d192e819 d6990624 f40e3585 106aa070
19a4c116 1e376c08 2748774c 34b0bcb5
391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3
748f82ee 78a5636f 84c87814 8cc70208
90befffa a4506ceb bef9a3f7 c67178f2
和8个哈希初值类似,这些常量是对自然数中前64个质数(2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97…)的立方根的小数部分取前32bit而来。
信息预处理
SHA256算法中的预处理就是在想要Hash的消息后面补充需要的信息,使整个消息满足指定的结构。
信息的预处理分为两个步骤:
附加填充比特
和附加长度
假定原始数据为:
01100001 01100010 01100011
tips:1字节=8位二进制=2位16进制
附加填充比特
补位第一步:
01100001 01100010 01100011 1
在原始数据后面直接补一个“1”补位第二步:
0110000101100010 01100011 10…..0
然后补423个“0”注:
- 信息必须进行填充,故填充是至少补一位,最多补512位。
- 补0的数量记为K,K的取值需要满足下述表达式的最小非负整数值。( 原始长度L + 1 + K ) mod 512 = 448(512-448=64,保证后面留有64bit存放记录原始信息的长度)
我们可以把最后补位完成后的数据用16进制写成下面的样子
61626380 0000000000000000 00000000
00000000 0000000000000000 00000000
00000000 0000000000000000 00000000
00000000 00000000
附加长度值
附加长度值就是将原始数据(第一步填充前的消息)的长度信息补到已经进行了填充操作的消息后面。
因为SHA256用一个64位的数据来表示原始消息的长度,所以通过SHA256计算的消息长度必须要小于2^64
,当然绝大多数情况这足够大了。
61626380 0000000000000000 00000000
00000000 0000000000000000 00000000
00000000 0000000000000000 00000000
00000000 0000000000000000 00000018
注意:原始信息长度是24(十进制),24转化成十六进制就是18
需要使用的函数
SHA256散列函数中涉及的操作全部是逻辑的位运算
CH(x, y, z) = (x AND y) XOR ( (NOT x) AND z)
MAJ( x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z)
BSIG0(x) = ROTR^2(x) XOR ROTR^13(x) XOR ROTR^22(x)
BSIG1(x) = ROTR^6(x) XOR ROTR^11(x) XOR ROTR^25(x)
SSIG0(x) = ROTR^7(x) XOR ROTR^18(x) XOR SHR^3(x)
SSIG1(x) = ROTR^17(x) XOR ROTR^19(x) XOR SHR^10(x)
其中x、y、z皆为32bit的字。
ROTR^2(x)是对x进行循环右移2位。
SHR^3(x)是对x进行右移3位。
XORshi是异或
注:
循环移位:比如我们有个1字节的数: x =10111110。现在需要对其循环右移4位。也就是最后结果为x = 11101011
右移:空缺部分直接补零
计算消息摘要
将消息分成N个512bit的数据块,于是整个算法需要做的就是完成N次迭代,N次迭代的结果就是最终的哈希值,即256bit的数字摘要。
一个256-bit的摘要的初始值H0,经过第一个数据块进行运算,得到H1,即完成了第一次迭代
H1经过第二个数据块得到H2,……,依次处理,最后得到Hn,Hn即为最终的256-bit消息摘要
256-bit的Hi被描述8个小块,这是因为SHA256算法中的最小运算单元称为“字”(Word),一个字是32位。
此外,第一次迭代中,映射的初值设置为前面介绍的8个哈希初值,如下:
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
H0= h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19
迭代的内容
- 构造64个字(word):对于每一块,将块分解为16个32-bit的big-endian的字,记为w[0], …, w[15],也就是说,前16个字直接由消息的第i个块分解得到。其余的字由如下迭代公式得到:Wt=σ1(Wt−2)+Wt−7+σ0(Wt−15)+Wt−16
- 进行64次循环:即进行64次加密循环即可完成一次迭代
For i=1 to N
1) For t = 0 to 15
Wt = M(i)t
For t = 16 to 63
Wt = SSIG1(W(t-2)) + W(t-7) + SSIG0(t-15) + W(t-16)
2)a = H(i-1)0
b = H(i-1)1
c = H(i-1)2
d = H(i-1)3
e = H(i-1)4
f = H(i-1)5
g = H(i-1)6
h = H(i-1)7
3)For t = 0 to 63
T1 = h + BSIG1(e) + CH(e,f,g) + Kt + Wt
T2 = BSIG0(a) + MAJ(a,b,c)
h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2
4) H(i)0 = a + H(i-1)0
H(i)1 = b + H(i-1)1
H(i)2 = c + H(i-1)2
H(i)3 = d + H(i-1)3
H(i)4 = e + H(i-1)4
H(i)5 = f + H(i-1)5
H(i)6 = g + H(i-1)6
H(i)7 = h + H(i-1)7
注:
- 在“4)”中,两个数字加在一起,如果结果大于
2^32
,则用两数之和对2^32
取模找到余数对其重新赋值- abcdefgh初始值是8个哈希初值
- Kt是第t个密钥,对应我们上文提到的64个常量
- 最后一次循环所产生的八个字合起来即是第i个块对应到的散列字符串H{i}
PKI 公钥体系的一些基本概念
tips:PKI(Public Key Infrastructure)
- 对称加密算法,典型算法:DES、AES,...
- 加解密方共用一个密钥
- 加解密速度快,但密钥分发比较困难
- 非对称密码算法(公钥体系),典型算法:RSA、ECC
- 加解密时,通讯一方有一对密钥(公钥和私钥)
- 公钥可以公开,分发给任何人
- 私钥不可以公开,严格持有,例如U盾中存放私钥等
- 公钥加密,只能用私钥解密,反之亦然
- 加解密速度较慢,但无密钥分发问题
- 区块链主要使用ECC椭圆曲线算法
- 公钥体系与对称密钥相结合的加密方式
- 公钥体系通常运算性能低,做大量数据加解密力不从心
- 通常利用公钥体系实现对称密钥的安全交换
共识算法
POW:proof of work 工作量证明
区块头如下:
大小 | 字段 | 描述 |
---|---|---|
4字节 | 版本 | 版本号,用于跟踪软件/协议的更新 |
32字节 | 父区块的哈希 | 引用区块链中父区块的哈希值 |
32字节 | Merkle根 | 该区块交易中Merkle树根的哈希值 |
4字节 | 时间戳 | 该区块产生的近似时间(精确到秒的Unix时间戳) |
4字节 | 难度目标 | 该区块工作量证明算法的难度目标 |
4字节 | Nonce | 用于工作量证明算法的计数器 |
SHA256(version+prev_hash+merkle_root+ntime+nbits+Nonce)< target
- 比特币区块的版本号:version
- 上一个区块的散列值:prev_hash
- 需要写入交易记录散列数的值:merkle_root
- 更新的时间:ntime
- 当前的难度:nbits
根据比特币相关算法的定义,Nonce的值存在于0到2的32次方之间,target是已经给定的、根据当前难度求得的数值。比特币算法的特点在于:由于散列的性质,比特币需要的那个x只能通过计算得出,而没有任何的捷径可走.
例如当前难度为
0x1903a30c
target=coefficient*2^(8*(exponent-3))
target=0x03a30c*2^(8*(0x19-0x03)) //0x19 和 0x03a30c 来自难度的拆分
target=0x03a30c*2^(8*0x16)
target=我不想计算了
只要你算出的
SHA256<target
则工作量证明成功
POS:Proof of Stake,股权证明
POS是一类共识算法,各个区块链项目的POS差别很大
POW通过改变Nonce值来不断改变Hash值去和Target比较
POW的公式可简化为:
F(Nonce)<Target
而POS的公式简化为:
F(TimeStamp)<Target*Banlance
tips:Target越大,挖矿难度越低
币龄:每个币每天产生1币龄,比如你持有100个币,总共持有了30天,那么,此时你的币龄就为3000。
proofhash < 币龄x目标值 展开如下:
hash(nStakeModifier + txPrev.block.nTime + txPrev.offset + txPrev.nTime + txPrev.vout.n + nTime) < bnTarget x bnCoinDayWeight
- 其中proofhash,对应一组数据的哈希值,即
hash(nStakeModifier + txPrev.block.nTime + txPrev.offset + txPrev.nTime + txPrev.vout.n + nTime)。
- 币龄即
bnCoinDayWeight
,即币天,即持有的币数乘以持有币的天数,此处天数最大值为90天。- 目标值,即
bnTarget
,用于衡量PoS挖矿难度。目标值与难度成反比,目标值越大、难度越小;反之亦然。由公式可见,持有的币天越大,挖到区块的机会越大。
点点币使用目标值来衡量挖矿难度,目标值与难度成反比,目标值越大、难度越小;反之亦然。
当前区块的目标值与前一个区块目标值、前两个区块的时间间隔有关。
计算公式如下:
当前区块目标值 = 前一个区块目标值 x (1007x10x60 + 2x前两个区块时间间隔) / (1009x10x60)
由公式可见,两个区块目标间隔时间即为10分钟。
如果前两个区块时间间隔大于10分钟,目标值会提高,即当前区块难度会降低。
反之,如果前两个区块时间间隔小于10分钟,目标值会降低,即当前区块难度会提高。
POS2.0
为了进一步巩固PoS的安全,2014年rat4(Pavel Vasin)提出了PoS 2.0,并发布了黑币。
黑币前5000个块,为纯PoW阶段;第5001个块到第10000个块为PoW与PoS并存阶段,从第10001个块及以后为纯PoS阶段。
黑币首创快速挖矿+低股息发行模式,发行阶段采用POW方式,通过算法改进在短时间内无法制造出专用的GPU和AISC矿机,解决分配不公平的问题。
PoS2.0相比PoS的改进:
- 将币龄从等式中拿掉。新系统采用如下公式计算权益证明:
proofhash < 币数x目标值
点点币中,部分节点平时保持离线,只在积累了可观的币龄以后才连线获取利息,然后再次离线。
PoS 2.0中拿掉币龄,使得积攒币龄的方法不再有效,所有节点必须更多的保持在线,以进行权益累积。
越多的节点在线进行权益累积,系统遭遇51%攻击的可能性就越低。
黑币的PoS证明计算公式为:
proofhash < 币数x目标值
展开如下:
hash(nStakeModifier + txPrev.block.nTime + txPrev.nTime + txPrev.vout.hash + txPrev.vout.n + nTime) < bnTarget * nWeight
币数即nWeight,目标值即bnTarget。
DPOS
正常操作
在正常操作模式下,块生产者每3秒钟轮流生成一个块。假设没有人错过自己的轮次,那么这将产生最长链。块生产者在被调度轮次之外的任何时间段出块都是无效的。
为了便于理解,生成块的顺序为ABC,实际环境下,会根据算法不断调节顺序
少数分叉
不超过节点总数三分之一的恶意或故障节点可能创建少数分叉。在这种情况下,少数分叉每9秒只能产生一个块,而多数分叉每9秒可以产生两个块。这样,诚实的2/3多数将永远比少数(的链)更长。
离线少数的多重生产
(离线的)少数人可以试图产生无限数量的分叉,但是他们的所有分叉都将比多数人的那条链短,因为少数人在出块速度上注定比多数人来的更慢。
网络碎片化
网络完全有可能碎片化,导致没有任何分叉拥有多数块生成者。在这种情况下,最长的链将倒向最大的那个少数群体。当网络连通性恢复时,较小的少数群体会自然切换到最长的那条链,明确的共识将恢复。
多数生产者舞弊
tips:如果节点C也作弊呢?那这个币就废了
在线少数的多重生产
在这种场景下,少数节点B在其时间段内产生了两个或更多可供选择的块。下一个计划生产者(C)可以选择基于B产生的任何一种方案继续构建链条。一旦如此,这个选择就成为最长的链,而所有选择B1的节点都将切换分叉。少数不良生产者企图广播再多的替代块也无关紧要,它们作为最长链的一部分永远不会超过一轮。
网络分片
假定段1有11个节点,段2有10个节点,出块顺序是A-U
33秒后:段1产生11块,段2产生0块
63秒后:段1产生11块,段2产生10块
66秒后:段1产生12块,段2产生10块
99秒后:段1产生22块,段2产生10块
比特币交易的生命周期
创建比特币交易
拥有多少比特币由手里拥有的的UTXO决定
通过手里的私钥解锁UTXO,来证明对比特币(UTXO)的使用权
使用比特币时,需要用自己手里的私钥做数字签名,然后由比特币系统验证你对该比特币的拥有权
数字签名只能由私钥来创建
数字签名中并不包括私钥,所以在网络中传输很安全,
广播交易至比特币网络
比特币交易在比特币网络中的传播如下图
当所做的转账交易传播到一个节点时,该网络节点做的第一件事情就是验证该交易的合法性(交易的数据结构,数据签名是否有效,UTXO是否属于签名的私钥),若该交易不合法,则直接被抛弃,若该交易合法,则该网络节点把交易信息发给和它相连的其他节点
每当一个交易刚到一个节点时,该节点都会验证交易的合法性
比特币交易在比特币网络中的传播
所有节点都是对等的,每一个节点都会记录一些常用的节点
任何一个节点宕机或者退出网络,都不影响整个系统
任何一个节点加进来时也是非常容易的事情,对整个网络也没有影响
比特币交易结构
交易结构
tips:
- 如果
时钟时间
被设置为0,则意味着该交易立即执行。如果不是0并且该数值小于5亿,则认定是区块的高度,该交易在此高度的区块之后执行- 可以先有输出,后有输入:在coinbase,矿工挖到矿之后,系统会给矿工奖励
交易输出结构
交易输入的结构
tips:解锁脚本通常是私钥的签名
交易费
交易费=求和(所有输入)-求和(所有输出)
交易脚本和脚本语言
在比特币中,每一个交易输出中都有一个锁定脚本,想要花费这个UTXO,必须用解锁脚本解决“阻碍”
P2PKH(Pay-to-Public-Key-Hash)
锁定脚本:OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUAL OP_CHECKSIG
解锁版脚本是:<Cafe Signature> <Cafe Public Key>
两个脚本结合起来可以形成如下有效组合脚本:
<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160<Cafe Public Key Hash> OP_EQUAL OP_CHECKSIG‘
P2PK(Pay-to-Public-Key)
P2PK锁定版脚本形式如下:
<Public Key A> OP_CHECKSIG
用于解锁的脚本是一个简单签名:
<Signature from Private Key A>
经由交易验证软件确认的组合脚本为:
<Signature from Private Key A> <Public Key A> OP_CHECKSIG
该脚本只是CHECKSIG操作符的简单调用,该操作主要是为了验证签名是否正确,如果正确,则返回为真(Ture)。
多重签名
M <Public Key 1> <Public Key 2> ... <Public Key N> N OP_CHECKMULTISIG
2 <Public Key A> <Public Key B> <Public Key C> 3 OP_CHECKMULTISIG
<Signature B> <Signature C> 2 <Public Key A> <Public Key B> <Public Key C> 3 OP_CHECKMULTISIG
P2SH(Pay-to-Script-Hash)
2 <Mohammed's Public Key> <Partner1 Public Key> <Partner2 Public Key> <Partner3 Public Key> <Attorney Public Key> 5 OP_CHECKMULTISIG
2
04C16B8698A9ABF84250A7C3EA7EE-
DEF9897D1C8C6ADF47F06CF73370D74DCCA01CDCA79DCC5C395D7EEC6984D83F1F50C900A24DD47F569FD4193AF5DE762C58704A2192968D8655D6A935BEAF2CA23E3FB87A3495E7AF308EDF08DAC3C1FCBFC2C75B4B0F4D0B1B70CD2423657738C0C2B1D5CE65C97D78D0E34224858008E8B49047E63248B75DB7379BE9CDA8CE5751D16485F431E46117B9D0C1837C9D5737812F393DA7D4420D7E1A9162F0279CFC10F1E8E8F3020DECDBC3C0DD389D99779650421D65CBD7149B255382ED7F78E946580657EE6FDA162A187543A9D85BAAA93A4AB3A8F044DA-
DA618D087227440645ABE8A35DA8C5B73997AD343BE5C2AFD94A5043752580AFA1EC-
ED3C68D446BCAB69AC0A7DF50D56231BE0AABF1FDEEC78A6A45E394BA29A1EDF518C022DD618DA774D207D137AAB59E0B000EB7ED238F4D800 5 OP_CHECKMULTISIG
54c557e07dde5bb6cb791c7a540e0a4796f5e97
OP_HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e OP_EQUAL
P2SH(Pay-to-Script-Hash)
不含P2SH的复杂脚本
P2SH复杂脚本
P2SH(Pay-to-Script-Hash)
OP_HASH160 54c557e07dde5bb6cb791c7a540e0a4796f5e97e OP_EQUA
<Sig1> <Sig2> <2 PK1 PK2 PK3 PK4 PK5 5 OP_CHECKMULTISIG>
两个脚本经由两步实现组合。首先,将赎回脚本与锁定脚本比对以确认其与哈希是否匹配:
<2 PK1 PK2 PK3 PK4 PK5 5 OP_CHECKMULTISIG> OP_HASH160 <redeem scriptHash> OP_EQUAL
假如赎回脚本与哈希匹配,解锁脚本会被执行以释放赎回脚本:
<Sig1> <Sig2> 2 PK1 PK2 PK3 PK4 PK5 5 OP_CHECKMULTISIG
UTXO详解
在比特币中并没有账户的概念,也没有账户余额集中存储的一个地方
UTXO — Unspent Transaction Output
在比特币里,Transaction 被简称为 TX,所以上面这个短语缩写为 UTXO。
比特币的基本单位,不可分割,被所有者锁住,记录于区块链中被整个网络识别成货币单位。
经过三笔交易,Alice一共有3个UTXO。加一起一共是2.6个比特币,这个2.6的数字在比特币系统中是不存在的,没有地方存储这个2.6,只是分成3个UTXO,记录在区块链当中,不一定在一个区块,和发生交易的时间以及被打包进区块的时间有关系。
tips:图中第三笔交易找零数据错误,未来得及更改...
密钥&地址
一个随机生成的私钥(k),以十六进制格式表示(256位的二进制数,以64位十六进制数显示,每个十六进制数占4位):
1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD
K = G * 1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD
K = (x, y)
x=F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
y=07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB
x=F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
y=07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB
//K是对x,y的拼接
K = 04F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB
P2P网络架构&节点类型及分工
-
钱包:通常是桌面版钱包,移动端手机钱包
-
矿工:维护整个区块链数据打包的节点
-
完整区块链:包括完整的区块链交易数据的节点(数据量比较大)
-
网络路由节点:P2P的网络路由节点、stratum、移动钱包和P2P网络的交互,还有矿池的pool节点
节点类型
- 核心客户端:包含全部类型的节点
- 完整区块链节点:需要用到区块链所有数据的服务,比如查询地址上有多少钱
- 独立矿工:自己挖矿,存储完整区块链节点。如果不包含完整区块链,则需要访问完整区块链节点才可以挖矿(参考第6条)
- 轻量(SPV)钱包:
- 矿池协议服务器:比特币网络基本上是基于P2P的,但是矿池协议服务用的是Stratum协议还有Pool协议,通过Stratum和P2P做连接
6.挖矿节点:
7.轻量Stratum钱包:针对于移动端特性,一般不会将手机作为网络路由节点来使用,然后又需要访问整个比特币网络,故以Stratum协议和P2P网络进行交互获取信息
- 每台计算机都彼此对等,各个节点共同提供网络服务,不存在任何“特殊”节点。
- 每个网络节点以“扁平(flat)”的拓扑结构相互连通
- P2P网络的节点之间交互运作、协同处理:
每个节点在对外提供服务的同时也使用网络中
其他节点所提供的服务
P2P网络技术的特点
- 去中心化
- 扩展性强
- 健壮性高
- 高性价比
- 负载均衡
网络发现,区块同步
1. 对等节点之间的初始“握手”通信
tips:假定节点A是新节点,节点B是常驻节点
新节点加入之初要和对等节点握手通讯,
- 新节点怎么和其他对等节点联系到的呢?
答:客户端软件会包含常驻节点信息,如专门提供比特币服务的网站,独立矿工、矿池,他们的地址信息长期都是固定的。
- 新节点会包含不止一个常驻节点信息
version信息
- PROTOCOL_VERSION:常量,定义了客户端所“说出”的比特币P2P协议所采用的版本(例如:70002)。
- nLocalServices:一组该节点支持的本地服务列表,当前仅支持NODE_NETWORK
- nTime:当前时间
- addrYou:当前节点可见的远程节点的IP地址
- addrMe:本地节点所发现的本机IP地址
- subver:指示当前节点运行的软件类型的子版本号(例如:”/Satoshi:0.9.2.1/”)
- BaseHeight:当前节点区块链的区块高度
2. 地址广播及发现
- 节点A会把自己所有记录的对等节点信息发送给B
- 节点B拿到节点信息后(包含节点A的信息)广播给节点B已经连接的节点,让大家都知道节点A已经进来了。
- 节点A可以向节点B发送getaddr请求节点B的对等节点(节点A获得越多地址信息越稳固),但并不是拿到的节点信息越多越好,因为节点之间会发送请求,会增加自己的负担。
3. 节点通过从对等节点读取区块来同步区块链
inv(inventory):存储列表
tips:节点A拿到存储列表后,并不会只向节点B发送请求数据信息(getdata),因为在如果数据量很大的话(或与此同时很多节点都像节点B请求数据),节点B就不堪重负了。因为节点A节点B已经交换过对等节点信息了,所以就同时像其他对等节点请求数据。
SPV节点同步区块头
SPV:Simplified Payment Verification”(简单支付验证)
因为手机端硬盘容量有限,不可能下载整个block链,所以只下载区块头,区块头虽然不包含交易流水,但可以定义一个区块,因为里面存储了merkle树根还有其他信息。所以区块头可以作为验证数据。
tips:整个区块头的大小约是整个链的千分之一。
区块链数据结构
区块数据结构简单分为:区块头、区块体
区块结构
区块头
区块标识符
- 区块头哈希值:对区块头求得的Hash
- 区块高度
因为在某一高度,区块链可能存在分叉的情况,所以,一个高度可能代表好多个区块。
我们认为,在一个区块后有六个区块时,可以唯一确定这个区块
创世区块
创世区块的哈希值为:
0000000000 19d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
https://blockchain.info/block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
https://blockexplorer.com/block/
区块的连接
Merkle树和简单支付验证(SPV)
Merkle树
tips:
- 红色方框就是Merkle树
- Merkle树不一定是二叉树,根据需要而定,可以是三叉树... 但比特币中用的是二叉树
- Transakce两两一组,如果有奇数个Transakce,怎double自己一下完成组队。每组的TransakceHash各自hash后拼接在一起继续hash,循序渐进...
- Merkle在P2P中很常用,可以做数据完整性校验和补充下载
SPV:简单支付验证
从网络上获取并保存最长链的所有block header至本地;
SPV client在相连Peer注册感兴趣的地址:让相连的Peer在收到和我相关的交易时,通知我一下
- 相连Peer主动通知可能相关的Transaction:为什么是可能相关,因为Peer注册了很多的地址,用过滤的方法来判断,让收到消息的节点,只会多不会少,保证和Transaction相关的节点一定能收到。
- 计算该交易的hash值tx_hash;
- 定位到包含该tx_hash所在的区块,验证block header是否
包含在已知的最长链中;- SPV client下载包含该Transaction的Merkle Tree;
- 根据这些hash值计算merkle_root_hash;
- 若计算结果与block header中的merkle_root_hash相等,则
交易真实存在;- 根据该block header所处的位置,确定该交易已经得到多少个确认。