mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2024-11-19 18:43:38 +00:00
173 lines
16 KiB
Java
173 lines
16 KiB
Java
最近总是能在一些网站上看到比特币大涨的消息,诺,这不都涨破20000美元啦。
|
||
|
||
最近比特币涨势喜人,牵动着每一位股民的心,持有的老哥后悔说当时我咋就没多买点呢,不然明天早饭又能多加个鸡蛋啦,没持有的呢,就在懊恼后悔当时为啥就没买入呢?这不我女朋友也看到新闻了,说比特币最近涨那么厉害,咱们要不买两个呀!然后这个总是听到的比特币到底是什么东西呀?
|
||
|
||
你说那个比特币呀,我也不是很懂,知道一点点,我给你讲一下我知道的吧。
|
||
|
||
**注:本文和股票无关,单纯的介绍一下比特币原理,投资有风险,入场需谨慎**
|
||
|
||
> 关键词 :比特币,去中心化,挖矿,区块链,双重支付,最长链原则,工作量证明
|
||
|
||
我先给你说一下比特币的历史吧。
|
||
|
||
> 2008年爆发全球金融危机,同年11月1日,一个自称中本聪(Satoshi Nakamoto)的人在P2P foundation网站上发布了比特币白皮书《比特币:一种点对点的电子现金系统》 陈述了他对电子货币的新设想——比特币就此面世。2009年1月3日,比特币创世区块诞生。
|
||
|
||
你平时不是会把每天的收入和支出记在自己的小本本上,我们称之为记账。我们平常在消费的时候,银行也会为我们记录这条交易记录及交易后银行卡里的余额。然后我们会通过银行卡里数字来评估自己拥有的财富。所以我们拥有多少财富都通过银行的记账本来决定的。
|
||
|
||
**中本聪**在**2008**年提出,其实我们可以不需要一个**中心化**的记账系统,不需要以某个人或者机构为中心来帮我们记账,我们可以**去中心化**,每一个人的账本都是透明公开的,这就叫做**去中心化电子记账系统**。下面我们通过一个例子来进行描述。
|
||
|
||
![区块](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/区块.3wdvlln33q60.png)
|
||
|
||
### 1.那你说的那个区块链到底是什么东西呀,我不是很懂哎?
|
||
|
||
我们对上图进行解析,A,B,C,D,四个小伙伴进行交易,首先 A 支付 5 个比特币给 B,那么他需要将这条交易信息发送给每位小伙伴,同理 B 和 C,C 和 D的交易也要传送给所有的小伙伴,用户会将这些交易信息记录下来,并打包成块,我们称之为**区块**,(区块大小约为1M,约4000条左右交易记录),当块存满时我们将这个块接到以前的交易记录上,形成一条链,过一段时间再把新的块接到它后面,我们称这条链为**区块链**,如下图。
|
||
|
||
![区块链](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/区块链.2s1tuiwa4ba0.png)
|
||
|
||
|
||
好啦,我们大概了解什么是区块链了。
|
||
|
||
### 2.好啦我知道什么是区块链了,但是那些用户为什么要记录交易信息呢?
|
||
|
||
记账奖励:每个用户都可以去记账,如果某个用户进行记帐则会奖励他一些手续费,比如A 和 B 交易 10 个比特币,A 就需要多支出一点点给为其记录的人。其实现实生活中,我们使用银行卡时也会有手续费,这里的手续费是支付给银行。
|
||
|
||
打包(将交易记录打包成块)奖励:打包者只能有一位,完成打包的那一位能够获得**打包奖励**,
|
||
|
||
### 3.哦,知道了,那打包一次能获得多少奖励呢?
|
||
|
||
2008年刚提出这个系统时,奖励方案如下
|
||
|
||
每十分钟打一个包,最开始的时候,每打一个包会奖励打包者 50 个比特币,过了四年之后,每打一个包奖励 25 个比特币,再过四年的则奖励 12.5个比特币,以此类推。
|
||
|
||
### 4.哇,那么多,那世界上一共有多少个比特币呢?
|
||
|
||
一个包奖励 50 个比特币,一个小时 6 个包,一天 24 小时,一年 365天 ,每隔四年减半,则计算公式如下
|
||
|
||
![微信图片_20201218150122](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/微信图片_20201218150122.1hx8euiaa9uo.png)
|
||
|
||
总数大概为 2100万个比特币。
|
||
|
||
### 5.因为我们有手续费和打包费的奖励机制,所以大家都抢着打包,但是打包者只能有一个人,那么我们应该让谁打包呢?
|
||
|
||
中本聪提出了一个**工作量证明**的办法,说白了就是想打包的用户都要去做一个很难的数学题,谁先做出来,谁就能获得这个打包的权力。打包者就能够获得奖励,但是这个题目很特别,就是我们任何人都不能用脑子把他做出来,我们只能一个数一个数的去尝试,直到你把这个数尝试出来,那么你就获得了奖励,这个过程就是我们经常说的挖矿。
|
||
|
||
### 6.你说的那个挖矿的原理是怎样的呢,我想不通?
|
||
|
||
刚才我们说挖矿的原理其实是让我们做一道数学题,谁先做出来算谁的,这个题目还不拼智商,需要我们一个一个的试,取决于咱们CPU的运行速度。那么具体原理是什么呢?
|
||
|
||
**这里可以选择性阅读,不感兴趣可以直接跳到第 8 个问题**
|
||
|
||
介绍原理之前,我们先来了解一下哈希函数,大家可以去看一下我之前之前的文章《[学生物的女朋友都能看懂的哈希表总结!](http://mp.weixin.qq.com/s?__biz=Mzg3NDQ2NDY3MA==&mid=2247486429&idx=1&sn=449b0482f89a4b2778cbd5c5d6dcc67f&chksm=ced11f2cf9a6963ab9ce6331c4bec69775e347ef03e4bae46e93113f6e99d18c83f45359a04c&scene=21#wechat_redirect)》,里面对哈希函数做出了简要描述。下面我们再来了解一下数字摘要。
|
||
|
||
数字摘要就是采用**单向 Hash 函数**将需要加密的明文“摘要”成一串固定长度的密文这一串密文又称为数字指纹,它有固定的长度,而且不同的明文摘要成密文,其结果总是不同的,而同样的明文其摘要必定一致。
|
||
|
||
通俗点说就是,一个字符串,我们通过 hash 函数计算,得到一个固定长度的密文,不同的字符串得到的密文不同,哪怕仅仅是两个字符串相差一个 0 最后的得到的密文也可能完全不同,相同的字符串会得到相同的密文。通过明文得到密文很容易,我们通过特定的哈希函数就可以,但是反过来是极其难的。
|
||
|
||
下面我们简单描述一下 著名的哈希函数 SHA256 的生成摘要的过程
|
||
|
||
![sha256](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/sha256.5veoxktednk0.png)
|
||
|
||
|
||
我们已经了解了生成摘要的过程,那么挖矿的具体原理是什么样呢?
|
||
|
||
刚才我们说到,区块链其实是一大堆交易信息,其实我们的区块里面不只有交易信息,还有头部。目前有很多人记录了系统的交易信息,然后想把自己记录的交易信息打包成块,并连接到区块链上,获得打包费。那么多人想打包,但是只能有一个人可以获得打包权,那么具体是解决了怎样的数学问题获得打包权的呢?
|
||
|
||
刚才我们描述了生成密文过程,那么我们的明文,也就是输入字符串,在这里主要由什么组成呢?
|
||
|
||
字符串 :**前块头部 + 账单的信息 + 时间 + 随机数**
|
||
|
||
主要有以上信息组成,前块的头部,你所记录的账单信息,时间戳,随机数组成。那么我们看,这里的组成部分对于所用用户来说,只有前块头部是固定的,账单信息因为每个人记录顺序不同也是不固定的,每个人开始的时间不一样,那么时间也是不固定的,随机数也不固定,那么既然我们的输入都是不固定的,那这个题应该怎么答呀,那怎么保证公平呢?主要通过以下方法
|
||
|
||
刚才我们也说了,经过 SHA256 加密之后会得到一个 256位的二进制数。
|
||
|
||
获得打包权的那个难题就是让我们把字符串经过两次 SHA256 运算之后得到一个哈希值,哈希值要求**前 n 位**为0,意思就是谁先算出那个前 n 位为 0 的哈希值,谁就能获得打包权。
|
||
|
||
因为每个人的输入是不固定的,但是对于个人来说,他开始运算的时间是固定的,头部也是固定的,他所记录内容也是固定的,所以他只能依靠调整**随机数**来修改最后的哈希值,只能挨个试,但是如果人品爆发可能试的第一个数就能得到符合要求的哈希值,但是总的来说还是一个考察算力的题目。
|
||
|
||
![两次哈希函数](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/两次哈希函数.3dv6ep2rqh00.png)
|
||
|
||
### 7.那哈希值前 n 位为 0 ,这个 n 是依据什么决定的呢?
|
||
|
||
这个 n 越大计算难度就越大,因为我们不能反算,只能挨个去试,每一位上出现 0 或 1 的概率都为 1/2,那么我们获得前 n 位为 0 的哈希值概率也就是 1/2 的 n 次方。
|
||
|
||
当时中本聪在设计时,为了保证每十分钟出一个块,所以就会适当的调整 n, 比特币系统每过2016个区块之后,就会自动调整一次难度目标。如果上一个难度目标调整周期(也就是之前2016个区块),平均出块时间大于10分钟,说明挖矿难度偏高,需要降低挖矿难度;反之,前一个难度目标调整周期,平均出块时间小于10分钟,说明挖矿难度偏低,需要提高挖矿难度。难度目标上调和下调的范围都有4倍的限制。
|
||
|
||
所以这个 n 是根据挖矿难度(算力)进行调整的,也就是我们矿机的算力和矿机数量等进行调整。
|
||
|
||
### 8.哦,我懂了,那如果有人冒充咱们咋办,偷偷花咱们的比特币!
|
||
|
||
这个问题问的好
|
||
|
||
说到防止假冒,我们先来说一下身份认证,身份验证又称“验证”、“鉴权”,是指通过一定的手段,完成对用户身份的确认。指纹,人脸,签名等都是传统的认证手段,另外我们说一下比特币系统的电子签名。
|
||
|
||
比特币用户在注册时会生成一个随机数,通过随机数会产生一个私钥的字符串,这个私钥又可以产生一个公钥字符串和地址,私钥和公钥是对应的,并且私钥是保密的,别人向你交易时,你只需要把你的地址发过去即可,如果你给别人交易时,则需要将你的公钥和地址一起发过去。流程图如下
|
||
|
||
![公钥私钥](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/公钥私钥.1z7tkrhr4q4g.png)
|
||
|
||
我们在传输记录时通过私钥加密,然后通过公钥解密,加密和解密的钥匙不一样,所以我们称之为非对称加密
|
||
|
||
具体交易流程如下,例 A支付 5 个比特币给 B
|
||
|
||
![广播](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/广播.3y66ai91qa00.png)
|
||
|
||
我们其他用户接收到了这个支付消息,那其他用户怎么判断这条信息是不是A发出的呢?不是他人冒充 A 发的呢?具体流程如下
|
||
|
||
![广播对比](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/广播对比.76soh60sm2s0.png)
|
||
|
||
其他用户进行对比,如果一致则认可这条消息是A发的,不一致则认为是别人冒充,所有用户则会拒绝这条消息。这里可能会不明白了,公钥和私钥你都发出来了解密肯定的呀,刚才我们说公钥的公开的,但是公钥是由私钥加密得到的,私钥是私密的唯一的,只有 A 用户知道自己的私钥。
|
||
|
||
### 9.哇,好神奇啊,我知道了,那要是我只有 5 个比特币,同时支付给两个人咋办,每个人五个,那我岂不是赚了呀。
|
||
|
||
厉害呀,这你都能想到,但是你想多啦。
|
||
|
||
比如A只有五个比特币,他同时发了两个消息,分别是给 B 五个比特币,给 C 五个比特币,但是他总数只有 5 个,这样显然是不行的,我们称之为**双重支付**。
|
||
|
||
那么我们如何解决呢?
|
||
|
||
##### 余额检查
|
||
|
||
![追溯](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/追溯.4lbdktlb5re0.png)追溯
|
||
|
||
用户在接收到这个消息时,会先从区块链里,进行查询A的交易记录,得出A的余额是否大于交易数额,如果大于则接收,反之则拒绝。
|
||
|
||
##### 解决双重支付
|
||
|
||
首先我们来了解下什么是双重支付,打个比方哈,袁记菜馆第963家分店因为店长经营不善,要进行出售,出售的时候店长将这个房子同时卖给了两个人,但是只有一个房子,这就是**双重支付**。
|
||
|
||
![双重支付](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/双重支付.2ff4ejsp3esk.png)双重支付
|
||
|
||
在比特币系统中是如何解决双重支付问题的呢?我们 A 用户只有 5 个比特币,但是他几乎同时发布了两条广播,此时有些用户会先接收到第一条广播,然后进行追溯,发现 A 只有5个比特币,则会拒绝第二条。同理先接收到第二条广播的用户也会如此。就好比形成了两个阵营,然后两个阵营的用户进行答题,然后获得了打包权,则会将自己打的包接到区块链上,那么他所接收到的那条消息则会被整个系统认可。另一条则会放弃。
|
||
|
||
比如用户 D 先接收到了第二条广播 ,A 支付给 C,然后 D 用户获得了打包权,则 D 将包接到链上,那么其余用户则会放弃自己的包,全部都认可 D 所记录的交易信息。所以此时 C 收入 5 个比特币,B 没有收入。所以我们接收到别人交易消息时,不能认为当时已经到账,要等新的块已经形成,消息被记录到主链上才可以。
|
||
|
||
### 10.那如果有人偷偷篡改交易信息,那他不就成比特币最多的人了吗?
|
||
|
||
想的挺全面呀,厉害呀你
|
||
|
||
我们考虑一下这种情况,A 已经支付给了 B 五个比特币,但是他想把这个记录删掉,伪造一下记录。有这种可能吗?
|
||
|
||
说之前我们先来描述一下比特币系统遵循的**最长链原则**,那什么是最长链原则呢?
|
||
|
||
![最长链](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/最长链.608rywpq68g0.png)最长链
|
||
|
||
比如上图,我们同时有两个块接到了链上,那么会有两拨人,他们都会以第一个接收到的块为准,然后两拨人继续运算,当某一拨中的某个人获得打包权之后则会将新块接到他接收的块后面,那么此时他的这个链是整个系统最长的链,则会被所有人认可,另一拨人也会来到这个最长链下面继续打包。之前的那个分支则会废弃。如果说某个人他就不想转移阵容,非得死守那个相对短的链,这样也是可以的,只要你一己之力可以对抗所有人,把你这个链变成最长链,大家则会都认可你这条链。
|
||
|
||
那么我们来说一下,如何防止篡改
|
||
|
||
![红色块分支](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/红色块分支.72gt7kf4gzo0.png)
|
||
|
||
|
||
A 此时想要修改红色块里的交易记录,则 A 需要重新计算重新打包,创造出一个支链来,但是大家不会承认你这个支链,因为这个支链不是最长的,所以不会承认你伪造的信息,如果你非要继续往下算,什么时候你自己创造的支链长度大于世界上所有人的打包的链的长度,那么恭喜你,你伪造成功了,大家都认可你的伪造信息了,所以说理论上是可以篡改的,但是你改了之后不会被大家承认,除非你的计算能力超过了世界上其余所有的人。大家试想一下一个掌握全世界一半以上算力的人,会去干这种无聊的事吗?
|
||
|
||
这下我全都懂了,那咱们快去买两个吧!
|
||
|
||
你看看现在一个多少钱啦,买不起呀咱们。
|
||
|
||
<u></u>
|
||
|
||
另外给大家建了一个寒假刷题互相监督群,需要的可以联系我,公众号内点击一起刷题即可,为了防止广告党进入,大家记得备注【刷题】,目前人数大概有200来人。大家可以自行组成小队,也可以一起商量题目。多个人一起走,才能走得更远
|
||
|
||
|
||
|
||
|