Skip to content

Cap SC datastore-key path behind protocol constant (MIP-0002) - #5288

Closed
bilboquet wants to merge 18 commits into
dev_breakingfrom
5284
Closed

bilboquet wants to merge 18 commits into
dev_breakingfrom
5284

Conversation

@bilboquet

@bilboquet bilboquet commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Implements #5284 (part (a) of #5241). Targets dev_breaking, gated by MIP-0002 (MipComponent::Execution v2).

What: Context::get_keys enforces MAX_SC_DATASTORE_KEY_COUNT once Execution v2 is active (pre-activation unchanged). Explicit over-cap counts error via the existing cleanup path; unbounded queries matching more than the cap fail loudly through a cap + 1 probe — never silently truncated. Implements the paginated get_keys_paginated[_for] trait methods against massa-sc-runtime#361 (pinned in Cargo.toml, to re-pin on merge).

Open / provisional (why draft):

Tests: test_get_keys_paginated_pages (chained pages, exclusive cursor), test_sc_datastore_key_cap (over-cap errors, at-cap passes, pre-activation uncapped). Full massa_execution_worker suite green, clippy/fmt clean.

Closes #5284 on merge (the sc-runtime sub-issue rides separately as massa-sc-runtime#361).

Depends massalabs/massa-sc-runtime#361

Leo-Besancon and others added 17 commits September 21, 2026 07:15
WMAS pays, from its own locked MAS, for the datastore balance entry
created when transferring/approving to a fresh address (charged to the
executing SC in set_data_entry). WMAS is a widely-used singleton that
cannot be redeployed without forcing all holders/integrations to migrate.

This adds a one-time, versioning-gated irregular state change: at the
activation of MipComponent::Execution version WMAS_PATCH_EXEC_VERSION,
every node deterministically overwrites the WMAS bytecode with an audited
fixed build, in execute_slot (shared by candidate and final execution).

Why this is safe:
- bytecode is stored separately from datastore + coin balance, so all
  balances and locked MAS are preserved by the swap;
- the module cache is keyed by bytecode hash, so the new bytecode is
  recompiled on first use with no explicit invalidation;
- the change is part of the slot's ledger changes and thus of final
  state, so nodes bootstrapping after activation get the patched bytecode.

Note: coin transfers (e.g. WMAS.withdraw) are NOT affected by the drain:
transfer_coins funds a new address's creation cost out of the transferred
amount and fails if it is insufficient, never touching the SC balance.

Operational values to fill before enabling (loud TODOs):
- WMAS_ADDRESS: verified mainnet address;
- resources/wmas_patched.wasm: reproducible fixed build (empty here, so
  the crate builds while the patch stays inert; applying empty bytecode is
  refused as a fail-safe);
- register the activation MIP bumping MipComponent::Execution to
  WMAS_PATCH_EXEC_VERSION. Until then execution_component_version never
  reaches it and this code is inert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces the `include_bytes!` from resources/wmas_patched.wasm with an
in-source `PATCHED_WMAS_BYTECODE` constant (wmas_bytecode.rs), so the patch
carries no external build artifact and the exact bytes are reviewable in
the source tree. The generated module records the source, length and
sha256 of the wasm for verification.

Also harden the activation path: wmas_address() now returns Option and the
hook skips (with a warning) unless BOTH a valid address and non-empty
bytecode are present, so a placeholder/misconfiguration can never panic or
apply a partial patch in consensus execution.

TODO(release): regenerate wmas_bytecode.rs from the reproducible, audited
build of the deployed WMAS contract and set WMAS_ADDRESS before enabling
the MIP.
…hedulable slot budget

send_message bounded max_gas only from below, so a message asking for more than
max_async_gas + max_gas_per_block - async_msg_cst_gas_cost was admitted but could
never be scheduled by take_batch_to_execute. It occupied async pool capacity until
its validity end, and cancel_async_message refunds coins but not the fee, so the
sender silently lost it.

Rejecting at emission changes execution results, so the check is gated on
MipComponent::Execution version 2 (MIP-0002-BugFix, shared with the WMAS patch).
The bound rejects only what no slot could ever schedule; a stricter always-schedulable
bound would collapse toward zero, since deferred calls can consume all of
max_async_gas and the remaining block gas can be zero.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Jean-François <jfm@laposte.net>
…MIP-0002)

Bound Context::get_keys by MAX_SC_DATASTORE_KEY_COUNT (provisional value,
TODO calibration campaign shared with #5285) once Execution v2 is active;
pre-activation behavior unchanged. Explicit over-cap counts and unbounded
queries matching more than the cap fail loudly instead of truncating.

Implement the paginated get_keys_paginated[_for] Interface methods against
massa-sc-runtime#361 (pinned in Cargo.toml, re-pin on merge).

Refs #5284 (part of #5241).
Signed-off-by: Jean-François <jfm@laposte.net>
Implement get_interface_version (was a bail stub) to report the active
execution component version, and reject direct calls to the paginated
datastore-key methods before MIP-0002 activation. The sc-runtime only
resolves the new imports from Execution v2, so updated nodes reject them
pre-activation exactly like non-updated nodes.

Re-pin massa-sc-runtime to 8c4e6ed (gated registration).

@Leo-Besancon Leo-Besancon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation looks good to me (now that the runtime's ABI have been gated behind the MIP too).

Not sure about the constant, I think that @peterjah outlined the impact of its value on currently used SCs.

@bilboquet

Copy link
Copy Markdown
Contributor Author

replaced by #5294

@bilboquet bilboquet closed this Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants