owned this note
owned this note
Published
Linked with GitHub
# 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 雜湊值
]

:::
$(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 的累積佇列
]

:::
在每個 timeslot 結束時,系統會執行以下操作:
- 將新的、需要延遲 accumulation 的 work-reports $W^Q$加入到 ϑ 中。
- 移除已經 accumulation 的 work-reports。
- 移除 dependencies 已經滿足的 work-reports。
在新 Epoch 開始時,系統會執行以下操作:
- 重新檢查 dependencies: 檢查 ϑ 中所有 work-reports 的 dependencies 是否已被滿足。
- 如果滿足,則將 work-report 從 ϑ 中移除,準備累積。
- 如果不滿足,則 work-report 繼續留在 ϑ 中等待。
- 如果不滿足且延遲超過一個 epoch 則 work-reports 被移除 (丟棄)。

$(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! 。
:::

$(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 數據上 的依賴,它需要導入這些區塊中的數據。
:::

$(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 中移除。
:::

$(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})\}$

:::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 的交易雜湊值
}
```
:::


:::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 項任務 (邀請嘉賓、會場佈置、設計宣傳海報)。
你更新了展覽的籌備狀態,例如:嘉賓名單確定了、會場佈置完成了、海報設計好了。
你記錄了延遲的任務:安排演講和撰寫新聞稿。
```




:::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 信息。
:::

$(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 函數可能需要的其他輸入數據。
:::




:::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. 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})$,


:::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

-->
$\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
:::
---


---
定義 selection function $R$,用於整合 deferred transfers 的 state
- 映射後會根據 source service index 排序再根據在 $\rm{t}$ 中的位置排序。
- $\rm{t}$ 排序是根據 source service 執行順序


---
State Integration(狀態整合) :



:::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)
:::
---



---
更新歷史紀錄($\xi$)

:::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

<!--
$\vartheta^{\prime \circlearrowleft}_{m-i} = \vartheta^{\prime}[m-i \% |\vartheta^{\prime}|]$
-->

:::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)

---
:::info
(12.28)

$\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)

$\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

> [!Tip]
> :cat2: : Extrinsic preimage 中,不會存在重複的資料,並且 $\mathbf{E}_P$ 這個序列,會依照 service index 進行排序
:::
:::info
(12.30)


> [!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)

該公式在描述儲存在 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)

> [!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)

我們定義 $\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']$==
>
> 
:::
---
**以下內容尚未整理完成,思考關於整個 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 提供的主機函數來訪問和修改服務狀態,實現狀態更新。

公式 (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() // 比對狀態與期望結果
```