区块链是如何工作的——用JavaScript演示
段琰baby
发表于 2022-11-20 23:53:01
84
0
0
1 l+ z: Z5 r% y& n% K7 k
这听起来很棒,那它是如何工作的呢?
为了说明区块链,我们将会使用一个名为BlockchainCLI的开源命令行工具。
我同时也建立了一个基于浏览器的版本
安装命令行工具# I7 r, y z( D3 q0 j" \
' b7 Z0 j+ @( h1 d L# j; z5 ?$ ?0 V
在此之前请先安装Node.js
* |' Z: b: I! j$ z. j
然后在你的命令行中运行以下指令:
npminstallblockchain-cli-g4 V7 U U) J6 l( i, n
blockchain$ D) {; E v) C/ y2 A8 `; {* L
你应该会看到?WelcometoBlockchainCLI!和一个blockchain→提示。这说明已经准备好了。
区块长什么样?0 ^, J2 d* u7 P5 _& D. L
4 ^1 \) z, J/ E2 b- u+ Y
想要查看当前的区块链,你需要在命令提示行下输入blockchain或者bc。你应该会看到像下面的图片一样的一个区块。3 S; h. f6 p" Q) M
Index:是哪一个区块(创世块的索引是0)
% S0 k* [+ _2 s, M' G
Hash:块是否有效?
PreviousHash:前一个区块是否有效?
5 C+ A F: ?( s+ C% H5 J6 t+ e% P
Timestamp:什么时候添加的区块?) c7 r1 I! Y% F: S, |7 T
! v7 W2 ^9 ^0 i* u0 a
Data:什么信息存储在区块上?) F% z/ U3 K+ S% Z- I0 p4 S: Q
5 E T O( e5 N6 A* ^4 g. j; [! s
Nonce:在找到有效区块之前,我们进行了多少次迭代?8 w4 A' i; U* K$ T$ p7 M, B8 `
创世块
* W+ F4 i' S" \; Q
每一个区块链都是从?GenesisBlock开始的。正如你们将要在后面看到的,区块链上的每一个区块都依赖于前一个区块。所以,需要创世块来挖出我们的第一个区块。. Z+ C( M% Z7 P- L) f i
4 I6 W P7 ?1 @9 q: P6 ~9 T' ~
当一个新的区块被开采时会发生什么?
让我们挖出我们的第一个区块。在命令行中输入minefreeCodeCamp。
区块链查看链上最新的区块来获取index和previoushash。在这个案例下创世块是最新的区块。& ]( }" p1 ^( A4 M- M a: j1 y
, |5 R% D1 P8 t4 s5 s
Index:0+1=1
) o( o4 {' v' J: ^1 M5 T
PreviousHash:0000018035a828da0…: ?7 s; U% Z5 l
Timestamp:区块被添加的时间
Data:freeCodeCamp
* Y* d) J% r6 b6 W& T
Hash:???
- y* |5 j5 X1 S1 q3 u4 }& {9 }$ z
Nonce:???4 k }; H5 Z0 V
Hash是如何计算的?
哈希值是唯一标识数据的固定长度的数值。" U! V# F0 K# q1 R: W* S5 U7 g$ b
Hash是通过将Index、PreviousHash、Timestamp、Data和Nonce作为输入值来计算的。
CryptoJS.SHA256(index+previousHash+timestamp+data+nonce)3 a* O# ~8 A3 e) d! b
SHA256算法将会依据这些输入计算出一个唯一Hash值。同样的输入总是会返回同样的结果。- Y6 i* p+ J5 h+ B7 Y, R* P
你是否注意到区块Hash中的四个前导0?
四个前导0是一个有效Hash的最低要求。所需前导0的数量被称之为难度
. l% K: ]* `+ n2 f1 O3 o: A6 y
functionisValidHashDifficulty(hash,difficulty){' \' D' O: p" |: v
, e& j1 p& `) [" W- G
for(vari=0,b=hash.length;i=difficulty;, D/ r9 `& m: Q. @. z2 w+ [3 g: X
- n2 f% `# `7 ?" L! m7 m7 N
}/ m8 W2 ?* {* q& k1 V, l7 s- v
这也被称为工作证明系统. R% q3 z% L: ]3 s# c
& P0 _# Q, p8 n# K+ }! v$ Z
Nonce是什么?
' Q4 S3 j N( K) y! u' B
Nonce是用来查找一个有效Hash的次数。) O' b- @9 e g' F
letnonce=0;
lethash;
8 x0 }% Y ]6 p! P- {4 \
letinput;
while(!isValidHashDifficulty(hash)){2 c4 R9 l( Y# A D7 w0 V2 w9 a
nonce=nonce+1;
+ F/ y/ p! `+ R: E A" ^% \+ A
input=index+previousHash+timestamp+data+nonce;. P. q; w# ^8 Z6 V# b( f
2 u9 ]; `% h& t5 b5 Z: k8 |2 R' l
hash=CryptoJS.SHA256(input)
7 U6 j$ c3 j* J! D, @9 F: A7 `
}
; _9 o6 u( H" ^- o3 q+ i0 k
Nonce迭代到直到Hash有效。在我们的案例中,一个有效的Hash至少要拥有4个前置0。查找与有效Hash对应的Nonce的过程就是挖矿。/ s1 [) }. Q2 F: {+ g
7 f) z! }; V! g' e8 D$ b( |! B, O
随着难度的增加,可能的有效Hash数量就会减少。伴随着有效Hash的减少,我们需要更强的算力来查找有效Hash。# J5 d+ c! C/ d0 P f
6 I- q6 I' E, I8 P5 D( X, {3 Y
为什么这么重要?
这些机制非常重要,它们使区块链不可变。0 ^& V. c$ r3 k; ^$ K
如果我们有这么一个区块链“A->B->C”,而且有一个人想要改变区块A上的数据。那么会发生什么呢? o9 B( a, d( R7 k8 }$ j6 C9 {% s& [
区块A上的数据改变了。% f8 i4 U& h3 k& _
区块A的hash改变了,因为数据被用来计算hash。" [8 Y0 [ ~3 [+ E8 K; [; E
* E. h3 y) m& U4 Q% Q! N) ~
区块A失效了,因为它的hash不再有4个前导0。2 ~6 }, N L& G l# X
6 ?/ y( G# i+ b2 S) v5 K
区块B的hash改变了,因为区块A的hash被用来计算区块B的hash。8 h/ v v2 O# H1 |0 s" H# I3 F
区块B失效了,因为它的hash不再有4个前导0。1 _2 Q4 z0 b- o
/ N- A D; b$ `; D
区块B的hash改变了,因为区块C的hash被用来计算区块B的hash。
区块C失效了,因为它的hash不再有4个前导0。, i5 N. N- ]* M% ]& e9 T
0 U4 @& V* @+ H7 u
改变一个区块的唯一方法就是将这个区块重新挖一遍,接下来是所有的区块。由于总是有新的区块被添加,因此改变区块几乎是一件不可能的事。
我希望这个教程能够对您有所帮助!
安装命令行工具" j+ R4 m; S6 I5 }
' C s0 G3 O5 U6 r# Y+ G/ V
在此之前请先安装Node.js
然后在你的命令行中运行以下指令:: x) F" D& N# y# A7 N
npminstallblockchain-cli-g, n- F) V5 w2 P) b4 y: G0 y! O
; P! }+ P0 I. h/ K$ u ?: I
blockchain
你应该会看到?WelcometoBlockchainCLI!和一个blockchain→提示。这说明已经准备好了。5 i+ @, v& |% N* U) M' G
0 C; U8 ?. ]( }! t
区块长什么样?- c0 m$ t: Y+ ?9 ~. C
想要查看当前的区块链,你需要在命令提示行下输入blockchain或者bc。你应该会看到像下面的图片一样的一个区块。
7 z& o: y q% P, w$ z: J
Index:是哪一个区块(创世块的索引是0)?
Hash:块是否有效?8 d" U3 {# h) w$ M `% w! Q
3 f8 b( }6 k, n- M/ U( u1 s* J" u
PreviousHash:前一个区块是否有效?
: i2 i8 m# W4 K( v
Timestamp:什么时候添加的区块?' E2 a: q# J) L h" X5 y' H
* i6 N7 g! g f( k8 [5 B7 P' P( o6 I
Data:什么信息存储在区块上?, |# X: Z; _, Z# q
Nonce:在找到有效区块之前,我们进行了多少次迭代?
5 u. r K; {* C, j
创世块
2 b( s/ W; B, F7 a% M* \
每一个区块链都是从?GenesisBlock开始的。正如你们将要在后面看到的,区块链上的每一个区块都依赖于前一个区块。所以,需要创世块来挖出我们的第一个区块。
# S0 i% J4 I6 G1 n" `
当一个新的区块被开采时会发生什么?
9 C" p& ?. Z* G7 Q" @- r; N
让我们挖出我们的第一个区块。在命令行中输入minefreeCodeCamp。
) N1 ^) S& ?# h# w
区块链查看链上最新的区块来获取index和previoushash。在这个案例下创世块是最新的区块。
' I8 l0 U' c* t+ Q) v: E, ]2 P
Index:0+1=1. L! R, S" q8 o) J
PreviousHash:0000018035a828da0…
8 |. `8 X' M3 z T( A5 z# x7 h
Timestamp:区块被添加的时间4 {# ]7 d) q% V ?. ^, ~5 S
Data:freeCodeCamp
1 X$ x, M; Q& \7 y9 T
Hash:???. x/ `8 ?. p B9 Y2 x
Nonce:???
: j( v" x4 S; l2 }: K( C" l
Hash是如何计算的?" t+ z; W' I- M/ m5 W2 }
哈希值是唯一标识数据的固定长度的数值。# L% o; b" M4 h3 N1 N, q/ q
- v; C0 ]1 o+ u& n, d+ Z, R, f
Hash是通过将Index、PreviousHash、Timestamp、Data和Nonce作为输入值来计算的。" j3 r9 D( Z, Y: v( i7 l2 c
' a( o7 F* I5 C d- y% X
CryptoJS.SHA256(index+previousHash+timestamp+data+nonce)
" ~' S* H$ l" D& v# P
SHA256算法将会依据这些输入计算出一个唯一Hash值。同样的输入总是会返回同样的结果。
+ x2 X* a1 |3 s) [3 Q
你是否注意到区块Hash中的四个前导0?
四个前导0是一个有效Hash的最低要求。所需前导0的数量被称之为难度
8 b+ P# c: ?3 U
functionisValidHashDifficulty(hash,difficulty){' N6 J0 A( b) ?6 Z# ?/ D
for(vari=0,b=hash.length;i=difficulty;3 p" n" n2 M* w3 O3 ~' S/ d8 z
( H: a, f" u) I ^* ^" _, z7 S
}* `' K' i: G! z
6 y- {% b; L$ H: \9 t
这也被称为工作证明系统
Nonce是什么?' f1 Z3 e% [1 D5 D* o7 L% O& I& J
4 Y' i2 @ J+ S, o, d
Nonce是用来查找一个有效Hash的次数。
L: r. _9 A. }1 R$ f6 N% _2 n) W, o
letnonce=0;
lethash;
letinput;
! a( M" y7 [3 ^" Y. P, @7 E
while(!isValidHashDifficulty(hash)){! A$ Y0 ]* o, D
7 o9 n4 a% J1 X( C# W# |
nonce=nonce+1;" I7 X( p; V6 m/ J3 r; y& H# p
7 g5 g! s+ g! N, H0 p2 `2 w( B4 p
input=index+previousHash+timestamp+data+nonce;8 r6 P1 w3 [1 ?
. M) t! z4 P* [$ H
hash=CryptoJS.SHA256(input)8 P L; d( g* ]7 g# V3 {3 B
}
. \; ?0 @% e( J1 Q* L$ v+ p
Nonce迭代到直到Hash有效。在我们的案例中,一个有效的Hash至少要拥有4个前置0。查找与有效Hash对应的Nonce的过程就是挖矿。
随着难度的增加,可能的有效Hash数量就会减少。伴随着有效Hash的减少,我们需要更强的算力来查找有效Hash。
; L; q0 g: u7 z- M. [
为什么这么重要?) s* A* t0 I5 p! d+ [! {
这些机制非常重要,它们使区块链不可变。
( _1 H- ?* M7 C2 m' _4 f: G) b
如果我们有这么一个区块链“A->B->C”,而且有一个人想要改变区块A上的数据。那么会发生什么呢?
+ v4 F* S. _( D$ V* B7 G8 i" K: G) f
区块A上的数据改变了。7 O+ O2 u& M4 N! v: t( s1 }
_8 }( a( {# j7 [
区块A的hash改变了,因为数据被用来计算hash。( `9 {* [) K" q5 x
区块A失效了,因为它的hash不再有4个前导0。/ Y6 U9 r5 y" W/ c
区块B的hash改变了,因为区块A的hash被用来计算区块B的hash。
/ s7 Y% H, ]; }
区块B失效了,因为它的hash不再有4个前导0。
区块B的hash改变了,因为区块C的hash被用来计算区块B的hash。
: S$ _- O, _$ I, s. e+ r
区块C失效了,因为它的hash不再有4个前导0。
改变一个区块的唯一方法就是将这个区块重新挖一遍,接下来是所有的区块。由于总是有新的区块被添加,因此改变区块几乎是一件不可能的事。' u, D7 B: v4 [8 ^/ b9 o( M
成为第一个吐槽的人