比特币是什么
比特币是一种基于分布式网络的数字货币。
比特币系统(广义的比特币)则是用来构建这种数字货币的网络系统,是一个分布式的点对点网络系统。
数字货币是什么
凯恩斯在《货币论》上讲,货币可以承载债务,价格的一般等价物。货币的本质是等价物,它可以是任何东西,如:一张纸,一个数字,只要人们认可它的价值。人民币,美元等作为国家信用货币,其价值由国家主权背书。
而数字货币是一种不依赖信用和实物的新型货币(一串数字),它的价值由大家的共识决定。比特币就是一种数字货币。(我们在网银,微信,支付宝的金额,准确来讲,它是信用货币的数字化,不是数字货币,不过央行也在研究比特币,准备发行数字货币)
信任从何而来:
-
财产只受自己的控制(私钥)
-
无通胀(总量不变2100万个)
-
没有假钞(任何作弊的支付都无法完成其他矿工的确认)
-
流通性好(国际汇款,需要时间很多(中间有很多的环节),但是它是点对点的直接到账)
运行原理
大家知道,在银行系统的数据库里记录着跟我们身份 id
对应的财产,下文称这样的记录为账本,如张三的卡 10 月 1 日转入 1w
, 余额 10w
。
比特币系统(去中心化的记账系统)也同样有这样的账本,不同银行由单一的组织负责记录,比特币的记账由所有运行系统的人(即节点,可以简单理解为一台电脑)共同参与记录,每个节点都保存(同步)一份完整的账本。
同时使用简单多数原则,来保证账本的一致性。举个例子:如果有人在自己电脑上把自己的余额从 1 万改为 1 百万,他这个账本和大多数人的账本不一致,就会被比特币系统认为是无效的。
比特币原理
账本如何验证?说明哪个账本是有效的
假设有一个账页 序号为 0
的账页交易记录如下:
账号 | 入账 | 出账 | 余额 |
---|---|---|---|
王二 | 100 | 190 | |
张三 | 100 | 30 | |
李四 | 120 | 90 | 170 |
记账时间为:2017-10-22 10:22:02
如果此时张三将余额30改变为了300,此时如何来说明哪个账本有效呢?
方案一: 核对账本记录,少数服从多数(存在海量的数据,效率比较底下)
方案二:Hash
哈希函数:Hash (原始信息) = 摘要信息
原始信息可以是任意的信息,hash 之后会得到一个简短的摘要信息
哈希函数有几个特点:
- 同样的原始信息用同一个哈希函数总能得到相同的摘要信息
- 原始信息任何微小的变化都会哈希出面目全非的摘要信息
- 从摘要信息无法逆向推算出原始信息
区块链在记账是会把账页信息(包含序号、记账时间、交易记录)作为原始信息进行 Hash, 得到一个 Hash 值,如:787635ACD
, 用函数表示为:
Hash(序号0,记账时间,交易记录) = 787635ACD
账页信息和 Hash 值组合在一起就构成了第一个区块。
比特币系统里约 10 分钟记一次账,即每个区块生成时间大概间隔 10 分钟
在记第 2 个账页的时候,会把上一个块的 Hash 值和当前的账页信息一起作为原始信息进行 Hash, 即:
Hash(上一个Hash值,序号1,记账时间,交易记录) = 456635BCD
这样第 2 个区块不仅包含了本账页信息,还间接的包含了第一个区块的信息。依次按照此方法继续记账,则最新的区块总是间接包含了所有之前的账页信息。
所有这些区块组合起来就形成了区块链,这样的区块链就构成了一个便于验证(只要验证最后一个区块的 Hash 值就相当于验证了整个账本),不可更改(任何一个交易信息的更改,会让所有之后的区块的 Hash 值发生变化,这样在验证时就无法通过)的总账本。
所有权问题?说明谁拥有这个货币
我们先来回顾下现实的银行系统:
- 首先我们需要把我们的个人信息(如身份证)给银行,银行给我们开立相对应的账户,银行在开户的时候确立了对账户的所有权。
- 进行支付的时候,银行对交易双方完成转账(银行在开户的时候已经知道我们对应的账户)。
同时银行会对账户信息进行保密(这点其实不能保证)。
那么比特币如何在没有第三方银行的参与下,在确保隐私的同时如何确定账户所有权的呢?
实际上比特币的账户是用地址来表示,账本上不显示个人信息,转账是把比特币从一个地址转移到另一个地址。
转账记录如这样:
{
"付款地址":"2A39CBa2390FDe",
"收款地址":"AAC9CBa239aFcc",
"金额":"0.2btc"
}
接下来问题就变为了 谁有权用某个地址进行付款。
支付和所有权 实际是同一个问题,如果此比特币只有我可以用来支付,那么说明我拥有所有权
比特币的解决方案是,谁拥有某个地址的私钥 (如果完全没有加密概念的人,可以简单的把私钥当作密码),谁就能用这个地址进行支付。(所以私钥一定保管好,如果私钥泄漏,比特币就可能丢失)
比特币地址和私钥是一个非对称的关系,私钥经过一系列运算(其中有两次 Hash)之后,可以得到地址,但是无法从地址反推得到私钥。
地址: 2A39CBa2390FDe
私钥: sdgHsdniNIhdsgaKIhkgnakgaihNKHIskdgal
Hash(Hash(fun(sdgHsdniNIhdsgaKIhkgnakgaihNKHIskdgal))) -> 2A39CBa2390FDe
银行系统银行账号和密码是完全独立的,无法互相推导,转出时需要同时验证账号和密码
这个时候问题就变为了,如何证明你拥有某个地址的私钥(在不泄漏私钥的情况下,因为私钥泄露了,别人也就可以用私钥进行对地址交易,因此就用到了非对称加密技术,需要有公钥和私钥)。
对交易信息进行签名
实际在签名之前,会先对交易信息进行 Hash 运算得到摘要信息,然后对摘要信息进行签名。过程大概是这样:
- 对交易进行 hash, 得到一个摘要信息(Hash 值)
hash('{
"付款地址":"2A39CBa2390FDe",
"收款地址":"AAC9CBa239aFcc",
"金额":"0.2btc"
}') -> 8aDB23CDEA6
- 用私钥对交易摘要进行签名(付款方在安全的环境下进行,以避免私钥泄密), 用代码表示大概是这样。
# 参数1为交易摘要
# 参数2为私钥
# 返回签名信息
sign("8aDB23CDEA6", "J78sknJhidhLIqdngalket") -> "3cdferdadgadg"
广播
在签名运算之后,付款节点就开始在全网进行广播:我支付了 0.2btc
到 AAC9CBa239aFcc
, 签名信息是 3cdferdadgadg
,你们来确认一下吧。
广播过程实际上是发信息到相连的其它节点,其它节点在验证通过后再转发到与之相连的节点,这样的扩散过程。
广播的信息包含了交易原始信息和签名信息
验证
其它节点在收到广播信息之后,会验证签名信息是不是付款方用私钥对交易原始信息签名产生的,如果验证通过说明确实是付款方本人发出的交易,说明交易有效,才会记录到账本中去。
(实际还会验证付款账号有没有足够的余额,我们暂时忽略这点)
验证过程实际是签名过程的逆运算,用代码表示大概过程是这样的:
# 参数1为签名信息
# 参数2为付款方地址
# 返回交易摘要
verify("3cdferdadgadg", "2A39CBa2390FDe") -> "8aDB23CDEA6"
如果验证输出的信息和原始交易信息的 hash 一致,则验证通过,记录账本,用代码表示大概是这样:
if(verify("3cdferdadgadg", "2A39CBa2390FDe")
== hash('{"付款地址":"2A39CBa2390FDe",
"收款地址":"AAC9CBa239aFcc",
"金额":"0.2btc"}')) :
# 写入账本
# 广播
else:
# donothing
大家可以理解为付款地址为公钥,签名过程即为用私钥对交易摘要的加密过程,验证过程为用公钥解密的过程 (为方便大家理解,严格来讲是不准确的)。
为什么记账?(挖矿)
我们知道所有的计算和存贮是需要消耗计算机资源的(记账的过程),既然要付出成本,那节点为什么还要参与记账呢?在中本聪(比特币之父)的设计里,完成记账的节点可以获得系统给与的一定数量的比特币奖励,这个奖励的过程也就是比特币的发行过程,因此大家形象的把记账称为 “挖矿”,本文将详细讨论这个过程。
由于记账是有奖励的,每次记账都可以给自己凭空增加一定数量的个比特币(当前是 12.5 比特币,写作时每个比特币是 4 万人民币以上,大家可以算算多少钱),因此就出现大家争相记账,大家一起记账就会引起问题:出现记账不一致的问题,比特币系统引入工作量证明来解决这个问题,规则如下:
- 一段时间内(10 分钟左右,具体时间会与密码学难题难度相互影响)只有一人可以记账成功
- 通过解决密码学难题(即工作量证明)竞争获得唯一记账权
- 其他节点复制记账结果
工作量证明
我们了解到,每次记账的时候会把上一个块的 Hash 值和当前的账页信息一起作为原始信息进行 Hash。 如果仅仅是这样,显然每个人都可以很轻松的完成记账。 为了保证 10 分钟左右只有一个人可以记账,就必须要提高记账的难度,使得 Hash 的结果必须以若干个 0 开头。同时为了满足这个条件,在进行 Hash 时引入一个随机数变量。 用伪代码表示一下:
Hash(上一个Hash值,交易记录集) = 456635BCD
Hash(上一个Hash值,交易记录集,随机数) = 0000aFD635BCD
我们知道改变 Hash 的原始信息的任何一部分,Hash 值也会随之不断的变化,因此在运算 Hash 时,不断的改变随机数的值,总可以找到一个随机数使的 Hash 的结果以若干个 0 开头,率先找到随机数的节点就获得此次记账的唯一记账权。(比特币的矿工很多,是以18个0开头)
交易记录集,在进行工作量证明之前,记账节点会做进行如下准备工作:
- 收集广播中还没有被记录账本的原始交易信息
- 检查每个交易信息中付款地址有没有足够的余额
- 验证交易是否有正确的签名
- 把验证通过的交易信息进行打包记录
- 添加一个奖励交易:给自己的地址增加 12.5 比特币
如果一个节点能够比别人更快的找到这个Hash的结果,那么整个交易就会被打包成区块记录到区块链中
我们简单分析下记账难度有多大,
Hash 值是由数字和大小写字母构成的字符串,每一位有 62 种可能性(可能为 26 个大写字母、26 个小写字母,10 个数字中任一个),假设任何一个字符出现的概率是均等的,那么第一位为 0 的概率是 1/62(其他位出现什么字符先不管),理论上需要尝试 62 次 Hash 运算才会出现一次第一位为 0 的情况,如果前两 2 位为 0,就得尝试 62 的平方次 Hash 运算,以 n 个 0 开头就需要尝试 62 的 n 次方次运算。
我们可以看到 Hash 值以 18 个 0 开头,理论上需要尝试 62 的 18 次方次,这个数是非常非常巨大的,我已经算不清楚了,应该是亿亿级别以上了。如此大的计算量需要投入大量的计算设备、电力等,目前应该没有单矿工独立参与挖矿了,基本都是由矿工联合起来组成矿池进行挖矿(矿池里的矿工按算力百分比来分收益)。
从经济的角度讲,只有挖矿还有收益(比特币价格不断上涨也让收益变大),就会有新的矿工加入,从而加剧竞争,提高算力难度,挖矿就需要耗费更多的运算和电力,相互作用引起最终成本会接近收益。
题外话:国内由于电力成本较低,相对收益更高,中国的算力占整个网络的一半以上
在节点成功找到满足的 Hash 值之后,会马上对全网进行广播打包区块,网络的节点收到广播打包区块,会立刻对其进行验证。
如果验证通过,则表明已经有节点成功挖出区块,自己就不再竞争当前区块打包,而是选择接受这个区块,记录到自己的账本中,然后进行下一个区块的竞争猜谜。
网络中只有最快解谜的区块,才会添加的账本中,其他的节点进行复制,这样就保证了整个账本的唯一性。
以谁的账本为准?(共识机制)
比特币没有中心机构,几乎所有的完整节点都有一份公共总帐本,那么大家如何达成共识:确认哪一份才是公认权威的总账本呢?
我们了解通过工作量证明来竞争记账,权威的总帐本是怎么达到共识的,没有完全说清楚,今天补上,实际上,比特币的共识由所有节点的 4 个独立过程相互作用而产生:
每个节点(挖矿节点)依据标准对每个交易进行独立验证
挖矿节点通过完成工作量证明,将交易记录独立打包进新区块
每个节点独立的对新区块进行校验并组装进区块链
每个节点对区块链进行独立选择,在工作量证明机制下选择累计工作量最大的区块链
共识最终目的是保证比特币不停的在工作量最大的区块链上运转,工作量最大的区块链就是权威的公共总帐本。
最长链的选择
先来一个定义,把累计了最多难度的区块链。在一般情况下,也是包含最多区块的那个链称为主链
每一个(挖矿)节点总是选择并尝试延长主链。
当有两名矿工在几乎在相同的时间内,各自都算得了工作量证明解,便立即传播自己的 “获胜” 区块到网络中,先是传播给邻近的节点而后传播到整个网络。每个收到有效区块的节点都会将其并入并延长区块链。
当这个两个区块传播时,一些节点首先收到 #3458A
, 一些节点首先收到 #3458B
,这两个候选区块(通常这两个候选区块会包含几乎相同的交易)都是主链的延伸,分叉就会产生,这时分叉出有竞争关系的两条链,如图:
两个块都收到的节点,会把其中有更多工作量的一条会继续作为主链,另一条作为备用链保存(保存是因为备用链将来可能会超过主链难度称为新主链)。
收到 #3458A
的(挖矿)节点,会立刻以这个区块为父区块来产生新的候选区块,并尝试寻找这个候选区块的工作量证明解。同样地,接受 #3458B
区块的节点会以这个区块为链的顶点开始生成新块,延长这个链(下面称为 B 链)。
这时总会有一方抢先发现工作量证明解并将其传播出去,假设以 #3458B
为父区块的工作量证明首先解出,如图:
当原本以 #3458A
为父区块求解的节点在收到 #3458B
, #3459B
之后,会立刻将 B 链作为主链(因为 #3458A
为顶点的链已经不是最长链了)继续挖矿。
来源:CSDN
作者:frewenwang
链接:https://blog.csdn.net/fuziwang/article/details/103494122