使用 JavaScript 解释区块链(Blockchain)

Posted by cl9000 on May 19, 2020

创造性就是发明、实验、成长、冒险、犯规、犯错和享受乐趣。 ——<玛丽·卢·库克>

作者:Ashish Lahoti
译者:cl9000
来源:https://codingnconcepts.com/javascript/blockchain-explained-using-javascript/

在本文中,我们将学习如何使用 JavaScript 实现区块链。

环境条件

如果你之前没有 JavaScriptNodeJSVSCode 方面的经验,也不必担心。只要跟随本文,你将学习区块链的基础知识,你可以稍后使用其它任何语言实现。

区块链 Blockchain

区块链只不过是一个数字的、分布式的、不可变的和可信的账本,它可以用来记录从金融交易、政府记录到土地所有权,甚至是购买订单的任何事情。

每个交易记录都是一个块,按时间顺序连接在一起,形成一个块链。如果你想改变一个特定块中的记录,你不需要重写它。相反,更改被记录在一个新的块中。

也请阅读区块链基础知识及其实用用例

块 Block

让我们看看区块链中一个典型的块是由什么组成的

  • Timestamp(时间戳) 是事务发生时的日期和时间。
  • Record(记录) 通常包含交易的详细信息,如发送方、接收方、金额等。我们将在我们的程序中使用发送方和接收方的实际名称,但在像 比特币(bitcoin) 这样的实际用例中,实际名称不会被披露,而是使用发送方和接收方的数字签名(digital signature)。
  • Hash(哈希)是代表区块中交易的数字指纹,是完全唯一的。如果事务细节有任何变化,Hash(哈希)也会发生变化。通常,它是通过对事务细节应用 SHA-256 等加密算法生成的字母数字序列。
  • Previous Hash 是区块链中前一个块的 Hash 值。这也用于生成块的Hash(哈希)
  • Nonce“number only use once”的缩写,它是一个添加到区块链块中的数字,再Hash(哈希)后,该数字满足难度级别限制。稍后我们将对此进行更多讨论

步骤1:创建Block (Block .js)

现在我们知道了 块 由什么组成,我们来创建它

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const SHA256 = require('crypto-js/sha256');

class Block {
constructor(timestamp, previousHash, record, difficultyLevel) {
this.timestamp = timestamp;
this.record = record;
this.previousHash = previousHash;
const proofOfWork = this.proofOfWork(difficultyLevel);
this.hash = proofOfWork.hash;
this.nonce = proofOfWork.nonce;
}

/* Genesis Block */
static genesis() {
return new this(new Date(),
"",
"GENESIS"
);
}

/* Block Mining */
static mineBlock(previousBlock, record, difficultyLevel) {
const timestamp = new Date();
const previousHash = previousBlock.hash;
return new Block(timestamp, previousHash, record, difficultyLevel);
}

/* Generate Hash using SHA256 */
static computeHash(message){
return SHA256(message).toString();
}

/* Proof of Work */
proofOfWork(difficultyLevel) {
const message = this.timestamp + JSON.stringify(this.record) + this.previousHash;
if(difficultyLevel){
const leadingZeros = "0".repeat(difficultyLevel);
let nonce = 0;
while(true){
let hash = Block.computeHash(message + nonce);
if(hash.substring(0, difficultyLevel) == leadingZeros){
return {
hash,
nonce
};
}
nonce++;
}
}else{
return {
hash: Block.computeHash(message),
nonce: 0
}
}
}
}

module.exports = Block;

再来理解几个术语

  • Genesis Block(创世区块) 是区块链中第一个没有任何交易细节和先前哈希的区块。这通常是在创建区块链时添加的。也被称为 零块
  • Difficulty Level (难度等级) 是对块生成哈希值的限制。难度越高,生成哈希所需的时间就越多。
  • Block Mining(块挖掘) 是将一个新块添加到区块链的过程。谁添加了新的块被称为 块矿工,在比特币的情况下也称为比特币矿工。任何人都可以注册他们的电脑成为 比特币矿工 之一,以像比特币这样的公开区块链。所有的 比特币矿工 在比特币网络得到整个区块链的副本,当一个新的块被添加到区块链时,每个都接收到一个通知。。
  • Proof of Work(工作量证明) 是区块链中的每个块矿工都试图解决的一个加密哈希谜题。一旦一个区块矿工解决了这个难题,本质上意味着生成了具有上述难度等级的区块的哈希值,他们将这个消息传播到区块链网络,哈希值由网络中所有其他区块矿工验证。

对我们来说什么是工作证明?

工作量证明是根据难度级别生成以0开头的哈希。
难度级别5表示,生成带有5个以0开头的哈希,例如 00000b4d7m3h1s0k2s8bw0hn382

我们将如何实现?

我们将通过对交易明细和现时值应用 SHA-256 算法来计算哈希。我们将从 0 的随机数开始,一直递增,直到找到达到难度级别并以0开头的哈希。
我们将通过对事务细节和nonce 值应用 SHA-256 算法来计算哈希值。我们将从 nonce 值为 0 开始,并一直递增,直到找到具有难度级别并以0开头的哈希值。

步骤2:建立区块链(blockchain.js)

现在已经学到了很多术语,我们来快速创建一个区块链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Block = require('./block');

class Blockchain {

constructor() {
this.difficultyLevel = 1;
this.chain = [Block.genesis()];
}

addBlock(record) {
const newBlock = Block.mineBlock(this.chain[this.chain.length-1], record, this.difficultyLevel);
this.chain.push(newBlock);
}
}

module.exports = Blockchain;

步骤3:测试区块链(server.js)

让我们创建一些带有随机发送方、接收方和金额细节的交易块。同时,让我们在每2次交易后增加难度等级。

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
29
30
31
32
33
34
35
36
const Blockchain = require('./blockchain')
const { performance } = require('perf_hooks');

const blockchain = new Blockchain();

const userList = ["Alice", "Bob", "Charlie", "David", "Eric", "Franklin", "Gavin", "Harry", "Iris",
"Joey", "Kate", "Leo", "Monica", "Nancy", "Oscar", "Phoebe", "Quinn", "Ross",
"Sofia", "Tyler", "Umar", "Victor", "Wilson", "Xena", "Yasmine", "Zara"];

const addNBlocks = (n) => {
for(let i = 0; i < n; i++) {
blockchain.addBlock({
sender: userList[Math.floor(Math.random() * userList.length)],
receiver: userList[Math.floor(Math.random() * userList.length)],
amount: Math.floor(Math.random() * 1000)
});
}
}

const t0 = performance.now();
addNBlocks(2);
var t1 = performance.now()
console.log("[Difficulty Level 1] Added first 2 blocks in " + (t1 - t0) + " milliseconds.")

blockchain.difficultyLevel = 3;
addNBlocks(2);
var t2 = performance.now()
console.log("[Difficulty Level 3] Added next 2 blocks in " + (t2 - t1) + " milliseconds.")

blockchain.difficultyLevel = 5;
addNBlocks(2);
var t3 = performance.now()
console.log("[Difficulty Level 5] Added next 2 blocks in " + (t3 - t2) + " milliseconds.")

/* Print Blockchain*/
console.log(blockchain.chain);

现在一切都准备好了,转到终端并运行以下命令

1
2
npm install --save crypto-js
node server

看到如下输出

Output
[Difficulty Level 1] Added first 2 blocks in 6.2153230011463165 milliseconds.
[Difficulty Level 3] Added next 2 blocks in 175.92524899542332 milliseconds.
[Difficulty Level 5] Added next 2 blocks in 2065.910447001457 milliseconds.
[ Block {
timestamp: 2020-05-18T17:05:37.501Z,
record: ‘GENESIS’,
previousHash: ‘’,
hash: ‘9636ccb176c9f4825d24e1b8db51e3ffb5d448ba112ec0db9672e80f6dc855c3’,
nonce: 0 },
Block {
timestamp: 2020-05-18T17:05:37.504Z,
record: { sender: ‘Xena’, receiver: ‘Umar’, amount: 770 },
previousHash: ‘9636ccb176c9f4825d24e1b8db51e3ffb5d448ba112ec0db9672e80f6dc855c3’,
hash: ‘0329bb14cb5d59a2ddce485019de8041c6790b4483afbad91516ec78e21a70f4’,
nonce: 24 },
Block {
timestamp: 2020-05-18T17:05:37.509Z,
record: { sender: ‘Harry’, receiver: ‘Wilson’, amount: 601 },
previousHash: ‘0329bb14cb5d59a2ddce485019de8041c6790b4483afbad91516ec78e21a70f4’,
hash: ‘05187dd8fa18b1ebd50565f1607e43ab9ad081955a71fb6f542cb91755192b49’,
nonce: 12 },
Block {
timestamp: 2020-05-18T17:05:37.512Z,
record: { sender: ‘David’, receiver: ‘Quinn’, amount: 600 },
previousHash: ‘05187dd8fa18b1ebd50565f1607e43ab9ad081955a71fb6f542cb91755192b49’,
hash: ‘000a0f95e605831a1fa0178351a195fc6f60752fd59e251ea56b1c0d464b8920’,
nonce: 7947 },
Block {
timestamp: 2020-05-18T17:05:37.620Z,
record: { sender: ‘Yasmine’, receiver: ‘Umar’, amount: 918 },
previousHash: ‘000a0f95e605831a1fa0178351a195fc6f60752fd59e251ea56b1c0d464b8920’,
hash: ‘000e8a70d4b6673f3a10cc68fdc21e0cda7a71aa0fe56d31a13cf95832596a45’,
nonce: 5384 },
Block {
timestamp: 2020-05-18T17:05:37.686Z,
record: { sender: ‘Phoebe’, receiver: ‘Victor’, amount: 336 },
previousHash: ‘000e8a70d4b6673f3a10cc68fdc21e0cda7a71aa0fe56d31a13cf95832596a45’,
hash: ‘000005b737aaa4faa3b87b56474dec9537eee843c2881cb5f6432ca9708bd7b5’,
nonce: 45944 },
Block {
timestamp: 2020-05-18T17:05:38.178Z,
record: { sender: ‘Umar’, receiver: ‘Oscar’, amount: 239 },
previousHash: ‘000005b737aaa4faa3b87b56474dec9537eee843c2881cb5f6432ca9708bd7b5’,
hash: ‘0000057a7a4c7caea164b4e5672a3c38fcf12c6c8bfb4b1c503ca876664f2660’,
nonce: 150796 } ]

解析输出

  • 当我们将难度级别从 13 增加到 5 时,生成散列和添加新块需要更多的时间。像比特币这样的区块链技术需要以 1830 的难度级别来解决哈希谜题。你可以想象一下解决这些谜题需要多少时间。
  • 区块链的第一个区块是没有交易信息和先前哈希值的起源区块
  • 请查看根据难度级别由1、3和5个以0开头生成的散列
  • 变量 nonce的值随着难度级别的增加而增加,它还告诉我们哈希算法生成哈希的尝试次数。

总结

希望你现在已经对区块链技术有了一个基本的了解,以及我们如何实现它。请注意,上面的例子是区块链的一个非常基本的实现。现实世界的例子非常复杂,但这是进入区块链世界的第一步。

请在github - https://github.com/ashishlahoti/blockchain.js上查看这个例子的源代码

参考

关注【公众号】,了解更多。
关注【公众号】,了解更多。
关注【公众号】,了解更多。



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!