# XII. Accumulation [data](https://github.com/jam-duna/jamtestnet/tree/main/data/orderedaccumulation) ## 12.1 History and Queuing 主要講述 JAM 系統如何利用 accumulation history $(\xi)$ 和累積佇列 $(\theta)$ 來追蹤 work-package 的累積狀態和 dependencies,區分可立即累積 $(W^!)$ 和需延遲累積 $(W^Q)$ 的 work-reports。 #### Work-report accumulation 的執行過程: ::: info - 檢查 dependencies: 當一個 work-report 被提交預備累積時,系統會檢查它的 dependencies work-report 是否已被 accumulation。 - 立即 accumulation: dependencies 都滿足,work-report 會被立即 accumulation。 - 延遲 accumulation: dependencies 沒有滿足,work-report 會被放入 accumulation queue ϑ 中,等待 dependencies 滿足。 - 佇列管理: 累積佇列 ϑ 會追蹤每個 work-report 的 dependencies,並在每個 timeslot 開始時檢查是否有 work-report 的 dependencies 已經滿足。 - 最多延遲一個 epoch: 如果一個 work-report 在當前的 epoch 中沒有被累積,它會在累積佇列 ϑ 中等待最多一個 epoch。 - 重新檢查: 在下一個 epoch 開始時,系統會重新檢查 ϑ 中的 work-reports,如果 dependencies 滿足了,就會進行 accumulation。 ::: $(12.1)\ \ \ \xi \in [\![\mathbb{\{H\}}]\!]_{E}$ :::info 定義: $\xi$: 累積歷史記錄 (accumulation history) 儲存一個 epoch 各 slot 的 accumulation history,共有 $E$ 個 hash 值的集合,內容為某 slot work-package 的 hash 值集合。 - $\xi$: accumulation history,在各 slot 完成 accumulation 的 work package 的 hash 值集合。 - $[\mathbb{\{H\}}]$: 一個集合,其中元素為 work package hash 值。 :::success ξ = [ {A, B}, // Timeslot 1 累積的 work-package 雜湊值 {C}, // Timeslot 2 累積的 work-package 雜湊值 {D, E} // Timeslot 3 累積的 work-package 雜湊值 ] ![image](https://hackmd.io/_uploads/SkfONpBhJe.png) ::: $(12.2)\ \ \ \overbrace{\xi} \equiv \bigcup_{x \in \xi}(x)$ :::info 定義: $\overbrace{\xi}$: 累積歷史記錄集合 (accumulation history set) 是一個集合 (set),包含了所有已被累積的 work-package hash 值 :::success $\overbrace{\xi}$ = {A, B, C, D, E} // (12.1) 元素聯集 ::: $(12.3)\ \ \ \vartheta \in [\![[\![(\mathbb{W}, \{\mathbb{H}\})]\!]]\!]_\rm{E}$ :::info 定義 $\vartheta$ (accumulation queue): 包含準備好 accumulation 的 work-reports,但 dependencies 尚未滿足,因此 accumulation 被延遲,work-report 的累積最多會被延遲一個 epoch。 - ϑ: 一個 sequence,包含了多個準備好 accumulation 的 work-reports。 - $\mathbb{W}$: 一個已經準備好(available 或 audited)的 work-report。 - $\mathbb\{H\}$: 尚未 accumulation 的 work-package hash 值。 :::success ϑ = [ [(A, {X}), (B, {})], // Timeslot 1 的累積佇列 [(C, {Y})], // Timeslot 2 的累積佇列 [(D, {})], // Timeslot 3 的累積佇列 [], // Timeslot 4 的累積佇列 [(E, {W, Z})] // Timeslot 5 的累積佇列 ] ![image](https://hackmd.io/_uploads/SkPbaTr2yl.png) ::: 在每個 timeslot 結束時,系統會執行以下操作: - 將新的、需要延遲 accumulation 的 work-reports $W^Q$加入到 ϑ 中。 - 移除已經 accumulation 的 work-reports。 - 移除 dependencies 已經滿足的 work-reports。 在新 Epoch 開始時,系統會執行以下操作: - 重新檢查 dependencies: 檢查 ϑ 中所有 work-reports 的 dependencies 是否已被滿足。 - 如果滿足,則將 work-report 從 ϑ 中移除,準備累積。 - 如果不滿足,則 work-report 繼續留在 ϑ 中等待。 - 如果不滿足且延遲超過一個 epoch 則 work-reports 被移除 (丟棄)。 ![image](https://hackmd.io/_uploads/S1-jaIlEJg.png) $(12.4) \ W^{!} \equiv [w \ | \ w < W, \ |(w_x)_p| = 0 \land w_l = \{\}]]$ :::info 定義 $W^{!}$ (immediately accumulatable work-reports sequence): 包含了所有符合條件的 work-reports,這些 work-reports 沒有任何未滿足的 dependencies,可以直接 accumulation。 - $w$: 代表一個 work-report,一個已完成的計算任務的報告,包含了計算結果和相關信息。 - $W$: 包含所有已準備好累積的 work-reports 集合。 - $(w_x)_p$ 有先決條件 (prerequisite) 的 work-report 集合 。 - $w_l$: work-report 儲存導入區塊的相關資訊。 從所有已準備好 accumulation 的 work-reports (W) 中篩選出那些可以立即累積的 work-reports。篩選條件是: - $(w_x)_p| = 0$: 代表 work-report 不需要等待其他 work-package 的計算結果。 - $w_l = \{\}$: work-report 的區塊根查詢字典為空,不需要導入其他區塊的數據。 在每個 timeslot 開始時,系統會執行以下操作: - 檢查 accumulation queue (ϑ): 檢查 ϑ 中是否有 work-report 的 dependencies 已被滿足。 - 加入可立即累積的 work-reports: 系統會加入所有沒有 dependencies 可立即累積的 work report 加入到 W! 。 ::: ![image](https://hackmd.io/_uploads/Sk7zePxNye.png) $(12.5)\ \ \ W^{Q} \equiv E([D(w) | w < W, |(w_x)_p| > 0 \lor w_l \neq \{\}], \overbrace{\xi})$ :::info 定義 $W^{Q}$ (delay-accumulatable work-reports sequence): 包含了當前 epoch 所有需要延遲 accumulation 的 work-reports,這些 work-reports 因為具有未滿足的 dependencies,所以不能立即 accumulation。 - $E$ (queue editing function),用於更新 work-reports 佇列,當其中一些 work-reports 被累積時。 - $D(w)$: work report dependency data。(Formula 12.6) - $\overbrace{\xi}$ 是累積歷史記錄 (accumulated history) 的集合,包含了所有已被累積的 work-package 雜湊值。 從所有已準備好 accumulation 的 work-reports $(W)$ 中篩選出那些需要延遲累積的 work-reports: $\overbrace{\xi}$: 排除已 accumulation 的 work reports。 $(w_x)_p| > 0$: work-report 具有先決條件的 work-package,也就是說,它依賴於其他的 work-package。 $w_l ≠ \{\}$: work-report 的區塊根查詢字典不為空,表示它有需要導入的區塊。 ::: $(12.6)\ \ \ D(w) \equiv (w, \{(w_x)_p\} \cup \mathcal{K}(w_l))$ :::info 定義 $D(w)$(work-report information function): 將 work-report w 及其所有 dependencies 的資訊整合到一個 tuple 中,方便系統進行管理和追蹤。 這個 tuple 包含兩個元素: - w: work-report 本身。 - ${(w_x)_p} ∪ \mathcal{K}(w_l)$: work-report 的所有 dependencies,包括先決條件的 work-packages 和需要導入的區塊。 - Prerequisite work-packages 代表 work-report 計算上 的依賴,它需要等待這些 work-packages 的計算結果。 - Segment-root lookup dictionary 代表 work-report 數據上 的依賴,它需要導入這些區塊中的數據。 ::: ![image](https://hackmd.io/_uploads/SJbpwDgNyl.png) $(12.7)\ \ \ E:\{\begin{matrix}([\![(\mathbb{W},\{\mathbb{H}\})]\!],\{\mathbb{H}\}) \rightarrow [\![(\mathbb{W},\{\mathbb{H}\})]\!]\\ (r,x) \mapsto [(w,d \backslash x)] \{ (w,d) \in r, (w_x)_h \notin x \}\end{matrix}$ :::info 定義了 $E$ (queue-editing function): 根據已被累積的 work-packages 來更新 $W^{Q}$ (12.5 delay 的 work reports) 移除已累積的 work-reports 和已滿足的 dependencies。 Notation: $r$: work-report dependency 序列,每個元素是一個 tuple,包含一個 work-report (w) 和其 dependencies 集合 (d)。 $x$: 已被累積的 work-package hash 值的集合,代表已被累積的 work-packages。 $(w_x)_h$: 代表 work-report w 的 work-package 的 hash 值 更新過程: 1. 移除已累積的 work-reports: 如果一個 work-report hash 值在 $x$ 中,就從 $r$ 中移除。 2. 移除已滿足的 dependencies: 對於剩下的 work-reports,檢查它們的 dependencies,如果某些 dependency 已經被執行 (hash 在 $x$ 中),就從 dependency 集合 d 中移除。 ::: ![image](https://hackmd.io/_uploads/B1P0Pwe4Je.png) $(12.8)\ \ \ Q:\{\begin{matrix}\{(\mathbb{W},\{\mathbb{H}\})\} \rightarrow [\mathbb{W}]\\ r \mapsto \begin{cases} (g - Q(E(r,P(g)))) & \text{if } g \neq [] \\ [] & \text{otherwise} \end{cases}\\ \text{where } g = [w | (w,\{\}) < r] \end{matrix}$ :::info 定義 $Q$(accumulation priority queue function): 給定一組尚未累積的 work-reports 和它們的 dependencies 的情況下,決定哪些 work-reports 可以累積。 - $r$: work report dependency sequence(12.7) - $g$: 所有沒有 dependencies 的 work-reports。 - $E$: (12.7) queue-editing function。 - $P$: (12.9) mapping function: 從 work-reports 中找其對應的 work-package hash 值。 運作方式: - 初始階段: $Q$ 函數首先會從輸入的 work-report 資訊序列 r 中找出所有沒有 dependencies 的 work-reports,這些 work-reports 構成序列 $g$。 這些 work-reports 會被 **優先處理** 如果 $g$ 為空,則表示沒有 work-report 可以累積,函數返回一個空序列。。 - 遞迴階段: 如果 $g$ 不為空,$Q$ 函數會遞迴地處理更新後的佇列,找出下一批可以累積的 work-reports。 這些遞迴找到的 work-reports 會排在初始階段找到的 work-reports 之後。 - 使用 mapping function $P$ 提取 $g$ 中所有 work-report 對應 work-package hash 值。 - 使用 queue edit function $E$ 更新 $r$,移除 $g$ 中 work-reports 以及它們所滿足的 dependencies。 - 遞迴地呼叫 Q 函數來處理更新後的佇列,找出下一批可以累積的 work-reports。 從 g 中移除掉已經被累積的 work-reports。 ::: $(12.9)\ \ \ P:\{\begin{matrix} \{\mathbb{W} \rightarrow \{\mathbb{H}\}\\ \mathbf{w} \mapsto \{(w_s)_h | w \in \mathbf{w}\} \end{matrix}$ :::info 定義 $P$ (mapping function): 從 work-reports 中找其對應的 work-package hash 值。 $w$: 一組 work-reports。 輸入到函數中的報告集合。 $(w_s)_h$: work-report (w) 中,對應的 work-package 的 hash 值。 Formula 意義: 函數 P 的輸入是一組 work-reports ${W}$,輸出對應 work-package 的 hash 值 $\mathbb{H}$ ::: $(12.10)\ \ \ \text{let } m = \mathbf{H}_t \mod E$ :::info $m$ 目前區塊的對於該 epoch 的 slot index。 $H_t$ 從 JAM 開始計算的 slot index。 $E$ 代表每個 epoch 中的 slot 數量。 Formula 意義: 利用 $H_t$ 計算 epoch 中的 slot index。(用於Formula 12.12) ::: $(12.11)\ \ \ \mathbf{W}^{*} \equiv \mathbf{W}^{!} ⌢ Q(\mathbf{q})$ :::info 定義 $\mathbf{W}^{*}$: 指可以在當前區塊 accumulate 的 work-reports 序列。準備好被處理的 list。(單一 slot 資源有限) - $\mathbf{W}^{!}$:(12.4) 可以立即累積的 work-reports 序列。 - $Q(\mathbf{q})$:(12.8) 提供考慮 dependencies 和優先級後準備好的 work-reports 列表。 Formula 意義: 將 $\mathbf{W}^{!}$ 中的 work report 透過 $Q(\mathbf{q})$ 優先級排序得到當前的區塊中被累積的 work reports ::: :::warning Update 12.12, check example of theta ::: --- ## 12.2. Execution 此章重點為在 gas limit 的限制下,JAM 系統如何使用 outer accumulation function (Δ+) 和 parallel accumulation function (Δ∗) 來執行 accumulation 操作,並更新系統狀態,以實現高效和可靠的狀態更新。 >每個 block 都有一個 gas 上限,可能無法在單個 block 內處理 $\mathbf{W}^*$ 中的所有項目。 為了盡可能的使用 gas,所以要盡可能地累積 work-items 。 > - gas 是 JAM VM 裡的執行時間單位 >$\Delta_+$ 順序執行模式(outer accumulation function) : >- gas limit 有上限,但是 accumulation 的過程可能導致實際使用的 gas 少於宣告的上限。 >- 只有在work-items 被累積以後,才能知道是否使用了較少的 gas,所以需要一種 **順序執行** 模式。 >- 依序累積 work-reports。 >- 適用於 gas limit 較低的情況。 當 gas limit 較低時,依序累積可以更精細地控制 gas 消耗,避免超出 gas limit。 >- 適用於 work-reports 之間存在複雜的 dependencies 的情況。 依序累積可以確保 work-reports 按照 dependencies 的順序累積,避免因為 dependency 未滿足而導致錯誤。 >$\Delta_*$ : 非順序執行模式(parallel accumulation function ) : > - PVM 的設置並非零成本,所以希望將成本分攤到盡可能多的 work-items > - 方式 : 將屬於同一 service 的 work-items 聚合到 PVM invocation(調用)實作。這樣就可以累積更多的 work-items >- 並行累積 work-reports。 將屬於同一個 service 的 work-items 聚合到同一個 PVM 執行中,並行處理。 >- 適用於 gas limit 較高的情況。 當 gas limit 較高時,並行累積可以充分利用系統資源,提高累積效率。 >- 適用於 work-reports 之間 dependencies 較少的情況。 並行累積可以同時處理多個 work-reports,提高效率。 > 參考[name=Tvvkk7] >$\Delta_1$ : 單一服務執行模式(single-service accumulation) : >- 並行累積 (Δ∗) 中: 當 Δ∗ 函數需要並行處理多個 service 的 work-reports 時,它會 為每個 service 呼叫一次 Δ_1 函數,讓每個 service 的 work-reports 在各自的 PVM 中並行執行。 >- 單獨累積特定 service 的 work-reports: 當只需要累積特定 service 的 work-reports 時,可以直接呼叫 Δ_1 函數。 --- $(12.13)\ \ \ \mathbb{U} = \left( \mathbf{d} \in \mathbb{D}\langle \mathbb{N}_S \rightarrow \mathbb{A} \rangle, \mathbf{i} \in [\mathbb{K}]_\rm{V}, \mathbf{q} \in [\![[\![\mathbb{H}]\!]_\rm{Q}]\!]_C, \mathbf{x} \in (\mathbb{N}_S, \mathbb{N}_S, \mathbb{N}_S, \mathbb{D}(\mathbb{N}_S \rightarrow \mathbb{N}_G)) \right)$ :::info 定義 $\mathbb{U}$ (partial state set)。 這個集合包含了 accumulation 過程中,過程中需要且可能被修改的 parameter。將 accumulation 過程中所有相關的 pararmeter 打包在一起。 用於 formula (12.16) - outer accumulation function (Δ+) formula (12.17) - parallel accumulation function (Δ∗) Notation: $\mathbb{D}$: 字典(map)。 $\mathbb{N}_S$: service ID。 $\mathbb{A}$: service account。 $\rm{V}$: 驗證者數量。 $\mathsf{Q}$: work report queue 的容量。 $\rm{C}$: core 數量 $\mathbb{N}_G$ 代表氣體限制的集合。 $d \in \mathbb{D}⟨\mathbb{N}_S → \mathbb{A}⟩$: 這是 service accounts state,是一個 map 將 service 的 ID ($\mathbb{N}_S$) 對應到 service account ($\mathbb{A}$)。 ``` service accounts map: { 0x123: {balance: 100, ...}, 0x456: {balance: 50, ...} } 0x123 和 0x456 是 service 的 ID {balance: 100, ...} 和 {balance: 50, ...} 是 service account 內容。 ``` $i \in [\mathbb{K}]_\mathsf{V}$: upcoming validator keys,是一個長度為 $\mathsf{V}$ 的序列 (sequence),每個元素代表一個 validator 的公鑰。 $\mathbf{q} \in [\![[\![\mathbb{H}]\!]_\rm{Q}]\!]_C$: 這是 work-reports 的 queue,是一個長度為 C 的序列,而裡面每個子序列的元素是一個長度為 $\mathsf{Q}$ 的 queue,$\mathbb{H}$ 每個元素是一個 work-report 的 ID。 ``` JAM 系統中有 3 個核心 (core) 每個清單最多可以容納 2 個 work-report。 以下 work-report 等待處理: Work-report A, B 分配給 Core 1 Work-report C 分配給 Core 2 Work-report D, E 分配給 Core 3 q = [ [A, B], // Core 1 的待處理清單 [C, _], // Core 2 的待處理清單,_ 表示空位 [D, E] // Core 3 的待處理清單 ] ``` $\mathbf{x} \in (\mathbb{N}_S, \mathbb{N}_S, \mathbb{N}_S, \mathbb{D}(\mathbb{N}_S \rightarrow \mathbb{N}_G))$ 權限狀態(privileges state): - 第一個 $\mathbb{N}_S$: 代表 manager service 的 ID,manager service 負責**管理** JAM 系統中的其他 services,例如創建新的 service、更新 service 的 code 等。 - 第二個 $\mathbb{N}_S$: 代表 assign service 的 ID,assign service 負責**分配** work package 給 core 執行。 - 第三個 $\mathbb{N}_S$: 代表 designate service 的 ID,designate service 負責**指定**哪些 validator 可以參與 core 的運作。 - D(N_S → N_G): 一個字典(map),用於儲存每個 service 的 gas limit。 ``` 假設一個 JAM 系統中有三個 service accounts: Service A:負責處理用戶註冊。 Service B:負責處理用戶身份驗證。 Service C:負責管理系統參數。 每個 service account 都有一個唯一的 service ID (N_S): Service A: N_S = 1 Service B: N_S = 2 Service C: N_S = 3 系統中有三個特殊的 service,分別負責管理、分配和指定: Manager service: N_S = 1 (Service A) Assign service: N_S = 2 (Service B) Designate service: N_S = 3 (Service C) 每個 service 都有自己的 gas limit (N_G): Service A: N_G = 1000 Service B: N_G = 2000 Service C: N_G = 3000 那麼,privileges state x 可以表示為: x = (1, 2, 3, {1: 1000, 2: 2000, 3: 3000}) 其中: (1, 2, 3) 分別代表 manager service、assign service 和 designate service 的索引。 {1: 1000, 2: 2000, 3: 3000} 是一個字典,表示每個 service 的 gas limit。 這個 privileges state x 的含義是: Service A 是 manager service,負責管理其他 services。 Service B 是 assign service,負責分配 work package。 Service C 是 designate service,負責指定 validator。 每個 service 的 gas limit 分別是 1000、2000 和 3000。 ``` ::: $(12.14)\ \ \ \mathbb{T} \equiv (s \in \mathbb{N}_S, d \in \mathbb{N}_S, a \in \mathbb{N}_B, m \in \mathbb{Y}_{\rm{W}_\it{T}}, g \in \mathbb{N}_G)$ :::info 定義 $\mathbb{T}$ (deferred transfer): 在 accumulation 過程中產生的轉帳操作。這些轉帳操作並不會立即執行,而是會被暫時儲存起來,直到 accumulation 過程完成後才會被執行。 $\mathbb{N}_B$ 代表餘額的集合。 $\mathbb{Y}_{W_T}$ 代表長度為 W$_\it{T}$ 的八位元組序列的集合,用於儲存轉帳的備註資訊。 $\mathbb{N}_G$ 代表氣體限制的集合。 T: 這是一個集合,表示延遲轉帳的表徵 (characterization)。 $s \in \mathbb{N}_S$: 發送方 (sender) 的 service ID。 $d \in \mathbb{N}_S$: 接收方 (receiver) 的 service ID。 $a \in \mathbb{N}_B$: 轉帳的金額(balance)。 $m \in \mathbb{Y}_{(\rm{W}_\it{T})}$: 轉帳的備註 (memo) 組成部分,$\rm{W}_T$ = 128 個八位元組,表示轉帳的備註資訊。 $g \in \mathbb{N}_G$: 轉帳的氣體限制 (gas limit),表示轉帳操作允許消耗的最大 gas 量。 定義一個集合 T,用於表徵延遲轉帳。延遲轉帳是指在累積過程中產生的轉帳操作,這些轉帳操作會被暫時儲存起來,直到累積過程完成後再執行。 ``` T = { 發送方(s) 接收方(d) 金額(a) 備註(m) gas limit(g) (A, B, 100, "buy", 50), // Service A 向 Service B 轉帳 100 個遊戲幣 (C, D, 50, "bonus", 20) // Service C 向 Service D 轉帳 50 個獎勵積分 } ``` ::: $(12.15)\ \ \ B \equiv \{(\mathbb{N}_S, \mathbb{H})\}$ ![v0.6.4 (12.15)](https://hackmd.io/_uploads/BJPuxkdhyg.png) :::info $B$: 一個集合,用於儲存 service ID 和 accumulation 輸出 hash 值的配對。 $\mathbb{N}_S$: Service ID。 $\mathbb{H}$: Hash 值。 定義一個集合 $B$,用於儲存 service ID 和 accumulation 輸出 hash 的配對。這些配對可以用於驗證 accumulation 結果的正確性。 ``` Service A 轉帳給 Service B, Service C 轉帳給 Service D B = { (A, hash1), // Service A 的交易雜湊值 (B, hash1), // Service B 的交易雜湊值 (C, hash2), // Service C 的交易雜湊值 (D, hash2) // Service D 的交易雜湊值 } ``` ::: ![image](https://hackmd.io/_uploads/S1Vp92Z4kx.png) ![v0.6.4 (12.16)](https://hackmd.io/_uploads/HJNzGyu3Je.png) :::info $\Delta_{+}$: outer accumulation function 函數,用於累積 work-reports 並更新狀態。 $\Delta_{+} : (\mathbb{N}_G, \mathbb{[W]}, \mathbb{U}, D(\mathbb{N}_S → \mathbb{N}_G)) → (\mathbb{N}, \mathbb{U}, \mathbb{T}, B)$ :::success 輸入: $\mathbb{N}_G$:氣體限制 (gas limit) 的集合。 $[\mathbb{W}]$:work-reports 的序列。 $\mathbb{U}$:(Formula 12.13) Partial state set。 $D(\mathbb{N}_S → \mathbb{N}_G)$:Service / Gas limit 的 map 輸出: $N$:累積的 work-results 的數量。 $U$:更新後的 U。 $[T]$:延遲轉帳的序列。 $B$:Service / Accumulate hash 的 map。 ::: :::info $\Delta_{+}: (g, w, o, f) \mapsto \begin{cases} (0, o, [], \{\}) & \text{if } i = 0 \\ (i + j, o', t^{*} ⌢ t, b^{*} \cup b) & \text{otherwise} \end{cases}$ $\text{where } i = \text{max}([\mathbb{N}]_{|w|+1}): \sum_{w \in \mathbb{W}} \sum_{r \in w_r}(r_g) \leq g$ :::success 如果 i = 0,表示沒有 work-report 可以累積,則函數返回 (0, o, [], {}): - 0: 表示累積的 work-report 數量為 0。 - o: 表示 partial state 沒有改變。 - []: 表示沒有延遲轉帳。 - {}: 表示沒有服務/雜湊值對。 如果 i ≠ 0,表示有 work-report 可以累積,則函數返回 $(i + j, o', t^{*} ⌢ t, b^{*} \cup b)$: - $i + j$:表示累積的 work-reports 的總數量。 - $i$ 是透過 $max(n | g ≥ g' + Σ_(r∈w_(...i-1))(r_g))$ 計算出的,表示在 gas limit 限制下,可以累積的 work-reports 的最大數量。 - $j$ 是遞迴呼叫 $\Delta_{+}$ 函數累積的 work-reports 的數量。 - o':表示更新後的 partial state,包含了累積 work-reports 後,更新後的 service accounts state、upcoming validator keys 等資訊。 - $t^{*} ⌢ t$:表示合併的延遲轉帳序列。 - $t^{*}$ 是並行累積函數 $\Delta_*$ 產生的延遲轉帳序列。 - $t$ 是遞迴呼叫 $\Delta_+$ 函數產生的延遲轉帳序列。 - ⌢ 表示序列的 concatenation 操作,將兩個序列連接起來。 - $b^{*} ∪ b$:表示合併後的服務/雜湊值對的集合。 - b^{*} 是並行累積函數 Δ∗ 產生的服務/雜湊值對的集合。 - b 是遞迴呼叫 Δ+ 函數產生的服務/雜湊值對的集合。 - ∪ 表示集合的聯集操作,將兩個集合合併起來。 ::: :::info $and (g*, o*, t*, b*) = Δ∗(o, w_(...i-1), f)$ 這行程式碼 呼叫了並行累積函數 Δ∗ 來累積一部分 work-reports。 Δ∗(o, w_(...i-1), f) 表示將初始狀態 o、前 i-1 個 work-reports (w_(...i-1)) 和服務的 gas limit 字典 f 作為輸入參數傳遞給 Δ∗ 函數。 (g*, o*, t*, b*) 表示 Δ∗ 函數的輸出值: ``` g*: Δ∗ 函數消耗的 gas 量。 o*: Δ∗ 函數更新後的狀態。 t*: Δ∗ 函數產生的延遲轉帳序列。 b*: Δ∗ 函數產生的服務/雜湊值對的集合。 ``` $and (j, o', t, b) = Δ+(g - g*, w_(i...), o*, {})$ 這行程式碼 遞迴地呼叫了外部累積函數 Δ+ 來累積剩餘的 work-reports。 Δ+(g - g*, w_(i...), o*, {}) 表示將以下參數傳遞給 Δ+ 函數: g - g*: 剩餘的 gas limit,也就是初始 gas limit g 減去 Δ∗ 函數消耗的 gas 量 g*。 w_(i...): 剩下的 work-reports,也就是從第 i 個 work-report 開始到最後一個 work-report。 o*: Δ∗ 函數更新後的狀態。 {}: 一個空的服務/雜湊值對的集合,因為遞迴呼叫時不需要傳遞這個參數。 (j, o', t, b) 表示遞迴呼叫 Δ+ 函數的輸出值: ``` j: 遞迴呼叫 Δ+ 函數累積的 work-reports 的數量。 o': 遞迴呼叫 Δ+ 函數更新後的狀態。 t: 遞迴呼叫 Δ+ 函數產生的延遲轉帳序列。 b: 遞迴呼叫 Δ+ 函數產生的服務/雜湊值對的集合。 ``` ::: ``` 情境: 假設你是一位活動企劃,負責籌備一個大型的科技展覽。你需要完成一系列的任務,例如: 會場佈置: 需要 3 天時間。 邀請嘉賓: 需要 2 天時間。 安排演講: 需要 4 天時間,但需要等嘉賓確認才能安排 (dependency)。 設計宣傳海報: 需要 1 天時間。 撰寫新聞稿: 需要 2 天時間,但需要等演講安排好才能撰寫 (dependency)。 你的時間 (gas limit) 有限,假設你只有 5 天的時間來完成這些任務。 外部累積函數 (Δ+) Δ+ 函數就像是你安排任務的 "策略",它會 依序 處理這些任務,並考慮時間限制和 dependencies。 執行過程 計算可完成的任務數量: 你會先計算在 5 天內可以完成哪些任務。 會場佈置 (3 天) + 邀請嘉賓 (2 天) = 5 天,正好滿足時間限制。 安排演講需要 4 天,但它依賴於邀請嘉賓,所以不能立即完成。 設計宣傳海報 (1 天) 可以完成。 呼叫並行累積函數 (Δ∗): 你發現會場佈置和設計宣傳海報 沒有 dependencies 而且可以並行 執行,所以你決定 "委託" 給你的同事 (Δ∗ 函數) 來處理這兩項任務。 你的同事會 並行地 完成會場佈置和設計宣傳海報。 繼續執行任務: 同時,你會 依序 完成邀請嘉賓的任務。 處理延遲的任務: 你會將安排演講和撰寫新聞稿這兩項任務 延遲 到下一次有空的時候處理,因為它們的 dependencies 還沒滿足。 記錄結果: 你完成了 3 項任務 (邀請嘉賓、會場佈置、設計宣傳海報)。 你更新了展覽的籌備狀態,例如:嘉賓名單確定了、會場佈置完成了、海報設計好了。 你記錄了延遲的任務:安排演講和撰寫新聞稿。 ``` ![image](https://hackmd.io/_uploads/H1A0q2WNkg.png) ![(GP v0.5.4) 12.17](https://hackmd.io/_uploads/H1tMNmaLkg.png) ![(GP v0.6.4) 12.17](https://hackmd.io/_uploads/r1lv0duhJx.png) ![(GP v0.6.5) 12.17](https://hackmd.io/_uploads/rJ_5h01llx.png) :::info TODO: 更新 $\Delta_{*}$: parallel accumulation function 函數,用於並行累積 work-reports 並更新狀態。 並行累積 work-reports,並更新狀態。它會根據輸入的 work-reports 序列,將與同一個服務相關聯的 work-items 聚合到同一個 PVM 執行中,並行處理這些 work-items,並將累積過程中產生的延遲轉帳儲存在 $\mathbb{T}$ 序列中,將服務索引和累積輸出雜湊值的配對儲存在 $\mathbb{B}$ 集合中 輸入: - $\mathbb{U}$:參數狀態集合。 - $[\mathbb{W}]$:work-reports 的序列。 - $D(\mathbb{N}_S → \mathbb{N}_G)$:服務索引到 gas limit 的映射 (字典)。 輸出: - $\mathbb{N}_G$:累積過程消耗的 gas 總量。 - $\mathbb{U}$:更新後的 U 集合。 - $[\mathbb{T}]$:延遲轉帳的序列。 - $B$:服務/雜湊值對的集合。 Δ∗ 函數會根據輸入 (o, w, f) 計算輸出 (u, (x′, d′, i′, q′), tˆ, b)。 輸入 o:初始的部分狀態 (partial state)。 w:work-reports 的序列。 f:服務的 gas limit 字典。 輸出 u:所有 service 消耗的 gas 總量。 (x′, d′, i′, q′):更新後的 partial state 的各個組成部分。 tˆ:延遲轉帳的序列。 b:服務/雜湊值對的集合。 $s = {r_s | w ∈ w, r ∈ w_r} ∪ K(f)$ 這個式子用於計算 所有涉及到的 service 的集合 (s)。 $r_s$:work-report r 中的 service ID。 $w_r$:work-report w 中的 work-item 序列。 $K(f)$:服務的 gas limit 字典 $f$ 中的所有 key,也就是所有 service ID。 $u = Σ_(s∈s)(Δ_1(o, w, f, s)_u)$ 這個式子用於計算 所有 service 消耗的 gas 總量 (u)。 $Δ_1(o, w, f, s)_u$:單一服務累積函數 Δ_1 針對 service s 消耗的 gas 量。 $b = {(s, b) | s ∈ s, b = Δ_1(o, w, f, s)_b, b ≠ ∅}$ 這個式子用於生成 服務/雜湊值對的集合 (b)。 $Δ_1(o, w, f, s)_b$:單一服務累積函數 Δ_1 針對 service s 產生的雜湊值。 $tˆ = [Δ_1(o, w, f, s)_t | s < s]$ 這個式子用於生成 延遲轉帳的序列 (tˆ)。 $Δ_1(o, w, f, s)_t$:單一服務累積函數 $Δ_1$ 針對 service s 產生的延遲轉帳序列。 $((m, a, v, z), d, i, q) = o$ 這個式子將初始的部分狀態 $o$ 解構為不同的組成部分。 $x′ = (Δ_1(o, w, f, m)_o)_x$ $i′ = (Δ_1(o, w, f, a)_o)_i$ $q′ = (Δ_1(o, w, f, v)_o)_q$ $d′ = {s ↦ d_s | s ∈ K(d) \ s} ∪ ⋃_(s∈s)((Δ_1(o, w, f, s)_o)_d)$ 這些式子用於 更新部分狀態的各個組成部分。 ``` 想像一個線上購物平台,使用 JAM 系統處理用戶的訂單和支付。 Service A:訂單管理服務,負責處理用戶的訂單資訊,例如商品、數量、地址等。 Service B:支付服務,負責處理用戶的支付資訊,例如付款方式、金額等。 Service C:庫存管理服務,負責管理商品的庫存資訊。 現在,有一批 work-reports 需要被累積,這些 work-reports 記錄了不同用戶的購物行為: Work-report 1:用戶 A 提交了一個購買商品 X 的訂單,包含商品資訊、數量和地址。 Work-report 2:用戶 B 提交了一個購買商品 Y 的訂單,包含商品資訊、數量和地址。 Work-report 3:用戶 A 使用信用卡支付了訂單 1 的款項。 並行累積 Δ∗ 函數會將這些 work-reports 分組,將屬於同一個 service 的 work-items 聚合到同一個 PVM 執行中,並行處理。 在這個例子中,Δ∗ 函數會將 work-report 1 和 3 的 work-items 聚合到 Service A 的 PVM 中執行,并将 work-report 2 的 work-items 放到 Service B 的 PVM 中執行。 執行過程 Service A 的 PVM 會並行執行 work-report 1 和 3 中的 work-items,例如: 檢查 work-report 1 中的商品資訊和庫存 (與 Service C 互動)。 驗證 work-report 3 中的支付資訊 (與 Service B 互動)。 更新用戶 A 的訂單狀態。 生成訂單記錄和雜湊值。 Service B 的 PVM 會執行 work-report 2 中的 work-items,執行過程與 Service A 類似。 輸出結果 N_G:累積過程消耗的 gas 總量。 U:更新後的 partial state set U,包含了更新後的 service accounts state、upcoming validator keys 等資訊。 [T]:延遲轉帳序列,包含了所有延遲的轉帳操作,例如將用戶 A 的款項轉移到賣家帳戶。 B:服務/雜湊值對的集合,包含了每個 service 的 accumulation 輸出雜湊值,例如 Service A 的訂單處理結果和 Service B 的支付處理結果。 ``` ::: :::info 比較: 初始 gas limit: Δ+ 函數需要一個初始的 gas limit $(N_G)$ 作為輸入,而 Δ∗ 函數不需要。這是因為 Δ+ 函數會依序累積 work-reports,需要控制 gas 的消耗,而 Δ∗ 函數會並行累積 work-reports,gas 的消耗會在每個 service 的 PVM 中分別計算。 輸出 gas limit: Δ∗ 函數會輸出一個 gas limit $(N_G)$,表示累積過程實際消耗的 gas 量,而 Δ+ 函數不需要輸出 gas limit,因為它會在執行過程中更新 U 集合中的 gas limit 信息。 ::: ![v0.6.3 (12.18)](https://hackmd.io/_uploads/BJmNeXXoyg.png) $(12.18)\ \mathbb{O} \equiv (o \in \mathbb{Y} \cup \mathbb{J}, l \in \mathbb{H}, k \in \mathbb{H}, a \in \mathbb{Y})$ :::info 定義 $\mathbb{O}$: 操作 tuple (operand tuple)是一個集合,打包work item 執行結果和上下文資訊給 PVM accumulate function 使用(formula 12.19): - $o \in \mathbb{Y} \cup \mathbb{J}$: 程式碼執行的輸出或錯誤,可以是一個八位元組序列 ($\mathbb{Y}$),表示執行成功,或者是一個錯誤類型 ($\mathbb{J}$),表示執行失敗。 - $l \in \mathbb{H}$: 代表工作負載 (payload) 的 hash 值,表示 refine 階段執行的 work item 中的負載。 - $k \in \mathbb{H}$: 服務程式碼的 hash 值,表示執行 work item 時的服務程式碼版本。 - $a \in \mathbb{Y}$: 要傳遞給 Accumulate 函數的額外參數,表示 Accumulate 函數可能需要的其他輸入數據。 ::: ![image](https://hackmd.io/_uploads/BJp-o2-VJl.png) ![(GP v0.5.4) 12.19](https://hackmd.io/_uploads/HkxLE7TU1x.png) ![(GP v0.6.3) 12.19](https://hackmd.io/_uploads/SyhkZmmjke.png) ![v0.6.4 (12.19)](https://hackmd.io/_uploads/rkxx941_2Jx.png) :::info TODO: 更新 定義 $\Delta_1$ (single-service accumulation)此函數的作用是 accumulate 特定單一 service$(N_S)$ 的 work-reports,並使用 PVM 累積函數 $(Ψ_A)$ 來執行這些 work-items。 輸入: - $\mathbb{U}$:部分狀態的集合。 - $[W]$:work-reports 的序列。 - $D(N_S → N_G)$:服務索引到 gas limit 的映射 (字典)。 - $N_S$:要累積的 work-reports 所屬的服務的索引。 輸出: - $\mathbb{U}$:操作 tuple 的集合 (包含要傳遞給 PVM 累積函數的參數)。 - $[\mathbb{T}]$:延遲轉帳的序列。 - $\mathbb{H}$:accumulate hash 結果 - ${\mathbb{N}_G}$:氣體限制。 $g = \mathcal{U}(f_s, 0) + \sum_{w \in \mathbb{W}, r \in w_r, r_s = s}(r_g)$ 這個公式用於計算 service s 在執行累積操作時 實際可用的 gas limit。 它等於 service s 的初始 gas limit 加上所有屬於 service s 的 work-report 消耗的 gas 量總和,並確保 g 的值不小於 0。 $g$:service $s$ 可用的 gas limit。 $\mathcal{U}(f_s, 0)$:一個函數,返回 $f_s$ 或 0 中較大的值。 $f_s$ 是 service s 的初始 gas limit。 $\sum_{w \in \mathbb{W}, r \in w_r, r_s = s}(r_g)$:所有屬於 service s 的 work-report (r) 消耗的 gas 量總和。 $w \in \mathbb{W}$ 表示遍歷所有 work-reports (w)。 $r \in w_r$ 表示遍歷 work-report 中的所有 work-items。 $r_s = s$ 表示篩選出屬於 service s 的 work-item。 $r_g$ 表示 work-item $r$ 消耗的 gas 量。 $p = [(o, l, k, a) \ | \ w \in \mathbb{W}, r \in w_r, r_s = s]$ 給PVM 的參數 o: 初始的部分狀態 (partial state)。 w: work-reports 的序列。 f: 服務的 gas limit 字典。 s: 要累積的 work-reports 所屬的服務的索引。 --- $p$: 要傳遞給 PVM 累積函數的操作 tuple 序列。 $(o, l, k, a)$: 一個操作 tuple,包含以下元素: $o$: 程式碼執行的輸出或錯誤。 $l$: 工作負載 (payload) 的雜湊值。 $k$: 報告時服務程式碼的雜湊值。 $a$: 要傳遞給 Accumulate 函數的額外參數。 $w \in \mathbb{W}$: 表示遍歷所有 work-reports (w)。 $r \in w_r$: 表示遍歷 work-report w 中的所有 work-items。 $r_s = s$: 表示篩選出屬於 service s 的 work-item。 --- 這個公式用於篩選生成要傳遞給 PVM 累積函數的參數 tuple。 --- ``` 情境: 假設一個線上拍賣平台,使用 JAM 系統處理用戶的出價和交易。 Service A:用戶帳戶管理服務,負責儲存用戶的餘額和拍賣品資訊。 Work-reports 序列 [w1, w2, w3] 等待累積: w1:用戶 A 對拍賣品 X 出價 100 元。 w2:用戶 B 對拍賣品 X 出價 150 元。 w3:用戶 A 對拍賣品 Y 出價 50 元。 單一服務累積 Δ_1 函數會被呼叫,用於累積 Service A 的 work-reports (w1 和 w3)。 執行過程 提取 work-items: 從 work-reports 序列 [w1, w2, w3] 中提取屬於 Service A 的 work-items,也就是 w1 和 w3 中的 work-items。 呼叫 PVM 累積函數: 使用 PVM 累積函數 Ψ_A 來執行這些 work-items,例如: 檢查用戶 A 的餘額是否足夠支付出價。 更新拍賣品 X 和 Y 的最高出價記錄。 更新用戶 A 的出價資訊。 產生交易記錄和雜湊值。 處理延遲轉帳: 如果有需要,將延遲轉帳資訊添加到 [T] 序列中,例如,如果用戶 A 的出價成功,則需要將 100 元從用戶 A 的帳戶中凍結,作為保證金。 返回結果: 返回以下資訊: O:操作 tuple,包含 PVM 累積函數的執行結果,例如 "出價成功" 或 "出價失敗"。 [T]:延遲轉帳序列,包含所有延遲的轉帳操作。 H ∪ {N_G}:雜湊值或氣體限制,例如交易雜湊值或實際使用的 gas 量。 ``` ::: --- ## 12.3 Deferred Transfers and State Integration 目標 : 整合因為 dependency 而延遲的 work-report 並進行狀態更新。 --- 限制 gas 的最大值不超過 $\mathsf{G}_\it{T}$ ![Eq 12.20](https://hackmd.io/_uploads/BkrXvLgNke.png) ![v0.6.4 (12.20)](https://hackmd.io/_uploads/BkAbIkO2kl.png) Eq. I.4.4 : $$\mathsf{G}_T, \mathsf{G}_A \cdot \mathsf{C} + \sum_{x \in \mathcal{V}(\chi_\mathbf{g})}(x)$$ :::info $\rm{G}_\it{T}$ = 35,000,000 : 分配給所有核心進行 accumulation 的總 gas $\rm{G}_\it{A}$ = 100,000 : 分配給單一核心進行 accumulation 的總 gas $\rm{C}$ : #Cores = 341 $\rm{G}_\it{A} \cdot \rm{C}$ = 34,100,000 $\chi_g$ : dictionary, the always-accumulate service indices 以及 gas limit $\mathcal{V}$ : 可以取得 dictionary 的 values $\sum_{\it{x} \in \mathcal{V}(\chi_\mathbf{g})}(\it{x})$ : always-accumulate services 的 gas limit 總和 ::: 執行 outer accumulation function,未滿足 dependency 的 work reports 會被安排到 deferred transfers $(\mathbf{t})$, ![Eq 12.21, 12.22](https://hackmd.io/_uploads/HJTahdgVkg.png) ![v0.6.4 (12.21~22)](https://hackmd.io/_uploads/BJZwLJOh1g.png) :::info $n$: 已累積的 work-result 數量 $\mathbf{o}$: posterior state-context - :::spoiler states $\chi$: 有特權的 services $\delta$: service account 的狀態 $\iota$: 下一個將使用的 validator keys 和 metadata。 $\varphi$: The authorization queue - :::spoiler 有特權的 services $$ \chi \equiv ({ {\chi_m} \in {\mathbb{N}_S}, {\chi_a} \in {\mathbb{N}_S}, {\chi_v} \in {\mathbb{N}_S}, {\chi_\mathbf{g}} \in {\mathbb{D} \langle {\mathbb{N}_S} \rightarrow {\mathbb{N}_G} \rangle} } ) $$ $\chi_m$: 代表一個 manager service(super user) 的 index, 這個 service 能夠影響區塊之間 $\chi$ 的組成 (可以影響 $\chi$ 中的 service index 或是 gas limit 數值) $\chi_a$: 可以修改區塊之間的 $\varphi$ $\chi_v$: 可以修改區塊之間的 $\iota$ $\chi_\mathbf{g}$: 是一個 Dictionary, 儲存在每一個區塊可以自動累積的 service indices 以及他們被分配到的 gas limit <!--- :::spoiler Service accounts ![image](https://hackmd.io/_uploads/HkU2J9WEJx.png) --> $\mathbf{t}$: 被 deferred transfers 的 work reports $\mathbf{C}$: BEEFY commitment map (accumulation commitment map),包含輸出累積的服務索引及其對應的累績結果。 - $\mathbf{C}$ is set of pairs of indices of the output-yielding accumulated services to their accumulation result. $\rightarrow$ {service index $\in \mathbb{N}_S$, accmulation result $\in \mathbb{H}$} - 對 BEEFY protocol 有用 - 在 Eq. 7.3 (Recent History) : 使用於推導 accumulation-result tree root。 $\delta^{\dagger}$ : 已經 preimage integration,還未 accumulation ::: --- ![image](https://hackmd.io/_uploads/BkxtDy_3yg.png) ![v0.6.4 (12.21~22)](https://hackmd.io/_uploads/rk-Lwydhke.png) --- 定義 selection function $R$,用於整合 deferred transfers 的 state - 映射後會根據 source service index 排序再根據在 $\rm{t}$ 中的位置排序。 - $\rm{t}$ 排序是根據 source service 執行順序 ![Eq. 12.23](https://hackmd.io/_uploads/HkrGTrs7Jl.png) ![Eq. 12.14](https://hackmd.io/_uploads/rkPCocl4Jx.png) --- State Integration(狀態整合) : ![image](https://hackmd.io/_uploads/SkKYIXm4kl.png) ![v0.6.4 (12.27~28)](https://hackmd.io/_uploads/SyaeuyunJx.png) ![image](https://hackmd.io/_uploads/rkcYisxVyl.png) :::info The second intermediate state δ‡ may then be defined with all the deferred effects of the transfers applied: $\delta^{\ddagger}$ : 已經 accumulation,還未 on-transfer $\delta^{\dagger}$ : 已經 preimage integration,還未 accumulation $\Psi_T$ (on-transfer invocation): - service code 3$^{rd}$ entry-point - on-transfer : destination service 收到 source service 的訊息 - if $R(d)=[]$ : service 沒有要執行的 code,或這個 service 有關的 work-report 沒有 transfers - $\Psi_T$ (section B.5) -> $\Psi_M$(section A.8) -> $\Psi_H$(section A.6) ::: --- ![image](https://hackmd.io/_uploads/H1-cKyu3kg.png) ![v0.6.4 (12.29)](https://hackmd.io/_uploads/BJVjFy_3kl.png) ![v0.6.4 (12.30)](https://hackmd.io/_uploads/HJy0YJu31e.png) --- 更新歷史紀錄($\xi$) ![image](https://hackmd.io/_uploads/HJyVariXJl.png) :::info $\mathbf{W}^*$: 在當前區塊可以累積的 work-reports 序列。 $P(\mathbf{W}^*)$: 藉由 function $P$ 取得 work package hashes $ i = 0 ... 599 $ : $\xi^{\prime}_0\equiv\xi_1$ , $\xi_{599}$ (最舊的紀錄)會直接丟棄 ::: --- 更新 accumulation queue ![image](https://hackmd.io/_uploads/rkEr6HsX1x.png) ![image](https://hackmd.io/_uploads/ByZUwReEyg.png)<!-- $\vartheta^{\prime \circlearrowleft}_{m-i} = \vartheta^{\prime}[m-i \% |\vartheta^{\prime}|]$ --> ![image](https://hackmd.io/_uploads/r18xIRxVkx.png) :::info $\vartheta$ : accumulation queue $m$ : 目前的 timeslot $\tau^\prime$: 代表目前區塊的 slot index。 $\tau$: 前一個區塊的 slot index。 $i=0$ : 這個 timeslot 滿足 dependency 被 accumulated 的 report 從 $\rm{W}^Q$ 移除 $1 \le i < \tau^{\prime}-\tau$ : 依賴於未完成累積的package,超過 600 個 timeslots 所以被清除 - 上個 timeslot (epoch_2,slot_300) ... (epoch_3, slot_299) - 目前 timeslot (epoch_2,slot_299) ... (epoch_3, slot_300) $i \ge \tau^{\prime}-\tau$ : 更新 accumulation queue 中其他 timeslot 滿足 dependency 且已累積的 work report Accumulate - may transfer funds, alter state, read other services' state OnTransfer - may alter state and read other services' state <!-- https://youtu.be/tdvqkKdFTlw?t=1924 --> ::: --- ## 12.4 Preimage Integration 此章節主要是說明**在 Accumulation 階段後 (service accounts $\delta^{\ddagger}$),如何將 extrinsic preimage $\mathbf{E}_P$ 更新到 service account state $\delta'$ 中**,如同公式 12.33 描述,其他公式均則在定義 12.33 相關的變數含意。 (12.33) ![image](https://hackmd.io/_uploads/HJD0tjlEJx.png) --- :::info (12.28) ![image](https://hackmd.io/_uploads/ry9zhux4kl.png) $\mathbf{E}_P$ 是一個由 $(\mathbb{N}_S, \mathbb{Y})$ pair 組成的序列 - $\mathbf{E}_P$: preimage (lookup extrinsic) - $\mathbb{N}_S$: service index - $\mathbb{Y}$: The set of octet strings/blobs - ==(待確認)目前還沒有完全理解,該 service 所請求的資料是什麼?== > [!Tip] > :cat: : (一個區塊中的) Extrisic preimage $\mathbf{E}_P$ 中,儲存了不同 service accounts 所請求的資料。 ::: :::info (12.29) ![image](https://hackmd.io/_uploads/Sy6vTdx4yg.png) $\mathbf{E}_P$ 是一個序列,使用 service index 進行排序,並且移除重複的資料 $\mathbb{Y}$ - $\mathbf{E}_P$: preimage (lookup extrinsic) - $i$: 在這個公式中,$i$ 代表 $(\mathbb{N}_S, \mathbb{Y})$ - 雙垂直波浪: 透過 $i$ 的 key (service index) 進行排序,並且移除重複的 $i$ value ($\mathbb{Y}$) ==:question:$\mathbf{E}_P$ 的案例中,element 為 $(\mathbb{N}_S, \mathbb{Y})$ 如何進行排序與刪除重複資料?== - 閱讀更多, 3.7.1. Construction ![image](https://hackmd.io/_uploads/HywCGfQE1e.png) > [!Tip] > :cat2: : Extrinsic preimage 中,不會存在重複的資料,並且 $\mathbf{E}_P$ 這個序列,會依照 service index 進行排序 ::: :::info (12.30) ![image](https://hackmd.io/_uploads/SJVXDilEyl.png) ![GPv0.6.0 (12.30)](https://hackmd.io/_uploads/Sy1ufLF_1l.png) > [!Tip] > :cat2: : $R$ 是一個函數, 用來確認某個 preimage 當前/更新前 (prior state) 還沒儲存於 service accounts $\mathbf{d}$ 中, 函數 $R$ 的輸出會是一個 `bool` > > $R$ 函數的兩個條件如下: > 1. service 的 preimage dictionary 找不到輸入的 preimage hash > 2. service 的 lookup dictionary 找不到 (preimage hash, preimage length) 所 mapping 到的資訊 > [!Caution] > 與 (12.23) selection function $R$ 不一致 > - $R$ 的參數數量與 12.23 定義 selection function $R$ 不同 > - 影片中的版本,preimage integration 為 12.1 章, 還沒有出現該 $R$ function - $\mathbf{d}$: service accounts dictionary (定義於 12.13) - 等同於 $\delta \in \mathbb{D} \langle {\mathbb{N}_S} \to {\mathbb{A}} \rangle$, 可參考 [9. service Accounts](https://hackmd.io/XWhIlQXVQqu0OqHjUH4MYA) 對於 $\mathbb{A}$ 的定義 - $s$: service index - $h$: preimage hash - $l$: preimage length ```python # (12.30) pseudo code def R(service_accounts, service_index, preimage_hash, preimage_length): # 輸入的 preimage hash 不在 service preimage dict 中 servcie_preimage_dict = service_accounts[service_idnex].preimage_dict bool condition_1 = preimage_hash not in service_preimage_dict.keys() # 輸入的 preimage hash and length, 無法於 service lookup dict 中找到對應資料 service_lookup_dict = service_accounts[service_index] service_lookup_key = tuple(preimage_hash, preimage_length) bool condition_2 = service_lookup_dict[service_lookup_key] == [] return condition_1 and condition_2 ``` ::: :::info (12.31) ![image](https://hackmd.io/_uploads/BJOr_jgNkx.png) 該公式在描述儲存在 Extrinsic 中的 preimage, 應該符合 $R$ 函數的條件: 1. 該 extrinsic preimage 不存在對應的 service ($s$) preimage dictionary ($\mathbf{a}_\mathbf{p}$) 中 2. 該 extrinsic preimage 不存在對應的 service ($s$) lookup dictionary ($\mathbf{a}_\mathbf{l}$) 中 > [!Tip] > :cat2: : 反過來說 > - Extrinsic preimage 資料是由 service 請求,但是在當前(更新前)的狀態(prior state)中還沒有被記錄。 > - 如果 preimage 已經存在於特定 service account 中,那麼他也不需要請求這個資料 (==應該會哪條件限制重複請求?不清楚 service 請求資料行為在哪個章節==) - $s$: service index - $\mathbf{p}$: preimage - $\delta$: service accounts dictinoary - $s$: service index - $\mathcal{H}(\mathbf{p})$: preimage hash - $|\mathbf{p}|$: preimage length ::: :::info (12.32) ![image](https://hackmd.io/_uploads/Bk9aFsgVJl.png) > [!Tip] > $\mathbf{P}$ 是一個集合, 代表 > - 集合元素為 $(s, \mathbf{p})$ pair > - 並且 $(s, \mathbf{p})$ 符合 $R$ 函數的條件 > - 在 accumulation 後的 service accounts $\delta^{\ddagger}$ 中,不存在該 $(s, \mathbf{p})$ - $\mathbf{P}$: 有用的/需要被使用的 preimage - $s$: service index - $\mathbf{p}$: preimage - $\delta^{\ddagger}$: 描述一個在 accumulation 後,on-transfer 之前的 service accounts 的狀態 ::: :::info (12.33) ![image](https://hackmd.io/_uploads/HJD0tjlEJx.png) 我們定義 $\delta'$ 來描述 integration 後的狀態, 並忽略不再需要的 preimage (不符合 $R$ 函數的條件) - $\delta'$: 是一個描述 integration 後 service accounts 的狀態 - $\delta^{\ddagger}$: 是一個描述 accumulation 後,on-transfer 之前的 service accounts 狀態 > [!Tip] > :dog: > - 該公式在定義如何更新 service account 中的 $\mathbf{p}$ 跟 $\mathbf{l}$ > - 如果這個 preimage 不存在於 accumulation 中使用的 service accounts 中, 就在該 service account 的 preimage dictionary 新增一筆 > - 如果這個 preimage 不存在於 accumulation 中使用的 service accounts 中, 就在該 service account 的 lookup dictionary 新增一筆 > - 之前在 9. Service Accounts 中,未提及 lookup dictionary 儲存的資訊,於此公式中的 $[\tau']$,將與 9. Service Accounts 中的 historical hookup function 處理邏輯有關 > - historical lookup function, 可以提供查詢某個 service 是否在某個時間點,可以存取到特定的 preimage > - 以此案例, $[\tau']$, 將會對應 historical lookup function 的 $I$ function (公式 9.7), 當 lookup dictionary value 長度為 1 時, 代表想要查詢的時間點大於等於 $\tau'$ 時,這個 service account 可以在 $\tau'$ 這個時間點後,存取到該 preimage ==不過其他長度的 lookup dictionary 的情況,在 (12.33) 中無法解釋, 於此公式中是直接指定長度為 1 的陣列 $[\tau']$== > > ![image](https://hackmd.io/_uploads/HJaYnaZN1x.png) ::: --- **以下內容尚未整理完成,思考關於整個 Extrinsic preimage 被使用的過程** > :cat2: : service 請求資料 :arrow_right: 某個 service 將資料放到下一個區塊 Extrinsic 中 :arrow_right: Accumulation 階段處理 :arrow_right: preimage integration 將更新相關資訊到 service account state 中 ==待確認== :rocket: : 定義了一個 $\delta'$, 代表在下一個時間點 $\tau'$, 該 service account 有資格存取該 preimage (這個 preimage 在前一個階段的 accumulation 並沒有被使用), 因為 in-core 階段,service 可能會需要使用到相關記錄於鏈上的資料, service 將會請求資料在 in-core 環境中進行使用 extrinsic 中的 preimage 如果不在該 accumulation service accounts $\delta^{\ddagger}$ 中的話, 我們就會更新 service accounts 中的 preimage dict 以及 lookup dict 的內容, 將其(preimage)加入。 Extrinsic preimage 中的資料,必須是之前由某個服務(service)請求過,但尚未在 **prior state** 中提供的(這意味著在之前的區塊中,服務尚未儲存或處理這些資料)。只有這些資料,才會在 **accumulation** 之後,經過整合(integration)過程,被納入 **posterior account state** 中,並成為下一個時間點中 in-core 環境可用的資料。 ### Appendix Accumulate 邏輯的執行: 第 12 章介紹了 work-report accumulation 的過程,其中系統會創建 PVM 實例來執行 work-report 中的 Accumulate 邏輯程式碼。 Gas 計量: PVM 的 gas 計量模型在 work-report accumulation 過程中被用於限制 Accumulate 邏輯的計算資源消耗量。 主機函數: Accumulate 邏輯程式碼可以調用 PVM 提供的主機函數來訪問和修改服務狀態,實現狀態更新。 ![Screenshot 2024-12-10 14.02.37](https://hackmd.io/_uploads/rJvsFUH41x.png) 公式 (A.1) 定義了 PVM 函數 Ψ,它是一個遞迴函數,用於模擬 PVM 的執行過程。 :::info Ψ 函數接受以下參數: p: 編碼好的整段程式(位元組blob)。 ι: gas 計數器,用於跟蹤剩余的 gas 量。 ρ: gas計數器,追蹤剩餘gas量。 ω: 寄存器 (register),用於存儲數據和中間結果。 μ: 內存 (memory),用於存儲程序代碼和數據。 Ψ 函數的輸出是一個包含以下元素的元組: ε: 退出原因,表示 PVM 執行結束的原因,例如正常退出、gas 不足、遇到錯誤等。 ι: 新的程序計數器。 ρ': 新的 gas 計數器。 ω': 新的寄存器。 μ': 新的內存。 Ψ 函數的遞歸定義如下: 如果 ε = ► (正常退出),則返回當前狀態 (p, ι, ρ, ω, μ)。 如果 ρ' < 0 (gas 不足),則返回 (∞, ι', ρ', ω', μ'),表示 gas 不足導致退出。 如果 ε ∈ {♯, ☇} (遇到陷阱或頁面錯誤),則返回 (ε, 0, ρ', ω', μ'),表示遇到錯誤導致退出,並將程序計數器設置為 0。 否則,使用 Ψ_1 函數計算新的狀態 (ε, ι', ρ', ω', μ'),並遞歸調用 Ψ 函數,繼續執行下一條指令。 其中,Ψ_1 函數用於執行單條 PVM 指令,並根據指令的類型和操作數更新 PVM 的狀態。 p = Ɛ(j) Ɛ_1(z) ~Ɛ(c) ~Ɛ(j) (c) Ɛ(k), k = |c| 這段公式用於計算下一條指令的地址,其中 Ɛ, Ɛ_1, j, z, c, k 都是與指令解碼和地址計算相關的變量。 總結 ::: 公式 (A.2) 定義了 skip 函數 skip 用於在 PVM 程式碼中定位下一條指令,確保程序計數器正確更新。 $(A.2)\ \ skip: \begin{cases} \mathbb{N} \longrightarrow \mathbb{N} \\ i \longmapsto \min (24, j \in \mathbb{N} : (k \cap [1,1,...])_{i+1+j} = 1) \end{cases}$ :::info skip: 一個函數,用於計算從當前指令的 opcode 到下一條指令的 opcode 的八位位組數減一。 i: 當前指令的 opcode 在指令數據 c 中的索引。 k: 指令 opcode 位元遮罩,用於標記哪些八位位組是 opcode。 j: 一個自然數,表示從當前指令的 opcode 開始搜索的八位位組數。 公式解析 skip(i) 的計算過程如下: 從當前指令的 opcode (i) 開始,在指令數據 c 中向後搜索。 找到第一個位元遮罩 k 中對應位元為 1 的八位位組,其索引為 i + 1 + j。 skip(i) 的值為 j,最大值不超過 24。 ::: $(A.3)\ \ \ \zeta = c ⌢ [0,0,...]$ :::info 說明 ζ : 相當於指令 c,但附加了一個無限的零序列,以防止程序計數器超出程式碼範圍。 c: PVM 程式碼的指令數據。 [0, 0, ...]: 一個無限的零序列。 ⌢ : 序列連接操作符,用於將兩個序列連接成一個新的序列。 公式解析 ζ 是將指令數據 c 與一個無限的零序列連接而成的。 總結 ζ 用於確保 PVM 在執行過程中不會發生越界訪問,提高程式碼的安全性。 ::: $(A.4)\ \ \varpi \equiv [0] \sim [n+1+skip(n) | n \in \mathbb{N}, n < |c|, k_n = 1 \land c_n \in T]$ :::info 說明 ϖ: 表示 basic block 的起始指令的 opcode 在指令數據 c 中的索引序列。 n: 指令數據 c 中的一個八位位組索引。 c: PVM 程式碼的指令數據。 k: 指令 opcode 位元遮罩,用於標記哪些八位位組是 opcode。 T: block termination instruction 的 opcode 的集合。 skip: 一個函數,用於計算從當前指令的 opcode 到下一條指令的 opcode 的八位位組數減一。 公式解析 ϖ 序列的生成過程如下: 首先將 0 加入 ϖ 序列,因為第一條指令總是 basic block 的起始指令。 遍歷指令數據 c 中的所有八位位組索引 n。 如果 k_n = 1 且 c_n ∈ T,則表示 n 是 basic block 的終止指令。 將 n + 1 + skip(n) 加入 ϖ 序列,表示下一條指令是 basic block 的起始指令。 總結: ϖ 序列記錄了 PVM 程式碼中所有 basic block 的起始指令的位置,用於控制流分析和程式碼優化。 ::: Test Flow: ``` JamTestVectorsRunner.Run() ├─ RunFnnc() │ └─ stf.UpdateAccumlate() │ ├─ accumulation.ProcessAccumulation() │ │ ├─ UpdateImmediatelyAccumulateWorkReports() // W! │ │ ├─ UpdateQueuedWorkReports() // WQ │ │ └─ UpdateAccumulatableWorkReports() // W* │ └─ accumulation.DeferredTransfers() │ ├─ executeOuterAccumulation() │ │ └─ OuterAccumulation() + PVM │ ├─ updateDeltaDoubleDagger() │ ├─ updateXi() │ └─ updateTheta() │ └─ Verify() └─ Validate() // 比對狀態與期望結果 ```