区块链学习(一)

从事C++服务器开发六年多了,主要是做并发服务器和游戏相关开发,区块链技术新兴起,自己也是很感兴趣,我是零基础学区块链的,给自己设定了一个规划,先读一读区块链相关的基础和概念,以及基本算法,然后用成熟的引擎做一个demo,接下来不断深入学习。

什么是区块链?

一两句话很难解释清楚,至少我自己还不能概括的很全面。我自己的理解是区块链技术包含了很多功能,如点对点传输,分布式数据存储,利用加密和共识算法实现数据的统一。区块链是多个技术的合理应用和创新,我觉得应该在以后的学习中不断去理解。

什么是比特币?

比特币是区块链比较成熟的应用,比特币依赖于区块链技术。

区块链的基本构成

区块链由一个个区块按照规律链接构成,每个区块中包含了很多交易。区块链的形成过程:交易是签过名的数据结构,该数据结构会在区块链网络中广播,并且被收集到区块中,然后区块会在区块链网络中广播,一个区块引用上一个区块从而形成区块链。区块链包括成千上万个区块, 而一个区块内又包含一个或多个交易, 上下关联的交易组成了一个交易链, 一个交易链内部可能又包含了多个交易。

4 比特币地址

比特币地址通常代表收款方,代表一对公钥和私钥的所有者,也可以代表其他。比特币地址是由数字和字母组成的字符串,由公钥生成的比特币地址以数字“1”开头。比特币地址有公钥经过Hash函数生成

交易的原理

交易实质上是包含一组输入列表和输出列表的数据结构,交易包含的结构如下:

一个交易的输入和输出样式:

Input表示交易的输入,一个交易的输入引用的是另一个交易的输出,该交易的输入从交易
f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6的0号输出中导入了50个比特币, 然后该输出发送50个比特币到一个比特币地址的公钥Hash值,404371705fa9bd789a2fcd52d2c580b65d35549d。同样道理,如果接受者想花掉50比特币,需要用output作为自己交易的输入。输入是对其他交易的输出的引用,一个交易可能有很多输入,Previous tx是以前交易的Hash值,Index是被引用交易的特定输出号,
ScriptSig是脚本的签名, Scriptpubkey是脚本的公钥,公钥属于交易输出的收款人, 并且表明交易创建者允许收款人获得的输出金额; 另一个部分是ECDSA签名, 是通过对交易的Hash值进行ECDSA签名而得到的。 签名和公钥一起, 证明原地址的真正所有者创建了该支付交易。
Value表示支付的金额,1BTC=100000000聪。

找零问题

当需要支付的金额小于可用余额时, 在交易信息中必须告诉比特币网络零钱将要被发送至哪个地址,即“找零地址”。 找零地址可能是也可能不是原先的发送地址。地址A发起付款到地址B, 但此时将找零地址更改为新生成的地址C,此时能保证交易的安全性。
如果找零地址不是C而是A,很多情况会被人追踪到一笔交易的流程。

上图中交易流程很难被推断出来。

区块和区块链

数据会以文件的形式被永久记录, 我们称这些文件为区块。 一个区块是一些或所有最新比特币交易的记录集, 且未被其他先前的区块记录。 新区块会被加入到记录的最后, 一旦写上, 就再也不能改变或删除。
区块结构:

区块头包含6个数据,如下

hashPrevBlock值为前一个块的256位Hash值,也就是前一个块的hashMerkleRoot。该字段使得各个区块之间可以连接起来,形成一个巨大的“链条”。 每个区块都必须要指向前一个区块, 否则无法通过验证。 这个区块链条会一直追溯到源头, 也就是指向创世区块。 创世区块的hashPrevBlock的值为零或为空。 在区块头中, 随机数Nonce对每个块唯一。求Nonce没有固定的算法,Nonce有很多值,找到一个满足条件即可。所以要求不断尝试找到合适的Nonce为止,这个过程就是挖矿。
区块内包含许多交易, 它们通过Merkle根节点间接被散列, 以保证矿工能及时追踪一个正在打包的区块内交易的变化情况。 一旦生成Merkle根节点, 那么对包含一个交易的区块做散列所花的时间,对包含1万个交易的区块做散列所花的时间是一样的。目标Hash值的压缩格式是一个特殊的浮点编码类型, 首字节是指数 , 后3个字节是尾数, 它能表示256位的数值。
一个区块头的SHA-256(一种单向函数的算法, 可形成长度为256位的串) 值必定要小于或等于目标Hash值, 该区块才能被网络所接受。 目标Hash值越低, 产生一个新区块的难度就越大。Merkle树是Hash的二叉树。 在比特币中会两次使用SHA-256算法来生成Merkle树, 如果叶子个数为奇数, 则要重复计算最后一个叶子的两次SHA-256值, 以达到偶数叶子节点的要求。想象有3个交易, a、 b、 c, 那么Merkle根的生成过程如下所示:
计算a交易的hash值

d1 = dhash(a)
d2 = dhash(b)
d3 = dhash(c)
由于只有3个元素, 是奇数, 因而将最后一个元素重算一次
d4 = dhash(c)
接下来将上面产生的hash值两两计算
d5 = dhash(d1 concat d2)
d6 = dhash(d3 concat d4)
d7 = dhash(d5 concat d6)

这里的d7就是以上三个交易的Merkle根。 需要注意的是, Merkle树的Hash值是小头位序。

区块链原理和分叉


对于区块链中的任何区块来说, 只有一条通向创世块的路径。 然而, 从创世块出发, 却可能有分叉。 当两个区块产生的时间仅相差几秒时, 可能会产生包含一个区块的分叉。 当出现以上现象时, 矿工节点会根据收到区块的时间, 在先收到的区块的基础上继续挖矿。 哪个区块的后续区块先出现, 那么这个区块就会被包括进主链, 因为这条块链更长。短区块链(或有效区块链) 中的区块没有作用, 当比特币客户端转向另一个长区块链时, 短区块链中所有有效的交易都将被重新加入到交易队列池中, 并被包括到另一个区块中。 短区块链中的区块收益不会在长链中出现, 因而这些收益实际上是丢失了, 这就是比特币网络设定100个区块成熟时间的原因。

挖矿原理

比特币的挖矿和节点软件是基于对等网络、 数字签名来发起和验证交易的。 节点向网络广播交易, 这些广播出来的交易需要经过矿工的验证, 矿工们会用自己的工作证明结果来表达确认, 确认后的交易会被打包到数据块中, 数据块会串起来形成连续的数据块链。
每一个比特币的节点都会收集所有尚未确认的交易, 并且会将其归集到一个数据块中, 这个数据块将和前面一个数据块集成在一起。 矿工节点会附加一个随机调整数, 并计算前一个数据块的SHA-256 Hash运算值。 挖矿节点不断进行重复尝试, 直到它找到的随机调整数使得产生的
Hash值低于某个特定的目标为止。 由于Hash运算是不可逆的, 因此寻找到符合要求的随机调整数将会非常困难, 因此需要一个可以预计总次数的不断试错的过程。 这时, 工作量证明机制就发挥作用了。 当一个节点找到了符合要求的解, 那么它就可以向全网广播自己的结果。 其他节点就可以接收这个新解出来的数据块, 并检验其是否符合规则。 只要其他节点通过计算Hash值发现其确实满足要求(比特币要求的运算目标) ,那么该数据块就是有效的, 其他的节点就会接受该数据块, 并将其附加在自己已有的链条之后.

Nonce随机数通常都不会相同, 但是它以严格的线性方式在增长,从0开始, 每次执行散列时都会增长, 当Nonce溢出时(此事经常发生) , 挖矿交易的extraNonce项就会增长, 其将改变Merkle树的根节点.

挖矿难度

挖矿难度是对挖矿困难程度的度量, 即指计算符合给定目标的一个Hash值的困难程度。 比特币网络有一个全局的区块难度, 有效的区域必须有一个Hash值, 该Hash值必须小于给定的目标Hash值。

难度计算公式如下:
diff = diff_1_target / target
目标值是一个很大的数字,这里出现了一个 diff_1_target,这是常数,是一个很大的数字,这个数字也被称作是矿池难度,即矿池挖矿时的最大难度。这个最大难度值是标记为0x1d00ffff的数,这个标记是压缩标记,它的实际值是:

1
0x00ffff * 2**(8*(0x1d - 3)) = 0x00000000FFFF00000000000000000000000000000000000000000000000000。

计算时,后面三个字节作为底,前面一个字节1d表示的是次方数,最终得出上面这个数字,挖矿时矿池也可以保留的尾数,即
0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

而比特币的挖矿难度,根据上面的公式可知,它和diff_1_target及当前网络目标值(target)有关,将diff_1_target值代入,得到:
diff = 0x1d00ffff / target
在调整难度的时候,只需要调整target大小即可,target越小,难度越大,反之,难度越小。矿池一般用后面全是FF的值来代表diff_1_target,计算出来的难度就叫做矿池难度pdiff,如果用后面全是00的值来代表diff_1_target,那么计算出来的难度值是比特币客户端难度bdiff。这里只是说明,它们有两个值,代表不同计算方式,实际上,它们计算出来的难度并不会相差很远。
网络调整难度的目的,是为了调整出块的速度保持在平均10分钟1个块,每2016个块作为一个周期调整,这样刚好2周作为一个周期,如果这2016个块中,平均出块速率快过10分钟1个块,那么难度将会增大到,维持这个难度的情况下,满足10分钟出一个块的水平。什么时候调整难度呢?由于2016的周期从来没有变过,那么该周期内还剩余的区块数量是可以计算出来的:
该周期剩余区块数量 = 2016 - (当前区块高度 % 2016)
以当前最新一个块 482017 为例
当前高度 % 2016 = 482017 % 2016 = 193
该周期剩余区块数量 = 2016 - 193 = 1823
也即该周期内才出193个区块,得等到1823个块以后才会调整难度,对于BCC来说,也是一样的。

挖矿收益计算

挖矿时,计算出来的区块哈希值,是要小于当前target值的,这个哈希值是一个范围很大的值(从0到(2^256)-1),只有靠矿机的暴力破解,才能算出这个值。
diff_1_target,即0x00000000FFFF0000000000000000000000000000000000000000000000000000 , FFFF后面有26个字节,

123456789101112131415161718192021222324
即8*26 = 208位,所以diff_1_target又可以写成 0xffff*(2**208)。如果当前难度是D的话,那么根据上面我们讲过的公式diff = diff_1_target / target那么target = (0xffff * (2 ** 208)) / D需要要搜索出这个target值,需要计算的哈希次数是2 ** 256 / target将D移到左边,得到D * (2 ** 256) / (0xffff * (2 ** 208))将2 ** 208移到左边,得到D * (2 ** 256) / (2 ** 208) / 0xffff化简得到D * (2 ** 48) / 0xffff也即10分钟(600秒)内要计算这么多次,才能得到一个块,那么平均每秒就是:D * (2 ** 48) / 0xffff / 600将0xffff写成十进制是2 ** 16D * (2 ** 48) / (2 ** 16) / 600化简得到D * (2 ** 32) / 600假设现在全网难度是888171856257,那么平均要计算 6357781793085713285次哈希运算才能得到一个块。我们不妨用现在的算力验证一下,现在的全网算力是5.68 EH/s, 大概接近这个值。难度和算力的关系我们已经看出来了,难度越大,需要的算力就越大。那么以单位为1Th/s的云合约标准算力来计算,一天的收益能够达到多少呢?一天能够计算的哈希次数 = 1T * 86400假设当前难度为D,那么收益 = 1T * 86400 / D / ( 2 * 32) * 600* 块收益

脚本系统

脚本操作码很多,自己去查查吧。下面简述下脚本工作原理。
以下为三个交易的关系图,一个交易的输出是下一个交易的输入。

交易的关系数据图:

交易a hash值为

交易b hash值为

交易a的输出脚本, 若干个脚本指令和转账接收方的公钥Hash

交易b的输入脚本, 这么一长串只是两个元素, 签名和公钥

首先执行的是输入脚本。 因为脚本是从左向右执行的, 那么先入栈的是签名, 随后是公钥。 接着, 执行的是输出脚本。 从左向右执行, 第
一个指令是OP_DUP——复制栈顶元素

OP_HASH160用于计算栈顶元素Hash, 得到pubkeyhash

然后将输出脚本中的公钥Hash入栈, 为了与前面计算中所得到的Hash区别开来, 这里称它为pubkeyhash’

OP_EQUALVERIFY则会检查栈顶前两个元素是否相等, 如果相等则继续执行, 否则中断执行, 返回失败

OP_CHECKSIG使用栈顶前两个元素执行签名校验操作, 如果相等, 则返回成功, 否则返回失败

没看懂?再来一遍
以著名的Pizza Transaction为例,来验证一个交易是否是有效的
在交易cca75078…4d79中,唯一的TxIn输入提供的sigScript是:

1234567
8b4830450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e0141042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb

该sigScript实际上由两部分构成:
签名:30450221…ee0e01(71字节+1字节签名类型),实际签名是去掉最后一个字节01的30450221…ee0e,签名类型是SIGHASH_ALL(0x01)。
公钥:042e930f…cabb(65字节)
为了验证该交易是否有效,我们首先要根据TxIn所声明的Previous Output Hash:a1075db5…d48d和索引0找到上一笔交易的输出a1075db5…d48d。
这笔交易输出的脚本是:
1976a91446af3fb481837fadbb421727f9959c2d32a3682988ac
比特币的脚本由一系列指令和数据构成,每个指令占用一个字节,数据由数据头部的长度决定。上述二进制脚本翻译后的比特币指令如下
OP_DUP OP_HASH160 46af3fb4…6829 OP_EQUALVERIFY OP_CHECKSIG
现在,我们有了签名,公钥和脚本:
sig: 30450221…ee0e01
pubkey: 042e930f…cabb
script: OP_DUP OP_HASH160 46af3fb4…6829 OP_EQUALVERIFY OP_CHECKSIG
就可以运行这个脚本来验证交易是否有效。
比特币脚本被设计成以栈来运行的虚拟机指令,它只有有限的几种指令,并且故意被设计成没有循环、条件跳转,所以,比特币脚本不是图灵完备的语言。
比特币脚本的执行非常简单。我们首先要准备一个空栈,然后把签名和公钥入栈:

紧接着,我们就可以执行TxOut的脚本:
OP_DUP OP_HASH160 46af3fb4…6829 OP_EQUALVERIFY OP_CHECKSIG
首先执行OP_DUP,这条指令把栈顶的元素复制一份,所以结果变成:

紧接着执行OP_HASH160,它对栈顶元素计算SHA256/RipeMD160,实际上是计算公钥Hash,所以运行结果变成

接下来的指令实际上是一个数据,我们直接把数据入栈:

然后,执行OP_EQUALVERIFY,这条指令会比较栈顶的两个元素是否相等,如果不等,整个脚本就执行失败了,如果相等,脚本会继续执行,所以运行结果变成

最后,执行指令OP_CHECKSIG,这条指令会验证签名.
其实脚本的验证过程就是根据自己的输入将签名和公钥入栈,根据上一个交易的输出脚本指令依次执行,判断结果是否和上一个交易要求的公钥地址匹配。换言之,谁能根据我输出脚本的规则计算出符合我要求的公钥地址,谁就能使用这笔交易。

由于引入了脚本,我们可以看到,比特币实际上通过编程脚本实现了一个严格以计算机程序验证为基础的数字货币所有权的转移机制。由于计算机程序的可扩展性,比特币支付其实并不限定在必须支付给某一个公钥地址。利用脚本,我们可以构造出各种支付条件,例如,多重签名验证条件:

2 3 OP_CHECKMULTISIGN
这种提供多个公钥地址,并且需要多个签名验证的多重签名脚本,允许在M个签名种至少给出N个签名即可使用。上述脚本允许提供3个公钥地址中的任意两个有效签名。

当我们把比特币托管在某个第三方的在线钱包中时,就可以使用多重签名来保证只有自己和第三方钱包共同签名后才可动用输出,这样保证了黑客在攻击了第三方钱包后也无法花掉用户的比特币。

通过OP_CHECKLOCKTIMEVERIFY,我们可以指定一个交易的锁定时间,在此之前,该交易输出无法被花掉。这个指令其实实现了支付宝的7天资金锁定然后再支付给卖家的功能。

还有一些交易并没有指定一个公钥Hash,例如,这个交易的脚本如下:

OP_HASH256 6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 OP_EQUAL
它的意思是说,谁能够提供一个数据,它的SHA256是6fe28c0a…0000,谁就可以花费这笔交易

我的公众号:

QQ交流群:685914495

原文地址:https://www.cnblogs.com/secondtonone1/p/8996332.html

时间: 2024-10-10 04:11:15

区块链学习(一)的相关文章

区块链学习记录

[深度]终于把区块链的技术与应用讲清楚了(57张PPT) bitcoin 比特币源码学习笔记(一) VC编译调试比特币源码 以太坊官网 以太坊Github 以太坊go-ethereum项目源码本地环境搭建

区块链学习路线

2018年春节最火热的概念应该就是区块链了,从百度的莱茨狗和网易星球刷屏朋友圈,到3点钟区块链无眠群的大火, 大佬们纷纷进军区块链,不了解区块链好像错过了什么,这里把自己学习区块链过程中的一些资料进行索引,可以循序渐进的了解区块链技术及其应用. 一.目标 比特币发展历史,挖矿以及相关应用 区块链底层技术,如共识算法, 侧链技术, 密码学知识等,理解PKI基本知识和原理 研究以太坊技术,了解ERC20,能够自行开发DAPP 熟悉Hyperledger Fabric 1.0架构,了解其业务流程和设计

区块链学习(2)--以太坊中基本概念

1.以太币单位换算.以太坊的单位,沿袭了科学界的传统,用做过杰出贡献的数学.密码学专家的名字命名.以太坊的最小单位是 Wei. Kwei(Babbage)= 10 的 3 次方 Wei Mwei(Lovelace)= 10 的 6 次方 Wei Gwei(Shannon)= 10 的 9 次方 Wei MicroEther(Szabo)= 10 的 12 次方 Wei MilliEther(Finney)= 10 的 15 次方 Wei Ether = 10 的 18 次方 Wei 2.以太坊账

区块链学习之:区块链初识

区块链初识: 区块链是一种特殊的分布式数据库技术的实现. 区块链的主要作用是储存信息.任何需要保存的信息,都可以写入区块链,也可以从里面读取,所以它是数据库. 其次,任何人都可以架设服务器,加入区块链网络,成为一个节点.区块链的世界里面,没有中心节点,每个节点都是平等的,都保存着整个数据库.你可以向任何一个节点,写入/读取数据,因为所有节点最后都会同步,保证区块链一致. 分布式数据库并非新发明,市场上早有此类产品.但是,区块链有一个革命性特点. 区块链没有管理员,它是彻底无中心的.其他的数据库都

剑英的区块链学习手记(一)

开篇布拉拉 因为参与了小蚁的c#智能合约编译器的开发,让我第一次近距离接触到区块链技术. 以前我对区块链技术的了解,只知道有一种叫做比特币的玩意儿,以前有同事在几百块一个比特币的时候屯了一批,后来价格炒高了,一下子成了人生赢家. 完全外行的了解,但是这个例子让我有了一个原始的理解,这玩意儿和钱有关系. 后来有幸获得小蚁核心开发者张铮文的面授,讲了些啥没记住,就记住了他掏出钱包的帅气身姿. 这给我留下了更深的印象,区块链技术,谈的就是钱. 铮文对区块链的定义是状态机,去中心化的分布式的状态机. 虽

区块链学习一基本知识

一.什么是区块链 在符合现实社会法律法规前提下,可治理的,依赖于密码学算法和博弈经济性设计,基于共识算法,对发生在主体间的价值创造,价值转移,价值交换,以及涉及到各个价值主体由机器驱动的业务流程,在多个对等的主体间形成的共识,从而达到共享业务状态,共享价值状态,即共享账本,加速资源配置和价值流通,最终提高生产力的目的. 区块链的本质是共识,共识才能形成公认的价值. 二.区块链的共性1.共识(consensus)区块链的本质是共识,共识才能形成公认的市场价值. 2.可验证性(validity) 3

区块链学习一

一.区块链的本质 区块链是什么?一句话,它是一种特殊的分布式数据库. 首先,区块链的主要作用是储存信息.任何需要保存的信息,都可以写入区块链,也可以从里面读取,所以它是数据库. 其次,任何人都可以架设服务器,加入区块链网络,成为一个节点.区块链的世界里面,没有中心节点,每个节点都是平等的,都保存着整个数据库.你可以向任何一个节点,写入/读取数据,因为所有节点最后都会同步,保证区块链一致. 二.区块链的最大特点 分布式数据库并非新发明,市场上早有此类产品.但是,区块链有一个革命性特点. 区块链没有

区块链学习--win10下构建以太坊私链

构建以太坊私链1.环境是win10,下载对应的最新版本Ethereum-Wallet-win64-0-10-0.ziphttps://github.com/ethereum/mist/releases 2.解压到指定目录即可,运行Ethereum-Wallet初始化数据,私链搭建无需同步 3.初始化的相关数据,如用户为:administrator,则在系统生成目录:C:\Users\administror\AppData\Roaming\Ethereum WalletC:\Users\hehei

区块链学习(5)比特币网络

比特币采用了P2P(peer-to-peer)网络架构.P2P是指位于同一网络中的每台计算机都彼此对等,不存在任何"特殊"节点.P2P网络中不存在中心化的服务,计算机网络中的课程已经讲过了P2P,不过为了更好了解的P2P,先看下中心化的网络结构. 从图中可以看出中心化的结构节点直接的通讯通过一个中心化的服务器来传输.日常生活中这种中心化的结构还是比较常见的,像银行转账,银行就是这个中心话的节点.羡慕再看看P2P. 可以看出P2P的网络中每个节点之间可以相互通信,没有中心化的节点.一个结