不知從何時起,區塊鏈在網上一會兒就火了。git
這裏Jerry就不班門弄斧了,網上有太多的區塊鏈介紹文章。個人這篇文章沒有任何高大上的術語,就是300行ABAP代碼,實現一個最簡單的區塊鏈原型。github
我我的以爲,同區塊鏈自己的實現技術相比,更難的事情是如何找到一個合適的業務場景,把區塊鏈集成到SAP產品中去,讓它發揮出做用。算法
這篇文章包含三個版本,每一個版本在前一版本基礎上增添了一些新的功能。數據結構
區塊鏈,顧名思義,由區塊組成的一條鏈。函數
下圖和咱們在大學計算機專業課《數據結構》裏學到的單鏈表很像。在這個版本里,每一個區塊包含了最基本的字段:塊索引,塊的建立時間戳,當前塊的哈希值(hash)和前一塊的哈希值。每一個區塊的pHash字段存儲了前一塊的哈希值,這樣就構成了一個鏈表。鏈表的第一個節點,就是下圖最左邊紅色擡頭的區塊爲創世塊,其索引爲0,pHash字段爲空。區塊鏈
區塊的ABAP實現:ZCL_BLOCK。上圖所示的字段都建模在這個類裏,出於簡單起見,大部分字段設置爲public。測試
每一個區塊的哈希值是由該區塊全部其餘字段的值做爲輸入,經過SHA1算法計算出來,存儲到字段mv_hash裏。編碼
鏈的實現:ZCL_BLOCKCHAIN3d
初版的全部代碼在個人github上。blog
執行測試程序ZBLOCKCHAIN_V1,輸入您想建立的區塊個數,會看到以下輸出:(我選擇的個數是5)
由於SAP GUI沒有鏈表的UI控件,所以我用樹控件模擬。
下圖第21行,我把區塊鏈裏索引爲1的區塊內容篡改成"Change by Jerry", 而後再執行第23行的is_valid方法進行檢查:
由於第21行set_data方法修改了第一個區塊的內容後,會觸發其哈希值的從新計算。這樣第一個區塊的哈希發生了變化(假設從YYY變到了CCC),而第二個區塊的pHash仍然指向第一個區塊變化以前的舊哈希值YYY,所以這個區塊鏈被斷定爲無效。
上圖的輸出來自校驗方法is_valid: 遍歷鏈裏每一個區塊,比較區塊裏存儲前一區塊哈希值的字段pHash和位於該區塊前一個位置的區塊的哈希值是否一致。
第二版代碼的地址在個人github上。
這一版的鏈實現類ZCL_BLOCKCHAIN_V2的構造函數增長了一個輸入參數:iv_difficulty。這個參數有什麼用?
仔細觀察初版測試程序的樹狀輸出,能夠看到每一個區塊的哈希值沒有任何規律。而第二版的這個輸入參數就是爲了提升哈希值的計算成本,即只有當計算出來的哈希值知足必定規則時,該哈希值才能被區塊鏈所接受。參數iv_difficulty定義了可以被接受的哈希值的前導零個數。
例如我指定前導零個數爲3:
執行結果:能看到全部的哈希值的前三位都爲零。
這裏有兩個問題:
首先在區塊的實現類ZCL_BLOCK裏增長了一個新的成員字段mv_nonce:
在將一個區塊實例添加到鏈裏的方法add_block裏,增長了一個方法mine。
這個方法裏是一個循環,在循環體內計算出一個哈希值,而後檢查其是否包含指定位數的前導零。若是沒有,將mv_nonce加1,而後繼續循環。mv_nonce也會做爲輸入的一部分參與哈希計算。也就是說,最終區塊字段mv_nonce的值表明了表明了在獲得符合前導零位數要求的合法哈希值以前,一共通過了多少次計算。而經過在循環裏不斷嘗試最終獲得一個合法的哈希值的這一過程,就是區塊鏈圈內俗稱的「挖礦」。
在個人測試系統裏,建立10個區塊,前導零個數爲4,總共花費了10秒鐘。
從這個花費的時間能體會出,POW實際上是一種機制,經過引入須要必定工做量的哈希計算來避免區塊鏈被垃圾填充或者區塊內容被篡改。
這一版的源代碼:
https://github.com/i042416/KnowlegeRepository/tree/master/ABAP/blockchain/v3
使用ZCL_TRANSACTION來表明一筆交易,包含三個字段:mv_from_address(支付方),mv_to_address(收款方)和mv_amount(交易金額)。
在這一版本里,首先被加強的是ZCL_BLOCK3: 去掉了前兩個版本使用的mv_index和mv_data字段,增長了一個字段mt_transaction, 存儲的是交易的集合。
在計算哈希值時,交易類的每個字段也要參與計算:
類ZCL_BLOCKCHAIN_V3增長了一個新的成員變量mt_pending_trans。每次調用方法create_transaction,並不會建立一個新的區塊用於記錄該條交易,只是簡單地把該條交易添加到待處理任務隊列mt_pending_trans裏。
字段mv_mine_reward存儲了挖礦的獎勵,硬編碼成100。
這個待處理任務隊列僅當方法mine_pending_trans被調用時纔會獲得處理。
第6行的區塊實例的mine方法調用以後,計算出一個符合前導零規範的哈希值。接着待處理任務隊列被清空,而後一個新的交易記錄在第13行被建立出來,做爲挖礦的獎勵,獎勵方的帳號信息由輸入參數iv_award_address定義。
既然如今交易信息存儲在了每一個區塊裏,那麼簡單遍歷這些區塊,就能得出某個帳號最後的餘額是多少。採用的邏輯是,遍歷每一個區塊記錄的每筆交易,若是某賬號出如今交易記錄的支付方,則餘額減去當前這筆交易的交易金額(第5行), 反之帳號若是出如今發送方,則餘額加上交易金額(第9行)。
測試程序以下。由於Tom轉了100元給Jerry,Jerry又轉了10元給Tom,而後第15行挖礦設置的獎勵帳號是Jerry,故最後Jerry的餘額是100-10+100 = 190元。
但願您讀完本文以後,對區塊鏈的工做原理有一個最基本的認識。感謝閱讀。
要獲取更多Jerry的原創技術文章,請關注公衆號"汪子熙"或者掃描下面二維碼: