300行ABAP程式碼實現一個最簡單的區塊鏈原型
不知從什麼時候起,區塊鏈在網上一下子就火了。
這裡Jerry就不班門弄斧了,網上有太多的區塊鏈介紹文章。我的這篇文章沒有任何高大上的術語,就是300行ABAP程式碼,實現一個最簡單的區塊鏈原型。
我個人覺得,同區塊鏈本身的實現技術相比,更難的事情是如何找到一個合適的業務場景,把區塊鏈整合到SAP產品中去,讓它發揮出作用。
這篇文章包含三個版本,每個版本在前一版本基礎上增添了一些新的功能。
版本1:區塊和鏈這兩個資料結構的實現
區塊鏈,顧名思義,由區塊組成的一條鏈。
下圖和我們在大學計算機專業課《資料結構》裡學到的單連結串列很像。在這個版本里,每個區塊包含了最基本的欄位:塊索引,塊的建立時間戳,當前塊的雜湊值(hash)和前一塊的雜湊值。每個區塊的pHash欄位儲存了前一塊的雜湊值,這樣就構成了一個連結串列。連結串列的第一個節點,就是下圖最左邊紅色抬頭的區塊為創世塊,其索引為0,pHash欄位為空。
區塊的ABAP實現:ZCL_BLOCK。上圖所示的欄位都建模在這個類裡,出於簡單起見,大部分欄位設定為public。
每個區塊的雜湊值是由該區塊所有其他欄位的值作為輸入,透過SHA1演算法計算出來,儲存到欄位mv_hash裡。
鏈的實現:ZCL_BLOCKCHAIN
- ADD_BLOCK: 接受一個區塊的例項作為輸入引數,將該例項的pHash指向當前連結串列尾部的區塊,這樣該例項成為連結串列新的尾部區塊。
- CONSTRUCTOR: 建構函式,執行鏈的初始化操作,建立創世塊區塊。
- GET_BLOCK_BY_INDEX: 根據索引訪問指定的區塊。
- GET_SIZE: 返回鏈裡包含的區塊數量。
- IS_VALID: 檢查該區塊鏈是否有效。具體檢查邏輯在後續介紹。
第一版的所有程式碼在我的github上。
執行測試程式ZBLOCKCHAIN_V1,輸入您想建立的區塊個數,會看到如下輸出:(我選擇的個數是5)
因為SAP GUI沒有連結串列的UI控制元件,因此我用樹控制元件模擬。
下圖第21行,我把區塊鏈裡索引為1的區塊內容篡改為"Change by Jerry", 然後再執行第23行的is_valid方法進行檢查:
因為第21行set_data方法修改了第一個區塊的內容後,會觸發其雜湊值的重新計算。這樣第一個區塊的雜湊發生了變化(假設從YYY變到了CCC),而第二個區塊的pHash仍然指向第一個區塊變化之前的舊雜湊值YYY,因此這個區塊鏈被判定為無效。
上圖的輸出來自校驗方法is_valid: 遍歷鏈裡每個區塊,比較區塊裡儲存前一區塊雜湊值的欄位pHash和位於該區塊前一個位置的區塊的雜湊值是否一致。
版本2:增加挖礦成本,增加對工作量證明(Proof of Work,縮寫為POW)的支援
第二版程式碼的地址在我的github上。
這一版的鏈實現類ZCL_BLOCKCHAIN_V2的建構函式增加了一個輸入引數:iv_difficulty。這個引數有什麼用?
仔細觀察第一版測試程式的樹狀輸出,可以看到每個區塊的雜湊值沒有任何規律。而第二版的這個輸入引數就是為了提高雜湊值的計算成本,即只有當計算出來的雜湊值滿足一定規則時,該雜湊值才能被區塊鏈所接受。引數iv_difficulty定義了能夠被接受的雜湊值的前導零個數。
例如我指定前導零個數為3:
執行結果:能看到所有的雜湊值的前三位都為零。
這裡有兩個問題:
- 下圖最後一列Nonce的含義是什麼?
- iv_difficulty這個引數是如何參與雜湊值計算的呢?
首先在區塊的實現類ZCL_BLOCK裡增加了一個新的成員欄位mv_nonce:
在將一個區塊例項新增到鏈裡的方法add_block裡,增加了一個方法mine。
這個方法裡是一個迴圈,在迴圈體內計算出一個雜湊值,然後檢查其是否包含指定位數的前導零。如果沒有,將mv_nonce加1,然後繼續迴圈。mv_nonce也會作為輸入的一部分參與雜湊計算。也就是說,最終區塊欄位mv_nonce的值代表了代表了在得到符合前導零位數要求的合法雜湊值之前,一共經過了多少次計算。而透過在迴圈裡不斷嘗試最終得到一個合法的雜湊值的這一過程,就是區塊鏈圈內俗稱的“挖礦”。
在我的測試系統裡,建立10個區塊,前導零個數為4,總共花費了10秒鐘。
從這個花費的時間能體會出,POW其實是一種機制,透過引入需要一定工作量的雜湊計算來避免區塊鏈被垃圾填充或者區塊內容被篡改。
版本3:使用區塊鏈記錄交易明細,增加挖礦獎勵
這一版的原始碼:
使用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的原創技術文章,請關注公眾號"汪子熙"或者掃描下面二維碼:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2153851/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用ABAP實現一個最簡單的區塊鏈原型區塊鏈原型
- 一個簡單的區塊鏈程式碼實現區塊鏈
- 300行Kotlin程式碼實現的區塊鏈Kotlin區塊鏈
- 51行程式碼實現簡單的PHP區塊鏈行程PHP區塊鏈
- 簡單的實現一個原型鏈原型
- 61行程式碼構建最簡單區塊鏈行程區塊鏈
- 200 行程式碼實現一個簡單的區塊鏈應用行程區塊鏈
- 用java實現一個簡單的區塊鏈Java區塊鏈
- 一個簡單的區塊鏈區塊鏈
- 一個簡單的區塊鏈貨幣,python實現區塊鏈Python
- 50行python程式碼實現的小區塊鏈Python區塊鏈
- 一文讀懂區塊鏈以及一個區塊鏈的實現區塊鏈
- 50行ruby程式碼開發一個區塊鏈區塊鏈
- [譯] 用 Java 程式碼實現區塊鏈Java區塊鏈
- tensorflowrnn最簡單實現程式碼RNN
- 簡單說區塊鏈區塊鏈
- 用Java程式碼實現區塊鏈技術Java區塊鏈
- NodeJS實現簡易區塊鏈NodeJS區塊鏈
- UICollectionView(二)實現一個最簡單的UICollectionViewUIView
- 什麼是區塊鏈,簡單瞭解區塊鏈區塊鏈
- 200行golang 實現的區塊鏈Golang區塊鏈
- 自己實現一個最簡單的資料庫資料庫
- 最簡單的原型繼承原型繼承
- 最簡單的一個powershell的指令碼指令碼
- JavaScript實現區塊鏈JavaScript區塊鏈
- 雲+區塊鏈 實現區塊鏈技術的普惠應用區塊鏈
- 300行Python程式碼實現俄羅斯方塊,致敬逝去的童年Python
- 和數軟體:以最簡單的方式瞭解區塊鏈技術區塊鏈
- 區塊鏈-NFT 的實現原理區塊鏈
- 區塊鏈知識,區塊鏈簡史區塊鏈
- Promise 原始碼:實現一個簡單的 PromisePromise原始碼
- C#實現一個最簡單的HTTP伺服器C#HTTP伺服器
- 用Java程式碼實現一個簡單的聊天室功能Java
- go開發一個自己的區塊鏈只需180行程式碼Go區塊鏈行程
- 3行程式碼實現一個簡易版promise行程Promise
- 【區塊鏈技術實現】區塊鏈
- 打造一個最小區塊鏈區塊鏈
- vuex 原始碼:如何實現一個簡單的 vuexVue原始碼