簡而言之,TON 的核心設計理念是以一種「自下而上」的方式重構傳統的區塊鏈協議,並以捨棄互通性為代價,實現對高並發和高可擴展性的極致追求。
作者:馬裡奧看 Web3
封面: Photo by ilgmyzin on Unsplash
引言:隨著幣安上線 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 的 function1 中調用合約 B 的 function2,或透過合約 C 的唯讀 function3 存取某狀態數據,整個過程是原子性的,在一筆交易中被執行,這是一件非常容易的事情,然而在 TON 中,這將不可能實現,任何與外部智能合約的互動都將透過打包新的交易非同步執行,這種由智能合約發起的交易也被稱為內部訊息。且執行過程中無法阻塞以獲得執行結果。
例如我們開發一個 DEX,如果採用 EVM 中常見的範式,通常會有一個統一的 router 合約用於管理交易路由,而每個 Pool 都單獨管理某個交易對相關的 LP 數據,那麼假設當前有兩個池子 USDT-DAI 和 DAI-ETH。當使用者希望透過 USDT 直接購買 ETH,就可以透過 router 合約在一筆交易中順序請求這兩個池子,完成原子性交易。然而在 TON 中就沒有這麼容易實現了,需要思考新的開發範式,若仍然復用該範式的話,那信息流可能是這樣的,這個請求將伴隨一個由用戶發起的 external message 和三個 internal messages 完成(注意這是用來說明差異性的,真實的開發中甚至連 ERC20 的範式也要重新設計)。
2. 需要仔細考慮跨合約呼叫時出現執行錯誤情況的處理流程,為每個合約間呼叫設計對應的彈回(bounce)函數。我們知道在主流的 EVM 中,當交易執行時遇到問題時,整個交易將會被回滾,也就是被重置到執行最初時的狀態。這在串行單線程模型中是容易理解的。然而在 TON 中,由於合約間呼叫採用了非同步的方式執行,即使後續某環節出錯,由於前面已經被成功執行的交易已經被執行並確認,這就有可能造成問題。因此 TON 中設定了一種特殊的訊息類型,叫做彈回訊息,即當某內部訊息觸發的後續執行過程出現錯誤時,被觸發合約可以透過觸發合約預留的彈回函數將觸發合約中的某有些狀態重置。
3. 在某些複雜情況下,先被接收的交易不一定先被執行完畢,因此不可以預設這種時序關係。在這樣一個非同步和平行智能合約呼叫的系統中,定義處理操作順序可能很難。這就是為什麼 TON 中的每個訊息都有它的邏輯時間 Lamport time(後面簡稱 lt)。它用於理解哪個事件引發了另一個以及驗證者首先需要處理什麼。對於一個簡單的模型,先被接收的交易一定先被執行完成。
在這個模型中,A 和 B 分別表示兩個智能合約,則有如果 msg1_lt < msg2_lt,則 tx1_lt < tx2_lt 的時序關係。
然而在較為複雜的情況下,這個規則就會被打破。在官方文件中有這樣的例子,假設我們有三個合約 A、B 和 C。在一筆交易中,A 發送兩個內部訊息 msg1 和 msg2:一個給 B,另一個給 C。儘管它們是按確切順序創建的(先 msg1,然後是 msg2),但我們無法確定 msg1 將在 msg2 之前被處理。這是因為從 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 開發有興趣的夥伴也可以聯絡我,和我們一起討論。
免責聲明:作為區塊鏈資訊平台,本站所發布文章僅代表作者及來賓個人觀點,與 Web3Caff 立場無關。文章內的資訊僅供參考,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。