本文件說明截至目前為止,引導式元件架構的設計原則。
如果本文件中包含原則,則可能是元件架構已支援該原則,或該架構屬於原始願景的一部分 (即使未在今天的系統中完全發揮功效)。本文件旨在讓使用者瞭解何謂準則,而非該原則。這些原則的現狀或針對架構最初並非設計新原則的建議,則不在本文件的討論範圍內。遷移至 Components v2 後,我們預期將調整原則調整為最符合元件架構最初構想所學的原則。從本文件開始記錄歷史脈絡,做為改善相關程序的起點。
背景
我們定義了「原則」做為一般系統屬性的基本陳述,通常能維持真實的系統屬性。原則是根據系統的設計目標衍生而來。雖然一般而言是真的,但在特定情況下,部分原則可能無法完全滿足,例如:
- 技術債不符合現代標準。
- 需要屬於一般規則的特殊用途。
- 開發人員掛鉤可提供比實際工作環境適用範圍更強大或特殊權限的存取權。
以下幾個策略可有效提高系統維持原則的執行程度,這些原則並非彼此互斥:
- 讓工具或執行階段強制執行不變性,以致於無法違反原則。
- 設計 API,以按照原則自然鼓勵使用者與系統互動。
- 建立遵循原則的較高層級架構。
- 在變更系統時練習謹慎,並根據原則評估變更。
- 透過說明文件和範例宣傳最佳做法
本文件的部分原則是專為「元件架構」所設計。其他則是元件架構承諾的 Fuchsia 一般原則。
原則
最低權限
元件應獲得在系統中執行其角色所需的最低功能,且不要依據最低權限原則的要求。
範例:sysmgr
提供元件 v1 中的反模式範例。第 1 版 API 支援將以專屬功能組合佈建的封閉式子領域執行個體化。不過,sysmgr
定義的領域幾乎涵蓋所有系統能力,讓 v1 元件可輕鬆違反最低權限。
目前導入的項目
元件架構提供能力轉送做為存取權控管的主要形式。此方法要求所有功能 * 都必須在路徑中明確宣告,藉此授予子項能力。運用能力轉送,父項元件會為子項定義沙箱。
未實現的願景
最初有個構想要搭配角色型存取權控管來輔助能力轉送。不過,這個想法從未進行過早期的腦力激盪。
元件管理員有一個意圖支援彈性隔離政策,這是另一種控管權限的機制。詳情請參閱下方的隔離一節。
無環境授權
當程式可以對物件執行作業而不明確取得物件存取權 (例如透過名稱或編號來參照物件) 時,系統會呈現「環境授權」。您可能很難確保程式有存取物件的正當理由,因為這可以自行產生名稱。
相反地,透過功能型安全性,程式只能在能存取物件的情況下,對物件執行作業。功能可以轉移,但無法偽造,讓在沒有環境授權的情況下安全地委派存取權。
Fuchsia 和同樣的元件架構,應在不使用環境授權的情況下運作。
目前導入的項目
由於功能只由父項提供 *,因此沒有全域命名空間用於取得功能,或在物件上執行作業。範例:元件的 POSIX 檔案系統看起來會由元件的沙箱宣告衍生。
元件架構 (如果有些特殊權限 API 除外),[*][#peer-exception] 不會向元件顯示對等端的身分。這可防止元件濫用對等身分來建立環境授權。
架構功能是一種有限的環境授權形式,因為任何元件皆可存取。不過,由於這些功能的範圍僅限於元件本身的運作範圍,因此這個環境授權是安全的*。
未實現的願景
允許父項佈建預設繼承功能的元件架構「環境」,會在建立某種環境授權的安全性和人體工學之間取得折疊。雖然元件可覆寫傳遞至子項的環境,但在多數情況下,這些元件與一般能力轉送不同,卻無法深入瞭解構成環境的功能。具體而言,環境會用於佈建執行器和解析器。這個點代表架構中可能出現的落差,是為了以安全和人體工方式轉送功能。
普及性
元件是 Fuchsia 軟體的基礎構成要素。Universality 是適用於所有使用者空間軟體的原則,應以元件的形式執行。
這個原則既強大又弱。最弱的形式是所有軟體都應在元件中執行。強而有力的,屬於大型子系統中的程式應該是元件,而非程序。此外,個別計畫可能會決定將子模組拆分為多個元件。
目前導入的項目
截至 2022 年 4 月為止,大型系統區塊是以 v2 元件的形式執行。
截至 2022 年 4 月為止,大部分的使用者體驗元件 (在 Modular 下執行) 都仍為 v1,但有可將其遷移至 v2 的有效專案。
驅動程式和檔案系統是程序,但是現在有計畫如何將其轉換為元件。
未實現的願景
不清楚如何全面應用強烈的原則。 例如:
- Chromium 中的程序只是程序,而非元件。我們不確定是否應採用元件。
- 殼層程式是現今的處理程序,我們不知道這些程式是否會成為元件。
對於以元件形式與程序的形式呈現程式,我們從未制訂正式的指引。
獨立
同一 (或不同) 元件可能會同時在 Fuchsia 裝置上同時運作。元件執行個體與下列維度是各自獨立的:
- 身分:每個執行個體都能與其他執行個體區別。
- 沙箱:每個執行個體都有專為該執行個體量身打造的命名空間。
- 儲存空間:每個執行個體都有自己的私人儲存空間位置,並假設其需要儲存空間 (例如授予、信箱、資料、快取和其他狀態)。
- 生命週期:每個執行個體都可以獨立啟動或停止。
- 子項:每個執行個體都有自己的子項清單,且負責設定其子項運作的環境。
目前導入的項目
您可以建立元件的多個執行個體。元件執行個體會沿用自己的狀態、子項和生命週期。
現今的系統有幾個與「元件身分」對應的概念,這些概念在不同情況下使用:
- 元件的絕對模組。用於能力許可清單。
- 元件的相對按鈕。傳入元件事件的酬載,由
archivist
和test_manager
用於識別用戶端。 - 執行個體 ID。用於永久儲存空間。這可讓元件的拓撲位置變更,而不會遺失儲存空間。
- 元件的網址。解析元件時會使用,有時則可做為元件執行個體身分的 Proxy (例如透過 Cobalt) 區分。
未實現的願景
系統不會實作授予 (持續運作的功能) 和信箱 (基本上是不需執行寄件者和接收方執行的元件之間的訊息匯流排)。
「元件身分」的問題尚未完全解決。如上一節所述,元件架構有不同的身分特質,彼此之間不會一致。舉例來說,在哪些情況下,更新/移動/重新建立的元件會視為「相同」?
隔離
元件可能包含機密資訊和權限,而元件架構負責保護其機密性、完整性和可用性。為此,元件架構使用各種機制來隔離元件,並避免元件彼此幹擾。請特別注意以下幾點:
- 元件架構應防止元件讀取或修改彼此的內部狀態。
- 元件架構不得向元件顯示同類應用程式的真實身分。應用程式應提供本機身分 (例如子名稱)、經過模糊處理的身分,或完全不提供身分識別資訊。
目前導入的項目
由於元件會透過功能互動,因此不知道會位於另一端。
與執行器合作的元件架構支援各種機制,用於隔離元件之間的狀態,而元件架構可以定義本身或從 Zircon 使用:
- 程序隔離:部分執行器會在不同的程序中執行元件,防止元件存取彼此的記憶體和控點。
- ELF 執行元件會實作程序隔離:每個元件都會收到自己的程序和工作。
- 但是,並非所有執行器都提供相同的隔離保證。Dart 執行元件有多個元件執行個體共用相同程序,可提供低強度記憶體隔離保證。
- 儲存空間隔離:元件無法直接存取彼此的隔離永久儲存空間,通常也不會授予共用可變動儲存空間的存取權。
- 記憶體隔離:元件無法直接存取彼此的私人記憶體 (但可能會決定交換共用 VMO)。
元件架構不會揭露元件對等端的身分*。
未實現的願景
原先的想法是,元件架構會定義一種容器類型 (稱為「元件」),做為執行階段隔離邊界。系統會將此視為基本元件關係之一。設定劃分界線可讓產品負責人在安全性與效能之間做出取捨。
我們已針對特定用途 (devhost、fshost) 透過自訂解決方案,在處理程序中分配元件的主要效能優勢,但通常沒有在元件架構層級使用。一個階段,我們相信 Flutter 會是重要的用途,因為 Flutter 程式可受惠於協同作業功能 (因此每個 Flutter 程式都不必帶入自己的執行階段)。然而,由於 Flutter 和 Dart 中缺少穩定的 ABI,因此很難達成此目標,而且並沒有特別提出的用途。
我們一直致力為元件提供經過模糊處理的權杖,讓元件可用於在本機識別對等互連。這稱為「模糊化的菱形」:元件管理員可在元件之間取用相對同一個範本,對其進行雜湊 (或許含有 Nonce),並以雜湊值呈現用戶端。由於這個值是衍生自相對路徑名稱,因此本質上適用於特定執行個體。
可靠度
系統資源沒有限制。運算裝置的記憶體、磁碟或 CPU 作業時間會不多,元件架構應追蹤元件使用資源的方式,確保元件可以有效率地使用資源,並且能夠在不再需要使用資源,或當系統超量訂閱其他用途時,需要將資源收回時。
使用資源時必須要有理由。一般來說,系統中的每個資源都必須以某種方式考量,以便系統確保資源有效使用。
每個元件存在的原因都不同。父項元件執行個體會刪除不再使用的子項,藉此判斷子項是否存在。父項也可以協助設定子項的資源限制。
每個元件運作都有原因。元件架構會在有工作時啟動元件執行個體 (例如回應其他元件傳入的服務要求),並在需求消失時停止這些執行個體 (或比迎合相同資源的其他需求更低)。
目前導入的項目
元件架構目前支援的可靠度是基本的。
元件架構要求每個元件都必須屬於父項元件。
元件管理員會根據要求啟動元件執行個體 (單一執行元件除外)。元件管理員一律不會主動停止元件,除非元件遭到刪除或系統關閉時。
元件管理員會收回已刪除動態元件的資源,並在元件刪除後在背景中清除其儲存空間。
元件架構支援 eager
選項,可讓系統自動啟動元件執行個體。對於這項功能如何融入當責的願景,我們有許多不確定性。沒有與 Eager 元件啟動相關聯的明確的「原因」,且元件管理員也從未重新啟動 Eager 元件。另一方面,從使用者體驗的角度來看,這是執行「Daemon」類型元件的簡單方法,我們還沒有找到更好的解決方案。
未實現的願景
這個願景原本就有很大的願景。
每個執行中的程序都必須屬於至少一個元件執行個體,其功能包括目前使用中、最近使用過或即將使用的功能;系統會將所有離群值視為無原因執行,並立即停止。
目前「隔離儲存空間」中的「資源必須用於原因」為 true,但這才是關於這一點。有一個資源管理系統的願景,其中使用的各項資源都會歸因至特定元件執行個體。這項歸因可用於公開診斷指標、強制執行資源限制,以及平衡負載。我們可能會追蹤的資源包括儲存空間、記憶體、CPU、GPU、電力或頻寬。日後可能會實作這項功能或其中一部分。
如今「每個元件執行都有某種原因」但如今只有部分達成。大多數的元件都是為了回應存取其中一個公開功能的要求而啟動。但是,元件管理員不會輕易地主動終止未使用或耗用過多資源的元件。特別是,評估元件「未使用」時會出現相當困難的問題,因為元件管理員只會處理服務探索的初步階段,一旦用戶端與供應商之間的連線建立後,就無法。
我們最初計劃建立一個「延遲通訊」架構。這麼做可讓元件分派訊息或工作項目,而這些項目稍後會傳送至接收元件,進而放寬元件需要執行的時間限制,並讓元件執行階段有更多時間啟動及停止這些元件。我們特別提出了下列系統提議:
- 工作排程器:安排工作,等到符合特定條件時才進行處理。
- 信箱:允許元件將訊息張貼到「信箱」,這個信箱會保留下來,直到接收元件準備好處理為止。
延續性
這個元件架構應提供機制來維持連貫性:使用者通常不需要擔心重新啟動軟體,因為軟體可在重新啟動或更換裝置時,從上次中斷的地方自動繼續執行。
錯覺的擬真度取決於每次重新啟動時保留下列屬性的程度:
- 狀態:保留元件執行個體中使用者可見的狀態。
- 功能:保留對元件執行個體授予的權限。
- 結構:保留協作元件執行個體之間的關係,以便視需要重新建立通訊。
- 行為:保留元件執行個體的執行階段行為。
實務上,幻覺是不完美的。系統無法保證在網路服務出現軟體升級、非確定性、錯誤、錯誤和外部依附元件時能保持善意複製。
雖然讓元件永久保持運作可能比較簡單,但最終會耗盡資源,因此必須立即停止較不重要的元件,以平衡工作集大小 (請參閱「可靠度」)。
目前導入的項目
一般來說,即使元件停止執行,元件仍會持續存在。比較這與程序的運作方式。
如果元件重新啟動,轉送、從元件的轉送功能,或透過元件轉送的功能都會保持一致。不過,重新啟動後不會保留與這些功能的連線。視能力而定,新執行個體的運作方式可能會與舊執行個體不同,也可能無法取得多個執行個體。
元件架構支援靜態元件執行個體的永久儲存空間。即使元件的拓撲位置變更,系統還是可以保留元件的儲存空間。
未實現的願景
系統中有許多元件無法容忍重新啟動。您只要搜尋使用 reboot_on_terminate
功能的元件,即可找到其中多項功能。
針對建構元件,您可以如何建構能在重新啟動時復原其狀態的元件,或是某個元件無法使用時的處理方式。
關於如何設定元件的重新啟動政策,會提出開放式問題。此外,當伺服器重新啟動時,在元件之間重新建立連線的時機和方式也相當重要。
元件無法保存功能 (也稱為「授權」)。如果重新啟動,則必須重新取得。元件也無法再保存收到的訊息,或將傳送的訊息延遲送達之後。不過,有個名為「信箱」的訊息佇列架構的概念,也可提供相關支援。
如果元件訂閱事件後在佇列中,當部分未處理的事件在佇列中消失,則該元件會遺失這些事件。
元件不支援暫停/休眠。
偏好宣告式 API,而非命令式 API
這個原則又稱為「優先使用靜態而非動態值」。
元件架構對於靜態、宣告和組合時間的 API 仍是動態、命令式和執行階段型 API 的一般偏好。
這並不是說「所有」元件架構 API 都是宣告式 API,完全靜態系統不太可能派上用場!然而一般規則是,如果可以靜態方式描述元件的定義或行為,就應該採取靜態做法。
宣告式具備下列優點:
- 無障礙功能:開發人員和安全性專家可以存取系統的結構和安全性政策。原則上,使用者也能以各種方式向使用者描述這些元素,例如「模組 X 想要存取麥克風...」
- 對齊:安全界限清楚標示,並與公認的架構抽象層對齊。我們在這裡將其置於元件執行個體邊界
- 可稽核性:將宣告內容交由人工審查人員輕鬆審核。集中管理最機密的宣告 (例如角色式存取權控管政策) 也能帶來許多助益。
- 可測試性:可以輕鬆評估修改宣告後的預測結果和實際結果。
- 不可變動:權威宣告可以內建至系統的信任鏈並通過驗證。
目前導入的項目
宣告式 API 的願景是透過 CML 實現。CML 會以靜態方式說明元件的輸入和輸出內容 (能力路徑)、組合 (子項) 和執行資訊。
結合運用後,Fuchsia 建構中的元件資訊清單就會形成「元件執行個體樹狀結構」,可以透過主機端工具 (scrutiny
) 探索,甚至是只透過檢查來源檔案進行探索。另外還有 verify routes
外掛程式scrutiny
在 CQ 上自動執行,可確認靜態拓撲中的所有路徑均完整驗證。*
安全性政策許可清單是宣告式 API 的一部分。
元件架構 API 的某些部分是必要元件,但前提是這些部分必須有合理理由。範例包括:集合、動態優惠、RealmBuilder,以及來自集合的服務匯總。
未實現的願景
元件架構 API 的動態部分並未完整開發。過去,許多問題已委派給工作階段架構,但工作階段架構已淘汰。整體而言,目前的產品對動態元件設定的需求並未大幅提高。但是,當 Fuchsia 採用第三方或工作站 (例如工作站) 執行產品時,這可能會改變。
元件架構 API 多半為靜態或主要動態;兩者之間並不明顯 (服務匯總是例外)。在某些情況下,建議您讓 API 主要靜態,但會委派一部分至執行階段,或者主要動態但受到靜態描述的「上限」限制。
沙箱
元件執行個體無法得知sandbox服務的實際來源。他們發現了沙箱所定義的主觀實境除非提供某種外部認證方式,否則元件執行個體必須無法辨別其在「測試」沙箱或「實際」沙箱中執行,即使其可能涵蓋側邊通道。
家長對子女擁有更充分的權力:
- 雖然父項元件執行個體知道每個子項的網址,但反之亦然。
- 當元件要求使用功能時,就無法控制這些功能的來源。元件必須信任其父項,使其具有來自可信來源的功能。沙箱支援名為「遞迴對稱」的屬性。這種做法的概念是將元件拓撲的子樹狀結構視為完整元件拓撲,只要利用子樹狀結構的根做為完整拓撲的根源即可。具體來說,您應該在元件拓撲的子目錄中執行個別的系統副本,而不會進行破壞。
此原則的統整是,元件管理員應不具有全域單例模式。
目前導入的項目
沙箱的大部分願景實施。定義子樹狀結構時,其行為與完整拓撲相似:
- 由於元件無法存取父項的相關資訊,因此「無法判斷」其在樹狀結構的哪個部分。舉例來說,元件無法判斷元件是在測試還是正式環境中執行 (除非該元件與其提供的功能互動而推斷這項事實)。
- 系統會限定所有包含
framework
來源的功能。 - 元件架構提供數種「內建功能」,但只要將其替換為其他來源的能力,就能顯現這些功能。包括執行器和解析器。
- 當您訂閱範圍限定為子樹狀結構根的事件時,事件的星期一是相對於根。
- 您可以執行巢狀結構人的巢狀結構執行個體。傳送給此封存人的選取器是與封存人所訂閱事件的相對關係。
未實現的願景
元件架構 API 的某些部分使用迴圈:
系統關閉 API,雖然可預期的範圍限定為子樹狀結構,但一律會關閉整個樹狀結構。
有個概念可以執行 ffx component relative
至子樹狀結構,但這尚未實作。
不曾實作的一個相關概念,是應該能夠在樹狀結構中執行元件管理員的巢狀結構執行個體,並且應該可以「組合」具有父項樹狀結構的巢狀元件管理員底下的子樹狀結構。
在最強大的形式中,遞迴對稱能夠支援「移除」拓撲的子樹狀結構,以便在不同的裝置上執行,且所有持續性狀態皆完整。
封裝
封裝 (如 OOP 相同) 是指隱藏元件的內部結構或來自所含元件的資料。請特別注意,這表示元件執行個體只應直接瞭解其子項元件 (本身執行個體化的元件),而不是有關子項的子系,而非自己的祖系。
目前導入的項目
元件既可靠又有信仰,能夠封裝。父項可以存取子項的身分和公開權限,但無法存取子項,但禁止某些具有特殊權限的 API。*
如「沙箱」一節中所述,對於惡意父項的攻擊,目前沒有保護措施可以提供孩子的遭入侵能力。這是根據設計完成的;在能力系統裡,家長主導子項是正常現象。
未實現的願景
子項內部狀態通常會與父項隔離,就像其他兩個元件執行個體一樣。但家長可透過巧妙的方式規避這項機制。舉例來說,父項可以插入大致類似 ELF 執行元件的虛擬 ELF 執行元件,但會在元件程序中插入執行緒,藉此竊取元件的私人記憶體。
鬆耦合
鬆耦合設計可讓元件隨著時間推移更輕鬆。這個元件架構捨棄了常見處理序間通訊 (IPC) 通訊協定和資料格式的大多數元件實作詳細資料 (例如實作元件的程式設計語言)。
當元件使用某個能力時,應明確宣告需要該能力滿足的限制。只要能力提供者遵守這些限制,就應該能將其中一種實作替換為另一個實作項目。這個屬性稱為可替代性。這類限制的例子包括:
當元件依據命名空間要求功能時,決定要使用的實作項目會存放在元件的祖系中,因為它們會設定元件的環境。相較於明確要求繫結至這些功能的特定實作,這種「依意義呼叫」方法能讓系統更具動態性及設定功能 (但有時可能會允許這些元件)。
目前導入的項目
功能是元件的輸入和輸出。大致上來說,各元件之間的互動可以依據不同路徑之間的功能描述,這種合理元件則取決於彼此的介面,而非它們的實作。
但是,當元件執行個體化子項時,會指定網址以選擇子元件。在這種情況下,元件可能會預期子項的特定實作方式。這是一種更緊耦合的形式,不過由於網址會與解析器相對解析,因此有一定程度的自由,因此最終決定將網址解析到哪個元件。
元件架構會隱藏對等端的身分,以支援取代性。
未實現的願景
元件只會依據名稱依附功能,不含任何版本資訊。這可能會導致元件與版本緊密耦合。平台 ABI 版本可以解決這個問題。
我們還不清楚元件網址依附於此原則的程度。
可更新性
元件可單獨更新,無須其他元件。
系統可及時擷取、快取及移除元件二進位檔和資產,但這些二進位檔不再需要使用,就能釋出其他元件的儲存空間。
軟體套件經過簽署,以驗證其真實性和完整性,因此可以安全地從任何可用來源 (包括其他 Fuuchsia 裝置) 再次擷取套件。
目前導入的項目
在 eng 建構作業中,當元件重新啟動時,其執行階段資訊 (例如套件、二進位檔和命名空間) 會更新至套件伺服器中的最新版本。(但如果不更新,資訊清單就不會更新)。
元件終止時,系統會捨棄元件的執行階段資產 (二進位檔和套件)。
未實現的願景
系統已核准用於即時更新的 RFC,將可協助您更新 OTA 以外的套件。不過,部分工作仍然會為了整合此更新流程與元件架構。
元件管理員一律不會收回資訊清單的快取副本。在 eng 建構中,這可能會導致元件的執行階段狀態及其子項或能力路徑不一致。
可用性
元件架構的基本要件應可讓開發人員輕鬆學習及應用。
這個元件架構提供相對較少的一般用途基本功能,可有效涵蓋 Fuuchsia 架構層 (從裝置驅動程式到第三方使用者應用程式) 的軟體組合需求。所有元件都使用相同的基本功能,但由於其角色不同,可能會獲得不同的功能。
這個元件架構也會對產品專屬的需求做出假設,例如產品是否提供使用者介面或運作方式。這樣我們就不必為每次推出的新用途 重新創造工作機會。
元件架構有責任讓使用者輕鬆充分運用元件架構。做法如下:
- 設計 API 以自然地引導使用者前往正確的方向。
- 發布易於存取、詳細且最新的文件。
- 提供與實際使用者問題相關的典型範例。
目前導入的項目
我們在 //docs/concepts/components 和 //docs/development/components 底下提供了參考文件,請參閱「元件入門指南」。
我們針對//範例提供了一些基本範例。
未實現的願景
整體來說,許多元件架構 API 的成效不如預期。
針對元件進行疊代和在測試以外的驗證正確性而言,開發人員擁有許多需要改進的經驗。對於以執行階段為基礎的元件探索工具,我們有幾個想法尚未探討。
我們還有更多文件可供撰寫,尤其是關於教學樣式的文件。此外,部分現有說明文件也能受益於一些愛用。我們所提供的範例相當基本,僅限於 C++ 和 rust。我們或許可以從更複雜或真實的範例進行學習。
視覺缺口
元件架構在 Zircon 部分提供抽象化機制,但這些抽象與 Zircon 不同,而且無法擷取 Zircon 提供的所有功能。例如:
- Zircon 針對所有物件類型的建構提供了政策控制項。元件架構只有一部分的水電工程,例如程序物件建立。
- Zircon 具有元件架構不支援的功能類型 (例如事件配對、通訊端)。
- 依附元件架構功能一律是「工廠」,可用來取得 Zircon 物件。無法轉送單例模式 Zircon 物件。
這個元件架構幾乎無法促進與以傳統程式模型編寫的軟體的相容性。這可能是刻意的,但我們日後可能會決定納入其中一些功能。
附錄
架構功能
架構 (透過元件管理員) 可存取某些非父項授予的功能,例如:
fuchsia.component.Realm
,可讓元件控管其子項的生命週期。- 元件範圍事件串流,可讓元件接收與子項相關的生命週期事件。- 透過
/pkg
存取自己的套件,每個元件甚至不需要提出要求
儘管如此,由於架構功能絕對不會提供所含環境功能的存取權,這些功能不會違反最低權限、無環境授權或封裝。
公開同類應用程式資訊的 API
有些特殊權限 API (例如限定範圍的事件串流) 會公開元件的內部資訊,例如元件、網址或傳出目錄。不過,這些 API 會鎖定,而且只能透過非實際工作環境或特殊權限元件 (例如 archivist
或 debug_data
) 使用。
拓撲的靜態驗證限制
靜態驗證的拓撲數量設有限制。探索達到集合後,通常就會停止,因為集合的內容是由執行階段決定。