Skip to content

Commit 5147b04

Browse files
authored
Merge pull request #2260 from opentensor/feat/vune/simpler-mev
feat: simpler mev shield
2 parents a7b5d97 + 6ebaa9d commit 5147b04

File tree

6 files changed

+27
-699
lines changed

6 files changed

+27
-699
lines changed

node/src/mev_shield/proposer.rs

Lines changed: 20 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@ use ml_kem::kem::{Decapsulate, DecapsulationKey};
44
use ml_kem::{Ciphertext, Encoded, EncodedSizeUser, MlKem768, MlKem768Params};
55
use sc_service::SpawnTaskHandle;
66
use sc_transaction_pool_api::{TransactionPool, TransactionSource};
7-
use sp_core::{H256, sr25519};
7+
use sp_core::H256;
88
use sp_runtime::traits::{Header, SaturatedConversion};
9-
use sp_runtime::{AccountId32, MultiSignature, OpaqueExtrinsic};
9+
use sp_runtime::{AccountId32, OpaqueExtrinsic};
1010
use std::{
1111
collections::HashMap,
1212
sync::{Arc, Mutex},
1313
time::Duration,
1414
};
1515
use tokio::time::sleep;
1616

17-
const KEY_FP_LEN: usize = 32;
18-
1917
/// Buffer of wrappers keyed by the block number in which they were included.
2018
#[derive(Default, Clone)]
2119
struct WrapperBuffer {
@@ -84,7 +82,7 @@ impl WrapperBuffer {
8482
/// Start a background worker that:
8583
/// • watches imported blocks and captures `MevShield::submit_encrypted`
8684
/// • buffers those wrappers per originating block,
87-
/// • during the last `decrypt_window_ms` of the slot: decrypt & submit unsigned `execute_revealed`
85+
/// • during the last `decrypt_window_ms` of the slot: decrypt & submit `submit_one`
8886
pub fn spawn_revealer<B, C, Pool>(
8987
task_spawner: &SpawnTaskHandle,
9088
client: Arc<C>,
@@ -347,7 +345,7 @@ pub fn spawn_revealer<B, C, Pool>(
347345
curr_block
348346
);
349347

350-
let mut to_submit: Vec<(H256, node_subtensor_runtime::RuntimeCall)> =
348+
let mut to_submit: Vec<(H256, node_subtensor_runtime::UncheckedExtrinsic)> =
351349
Vec::new();
352350
let mut failed_calls: Vec<(H256, node_subtensor_runtime::RuntimeCall)> =
353351
Vec::new();
@@ -714,27 +712,16 @@ pub fn spawn_revealer<B, C, Pool>(
714712
);
715713

716714
// Safely parse plaintext layout without panics.
717-
//
718-
// Layout:
719-
// signer (32)
720-
// key_hash (32) == Hashing::hash(NextKey_bytes) at submit time
721-
// call (..)
722-
// sig_kind (1)
723-
// sig (64)
724-
let min_plain_len: usize = 32usize
725-
.saturating_add(KEY_FP_LEN)
726-
.saturating_add(1usize)
727-
.saturating_add(64usize);
728-
729-
if plaintext.len() < min_plain_len {
715+
716+
if plaintext.is_empty() {
730717
let error_message = "plaintext too short";
731718
log::debug!(
732719
target: "mev-shield",
733720
" id=0x{}: {} (len={}, min={})",
734721
hex::encode(id.as_bytes()),
735722
error_message,
736723
plaintext.len(),
737-
min_plain_len
724+
1
738725
);
739726
failed_calls.push((
740727
id,
@@ -743,108 +730,10 @@ pub fn spawn_revealer<B, C, Pool>(
743730
continue;
744731
}
745732

746-
let signer_raw = match plaintext.get(0..32) {
747-
Some(s) => s,
748-
None => {
749-
let error_message = "missing signer bytes";
750-
log::debug!(
751-
target: "mev-shield",
752-
" id=0x{}: {}",
753-
hex::encode(id.as_bytes()),
754-
error_message
755-
);
756-
failed_calls.push((
757-
id,
758-
create_failed_call(id, error_message),
759-
));
760-
continue;
761-
}
762-
};
763-
764-
let key_hash_raw = match plaintext.get(32..32usize.saturating_add(KEY_FP_LEN))
765-
{
766-
Some(s) if s.len() == KEY_FP_LEN => s,
767-
_ => {
768-
let error_message = "missing or malformed key_hash bytes";
769-
log::debug!(
770-
target: "mev-shield",
771-
" id=0x{}: {}",
772-
hex::encode(id.as_bytes()),
773-
error_message
774-
);
775-
failed_calls.push((
776-
id,
777-
create_failed_call(id, error_message),
778-
));
779-
continue;
780-
}
781-
};
782-
783-
// sig_off = len - 65 (sig_kind + 64-byte sig)
784-
let sig_min_offset: usize =
785-
32usize.saturating_add(KEY_FP_LEN);
786-
787-
let sig_off = match plaintext.len().checked_sub(65usize) {
788-
Some(off) if off >= sig_min_offset => off,
789-
_ => {
790-
let error_message = "invalid plaintext length for signature split";
791-
log::debug!(
792-
target: "mev-shield",
793-
" id=0x{}: {} (len={})",
794-
hex::encode(id.as_bytes()),
795-
error_message,
796-
plaintext.len()
797-
);
798-
failed_calls.push((
799-
id,
800-
create_failed_call(id, error_message),
801-
));
802-
continue;
803-
}
804-
};
805-
806-
let call_start: usize = sig_min_offset;
807-
let call_bytes = match plaintext.get(call_start..sig_off) {
733+
let signed_extrinsic_bytes = match plaintext.get(0..plaintext.len()) {
808734
Some(s) if !s.is_empty() => s,
809735
_ => {
810-
let error_message = "missing call bytes";
811-
log::debug!(
812-
target: "mev-shield",
813-
" id=0x{}: {}",
814-
hex::encode(id.as_bytes()),
815-
error_message
816-
);
817-
failed_calls.push((
818-
id,
819-
create_failed_call(id, error_message),
820-
));
821-
continue;
822-
}
823-
};
824-
825-
let sig_kind = match plaintext.get(sig_off) {
826-
Some(b) => *b,
827-
None => {
828-
let error_message = "missing signature kind byte";
829-
log::debug!(
830-
target: "mev-shield",
831-
" id=0x{}: {}",
832-
hex::encode(id.as_bytes()),
833-
error_message
834-
);
835-
failed_calls.push((
836-
id,
837-
create_failed_call(id, error_message),
838-
));
839-
continue;
840-
}
841-
};
842-
843-
let sig_bytes_start = sig_off.saturating_add(1usize);
844-
let sig_bytes = match plaintext.get(sig_bytes_start..) {
845-
Some(s) if s.len() == 64 => s,
846-
_ => {
847-
let error_message = "signature bytes not 64 bytes";
736+
let error_message = "missing signed extrinsic bytes";
848737
log::debug!(
849738
target: "mev-shield",
850739
" id=0x{}: {}",
@@ -859,40 +748,18 @@ pub fn spawn_revealer<B, C, Pool>(
859748
}
860749
};
861750

862-
let signer_array: [u8; 32] = match signer_raw.try_into() {
863-
Ok(a) => a,
864-
Err(_) => {
865-
let error_message = "signer_raw not 32 bytes";
866-
log::debug!(
867-
target: "mev-shield",
868-
" id=0x{}: {}",
869-
hex::encode(id.as_bytes()),
870-
error_message
871-
);
872-
failed_calls.push((
873-
id,
874-
create_failed_call(id, error_message),
875-
));
876-
continue;
877-
}
878-
};
879-
let signer = sp_runtime::AccountId32::new(signer_array);
880-
881-
let mut fp_array = [0u8; KEY_FP_LEN];
882-
fp_array.copy_from_slice(key_hash_raw);
883-
let key_hash_h256 = H256(fp_array);
884751

885-
let inner_call: node_subtensor_runtime::RuntimeCall =
886-
match Decode::decode(&mut &call_bytes[..]) {
752+
let signed_extrinsic: node_subtensor_runtime::UncheckedExtrinsic =
753+
match Decode::decode(&mut &signed_extrinsic_bytes[..]) {
887754
Ok(c) => c,
888755
Err(e) => {
889-
let error_message = "failed to decode RuntimeCall";
756+
let error_message = "failed to decode UncheckedExtrinsic";
890757
log::debug!(
891758
target: "mev-shield",
892759
" id=0x{}: {} (len={}): {:?}",
893760
hex::encode(id.as_bytes()),
894761
error_message,
895-
call_bytes.len(),
762+
signed_extrinsic_bytes.len(),
896763
e
897764
);
898765
failed_calls.push((
@@ -903,62 +770,19 @@ pub fn spawn_revealer<B, C, Pool>(
903770
}
904771
};
905772

906-
let signature: MultiSignature =
907-
if sig_kind == 0x01 {
908-
let mut raw_sig = [0u8; 64];
909-
raw_sig.copy_from_slice(sig_bytes);
910-
MultiSignature::from(sr25519::Signature::from_raw(raw_sig))
911-
} else {
912-
let error_message = "unsupported signature format";
913-
log::debug!(
914-
target: "mev-shield",
915-
" id=0x{}: {} (kind=0x{:02x}, len={})",
916-
hex::encode(id.as_bytes()),
917-
error_message,
918-
sig_kind,
919-
sig_bytes.len()
920-
);
921-
failed_calls.push((
922-
id,
923-
create_failed_call(id, error_message),
924-
));
925-
continue;
926-
};
927-
928-
log::debug!(
929-
target: "mev-shield",
930-
" id=0x{}: decrypted wrapper: signer={}, key_hash=0x{}, call={:?}",
931-
hex::encode(id.as_bytes()),
932-
signer,
933-
hex::encode(key_hash_h256.as_bytes()),
934-
inner_call
935-
);
936-
937-
let reveal = node_subtensor_runtime::RuntimeCall::MevShield(
938-
pallet_shield::Call::execute_revealed {
939-
id,
940-
signer: signer.clone(),
941-
key_hash: key_hash_h256.into(),
942-
call: Box::new(inner_call),
943-
signature,
944-
},
945-
);
946-
947-
to_submit.push((id, reveal));
773+
to_submit.push((id, signed_extrinsic));
948774
}
949775

950-
// Submit locally.
776+
// Submit as external the signed extrinsics.
951777
let at = client.info().best_hash;
952778
log::debug!(
953779
target: "mev-shield",
954-
"revealer: submitting {} execute_revealed calls at best_hash={:?}",
780+
"revealer: submitting {} extrinsics to pool at best_hash={:?}",
955781
to_submit.len(),
956782
at
957783
);
958784

959-
for (id, call) in to_submit.into_iter() {
960-
let uxt: node_subtensor_runtime::UncheckedExtrinsic =
961-
node_subtensor_runtime::UncheckedExtrinsic::new_bare(call);
785+
for (id, uxt) in to_submit.into_iter() {
962786
let xt_bytes = uxt.encode();
963787

964788
log::debug!(
@@ -971,23 +795,23 @@ pub fn spawn_revealer<B, C, Pool>(
971795
match OpaqueExtrinsic::from_bytes(&xt_bytes) {
972796
Ok(opaque) => {
973797
match pool
974-
.submit_one(at, TransactionSource::Local, opaque)
798+
.submit_one(at, TransactionSource::External, opaque)
975799
.await
976800
{
977801
Ok(_) => {
978802
let xt_hash =
979803
sp_core::hashing::blake2_256(&xt_bytes);
980804
log::debug!(
981805
target: "mev-shield",
982-
" id=0x{}: submit_one(execute_revealed) OK, xt_hash=0x{}",
806+
" id=0x{}: submit_one(...) OK, xt_hash=0x{}",
983807
hex::encode(id.as_bytes()),
984808
hex::encode(xt_hash)
985809
);
986810
}
987811
Err(e) => {
988812
log::debug!(
989813
target: "mev-shield",
990-
" id=0x{}: submit_one(execute_revealed) FAILED: {:?}",
814+
" id=0x{}: submit_one(...) FAILED: {:?}",
991815
hex::encode(id.as_bytes()),
992816
e
993817
);

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(),

0 commit comments

Comments
 (0)