@@ -28,8 +28,8 @@ pub mod pallet {
2828 InvalidTransaction , TransactionSource , ValidTransaction ,
2929 } ;
3030 use sp_runtime:: {
31- AccountId32 , DispatchErrorWithPostInfo , MultiSignature , RuntimeDebug , Saturating ,
32- traits:: { BadOrigin , Dispatchable , Hash , Verify } ,
31+ AccountId32 , DispatchErrorWithPostInfo , RuntimeDebug , Saturating ,
32+ traits:: { BadOrigin , Hash } ,
3333 } ;
3434 use sp_std:: { marker:: PhantomData , prelude:: * } ;
3535 use subtensor_macros:: freeze_struct;
@@ -330,91 +330,6 @@ pub mod pallet {
330330 Ok ( ( ) )
331331 }
332332
333- /// Executed by the block author after decrypting a batch of wrappers.
334- ///
335- /// The author passes in:
336- ///
337- /// * `id` – wrapper id (hash of (author, commitment, ciphertext))
338- /// * `signer` – account that should be treated as the origin of `call`
339- /// * `key_hash` – 32‑byte hash the client embedded (and signed) in the payload
340- /// * `call` – inner RuntimeCall to execute on behalf of `signer`
341- /// * `signature` – MultiSignature over the domain‑separated payload
342- ///
343- #[ pallet:: call_index( 2 ) ]
344- #[ pallet:: weight( (
345- Weight :: from_parts( 77_280_000 , 0 )
346- . saturating_add( T :: DbWeight :: get( ) . reads( 4_u64 ) )
347- . saturating_add( T :: DbWeight :: get( ) . writes( 1_u64 ) ) ,
348- DispatchClass :: Normal ,
349- Pays :: No
350- ) ) ]
351- #[ allow( clippy:: useless_conversion) ]
352- pub fn execute_revealed (
353- origin : OriginFor < T > ,
354- id : T :: Hash ,
355- signer : T :: AccountId ,
356- key_hash : T :: Hash ,
357- call : Box < <T as Config >:: RuntimeCall > ,
358- signature : MultiSignature ,
359- ) -> DispatchResultWithPostInfo {
360- // Unsigned: only the author node may inject this via ValidateUnsigned.
361- ensure_none ( origin) ?;
362-
363- // 1) Load and consume the submission.
364- let Some ( sub) = Submissions :: < T > :: take ( id) else {
365- return Err ( Error :: < T > :: MissingSubmission . into ( ) ) ;
366- } ;
367-
368- // 2) Bind to the MEV‑Shield key epoch at submit time.
369- let expected_key_hash =
370- KeyHashByBlock :: < T > :: get ( sub. submitted_in ) . ok_or ( Error :: < T > :: KeyExpired ) ?;
371-
372- ensure ! ( key_hash == expected_key_hash, Error :: <T >:: KeyHashMismatch ) ;
373-
374- // 3) Rebuild the same payload bytes the client used for both
375- // commitment and signature.
376- let payload_bytes = Self :: build_raw_payload_bytes ( & signer, & key_hash, call. as_ref ( ) ) ;
377-
378- // 4) Commitment check against on-chain stored commitment.
379- let recomputed: T :: Hash = T :: Hashing :: hash ( & payload_bytes) ;
380- ensure ! ( sub. commitment == recomputed, Error :: <T >:: CommitmentMismatch ) ;
381-
382- // 5) Signature check over the same payload, with domain separation
383- // and genesis hash to make signatures chain‑bound.
384- let genesis = frame_system:: Pallet :: < T > :: block_hash ( BlockNumberFor :: < T > :: zero ( ) ) ;
385- let mut msg = b"mev-shield:v1" . to_vec ( ) ;
386- msg. extend_from_slice ( genesis. as_ref ( ) ) ;
387- msg. extend_from_slice ( & payload_bytes) ;
388-
389- let sig_ok = signature. verify ( msg. as_slice ( ) , & signer) ;
390- ensure ! ( sig_ok, Error :: <T >:: SignatureInvalid ) ;
391-
392- // 6) Dispatch inner call from signer.
393- let info = call. get_dispatch_info ( ) ;
394- let required = info. call_weight . saturating_add ( info. extension_weight ) ;
395-
396- let origin_signed = frame_system:: RawOrigin :: Signed ( signer. clone ( ) ) . into ( ) ;
397- let res = ( * call) . dispatch ( origin_signed) ;
398-
399- match res {
400- Ok ( post) => {
401- let actual = post. actual_weight . unwrap_or ( required) ;
402- Self :: deposit_event ( Event :: DecryptedExecuted { id, signer } ) ;
403- Ok ( PostDispatchInfo {
404- actual_weight : Some ( actual) ,
405- pays_fee : Pays :: No ,
406- } )
407- }
408- Err ( e) => {
409- Self :: deposit_event ( Event :: DecryptedRejected { id, reason : e } ) ;
410- Ok ( PostDispatchInfo {
411- actual_weight : Some ( required) ,
412- pays_fee : Pays :: No ,
413- } )
414- }
415- }
416- }
417-
418333 /// Marks a submission as failed to decrypt and removes it from storage.
419334 ///
420335 /// Called by the block author when decryption fails at any stage (e.g., ML-KEM decapsulate
@@ -453,48 +368,12 @@ pub mod pallet {
453368 }
454369 }
455370
456- impl < T : Config > Pallet < T > {
457- /// Build the raw payload bytes used for both:
458- ///
459- /// * `commitment = T::Hashing::hash(raw_payload)`
460- /// * signature message (after domain separation)
461- ///
462- /// Layout:
463- ///
464- /// signer (32B) || key_hash (T::Hash bytes) || SCALE(call)
465- fn build_raw_payload_bytes (
466- signer : & T :: AccountId ,
467- key_hash : & T :: Hash ,
468- call : & <T as Config >:: RuntimeCall ,
469- ) -> Vec < u8 > {
470- let mut out = Vec :: new ( ) ;
471- out. extend_from_slice ( signer. as_ref ( ) ) ;
472- out. extend_from_slice ( key_hash. as_ref ( ) ) ;
473- out. extend ( call. encode ( ) ) ;
474- out
475- }
476- }
477-
478371 #[ pallet:: validate_unsigned]
479372 impl < T : Config > ValidateUnsigned for Pallet < T > {
480373 type Call = Call < T > ;
481374
482375 fn validate_unsigned ( source : TransactionSource , call : & Self :: Call ) -> TransactionValidity {
483376 match call {
484- Call :: execute_revealed { id, .. } => {
485- match source {
486- // Only allow locally-submitted / already-in-block txs.
487- TransactionSource :: Local | TransactionSource :: InBlock => {
488- ValidTransaction :: with_tag_prefix ( "mev-shield-exec" )
489- . priority ( 1u64 )
490- . longevity ( 64 ) // long because propagate(false)
491- . and_provides ( id) // dedupe by wrapper id
492- . propagate ( false ) // CRITICAL: no gossip, stays on author node
493- . build ( )
494- }
495- _ => InvalidTransaction :: Call . into ( ) ,
496- }
497- }
498377 Call :: mark_decryption_failed { id, .. } => {
499378 match source {
500379 TransactionSource :: Local | TransactionSource :: InBlock => {
0 commit comments