| RFC-0279:支援產品專屬的 Blob 格式 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 本 RFC 建議針對不同產品使用不同 Blob 類型 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2026-02-02 |
| 審查日期 (年-月-日) | 2026-03-10 |
問題陳述
不同類型的 Fuchsia 產品可能會以不同的格式將 Blob 儲存在 Blobfs / fxblob 中,以配合特定工作負載或需求。舉例來說,您可能需要盡可能提高壓縮比、加快解壓縮速度,或是減少處理 RAM 的用量。目前 Fuchsia 產生各種 Blob 格式設定的建構版本功能非常有限。
摘要
這項 RFC 建議導入任意 Blob 類型,並在本機儲存空間、建構、組裝、軟體推送和伺服器端基礎架構中支援這些類型。這項提案是以 RFC-276 (「支援系統更新,並變更 Blob 格式」) 中核准的想法和提案為基礎。不過,這項 RFC 並未著重於從類型 1 遷移至類型 2,而是透過以下方式,概略說明如何支援任意 Blob 類型:
- 利用內建於本機儲存空間和軟體的軟體支援,簡化從類型 1 到類型 2 的遷移作業,以支援任意類型。
- 在組裝產品套裝組合時,利用軟體組裝支援功能產生所需類型的 Blob。
- 擴充更新用戶端/伺服器通訊,讓用戶端可以要求特定 Blob 類型。
- 擴充工具,在所有支援的 Blob 類型之間轉換。
請務必熟悉 RFC-276:系統更新支援,因為這項 RFC 是以該 RFC 的概念和說明為基礎。
利害關係人
協助人員:davemoore@google.com
審查者:
- csuter@google.com (儲存空間)
- jfsulliv@google.com (儲存空間)
- etryzelaar@google.com (SWD)
- amituttam@google.com (PM)
- awolter@google.com (軟體組裝)
- markdittmer@google.com (安全性)
- gtsai@google.com (基礎架構)
公共平台:
軟體推送、本機儲存空間和基礎架構團隊內部進行了一系列設計討論,其中也包括這項 RFC。本 RFC 中文字的早期版本已由 Build 和 Assembly 團隊的利害關係人審查。
需求條件
- 如同 RFC-276,對於每個正式版用戶端裝置,一律可軟性轉換為新的 Blob 格式。也就是說,正式版中的任何用戶端裝置都應能遷移至新的 Blob 格式,且使用者不會受到任何影響。
- 再次提醒,未傳送的 blob 格式和特定 blob 的 Merkle 根計算方式維持不變。應避免導入產品專屬 Blob 的墊腳石。
- 產品設定應能指定是否要將所有 Blob 更新為指定格式,以防這些 Blob 已以不同格式儲存在磁碟上。如要更新現有 Blob,機制應能完成 Blob 更新,改用預期格式,且不會對使用者造成影響 (無論是預期或非預期的中斷),例如:
- 預期用途:由軟體 / 設定控制,例如管理裝置熱力、讀取/寫入效能需求、測試和基準化。
- 非預期:電力中斷、裝置重新啟動、遷移作業未完成 (例如連線問題、系統當機導致重新啟動等)。
設計
下列各節說明為滿足上述需求而進行的技術變更。產品專屬 Blob 可直接沿用 RFC-276 的大部分設計和實作選項。事實上,在草擬 RFC-276 時,團隊預期未來可能需要更多 Blob 類型,因此盡可能避免選擇會導致類型 1 到類型 2 遷移作業特殊的選項。因此,本 RFC 的重點在於 RFC-276 設計的差異和頂端部分。
Blob 類型命名、舊版 Blob 類型、排序方式和後果
本節將說明 Blob 類型的重要詳細資料。與 RFC-207 和 RFC-276 相比,意義或語意並無變更,但由於先前只定義了傳送 BLOB 類型 1 和 2,因此很容易誤解語意。請務必注意,這些類型應視為 enum,且特別不應視為版本分母。後果如下:
- 第 2 類與第 1 類不同。它滿足了不同的用途,僅此而已。
- 不會取代第 1 類。
- 不是第 1 類型的後繼者。
- 沒有訂購。類型只是名稱,沒有其他用途。
- 沒有「最多 N 類型」的概念:假設定義了 Blob 類型 1、2、3 和 4,聲明「產品 X 支援 Blob 類型 1 和 4」並不表示也支援 2 和 3。
回顧來看,RFC-276 中應為型別 2 命名,以免誤解為整數。
舊版 Blob 類型
如上一節所述,這兩種型別可能會遭到誤解,因此我們將類型 1 和類型 2 稱為「舊版 Blob 類型」。
對於即將推出的類型,我們將停用使用類似整數或單一字母的名稱,因為這類名稱可能會被解讀為暗示排序、繼承或改善。而是使用描述性命名。也就是說,新的 Blob 類型應透過列舉中的名稱傳達其意義,並在轉換為字串時傳達意義,例如:
pub enum DeliveryBlobType {
...
/// Type 1 supports the zstd-chunked compression format. [legacy type]
Type1 = 1,
...
/// Uncompressed is a raw, uncompressed format [descriptive naming]
Uncompressed = 17,
/// Zstd compression, default settings [descriptive naming]
ZstdDefault = 18,
...
}
請注意,上述範例中分配的整數僅供說明之用。這些範例並未反映目前現有的程式碼,或以exact相同的方式實作。
將描述性型別轉換為字串時,這項 RFC 建議將上述範例中的 ZstdDefault 轉換為 vnd.fuchsia-blob.raw+zstd。這是因為這是有效的 MIME 類型字串,可與潛在的未來擴充功能完美搭配,允許用戶端/伺服器內容交涉,詳情請參閱下文。
改用描述性 Blob 類型
如上一節所述,即將推出的所有 Blob 類型都會有描述性名稱。這是在新產品中導入 Fuchsia 時進行徹底切割的絕佳機會,可完全避免在這些產品中使用舊版 Blob 類型。因此,這份 RFC 建議採用下列各種 Blob 類型的使用路線圖:
- 導入
Uncompressed和ZstdLevel_X_Chunksize_Y的描述性 Blob 類型,可確保有一個未壓縮的原始 Blob 類型,以及模仿現有類型 1 和類型 2 的類型。- 舊版 blob (以 C++ 編寫) 目前預計不會支援說明性 blob 類型,只會支援舊版類型。
- 新版 fxblob 應可支援所有 blob 類型,並瞭解舊版類型與對應描述性類型之間的相似和差異之處。
- 每項產品都必須支援未壓縮的 Blob 類型。
- 舊版 blobfs 產品必須支援類型 1。
- 以 Fxblob 為基礎的產品必須支援類型 1 和
Uncompressed。
- 如果用戶端向伺服器要求舊版 Blob 類型 (即使用「https://blob.domain.tld/blobs/LegacyTypeName/87fa73ed...」這類網址),無論是否設定未壓縮標記,伺服器一律會傳回
LegacyTypeNameBlob 類型。 - 如果用戶端向伺服器要求說明性 Blob 類型,也就是使用「https://blob.domain.tld/blobs/DescriptiveTypeName/87fa73ed...」這類網址,伺服器會傳回
DescriptiveTypeName或Uncompressed的 Blob 類型,但絕不會傳回舊版類型 (例如含有未壓縮旗標的 type1)。- 日後如果新增用戶端/伺服器內容交涉 (請參閱下文),伺服器可能會傳回要求中指出的任何支援類型。
- 如要從產品中移除第 1 類或第 2 類,必須先移除中間步驟。
視需要導入新的傳送 Blob 類型 <T>
RFC-207 (「離線 blob 壓縮」) 討論了傳送 blob 的導入作業。這些 Blob 的設計目的是為了有效率地將資料從 Blob 伺服器傳輸到裝置上的 fxblob/blobfs。傳送 Blob 包含原始資料和共用中繼資料 (用於軟體推送和本機儲存)。例如,這項中繼資料可以指定酬載壓縮類型。
與第 1 類型到第 2 類型的遷移不同,後者主要解決改善壓縮比的需求,但這項 RFC 並未指定即將推出的類型 (在本 RFC 中通常稱為 <T>) 屬性。這些即將推出的類型不會要求變更本機儲存空間、SWD 或伺服器端基礎架構的設計或概念實作。因此,對於符合本 RFC 所述架構的新傳送 Blob 類型,不會再有其他 RFC。
以下列舉幾種目前預期的潛在類型:
- 壓縮率高於類型 1 或類型 2。
- 比類型 1 或類型 2 更快解壓縮。
- 與類型 1 或類型 2 不同的壓縮演算法。
- 差異編碼:使用修補程式格式,在 OTA 更新期間將現有 Blob 更新為較新的 Blob。
雖然從技術上來說,這個設計可實現上述所有功能,但請注意,這並非公告,表示我們會在可預見的未來實作所有這些功能。
導入新 Blob 型別的後果是 RFC-276 中描述的概括:
- Fuchsia 平台程式碼 (本機儲存空間、套件管理、ffx) 將能處理先前存在的 Blob 類型,以及新導入的 Blob 類型。
- 如果 blob 類型不只是在日後的建構作業中停用,而是要完全移除,包括可處理該類型的平台程式碼 (例如從程式碼集移除壓縮演算法),則必須按照 RFC-276 所述,執行適當的過渡程序。
- 對於涉及 TUF 存放區的本機開發工作流程,無法保證
fx ota一定會成功,因為目前沒有 TUF 型機制,可透過踏腳石版本強制執行多級式更新。在這種情況下,開發人員應ffx target flash裝置做為解決方法。
當特定產品的組裝設定已變更為預設建立 Blob 型別 <T> 時:
- 根據預設,產品組合只會包含 <T> 類型的傳送 Blob。
- 系統更新程式會開始要求 <T> 型別的 Blob。
- 伺服器端套件放送基礎架構會確保類型 <T> 和特定專案先前的預設 Blob 類型可供用戶端裝置使用。伺服器端基礎架構可使用
ffx工具,視需要即時產生所需的 Blob 類型。RFC 並未規定是否要永久儲存、僅快取或不儲存從相同「原始 Blob」產生的所有不同檔案,應視特定後端、伺服器和產品情況而定。
從用戶端的角度來看,Blob 存放區的伺服器端表示法如下方樹狀結構所示,可透過「https://some_blob_repo.domain/blobs/<T>/<hash>」等網址存取:
blobs
+> 1/
+> a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
+> ...
+> 2/
+> a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
+> ...
+> some_other_type/
+> a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
+> ...
+> yet_another_type/
+> a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
+> ...
Blob 重寫情境
本 RFC 解決的潛在遷移情境如下:
- 在 OTA 中將 blob 型別 <T> 完整遷移至型別 <U>:在這種情況下,blob 儲存空間會決定目前 blob 的型別。隨後,它會根據 RFC-276 中說明的機制,向套件管理堆疊指出 OTA 期間是否需要重新下載特定 Blob。
- 更一般的情況是,Blob 儲存空間目前包含多種不同 Blob 格式的 Blob,也就是從 <Ta、Tb、Tc、Td...> 類型遷移至 <U> 類型。不過,這類情況也適用相同的概念和實作方式:Blob 儲存空間會判斷 Blob 並非採用所需的 <U> 格式,並向套件管理堆疊指出需要替換 Blob。
- 逐步遷移:請注意,一般情況下,您不一定需要或甚至不希望遷移所有 Blob,如先前項目符號所述。舉例來說,如果新推出的 Blob 類型提供更優異的壓縮功能,且已知特定產品的儲存空間不足,就可能需要透過 OTA 進行完整遷移。不過,由於產品的 Blob 儲存空間會支援產品先前使用的所有 Blob 類型,且這些類型尚未完全取代,因此 Blobfs/fxblob 中儲存的 Blob 不一定需要是相同類型。因此在大多數情況下,只有新下載的 Blob 才會採用所需格式。隨著時間推移,先前儲存格式中的 Blob 數量會持續減少,因為在被具有不同雜湊值的新 Blob 取代後,這些 Blob 會遭到垃圾收集。
第一點說明的情境是,在 OTA 期間,系統會以新的傳送類型重新下載 Blob 儲存空間中所有 Blob,並取代現有 Blob。後者 (「逐步遷移」) 不會覆寫現有 Blob。這是重要的區別,可解決特定挑戰:隨著遷移作業逐步進行,很難在任何時間點推斷裝置 Blob 儲存空間的確切可用空間量。如果裝置有充足的儲存空間,通常不會發生這種情況,但如果裝置的儲存空間有限,就可能會發生。因此,您可以按照 RFC-276 中列出的步驟和程序,逐步或一次性遷移至任何即將推出的 <T> 類型。
遷移作業要逐步進行還是需要完全重寫,取決於組件的設定,就像為產品設定所需的 Blob 類型一樣。因此,Blob 儲存空間可以與套件管理堆疊通訊,指出哪些 Blob 需要以新編碼重新下載,並採用 RFC-276 中定義的相同機制:
fn do_ota() {
...
for hash in list_of_expected_hashes {
let blob = match get_blob_by_hash_from_blob_storage(hash) {
(Some(blob), info) if info.desired_type => blob,
_ => {
let blob = fetch_blob_from_server(hash);
write_blob_to_blob_storage(&blob);
blob
}
};
}
...
}
如要逐步遷移,info.desired_type 值一律為 true。
這樣一來,系統就不會重新下載 Blob 儲存空間中任何編碼的現有 Blob。
降低漸進式 Blob 遷移作業的風險
上節介紹了逐步遷移的概念,但這並未納入 RFC-276 的範圍。逐步遷移時會遇到概念上的困難,需要另外處理。為說明這項挑戰,以下情境會考量下列情況:
- 多個 Blob 類型遷移作業會在較長的時間內進行 (類型 A -> 類型 B -> 類型 C),此外:
- blob 儲存空間中的每個 blob 從未儲存為 B 類型。
- 自動大小檢查機制會根據目前系統映像檔和預期更新的壓縮建構構件大小進行估算,判斷 OTA 是否適合裝置。就概念而言,為了計算,系統會將可用空間視為兩個大小相等的範圍,這兩個範圍必須夠大,才能容納「舊」的一組 Blob (執行 OTA 前) 和「新」的一組 Blob (系統在啟動更新版本後需要的 Blob)。
下圖說明瞭這段期間的情況。

導致這項困難的程序如下:
- 第 1 階段:開始第一次遷移作業前,系統上的每個 Blob 都會以 A 類型儲存。在安裝 OTA 之前,系統會開始逐步遷移至 B 型,並透過大小檢查機制計算裝置上應有的儲存空間 (50%)。執行 OTA 時,裝置會重新啟動並進入新系統,每當下載新 Blob 時,就會使用新的 B 型 Blob。
- 第 2 階段:在多次 OTA 更新過程中,大多數 Blob 的雜湊值會逐漸變更。隨後,系統會逐步以 B 類型 Blob 取代 A 類型 Blob。不過,有一個特別大的 A 型 Blob (圖片中的「ab7fe7331...」),由於內容沒有變更,因此不會在已儲存該 Blob 的裝置上替換。
- 不過,建構伺服器產生的建構版本包含 B 類型的 blob ab7fe7331 (以全新建構版本刷入裝置時,也會包含 B 類型的 blob ab7fe7331)。如果 Blob ab7fe7331 使用 B 類型所需的儲存空間比 A 類型少 (例如因為壓縮效果較好),則大小檢查機制會低估儲存空間需求,因為許多已部署的裝置仍以 A 類型保留 Blob ab7fe7331。
- 第 3 階段:在多次 OTA 期間,除了 blob ab7fe7331 以外,所有 blob 都已更新為 B 類型。
- 第 4 階段:現在要規劃遷移至 C 類型的作業。此外,由於 blob ab7fe7331 已由具有不同雜湊值的小型 blob 取代,因此不再是 OTA 的一部分。因此,現在將整個 OTA 更新至新版本,只需要略低於 50% 的容量。
- 第 5 階段:由於 blob ab7fe7331 仍為 A 類型格式,且在下次啟動前,執行中的系統仍需使用該 blob,因此 OTA 的 blob 下載作業會失敗,因為「blob ab7fe7331 + 所有 B 類型 blob + 所有 C 類型 blob - B 類型格式中 blob ab7fe7331 的保留空間」的總大小大於 100%。
對於儲存空間充足的系統而言,這種情況不太可能成為實際問題,但對於 Fuchsia 產品而言,這就相當重要,因為這些產品的完整 OTA 大小往往接近 Blob 儲存空間容量的 50%。
值得注意的是,上述情況的發生,是因為所述大小檢查機制具有漸進式性質,也就是說,該機制會根據「目前」和「下一個」Blob 集計算儲存空間需求。開發人員可以設計保守機制,記錄傳送至產品機群的每個 Blob 的最大壓縮大小,並假設裝置可能擁有所有雜湊的最大 Blob 組合,計算 Blob 儲存空間中應有的雜湊大小需求。
這項機制的缺點是,必然會導致大量誤判,因為很可能沒有任何裝置真的擁有這組最大可能的 Blob。這會導致開發團隊的儲存空間預算比實際需求更緊縮。
如上所述,儲存空間受限的裝置會遇到問題,因此本 RFC 建議制定政策,確保這些裝置一律執行完整遷移作業。因此可以輕鬆推斷免費儲存空間。
如果因產品特定需求 (例如違反重要推出計畫) 而無法全面遷移,則必須在遷移至 C 型之前,完成儲存空間受限裝置的全面遷移,例如上圖中的第 3 階段。這樣一來,就能確保漸進式大小檢查機制計算出的結果符合裝置上的實際分配情形。產品發布團隊必須據此規劃發布時間表和程序。
實作
這項 RFC 的實作作業預計會與 RFC-276 (從第 1 類遷移至第 2 類 Blob) 同步完成。因為在許多方面,這項 RFC 都是對前者所述概念的概括,因此一併實作這兩項 RFC 效率較高。隨後,即使這項 RFC 並未強制規定過渡期,實作作業仍會嵌入 RFC-276 三階段方法的第一階段,概念上如下所示:
- 在 blob 儲存空間層 (本機儲存空間) 實作 blob 覆寫和可更新狀態的支援功能。
- 在套件管理堆疊中實作對型別 <T> 的支援 傳送 Blob (SWD)。
- 實作支援,將 Blob 類型從 <T> 轉換為 <U> (透過
ffx)。(SWD)。 - 支援建立類型為 <T> 遞送 Blob 的產品組合 (組裝)。
- 這項 RFC 不會變更預設設定。
- 支援提供 <T> 傳送 Blob (基礎架構)。
- 如果用戶端要求,伺服器端基礎架構仍可提供先前的預設 Blob 類型,必要時可使用
ffx進行即時轉換。
- 如果用戶端要求,伺服器端基礎架構仍可提供先前的預設 Blob 類型,必要時可使用
- 支援公開 Blob 重寫政策的狀態旗標 (本機儲存空間)。
完成這項作業並確認伺服器端基礎架構可提供 <T> 型別的 Blob 後,系統會調整指定 <T> 型別消費者的產品設定,導致後續建構作業開始擷取 <T> 型別的 Blob,而非先前的型別。
效能
根據這項 RFC 提案,預計在某些情況下,這項功能會對效能造成影響,但由於尚未定義即將推出的 Blob 類型,因此我們目前無法精確量化影響程度。不過,就品質而言,預期會出現以下情況:
- 每當系統在 OTA 期間執行完整的 Blob 類型遷移作業 (即重新編寫所有 Blob),所需時間會比平常更長,因為系統會重新下載並重新編寫先前格式的所有 Blob。
- 如果導入的新 Blob 類型與現有類型採用不同的編碼,組裝期間的效能可能會有所變化。視具體細節而定,速度可能會變慢或變快,幅度可能不大或很大。目前無法判斷,也不在本 RFC 的討論範圍內。
- 每推出新的傳送 Blob 類型,測試數量就會增加,確保新類型能正常運作。這會比線性擴充略高,也就是說,針對每個現有 Blob 類型定期執行的測試套件,現在也會針對新導入的類型執行。此外,視需要也可以測試從特定類型遷移至新類型,以及回退至其他類型的作業。
- 視需求而定,您可能不需要測試每個產品 / 主機板設定的每個 Blob 類型。這項決定會視情況而定,且本 RFC 刻意不為產生的測試矩陣設定需求。產品和測試團隊應確保產品選取的 BLOB 類型符合測試程序,並可選擇不採用特定產品絕對不適用的測試設定。
人體工學
如先前所述,ffx 工具已取得傳送 Blob 的功能,最初支援類型 1,之後支援類型 2,但截至本文撰寫時,類型 2 的支援尚未完成。
這項 RFC 規定,在本地儲存空間和軟體推送中導入其他 Blob 類型時,一律須在 ffx 中支援新類型。因此,對於任何一對 Blob 型別 <T>、<U>,以下應一律可行。請注意,這些指令僅為概念範例。即將推出的實作項目可能會選擇不同的語法、子指令命名和/或提供額外功能:
# Encoding an uncompressed blob into <T>
$ ffx package blob compress --type <T> --output <output_file> raw_input_file
# Encoding an uncompressed blob into <U>
$ ffx package blob compress --type <U> --output <output_file> raw_input_file
# Recompressing a <T> blob into <U>
$ ffx package blob decompress --output raw_blob v1_compressed_input_file
$ ffx package blob compress --type <U> --output <output_file> raw_blob
與先前的 Blob 類型相同,ffx 可以偵測找到的 Blob 格式,因此解碼時不需要明確傳遞 --blob-format 引數。
與先前的 RFC 不同,這個 RFC 不會變更 ffx package blob compress 或 ffx product 的預設 Blob 類型。如果 ffx 或組件要使用新定義的 Blob 類型,就必須透過指令列引數或組件設定明確啟用。
請注意,撰寫本文時,我們正在考慮對人體工學進行微小潛在變更:目前如上述範例所述,ffx 指令表示 Blob 類型僅與壓縮有關。雖然一開始是這樣,但並非一定如此。舉例來說,產生 delta blob (即兩個 blob 之間的二進位差異,可做為節省資料移轉頻寬的指標) 也是 blob 類型的明顯候選項目。隨後,系統會考慮在未來分別呼叫 ffx 子指令 ffx package blob encode 和 decode。
回溯相容性
如同先前對磁碟上 Blob 格式的變更,導入新類型 <T> 不會中斷 Fuchsia 產品的運作或開發工作流程。因此,設計和實作計畫會盡量確保回溯相容性。
正式版
由於導入本 RFC 所述的 Blob 類型,不一定會連帶將產品從其他 Blob 類型遷移,因此本 RFC 並未規定新 Blob 類型是否需要踏腳石。這項工作會委派給產品專屬情況。
不過,我們確實需要伺服器端基礎架構,確保產品一律可以下載一組可解讀的 Blob。如上文「設計」一節所述,當用戶端要求特定格式時,伺服器後端會利用 ffx 即時轉換 Blob 型別。
這種做法可讓我們幾乎無限期支援遷移作業:導入新的 BLOB 類型時,不需要任何過渡階段,但完全淘汰不再使用的 BLOB 類型時 (也就是停止支援伺服器端),則需要過渡階段。這是因為從非常舊的版本更新時,系統可能不知道要升級至哪種 Blob 類型,因此在系統更新至當時的最新版本時,不會要求新的 Blob 類型。如要解決這個問題,請先強制更新至支援已淘汰 Blob 類型的最後一個版本。但請注意,這不一定適用於所有產品專屬的 Blob 類型。但如果發生這種情況,請按照 RFC-276 的程序處理。
開發
遷移期間,開發主機會從發布類型 <T> 變更為類型 <U> 的傳送 Blob。與 RFC-207 和 RFC-276 類似,開發主機一次只支援一種 Blob 格式。因此,主機端伺服器可能不會保留舊版 Blob 格式,以確保回溯相容性。
與可透過墊腳石強制執行的正式版建構不同,開發工作流程缺少透過特定建構強制更新的機制。因此,fx ota 會依賴裝置端備援,也就是說,fxblob/blobfs 會根據傳入的 Blob 處理必要動作。
安全性考量
這項 RFC 對攻擊面有影響,超出 RFC-207 說明的範圍。這樣一來,您就能變更 Blob 的磁碟格式,不必進行特殊準備,也不必遵循後續的 RFC。因此,有意導入新 Blob 類型的團隊應與安全團隊密切合作,特別是以下幾點:
- 在大多數情況下,我們預期新 Blob 類型會隨新編碼器 (例如 Blob 的壓縮演算法) 一併推出。過去就曾發生這類編碼器遭到濫用的情況。因此,導入新編碼時應經過安全審查,確認是否適合預期用途。這適用於格式本身的審查,以及實作和推出作業。
- 編碼器和解碼器必須持續更新,確保 Fuchsia 包含所有已知安全漏洞的修正程式。
- 應對所有支援的 Blob 格式執行模糊測試,盡早發現潛在的安全性漏洞。
事實上已淘汰的 Blob 類型
導入新的 Blob 類型時,舊的 Blob 類型一律會事實上遭到淘汰,雖然上文已明確指出 Blob 類型通常反映不同的用途,且某些類型不應接續其他類型,但這確實可能實際發生。
舉例來說,新推出的壓縮演算法在特定產品的所有相關指標中,可能都優於現有的演算法。如果發生這種情況,且 Fuchsia 平台持續支援先前的演算法,則必須確保處理其他演算法的程式碼持續更新及監控安全性問題,以防降級攻擊。測試部分包含這類攻擊的測試其他詳細資料。
因此,如果導入的新 Blob 類型可能導致其他 Blob 類型事實上遭到淘汰 (例如技術範圍重疊),產品和發布團隊應考慮導入過渡期。這個過渡期會停用產品上先前使用的 BLOB 類型,也就是說,在 OTA 期間,生產裝置會拒絕將舊的 BLOB 類型寫入 BLOB 儲存空間。
隱私權注意事項
這項 RFC 不包含任何隱私權相關異動。自 RFC-207 起,用戶端和伺服器之間就會傳送傳送 Blob 類型。此外,本 RFC 並未提議對資料移轉進行任何額外修改。
測試
由於這項 RFC 是先前 RFC 的邏輯延伸,因此 RFC-276 中說明的測試概念也適用於這項 RFC。同樣涵蓋自動和手動測試。
自動化測試
為 RFC-207 和 RFC-276 開發的自動測試程式碼將會擴充,涵蓋新導入的 Blob 類型測試。由於後者 RFC 的設計前提是最終會開發及部署其他 Blob 類型,因此測試概念特別設計成符合這項需求的通用概念。這表示從 <T> 類型遷移至 <U> 類型的測試情境已是設計的一部分,擴充自動化測試以納入新的 Blob 類型非常簡單。因此,本 RFC 不會對已設計的測試概念提出額外變更。
Blob 降級攻擊測試
實作這項 RFC 後,系統會導入對抗性測試,驗證防範 Blob 降級攻擊的韌性。具體來說,可能的情況是產品的 Blob 類型事實上已遭淘汰,如本 RFC 先前所述:當產品從某個 Blob 類型移至另一個類型時,背後有策略性原因。為涵蓋這種情況,系統會進行高階測試,確認在要求 <U> 型別 Blob 時收到 <T> 型別 Blob 會導致錯誤,且收到的 <T> 型別 Blob 不會寫入磁碟。
請注意,其中有一個章節是關於未來工作,建議導入政策來接受多種 BLOB 類型、設定偏好設定,以及定義可接受和不可接受的 BLOB 類型政策。如果 / 何時實作這項功能,就必須相應擴充 Blob 降級攻擊測試,確保涵蓋所有相關情況。
手動測試
對於產品,測試團隊進行的手動 OTA 測試和後續的內部測試版本,會驗證自動測試的結果,並確認導入新的 Blob 類型不會導致無法預料的問題。手動測試是針對具體產品需求進行,也就是不會手動驗證每種可能的遷移排列組合。
說明文件
接受這項 RFC 後,我們會審查 BlobFS 和 OTA 更新的說明文件,並視需要更新,以反映導入新 Blob 類型後變更的詳細資料。
缺點、替代方案和未知事項
替代方案
產品專屬 Blob 類型的伺服器端支援替代方案
如果不想讓伺服器端瞭解整個傳送 Blob 的概念,可以考慮將產品專屬 Blob 傳送至裝置。如果 Blob 雜湊不是單純從原始二進位內容計算而來,而是從元組 (content, blobType) 計算而來,不同 Blob 類型 (設定不同和/或適用於特定產品) 的名稱就會不同。在這個實作方式中,伺服器不必區分不同類型,而是能夠從看起來只包含所有 Blob 的一個目錄提供所有內容:
blobs/
+> ...
+> a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
+> 76d4f97c1aaf486fabeabdce2095aa9d736f72e1257acd654dcbbddeb4564c28
+> ...
在這個範例中,列出的兩個檔案會具有相同的酬載,但由於 Blob 類型不同,因此雜湊和檔案名稱也會不同。Blob 伺服器可從相同目錄將這些檔案提供給用戶端。
如果堅持採用原始 Fuchsia 設計,並完全從原始酬載的雜湊值 (即未經壓縮或編碼) 衍生名稱,則會產生類似多個目錄的項目,並以傳送 Blob 類型命名:
blobs
+> 1/
+> a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
+> ...
+> 2/
+> a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
+> ...
+> next_generation_type/
+> a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
+> ...
這兩種設計都完全可行,但如果變更目前內建於 Fuchsia 平台和工具的設計,並不會帶來顯著的明顯優勢,因此額外投入工程資源並不划算。
因此,這項 RFC 會保留目前的設計,並繼續僅從原始內容衍生檔案名稱。從用戶端的角度來看,設計仍會使用簡單的路徑分隔符,避免產生模稜兩可的情況。
之後的作業
接受及拒絕下載 Blob 類型的政策
由於可能存在許多不同類型的 Blob,因此未來可能需要自動改用其他類型,前提是伺服器上沒有要求的 Blob 類型。目前,Blob 下載器會預期 Blob 以指定格式提供,如果無法提供,就會發生錯誤。
不過,如果實作的架構可接受多種型別,且用戶端可依序傳達偏好設定 (如下一節所述),明確定義產品的政策會很有幫助。這些政策可僅允許非常特定的替代類型,藉此拒絕下載及儲存事實上已淘汰的格式,有助於防止降級攻擊。雖然這項 RFC 並未規定確切的技術實作方式,但建議以清楚、簡潔、明確的方式提供這些政策,而不是隱含地分散在多個編譯單元或元件中。
請注意,如要實作這類功能,就必須擴充測試,以防範 Blob 類型降級攻擊,詳情請參閱測試一節。
用戶端與伺服器之間非純量的 Blob 類型交涉
本文所述的設計是根據用戶端透過網址中的純量分隔符號,將所需傳送的 Blob 類型傳達給伺服器,例如:
https://some-package-server.com/blobs/next_generation_type/a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
優點是請求架構非常清楚易懂,且實作方式簡單明瞭。雖然目前沒有已知的具體需求,但未來可能會需要根據多個因素 (而非單一純量值) 選擇要傳送給用戶端的 Blob。舉例來說,假設用戶端傳送要求給更新伺服器,指定偏好的配送類型為「AB 陽性」,同時指出「B 陰性」類型也可以接受。這可透過多種可能實作方式啟用,以下是其中兩種:
- 更複雜的要求網址,可傳達必要資訊。雖然可以這麼做,但相較於下一個項目符號中的解決方案,這相當不尋常。
- 其他 HTTP 標頭,會隨用戶端要求傳輸至伺服器。這項功能的常見實作方式是依據 MIME 類型和 http
Accept標頭,請參閱下節。
請注意,由於目前沒有具體要求,這項 RFC 並未強制實作,而是將其歸類為未來可能的工作。
透過 MIME 類型和 Accept 標頭進行內容交涉
如要滿足這項要求,可行的實作方式是利用供應商專屬的自訂 MIME 類型和 HTTP「Accept」標頭。舉例來說,本節的其餘部分假設我們正在查看三種不同的 Blob 類型:
- 未壓縮的 Blob。
- 使用 lz4 演算法壓縮的 Blob。使用 zstd 演算法壓縮的 Blob,具有可變的壓縮層級和區塊大小。
如果更新伺服器實作適當的內容交涉對應項目,這三種提及的類型可能會使用 MIME 類型,例如:
application/vnd.fuchsia-blob.rawapplication/vnd.fuchsia-blob.raw+lz4application/vnd.fuchsia-blob.raw+zstd; level=<L>; chunk=<C>
在這個實作方式中,Blob 類型不再以「類型 1」等簡單用語說明,隨後,Blob 標頭可能不再只包含表示 Blob 類型的整數。u32而是可能取得額外欄位,可能為可變長度,用於包含描述 Blob 類型的字串。
系統更新用戶端隨後會要求網址,概念上類似於:
https://some-package-server.com/blobs/<doesnt_matter>/a68945271ac8812c85b4d7239c2ac919030ea7bc6d0bd4cec038b0643dc1e728
但會傳送含有 Accept 標頭的 HTTP 要求,例如:
Accept: application/vnd.fuchsia-blob.raw+zstd; level=3, application/vnd.fuchsia-blob.raw+lz4; q=0.8, application/vnd.fuchsia-blob.raw; q=0.5
在這種情況下,更新伺服器基本上可以忽略 blobs/ 和 hash value 之間的網址區隔,並根據 Accept 標頭中傳達的偏好設定,提供相應的雜湊值。
如要處理從 Blob 伺服器到目標裝置的 Blob 傳輸作業,以及將 Blob 傳輸到目標裝置的儲存空間,有多種可行選項,各有優缺點,特別是下列選項:
- 放送 blob 格式維持不變。套件管理堆疊會維護表格,將傳送 Blob 類型對應至 MIME 類型字串。儲存空間程式碼會維護傳送 Blob 類型在 Blob 檔案系統實際程式碼方面的意義。這項配置的主要優點是,無論在儲存空間或套件管理中,都不必變更目前的傳送 Blob 實作方式。變更後,解析器 / blob 下載器在向伺服器要求 blob 時,會查詢上述表格,判斷適當的 MIME 類型字串。缺點是 MIME 類型與實際程式碼之間的對應關係,會分散在套件管理和儲存空間程式碼之間。每當系統導入或停用新的 Blob 類型時,都需要手動保持同步。相較於下文介紹的其他選項,這個方法可能較容易出錯,但仍相當簡單,因此不太可能因這種分割方式而產生問題。
- 傳送 Blob 格式可直接封裝 MIME 類型。因此需要進行變更,如下例所示。在這個實作中,我們今天用來對應定義 Blob 類型的列舉的整數類型欄位,仍會用於舊版類型。這個欄位中的保留魔術值表示應使用 MIME 類型欄位,而非舊版類型欄位。這樣做的好處是,在套件管理堆疊中,不需要將 MIME 類型對應至列舉,也不需要從該處對應至儲存空間中的實際功能。而是立即根據 MIME 類型儲存
match。缺點是 blob 標頭會引入另一個可變長度的欄位,導致額外的複雜性,而且 blob 類型本身也必須變更。

這項 RFC 目前並未規定使用 MIME 類型和 Accept
標頭的實作方式,但如果出現內容交涉的具體需求,則可做為未來實作方式的參考。如果是,我們會在後續的 RFC 或設計文件中討論實作細節。
機會型線上遷移
本 RFC 主要說明「伺服器端提供的」遷移作業,並假設在從 <T> 型別遷移至 <U> 型別時,<U> 型別的所有 Blob 都是透過 Blob 伺服器提供,且遵循 RFC-207 (離線 Blob 壓縮) 中規定的設計和軟體發布機制。
不過,在某些情況下,您可能偏好執行線上 (即裝置端) 遷移作業,而不是從伺服器下載 <U> blob,例如:
- 針對特定遷移情境最重要的指標 (例如盡量減少整體網路活動、使用處理器效能特別強大的裝置、採用非常有效率的壓縮演算法等),建議執行線上遷移,並在裝置上重新編碼 Blob。
- 前述要點的特殊情況是 <U> 型別為未編碼 / 未壓縮的 Blob。在這種情況下,幾乎一律建議在裝置上執行線上遷移情境,而不從 Blob 伺服器下載未壓縮的 Blob。
這些遷移作業在概念上可能比 RFC-276 或本 RFC 中說明的遷移作業簡單,但有意超出本 RFC 的範圍。由於至少部分情境可實作,且不必變更軟體傳送至裝置的方式,因此實作前可能不一定需要後續的 RFC。