Conversation
shamil-gadelshin
previously approved these changes
Feb 20, 2026
Contributor
|
Seems it introduces the problem that the Ink contract doesn't work. I am not sure what is issue yet. Everything is fine in my local. #2450 created to debug it. |
sam0x17
previously approved these changes
Feb 23, 2026
JohnReedV
previously approved these changes
Feb 24, 2026
991cb7a to
2cf308a
Compare
2cf308a to
805de46
Compare
sam0x17
approved these changes
Feb 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Companion PR to opentensor/polkadot-sdk#6
Reworks the MEV Shield from a store-then-decrypt model to a decrypt-at-proposal model.
Previously, encrypted transactions were stored on-chain (
Submissions) and decrypted by the block author in a separate step, leaving a window where decrypted transactions sat in the pool before inclusion. Now, encrypted transactions travel through the pool as opaque ciphertext and the block proposer decrypts them inline during block building, including the inner extrinsic in the same block. There is no point where a decrypted transaction is visible before it lands in a finalized block.Encryption uses ML-KEM-768 + XChaCha20-Poly1305 with per-block ephemeral keys rotated via an inherent.
Breaking changes for clients
This PR introduces breaking changes that require client-side updates.
Encrypted message format
The ciphertext payload now includes the next public key hash as a prefix. The new wire format is:
key_hash:xxhash128(NextKey)— the 16-byte hash of the ML-KEM public key used for encryption. Clients must compute this from theNextKeythey encrypt against.kem_len: 2-byte little-endian length of the KEM ciphertext that follows.kem_ct: ML-KEM-768 encapsulation ciphertext (typically 1088 bytes).nonce: 24-byte random nonce for XChaCha20-Poly1305.aead_ct: The authenticated ciphertext containing the encoded inner extrinsic.submit_encryptedAPI changeThe old unused
commitmentparameter has been removed. The new signature is:New transaction extension:
CheckShieldedTxValidityA new transaction extension validates encrypted messages at two levels:
FailedShieldedTxParsingerror.key_hashmatches eitherCurrentKeyorNextKey. If it doesn't match, the transaction is dropped silently — the block proposer returns anInvalidtransaction error without a custom error code because the block proposer does not propagate the inner error code of the extension.This means clients should expect:
FailedShieldedTxParsingerror if the ciphertext format is wrong.Invaliderror (no specific code) if thekey_hashdoesn't match any active key — e.g. when using a stale or wrong key.Rollout plan
The upgrade will be deployed in 3 parts:
ShieldApiruntime API used by the block proposer.Changes
pallet-shield(reworked)announce_next_keyinherent: rotatesCurrentKey <- NextKeyeach block and publishes the next block author's ML-KEM public keysubmit_encryptedextrinsic: accepts an encrypted ciphertext wrapper — the block proposer decrypts and includes the inner extrinsic in the same blocktry_decode_shielded_tx/try_unshield_tx: runtime helpers called by the block proposer via theShieldApiruntime APICheckShieldedTxValiditytransaction extension: pool validation checks ciphertext structure; block import additionally validateskey_hashagainstCurrentKey/NextKeyFindAuthorstrait for resolving current and next block authorSubmissions,KeyHashByBlock)stp-io(new crate — host functions)mlkem768_decapsulate: ML-KEM-768 decapsulation via theShieldKeystoreextensionaead_decrypt: XChaCha20-Poly1305 decryption via theShieldKeystoreextensionSubtensorHostFunctionsfor registration in the nodeNode integration
ShieldKeystorecreated inservice.rsand threaded through to the proposer and inherent providersShieldInherentDataProvideradded to Aura consensus configurationKeyRotationServicegenerates a new ML-KEM keypair on each own-block importSubtensorHostFunctionsregistered in the client executorRuntime integration
ShieldApiruntime API implementedCheckShieldedTxValidityadded to the transaction extension pipelineTests
try_decode_shielded_tx,try_unshield_tx, depth-limit protection, inherent creation,CheckShieldedTxValidityextension (key_hash matching, malformed rejection, pool vs in-block source)E2E (branch:
setup-e2e)14 tests across 3 files covering 3-node and 6-node topologies:
Key rotation (3-node)
Encrypted transactions (3-node)
Scaling (6-node)
Edge cases