國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
93
第六章 金融 KYC 平台實作相關問題討論及解決方式
本研究在實 際透過 學 生架設的 ethereum 區塊鏈(Geth/v1.5.3-stable-978737f5/
windows/go1.7.3) 以 meteor 為 Dapp 平台進行系統實作時,遇到下述系統及實作 上考量的問題,有些透過系統及程式解決,有些則以研究的假設做法解決,在實 務上很多屬於各銀行的內部規範,則不在此研究的討論範圍。
6.1 集中式 vs 分散式 KYC 資料庫存放
本研究在考量金融 KYC 平台設計時,考慮過兩種不同的 KYC 資料存放設計方 式如下:
集中式 KYC 資料庫:
在 TATA Consultant Service 的 Reimaging KYC Using Blockchain Technology 一 文曾提出一個集中式 KYC 資料庫的區塊鏈架構示意圖:
圖 6.1 集中式 KYC 資料庫架構
資料來源:” Reimaging KYC Using Blockchain Technology” by Ganesh Raghavan Padmanabhan, Anusha Sivaramakrishnan, 2016, page 7.
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
94
這樣架構的好處是沒有 KYC 資料分散在不同銀行資料庫存放所要考慮的資 料同步、更新問題,也不需考慮不同銀行資料庫同步的傳輸協定和傳輸安全的設 計問題,所有的銀行只要單存的加入此聯盟即可,看似一個很理想的架構。
分散式 KYC 資料庫:
本研究提出的資料庫架構如下:
圖 6.2 分散式 KYC 資料庫架構 資料來源:本研究整理
各銀行仍保留所有在該銀行開戶的 KYC 原始資料,只有將這些 KYC 資料 的 HASH 資訊放到區塊鏈中供資料比對使用,當其他銀行有需要進行個別客戶 的資料同步時,才會透過 API 向原始銀行撈取 KYC 資料,並再次存放於個別的 資料庫中。
本研究最終選擇分散式 KYC 資料存放,原因是:各家銀行都極度的保護及 重視自己客戶的資料,每家銀行互相不信任,因此絕對不會同意把所有客戶的 KYC 資料提供出去放置在一個共同使用的集中式資料庫中(不管是由哪個銀行或 是獨立機構來管理)。但是若只是分享在聯盟鏈中的某些共同特定客戶的資訊,
可能在意願上會比較高,雖然會導致資料同步、變更上的複雜度。這是考量實務 執行上的可行性所做的一個決定。
‧
6.3 Solidity structure/function 變數數量限制
本研究在設計 smart contract 的時候,本來是要簡化 smart contract,只透過一個 structure 和一個 function,儲存及更新所有相關的 KYC 屬性,但發現不管是 structure 或是 function 的參數,若超過 14 個 bytes32 type(or 7 個 string type),在 compile smart contract 的時候就會發生失敗,而不允許建立。會出現底下錯誤:
Internal compiler error (/src/libsolidity/codegen/CompilerUtils.cpp:203): Stack too deep, try using less variables.
找尋了一些相關的文件,發現也有很多人遇到類似的問題,據推測應該是在 ethereum 的程式碼對於 solidity 處理變數的長度是有限制的。
這個問題的解法,本想過用”|”去分解合併這些變數,但這樣會造成 Dapp 在 處理上的複雜度,而且,由於本研究希望能紀錄每個 KYC 屬性的 Hash 及簽章 資訊,透過”|”去分解合併會造成超過變數長度的問題。
因此,本研究調整為一個 structure 只存放四筆資料,而異動屬性時也拆分為 分別不同的屬性透過不同的 function 去執行。
此限制問題是透過上述方式解決,也能順利運作。範例如下:
‧
function set_name(string customerid, string hash_value, string owner_of_bank, string digital_sig, bool queriable ) {
name_mapping[sha256(customerid)].hash_value = hash_value;
name_mapping[sha256(customerid)].owner_of_bank = owner_of_bank;
name_mapping[sha256(customerid)].digital_sig = digital_sig;
name_mapping[sha256(customerid)].queriable = queriable;
SETEVENT(sha256(customerid), "set_name", owner_of_bank);
}
6.4 Solidity contract 大小限制
本研究的 KYC 資訊,總共有 27 個,再加上其他輔助性的資料,總共 29 個 structure + 29 個 function。但當學生嘗試將這些資料都放在同一個 contract 的時候,雖然 在 Browser-Solidity 上看起來可以建立,但細看 transaction 的 detail,會看到 gas 總是顯示花費 50M gas 的值,且此建立的 contract 無法後續存取,等同於建立失
‧
在此版 ethereum (Geth/v1.5.3-stable-978737f5/ windows/go1.7.3) block 的 gas limit 預設為 4,712,388。但因在此研究儲存的金融 KYC smart contract 在建立時需要超 過這樣的 gas 限制,因此需要進行調整,才能夠建立 contract。
而調整的方式有兩個地方:
1. 在 genisis.json 檔案中,去放大 gas limit,參數如下
"gasLimit": "0x999999999"
2. 在 geth 指令中,指定 –targetgaslimit 0x99999999 參數,此點必須特別注意,
若沒有在 ethereum node 的 geth 指令指定上述指令,則 ethereum 會在每個 block create 的時候,以目前 gasLimit * (1/1024)的幅度,往預設 gasLimit 進行調整。
長久執行下去,還是會跑回預設值。
6.6 Solidity String 變數 vs bytes32 變數
String 是用來儲存一個任意長度的字串(UTF-8 encoded),在設計前台的時候,儲 存或是存取比較方便,通常用 double 或是 single-quotes,而且 string 支援跳脫 字元”\”,可以直接以 \xNN 或是\xNNNN 來儲存 16 進位和 Unicode 的字串。
Bytes32 剛好在 ethreum virtual machine(EVM)中直接可以塞入一個 single word 中,而 string 是一個動態的 size type,因此 bytes32 會使用較少的 gas 來進
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
98
6.7 資料同步時機-on demand vs event trigger
本研究各銀行間的 KYC 資料,若有客戶在某特定銀行有進行資料異動時,資料 同步設計的方式有兩種:
On Demand:當客戶在其他銀行購買新的金融服務時,會去撈取區塊鏈上最 新的 KYC 資訊,當發現和自己的資料庫資料不一致時,去執行資料同步動作 (向最後異動的銀行讀取資料)
圖 6.4 on demand 資料同步示意圖 資料來源:本研究整理
Event Trigger:在 Dapp 上設計 event handling 的背景執行程式,當一有客戶在 任何銀行進行 KYC 資料異動時,每間銀行收到這樣的 event,會透過 HASH ID 去查找自己的資料庫,若有這個客戶,就主動 trigger 資料更新的步驟。架構 方式如下:
Smart contract 上設計當進行資料異動時,發送 event
圖 6.5 Solity Event 處理內容 資料來源:本研究整理
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
99
Dapp 上設計 event handling 的程式,當有 event 發生時,確認是否需要 進行同步作業,若需要則自動執行同步作業
圖 6.6 Dapp Event Trigger 同步示意圖 資料來源:本研究整理
本研究最終採用第一種 on-demand 設計,當銀行需要進行同步作業時,再手 動進行同步作業。會採用此方式,最主要的考量如下:
目前銀行的 KYC 資料,也沒有自動更新機制,只有在客戶要購買其他 的金融服務時,才會重新填寫,此時才會更新銀行裡面客戶的 KYC 紀 錄
一些銀行的 KYC 資料填寫時,會聲明這份 KYC 資料的有效期是一年,
一年後可能需要重新檢視客戶的 KYC 資料是否需要更新,這部分也會 是 batch 更動,而不是即時更動
在實際撰寫 Dapp event handling 程式時,若要針對每一筆 event 都進行 資料庫的查找動作,對系統來說會造成額外的負擔,若客戶資料量龐大,
會影響到資料庫的效能。
綜合上述三點的考量,因此本研究還是以 on-demand 做為資料同步的實作。
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
100
6.8 資料同步比對-Merkle Tree vs Single Hash
在本研究裡,KYC 資訊總共有 27 個屬性,當銀行要比對是否本身資料庫的資料,
是否跟區塊鏈一致、需要進行資料同步時,本研究曾考慮過兩種做法,底下將敘 述這兩種做法的差異以及最後本研究採用的方式:
Merkle Tree:參考比特幣的 Merkle Tree 設計理念,將 27 個屬性(最後一個屬 性 Duplicate 計算)依照底下的方式進行 Hash 運算,並將最後 Merkle Tree Root 的值,儲存在本地資料庫以及區塊鏈 smart contract 中,每當銀行要比對資料 是否有異動時,只要比對資料庫裡 Merkle Tree Root 的值是否和區塊鏈中的一 致,即可判斷是否要進行同步的動作。
圖 6.7 Merkle Tree Hash 計算示意圖
資料來源:Wikipedia: ” https://en.wikipedia.org/wiki/Merkle_tree”
Single Hash:將 27 個 KYC 屬性的 Hash 值分別儲存到區塊鏈中,本地端資料 庫只儲存原始資料,不儲存 Hash 資料。當要比對資料時,在動態每次算出該 筆 KYC 屬性的 Hash 值去和區塊鏈的做比對,若該筆值有異動,僅同步有異
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
101
動那個屬性。
圖 6.8 Solidity KYC 屬性 Single Hash 設計示意圖 資料來源:本研究整理
本研究最終採用 Single Hash 比對方式,原因如下:
本研究不似比特幣有所謂 Light Client,需要透過 Merkle Tree 演算法來 確認其中的一筆交易是否存在於該區塊之中,本研究除了要知道是否該 客戶的 KYC 資料有異動,還要知道是哪一筆屬性不同。要達成這個目 的,用 Merkle Tree 會顯得多此一舉,因為終究還是得要逐筆屬性比對。
在設計資料同步機制時,不管是 on-demand 同步,或是 event-trigger 同 步,都是針對逐筆屬性向區塊鏈中紀錄的更新銀行進行同步,並沒有用 到 Merkle Tree Hash 比對的必要性。
‧
‧ 國
立 政 治 大 學
‧
N a tio na
l C h engchi U ni ve rs it y
103
因此,在設計上,當客戶退出區塊鏈時,我們會將客戶的 Hash ID 資訊,設計一 個 Exist = “False”的標籤(此標籤在客戶一開始出現在區塊鏈的時候,會標示 成”True”),所有 Dapp 針對區塊鏈客戶的查詢,都是要先從客戶 Exist=”true”開始。
因此當客戶標記成”false”,等同於此客戶不存在於區塊鏈中,而且,區塊鏈僅儲 存客戶 KYC 屬性的 Hash 資料,是沒有隱私的疑慮。