Skip to main content
交易引擎裡有三樣不同的東西都叫「狀態」,混為一談,系統給出的答案就會變成看你問誰而定。本頁把三者區分開,並說明哪一種才是權威。

三種表示

引擎狀態市場 · 帳戶 · 部位 · 訂單簿 · 清算所跨區塊存續 · 一份重建
區塊工作集標記價格 · 被觸及帳戶 · 成交 · 暫存輸出只存續一個區塊 · 一本流水帳
鏈上狀態帶版本的鍵值,由 Merkle 認證權威
這防住的是哪種失效引擎的記憶體視圖一旦與已提交內容漂移,還是會照常給出答案,而每一個答案都是錯的,並且要到結算時才暴露出來。
引擎狀態必須能從已提交的紀錄推導出來,反過來絕對不行
引擎狀態是內核在區塊之間持有的東西:市場中繼資料、帳戶、部位、訂單簿、商品狀態、清算所狀態。這是工作表示——照撮合與清算實際的存取模式佈局,不照儲存佈局。 區塊工作集只在一個區塊執行期間存在:區塊開始時固定的標記價格、哪些帳戶和訂單被觸及、產生了哪些成交、正在組裝的輸出。這是本區塊內發生了什麼的一份流水帳。 鏈上狀態是已提交的結果:帶版本的鍵值條目,由 Merkle 結構做認證,持久且可重放。節點同步的是這一份,證明針對的是這一份,索引器讀的也是這一份。 鏈上狀態是權威。 區塊工作集是用來建構確定性輸出的流水帳,不是事實來源。引擎狀態則是鏈上狀態為執行而最佳化的一份重建,必須能從已提交的紀錄推導出來;反過來絕對不行。 把這個關係搞反,會導致一種特定而且認得出來的失效:引擎的記憶體視圖一旦與已提交內容漂移,還是會照常給出答案,而每一個答案都是錯的,並且要到結算時才暴露出來。

鍵

鏈上狀態按鍵編址。交易狀態歸入具名、而且顯式版本化的命名空間,例如手續費配置、永續合約索引、槓桿級距表、管理角色清單。 版本後綴不是裝飾。一份配置的結構若有變化,就遷到該鍵的新版本,舊鍵保留下來,遷移期間仍讀得到以舊結構寫入的狀態。讀取方若把某個版本寫死、又從不重新檢查,遷移之後就會悄無聲息地讀到過期配置;讀取方若每次解析當前鍵,就不會。
這就是為什麼配置應當從鏈上讀,不要在用戶端程式碼裡寫死。費率級距服務每個週期都讀鏈上即時的手續費配置,正是出於這個原因——級距表一旦寫死在用戶端裡,終究會和網路實際套用的那一張對不上。

版本

每一個已提交的區塊都會推進一個版本。狀態值按寫入時所處的版本儲存,這意味著這個儲存區不只是「當前狀態」,而是「任意版本上的狀態」。 這一性質一口氣讓好幾件事成為可能:
  • 證明可以針對某個特定版本產生,而不只是針對當下。
  • 重放可以從任意版本開始,而不只是從創世開始。
  • 讀取可以是歷史性的——索引器重建某個部位的歷史,是在請求舊版本,不是在掃描日誌。
  • 修剪變成一項政策決定——往回保留多久——不是結構性限制。

最終被提交的是什麼

內核執行每個區塊產生兩樣東西。每筆交易攜帶自己的寫入與事件,並與該交易綁定。不屬於任何單筆使用者交易的影響——資金費收付、保險基金變動、區塊級計數器——進入一個專門的系統通道。 兩者合起來,沒有任何東西會丟失:內核內部的任何一種執行影響,不是落在某筆交易的輸出裡,就是落在系統通道裡。正因為這份完整性,已提交的紀錄才能當作完整的事實,而不是一份摘要;也正因為如此,撮合就算是成批運行,事件仍然追得回導致它的那筆交易。

後續閱讀

儲存與證明

已提交狀態如何在實體上儲存、認證與修剪。

狀態同步

節點從沒見過這條鏈,要怎麼追上。

IntentionKernel

引擎狀態與區塊工作集待在哪裡。

索引器

把已提交狀態變成可查詢的東西。