Skip to content

Commit 5b8537f

Browse files
committed
fix conflict
2 parents 10d5112 + 5147b04 commit 5b8537f

File tree

11 files changed

+301
-948
lines changed

11 files changed

+301
-948
lines changed

node/src/mev_shield/proposer.rs

Lines changed: 20 additions & 196 deletions
Large diffs are not rendered by default.

node/src/service.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ where
568568
timing.clone(),
569569
);
570570

571-
// Start last-portion-of-slot revealer (decrypt -> execute_revealed).
571+
// Start last-portion-of-slot revealer (decrypt -> submit_one).
572572
proposer::spawn_revealer::<Block, _, _>(
573573
&task_manager.spawn_handle(),
574574
client.clone(),

pallets/shield/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ sp-consensus-aura.workspace = true
3838
[dev-dependencies]
3939

4040
[features]
41-
default = []
41+
default = ["std"]
4242

4343
std = [
4444
"codec/std",

pallets/shield/src/benchmarking.rs

Lines changed: 2 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use frame_support::{BoundedVec, pallet_prelude::ConstU32};
55
use frame_system::{RawOrigin, pallet_prelude::BlockNumberFor};
66
use sp_core::{crypto::KeyTypeId, sr25519};
77
use sp_io::crypto::sr25519_generate;
8-
use sp_runtime::{AccountId32, MultiSignature, traits::Hash as HashT};
9-
use sp_std::{boxed::Box, vec, vec::Vec};
8+
use sp_runtime::{AccountId32, traits::Hash as HashT};
9+
use sp_std::vec;
1010

1111
/// Helper to build bounded bytes (public key) of a given length.
1212
fn bounded_pk<const N: u32>(len: usize) -> BoundedVec<u8, ConstU32<N>> {
@@ -103,93 +103,6 @@ mod benches {
103103
assert_eq!(got.ciphertext.as_slice(), ciphertext.as_slice());
104104
}
105105

106-
/// Benchmark `execute_revealed`.
107-
#[benchmark]
108-
fn execute_revealed() {
109-
use codec::Encode;
110-
use frame_support::BoundedVec;
111-
use sp_core::{crypto::KeyTypeId, sr25519};
112-
use sp_io::crypto::{sr25519_generate, sr25519_sign};
113-
use sp_runtime::traits::Zero;
114-
115-
// 1) Generate a dev sr25519 key in the host keystore and derive the account.
116-
const KT: KeyTypeId = KeyTypeId(*b"benc");
117-
let signer_pub: sr25519::Public = sr25519_generate(KT, Some("//Alice".as_bytes().to_vec()));
118-
let signer: AccountId32 = signer_pub.into();
119-
120-
// 2) Inner call that will be executed as the signer (cheap & always available).
121-
let inner_call: <T as pallet::Config>::RuntimeCall = frame_system::Call::<T>::remark {
122-
remark: vec![1, 2, 3],
123-
}
124-
.into();
125-
126-
// 3) Simulate the MEV‑Shield key epoch at the current block.
127-
//
128-
// In the real system, KeyHashByBlock[submitted_in] is filled by on_initialize
129-
// as hash(CurrentKey). For the benchmark we just use a dummy value and
130-
// insert it directly.
131-
let submitted_in: BlockNumberFor<T> = frame_system::Pallet::<T>::block_number();
132-
let dummy_epoch_bytes: &[u8] = b"benchmark-epoch-key";
133-
let key_hash: <T as frame_system::Config>::Hash =
134-
<T as frame_system::Config>::Hashing::hash(dummy_epoch_bytes);
135-
KeyHashByBlock::<T>::insert(submitted_in, key_hash);
136-
137-
// 4) Build payload and commitment exactly how the pallet expects:
138-
// payload = signer (32B) || key_hash (T::Hash bytes) || SCALE(call)
139-
let mut payload_bytes = Vec::new();
140-
payload_bytes.extend_from_slice(signer.as_ref());
141-
payload_bytes.extend_from_slice(key_hash.as_ref());
142-
payload_bytes.extend(inner_call.encode());
143-
144-
let commitment: <T as frame_system::Config>::Hash =
145-
<T as frame_system::Config>::Hashing::hash(payload_bytes.as_slice());
146-
147-
// 5) Ciphertext is stored in the submission but not used by `execute_revealed`;
148-
// keep it small and arbitrary.
149-
const CT_DEFAULT_LEN: usize = 64;
150-
let ciphertext: BoundedVec<u8, ConstU32<8192>> =
151-
BoundedVec::truncate_from(vec![0u8; CT_DEFAULT_LEN]);
152-
153-
// The submission `id` must match pallet's hashing scheme in submit_encrypted.
154-
let id: <T as frame_system::Config>::Hash = <T as frame_system::Config>::Hashing::hash_of(
155-
&(signer.clone(), commitment, &ciphertext),
156-
);
157-
158-
// 6) Seed the Submissions map with the expected entry.
159-
let sub = Submission::<T::AccountId, BlockNumberFor<T>, <T as frame_system::Config>::Hash> {
160-
author: signer.clone(),
161-
commitment,
162-
ciphertext: ciphertext.clone(),
163-
submitted_in,
164-
};
165-
Submissions::<T>::insert(id, sub);
166-
167-
// 7) Domain-separated signing as in pallet:
168-
// "mev-shield:v1" || genesis_hash || payload
169-
let zero: BlockNumberFor<T> = Zero::zero();
170-
let genesis = frame_system::Pallet::<T>::block_hash(zero);
171-
let mut msg = b"mev-shield:v1".to_vec();
172-
msg.extend_from_slice(genesis.as_ref());
173-
msg.extend_from_slice(&payload_bytes);
174-
175-
let sig = sr25519_sign(KT, &signer_pub, &msg).expect("signing should succeed in benches");
176-
let signature: MultiSignature = sig.into();
177-
178-
// 8) Measure: dispatch the unsigned extrinsic (RawOrigin::None) with a valid wrapper.
179-
#[extrinsic_call]
180-
execute_revealed(
181-
RawOrigin::None,
182-
id,
183-
signer.clone(),
184-
key_hash,
185-
Box::new(inner_call.clone()),
186-
signature.clone(),
187-
);
188-
189-
// 9) Assert: submission consumed.
190-
assert!(Submissions::<T>::get(id).is_none());
191-
}
192-
193106
/// Benchmark `mark_decryption_failed`.
194107
#[benchmark]
195108
fn mark_decryption_failed() {

pallets/shield/src/lib.rs

Lines changed: 2 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)