天天看點

通過一個App Demo的示範深入了解區塊鍊運作原理

什麼是區塊鍊?

從字面上看:區塊鍊是由一個個記錄着各種資訊的小區塊連結起來組成的一個鍊條,類似于我們将一塊塊磚頭疊起來,而且疊起來後是沒辦法拆掉的,每個磚頭上面還寫着各種資訊,包括:誰疊的,什麼時候疊的,磚頭用了什麼材質等等,這些資訊你也沒辦法修改。

從計算機上看:區塊鍊是一種比較特殊的分布式資料庫。分布式資料庫就是将資料資訊單獨放在每台計算機,且存儲的資訊的一緻的,如果有一兩台計算機壞掉了,資訊也不會丢失,你還可以在其他計算機上檢視到。

區塊鍊是一種分布式的,是以它是沒有中心點的,資訊存儲在所有加入到區塊鍊網絡的節點當中,節點的資料是同步的。節點可以是一台伺服器,筆記本電腦,手機等。

你要知道的是這些節點的存儲的資料都是一模一樣。

區塊鍊特性

去中心化:因為它是分布式存儲的,是以不存在中心點,也可以說各個節點都是中心點,生活中應用就是不需要第三方系統了(銀行、支付寶、房産中介等都屬于第三方)。

開放性:區塊鍊的系統資料是公開透明的,每個人都可以參與進來,比如租房子,你可以知道這個房子以前的出租資訊,有沒出現過問題,當然這裡頭的一些個人私有資訊是加密的。

自治性:區塊鍊采用基于協商一緻的規範和協定(比如一套公開透明的算法),然後各個節點就按照這個規範來操作,這樣就是所有的東西都有機器完成,就沒有人情成分。 使得對"人"的信任改成了對機器的信任,任何人為的幹預不起作用。

資訊不可篡改:如果資訊存儲到區塊鍊中就被永久儲存,是沒辦法去改變,至于 51% 攻擊,基本不可能實作。

匿名性:區塊鍊上面沒有個人的資訊,因為這些都是加密的,是一堆數字字母組成的字元串,這樣就不會出現你的各種身份證資訊、電話号碼被倒賣的現象。

區塊結構

區塊包含兩個部分:

1、區塊頭(Head):記錄目前區塊的元資訊

2、區塊體(Body):實際資料

包含資料如下圖所示:

image

安裝指令行工具

  • 打開終端,輸入

    npm install blockchain-cli -g

youdi@MacbookPro > ~ > npm install blockchain-cli -g
/usr/local/bin/blockchain -> /usr/local/lib/node_modules/blockchain-cli/main.js
+ [email protected]
updated 1 package in 28.438s
           
  • 終端輸入

    blockchain

youdi@MacbookPro  ~  blockchain
  Welcome to Blockchain CLI!

  Commands:

    help [command...]      Provides help for a given command.
    exit                   Exits application.
    blockchain             See the current state of the blockchain.
    mine <data>            Mine a new block. Eg: mine hello!
    open <port>            Open port to accept incoming connections. Eg: open 2727
    connect <host> <port>  Connect to a new peer. Eg: connect localhost 2727
    peers                  Get the list of connected peers.
    discover               Discover new peers from your connected peers.

blockchain →
blockchain →
blockchain →
           

區塊(block)長什麼樣子?

blockchian ->

後面輸入

blockchain

或者bc(簡寫)檢視創始區塊結構。

  • Index (Block #):

    第幾個區塊? (創世區塊鍊的索引為0)
  • Hash:

    目前區塊的hash值
  • Previous Hash:

    上一個區塊的hash值
  • Timestamp:

    目前區塊建立時的時間戳
  • Data:

    存儲在目前區塊上的交易資訊
  • Nonce:

    在找到有效區塊之前,我們經曆的疊代次數

創世區塊(Genesis Block)

每個區塊鍊都是由一個

創始區塊「 Genesis Block」

開始。後面你所看到的區塊都依賴于上一個區塊。是以,創始區塊是我們挖取第一個區塊的基礎。

當一個區塊挖礦時都發生了什麼?

我們在

blockchain →

中輸入`mine youdi,挖取我們的第一個區塊。

  • Index:

    o+1 = 1
  • Previous Hash:

    0000018035a828da0…
  • Timestamp:

    這個區塊建立的時間
  • Data:

    youdi
  • Hash:

    00006c10b10baee43
  • Nonce:

    22269

Hash是怎麼計算的?

Hash

值是一個

十六進制

固定長度為

64位

的唯一的辨別。

hash

值是由

index

,

previous block hash

timestamp

block data

, 和

nonce

作為輸入資料計算而得。

CryptoJS.SHA256(index + previousHash + timestamp + data + nonce)
           

The SHA256 algorithm will calculate a unique hash, given those inputs. The same inputs will always return the same hash.

SHA256

算法将根據給出的輸入資料計算出一個唯一的hash值,隻要輸入值不變,永遠傳回相同的結果。

http://p3ipoi9q3.bkt.clouddn.com/2018-05-22-2018-05-22%2023.13.31.gif

輸入資料為

youdi

時,它的hash值永遠為

2e4f702517a39db2c3614921b136d05b0bde291b0c5720cc899f6091668599fd

你是否注意到塊哈希中的四個前導0?

四個前導0是有效散列的最低要求。 所需的前導0的數量稱為

難度

下面的方法驗證hash難度是否有效。

function isValidHashDifficulty(hash, difficulty) {
  for (var i = 0, b = hash.length; i < b; i ++) {
      if (hash[i] !== '0') {
          break;
      }
  }
  return i >= difficulty;
}

import hashlib

"""
工作量證明
"""


class ProofofWork():
    """
    pow
    """

    def __init__(self, block):
        self.block = block

    def mine(self):
        """
        挖礦函數
        :return:
        """
        i = 0
        prefix = '0000'

        while True:
            nonce = str(i)
            message = hashlib.sha256()
            message.update(str(self.block.data).encode('utf-8'))
            message.update(nonce.encode("utf-8"))
            digest = message.hexdigest()
            if digest.startswith(prefix):
                return nonce, digest
            i += 1

           

這就是我們所熟知的POW

工作量證明系統 - Proof-of-Work system

什麼是

nonce

nonce

是一個用來找到滿足條件的

hash

值的數字。

let nonce = 0;
let hash;
let input;
while(!isValidHashDifficulty(hash)) {     
  nonce = nonce + 1;
  input = index + previousHash + timestamp + data + nonce;
  hash = CryptoJS.SHA256(input)
}
           

nonce

值一直疊代,直到

hash

值有效為止。在我們案例中一個有效的hash值是最少有

4

個前導

。找到

nonce

值以滿足合适條件的

hash

值的過程就叫做挖礦。

随着難度的增加,可能的有效散列數減少。 使用較少可能的有效散列,需要更多的處理能力才能找到有效的散列。

Hash為什麼如此重要?

hash

散列很重要是因為它可以使區塊鍊不能被改變。

如果我們有三個區塊鍊

1 -> 2 -> 3 -> 4 -> 5

,當某個人想要試圖修改區塊A時,下面幾點将是會發生的幾種情況。

http://p3ipoi9q3.bkt.clouddn.com/2018-05-22-2018-05-22%2023.17.04.gif
  • 區塊3上的區塊鍊被修改。
  • 區塊3上的hash值将發生改變,因為hash值是通過資料計算而得。
  • 區塊3變得無效,因為它的hash值不再具備4個前導0的條件。
  • 區塊4的hash值将發生改變,因為區塊3的hash值用來參與計算區塊4的hash值。
  • 區塊4變得無效,因為它的hash值不再具備4個前導0的條件。
  • 區塊5的hash值将發生改變,因為區塊4的hash值用來參與計算區塊5的hash值。
  • 區塊5變得無效,因為它的hash值不再具備4個前導0的條件。

如果想要無效的區塊

3、4、5

變得有效,必須從區塊3開始再一次重新依次挖礦,當你的區塊鍊足夠長,節點足夠多時,就算你将這條鍊上的區塊鍊改變并且重新挖礦成功,但是因為超過50%的節點的資料和你的節點的資料不一緻,你這個被改變的節點的資料也依然無效。

http://p3ipoi9q3.bkt.clouddn.com/2018-05-22-2018-05-22%2023.17.53.gif 這個demo

的示範中,一共有三個節點,我修改了節點2的區塊鍊3并且重新挖礦取得合法的hash值,但是因為

節點B

節點C

中區塊3的hash值和A的不同,是以,我為了改變資料,必須超過51%的節點,這樣會消耗很多的資源,進而保證資料的安全,分布式保證資料的安全可靠。