區塊鏈 數據“全局一致”、“難以篡改”這兩個特性已經廣爲人知,是區塊鏈營造“信任”的基石。爲了達到這兩個效果,區塊鏈的共識、同步、校驗等技術細節足可大書特書,而本文要從“我篡改了區塊鏈數據”講起。

“我篡改了區塊鏈數據”

FISCO BCOS開源聯盟鏈社區現在相當活躍,每天都會產生大量的討論,大家也會饒有興趣地研究和挑戰區塊鏈如何做到“難以篡改”。我們注意到,尤其在FISCO BCOS支持MySQL數據庫作爲數據存儲引擎後,隔一陣子就有同學在羣裏問:“我手動修改了我節點連接的數據庫裏某個狀態數據,這是不是就是篡改了區塊鏈數據呢?”

直觀地舉個例,如鏈上有個智能合約,管理特定資產餘額,在數據庫合約表裏,經過共識的Alice的餘額本來是100,這時有人打開MySQL客戶端,找到那個合約對應的Table,把Alice的餘額update成10000。

這時他表示:“你看,我調用合約的查詢接口,查出來Alice的餘額確實是10000,這就不對了嘛,而且,鏈還在出塊,根本不防篡改嘛!”。

初步分析和解答

爲何這類問題最近多起來了?我們分析了下,猜想主要是由於MySQL數據庫用戶基礎良好,體系比較成熟,給用戶提供友好的命令行或圖形化交互工具,FISCO BCOS提供了一種Table風格的合約開發模式,表結構設計得清晰直觀,對於用戶來說,一方面理解和管理起來更容易了,另一方面順手update甚至delete一下都是小意思。

下圖僅爲示例數據,採用KVTable合約方式,創建了名爲t_kv_node的合約表,系統自動加了“u_”前綴,可見,這個表結構和數據一目瞭然。

而之前只採用LevelDB或RocksDB作爲存儲引擎,這兩個文件型數據庫交互工具比較少,在用戶面前的存在感不強,操作相對晦澀,主要通過API編程訪問,數據用肉眼難以辨別的Hash key尋址,動手修改數據庫的case就少了一些(但也不是不可能)。

所以,熱點問題浮出水面,前提是用戶可以更方便地修改底層數據了,而不是這個問題之前不存在。

這時我們會建議用戶試一下,針對Alice的餘額,發起一個交易,比如給Alice充值,或者讓Alice轉賬操作,這時,修改過數據的節點將無法參與共識。因爲該節點上算出來的Alice的餘額和其他節點結果不同,其他節點依舊按100的餘額進行計算,而不是10000,顯然結果是對不齊的。

複習下PBFT的容錯模型:定義“f”爲可容錯節點數,網絡中共識節點總數應等於或多於3f+1。即鏈上有4個共識節點時,可容錯的f=1,共識節點總數爲7個時,f=2,以此類推。

如果未修改過數據的節點數滿足PBFT要求的2f+1的數量,鏈依舊可以出塊。但被修改過的節點,一旦有交易涉及髒數據,就像踩到了雷一樣,從此再無法與鏈共識、同步,相當於被拋棄了。這種節點可以稱爲“拜占庭節點”,即作惡或出錯的節點,具備節點准入控制能力的聯盟鏈甚至會將拜占庭節點隔離出去。

還有一種可能性是,手動修改了數據庫裏的數據,但節點內存裏還剛好緩存了一份副本,並沒有被修改,所以通過節點對這個數據的查詢、交易還是正常的,甚至會用正確的結果把數據庫裏被篡改過的數據覆蓋掉,不過這是概率性事件,取決於緩存的大小和當時包含的數據項。

*注:對於採用PoW或其他共識機制的鏈來說,容錯模型有所不同,但在容錯範圍內的少數節點被篡改,也不會影響鏈的共識。

“能否篡改整個聯盟鏈”

有的同學可能會繼續刨根問底:“那我多修改幾個節點的數據是不是就篡改了?”,一般提出這個問題的同學是面向他自己部署的開發測試環境,所有節點都在他手上,所以可以隨便改。

在真實的聯盟鏈環境上,節點分別掌握在不同機構手裏,要修改,首先得侵入他人的網絡、獲得服務器和數據庫權限、發起修改再全身而退。事實上,在注重安全防護的商業化環境裏,這是非常艱難、幾乎不可能做到的事情。

從機構粒度來看,單個機構掌握的節點數,應該低於共識算法可容錯的數量。比如,鏈上總共有7個共識節點,那麼單個機構掌握的共識節點不應多於2個,這樣可以避免機構內部強行修改自己掌握的節點數據,或一個機構的所有節點都意外出錯、掉線(比如機房光纖都被挖斷了),導致鏈無法出塊。

真的沒有辦法防“本地篡改”嗎?

考慮區塊鏈數據本地驗證的機制,比如區塊之間的Hash關係、狀態的Merkle樹結構、共識節點的簽名等,按數據的互驗關係順藤摸瓜進行檢測,似乎有一定概率可以本地檢測出數據異常。

但進一步想,對某個數據的查詢,區塊鏈的本地校驗範圍是有限的,一般不會超出單個區塊或者一棵merkle樹,所以如果篡改者比較熟悉區塊鏈數據的結構和本地校驗邏輯,也可以順着數據校驗關係,從狀態值開始,把merkle樹、區塊Hash等關鍵數據全部改掉。

甚至更徹底地,從創世塊開始,把所有的區塊、系統配置(對於PoW,可以修改挖礦難度以加速出塊)、PBFT的共識者列表等等,都按他的邏輯改一遍,這樣這條本地數據鏈依舊是校驗自洽的,只是無法和其他節點共識了。

這種改法,聽起來需要不少力氣活,但對於一個有決心、有能力的篡改者來說,改改本地數據這個事情其實並不難,難的只是去改別的機構數據而已。

到了這個份上,就相當於一個人鐵了心要“騙自己”,那神仙都沒有辦法了。一旦把本地數據修改的權限交給了不適當的人,最壞情況下,整條鏈沒有一個字節是對的。

但是,本地數據再錯,也只會影響自己,影響不了別人,一旦和其他節點進行共識,就會被發現,甚至被懲戒,整個效果會有一點掩耳盜鈴的意思。

“爲什麼區塊鏈不攔住我篡改數據?”

再進一步,那位同學又會問:“爲什麼區塊鏈不能立刻發現、並且阻止我篡改數據?也許我只是無意手誤呢”。坦率說,這有點對區塊鏈期望過高了。

區塊鏈系統並非無所不能,也不會包辦一切,區塊鏈並不會阻止用戶對自己的服務器、軟件、數據庫等施加操作,就像法律不能也不應去阻止你打碎家裏的杯子一樣。

本質上,區塊鏈的一致性、難以篡改性是面向“全局”的,是由多方博弈和協作達成的,當鏈上交易牽涉錯誤數據時,共識機制可以檢測並拒絕已被篡改的數據,保證鏈上剩餘的大多數健康節點繼續共識出塊。而節點本地不參與共識的數據,共識機制鞭長莫及。

那麼,區塊鏈爲什麼不能主動檢測和糾正錯誤,保證每個節點上的數據一致性?首先,鏈上的數據非常龐雜,用戶直接登入數據庫手動修改少量數據,區塊鏈節點並不知道哪一條數據被修改了,無法觸發檢查。

如果區塊鏈系統定期巡檢所有數據,並將所有數據和其他節點進行比對,可想而知,這樣做的話,網絡、磁盤和計算開銷會非常大。

關鍵是,這並不解決問題,因爲從數據被篡改後到檢測出來的時間窗裏,哪怕髒數據只存在了幾十毫秒,但這時如果不幸有應用來查詢數據,依舊會得到篡改後的結果。對要求苛刻的業務來說,事後檢測未必是最佳選項,因爲有可能已經造成了業務損失,屆時能做的最多就是告警和衝正了。

當然,也可以結合數據庫的操作監控、binlog等輔助機制,加速響應速度和檢測效率。方法還是有的,如上所述,只是性價比較低,也不徹底解決問題,只有對數據修改極其敏感,且業務上接受延時發現和修訂的特定場景,纔會考慮將其作爲補救措施。我們把這部分歸類到運營管理工具裏,根據場景需求來實現。

還有一種方法,可以部分解決查詢問題:f+1查詢。即查詢數據時,無論是查區塊數據,還是合約的狀態數據,不妨多查幾個節點,查詢節點數多於 f 即可。

如鏈上有個7個節點時,f=2,用戶查詢自己節點之外,繼續發出網絡請求去查詢其他機構的2個節點,共查詢3個節點,如果得到的數據都是一致的,則表示數據一定是正確的,反之,一定是這3個節點裏出了問題。

但是,要執行f+1查詢,前提是其他機構開了查詢接口權限,讓你連接上去查詢。在很多安全防護嚴密的聯盟鏈上,一般只打開節點之間P2P互聯的網絡端口,不會輕易給其他機構提供數據查詢權限。再則,在網絡上發起多次查詢,其異步性、時效性、成功率和性能表現都會帶來更多變數。

綜上所述,對節點本地的數據,就像打地鼠,冒頭的(發出交易參與共識,或進行f+1查詢),區塊鏈全局共識和容錯機制能發現,沒有冒頭僅蹲在用戶硬盤裏的,只能用戶自己負責了。

結語

區塊鏈通過網絡博弈、多方校驗實現了全網的容錯防作惡,而區塊鏈同步給到各節點的本地數據,需要用戶自行妥善管理保存。

從信任傳遞來看,首先用戶得“信自己”,如果連自己都無法相信,說明系統和數據管理有漏洞,莫說是修改數據了,在本地系統的整個鏈路上,包括區塊鏈軟件、SDK、業務服務都有可能出錯和篡改作假,這樣的環境有何信任可言?

節點持有者必須非常審慎,首先不要手癢或手誤去改數據,然後關鍵是要建立周全的制度,包括管理策略和技術防護,比如,主機訪問控制、數據庫登錄和操作權限控制、操作審計、日誌審計等,以避免本機構內有人越權訪問監守自盜,或者被外部滲透。

萬一數據出錯,區塊鏈比中心化系統好一點的就是,還有可能通過與其他節點互相校驗檢測出來,這時則應該進行告警、查證、補正和追責,以及在有條件和有必要的前提下,善用f+1查詢方法,給查詢操作加一點點保險。

另外,建議定期備份節點數據到安全的離線設備上,這樣無論是出現意外還是人爲的數據問題,依舊可以從冷數據裏快速恢復,保證一定的RTO(復原時間目標)和RPO(恢復點目標)。

而區塊鏈的健壯性在於,無論單個角色怎麼折騰自己的節點和數據,對全局是沒有影響的,只有修改者自己受損。任憑窩裏翻天覆地,鏈上依舊雲淡風輕,其“全局一致”、“難以篡改”的定律依舊成立,鏈仍然是信任的錨點,這就是區塊鏈的魅力。

根據國家《 關於防範代幣發行融資風險的公告 》,大家應警惕代幣發行融資與交易的風險隱患。

本文來自 LIANYI 轉載,不代表鏈一財經立場,轉載請聯繫原作者。

相關文章