原文作者: @Web3 Mario
引言:隨著幣安上線TON 生態最大的遊戲Notcoin 以及由全流通token 經濟模型所引發的巨量財富效應,TON 在短時間內即取得了極大的關注。和朋友聊了一下得知TON 的技術門檻比較高,而且DApp 開發範式與主流公鏈協議有很大的差異,因此花了一些時間深入研究了一下相關課題,有些心得體會,與諸君分享。簡而言之,TON 的核心設計理念是以一種「自下而上」的方式重構傳統的區塊鏈協議,並以捨棄互通性為代價,實現對高並發和高可擴展性的極致追求。
TON 的核心設計思想-高並發與高可擴展性
可以這麼說,TON 中所有複雜的技術選型的目的都來自於對高並發與高可擴展性的追求,當然從其誕生的背景我們也不難理解這一點。 TON,即The Open Network,是一個去中心化的運算網絡,包含一個L1 區塊鏈和多個組件。 TON 最初由Telegram 的創始人Nikolai Durov 及其團隊共同開發,而發展到現在則由全球獨立貢獻者的社區支持並維護。其誕生要追溯到2017 年,Telegram 團隊開始為自己探索區塊鏈解決方案。由於當時沒有現有的L1 區塊鏈能夠支援Telegram 的九位數用戶基礎,他們決定設計自己的區塊鏈,當時稱為Telegram Open Network。時間來到了2018 年,為了獲得實現TON 所需的資源,Telegram 在2018 年第一季發起了Gram 代幣(後來改名為Toncoin)的銷售。 2020 年由於監管問題,Telegram 團隊退出了TON 專案。隨後,一小部分開源開發者和Telegram 比賽獲勝者接手了TON 的程式碼庫,將專案名稱更名為The Open Network,並繼續積極開發區塊鏈至今,並遵循原始TON 白皮書中概述的原則。
那麼既然是以作為Telegram 的去中心化執行環境作為設計目標,自然要面對兩個問題,高並發請求與海量數據,我們知道隨著技術發展到現在,號稱TPS 最高的Solana 實測最高TPS 也只有65000 ,這顯然不足以支撐百萬級TPS 要求的Telegram 生態。同時隨著Telegram 的大規模應用,其產生的資料量早已突破天際,而區塊鏈作為一個極度冗餘的分散式系統,若要求網路中每個節點都保存一份完整的數據,這也是不現實的。
因此為了解決上述兩個問題,TON 對主流的區塊鏈協議做出了兩個面向的優化:
透過採用「無限分片範式」(Infinite Sharding Paradigm)設計系統,解決資料冗餘問題,使其可以承載大數據,同時緩解效能瓶頸問題;
透過引入基於Actor 模型的完全並行執行環境,極大的提升網路TPS;
做區塊鏈的鏈-透過無限分片能力讓每個帳戶都有專屬的帳戶鏈
當下我們知道,分片(sharding)已經成為了大部分區塊鏈協議提升性能降低成本的主流方案,而TON 則將這點做到了極致,並提出了無限分片範式,所謂無限分片範式,指的是允許區塊鏈根據網路負載動態地增加或減少分片數量。這個範式使得TON 能夠在保持高效能的同時,處理大規模的交易和智能合約操作,理論上TON 可以為每個帳戶都建立一條專屬的帳戶鏈,並透過一定的規則保證這些鏈之間的一致性,
抽象的來理解,在TON 中一共存在四層鏈結構:
帳戶鏈(AccountChain):此層鍊錶示與某個帳戶相關的一系列交易所組成的鏈,之所以交易可以組成鍊式結構,是因為對於一個狀態機來說,只要執行規則一致,狀態機在接收到相同順序的指令後得到的結果是一致的,因此所有區塊鏈分散式系統中都需要對交易進行鍊式排序,TON 也不例外。帳戶鍊是TON 網路中最基本的組成單元,通常帳戶鍊是一個虛擬的概念,不太可能真正存在一個獨立的帳戶鏈。
分片鏈(ShardChain):在大部分的脈絡下,分片鏈才是TON 中實際的組成單元,所謂分片鏈,即為一組帳戶鏈的集合。
工作鏈(WorkChain):也可以叫做一組有自訂規則的分片鏈,例如建立一個基於EVM 的工作鏈,在其上運行Solidity 智能合約。理論上,社區中的每個人都可以創造自己的工作鏈。事實上,建造它是一個相當複雜的任務,在此之前還要支付創建它的(昂貴)費用,並獲得驗證者的2/3 的票數來批准創建你的工作鏈。
主鏈(MasterChain):最後在TON 中有一條特殊的鏈稱為主鏈,負責為所有分片鏈帶來最終性。一旦分片鏈的區塊的哈希值被合併到主鏈的區塊中,該分片鏈區塊及其所有父區塊被認為具有最終性,這意味著它們可以被認為是固定且不可變的內容,而被所有分片鏈的後續區塊引用。
透過採用這樣的範式,使TON 網路具備以下三個特點:
動態分片: TON 可以自動拆分和合併分片鏈以適應負載的變化。這意味著新區塊總是快速生成,而交易不會產生很長的等待時間。
高度可擴展: 透過無限分片範式,TON 能夠支援幾乎無限數量的分片,理論上可以達到2 的60 次方個工作鏈。
自適應: 當網路中的某個部分負載增加時,該部分可以被細分成更多的分片來處理增加的交易量。相反,當負載減少時,分片可以合併以提高效率。
那麼這樣一個多鏈系統,首先需要面臨的就是跨鏈通訊問題,尤其是由於具有無限分片的能力,當網路中的分片數量達到一定量級後,鏈與鏈之間的資訊路由將成為一件困難的事。試想網路中共有4 個節點,每個節點負責維護1 條獨立的工作鏈,其中連結關係表示該節點除了負責自身的工作鏈中交易排序工作之外,還需要監聽並處理目標鏈中狀態變化,在TON 中具體透過監聽輸出佇列的消息實現,
假設工作鏈1 中的帳戶A 希望向工作鏈3 中的帳戶C 發送一個訊息。則需要設計到訊息路由問題,在這個例子中有兩條路由路徑,工作鏈1 -> 工作鏈2-> 工作鏈3 ,工作鏈1 -> 工作鏈4 -> 工作鏈3 。
當面臨更複雜的情況時,就需要一個高效且低成本的路由演算法快速完成訊息通信,TON 選擇了所謂「超立方體路由演算法」來實現跨鏈訊息通信路由發現。所謂超立方體結構指的是一種特殊的網路拓樸結構,一個n 維超立方體是由2 ^n 個頂點組成的,每個頂點可以透過一個n 位的二進制數來唯一標識。在這個結構中,任兩個頂點如果在二進位表示中只有一位不同,那麼它們就是相鄰的。例如,在一個3 維超立方體中,頂點000 和頂點001 是相鄰的,因為它們只在最後一位上不同。而上述例子就是一個2 維超立方體。
在超立方體路由協定中,訊息將從來源工作鏈到目標工作鏈的路由過程是透過比較來源工作鍊和目標工作鏈位址的二進位表示來進行的。路由演算法會找到這兩個位址之間的最小距離(即二進位表示中不同位元的數量),並透過相鄰工作鏈逐步轉送訊息,直到達到目標工作鏈。這種方法能夠確保資料包沿著最短路徑傳輸,從而提高了網路的通訊效率。
當然為了簡化這個過程,TON 也提出了一個樂觀技術方案,當用戶可以提供對某個路由路徑的有效證明,這通常是某個merkle trie root,節點即可直接承認該用戶提交的消息的可信性,這也被稱為即時超立方體路由。
因此我們可以看到TON 中的地址和其他區塊鏈協議有著明顯的區別,其他主流區塊鏈協議大都採用橢圓加密演算法生成的公私鑰中公鑰對應的哈希作為地址,因為地址只是做唯一性區分,而不需要承載路由尋址的功能,而TON 中的位址有兩部分組成,(workchain_id, account_id),其中workchain_id 即按照超立方體路由演算法位址進行編碼,在這裡就不詳細展開了。
還有一個容易產生疑問的點,你可能已經發覺到主鍊和每個工作鏈均有連結關係,那麼所有跨鏈訊息均透過主鏈做中繼不就可以了麼,就像是cosmos 那樣。在TON 的設計理念中,主鏈僅用於處理最關鍵的任務,即維護眾多工作鏈的最終性,將訊息通過主鏈做路由也不是不行,只是由此產生的手續費用將十分昂貴。
最後簡單提一下其共識演算法,TON 採用了BFT+PoS 的方式,即任意staker 均有機會參與區塊打包,TON 的選舉治理合約會每隔一段時間,從所有Stakers 中隨機選擇一個打包的驗證者集群,被選中稱為驗證者的節點將透過BFT 演算法打包出塊,若打包錯誤訊息或作惡,其stake 的token 將會被罰沒,反之將得到出塊獎勵。這基本上已經是一個比較常見的選擇了,因此不在這裡展開介紹。
基於Actor 模型的智慧合約和完全平行執行環境
TON 中另一個與主流區塊鏈協議不同的點是其智慧合約執行環境。為了突破主流區塊鏈協議TPS 的限制,TON 採用了自下而上的設計思路,採用Actor 模型重構了智慧合約及其執行方式,使其具備了完全並行執行的能力。
我們知道主流的區塊鏈協議大都採用的是單線程串行的執行環境,以Ethereum 為例,其執行環境EVM 是一個以交易作為輸入的狀態機,當出塊節點通過打包區塊完成對交易的排序後,將以該順序透過EVM 執行交易,整個過程是完全串行並單線程的,即某個時刻只能有一筆被執行,這樣做的好處是只要確認了交易順序,執行的結果在在廣泛的分散式叢集中就具有一致性,同時由於同時只有一筆交易被串列執行,這就意味著在執行過程中,不可能存在其他交易對某待存取狀態資料進行修改,這樣就實現了智能合約之間的互通性。例如我們透過Uniswap 使用USDT 購買ETH,當該交易被執行時,該交易對中LP 的分佈情況即為一個確定值,這樣就可以透過某些數學模型得出對應的結果,但假設情況不是這樣的,在執行某bonding curve 的計算時,有其他LP 增加了新的流動性,那麼計算結果將會是一個過時的結果,這顯然是不可接受的。
但這種架構也有明顯的局限性,那就是TPS 的瓶頸,而這個瓶頸在當前多核心處理器下顯得很老舊,就像你用一個最新的PC 去玩一些老的電腦遊戲,比如紅警,當作戰單位多到一定數量後,還是會發現卡片的不行,這就是軟體架構的問題。
你可能會聽到一些協定已經在關注這個問題,並提出了自己的平行方案,以當前號稱TPS 最高的Solana 為例,也具備並行執行的能力。只不過其設計想法與TON 不同,在Solana 中,其核心思想是將所有交易依照執行依賴關係分為幾組,不同組之間不共享任何狀態資料。即不存在相同的依賴,這樣不同組內的交易就可以並行執行而不用擔心出現衝突的情況,而對於同組內的交易,則還是沿用傳統的串行方式執行。
而在TON 中,其完全捨棄了串行執行的架構,轉而採用了一個專為並行而生的開發範式,Actor 模型來重建執行環境。所謂Actor 模型是由Carl Hewitt 在1973 年首次提出,目的是透過訊息傳遞來解決傳統並發程序中共享狀態的複雜性問題。每個Actor 都有自己的私有狀態和行為,且與其他Actor 之間不共用任何狀態資訊。 Actor 模型是一種並發計算的計算模型,它透過訊息傳遞來實現平行計算。在這個模型中,Actor是基本的工作單元,它能夠處理接收的訊息、建立新的Actor、發送更多訊息、決定如何回應接下來的訊息。 Actor 模式需要具備以下幾個特性:
封裝與獨立性:每個Actor 在處理訊息時都是完全獨立的,可以並行處理訊息而不會互相干擾。
訊息傳遞:Actor 之間僅透過發送和接收訊息進行交互,訊息傳遞是異步的。
動態結構:Actor 可以在運行時創建更多的Actor,這種動態性使得Actor 模型能夠根據需要擴展系統。
TON 採用了這個架構,來設計智慧合約模型,這意味著在TON 中,每個智慧合約都是一個Actor 模型,其具備完全獨立的儲存空間。因為不依賴任何外部資料。除此之外,對同一個智慧合約的呼叫還是依照接收佇列中訊息的排序進行執行,因此TON 中的交易將可以被高效率的並行執行,而不需要擔心衝突問題。
然而這樣的設計方案也帶來了一些全新的影響,對於DApp 開發者來說,其習慣的開發典範將會被打破,具體如下:
1. 智能合約之間的非同步呼叫:在TON 的智能合約內部是無法原子性的調用外部合約或存取外部合約資料的,我們知道在Solidity 中,合約A 的function 1 中調用合約B 的function 2 ,或透過合約C 的唯讀functio n3 存取某狀態數據,整個過程是原子性的,在一筆交易中被執行,這是一件非常容易的事情,然而在TON 中,這將不可能實現,任何與外部智能合約的互動都將透過打包新的交易非同步執行,這種由智能合約發起的交易也被稱為內部訊息。且執行過程中無法阻塞以獲得執行結果。
例如我們開發一個DEX,如果採用EVM 中常見的範式,通常會有一個統一的router 合約用於管理交易路由,而每個Pool 都單獨管理某個交易對相關的LP 數據,那麼假設當前有兩個池子USDT-DAI 和DAI-ETH。當使用者希望透過USDT 直接購買ETH,就可以透過router 合約在一筆交易中順序請求這兩個池子,完成原子性交易。然而在TON 中就沒有這麼容易實現了,需要思考新的開發範式,若仍然復用該範式的話,那信息流可能是這樣的,這個請求將伴隨一個由用戶發起的external message 和三個internal messages 完成(注意這是用來說明差異性的,真實的開發中甚至連ERC 20 的範式也要重新設計)。
2. 需要仔細考慮跨合約呼叫時出現執行錯誤情況的處理流程,為每個合約間呼叫設計對應的彈回(bounce)函數。我們知道在主流的EVM 中,當交易執行時遇到問題時,整個交易將會被回滾,也就是被重置到執行最初時的狀態。這在串行單線程模型中是容易理解的。然而在TON 中,由於合約間呼叫採用了非同步的方式執行,即使後續某環節出錯,由於前面已經被成功執行的交易已經被執行並確認,這就有可能造成問題。因此TON 中設定了一種特殊的訊息類型,叫做彈回訊息,即當某內部訊息觸發的後續執行過程出現錯誤時,被觸發合約可以透過觸發合約預留的彈回函數將觸發合約中的某有些狀態重置。
3. 在某些複雜情況下,先被接收的交易不一定先被執行完畢,因此不可以預設這種時序關係。在這樣一個非同步和平行智能合約呼叫的系統中,定義處理操作順序可能很難。這就是為什麼TON 中的每個訊息都有它的邏輯時間Lamport time(後面簡稱lt)。它用於理解哪個事件引發了另一個以及驗證者首先需要處理什麼。對於一個簡單的模型,先被接收的交易一定先被執行完成。
在這個模型中,A 和B 分別表示兩個智能合約,則有如果msg 1 _lt < msg 2 _lt,則tx 1 _lt < tx 2 _lt 的時序關係。
然而在較為複雜的情況下,這個規則就會被打破。在官方文件中有這樣的例子,假設我們有三個合約A、B 和C。在一筆交易中,A 發送兩個內部訊息msg 1 和msg 2 :一個給B,另一個給C。儘管它們是按確切順序創建的(先msg 1 ,然後是msg 2),但我們無法確定msg 1 將在msg 2 之前被處理。這是因為從A 到B 和從A 到C 的路由可能在長度和驗證者集中有所不同。如果這些合約位於不同的分片鏈中,其中一則訊息可能需要幾個區塊才能到達目標合約。即我們有兩種可能的交易路徑,如圖所示。
4. 在TON 中,其智能合約的持久化存儲採用了一個以Cell 為單元的有向無環圖作為數據結構,數據將按照編碼規則緊湊的壓縮為一個Cell,同時按照有向無環圖的方式向下延伸,這與EVM 中狀態資料基於hashmap 的結構組織不同,由於資料請求演算法的不同,TON 中為不同深度的資料處理設定了不同的Gas 價格,越深的Cell 資料處理所需的Gas越高,因此在TON 中存在一種DOS 攻擊的範式,即某些惡意用戶透過發送大量垃圾訊息佔用某個智慧合約中所有的淺層Cell,這意味著誠實用戶的儲存成本將越來越高。而在EVM 中,由於hashmap 的查詢複雜度為o( 1),因此有著相同的Gas,不會有類似問題。所以TON Dapp 開發者應該盡量避免智能合約中出現無界資料類型。當出現無界資料類型時,應透過分片的方式將其打散。
5. 還有一些特徵則不那麼特殊了,例如智能合約需要為存儲支付租金,在TON 中智能合約天然是可升級的,以及原生的抽象帳戶功能,即在TON 中所有錢包地址均為智能合約,只是未被初始化等,這些需要開發者小心留意。
以上是這段時間我學習TON 相關技術的一些心得,與諸君分享,有寫錯的地方還望大家指正,與此同時,我認為憑藉著Telegram 天量的流量資源,TON 生態一定會為Web3帶來一些全新的應用,有對TON DApp 開發有興趣的夥伴也可以聯絡我,和我們一起討論。
X Links: https://x.com/web3_mario
Telegram Handle: @MarioChin Web3