feat(gas-keys): stabilize gas keys at protocol version 85#15183
Conversation
4aa89a4 to
0cc3dd4
Compare
There was a problem hiding this comment.
Pull request overview
This PR stabilizes the ProtocolFeature::GasKeys feature by moving it into the stable protocol feature set at protocol version 85, updating stable protocol version constants accordingly, and aligning tests/snapshots/changelog with the new stable behavior.
Changes:
- Promote
ProtocolFeature::GasKeysto stable at PV 85 and bumpSTABLE_PROTOCOL_VERSIONto 85. - Remove nightly-only ignore gating from test-loop gas key tests so they run on stable.
- Update chain snapshot hashes and add a changelog entry documenting GasKeys stabilization.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| test-loop-tests/src/tests/gas_keys.rs | Removes nightly-only ignore gates so GasKeys tests run under stable builds. |
| core/primitives-core/src/version.rs | Moves GasKeys to stable at PV 85 and bumps STABLE_PROTOCOL_VERSION to 85. |
| chain/chain/src/tests/simple_chain.rs | Updates insta snapshot hashes to reflect the new stable protocol version/feature set. |
| CHANGELOG.md | Documents GasKeys stabilization in the unreleased protocol changes section. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ### Protocol Changes | ||
| * The contract runtime has been upgraded to use the new Wasmtime-based runtime; | ||
| * The contract runtime now allows for bulk memory instructions in Wasm code. | ||
| * Stabilize GasKeys: transactions can now specify a gas key to pay for gas costs separately from the signer's main access key. |
There was a problem hiding this comment.
The new changelog bullet uses imperative tense ("Stabilize") while the surrounding bullets use past/present perfect ("has been upgraded", "now allows"). Consider rephrasing for consistency (e.g., "GasKeys stabilized" / "GasKeys has been stabilized") and aligning end punctuation with the other entries in this section.
| * Stabilize GasKeys: transactions can now specify a gas key to pay for gas costs separately from the signer's main access key. | |
| * GasKeys has been stabilized: transactions can now specify a gas key to pay for gas costs separately from the signer's main access key. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #15183 +/- ##
=======================================
Coverage 69.73% 69.74%
=======================================
Files 944 944
Lines 201033 201032 -1
Branches 201033 201032 -1
=======================================
+ Hits 140193 140202 +9
+ Misses 56133 56125 -8
+ Partials 4707 4705 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Per our procedures for stabilization, this PR requires additional sign off. |
285123b to
fa95fae
Compare
fa95fae to
55b2491
Compare
Why some test-loop tests switched to
|
rs_contract now imports the chain_id host fn (latest_protocol), so it no longer links below protocol 85. Point the protocol-upgrade tests that instantiate it pre-upgrade at backwards_compatible_rs_contract. Byte-for-byte identical to the same fix in #15183; kept as a standalone commit so it can be dropped if #15183 lands first.
rs_contract now imports the chain_id host fn (latest_protocol), so it no longer links below protocol 85. Point the protocol-upgrade tests that instantiate it pre-upgrade at backwards_compatible_rs_contract. Byte-for-byte identical to the same fix in #15183; kept as a standalone commit so it can be dropped if #15183 lands first.
rs_contract now imports the chain_id host fn (latest_protocol), so it no longer links below protocol 85. Point the protocol-upgrade tests that instantiate it pre-upgrade at backwards_compatible_rs_contract. Byte-for-byte identical to the same fix in #15183; kept as a standalone commit so it can be dropped if #15183 lands first.
rs_contract now imports the chain_id host fn (latest_protocol), so it no longer links below protocol 85. Point the protocol-upgrade tests that instantiate it pre-upgrade at backwards_compatible_rs_contract. Byte-for-byte identical to the same fix in #15183; kept as a standalone commit so it can be dropped if #15183 lands first.
rs_contract now imports the chain_id host fn (latest_protocol), so it no longer links below protocol 85. Point the protocol-upgrade tests that instantiate it pre-upgrade at backwards_compatible_rs_contract. Byte-for-byte identical to the same fix in #15183; kept as a standalone commit so it can be dropped if #15183 lands first.
# Conflicts: # core/primitives-core/src/version.rs
# Conflicts: # core/parameters/src/config_store.rs # core/parameters/src/snapshots/near_parameters__config_store__tests__149.json.snap # core/parameters/src/snapshots/near_parameters__config_store__tests__testnet_149.json.snap
## Summary Implements the [NEP-638](near/NEPs#638) `chain_id` host function, which lets a contract read the chain identifier (e.g. `mainnet`, `testnet`) at runtime instead of hardcoding it or passing it in as an argument. Gated behind protocol version 85. Signature: `chain_id(register_id: u64)` — writes the chain id bytes into the given register. Cost is `base + write_register_base + write_register_byte * num_bytes`; no new gas parameters are introduced (it reuses the existing register-write costs). ## Design notes - The value is fetched lazily through the `External` trait inside the host function (the same pattern as `validator_total_stake`), rather than being pre-populated into `VMContext`. So there is no per-call allocation unless a contract actually calls `chain_id`. `RuntimeExt::chain_id()` reads it from the epoch info provider. - Import gating is handled by `Config::chain_id_host_fn`: pre-v85 the `env.chain_id` import is not exposed, so a contract importing it fails to link. ## Testing - VM logic unit test: `runtime/near-vm-runner/src/logic/tests/context.rs::test_chain_id`. - VM integration test: `runtime/near-vm-runner/src/tests/chain_id_integration.rs` runs `ext_chain_id` through every VM backend (NearVm + Wasmtime) and checks the returned bytes. - e2e test-loop tests: `test-loop-tests/src/tests/chain_id.rs` covers the full transaction → receipt → outcome pipeline — `test_chain_id_returns_chain_id` asserts the genesis chain id at v85, and `test_chain_id_pre_activation_call_fails` confirms a contract importing `env.chain_id` fails to link at protocol 84. - The contract side reuses the shared `test-contract-rs` via a new `ext_chain_id` export, gated `#[cfg(feature = "latest_protocol")]` so it only ships in `rs_contract` (not `backwards_compatible_rs_contract`). ## Notes - Because `rs_contract` now imports `env.chain_id`, it no longer links below protocol 85. Three protocol-upgrade tests that instantiate it pre-upgrade (`cache_warming`, `deterministic_account_id`, `yield_resume`) are pointed at `backwards_compatible_rs_contract`. This fix is byte-for-byte identical to the same change in near#15183 and is kept as a standalone commit so it can be dropped cleanly if near#15183 lands first.
Gas Keys (NEP-611)
Gas keys are a new type of access key that carries a pre-funded NEAR balance and multiple independent nonce sequences. When a transaction is signed with a gas key, gas costs are deducted from the gas key's balance rather than the signer's account balance (deposits like NEAR transfers still come from the account).
Why do we need gas keys?
Enabling SPICE without a DoS vector. The SPICE project (Separation of Execution from Consensus) decouples transaction execution from block production: transactions are included in blocks first, and executed asynchronously later. This means chunk producers can no longer verify account balances at inclusion time. An attacker could drain an account's balance in one transaction, then flood the chain with many transactions signed by that account. All would be accepted (since execution hasn't caught up), consuming block space for free when they inevitably fail. Gas keys close this gap by requiring gas to be pre-committed in the key itself, so chunk producers can verify gas availability without access to the latest state.
Parallel transaction submission. Today, programmatic users who submit many transactions in parallel must manage multiple access keys (each with its own nonce sequence). A gas key supports up to 1,024 independent nonce slots via a single key, removing that complexity.
Context
Testing and QA
Checklist
Unreleasedsection.