原文作者:@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