使用简单的js代码来讲述比特币的工作原理
需求
- 在一个含有N(N>2)个人的小团体里建立一个通用的系统
- 该货币系统使用的货币没有实体媒介,即为数据形式存在
- 该转账操作需要通过互联网(或是团体里的局域网)来进行
步骤
假设存在一个有10个人的小团体,每个人都有自己的私有存储空间
1 2 3 4 5 6 7 8
| const peopleList = [] for (let i = 0; i < 10; i++) { peopleList.push({ name: i, note: [], historyList: [] }) }
|
首先要假设每个人账户里面都有至少1000块来自系统(-1
),否则无法进行转账
1 2 3 4 5 6 7 8 9
| for (let i = 0; i < 10; i++) { for (let j = 0; j < 10; j++) { peopleList[i].note.push({ from: -1, to: j, money: 1000 }) } }
|
第3个人转100给第9个人:记做 3->9: 100,全部人记录下来这个事件
1 2 3 4 5 6 7
| for (let i = 0; i < 10; i++) { peopleList[i].note.push({ from: 3, to: 9, money: 100 }) }
|
这样,一笔转账就被认为是完成了。
但是当转账的记录太多的时候每个人的存储空间就会出现不够用的情况,这个时候就要进行压缩操作。那么问题来了,压缩密钥怎么办,若是保存在一个人的手上肯定不行,所以就需要使用该网络中每个人都同意的唯一一把钥匙来密封它。通过密封,我们可以保证,一旦历史记录的备份已经被存入每一个人的文件夹,没有人能够对它作出任何更改。因此一旦压缩完成,那么这个压缩包就是绝对可信的。
这个压缩包的hash值被人们称为“矿”,同时也是工作证明。
一旦每个人都用尽自己的空间、无法记录进一步的交易,他们就开始卖力地计算历史交易记录的hash,使得它可以被藏入历史hash值列表historyList
中。在网络中,每个人都进行这个计算,而最早算出hash值的那个人会向其他所有人宣布这个值。
1 2 3 4 5 6
| const maxHistory = 10 let sealingNumber if (peopleList[7].note.length >= maxHistory) { sealingNumber = hash(JSON.stringify(peopleList[7].note)) peopleList[7].note = [] }
|
听到hash值之后,每个人都立即验证check()
它是否能产生要求的输出值。如果是的,每个人都为他们的历史hash值列表historyList
存入该值。
1 2 3 4 5 6
| for (let i = 0; i < 10; i++) { if (check(sealingNumber) === JSON.stringify(peopleList[i].note)) { peopleList[i].historyList.push(sealingNumber) peopleList[i].note = [] } }
|
如果对某人,比如7来说,那个sealingNumber
无法产生要求的输出值,怎么办?
可能的原因有:
- 他获取到的
sealingNumber
与之前在网络中宣布的不同
- 他可能记录错了
note
数组
他只能放弃自己错误的sealingNumber
然后从网络里获取别人的 note
数组和historyList
数组,否则他将被禁止进入网络
前面提到了hash值即sealingNumber
也可以被称作矿,这是因为第一个计算出hash值的人将得到免费的金钱作为对他的努力(比如:付出的CPU算力和电力)的奖励。
下面假设奖励为1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const maxHistory = 10 let sealingNumber if (peopleList[7].note.length >= maxHistory) { sealingNumber = hash(JSON.stringify(peopleList[7].note)) peopleList[7].note = [] if (isFirst(sealingNumber)) { peopleList[7].note.push({ from: -1, to: 7, money: 1 }) } }
for (let i = 0; i < 10; i++) { peopleList[i].note = [] peopleList[i].historyList.push(sealingNumber) peopleList[i].note.push({ from: -1, to: 7, money: 1 }) }
|
这就是比特币变为现实的方式。它是在区块链上被用来交易的第一种货币。同时,人们被奖励以比特币作为回报,以使在网络上,计算hash值努力会继续进行。
但是这里有个问题如果有人将很久之前的 note
数组和historyList
数组中对应的一项同时进行修改在检查上面将会成本较高,但是我们可以将每一个 note
数组的最后一项改为上一个historyList
数组的值也就是上一个 note
数组的hash值。这样,每一个hash值都依赖于它之前的 note
数组。因此,如果有人要修改一个 note
数组的历史记录,他将同样必须改变该页以后所有 note
数组的内容和hash值,以使这条链保持一致。
如果有人想要这么做的话那么他将会从改变的那个 note
数组开始计算hash值,但是计算也是需要消耗算力的,他的链增长速度肯定赶不上整个社区的链的增长速度,除非他拥有超越整个社区的算力,当然这都是后话了。有句话叫:在绝对的力量面前任何技巧都是花拳绣腿。
所以这保证了在一个网络中,最长的链就是可信的链。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| const maxHistory = 10 let sealingNumber if (peopleList[7].note.length > maxHistory) { peopleList[7].note.push({ from: null, to: null, money: peopleList[7].historyList[historyList.length - 1] }) sealingNumber = hash(JSON.stringify(peopleList[7].note)) peopleList[7].note = [] if (isFirst(sealingNumber)) { peopleList[7].note.push({ from: -1, to: 7, money: 1 }) } }
for (let i = 0; i < 10; i++) { peopleList[i].note = [] peopleList[i].historyList.push(sealingNumber) peopleList[i].note.push({ from: -1, to: 7, money: 1 }) }
|
万一,是6个人呢?
在这种情况下,这个协议将会变成一纸空文。使得整个社区变成这6个人的后花园。它就是人们所知的“51%攻击”。