区块链是一个分布式数据库,任何人都可以读取的它的区块数据。区块链是不可变的,意味着一旦将区块添加到链中,就只能在使链的其余部分无效的情况下才能对其进行更改,这就是加密货币基于区块链来实现的原因。
区块和链
区块
区块链允许我们检测何时有人操纵了任何先前的区块,如何确保完整性呢?每个区块都根据前一个区块的哈希值,结合区块内的其他内容计算出自己的哈希值,作为该区块的唯一标识。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
const SHA256 = require("crypto-js/sha256");
class Block {
constructor(timestamp, data, previousHash = "") {
this.timestamp = timestamp;
this.data = data;
this.previousHash = previousHash;
this.hash = this.calculateHash();
}
calculateHash() {
return SHA256(
this.timestamp + JSON.stringify(this.data) + this.previousHash
).toString();
}
}
|
链
但第一个区块是特殊的,它没有前一个区块,我们称它为创世区块。
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
|
class Blockchain {
constructor() {
this.chain = [this.createGenesisBlock()];
}
createGenesisBlock() {
return new Block("01/01/2021", "Genesis block", "0");
}
getLatestBlock() {
return this.chain[this.chain.length - 1];
}
addBlock(newBlock) {
newBlock.previousHash = this.getLatestBlock().hash;
newBlock.hash = newBlock.calculateHash();
this.chain.push(newBlock);
}
isChainValid() {
for (let i = 1; i < this.chain.length; i++) {
const currentBlock = this.chain[i];
const previousBlock = this.chain[i - 1];
if (currentBlock.hash !== currentBlock.calculateHash()) {
return false;
}
if (currentBlock.previousHash !== previousBlock.hash) {
return false;
}
}
return true;
}
}
|
isChainValid
方法用于验证区块链是否被篡改。若有人想要篡改区块链上的某个区块,他必须要更改这个区块之后的所有区块,才能确保区块链仍是完整的。
工作量证明
现在,我们来总结上面的区块链中的问题:
-
- 添加区块非常容易,攻击者可大量添加垃圾区块
-
- 篡改区块并不会耗费多少时间
-
- 结合上面两条可造出最长链
-
- …
如果区块的添加需要付出大量的算力成本,就可以在动机层面就杜绝攻击,区块链中这种机制叫工作量证明。简单来说,就是只添加哈希值满足特定条件的区块。
如果你想添加一个区块,首先需要付出算力,让你的区块的哈希值满足特定条件:
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
|
class Block {
constructor(timestamp, data, previousHash = "") {
this.timestamp = timestamp;
this.data = data;
this.previousHash = previousHash;
this.hash = this.calculateHash();
this.nonce = 0;
}
calculateHash() {
return SHA256(
this.timestamp +
JSON.stringify(this.data) +
this.previousHash +
this.nonce
).toString();
}
mineBlock(difficulty) {
while (
this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0")
) {
this.nonce++;
this.hash = this.calculateHash();
}
console.log("BLOCK MINED: " + this.hash);
}
}
|
mineBlock
可筛选出的区块是哈希值的前 difficulty
位均为 0 的区块。通过调整 difficulty
的值,可以控制添加新区块的时间间隔:
1
2
3
4
|
constructor() {
this.chain = [this.createGenesisBlock()];
this.difficulty = 2;
}
|
1
2
3
4
5
|
addBlock(newBlock) {
newBlock.previousHash = this.getLatestBlock().hash;
newBlock.mineBlock(this.difficulty);
this.chain.push(newBlock);
}
|
在比特币中,大约每 10 分钟才会添加一个新的区块,而这个计算有效哈希的过程被称为挖矿。
交易和矿工奖励
当区块链中储存的信息为转账信息时,区块链就成 了分布式账本。
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
|
class Block {
constructor(timestamp, transactions, previousHash = "") {
this.timestamp = timestamp;
this.transactions = transactions;
this.previousHash = previousHash;
this.hash = this.calculateHash();
this.nonce = 0;
}
calculateHash() {
return SHA256(
this.previousHash +
this.timestamp +
JSON.stringify(this.transactions) +
this.nonce
).toString();
}
}
class Transaction {
constructor(fromAddress, toAddress, amount) {
this.fromAddress = fromAddress;
this.toAddress = toAddress;
this.amount = amount;
}
}
|
我们的区块链中只能在一个区块中存储 1 个交易,并且矿工没有任何奖励,我们来解决这个问题。
数字签名
之前写完的,这部分内容不知啥时候弄丢了,打算重写。。。