解讀Starknet智能合約模型與原生AA:特立獨行的技術巨匠

中級3/18/2024, 9:32:21 AM
Starknet支持原生級別的AA賬戶抽象,允許高度定製的交易處理方案,併採取多項反製措施保障安全。這些特性爲Starknet創造了必要的條件,支持存儲分層、檢測垃圾合約等功能,盡管某些功能尚未落地,但爲AA生態的探索提供了重要基礎。

摘要:·Starknet最主要的幾大技術特性,包括利於ZK證明生成的Cairo語言、原生級別的AA、業務邏輯與狀態存儲相獨立的智能合約模型。·Cairo是一種通用的ZK語言,既可以在Starknet上實現智能合約,也可以用於開髮偏傳統的應用,其編譯流程中引入Sierra作爲中間語言,使得Cairo可以頻繁迭代,但又不必變更最底層的字節碼,隻需要把變化傳導至中間語言身上;在Cairo的標準庫內,還納入了賬戶抽象所需要的許多基本數據結構。·Starknet智能合約將業務邏輯與狀態數據分開來存儲,不衕於EVM鏈,Cairo合約部署包含“編譯、聲明、部署”三階段,業務邏輯被聲明在Contract class中,包含狀態數據的Contract實例可以與class建立關聯,併調用後者所包含的代碼;


·Starknet的上述智能合約模型利於代碼覆用、合約狀態覆用、存儲分層、檢測垃圾合約,也利於存儲租賃製和交易併行化的實現。雖然後兩者目前暫未落地,但Cairo智能合約的架構,還是爲其創造了“必要條件”。·Starknet鏈上隻有智能合約賬戶,沒有EOA賬戶,從一開始就支持原生級別的AA賬戶抽象。其AA方案一定程度吸收了ERC-4337的思路,允許用戶選擇高度定製化的交易處理方案。爲了防止潛在的攻擊場景,Starknet做出了諸多反製措施,爲AA生態做出了重要的探索。


正文:繼Starknet髮行代幣之後,STRK逐漸成爲以太坊觀察者眼中不可或缺的要素之一。這個曏來以“特立獨行”“不重視用戶體驗”而聞名的以太坊Layer2明星,就像一個與世無爭的隱士,在EVM兼容大行其道的Layer2生態裡默默的開辟自己的一畝三分地。由於太過忽視用戶,甚至公開在Discord開設“電子乞丐”頻道,Starknet一度遭到擼毛黨的抨擊,在遭噴“不近人情”的衕時,技術上的深厚造詣瞬間變得“一文不值”,似乎隻有UX和造富效應才是一切。《金閣寺》中那句“不被人理解成了我唯一的自豪”,簡直就是Starknet的自我寫照。但拋開這些江湖瑣事,單純從代碼極客們的“技術品味”出髮,作爲ZK Rollup先驅之一的Starknet和StarkEx,幾乎就是Cairo愛好者眼中的瑰寶,在某些全鏈游戲開髮者心中,Starknet和Cairo簡直就是web3的一切,無論是Solidity還是Move都無法與之相提併論。現如今橫亘在“技術極客”和“用戶”之間的最大代溝,其實更多歸因於人們對Starknet的認知欠缺。抱著對區塊鏈技術的興趣與探索欲,以及對Starknet的價值髮現,本文作者從Starknet的智能合約模型與原生AA出髮,爲大家簡單梳理其技術方案與機製設計,在爲更多人展示Starknet技術特性的衕時,也希望讓人們了解這個“不被人所理解的獨行俠”。Cairo語言極簡科普下文中我們將重點討論Starknet的智能合約模型與原生賬戶抽象,説明Starknet是如何實現原生AA的。讀完此文,大家也可以理解爲什麽Starknet中不衕錢包的助記詞不能混用。但在介紹原生賬戶抽象前,讓我們先了解下Starknet獨創的Cairo語言。在Cairo的髮展歷程中,出現了名爲Cairo0的早期版本,以及後來的的現代版。Cairo的現代版本整體語法類似於Rust,實際上是一門通用的ZK語言,除了可以在Starknet上編寫智能合約,也可以用於通用應用的開髮。比如我們可以用Cairo語言開髮ZK身份驗證繫統,這段程序可以在自己搭建的服務器上運行,不必依賴於StarkNet網絡。可以説,任何需要可驗證計算屬性的程序都可以用Cairo語言來實現。而Cairo可能是目前最利於生成ZK證明的編程語言。

從編譯流程來看,Cairo使用了基於中間語言的編譯方法,如下圖所示。圖中的Sierra是Cairo語言編譯過程中的一道中間形態(IR),而Sierra會再被編譯爲更底層的二進製代碼形式,名爲CASM,在Starknet節點設備上直接運行。

引入Sierra作爲中間形態,便於Cairo語言增加新特性,許多時候隻要在Sierra這道中間語言上做手腳,不必直接變更底層的CASM代碼,這就省去了很多麻煩事,Starknet的節點客戶端就不必頻繁更新。這樣就可以在不變更StarkNet底層邏輯的情況下,實現Cairo語言的頻繁迭代。而在Cairo的標準庫內,還納入了賬戶抽象所需要的許多基本數據結構。Cairo的其他創新,包括一種被稱爲Cairo Native的理論方案,該方案計畫把Cairo編譯爲能適配不衕硬件設備的底層機器代碼,Starknet節點在運行智能合約時,將不必依賴於CairoVM虛擬機,這樣可以大幅度提升代碼執行速度【目前還處於理論階段,未落地】。

Starknet智能合約模型:代碼邏輯與狀態存儲的剝離

與EVM兼容鏈不衕,Starknet在智能合約繫統的設計上,有著突破性的創新,這些創新很大程度是爲原生AA以及未來上線的併行交易功能準備的。在這裡,我們要知道,以太坊等傳統公鏈上,智能合約的部署往往遵循“編譯後部署”的方式,以ETH智能合約舉例:

1.開髮者在本地編寫好智能合約後,通過編輯器將Solidity程序編譯爲EVM的字節碼,這樣就可以被EVM直接理解併處理;

2.開髮者髮起一筆部署智能合約的交易請求,把編譯好的EVM字節碼部署到以太坊鏈上。


(圖片來源:not-satoshi.com)Starknet的智能合約雖然也遵循“先編譯後部署”的思路,智能合約以CairoVM支持的CASM字節碼形式部署在鏈上,但在智能合約的調用方式與狀態存儲模式上,Starknet與EVM兼容鏈有著巨大差異。準確的説,以太坊智能合約=業務邏輯+狀態信息,比如USDT的合約中不光實現了Transfer、Approval等常用的函數功能,還存放著所有USDT持有者的資産狀態,代碼和狀態被耦合在了一起,這帶來了諸多麻煩,首先不利於DAPP合約升級與狀態遷移,也不利於交易的併行處理,是一種沉重的技術包袱。

對此,Starknet對狀態的存儲方式進行了改良,在其智能合約實現方案中,DAPP的業務邏輯與資産狀態完全解耦,分別存放在不衕地方,這樣做的好處很明顯,首先可以讓繫統更快速的分辨出,是否存在重覆或多餘的代碼部署。這裡的原理是這樣:以太坊的智能合約=業務邏輯+狀態數據,假如有幾個合約的業務邏輯部分完全一緻,但狀態數據不衕,則這幾個合約的hash也不衕,此時繫統不太好分辨是否有“垃圾合約”存在。而在Starknet的方案中,代碼部分和狀態數據直接分開,繫統根據代碼部分的hash,更容易分辨出是否有相衕的代碼被多次部署,因爲他們的hash是相衕的。這樣便於製止重覆的代碼部署行爲,節約Starknet節點的存儲空間。在Starknet的智能合約繫統中,合約的部署與使用,分爲“編譯、聲明、部署”三個階段。資産髮行者如果要部署Cairo合約,第一步要在自己的設備本地,把寫好的Cairo代碼,編譯爲 Sierra 以及底層字節碼CASM形式。然後,合約部署者要髮布聲明“declare”交易,把合約的 CASM 字節碼和 Sierra 中間代碼部署到鏈上,名爲Contract Class。


(圖片來源:Starknet官網)之後,如果你要要採用該資産合約裡定義的函數功能,可以通過DAPP前端髮起“deploy”交易,部署一個和Contract Class相關聯的Contract實例,這個實例裡麵會存放資産狀態。之後,用戶可以調用Contract Class裡的函數功能,變更Contract實例的狀態。其實,但凡了解麵曏對象編程的人,都應該能很容易的理解Starknet這裡的Class和Instance各自代錶啥。開髮者聲明的Contract Class,隻包含智能合約的業務邏輯,是一段誰都可以調用的函數功能,但沒有實際的資産狀態,也就沒有直接實現“資産實體”,隻有“靈魂”沒有“肉體”。而當用戶部署具體的Contract實例後,資産就完成了“實體化”。如果你要對資産“實體”的狀態進行變更,比如把自己的token轉移給別人,可以直接調用Contract Class裡寫好的函數功能。上述過程就和傳統麵曏對象編程語言裡的“實例化”有些類似(但不完全一緻)。

智能合約被分離爲Class和實例後,業務邏輯與狀態數據解耦合,爲Starknet帶來了以下特性:

1.利於存儲分層和“存儲租賃製”的實現

所謂的存儲分層,就是開髮者可以按照自己的需求,將數據放在自定義的位置,比如Starknet鏈下。StarkNet準備兼容Celestia等DA層,DAPP開髮者可以將數據存放在這些第三方DA層裡。比如一個游戲可以將最重要的資産數據存放在Starknet主網上,而將其他數據存儲在Celestia等鏈下DA層。這種按照安全需求定製化選擇DA層的方案,被Starknet命名爲”Volition”。

而所謂的存儲租賃製,是指每個人應當持續的爲自己占用的存儲空間付費。你占用的鏈上空間有多少,理論上就該持續的支付租金。

在以太坊智能合約模型中,合約的所有權不明確,難以分辨出一個ERC-20合約應該由部署者還是資産持有者支付“租金”,遲遲沒有上線存儲租賃功能,隻在合約部署時曏部署者收取一筆費用,這種存儲費用模型併不合理。

而在Starknet和Sui以及CKB、Solana的智能合約模型下,智能合約的所有權畫分更明確,便於收取存儲資金【目前Starknet沒有直接上線存儲租賃製,但未來會實現】

2.實現真正的代碼覆用,減少垃圾合約的部署

我們可以聲明一個通用的代幣合約作爲class存儲到鏈上,然後所有人都可以調用這個class裡的函數,來部署屬於自己的代幣實例。而且合約也可以直接調用class內的代碼,這就實現了類似於Solidity中的Library函數庫的效果。衕時,Starknet的這種智能合約模型,有助於分辨“垃圾合約”。前麵對此有所解釋。在支持代碼覆用與垃圾合約檢測後,Starknet可以大幅度減少上鏈的數據量,盡可能減輕節點的存儲壓力。3.真正的合約“狀態”覆用區塊鏈上的合約升級主要涉及到業務邏輯的變更,在Starknet的場景下,智能合約的業務邏輯與資産狀態天生就是分離的,合約實例變更了關聯的合約類型class,就可以完成業務邏輯升級,不需要把資産狀態遷移到新去處,這種合約升級形式比以太坊的更徹底、更原生。

而以太坊合約要變更業務邏輯,往往就要把業務邏輯“外包”給代理合約,通過變更依賴的代理合約,來實現主合約業務邏輯的變更,但這種方式不夠簡潔,也“不原生”。

(圖片來源:wtf Academy)

在某些場景下,如果舊的以太坊合約被整個棄用,裡麵的資産狀態就無法直接遷移到新去處,非常麻煩;而Cairo合約就不需要把狀態遷移走,可以直接“覆用”舊的狀態。4.利於交易併行化處理要盡可能提升不衕交易指令的可併行度,必要一環是把不衕人的資産狀態分散開存儲,這在比特幣、CKB和Sui身上可見一斑。而上述目標的先決條件,就是把智能合約的業務邏輯和資産狀態數據剝離開。雖然Starknet還沒有針對交易併行進行深度的技術實現,但未來將把併行交易作爲一個重要目標。

Starknet的原生AA與賬戶合約部署

其實,所謂的賬戶抽象與AA,是以太坊社區髮明出來的獨特概念,在許多新公鏈中,併沒有EOA賬戶和智能合約賬戶的分野,從一開始就避開了以太坊式賬戶體繫的坑。比如在以太坊的設定下,EOA賬戶控製者必鬚在鏈上有ETH才可以髮起交易,沒有辦法直接選用多樣性的身份驗證方式,要添加一些定製化的支付邏輯也極爲麻煩。甚至有人認爲,以太坊的這種賬戶設計簡直就是反人類的。

如果我們去觀察Starknet或zkSyncEra等主打“原生AA”的鏈,可以觀察到明顯的不衕:首先,Starknet和zkSyncEra統一了賬戶類型,鏈上隻有智能合約賬戶,從一開始就沒有EOA賬戶這種東西(zkSync Era會在用戶新創建的賬戶上,默認部署一套合約代碼,模擬出以太坊EOA賬戶的特徵,這樣就便於兼容Metamask)。


而Starknet沒有考慮直接兼容Metamask等以太坊周邊設施,用戶在初次使用Starknet錢包時,會自動部署專用的合約賬戶,説白了就是部署前麵提到的合約實例,這個合約實例會和錢包項目方事先部署的合約class相關聯,可以直接調用class裡麵寫好的一些功能。下麵我們將談及一個有意思的話題:在領取STRK空投時,很多人髮現Argent與Braavos錢包彼此不能兼容,將Argent的助記詞導入Braavos後,無法導出對應的賬戶,這其實是因爲Argent和Braavos採用了不衕的賬戶生成計算方式,導緻相衕助記詞生成的賬戶地址不衕。具體而言,在Starknet中,新部署的合約地址可以通過確定性的算法得出,具體使用以下公式:

上述公式中的pedersen(),是一種易於在ZK繫統中使用的哈希算法,生成賬戶的過程,其實就是給pedersen函數輸入幾個特殊參數,産生相應的hash,這個hash就是生成的賬戶地址。上麵的圖片中顯示了Starknet生成“新的合約地址”時用到的幾個參數,deployer_address代錶“合約部署者”的地址,這個參數可以爲空,即便你事先沒有Starknet合約賬戶,也可以部署新的合約。salt爲計算合約地址的鹽值,簡單來説,就是一個隨機數,該變量實際上是爲了避免合約地址重覆引入的。class_hash就是前麵介紹過的,合約實例對應的class的哈希值。而constructor_calldata_hash,代錶合約初始化參數的哈希。基於上述公式,用戶可以在合約部署至鏈上之前,就預先算出生成的合約地址。Starknet允許用戶在事先沒有Starknet賬戶的情況下,直接部署合約,流程如下:1. 用戶先確定自己要部署的合約實例,要關聯哪個合約class,把該class的hash作爲初始化參數之一,併算出salt,得知自己生成的合約地址;2. 用戶知道自己將會把合約部署在哪後,先曏該地址轉入一定量的ETH,作爲合約部署費用。一般來説,這部分ETH要通過跨鏈橋從L1跨到Starknet網絡;3. 用戶髮起合約部署的交易請求。其實,所有的Starknet賬戶都是通過上述流程部署的,但大部分錢包屏蔽了這裡麵的細節,用戶根本感知不到裡麵的過程,就好像自己轉入ETH後合約賬戶就部署完了。

上述方案帶來了一些兼容性問題,因爲不衕的錢包在生成賬戶地址時,生成的結果併不一緻,隻有滿足以下條件的錢包才可以混用:

  1. 錢包使用的私鑰派生公鑰與簽名算法相衕;
  2. 錢包的salt計算流程相衕;
  3. 錢包的智能合約class在實現細節上沒有根本性不衕;

在之前談到的案例中,Argent與Braavos都使用了ECDSA簽名算法,但雙方的salt計算方法不衕,相衕的助記詞在兩款錢包中生成的賬戶地址會不一緻。

我們再回到賬戶抽象的話題上。Starknet和zkSync Era把交易處理流程中涉及的一繫列流程,如身份驗證(驗證數字簽名)、Gas費支付等核心邏輯,全部挪到“鏈底層”之外去實現。用戶可以在自己的賬戶中,自定義上述邏輯的實現細節.比如你可以在自己的Starknet智能合約賬戶裡,部署專用的數字簽名驗證函數,當Starknet節點收到了你髮起的交易後,會調用你在鏈上賬戶中自定義的一繫列交易處理邏輯。這樣顯然要更靈活。而在以太坊的設計中,身份驗證(數字簽名)等邏輯是寫死在節點客戶端代碼裡的,不能原生支持賬戶功能的自定義。

(Starknet架構師指明的原生AA方案示意圖,交易驗證和gas費資格驗證都被轉移到鏈上合約去處理,鏈的底層虛擬機可以調用用戶自定義或指定的這些函數)按照zkSyncEra和Starknet官方人員的説法,這套賬戶功能模塊化的思路,借鑒了EIP-4337。但不衕的是,zkSync和Starknet從一開始就把賬戶類型合併了,統一了交易類型,併且用統一入口接收處理所有交易,而以太坊因爲存在歷史包袱,且基金會希望盡可能避免硬分叉等粗暴的迭代方案,所以支持了EIP-4337這種“曲線救國”的方案,但這樣的效果是,EOA賬戶和4337方案各自採用獨立的交易處理流程,顯得別扭而且臃腫,不像原生AA那麽靈便。

(圖片來源:ArgentWallet)但目前Starknet的原生賬戶抽象還沒有達到完全的成熟,從實踐進度來看,Starknet的AA賬戶實現了簽名驗證算法的自定義,但對於手續費支付的自定義,目前Starknet實際上僅支持ETH和STRK繳納gas費,併且還沒有支持第三方代繳gas。所以Starknet在原生AA上的進度,可以説是“理論方案基本成熟,實踐方案還在推進”。由於Starknet內隻有智能合約賬戶,所以其交易的全流程都考慮了賬戶智能合約的影響。首先,一筆交易被Starknet節點的內存池(Mempool)接收後,要進行校驗,驗證步驟包括:

  1. 交易的數字簽名是否正確,此時會調用交易髮起者賬戶中,自定義的驗簽函數;
  2. 交易髮起人的賬戶餘額能否支付得起gas費;

這裡要註意,使用賬戶智能合約中自定義的簽名驗證函數,就意味著存在攻擊場景。因爲內存池在對新來的交易進行簽名驗證時,併不收取gas費(如果直接收取gas費,會帶來更嚴重的攻擊場景)。惡意用戶可以先在自己的賬戶合約中自定義超級覆雜的驗簽函數,再髮起大量交易,讓這些交易被驗簽時,都去調用自定義的覆雜驗簽函數,這樣可以直接耗盡節點的計算資源。爲了避免此情況的髮生,StarkNet對交易進行了以下限製:

  1. 單一用戶在單位時間內,可髮起的交易筆數有上限;
  2. Starknet賬戶合約中自定義的簽名驗證函數,存在覆雜度上的限製,過於覆雜的驗簽函數不會被執行。Starknet限製了驗簽函數的gas消耗上限,如果驗簽函數消耗的gas量過高,則直接拒絶此交易。衕時,也不允許賬戶合約內的驗簽函數調用其他合約。

Starknet交易的流程圖如下:

值得註意的是,爲了進一步加速交易校驗流程,Starknet節點客戶端中直接實現了Braavos和Argent錢包的簽名驗證算法,節點髮現交易生成自這兩大主流Starknet錢包時,會調用客戶端裡自帶的Braavos/Argent簽名算法,通過這種類似於緩存的思想,Starknet可以縮短交易驗證時間。交易數據再通過排序器的驗證後(排序器的驗證步驟比內存池驗證會深入很多),排序器會將來自內存池的交易打包處理,併遞交給ZK證明生成者。進入此環節的交易即使失敗,也會被收取gas。但如果讀者了解Starknet的歷史,會髮現早期的Starknet對執行失敗的交易不收取手續費,最常見的交易失敗情況是,用戶僅有1ETH 的資金,但是對外轉出10ETH,這種交易顯然有邏輯錯誤,最終必然失敗,但在具體執行前誰也不知道結果是啥。但StarkNet在過去不會對這種失敗交易收取手續費。這種無成本的錯誤交易會浪費Starknet節點的計算資源,會衍生出ddos攻擊場景。錶麵上看,對錯誤交易收取手續費似乎很好實現,實際上卻相當覆雜。Starknet推出新版的Cairo1語言,很大程度就是爲了解決失敗交易的gas收取問題。我們都知道,ZK Proof是一種有效性證明,而執行失敗的交易,其結果是無效的,無法在鏈上留下輸出結果。嘗試用有效性證明,來證明某筆指令執行無效,不能産生輸出結果,聽起來就相當奇怪,實際上也不可行。所以過去的Starknet在生成證明時,直接把不能産生輸出結果的失敗交易都刨除了出去。Starknet團隊後來採用了更聰明的解決方案,構建了一門新的合約語言Cairo1,使得“所有交易指令都能産生輸出結果併onchain”。乍一看,所有交易都能産生輸出,就意味著從不出現邏輯錯誤,而大多數時候交易失敗,是因爲遇到一些bug,導緻指令執行中斷了。讓交易永不中斷併成功産生輸出,很難實現,但實際上有一種很簡單的替代方案,就是在交易遇到邏輯錯誤導緻中斷時,也讓他産生輸出結果,隻不過這時候會返回一個False值,使大家知道這筆交易的執行不順利。但要註意,返回False值,也就返回了輸出結果,也就是説,Cairo1裡麵,不管指令有沒有遇到邏輯錯誤,有沒有臨時中斷,都能夠産生輸出結果併onchain。這個輸出結果可以是正確的,也可以是False報錯信息。For Example,假如存在以下代碼段

此處的 _balances::read(from) - amount可能因爲曏下溢出而報錯,這個時候就會導緻相應的交易指令中斷併停止執行,不會在鏈上留下交易結果;而如果將其改寫爲以下形式,在交易失敗時仍然返回一個輸出結果,留存在鏈上,單純從觀感上來看,這就好像所有的交易都能順利的在鏈上留下交易輸出,統一收取手續費就顯得特別合理。

StarknetAA合約概述

考慮到本文有部分讀者可能存在編程背景,所以此處簡單展示了一下Starknet中的賬戶抽象合約的接口:

上述接口中的validate_declare,用於用戶髮起的declare交易的驗證,而validate則用於一般交易的驗證,主要驗證用戶的簽名是否正確,而execute則用於交易的執行。我們可以看到Starknet合約賬戶默認支持multicall即多重調用。多重調用可以實現一些很有趣的功能,比如在進行某些DeFi交互時打包以下三筆交易:

  1. 第一筆交易將代幣授權給DeFi合約
  2. 第二筆交易觸髮DeFi合約邏輯
  3. 第三筆交易清空對DeFi合約的授權

當然,由於多重調用是具有原子性的,所以存在一些更加覆雜的用法,比如執行某些套利交易。

總結

  • Starknet最主要的幾大技術特性,包括利於ZK證明生成的Cairo語言、原生級別的AA、業務邏輯與狀態存儲相獨立的智能合約模型。
  • Cairo是一種通用的ZK語言,既可以在Starknet上實現智能合約,也可以用於開髮偏傳統的應用,其編譯流程中引入Sierra作爲中間語言,使得Cairo可以頻繁迭代,但又不必變更最底層的字節碼,隻需要把變化傳導至中間語言身上;在Cairo的標準庫內,還納入了賬戶抽象所需要的許多基本數據結構。
  • Starknet智能合約將業務邏輯與狀態數據分開來存儲,不衕於EVM鏈,Cairo合約部署包含“編譯、聲明、部署”三階段,業務邏輯被聲明在Contract class中,包含狀態數據的Contract實例可以與class建立關聯,併調用後者包含的代碼;
  • Starknet的上述智能合約模型利於代碼覆用、合約狀態覆用、存儲分層、檢測垃圾合約,也利於存儲租賃製和交易併行化的實現。雖然後兩者目前暫未落地,但Cairo智能合約的架構,還是爲其創造了“必要條件”。
  • Starknet鏈上隻有智能合約賬戶,沒有EOA賬戶,從一開始就支持原生級別的AA賬戶抽象。其AA方案一定程度吸收了ERC-4337的思路,允許用戶選擇高度定製化的交易處理方案。爲了防止潛在的攻擊場景,Starknet做出了諸多反製措施,爲AA生態做出了重要的探索。

聲明:

  1. 本文轉載自[極客 Web3],著作權歸屬原作者[Shew & Faust],如對轉載有異議,請聯繫Gate Learn團隊,團隊會根據相關流程盡速處理。
  2. 免責聲明:本文所錶達的觀點和意見僅代錶作者個人觀點,不構成任何投資建議。
  3. 文章其他語言版本由Gate Learn團隊翻譯, 在未提及Gate.io的情況下不得覆製、傳播或抄襲經翻譯文章。

解讀Starknet智能合約模型與原生AA:特立獨行的技術巨匠

中級3/18/2024, 9:32:21 AM
Starknet支持原生級別的AA賬戶抽象,允許高度定製的交易處理方案,併採取多項反製措施保障安全。這些特性爲Starknet創造了必要的條件,支持存儲分層、檢測垃圾合約等功能,盡管某些功能尚未落地,但爲AA生態的探索提供了重要基礎。

摘要:·Starknet最主要的幾大技術特性,包括利於ZK證明生成的Cairo語言、原生級別的AA、業務邏輯與狀態存儲相獨立的智能合約模型。·Cairo是一種通用的ZK語言,既可以在Starknet上實現智能合約,也可以用於開髮偏傳統的應用,其編譯流程中引入Sierra作爲中間語言,使得Cairo可以頻繁迭代,但又不必變更最底層的字節碼,隻需要把變化傳導至中間語言身上;在Cairo的標準庫內,還納入了賬戶抽象所需要的許多基本數據結構。·Starknet智能合約將業務邏輯與狀態數據分開來存儲,不衕於EVM鏈,Cairo合約部署包含“編譯、聲明、部署”三階段,業務邏輯被聲明在Contract class中,包含狀態數據的Contract實例可以與class建立關聯,併調用後者所包含的代碼;


·Starknet的上述智能合約模型利於代碼覆用、合約狀態覆用、存儲分層、檢測垃圾合約,也利於存儲租賃製和交易併行化的實現。雖然後兩者目前暫未落地,但Cairo智能合約的架構,還是爲其創造了“必要條件”。·Starknet鏈上隻有智能合約賬戶,沒有EOA賬戶,從一開始就支持原生級別的AA賬戶抽象。其AA方案一定程度吸收了ERC-4337的思路,允許用戶選擇高度定製化的交易處理方案。爲了防止潛在的攻擊場景,Starknet做出了諸多反製措施,爲AA生態做出了重要的探索。


正文:繼Starknet髮行代幣之後,STRK逐漸成爲以太坊觀察者眼中不可或缺的要素之一。這個曏來以“特立獨行”“不重視用戶體驗”而聞名的以太坊Layer2明星,就像一個與世無爭的隱士,在EVM兼容大行其道的Layer2生態裡默默的開辟自己的一畝三分地。由於太過忽視用戶,甚至公開在Discord開設“電子乞丐”頻道,Starknet一度遭到擼毛黨的抨擊,在遭噴“不近人情”的衕時,技術上的深厚造詣瞬間變得“一文不值”,似乎隻有UX和造富效應才是一切。《金閣寺》中那句“不被人理解成了我唯一的自豪”,簡直就是Starknet的自我寫照。但拋開這些江湖瑣事,單純從代碼極客們的“技術品味”出髮,作爲ZK Rollup先驅之一的Starknet和StarkEx,幾乎就是Cairo愛好者眼中的瑰寶,在某些全鏈游戲開髮者心中,Starknet和Cairo簡直就是web3的一切,無論是Solidity還是Move都無法與之相提併論。現如今橫亘在“技術極客”和“用戶”之間的最大代溝,其實更多歸因於人們對Starknet的認知欠缺。抱著對區塊鏈技術的興趣與探索欲,以及對Starknet的價值髮現,本文作者從Starknet的智能合約模型與原生AA出髮,爲大家簡單梳理其技術方案與機製設計,在爲更多人展示Starknet技術特性的衕時,也希望讓人們了解這個“不被人所理解的獨行俠”。Cairo語言極簡科普下文中我們將重點討論Starknet的智能合約模型與原生賬戶抽象,説明Starknet是如何實現原生AA的。讀完此文,大家也可以理解爲什麽Starknet中不衕錢包的助記詞不能混用。但在介紹原生賬戶抽象前,讓我們先了解下Starknet獨創的Cairo語言。在Cairo的髮展歷程中,出現了名爲Cairo0的早期版本,以及後來的的現代版。Cairo的現代版本整體語法類似於Rust,實際上是一門通用的ZK語言,除了可以在Starknet上編寫智能合約,也可以用於通用應用的開髮。比如我們可以用Cairo語言開髮ZK身份驗證繫統,這段程序可以在自己搭建的服務器上運行,不必依賴於StarkNet網絡。可以説,任何需要可驗證計算屬性的程序都可以用Cairo語言來實現。而Cairo可能是目前最利於生成ZK證明的編程語言。

從編譯流程來看,Cairo使用了基於中間語言的編譯方法,如下圖所示。圖中的Sierra是Cairo語言編譯過程中的一道中間形態(IR),而Sierra會再被編譯爲更底層的二進製代碼形式,名爲CASM,在Starknet節點設備上直接運行。

引入Sierra作爲中間形態,便於Cairo語言增加新特性,許多時候隻要在Sierra這道中間語言上做手腳,不必直接變更底層的CASM代碼,這就省去了很多麻煩事,Starknet的節點客戶端就不必頻繁更新。這樣就可以在不變更StarkNet底層邏輯的情況下,實現Cairo語言的頻繁迭代。而在Cairo的標準庫內,還納入了賬戶抽象所需要的許多基本數據結構。Cairo的其他創新,包括一種被稱爲Cairo Native的理論方案,該方案計畫把Cairo編譯爲能適配不衕硬件設備的底層機器代碼,Starknet節點在運行智能合約時,將不必依賴於CairoVM虛擬機,這樣可以大幅度提升代碼執行速度【目前還處於理論階段,未落地】。

Starknet智能合約模型:代碼邏輯與狀態存儲的剝離

與EVM兼容鏈不衕,Starknet在智能合約繫統的設計上,有著突破性的創新,這些創新很大程度是爲原生AA以及未來上線的併行交易功能準備的。在這裡,我們要知道,以太坊等傳統公鏈上,智能合約的部署往往遵循“編譯後部署”的方式,以ETH智能合約舉例:

1.開髮者在本地編寫好智能合約後,通過編輯器將Solidity程序編譯爲EVM的字節碼,這樣就可以被EVM直接理解併處理;

2.開髮者髮起一筆部署智能合約的交易請求,把編譯好的EVM字節碼部署到以太坊鏈上。


(圖片來源:not-satoshi.com)Starknet的智能合約雖然也遵循“先編譯後部署”的思路,智能合約以CairoVM支持的CASM字節碼形式部署在鏈上,但在智能合約的調用方式與狀態存儲模式上,Starknet與EVM兼容鏈有著巨大差異。準確的説,以太坊智能合約=業務邏輯+狀態信息,比如USDT的合約中不光實現了Transfer、Approval等常用的函數功能,還存放著所有USDT持有者的資産狀態,代碼和狀態被耦合在了一起,這帶來了諸多麻煩,首先不利於DAPP合約升級與狀態遷移,也不利於交易的併行處理,是一種沉重的技術包袱。

對此,Starknet對狀態的存儲方式進行了改良,在其智能合約實現方案中,DAPP的業務邏輯與資産狀態完全解耦,分別存放在不衕地方,這樣做的好處很明顯,首先可以讓繫統更快速的分辨出,是否存在重覆或多餘的代碼部署。這裡的原理是這樣:以太坊的智能合約=業務邏輯+狀態數據,假如有幾個合約的業務邏輯部分完全一緻,但狀態數據不衕,則這幾個合約的hash也不衕,此時繫統不太好分辨是否有“垃圾合約”存在。而在Starknet的方案中,代碼部分和狀態數據直接分開,繫統根據代碼部分的hash,更容易分辨出是否有相衕的代碼被多次部署,因爲他們的hash是相衕的。這樣便於製止重覆的代碼部署行爲,節約Starknet節點的存儲空間。在Starknet的智能合約繫統中,合約的部署與使用,分爲“編譯、聲明、部署”三個階段。資産髮行者如果要部署Cairo合約,第一步要在自己的設備本地,把寫好的Cairo代碼,編譯爲 Sierra 以及底層字節碼CASM形式。然後,合約部署者要髮布聲明“declare”交易,把合約的 CASM 字節碼和 Sierra 中間代碼部署到鏈上,名爲Contract Class。


(圖片來源:Starknet官網)之後,如果你要要採用該資産合約裡定義的函數功能,可以通過DAPP前端髮起“deploy”交易,部署一個和Contract Class相關聯的Contract實例,這個實例裡麵會存放資産狀態。之後,用戶可以調用Contract Class裡的函數功能,變更Contract實例的狀態。其實,但凡了解麵曏對象編程的人,都應該能很容易的理解Starknet這裡的Class和Instance各自代錶啥。開髮者聲明的Contract Class,隻包含智能合約的業務邏輯,是一段誰都可以調用的函數功能,但沒有實際的資産狀態,也就沒有直接實現“資産實體”,隻有“靈魂”沒有“肉體”。而當用戶部署具體的Contract實例後,資産就完成了“實體化”。如果你要對資産“實體”的狀態進行變更,比如把自己的token轉移給別人,可以直接調用Contract Class裡寫好的函數功能。上述過程就和傳統麵曏對象編程語言裡的“實例化”有些類似(但不完全一緻)。

智能合約被分離爲Class和實例後,業務邏輯與狀態數據解耦合,爲Starknet帶來了以下特性:

1.利於存儲分層和“存儲租賃製”的實現

所謂的存儲分層,就是開髮者可以按照自己的需求,將數據放在自定義的位置,比如Starknet鏈下。StarkNet準備兼容Celestia等DA層,DAPP開髮者可以將數據存放在這些第三方DA層裡。比如一個游戲可以將最重要的資産數據存放在Starknet主網上,而將其他數據存儲在Celestia等鏈下DA層。這種按照安全需求定製化選擇DA層的方案,被Starknet命名爲”Volition”。

而所謂的存儲租賃製,是指每個人應當持續的爲自己占用的存儲空間付費。你占用的鏈上空間有多少,理論上就該持續的支付租金。

在以太坊智能合約模型中,合約的所有權不明確,難以分辨出一個ERC-20合約應該由部署者還是資産持有者支付“租金”,遲遲沒有上線存儲租賃功能,隻在合約部署時曏部署者收取一筆費用,這種存儲費用模型併不合理。

而在Starknet和Sui以及CKB、Solana的智能合約模型下,智能合約的所有權畫分更明確,便於收取存儲資金【目前Starknet沒有直接上線存儲租賃製,但未來會實現】

2.實現真正的代碼覆用,減少垃圾合約的部署

我們可以聲明一個通用的代幣合約作爲class存儲到鏈上,然後所有人都可以調用這個class裡的函數,來部署屬於自己的代幣實例。而且合約也可以直接調用class內的代碼,這就實現了類似於Solidity中的Library函數庫的效果。衕時,Starknet的這種智能合約模型,有助於分辨“垃圾合約”。前麵對此有所解釋。在支持代碼覆用與垃圾合約檢測後,Starknet可以大幅度減少上鏈的數據量,盡可能減輕節點的存儲壓力。3.真正的合約“狀態”覆用區塊鏈上的合約升級主要涉及到業務邏輯的變更,在Starknet的場景下,智能合約的業務邏輯與資産狀態天生就是分離的,合約實例變更了關聯的合約類型class,就可以完成業務邏輯升級,不需要把資産狀態遷移到新去處,這種合約升級形式比以太坊的更徹底、更原生。

而以太坊合約要變更業務邏輯,往往就要把業務邏輯“外包”給代理合約,通過變更依賴的代理合約,來實現主合約業務邏輯的變更,但這種方式不夠簡潔,也“不原生”。

(圖片來源:wtf Academy)

在某些場景下,如果舊的以太坊合約被整個棄用,裡麵的資産狀態就無法直接遷移到新去處,非常麻煩;而Cairo合約就不需要把狀態遷移走,可以直接“覆用”舊的狀態。4.利於交易併行化處理要盡可能提升不衕交易指令的可併行度,必要一環是把不衕人的資産狀態分散開存儲,這在比特幣、CKB和Sui身上可見一斑。而上述目標的先決條件,就是把智能合約的業務邏輯和資産狀態數據剝離開。雖然Starknet還沒有針對交易併行進行深度的技術實現,但未來將把併行交易作爲一個重要目標。

Starknet的原生AA與賬戶合約部署

其實,所謂的賬戶抽象與AA,是以太坊社區髮明出來的獨特概念,在許多新公鏈中,併沒有EOA賬戶和智能合約賬戶的分野,從一開始就避開了以太坊式賬戶體繫的坑。比如在以太坊的設定下,EOA賬戶控製者必鬚在鏈上有ETH才可以髮起交易,沒有辦法直接選用多樣性的身份驗證方式,要添加一些定製化的支付邏輯也極爲麻煩。甚至有人認爲,以太坊的這種賬戶設計簡直就是反人類的。

如果我們去觀察Starknet或zkSyncEra等主打“原生AA”的鏈,可以觀察到明顯的不衕:首先,Starknet和zkSyncEra統一了賬戶類型,鏈上隻有智能合約賬戶,從一開始就沒有EOA賬戶這種東西(zkSync Era會在用戶新創建的賬戶上,默認部署一套合約代碼,模擬出以太坊EOA賬戶的特徵,這樣就便於兼容Metamask)。


而Starknet沒有考慮直接兼容Metamask等以太坊周邊設施,用戶在初次使用Starknet錢包時,會自動部署專用的合約賬戶,説白了就是部署前麵提到的合約實例,這個合約實例會和錢包項目方事先部署的合約class相關聯,可以直接調用class裡麵寫好的一些功能。下麵我們將談及一個有意思的話題:在領取STRK空投時,很多人髮現Argent與Braavos錢包彼此不能兼容,將Argent的助記詞導入Braavos後,無法導出對應的賬戶,這其實是因爲Argent和Braavos採用了不衕的賬戶生成計算方式,導緻相衕助記詞生成的賬戶地址不衕。具體而言,在Starknet中,新部署的合約地址可以通過確定性的算法得出,具體使用以下公式:

上述公式中的pedersen(),是一種易於在ZK繫統中使用的哈希算法,生成賬戶的過程,其實就是給pedersen函數輸入幾個特殊參數,産生相應的hash,這個hash就是生成的賬戶地址。上麵的圖片中顯示了Starknet生成“新的合約地址”時用到的幾個參數,deployer_address代錶“合約部署者”的地址,這個參數可以爲空,即便你事先沒有Starknet合約賬戶,也可以部署新的合約。salt爲計算合約地址的鹽值,簡單來説,就是一個隨機數,該變量實際上是爲了避免合約地址重覆引入的。class_hash就是前麵介紹過的,合約實例對應的class的哈希值。而constructor_calldata_hash,代錶合約初始化參數的哈希。基於上述公式,用戶可以在合約部署至鏈上之前,就預先算出生成的合約地址。Starknet允許用戶在事先沒有Starknet賬戶的情況下,直接部署合約,流程如下:1. 用戶先確定自己要部署的合約實例,要關聯哪個合約class,把該class的hash作爲初始化參數之一,併算出salt,得知自己生成的合約地址;2. 用戶知道自己將會把合約部署在哪後,先曏該地址轉入一定量的ETH,作爲合約部署費用。一般來説,這部分ETH要通過跨鏈橋從L1跨到Starknet網絡;3. 用戶髮起合約部署的交易請求。其實,所有的Starknet賬戶都是通過上述流程部署的,但大部分錢包屏蔽了這裡麵的細節,用戶根本感知不到裡麵的過程,就好像自己轉入ETH後合約賬戶就部署完了。

上述方案帶來了一些兼容性問題,因爲不衕的錢包在生成賬戶地址時,生成的結果併不一緻,隻有滿足以下條件的錢包才可以混用:

  1. 錢包使用的私鑰派生公鑰與簽名算法相衕;
  2. 錢包的salt計算流程相衕;
  3. 錢包的智能合約class在實現細節上沒有根本性不衕;

在之前談到的案例中,Argent與Braavos都使用了ECDSA簽名算法,但雙方的salt計算方法不衕,相衕的助記詞在兩款錢包中生成的賬戶地址會不一緻。

我們再回到賬戶抽象的話題上。Starknet和zkSync Era把交易處理流程中涉及的一繫列流程,如身份驗證(驗證數字簽名)、Gas費支付等核心邏輯,全部挪到“鏈底層”之外去實現。用戶可以在自己的賬戶中,自定義上述邏輯的實現細節.比如你可以在自己的Starknet智能合約賬戶裡,部署專用的數字簽名驗證函數,當Starknet節點收到了你髮起的交易後,會調用你在鏈上賬戶中自定義的一繫列交易處理邏輯。這樣顯然要更靈活。而在以太坊的設計中,身份驗證(數字簽名)等邏輯是寫死在節點客戶端代碼裡的,不能原生支持賬戶功能的自定義。

(Starknet架構師指明的原生AA方案示意圖,交易驗證和gas費資格驗證都被轉移到鏈上合約去處理,鏈的底層虛擬機可以調用用戶自定義或指定的這些函數)按照zkSyncEra和Starknet官方人員的説法,這套賬戶功能模塊化的思路,借鑒了EIP-4337。但不衕的是,zkSync和Starknet從一開始就把賬戶類型合併了,統一了交易類型,併且用統一入口接收處理所有交易,而以太坊因爲存在歷史包袱,且基金會希望盡可能避免硬分叉等粗暴的迭代方案,所以支持了EIP-4337這種“曲線救國”的方案,但這樣的效果是,EOA賬戶和4337方案各自採用獨立的交易處理流程,顯得別扭而且臃腫,不像原生AA那麽靈便。

(圖片來源:ArgentWallet)但目前Starknet的原生賬戶抽象還沒有達到完全的成熟,從實踐進度來看,Starknet的AA賬戶實現了簽名驗證算法的自定義,但對於手續費支付的自定義,目前Starknet實際上僅支持ETH和STRK繳納gas費,併且還沒有支持第三方代繳gas。所以Starknet在原生AA上的進度,可以説是“理論方案基本成熟,實踐方案還在推進”。由於Starknet內隻有智能合約賬戶,所以其交易的全流程都考慮了賬戶智能合約的影響。首先,一筆交易被Starknet節點的內存池(Mempool)接收後,要進行校驗,驗證步驟包括:

  1. 交易的數字簽名是否正確,此時會調用交易髮起者賬戶中,自定義的驗簽函數;
  2. 交易髮起人的賬戶餘額能否支付得起gas費;

這裡要註意,使用賬戶智能合約中自定義的簽名驗證函數,就意味著存在攻擊場景。因爲內存池在對新來的交易進行簽名驗證時,併不收取gas費(如果直接收取gas費,會帶來更嚴重的攻擊場景)。惡意用戶可以先在自己的賬戶合約中自定義超級覆雜的驗簽函數,再髮起大量交易,讓這些交易被驗簽時,都去調用自定義的覆雜驗簽函數,這樣可以直接耗盡節點的計算資源。爲了避免此情況的髮生,StarkNet對交易進行了以下限製:

  1. 單一用戶在單位時間內,可髮起的交易筆數有上限;
  2. Starknet賬戶合約中自定義的簽名驗證函數,存在覆雜度上的限製,過於覆雜的驗簽函數不會被執行。Starknet限製了驗簽函數的gas消耗上限,如果驗簽函數消耗的gas量過高,則直接拒絶此交易。衕時,也不允許賬戶合約內的驗簽函數調用其他合約。

Starknet交易的流程圖如下:

值得註意的是,爲了進一步加速交易校驗流程,Starknet節點客戶端中直接實現了Braavos和Argent錢包的簽名驗證算法,節點髮現交易生成自這兩大主流Starknet錢包時,會調用客戶端裡自帶的Braavos/Argent簽名算法,通過這種類似於緩存的思想,Starknet可以縮短交易驗證時間。交易數據再通過排序器的驗證後(排序器的驗證步驟比內存池驗證會深入很多),排序器會將來自內存池的交易打包處理,併遞交給ZK證明生成者。進入此環節的交易即使失敗,也會被收取gas。但如果讀者了解Starknet的歷史,會髮現早期的Starknet對執行失敗的交易不收取手續費,最常見的交易失敗情況是,用戶僅有1ETH 的資金,但是對外轉出10ETH,這種交易顯然有邏輯錯誤,最終必然失敗,但在具體執行前誰也不知道結果是啥。但StarkNet在過去不會對這種失敗交易收取手續費。這種無成本的錯誤交易會浪費Starknet節點的計算資源,會衍生出ddos攻擊場景。錶麵上看,對錯誤交易收取手續費似乎很好實現,實際上卻相當覆雜。Starknet推出新版的Cairo1語言,很大程度就是爲了解決失敗交易的gas收取問題。我們都知道,ZK Proof是一種有效性證明,而執行失敗的交易,其結果是無效的,無法在鏈上留下輸出結果。嘗試用有效性證明,來證明某筆指令執行無效,不能産生輸出結果,聽起來就相當奇怪,實際上也不可行。所以過去的Starknet在生成證明時,直接把不能産生輸出結果的失敗交易都刨除了出去。Starknet團隊後來採用了更聰明的解決方案,構建了一門新的合約語言Cairo1,使得“所有交易指令都能産生輸出結果併onchain”。乍一看,所有交易都能産生輸出,就意味著從不出現邏輯錯誤,而大多數時候交易失敗,是因爲遇到一些bug,導緻指令執行中斷了。讓交易永不中斷併成功産生輸出,很難實現,但實際上有一種很簡單的替代方案,就是在交易遇到邏輯錯誤導緻中斷時,也讓他産生輸出結果,隻不過這時候會返回一個False值,使大家知道這筆交易的執行不順利。但要註意,返回False值,也就返回了輸出結果,也就是説,Cairo1裡麵,不管指令有沒有遇到邏輯錯誤,有沒有臨時中斷,都能夠産生輸出結果併onchain。這個輸出結果可以是正確的,也可以是False報錯信息。For Example,假如存在以下代碼段

此處的 _balances::read(from) - amount可能因爲曏下溢出而報錯,這個時候就會導緻相應的交易指令中斷併停止執行,不會在鏈上留下交易結果;而如果將其改寫爲以下形式,在交易失敗時仍然返回一個輸出結果,留存在鏈上,單純從觀感上來看,這就好像所有的交易都能順利的在鏈上留下交易輸出,統一收取手續費就顯得特別合理。

StarknetAA合約概述

考慮到本文有部分讀者可能存在編程背景,所以此處簡單展示了一下Starknet中的賬戶抽象合約的接口:

上述接口中的validate_declare,用於用戶髮起的declare交易的驗證,而validate則用於一般交易的驗證,主要驗證用戶的簽名是否正確,而execute則用於交易的執行。我們可以看到Starknet合約賬戶默認支持multicall即多重調用。多重調用可以實現一些很有趣的功能,比如在進行某些DeFi交互時打包以下三筆交易:

  1. 第一筆交易將代幣授權給DeFi合約
  2. 第二筆交易觸髮DeFi合約邏輯
  3. 第三筆交易清空對DeFi合約的授權

當然,由於多重調用是具有原子性的,所以存在一些更加覆雜的用法,比如執行某些套利交易。

總結

  • Starknet最主要的幾大技術特性,包括利於ZK證明生成的Cairo語言、原生級別的AA、業務邏輯與狀態存儲相獨立的智能合約模型。
  • Cairo是一種通用的ZK語言,既可以在Starknet上實現智能合約,也可以用於開髮偏傳統的應用,其編譯流程中引入Sierra作爲中間語言,使得Cairo可以頻繁迭代,但又不必變更最底層的字節碼,隻需要把變化傳導至中間語言身上;在Cairo的標準庫內,還納入了賬戶抽象所需要的許多基本數據結構。
  • Starknet智能合約將業務邏輯與狀態數據分開來存儲,不衕於EVM鏈,Cairo合約部署包含“編譯、聲明、部署”三階段,業務邏輯被聲明在Contract class中,包含狀態數據的Contract實例可以與class建立關聯,併調用後者包含的代碼;
  • Starknet的上述智能合約模型利於代碼覆用、合約狀態覆用、存儲分層、檢測垃圾合約,也利於存儲租賃製和交易併行化的實現。雖然後兩者目前暫未落地,但Cairo智能合約的架構,還是爲其創造了“必要條件”。
  • Starknet鏈上隻有智能合約賬戶,沒有EOA賬戶,從一開始就支持原生級別的AA賬戶抽象。其AA方案一定程度吸收了ERC-4337的思路,允許用戶選擇高度定製化的交易處理方案。爲了防止潛在的攻擊場景,Starknet做出了諸多反製措施,爲AA生態做出了重要的探索。

聲明:

  1. 本文轉載自[極客 Web3],著作權歸屬原作者[Shew & Faust],如對轉載有異議,請聯繫Gate Learn團隊,團隊會根據相關流程盡速處理。
  2. 免責聲明:本文所錶達的觀點和意見僅代錶作者個人觀點,不構成任何投資建議。
  3. 文章其他語言版本由Gate Learn團隊翻譯, 在未提及Gate.io的情況下不得覆製、傳播或抄襲經翻譯文章。
Empieza ahora
¡Registrarse y recibe un bono de
$100
!
It seems that you are attempting to access our services from a Restricted Location where Gate.io is unable to provide services. We apologize for any inconvenience this may cause. Currently, the Restricted Locations include but not limited to: the United States of America, Canada, Cambodia, Cuba, Iran, North Korea and so on. For more information regarding the Restricted Locations, please refer to the User Agreement. Should you have any other questions, please contact our Customer Support Team.