diff --git a/crates/modules-interfaces/src/domain/fees/mod.rs b/crates/modules-interfaces/src/domain/fees/mod.rs index a533d37..9a97fe3 100644 --- a/crates/modules-interfaces/src/domain/fees/mod.rs +++ b/crates/modules-interfaces/src/domain/fees/mod.rs @@ -77,7 +77,7 @@ pub struct MessageAllocationNode { pub recipient: Option, /// `None` means any call key; the node converts the chain's wildcard sentinel. pub call_key: Option, - /// Available allowance; zero is exhausted, `None` is uncapped. + /// Stored chain budget, or a synthetic wildcard's allowance; `None` is uncapped. pub budget: Option, pub on: On, pub fee_params: MessageAllocationNodeParams, diff --git a/docs/website/src/impl-spec/04-fees.rst b/docs/website/src/impl-spec/04-fees.rst index 86f616a..fe7724a 100644 --- a/docs/website/src/impl-spec/04-fees.rst +++ b/docs/website/src/impl-spec/04-fees.rst @@ -289,8 +289,8 @@ For internal messages, ``on`` is checked after the allocation key is resolved, s phase mismatch on an exact allocation does not fall through to a wildcard. Chain keys are unique across phases; only synthetic recipient-wildcard entries may select different fee parameters by phase. For -external messages, an exhausted exact allocation spills to the per-recipient -``call_key`` wildcard. If neither key has an allocation, the external message uses +external messages, an exact allocation without room for the reservation spills to +the per-recipient ``call_key`` wildcard. If neither key has a present allocation, the external message uses the legacy unallocated path and consumes only its receipt cost. Existing but exhausted candidates yield an allocation-budget error. @@ -298,16 +298,19 @@ The default v0.3 fee expressions reject external reservations and receipts with ``fee below_minimum`` unless ``node.lockedReceiptGasPrice`` is positive, including external messages without a matching allocation -Entry presence determines matching, independently of ``budget``. The host supplies -the allowance available at execution start, optionally reduced by prior consumption. -Zero means an exhausted allocation; ``null`` removes the per-allocation cap while -keeping the execution's fee buckets. Local consumption is tracked separately. -An exhausted internal exact key still wins and fails its budget check; it never -falls through. An absent chain allocation (including a chain record whose original -budget is zero) must be omitted, not represented by an exhausted entry. - -The host must preserve every existing pinned key, including exhausted keys, and -must not add recipient wildcards to a pinned tree. An empty list restricts internal +Chain entries, those with a concrete ``recipient``, carry the budget stored on +chain. Consensus resolves only keys with a nonzero budget, so a chain entry whose +``budget`` is zero is absent: the message falls through to the per-recipient +``call_key`` wildcard, and with no wildcard left an internal message fails with +``fee no_matching_allocation`` while an external one takes the unallocated path. +Synthetic recipient wildcards match independently of ``budget``; zero there means +an exhausted allocation. ``null`` removes the per-allocation cap while keeping the +execution's fee buckets. Local consumption is tracked separately: an internal key +exhausted by this execution's own emissions still wins and fails its budget check; +it never falls through. + +The host must preserve every existing pinned key and must not add recipient +wildcards to a pinned tree. An empty list restricts internal pool-funded emissions. Open-pool and view executions may supply synthetic recipient wildcards with concrete fee parameters and phase, and optionally uncapped budgets. The executor conservatively treats each emission as novel; remaining allowances diff --git a/docs/website/src/impl-spec/appendix/manager-api.yaml b/docs/website/src/impl-spec/appendix/manager-api.yaml index 36e5bc7..17346a3 100644 --- a/docs/website/src/impl-spec/appendix/manager-api.yaml +++ b/docs/website/src/impl-spec/appendix/manager-api.yaml @@ -889,7 +889,7 @@ components: description: Call key bytes, or null for a wildcard. budget: nullable: true - description: Available allowance at execution start; zero is exhausted, null is uncapped. Does not affect key matching. + description: Stored chain budget, or the allowance of a synthetic recipient wildcard; null is uncapped. A zero-budget entry with a recipient is absent, as on chain. on: type: string enum: [decided, finalized] @@ -907,8 +907,7 @@ components: unchanged and meters their length. External and open allocations without a committed subtree use empty bytes. children_budget and subtree are required on every entry, including allocations without descendants. - Include exhausted allocations with budget zero to preserve internal key - precedence; omit allocations absent on-chain. Recipient wildcards are + Omit allocations absent on-chain. Recipient wildcards are synthetic entries for open-pool or view execution, not chain allocations. record_actions: type: array diff --git a/executors/v0.3.x b/executors/v0.3.x index 16b8173..f7f95a3 160000 --- a/executors/v0.3.x +++ b/executors/v0.3.x @@ -1 +1 @@ -Subproject commit 16b81732e12117daf7ef0335cbd32fc7d326b16d +Subproject commit f7f95a31dddbef2aa9371e2228644f83dcce9fe3