From b7b894cbae49e2ad75cc497c74f3fa5cd2f450fc Mon Sep 17 00:00:00 2001 From: apenzk Date: Fri, 12 Dec 2025 16:12:17 +0100 Subject: [PATCH 1/4] init --- MIP/mip-x/README.md | 110 ++++++++++++++++++++ MIP/mip-x/txt.md | 244 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+) create mode 100644 MIP/mip-x/README.md create mode 100644 MIP/mip-x/txt.md diff --git a/MIP/mip-x/README.md b/MIP/mip-x/README.md new file mode 100644 index 00000000..db7f44f4 --- /dev/null +++ b/MIP/mip-x/README.md @@ -0,0 +1,110 @@ +# MIP-\: \ + +- **Description**: A single sentence summarizing the contents of the proposal. +- **Authors**: [Author](mailto:author@email.com) +- **Desiderata**: [MD-\](../MD/md-\) +- **Approval**: + + + +## Abstract + + + +## Motivation + + + +## Specification + + + +_The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174._ + +## Reference implementation + + + +## Verification + + + +Needs discussion. + +## Appendix + + +### A1 + +Nothing important here. + +## Changelog + + diff --git a/MIP/mip-x/txt.md b/MIP/mip-x/txt.md new file mode 100644 index 00000000..0c7da970 --- /dev/null +++ b/MIP/mip-x/txt.md @@ -0,0 +1,244 @@ +# Mvmt ↔ Remote Rate Limiting — Current Status + +This document explains where rate limits live, which functions touch them, and +how the baseline and proposed alternatives behave with respect to bidirectional +offsetting and Movement inflow risk. + +## Design Context + +Bidirectional offsetting (where outflows release inflow capacity and vice versa) is a feature for systems that track **net exposure** or **net supply movement**. If 100M flows out and 100M flows in, the net change is zero, and the rate limit correctly reflects this. + +This proposal **intentionally rejects offsetting** as a design choice. The security goal for Movement is to enforce a **strict, non-offsettable gross inflow cap**. Inflow capacity should not increase just because funds flowed out—even if net exposure remains unchanged. + +The alternatives below represent a conscious tradeoff: abandoning net-flow semantics to achieve a hard ceiling on gross inflow. + +--- + +## Legend + +- `mvmt.*` → code executing on Movement +- `remote.*` → code executing on a remote chain (e.g. Ethereum) +- `source.*` / `dest.*` → code executing on the respective chain +- `X.rate_limit[from:Y, to:Z]` → rate limit stored on chain X for transfers from Y to Z +- `dst_eid` → destination endpoint id +- `src_eid` → source endpoint id +- `mvmt_eid` → Movement endpoint id +- ↓ consume capacity +- ↑ release capacity + +--- + +## BASELINE (Current Production) + +**Rule (applies symmetrically on all chains)** + +- `source.debit`: `source.try_consume_rate_limit(dst_eid)` +- `dest.credit`: `dest.release_rate_limit(src_eid)` + +Each chain enforces only its own local rate limits. + +```mermaid +flowchart LR + User --> source.debit + + subgraph Source["Source Chain"] + source.debit --> consume_dst["source.try_consume_rate_limit(dst_eid)"] + consume_dst --> source_rl_dst["source.rate_limit[from:source, to:dest] ↓"] + end + + source.debit --> send["send LZ message"] + send --> dest.credit + + subgraph Dest["Dest Chain"] + dest.credit --> release_src["dest.release_rate_limit(src_eid)"] + release_src --> dest_rl_src["dest.rate_limit[from:dest, to:source] ↑"] + end +``` + +**Baseline Behavior: Net-flow accounting via bidirectional offsetting** + +```text +Mvmt → Remote: + mvmt.rate_limit[from:mvmt, to:remote] ↓ + remote.rate_limit[from:remote, to:mvmt] ↑ + +Remote → Mvmt: + remote.rate_limit[from:remote, to:mvmt] ↓ + mvmt.rate_limit[from:mvmt, to:remote] ↑ +``` + +Outgoing flow creates incoming capacity and vice versa. This is correct net-flow accounting, but it means Movement inflow caps can grow beyond the configured limit if outflows occur. + +--- + +## ALTERNATIVE 1 (Mvmt-Centric, Supply-Coupled) + +**Idea** + +- Remove rate limiters from foreign chains entirely +- All rate limiting happens on Movement +- Outflows release Movement inflow capacity (supply-coupled) + +**Rule (Movement only)** + +- `mvmt.debit`: `mvmt.try_consume_rate_limit(dst_eid)` + `mvmt.release_rate_limit(mvmt_eid)` +- `mvmt.credit`: `mvmt.try_consume_rate_limit(mvmt_eid)` + `mvmt.release_rate_limit(src_eid)` + +**Mvmt → Remote (Outgoing)** + +```mermaid +flowchart LR + User --> mvmt.debit + + subgraph Mvmt + mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit(dst_eid)"] + consume_dst --> mvmt_rl_remote["mvmt.rate_limit[from:mvmt, to:remote] ↓"] + mvmt.debit --> release_mvmt["mvmt.release_rate_limit(mvmt_eid)"] + release_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit[from:remote, to:mvmt] ↑"] + end + + mvmt.debit --> send["send LZ message"] + send --> remote.credit + + subgraph Remote + remote.credit + end +``` + +**Remote → Mvmt (Incoming)** + +```mermaid +flowchart LR + User --> remote.debit + + subgraph Remote + remote.debit + end + + remote.debit --> send["send LZ message"] + send --> mvmt.credit + + subgraph Mvmt + mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit(mvmt_eid)"] + consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit[from:remote, to:mvmt] ↓"] + mvmt.credit --> release_src["mvmt.release_rate_limit(src_eid)"] + release_src --> mvmt_rl_remote["mvmt.rate_limit[from:mvmt, to:remote] ↑"] + end +``` + +**Behavior: Bidirectional offsetting preserved** + +```text +Mvmt → Remote: + mvmt.rate_limit[from:mvmt, to:remote] ↓ + mvmt.rate_limit[from:remote, to:mvmt] ↑ ← outflow increases inflow capacity + +Remote → Mvmt: + mvmt.rate_limit[from:remote, to:mvmt] ↓ + mvmt.rate_limit[from:mvmt, to:remote] ↑ ← inflow increases outflow capacity +``` + +If 100M flows out and 100M flows in, both limits return to their original values. This is valid net-flow accounting, but incompatible with the goal of a strict gross inflow cap. + +Alternative 1 preserves net-flow semantics, which are incompatible with the desired non-offsettable inflow limit. + +--- + +## ALTERNATIVE 2 (Mvmt-Centric, No Releases) + +**Idea** + +- Same as Alternative 1, but remove all `release_rate_limit` calls +- Only consume capacity, never release +- Outflows cannot increase inflow capacity + +**Rule (Movement only)** + +- `mvmt.debit`: `mvmt.try_consume_rate_limit(dst_eid)` only +- `mvmt.credit`: `mvmt.try_consume_rate_limit(mvmt_eid)` only + +**Mvmt → Remote (Outgoing)** + +```mermaid +flowchart LR + User --> mvmt.debit + + subgraph Mvmt + mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit(dst_eid)"] + consume_dst --> mvmt_rl_remote["mvmt.rate_limit[from:mvmt, to:remote] ↓"] + end + + mvmt.debit --> send["send LZ message"] + send --> remote.credit + + subgraph Remote + remote.credit + end +``` + +**Remote → Mvmt (Incoming)** + +```mermaid +flowchart LR + User --> remote.debit + + subgraph Remote + remote.debit + end + + remote.debit --> send["send LZ message"] + send --> mvmt.credit + + subgraph Mvmt + mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit(mvmt_eid)"] + consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit[from:remote, to:mvmt] ↓"] + end +``` + +**Behavior: No bidirectional offsetting (gross inflow cap enforced)** + +```text +Mvmt → Remote: + mvmt.rate_limit[from:mvmt, to:remote] ↓ + (no release) + +Remote → Mvmt: + mvmt.rate_limit[from:remote, to:mvmt] ↓ + (no release) +``` + +Limits only decrease. Capacity replenishes over time, not through offsetting flows. + +**Where Rate Limits Live** + +| Flow Direction | Enforced On | Storage | +|---------------|------------|---------| +| Remote → Mvmt | Mvmt | `mvmt.rate_limit[from:remote, to:mvmt]` | +| Mvmt → Remote | Mvmt | `mvmt.rate_limit[from:mvmt, to:remote]` | +| Cross-offset | ❌ | ❌ | + +**Security Invariant** + +```text +For all time t: + total_inflow_to_mvmt(t) ≤ mvmt.rate_limit[from:remote, to:mvmt] +``` + +--- + +## Summary + +**Baseline:** +- Mvmt→Remote: `mvmt.rate_limit[from:mvmt, to:remote] ↓`, `remote.rate_limit[from:remote, to:mvmt] ↑` +- Remote→Mvmt: `remote.rate_limit[from:remote, to:mvmt] ↓`, `mvmt.rate_limit[from:mvmt, to:remote] ↑` +- Behavior: Net-flow accounting with offsetting across chains. Valid, but incompatible with gross inflow cap goal. + +**Alternative 1:** +- Mvmt→Remote: `mvmt.rate_limit[from:mvmt, to:remote] ↓`, `mvmt.rate_limit[from:remote, to:mvmt] ↑` +- Remote→Mvmt: `mvmt.rate_limit[from:remote, to:mvmt] ↓`, `mvmt.rate_limit[from:mvmt, to:remote] ↑` +- Behavior: All on Mvmt, but preserves net-flow semantics. Still incompatible with gross inflow cap goal. + +**Alternative 2:** +- Mvmt→Remote: `mvmt.rate_limit[from:mvmt, to:remote] ↓` +- Remote→Mvmt: `mvmt.rate_limit[from:remote, to:mvmt] ↓` +- Behavior: All on Mvmt, no releases, no offsetting. Enforces strict gross inflow cap. From db7d3f94c4c949e18a441a253d00f862788c12ad Mon Sep 17 00:00:00 2001 From: apenzk Date: Fri, 12 Dec 2025 16:16:48 +0100 Subject: [PATCH 2/4] incorporate to mip --- MIP/mip-x/README.md | 279 ++++++++++++++++++++++++++++++++++---------- MIP/mip-x/txt.md | 244 -------------------------------------- 2 files changed, 218 insertions(+), 305 deletions(-) delete mode 100644 MIP/mip-x/txt.md diff --git a/MIP/mip-x/README.md b/MIP/mip-x/README.md index db7f44f4..b9564cb0 100644 --- a/MIP/mip-x/README.md +++ b/MIP/mip-x/README.md @@ -1,110 +1,267 @@ -# MIP-\: \ +# MIP-X: Non-Offsettable Gross Inflow Rate Limiting -- **Description**: A single sentence summarizing the contents of the proposal. -- **Authors**: [Author](mailto:author@email.com) -- **Desiderata**: [MD-\](../MD/md-\) +- **Description**: Replace net-flow rate limiting with a strict gross inflow cap on Movement. +- **Authors**: [Primata](), Ru, Andreas +- **Desiderata**: TBD - **Approval**: - +## Design Context -## Abstract +Bidirectional offsetting (where outflows release inflow capacity and vice versa) is a feature for systems that track **net exposure** or **net supply movement**. If 100M flows out and 100M flows in, the net change is zero, and the rate limit correctly reflects this. - +The alternatives below represent a conscious tradeoff: abandoning net-flow semantics to achieve a hard ceiling on gross inflow. -## Motivation +## Specification - +### Legend -## Specification +- `mvmt.*` → code executing on Movement +- `remote.*` → code executing on a remote chain (e.g. Ethereum) +- `source.*` / `dest.*` → code executing on the respective chain +- `X.rate_limit_budget[from:Y, to:Z]` → rate limit budget stored on chain X for transfers from Y to Z +- `dst_eid` → destination endpoint id +- `src_eid` → source endpoint id +- `mvmt_eid` → Movement endpoint id +- ↓ consume capacity +- ↑ release capacity - +**Rule (applies symmetrically on all chains)** -_The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174._ +- `source.debit`: `source.try_consume_rate_limit(dst_eid)` +- `dest.credit`: `dest.release_rate_limit(src_eid)` -## Reference implementation +Each chain enforces only its own local rate limits. - source.debit - TODO: Remove this comment before submitting ---> + subgraph Source["Source Chain"] + source.debit --> consume_dst["source.try_consume_rate_limit(dst_eid)"] + consume_dst --> source_rl_dst["source.rate_limit_budget[from:source, to:dest] ↓"] + end -## Verification + source.debit --> send["send LZ message"] + send --> dest.credit - release_src["dest.release_rate_limit(src_eid)"] + release_src --> dest_rl_src["dest.rate_limit_budget[from:dest, to:source] ↑"] + end +``` - All proposals must contain a section that discusses the various aspects of verification pertinent to the introduced changes. This section should address: +**Baseline Behavior: Net-flow accounting via bidirectional offsetting** - 1. **Correctness**: Ensure that the proposed changes behave as expected in all scenarios. Highlight any tests, simulations, or proofs done to validate the correctness of the changes. +```text +Mvmt → Remote: + mvmt.rate_limit_budget[from:mvmt, to:remote] ↓ + remote.rate_limit_budget[from:remote, to:mvmt] ↑ - 2. **Security Implications**: Address the potential security ramifications of the proposal. This includes discussing security-relevant design decisions, potential vulnerabilities, important discussions, implementation-specific guidance, and pitfalls. Mention any threats, risks, and mitigation strategies associated with the proposal. +Remote → Mvmt: + remote.rate_limit_budget[from:remote, to:mvmt] ↓ + mvmt.rate_limit_budget[from:mvmt, to:remote] ↑ +``` - 3. **Performance Impacts**: Outline any performance tests conducted and the impact of the proposal on system performance. This could be in terms of speed, resource consumption, or other relevant metrics. +Outgoing flow creates incoming capacity and vice versa. This is correct net-flow accounting, but it means Movement inflow caps can grow beyond the configured limit if outflows occur. - 4. **Validation Procedures**: Describe any procedures, tools, or methodologies used to validate the proposal against its requirements or objectives. +--- - 5. **Peer Review and Community Feedback**: Highlight any feedback from peer reviews or the community that played a crucial role in refining the verification process or the proposal itself. +### ALTERNATIVE 1 (Mvmt-Centric, Supply-Coupled) +**Idea** - TODO: Remove this comment before submitting ---> +- Remove rate limiters from foreign chains entirely +- All rate limiting happens on Movement +- Outflows release Movement inflow capacity (supply-coupled) -Needs discussion. +**Rule (Movement only)** -## Appendix - mvmt.debit ---> + subgraph Mvmt + mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit(dst_eid)"] + consume_dst --> mvmt_rl_remote["mvmt.rate_limit_budget[from:mvmt, to:remote] ↓"] + mvmt.debit --> release_mvmt["mvmt.release_rate_limit(mvmt_eid)"] + release_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget[from:remote, to:mvmt] ↑"] + end -### A1 + mvmt.debit --> send["send LZ message"] + send --> remote.credit -Nothing important here. + subgraph Remote + remote.credit + end +``` -## Changelog +**Remote → Mvmt (Incoming)** - remote.debit + + subgraph Remote + remote.debit + end + + remote.debit --> send["send LZ message"] + send --> mvmt.credit + + subgraph Mvmt + mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit(mvmt_eid)"] + consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget[from:remote, to:mvmt] ↓"] + mvmt.credit --> release_src["mvmt.release_rate_limit(src_eid)"] + release_src --> mvmt_rl_remote["mvmt.rate_limit_budget[from:mvmt, to:remote] ↑"] + end +``` + +**Behavior: Bidirectional offsetting preserved** + +```text +Mvmt → Remote: + mvmt.rate_limit_budget[from:mvmt, to:remote] ↓ + mvmt.rate_limit_budget[from:remote, to:mvmt] ↑ ← outflow increases inflow capacity + +Remote → Mvmt: + mvmt.rate_limit_budget[from:remote, to:mvmt] ↓ + mvmt.rate_limit_budget[from:mvmt, to:remote] ↑ ← inflow increases outflow capacity +``` + +If 100M flows out and 100M flows in, both limits return to their original values. This is valid net-flow accounting, but incompatible with the goal of a strict gross inflow cap. + +Alternative 1 preserves net-flow semantics, which are incompatible with the desired non-offsettable inflow limit. - 1. **Transparency and Clarity**: The Changelog acknowledges any corrections made post-publication, ensuring that readers are not misled and are always equipped with the most accurate information. +--- - 2. **Accountability**: By noting changes openly, we maintain a high level of responsibility and ownership over our content. It’s an affirmation that we value precision and are ready to correct oversights. +### ALTERNATIVE 2 (Mvmt-Centric, No Releases) - Each Changelog should briefly describe each change made, accompanied by a reference to the date, version and PR in which the change was implemented. +**Idea** + +- Same as Alternative 1, but remove all `release_rate_limit` calls +- Only consume capacity, never release +- Outflows cannot increase inflow capacity + +**Rule (Movement only)** + +- `mvmt.debit`: `mvmt.try_consume_rate_limit(dst_eid)` only +- `mvmt.credit`: `mvmt.try_consume_rate_limit(mvmt_eid)` only + +**Mvmt → Remote (Outgoing)** + +```mermaid +flowchart LR + User --> mvmt.debit + + subgraph Mvmt + mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit(dst_eid)"] + consume_dst --> mvmt_rl_remote["mvmt.rate_limit_budget[from:mvmt, to:remote] ↓"] + end + + mvmt.debit --> send["send LZ message"] + send --> remote.credit + + subgraph Remote + remote.credit + end +``` + +**Remote → Mvmt (Incoming)** + +```mermaid +flowchart LR + User --> remote.debit + + subgraph Remote + remote.debit + end + + remote.debit --> send["send LZ message"] + send --> mvmt.credit + + subgraph Mvmt + mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit(mvmt_eid)"] + consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget[from:remote, to:mvmt] ↓"] + end +``` + +**Behavior: No bidirectional offsetting (gross inflow cap enforced)** + +```text +Mvmt → Remote: + mvmt.rate_limit_budget[from:mvmt, to:remote] ↓ + (no release) + +Remote → Mvmt: + mvmt.rate_limit_budget[from:remote, to:mvmt] ↓ + (no release) +``` + +Limits only decrease. Capacity replenishes daily (rate limit resets), not through offsetting flows. + +**Where Rate Limits Live** + +| Flow Direction | Enforced On | Storage | +|---------------|------------|---------| +| Remote → Mvmt | Mvmt | `mvmt.rate_limit_budget[from:remote, to:mvmt]` | +| Mvmt → Remote | Mvmt | `mvmt.rate_limit_budget[from:mvmt, to:remote]` | +| Cross-offset | ❌ | ❌ | + +**Security Invariant** + +```text +For all time t: + total_inflow_to_mvmt(t) ≤ mvmt.rate_limit_budget[from:remote, to:mvmt] +``` + +--- + +### Summary + +**Baseline:** +- Mvmt→Remote: `mvmt.rate_limit_budget[from:mvmt, to:remote] ↓`, `remote.rate_limit_budget[from:remote, to:mvmt] ↑` +- Remote→Mvmt: `remote.rate_limit_budget[from:remote, to:mvmt] ↓`, `mvmt.rate_limit_budget[from:mvmt, to:remote] ↑` +- Behavior: Net-flow accounting with offsetting across chains. Valid, but incompatible with gross inflow cap goal. + +**Alternative 1:** +- Mvmt→Remote: `mvmt.rate_limit_budget[from:mvmt, to:remote] ↓`, `mvmt.rate_limit_budget[from:remote, to:mvmt] ↑` +- Remote→Mvmt: `mvmt.rate_limit_budget[from:remote, to:mvmt] ↓`, `mvmt.rate_limit_budget[from:mvmt, to:remote] ↑` +- Behavior: All on Mvmt, but preserves net-flow semantics. Still incompatible with gross inflow cap goal. + +**Alternative 2:** +- Mvmt→Remote: `mvmt.rate_limit_budget[from:mvmt, to:remote] ↓` +- Remote→Mvmt: `mvmt.rate_limit_budget[from:remote, to:mvmt] ↓` +- Behavior: All on Mvmt, no releases, no offsetting. Enforces strict gross inflow cap. + +## Changelog + + diff --git a/MIP/mip-x/txt.md b/MIP/mip-x/txt.md deleted file mode 100644 index 0c7da970..00000000 --- a/MIP/mip-x/txt.md +++ /dev/null @@ -1,244 +0,0 @@ -# Mvmt ↔ Remote Rate Limiting — Current Status - -This document explains where rate limits live, which functions touch them, and -how the baseline and proposed alternatives behave with respect to bidirectional -offsetting and Movement inflow risk. - -## Design Context - -Bidirectional offsetting (where outflows release inflow capacity and vice versa) is a feature for systems that track **net exposure** or **net supply movement**. If 100M flows out and 100M flows in, the net change is zero, and the rate limit correctly reflects this. - -This proposal **intentionally rejects offsetting** as a design choice. The security goal for Movement is to enforce a **strict, non-offsettable gross inflow cap**. Inflow capacity should not increase just because funds flowed out—even if net exposure remains unchanged. - -The alternatives below represent a conscious tradeoff: abandoning net-flow semantics to achieve a hard ceiling on gross inflow. - ---- - -## Legend - -- `mvmt.*` → code executing on Movement -- `remote.*` → code executing on a remote chain (e.g. Ethereum) -- `source.*` / `dest.*` → code executing on the respective chain -- `X.rate_limit[from:Y, to:Z]` → rate limit stored on chain X for transfers from Y to Z -- `dst_eid` → destination endpoint id -- `src_eid` → source endpoint id -- `mvmt_eid` → Movement endpoint id -- ↓ consume capacity -- ↑ release capacity - ---- - -## BASELINE (Current Production) - -**Rule (applies symmetrically on all chains)** - -- `source.debit`: `source.try_consume_rate_limit(dst_eid)` -- `dest.credit`: `dest.release_rate_limit(src_eid)` - -Each chain enforces only its own local rate limits. - -```mermaid -flowchart LR - User --> source.debit - - subgraph Source["Source Chain"] - source.debit --> consume_dst["source.try_consume_rate_limit(dst_eid)"] - consume_dst --> source_rl_dst["source.rate_limit[from:source, to:dest] ↓"] - end - - source.debit --> send["send LZ message"] - send --> dest.credit - - subgraph Dest["Dest Chain"] - dest.credit --> release_src["dest.release_rate_limit(src_eid)"] - release_src --> dest_rl_src["dest.rate_limit[from:dest, to:source] ↑"] - end -``` - -**Baseline Behavior: Net-flow accounting via bidirectional offsetting** - -```text -Mvmt → Remote: - mvmt.rate_limit[from:mvmt, to:remote] ↓ - remote.rate_limit[from:remote, to:mvmt] ↑ - -Remote → Mvmt: - remote.rate_limit[from:remote, to:mvmt] ↓ - mvmt.rate_limit[from:mvmt, to:remote] ↑ -``` - -Outgoing flow creates incoming capacity and vice versa. This is correct net-flow accounting, but it means Movement inflow caps can grow beyond the configured limit if outflows occur. - ---- - -## ALTERNATIVE 1 (Mvmt-Centric, Supply-Coupled) - -**Idea** - -- Remove rate limiters from foreign chains entirely -- All rate limiting happens on Movement -- Outflows release Movement inflow capacity (supply-coupled) - -**Rule (Movement only)** - -- `mvmt.debit`: `mvmt.try_consume_rate_limit(dst_eid)` + `mvmt.release_rate_limit(mvmt_eid)` -- `mvmt.credit`: `mvmt.try_consume_rate_limit(mvmt_eid)` + `mvmt.release_rate_limit(src_eid)` - -**Mvmt → Remote (Outgoing)** - -```mermaid -flowchart LR - User --> mvmt.debit - - subgraph Mvmt - mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit(dst_eid)"] - consume_dst --> mvmt_rl_remote["mvmt.rate_limit[from:mvmt, to:remote] ↓"] - mvmt.debit --> release_mvmt["mvmt.release_rate_limit(mvmt_eid)"] - release_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit[from:remote, to:mvmt] ↑"] - end - - mvmt.debit --> send["send LZ message"] - send --> remote.credit - - subgraph Remote - remote.credit - end -``` - -**Remote → Mvmt (Incoming)** - -```mermaid -flowchart LR - User --> remote.debit - - subgraph Remote - remote.debit - end - - remote.debit --> send["send LZ message"] - send --> mvmt.credit - - subgraph Mvmt - mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit(mvmt_eid)"] - consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit[from:remote, to:mvmt] ↓"] - mvmt.credit --> release_src["mvmt.release_rate_limit(src_eid)"] - release_src --> mvmt_rl_remote["mvmt.rate_limit[from:mvmt, to:remote] ↑"] - end -``` - -**Behavior: Bidirectional offsetting preserved** - -```text -Mvmt → Remote: - mvmt.rate_limit[from:mvmt, to:remote] ↓ - mvmt.rate_limit[from:remote, to:mvmt] ↑ ← outflow increases inflow capacity - -Remote → Mvmt: - mvmt.rate_limit[from:remote, to:mvmt] ↓ - mvmt.rate_limit[from:mvmt, to:remote] ↑ ← inflow increases outflow capacity -``` - -If 100M flows out and 100M flows in, both limits return to their original values. This is valid net-flow accounting, but incompatible with the goal of a strict gross inflow cap. - -Alternative 1 preserves net-flow semantics, which are incompatible with the desired non-offsettable inflow limit. - ---- - -## ALTERNATIVE 2 (Mvmt-Centric, No Releases) - -**Idea** - -- Same as Alternative 1, but remove all `release_rate_limit` calls -- Only consume capacity, never release -- Outflows cannot increase inflow capacity - -**Rule (Movement only)** - -- `mvmt.debit`: `mvmt.try_consume_rate_limit(dst_eid)` only -- `mvmt.credit`: `mvmt.try_consume_rate_limit(mvmt_eid)` only - -**Mvmt → Remote (Outgoing)** - -```mermaid -flowchart LR - User --> mvmt.debit - - subgraph Mvmt - mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit(dst_eid)"] - consume_dst --> mvmt_rl_remote["mvmt.rate_limit[from:mvmt, to:remote] ↓"] - end - - mvmt.debit --> send["send LZ message"] - send --> remote.credit - - subgraph Remote - remote.credit - end -``` - -**Remote → Mvmt (Incoming)** - -```mermaid -flowchart LR - User --> remote.debit - - subgraph Remote - remote.debit - end - - remote.debit --> send["send LZ message"] - send --> mvmt.credit - - subgraph Mvmt - mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit(mvmt_eid)"] - consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit[from:remote, to:mvmt] ↓"] - end -``` - -**Behavior: No bidirectional offsetting (gross inflow cap enforced)** - -```text -Mvmt → Remote: - mvmt.rate_limit[from:mvmt, to:remote] ↓ - (no release) - -Remote → Mvmt: - mvmt.rate_limit[from:remote, to:mvmt] ↓ - (no release) -``` - -Limits only decrease. Capacity replenishes over time, not through offsetting flows. - -**Where Rate Limits Live** - -| Flow Direction | Enforced On | Storage | -|---------------|------------|---------| -| Remote → Mvmt | Mvmt | `mvmt.rate_limit[from:remote, to:mvmt]` | -| Mvmt → Remote | Mvmt | `mvmt.rate_limit[from:mvmt, to:remote]` | -| Cross-offset | ❌ | ❌ | - -**Security Invariant** - -```text -For all time t: - total_inflow_to_mvmt(t) ≤ mvmt.rate_limit[from:remote, to:mvmt] -``` - ---- - -## Summary - -**Baseline:** -- Mvmt→Remote: `mvmt.rate_limit[from:mvmt, to:remote] ↓`, `remote.rate_limit[from:remote, to:mvmt] ↑` -- Remote→Mvmt: `remote.rate_limit[from:remote, to:mvmt] ↓`, `mvmt.rate_limit[from:mvmt, to:remote] ↑` -- Behavior: Net-flow accounting with offsetting across chains. Valid, but incompatible with gross inflow cap goal. - -**Alternative 1:** -- Mvmt→Remote: `mvmt.rate_limit[from:mvmt, to:remote] ↓`, `mvmt.rate_limit[from:remote, to:mvmt] ↑` -- Remote→Mvmt: `mvmt.rate_limit[from:remote, to:mvmt] ↓`, `mvmt.rate_limit[from:mvmt, to:remote] ↑` -- Behavior: All on Mvmt, but preserves net-flow semantics. Still incompatible with gross inflow cap goal. - -**Alternative 2:** -- Mvmt→Remote: `mvmt.rate_limit[from:mvmt, to:remote] ↓` -- Remote→Mvmt: `mvmt.rate_limit[from:remote, to:mvmt] ↓` -- Behavior: All on Mvmt, no releases, no offsetting. Enforces strict gross inflow cap. From 78ead9e39688ab0dded74cf6d064cfd05ceb485f Mon Sep 17 00:00:00 2001 From: apenzk Date: Mon, 15 Dec 2025 17:10:55 +0100 Subject: [PATCH 3/4] improve formats of diagrams --- MIP/mip-x/README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/MIP/mip-x/README.md b/MIP/mip-x/README.md index b9564cb0..a9e8c35b 100644 --- a/MIP/mip-x/README.md +++ b/MIP/mip-x/README.md @@ -55,16 +55,16 @@ flowchart LR User --> source.debit subgraph Source["Source Chain"] - source.debit --> consume_dst["source.try_consume_rate_limit(dst_eid)"] - consume_dst --> source_rl_dst["source.rate_limit_budget[from:source, to:dest] ↓"] + source.debit --> consume_dst["source.try_consume_rate_limit
(dst_eid)"] + consume_dst --> source_rl_dst["source.rate_limit_budget
[from:source, to:dest] ↓"] end source.debit --> send["send LZ message"] send --> dest.credit subgraph Dest["Dest Chain"] - dest.credit --> release_src["dest.release_rate_limit(src_eid)"] - release_src --> dest_rl_src["dest.rate_limit_budget[from:dest, to:source] ↑"] + dest.credit --> release_src["dest.release_rate_limit
(src_eid)"] + release_src --> dest_rl_src["dest.rate_limit_budget
[from:dest, to:source] ↑"] end ``` @@ -104,10 +104,10 @@ flowchart LR User --> mvmt.debit subgraph Mvmt - mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit(dst_eid)"] - consume_dst --> mvmt_rl_remote["mvmt.rate_limit_budget[from:mvmt, to:remote] ↓"] - mvmt.debit --> release_mvmt["mvmt.release_rate_limit(mvmt_eid)"] - release_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget[from:remote, to:mvmt] ↑"] + mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit
(dst_eid)"] + consume_dst --> mvmt_rl_remote["mvmt.rate_limit_budget
[from:mvmt, to:remote] ↓"] + mvmt.debit --> release_mvmt["mvmt.release_rate_limit
(mvmt_eid)"] + release_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget
[from:remote, to:mvmt] ↑"] end mvmt.debit --> send["send LZ message"] @@ -132,10 +132,10 @@ flowchart LR send --> mvmt.credit subgraph Mvmt - mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit(mvmt_eid)"] - consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget[from:remote, to:mvmt] ↓"] - mvmt.credit --> release_src["mvmt.release_rate_limit(src_eid)"] - release_src --> mvmt_rl_remote["mvmt.rate_limit_budget[from:mvmt, to:remote] ↑"] + mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit
(mvmt_eid)"] + consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget
[from:remote, to:mvmt] ↓"] + mvmt.credit --> release_src["mvmt.release_rate_limit
(src_eid)"] + release_src --> mvmt_rl_remote["mvmt.rate_limit_budget
[from:mvmt, to:remote] ↑"] end ``` @@ -177,8 +177,8 @@ flowchart LR User --> mvmt.debit subgraph Mvmt - mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit(dst_eid)"] - consume_dst --> mvmt_rl_remote["mvmt.rate_limit_budget[from:mvmt, to:remote] ↓"] + mvmt.debit --> consume_dst["mvmt.try_consume_rate_limit
(dst_eid)"] + consume_dst --> mvmt_rl_remote["mvmt.rate_limit_budget
[from:mvmt, to:remote] ↓"] end mvmt.debit --> send["send LZ message"] @@ -203,8 +203,8 @@ flowchart LR send --> mvmt.credit subgraph Mvmt - mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit(mvmt_eid)"] - consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget[from:remote, to:mvmt] ↓"] + mvmt.credit --> consume_mvmt["mvmt.try_consume_rate_limit
(mvmt_eid)"] + consume_mvmt --> mvmt_rl_mvmt["mvmt.rate_limit_budget
[from:remote, to:mvmt] ↓"] end ``` From 14228285121287a1fd21cba4701e360a74e50e1d Mon Sep 17 00:00:00 2001 From: apenzk Date: Tue, 16 Dec 2025 17:25:11 +0100 Subject: [PATCH 4/4] update mip number --- .github/CODEOWNERS | 1 + MIP/{mip-x => mip-126}/README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename MIP/{mip-x => mip-126}/README.md (99%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ebf7f92f..16c20f18 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -26,6 +26,7 @@ /MIP/mip-88/ @apenzk @Primata /MIP/mip-91/ @apenzk /MIP/mip-94/ @andygolay +/MIP/mip-126/ @primata @apenzk @rubujubi ## MGs /MG/mg-0/ @l-monninger diff --git a/MIP/mip-x/README.md b/MIP/mip-126/README.md similarity index 99% rename from MIP/mip-x/README.md rename to MIP/mip-126/README.md index a9e8c35b..a299e56d 100644 --- a/MIP/mip-x/README.md +++ b/MIP/mip-126/README.md @@ -1,4 +1,4 @@ -# MIP-X: Non-Offsettable Gross Inflow Rate Limiting +# MIP-126: Non-Offsettable Gross Inflow Rate Limiting - **Description**: Replace net-flow rate limiting with a strict gross inflow cap on Movement. - **Authors**: [Primata](), Ru, Andreas