1use alloc::boxed::Box;
2use alloc::string::{String, ToString};
3use alloc::vec::Vec;
4use alloc::{format, vec};
5use core::fmt;
6use core::str::FromStr;
7
8use ethers::abi::{encode, Token};
9use serde::{Deserialize, Serialize};
10use serde_json::Value as JsonValue;
11use sha3::{digest::Update, Digest, Keccak256};
12use umbral_pre::serde_bytes;
13
14use crate::address::Address;
15use crate::conditions::Context;
16use crate::prim_types::Uint256;
17use crate::session::{
18 decrypt_with_shared_secret, encrypt_with_shared_secret,
19 key::{SessionSharedSecret, SessionStaticKey},
20 DecryptionError,
21};
22use crate::versioning::{
23 messagepack_deserialize, messagepack_serialize, DeserializationError, ProtocolObject,
24 ProtocolObjectInner,
25};
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
29#[serde(rename_all = "kebab-case")]
30pub enum SignatureRequestType {
31 UserOp = 0,
33 PackedUserOp = 1,
35}
36
37impl SignatureRequestType {
38 pub fn as_u8(&self) -> u8 {
40 *self as u8
41 }
42
43 pub fn from_u8(i: u8) -> Result<Self, String> {
45 match i {
46 0 => Ok(Self::UserOp),
47 1 => Ok(Self::PackedUserOp),
48 _ => Err(format!("Invalid signature request type: {}", i)),
49 }
50 }
51}
52
53impl fmt::Display for SignatureRequestType {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 match self {
56 Self::UserOp => write!(f, "userop"),
57 Self::PackedUserOp => write!(f, "packedUserOp"),
58 }
59 }
60}
61
62pub const ENTRYPOINT_V08: &str = "0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108";
64pub const ENTRYPOINT_V07: &str = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
69pub enum AAVersion {
70 #[serde(rename = "0.7.0")]
72 V07,
73 #[serde(rename = "0.8.0")]
75 V08,
76 #[serde(rename = "mdt")]
78 MDT,
79}
80
81impl AAVersion {
82 pub fn as_str(&self) -> &'static str {
84 match self {
85 Self::V07 => "0.7.0",
86 Self::V08 => "0.8.0",
87 Self::MDT => "mdt",
88 }
89 }
90}
91
92impl FromStr for AAVersion {
93 type Err = String;
94
95 fn from_str(s: &str) -> Result<Self, Self::Err> {
96 match s {
97 "0.7.0" => Ok(Self::V07),
98 "0.8.0" => Ok(Self::V08),
99 "mdt" => Ok(Self::MDT),
100 _ => Err(format!("Invalid AA version: {}", s)),
101 }
102 }
103}
104
105impl fmt::Display for AAVersion {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 match self {
108 Self::V07 => write!(f, "{}", Self::V07.as_str()),
109 Self::V08 => write!(f, "{}", Self::V08.as_str()),
110 Self::MDT => write!(f, "{}", Self::MDT.as_str()),
111 }
112 }
113}
114
115pub trait BaseSignatureRequest: Serialize + for<'de> Deserialize<'de> {
117 fn cohort_id(&self) -> u32;
119 fn chain_id(&self) -> u64;
121 fn signature_type(&self) -> SignatureRequestType;
123 fn context(&self) -> Option<&Context>;
125 fn encrypt(
127 &self,
128 shared_secret: &SessionSharedSecret,
129 requester_public_key: &SessionStaticKey,
130 ) -> EncryptedThresholdSignatureRequest;
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
135pub struct UserOperation {
136 pub sender: Address,
138 pub nonce: Uint256,
140 #[serde(with = "serde_bytes::as_base64")]
142 pub call_data: Box<[u8]>,
143 pub call_gas_limit: u128,
145 pub verification_gas_limit: u128,
147 pub pre_verification_gas: u128,
149 pub max_fee_per_gas: u128,
151 pub max_priority_fee_per_gas: u128,
153 pub factory: Option<Address>,
155 pub factory_data: Option<Box<[u8]>>,
157 pub paymaster: Option<Address>,
159 pub paymaster_verification_gas_limit: Option<u128>,
161 pub paymaster_post_op_gas_limit: Option<u128>,
163 pub paymaster_data: Option<Box<[u8]>>,
165}
166
167impl UserOperation {
168 #[allow(clippy::too_many_arguments)]
170 pub fn new(
171 sender: Address,
172 nonce: Uint256,
173 call_data: &[u8],
174 call_gas_limit: u128,
175 verification_gas_limit: u128,
176 pre_verification_gas: u128,
177 max_fee_per_gas: u128,
178 max_priority_fee_per_gas: u128,
179 factory: Option<Address>,
180 factory_data: Option<&[u8]>,
181 paymaster: Option<Address>,
182 paymaster_verification_gas_limit: Option<u128>,
183 paymaster_post_op_gas_limit: Option<u128>,
184 paymaster_data: Option<&[u8]>,
185 ) -> Self {
186 Self {
187 sender,
188 nonce,
189 call_data: call_data.to_vec().into_boxed_slice(),
190 call_gas_limit,
191 verification_gas_limit,
192 pre_verification_gas,
193 max_fee_per_gas,
194 max_priority_fee_per_gas,
195 factory,
196 factory_data: factory_data.map(|data| data.to_vec().into_boxed_slice()),
197 paymaster,
198 paymaster_verification_gas_limit,
199 paymaster_post_op_gas_limit,
200 paymaster_data: paymaster_data.map(|data| data.to_vec().into_boxed_slice()),
201 }
202 }
203}
204
205#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
207pub struct UserOperationSignatureRequest {
208 pub user_op: UserOperation,
210 pub cohort_id: u32,
212 pub chain_id: u64,
214 pub aa_version: AAVersion,
216 pub context: Option<Context>,
218 pub signature_type: SignatureRequestType,
220}
221
222impl UserOperationSignatureRequest {
223 pub fn new(
225 user_op: UserOperation,
226 cohort_id: u32,
227 chain_id: u64,
228 aa_version: AAVersion,
229 context: Option<&Context>,
230 ) -> Self {
231 Self {
232 user_op,
233 cohort_id,
234 chain_id,
235 aa_version,
236 context: context.cloned(),
237 signature_type: SignatureRequestType::UserOp,
238 }
239 }
240}
241
242impl BaseSignatureRequest for UserOperationSignatureRequest {
243 fn cohort_id(&self) -> u32 {
244 self.cohort_id
245 }
246
247 fn chain_id(&self) -> u64 {
248 self.chain_id
249 }
250
251 fn signature_type(&self) -> SignatureRequestType {
252 self.signature_type
253 }
254
255 fn context(&self) -> Option<&Context> {
256 self.context.as_ref()
257 }
258
259 fn encrypt(
260 &self,
261 shared_secret: &SessionSharedSecret,
262 requester_public_key: &SessionStaticKey,
263 ) -> EncryptedThresholdSignatureRequest {
264 EncryptedThresholdSignatureRequest::new(
265 &DirectSignatureRequest::UserOp(self.clone()),
266 shared_secret,
267 requester_public_key,
268 )
269 }
270}
271
272#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
274pub struct PackedUserOperation {
275 pub sender: Address,
277 pub nonce: Uint256,
279 #[serde(with = "serde_bytes::as_base64")]
281 pub init_code: Box<[u8]>,
282 #[serde(with = "serde_bytes::as_base64")]
284 pub call_data: Box<[u8]>,
285 #[serde(with = "serde_bytes::as_base64")]
287 pub account_gas_limits: Box<[u8]>,
288 pub pre_verification_gas: u128,
290 #[serde(with = "serde_bytes::as_base64")]
292 pub gas_fees: Box<[u8]>,
293 #[serde(with = "serde_bytes::as_base64")]
295 pub paymaster_and_data: Box<[u8]>,
296}
297
298impl PackedUserOperation {
299 #[allow(clippy::too_many_arguments)]
301 pub fn new(
302 sender: Address,
303 nonce: Uint256,
304 init_code: &[u8],
305 call_data: &[u8],
306 account_gas_limits: &[u8],
307 pre_verification_gas: u128,
308 gas_fees: &[u8],
309 paymaster_and_data: &[u8],
310 ) -> Self {
311 Self {
312 sender,
313 nonce,
314 init_code: init_code.to_vec().into_boxed_slice(),
315 call_data: call_data.to_vec().into_boxed_slice(),
316 account_gas_limits: account_gas_limits.to_vec().into_boxed_slice(),
317 pre_verification_gas,
318 gas_fees: gas_fees.to_vec().into_boxed_slice(),
319 paymaster_and_data: paymaster_and_data.to_vec().into_boxed_slice(),
320 }
321 }
322
323 fn pack_account_gas_limits(call_gas_limit: u128, verification_gas_limit: u128) -> [u8; 32] {
325 let mut result = [0u8; 32];
326 result[0..16].copy_from_slice(&verification_gas_limit.to_be_bytes());
329 result[16..32].copy_from_slice(&call_gas_limit.to_be_bytes());
330 result
331 }
332
333 fn pack_gas_fees(max_fee_per_gas: u128, max_priority_fee_per_gas: u128) -> [u8; 32] {
335 let mut result = [0u8; 32];
336 result[0..16].copy_from_slice(&max_priority_fee_per_gas.to_be_bytes());
339 result[16..32].copy_from_slice(&max_fee_per_gas.to_be_bytes());
340 result
341 }
342
343 fn pack_paymaster_and_data(
345 paymaster: Option<&Address>,
346 paymaster_verification_gas_limit: Option<u128>,
347 paymaster_post_op_gas_limit: Option<u128>,
348 paymaster_data: Option<&[u8]>,
349 ) -> Vec<u8> {
350 match paymaster {
351 None => Vec::new(),
352 Some(addr) => {
353 let unwrapped_paymaster_data = match paymaster_data {
354 None => &[][..],
355 Some(data) => data,
356 };
357 let mut result = Vec::with_capacity(20 + 16 + 16 + unwrapped_paymaster_data.len());
358 result.extend_from_slice(addr.as_ref());
359
360 result.extend_from_slice(
362 &paymaster_verification_gas_limit.unwrap_or(0).to_be_bytes(),
363 );
364
365 result.extend_from_slice(&paymaster_post_op_gas_limit.unwrap_or(0).to_be_bytes());
367
368 result.extend_from_slice(unwrapped_paymaster_data);
369 result
370 }
371 }
372 }
373
374 fn pack_init_code(factory: Option<&Address>, factory_data: Option<&[u8]>) -> Vec<u8> {
375 match factory {
376 None => Vec::new(),
377 Some(addr) => {
378 let unwrapped_factory_data = match factory_data {
379 None => &[][..],
380 Some(data) => data,
381 };
382 let mut result = Vec::with_capacity(20 + unwrapped_factory_data.len());
383 result.extend_from_slice(addr.as_ref());
384 result.extend_from_slice(unwrapped_factory_data.as_ref());
385 result
386 }
387 }
388 }
389
390 pub fn from_user_operation(user_op: &UserOperation) -> Self {
392 let account_gas_limits =
393 Self::pack_account_gas_limits(user_op.call_gas_limit, user_op.verification_gas_limit);
394
395 let gas_fees =
396 Self::pack_gas_fees(user_op.max_fee_per_gas, user_op.max_priority_fee_per_gas);
397
398 let paymaster_and_data = Self::pack_paymaster_and_data(
399 user_op.paymaster.as_ref(),
400 user_op.paymaster_verification_gas_limit,
401 user_op.paymaster_post_op_gas_limit,
402 user_op.paymaster_data.as_ref().map(|data| data.as_ref()),
403 );
404
405 let init_code = Self::pack_init_code(
406 user_op.factory.as_ref(),
407 user_op.factory_data.as_ref().map(|data| data.as_ref()),
408 );
409
410 Self {
411 sender: user_op.sender,
412 nonce: user_op.nonce.clone(),
413 init_code: init_code.to_vec().into_boxed_slice(),
414 call_data: user_op.call_data.clone(),
415 account_gas_limits: account_gas_limits.to_vec().into_boxed_slice(),
416 pre_verification_gas: user_op.pre_verification_gas,
417 gas_fees: gas_fees.to_vec().into_boxed_slice(),
418 paymaster_and_data: paymaster_and_data.into_boxed_slice(),
419 }
420 }
421
422 pub fn to_eip712_message(&self, aa_version: &AAVersion) -> serde_json::Map<String, JsonValue> {
424 let mut message = serde_json::Map::new();
425 message.insert(
426 "sender".into(),
427 JsonValue::String(format!("0x{}", hex::encode(self.sender.as_ref()))),
428 );
429
430 message.insert("nonce".into(), JsonValue::String(self.nonce.to_string()));
432
433 message.insert(
434 "initCode".into(),
435 JsonValue::String(format!("0x{}", hex::encode(&self.init_code))),
436 );
437 message.insert(
438 "callData".into(),
439 JsonValue::String(format!("0x{}", hex::encode(&self.call_data))),
440 );
441 message.insert(
442 "accountGasLimits".into(),
443 JsonValue::String(format!("0x{}", hex::encode(&self.account_gas_limits))),
444 );
445 message.insert(
446 "preVerificationGas".into(),
447 JsonValue::String(self.pre_verification_gas.to_string()),
448 );
449 message.insert(
450 "gasFees".into(),
451 JsonValue::String(format!("0x{}", hex::encode(&self.gas_fees))),
452 );
453 message.insert(
454 "paymasterAndData".into(),
455 JsonValue::String(format!("0x{}", hex::encode(&self.paymaster_and_data))),
456 );
457
458 if *aa_version == AAVersion::MDT {
459 message.insert(
460 "entryPoint".into(),
461 JsonValue::String(ENTRYPOINT_V07.into()),
462 );
463 }
464
465 message
466 }
467
468 pub fn get_domain(
470 &self,
471 aa_version: &AAVersion,
472 chain_id: u64,
473 ) -> serde_json::Map<String, JsonValue> {
474 let mut domain = serde_json::Map::new();
475
476 let name = if *aa_version != AAVersion::MDT {
477 "ERC4337"
478 } else {
479 "MultiSigDeleGator"
480 };
481 domain.insert("name".into(), JsonValue::String(name.into()));
482 domain.insert("version".into(), JsonValue::String("1".into()));
483 domain.insert("chainId".into(), JsonValue::Number(chain_id.into()));
484
485 let verifying_contract = if *aa_version != AAVersion::MDT {
486 ENTRYPOINT_V08.into()
487 } else {
488 format!("0x{}", hex::encode(self.sender.as_ref()))
489 };
490 domain.insert(
491 "verifyingContract".into(),
492 JsonValue::String(verifying_contract),
493 );
494
495 domain
496 }
497
498 pub fn to_eip712_struct(
500 &self,
501 aa_version: &AAVersion,
502 chain_id: u64,
503 ) -> Result<serde_json::Map<String, JsonValue>, String> {
504 if *aa_version == AAVersion::V07 {
505 return Err(
506 "Not supported for AA v0.7.0 since it does not use EIP-712 signatures".into(),
507 );
508 }
509
510 let mut result = serde_json::Map::new();
511
512 let mut types = serde_json::Map::new();
514
515 let mut domain_type = Vec::new();
517 let mut name_field = serde_json::Map::new();
518 name_field.insert("name".into(), JsonValue::String("name".into()));
519 name_field.insert("type".into(), JsonValue::String("string".into()));
520 domain_type.push(JsonValue::Object(name_field));
521
522 let mut version_field = serde_json::Map::new();
523 version_field.insert("name".into(), JsonValue::String("version".into()));
524 version_field.insert("type".into(), JsonValue::String("string".into()));
525 domain_type.push(JsonValue::Object(version_field));
526
527 let mut chain_id_field = serde_json::Map::new();
528 chain_id_field.insert("name".into(), JsonValue::String("chainId".into()));
529 chain_id_field.insert("type".into(), JsonValue::String("uint256".into()));
530 domain_type.push(JsonValue::Object(chain_id_field));
531
532 let mut verifying_contract_field = serde_json::Map::new();
533 verifying_contract_field
534 .insert("name".into(), JsonValue::String("verifyingContract".into()));
535 verifying_contract_field.insert("type".into(), JsonValue::String("address".into()));
536 domain_type.push(JsonValue::Object(verifying_contract_field));
537
538 types.insert("EIP712Domain".into(), JsonValue::Array(domain_type));
539
540 let mut packed_user_op_type = Vec::new();
542
543 let field_specs = vec![
544 ("sender", "address"),
545 ("nonce", "uint256"),
546 ("initCode", "bytes"),
547 ("callData", "bytes"),
548 ("accountGasLimits", "bytes32"),
549 ("preVerificationGas", "uint256"),
550 ("gasFees", "bytes32"),
551 ("paymasterAndData", "bytes"),
552 ];
553
554 for (name, type_str) in field_specs {
555 let mut field = serde_json::Map::new();
556 field.insert("name".into(), JsonValue::String(name.into()));
557 field.insert("type".into(), JsonValue::String(type_str.into()));
558 packed_user_op_type.push(JsonValue::Object(field));
559 }
560
561 if *aa_version == AAVersion::MDT {
562 let mut entry_point_field = serde_json::Map::new();
563 entry_point_field.insert("name".into(), JsonValue::String("entryPoint".into()));
564 entry_point_field.insert("type".into(), JsonValue::String("address".into()));
565 packed_user_op_type.push(JsonValue::Object(entry_point_field));
566 }
567
568 types.insert(
569 "PackedUserOperation".into(),
570 JsonValue::Array(packed_user_op_type),
571 );
572
573 result.insert("types".into(), JsonValue::Object(types));
575 result.insert(
576 "primaryType".into(),
577 JsonValue::String("PackedUserOperation".into()),
578 );
579 result.insert(
580 "domain".into(),
581 JsonValue::Object(self.get_domain(aa_version, chain_id)),
582 );
583 result.insert(
584 "message".into(),
585 JsonValue::Object(self.to_eip712_message(aa_version)),
586 );
587
588 Ok(result)
589 }
590
591 pub fn to_v07_abi_encoded_fields(&self) -> Vec<u8> {
593 let init_code_hash = Keccak256::new().chain(self.init_code.as_ref()).finalize();
595 let call_data_hash = Keccak256::new().chain(self.call_data.as_ref()).finalize();
596 let paymaster_and_data_hash = Keccak256::new()
597 .chain(self.paymaster_and_data.as_ref())
598 .finalize();
599
600 let tokens = vec![
601 Token::Address(ethers::types::H160::from_slice(self.sender.as_ref())),
602 Token::Uint(ethers::types::U256::from_big_endian(
603 &self.nonce.to_be_bytes(),
604 )),
605 Token::FixedBytes(init_code_hash.to_vec()),
606 Token::FixedBytes(call_data_hash.to_vec()),
607 Token::FixedBytes(self.account_gas_limits.as_ref().to_vec()),
608 Token::Uint(ethers::types::U256::from(self.pre_verification_gas)),
609 Token::FixedBytes(self.gas_fees.as_ref().to_vec()),
610 Token::FixedBytes(paymaster_and_data_hash.to_vec()),
611 ];
612 encode(&tokens)
613 }
614
615 pub fn to_v07_hash(&self, chain_id: u64) -> Vec<u8> {
617 let hashed_packed_user_op = Keccak256::new()
618 .chain(self.to_v07_abi_encoded_fields())
619 .finalize()
620 .to_vec();
621 let tokens = vec![
622 Token::FixedBytes(hashed_packed_user_op),
623 Token::Address(ethers::types::H160::from_slice(
624 Address::from_str(ENTRYPOINT_V07)
625 .expect("Invalid entry point address")
626 .as_ref(),
627 )),
628 Token::Uint(ethers::types::U256::from(chain_id)),
629 ];
630 Keccak256::new().chain(encode(&tokens)).finalize().to_vec()
631 }
632}
633
634#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
636pub struct PackedUserOperationSignatureRequest {
637 pub packed_user_op: PackedUserOperation,
639 pub cohort_id: u32,
641 pub chain_id: u64,
643 pub aa_version: AAVersion,
645 pub context: Option<Context>,
647 pub signature_type: SignatureRequestType,
649}
650
651impl PackedUserOperationSignatureRequest {
652 pub fn new(
654 packed_user_op: PackedUserOperation,
655 cohort_id: u32,
656 chain_id: u64,
657 aa_version: AAVersion,
658 context: Option<&Context>,
659 ) -> Self {
660 Self {
661 packed_user_op,
662 cohort_id,
663 chain_id,
664 aa_version,
665 context: context.cloned(),
666 signature_type: SignatureRequestType::PackedUserOp,
667 }
668 }
669}
670
671impl BaseSignatureRequest for PackedUserOperationSignatureRequest {
672 fn cohort_id(&self) -> u32 {
673 self.cohort_id
674 }
675
676 fn chain_id(&self) -> u64 {
677 self.chain_id
678 }
679
680 fn signature_type(&self) -> SignatureRequestType {
681 self.signature_type
682 }
683
684 fn context(&self) -> Option<&Context> {
685 self.context.as_ref()
686 }
687
688 fn encrypt(
689 &self,
690 shared_secret: &SessionSharedSecret,
691 requester_public_key: &SessionStaticKey,
692 ) -> EncryptedThresholdSignatureRequest {
693 EncryptedThresholdSignatureRequest::new(
694 &DirectSignatureRequest::PackedUserOp(self.clone()),
695 shared_secret,
696 requester_public_key,
697 )
698 }
699}
700
701#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
703pub struct SignatureResponse {
704 pub signer: Address,
706 #[serde(rename = "message_hash", with = "serde_bytes::as_base64")]
708 pub hash: Box<[u8]>,
709 #[serde(with = "serde_bytes::as_base64")]
711 pub signature: Box<[u8]>,
712 pub signature_type: SignatureRequestType,
714}
715
716impl SignatureResponse {
717 pub fn new(
719 signer: Address,
720 hash: &[u8],
721 signature: &[u8],
722 signature_type: SignatureRequestType,
723 ) -> Self {
724 Self {
725 signer,
726 hash: hash.to_vec().into_boxed_slice(),
727 signature: signature.to_vec().into_boxed_slice(),
728 signature_type,
729 }
730 }
731
732 pub fn encrypt(
734 &self,
735 shared_secret: &SessionSharedSecret,
736 ) -> EncryptedThresholdSignatureResponse {
737 EncryptedThresholdSignatureResponse::new(self, shared_secret)
738 }
739}
740
741impl<'a> ProtocolObjectInner<'a> for UserOperationSignatureRequest {
744 fn brand() -> [u8; 4] {
745 *b"UOSR"
746 }
747
748 fn version() -> (u16, u16) {
749 (1, 0)
750 }
751
752 fn unversioned_to_bytes(&self) -> Box<[u8]> {
753 messagepack_serialize(&self)
754 }
755
756 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
757 if minor_version == 0 {
758 Some(messagepack_deserialize(bytes))
759 } else {
760 None
761 }
762 }
763}
764
765impl<'a> ProtocolObject<'a> for UserOperationSignatureRequest {}
766
767impl<'a> ProtocolObjectInner<'a> for PackedUserOperationSignatureRequest {
768 fn brand() -> [u8; 4] {
769 *b"PUOS"
770 }
771
772 fn version() -> (u16, u16) {
773 (1, 0)
774 }
775
776 fn unversioned_to_bytes(&self) -> Box<[u8]> {
777 messagepack_serialize(&self)
778 }
779
780 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
781 if minor_version == 0 {
782 Some(messagepack_deserialize(bytes))
783 } else {
784 None
785 }
786 }
787}
788
789impl<'a> ProtocolObject<'a> for PackedUserOperationSignatureRequest {}
790
791impl<'a> ProtocolObjectInner<'a> for SignatureResponse {
792 fn brand() -> [u8; 4] {
793 *b"SigR"
794 }
795
796 fn version() -> (u16, u16) {
797 (1, 0)
798 }
799
800 fn unversioned_to_bytes(&self) -> Box<[u8]> {
801 messagepack_serialize(&self)
802 }
803
804 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
805 if minor_version == 0 {
806 Some(messagepack_deserialize(bytes))
807 } else {
808 None
809 }
810 }
811}
812
813impl<'a> ProtocolObject<'a> for SignatureResponse {}
814
815impl<'a> ProtocolObjectInner<'a> for UserOperation {
816 fn brand() -> [u8; 4] {
817 *b"UOPR"
818 }
819
820 fn version() -> (u16, u16) {
821 (1, 0)
822 }
823
824 fn unversioned_to_bytes(&self) -> Box<[u8]> {
825 messagepack_serialize(&self)
826 }
827
828 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
829 if minor_version == 0 {
830 Some(messagepack_deserialize(bytes))
831 } else {
832 None
833 }
834 }
835}
836
837impl<'a> ProtocolObject<'a> for UserOperation {}
838
839impl<'a> ProtocolObjectInner<'a> for PackedUserOperation {
840 fn brand() -> [u8; 4] {
841 *b"PUOP"
842 }
843
844 fn version() -> (u16, u16) {
845 (1, 0)
846 }
847
848 fn unversioned_to_bytes(&self) -> Box<[u8]> {
849 messagepack_serialize(&self)
850 }
851
852 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
853 if minor_version == 0 {
854 Some(messagepack_deserialize(bytes))
855 } else {
856 None
857 }
858 }
859}
860
861impl<'a> ProtocolObject<'a> for PackedUserOperation {}
862
863#[derive(Debug, Clone, PartialEq, Eq)]
865pub enum DirectSignatureRequest {
866 UserOp(UserOperationSignatureRequest),
868 PackedUserOp(PackedUserOperationSignatureRequest),
870}
871
872impl DirectSignatureRequest {
873 pub fn from_bytes(bytes: &[u8]) -> Result<Self, String> {
875 if bytes.len() < 4 {
876 return Err("Insufficient bytes for brand identifier".into());
877 }
878
879 let brand = [bytes[0], bytes[1], bytes[2], bytes[3]];
881
882 match &brand {
883 b"UOSR" => UserOperationSignatureRequest::from_bytes(bytes)
884 .map(Self::UserOp)
885 .map_err(|e| format!("Failed to deserialize UserOperationSignatureRequest: {}", e)),
886 b"PUOS" => PackedUserOperationSignatureRequest::from_bytes(bytes)
887 .map(Self::PackedUserOp)
888 .map_err(|e| {
889 format!(
890 "Failed to deserialize PackedUserOperationSignatureRequest: {}",
891 e
892 )
893 }),
894 _ => Err(format!("Unknown signature request brand: {:?}", brand)),
895 }
896 }
897
898 pub fn signature_type(&self) -> SignatureRequestType {
900 match self {
901 Self::UserOp(req) => req.signature_type(),
902 Self::PackedUserOp(req) => req.signature_type(),
903 }
904 }
905
906 pub fn cohort_id(&self) -> u32 {
908 match self {
909 Self::UserOp(req) => req.cohort_id(),
910 Self::PackedUserOp(req) => req.cohort_id(),
911 }
912 }
913
914 pub fn chain_id(&self) -> u64 {
916 match self {
917 Self::UserOp(req) => req.chain_id(),
918 Self::PackedUserOp(req) => req.chain_id(),
919 }
920 }
921
922 pub fn context(&self) -> Option<&Context> {
924 match self {
925 Self::UserOp(req) => req.context(),
926 Self::PackedUserOp(req) => req.context(),
927 }
928 }
929
930 pub fn encrypt(
932 &self,
933 shared_secret: &SessionSharedSecret,
934 requester_public_key: &SessionStaticKey,
935 ) -> EncryptedThresholdSignatureRequest {
936 match self {
937 Self::UserOp(req) => req.encrypt(shared_secret, requester_public_key),
938 Self::PackedUserOp(req) => req.encrypt(shared_secret, requester_public_key),
939 }
940 }
941}
942
943pub fn deserialize_signature_request(bytes: &[u8]) -> Result<DirectSignatureRequest, String> {
945 DirectSignatureRequest::from_bytes(bytes)
946}
947
948pub fn serialize_signature_request(request: &DirectSignatureRequest) -> Box<[u8]> {
950 match request {
951 DirectSignatureRequest::UserOp(req) => req.to_bytes(),
952 DirectSignatureRequest::PackedUserOp(req) => req.to_bytes(),
953 }
954}
955
956#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
958pub struct EncryptedThresholdSignatureRequest {
959 pub cohort_id: u32,
961
962 pub requester_public_key: SessionStaticKey,
964
965 #[serde(with = "serde_bytes::as_base64")]
966 ciphertext: Box<[u8]>,
968}
969
970impl EncryptedThresholdSignatureRequest {
971 fn new(
972 request: &DirectSignatureRequest,
973 shared_secret: &SessionSharedSecret,
974 requester_public_key: &SessionStaticKey,
975 ) -> Self {
976 let serialization_bytes = serialize_signature_request(request);
977 let ciphertext = encrypt_with_shared_secret(shared_secret, &serialization_bytes)
978 .expect("Encryption failed - out of memory?");
979 Self {
980 cohort_id: request.cohort_id(),
981 requester_public_key: *requester_public_key,
982 ciphertext,
983 }
984 }
985
986 pub fn decrypt(
988 &self,
989 shared_secret: &SessionSharedSecret,
990 ) -> Result<DirectSignatureRequest, DecryptionError> {
991 let decryption_request_bytes = decrypt_with_shared_secret(shared_secret, &self.ciphertext)?;
992 let decryption_request =
993 deserialize_signature_request(&decryption_request_bytes).map_err(|err| {
994 DecryptionError::DeserializationFailed(DeserializationError::BadPayload {
995 error_msg: err.to_string(),
996 })
997 })?;
998 Ok(decryption_request)
999 }
1000}
1001
1002impl<'a> ProtocolObjectInner<'a> for EncryptedThresholdSignatureRequest {
1003 fn version() -> (u16, u16) {
1004 (1, 0)
1005 }
1006
1007 fn brand() -> [u8; 4] {
1008 *b"ETSR"
1009 }
1010
1011 fn unversioned_to_bytes(&self) -> Box<[u8]> {
1012 messagepack_serialize(&self)
1013 }
1014
1015 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
1016 if minor_version == 0 {
1017 Some(messagepack_deserialize(bytes))
1018 } else {
1019 None
1020 }
1021 }
1022}
1023
1024impl<'a> ProtocolObject<'a> for EncryptedThresholdSignatureRequest {}
1025
1026#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
1028pub struct EncryptedThresholdSignatureResponse {
1029 #[serde(with = "serde_bytes::as_base64")]
1030 ciphertext: Box<[u8]>,
1031}
1032
1033impl EncryptedThresholdSignatureResponse {
1034 fn new(response: &SignatureResponse, shared_secret: &SessionSharedSecret) -> Self {
1035 let ciphertext = encrypt_with_shared_secret(shared_secret, &response.to_bytes())
1036 .expect("Encryption failed - out of memory?");
1037 Self { ciphertext }
1038 }
1039
1040 pub fn decrypt(
1042 &self,
1043 shared_secret: &SessionSharedSecret,
1044 ) -> Result<SignatureResponse, DecryptionError> {
1045 let decryption_response_bytes =
1046 decrypt_with_shared_secret(shared_secret, &self.ciphertext)?;
1047 let decryption_response = SignatureResponse::from_bytes(&decryption_response_bytes)
1048 .map_err(DecryptionError::DeserializationFailed)?;
1049 Ok(decryption_response)
1050 }
1051}
1052
1053impl<'a> ProtocolObjectInner<'a> for EncryptedThresholdSignatureResponse {
1054 fn version() -> (u16, u16) {
1055 (1, 0)
1056 }
1057
1058 fn brand() -> [u8; 4] {
1059 *b"ETRe"
1060 }
1061
1062 fn unversioned_to_bytes(&self) -> Box<[u8]> {
1063 messagepack_serialize(&self)
1064 }
1065
1066 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
1067 if minor_version == 0 {
1068 Some(messagepack_deserialize(bytes))
1069 } else {
1070 None
1071 }
1072 }
1073}
1074
1075impl<'a> ProtocolObject<'a> for EncryptedThresholdSignatureResponse {}
1076
1077#[cfg(test)]
1078mod tests {
1079 use super::*;
1080 use crate::session::key::SessionStaticSecret;
1081 use alloc::string::ToString;
1082
1083 #[test]
1084 fn test_signature_type() {
1085 assert_eq!(SignatureRequestType::UserOp.as_u8(), 0,);
1086 assert_eq!(SignatureRequestType::PackedUserOp.as_u8(), 1,);
1087
1088 assert_eq!(
1089 SignatureRequestType::from_u8(0).unwrap(),
1090 SignatureRequestType::UserOp,
1091 );
1092 assert_eq!(
1093 SignatureRequestType::from_u8(1).unwrap(),
1094 SignatureRequestType::PackedUserOp,
1095 );
1096
1097 let result = SignatureRequestType::from_u8(22);
1098 assert!(result
1099 .unwrap_err()
1100 .contains("Invalid signature request type"));
1101
1102 assert_eq!(SignatureRequestType::UserOp.to_string(), "userop",);
1103 assert_eq!(
1104 SignatureRequestType::PackedUserOp.to_string(),
1105 "packedUserOp",
1106 );
1107 }
1108
1109 #[test]
1110 fn test_aa_version() {
1111 assert_eq!(AAVersion::from_str("0.7.0").unwrap(), AAVersion::V07);
1112 assert_eq!(AAVersion::from_str("0.8.0").unwrap(), AAVersion::V08);
1113 assert_eq!(AAVersion::from_str("mdt").unwrap(), AAVersion::MDT);
1114
1115 let result = AAVersion::from_str("invalid_version");
1116 assert!(result.unwrap_err().contains("Invalid AA version"));
1117
1118 assert_eq!(AAVersion::V07.to_string(), "0.7.0",);
1119 assert_eq!(AAVersion::V08.to_string(), "0.8.0",);
1120 assert_eq!(AAVersion::MDT.to_string(), "mdt",);
1121 }
1122
1123 #[test]
1124 fn test_user_operation() {
1125 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1126 let paymaster =
1127 Some(Address::from_str("0xabcdefabcdefabcdefabcdefabcdefabcdefabcd").unwrap());
1128 let factory =
1129 Some(Address::from_str("0x12345678901234567890abcdefabcdefabcdefab").unwrap());
1130
1131 let user_op = UserOperation::new(
1132 sender,
1133 Uint256::from(42),
1134 b"call_data",
1135 100000,
1136 200000,
1137 50000,
1138 20_000_000_000, 1_000_000_000, factory,
1141 Some(b"factory_data"),
1142 paymaster,
1143 Some(300000),
1144 Some(100000),
1145 Some(b"paymaster_data"),
1146 );
1147
1148 assert_eq!(user_op.sender, sender);
1149 assert_eq!(user_op.nonce, Uint256::from(42));
1150 assert_eq!(user_op.call_data.as_ref(), b"call_data");
1151 assert_eq!(user_op.call_gas_limit, 100000);
1152 assert_eq!(user_op.verification_gas_limit, 200000);
1153 assert_eq!(user_op.pre_verification_gas, 50000);
1154 assert_eq!(user_op.max_fee_per_gas, 20_000_000_000);
1155 assert_eq!(user_op.max_priority_fee_per_gas, 1_000_000_000);
1156 assert_eq!(user_op.factory, factory);
1157 assert_eq!(
1158 user_op.factory_data.clone().unwrap(),
1159 b"factory_data".to_vec().into_boxed_slice()
1160 );
1161 assert_eq!(user_op.paymaster, paymaster);
1162 assert_eq!(user_op.paymaster_verification_gas_limit.unwrap(), 300000);
1163 assert_eq!(user_op.paymaster_post_op_gas_limit.unwrap(), 100000);
1164 assert_eq!(
1165 user_op.paymaster_data.clone().unwrap(),
1166 b"paymaster_data".to_vec().into_boxed_slice()
1167 );
1168
1169 let serialized_user_op = user_op.to_bytes();
1170 let deserialized_user_op = UserOperation::from_bytes(&serialized_user_op).unwrap();
1171 assert_eq!(user_op, deserialized_user_op);
1172 }
1173
1174 #[test]
1175 fn test_packed_user_operation() {
1176 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1177
1178 let packed_user_op = PackedUserOperation::new(
1179 sender,
1180 Uint256::from(42),
1181 b"init_code",
1182 b"call_data",
1183 b"account_gas_limits",
1184 50000,
1185 b"gas_fees",
1186 b"paymaster_and_data",
1187 );
1188 assert_eq!(packed_user_op.sender, sender);
1189 assert_eq!(packed_user_op.nonce, Uint256::from(42));
1190 assert_eq!(packed_user_op.init_code.as_ref(), b"init_code");
1191 assert_eq!(packed_user_op.call_data.as_ref(), b"call_data");
1192 assert_eq!(
1193 packed_user_op.account_gas_limits.as_ref(),
1194 b"account_gas_limits"
1195 );
1196 assert_eq!(packed_user_op.pre_verification_gas, 50000);
1197 assert_eq!(packed_user_op.gas_fees.as_ref(), b"gas_fees");
1198 assert_eq!(
1199 packed_user_op.paymaster_and_data.as_ref(),
1200 b"paymaster_and_data"
1201 );
1202
1203 let serialized_packed_user_op = packed_user_op.to_bytes();
1204 let deserialized_packed_user_op =
1205 PackedUserOperation::from_bytes(&serialized_packed_user_op).unwrap();
1206 assert_eq!(packed_user_op, deserialized_packed_user_op);
1207
1208 let packed_gas_limits = PackedUserOperation::pack_account_gas_limits(100000, 200000);
1210 let mut expected_gas_limits = [0u8; 32];
1211 expected_gas_limits[0..16].copy_from_slice(&200000u128.to_be_bytes());
1212 expected_gas_limits[16..32].copy_from_slice(&100000u128.to_be_bytes());
1213 assert_eq!(packed_gas_limits, expected_gas_limits);
1214
1215 let packed_gas_fees = PackedUserOperation::pack_gas_fees(20_000_000_000, 1_000_000_000);
1217 let mut expected_gas_fees = [0u8; 32];
1218 expected_gas_fees[0..16].copy_from_slice(&1_000_000_000u128.to_be_bytes());
1219 expected_gas_fees[16..32].copy_from_slice(&20_000_000_000u128.to_be_bytes());
1220 assert_eq!(packed_gas_fees, expected_gas_fees);
1221
1222 let packed_init_code = PackedUserOperation::pack_init_code(Some(&sender), None);
1224 assert_eq!(packed_init_code, sender.as_ref().to_vec());
1225
1226 let packed_init_code_with_data =
1228 PackedUserOperation::pack_init_code(Some(&sender), Some(b"data"));
1229 let mut expected = sender.as_ref().to_vec();
1230 expected.extend_from_slice(b"data");
1231 assert_eq!(packed_init_code_with_data, expected);
1232
1233 let packed_paymaster_and_data = PackedUserOperation::pack_paymaster_and_data(
1235 Some(&sender),
1236 Some(300000),
1237 Some(100000),
1238 None,
1239 );
1240 let mut expected_paymaster = Vec::new();
1241 expected_paymaster.extend_from_slice(sender.as_ref());
1242 expected_paymaster.extend_from_slice(&300000u128.to_be_bytes());
1243 expected_paymaster.extend_from_slice(&100000u128.to_be_bytes());
1244 assert_eq!(packed_paymaster_and_data, expected_paymaster);
1245
1246 let packed_paymaster_and_data_with_data = PackedUserOperation::pack_paymaster_and_data(
1248 Some(&sender),
1249 Some(300000),
1250 Some(100000),
1251 Some(b"data"),
1252 );
1253 let mut expected_paymaster_with_data = Vec::new();
1254 expected_paymaster_with_data.extend_from_slice(sender.as_ref());
1255 expected_paymaster_with_data.extend_from_slice(&300000u128.to_be_bytes());
1256 expected_paymaster_with_data.extend_from_slice(&100000u128.to_be_bytes());
1257 expected_paymaster_with_data.extend_from_slice(b"data");
1258 assert_eq!(
1259 packed_paymaster_and_data_with_data,
1260 expected_paymaster_with_data
1261 );
1262 }
1263
1264 #[test]
1265 fn test_signature_response_serialization() {
1266 let signer = Address::from_str("0x789abcdef0123456789abcdef0123456789abcde").unwrap();
1267 let hash = b"test_hash";
1268 let signature = b"test_signature";
1269 let response =
1270 SignatureResponse::new(signer, hash, signature, SignatureRequestType::UserOp);
1271
1272 let bytes = response.to_bytes();
1273 let deserialized = SignatureResponse::from_bytes(&bytes).unwrap();
1274
1275 assert_eq!(response, deserialized);
1276 assert_eq!(deserialized.signer, signer);
1277 assert_eq!(deserialized.hash.as_ref(), hash);
1278 assert_eq!(deserialized.signature.as_ref(), signature);
1279 assert_eq!(deserialized.signature_type, SignatureRequestType::UserOp);
1280 }
1281
1282 #[test]
1283 fn test_aa_version_serialization() {
1284 let sender = Address::from_str("0x789abcdef0123456789abcdef0123456789abcde").unwrap();
1286 let user_op = UserOperation::new(
1287 sender,
1288 Uint256::from(1),
1289 b"",
1290 0,
1291 0,
1292 0,
1293 0,
1294 0,
1295 None,
1296 Some(b""),
1297 None,
1298 Some(0),
1299 Some(0),
1300 Some(b""),
1301 );
1302 let request_v08 = UserOperationSignatureRequest::new(
1303 user_op,
1304 1,
1305 137,
1306 AAVersion::V08,
1307 Some(&Context::new("test_context")),
1308 );
1309
1310 let bytes = request_v08.to_bytes();
1311 let deserialized_v08 = UserOperationSignatureRequest::from_bytes(&bytes).unwrap();
1312 assert_eq!(deserialized_v08.aa_version, AAVersion::V08);
1313
1314 let user_op = UserOperation::new(
1316 sender,
1317 Uint256::from(1),
1318 b"",
1319 0,
1320 0,
1321 0,
1322 0,
1323 0,
1324 None,
1325 Some(b""),
1326 None,
1327 Some(0),
1328 Some(0),
1329 Some(b""),
1330 );
1331 let request_v07 = UserOperationSignatureRequest::new(
1332 user_op,
1333 1,
1334 137,
1335 AAVersion::V07,
1336 Some(&Context::new("test_context")),
1337 );
1338
1339 let bytes = request_v07.to_bytes();
1340 let deserialized_v07 = UserOperationSignatureRequest::from_bytes(&bytes).unwrap();
1341 assert_eq!(deserialized_v07.aa_version, AAVersion::V07);
1342
1343 let sender_mdt = Address::from_str("0xabcdef0123456789abcdef0123456789abcdef01").unwrap();
1345 let user_op_mdt = UserOperation::new(
1346 sender_mdt,
1347 Uint256::from(2),
1348 b"call_data_mdt",
1349 0,
1350 0,
1351 0,
1352 0,
1353 0,
1354 None,
1356 None,
1357 None,
1358 None,
1359 None,
1360 None,
1361 );
1362 let request_mdt = UserOperationSignatureRequest::new(
1363 user_op_mdt,
1364 2,
1365 137,
1366 AAVersion::MDT,
1367 Some(&Context::new("test_context")),
1368 );
1369
1370 let bytes_mdt = request_mdt.to_bytes();
1371 let deserialized_mdt = UserOperationSignatureRequest::from_bytes(&bytes_mdt).unwrap();
1372 assert_eq!(deserialized_mdt.aa_version, AAVersion::MDT);
1373 }
1374
1375 #[test]
1376 fn test_packed_user_operation_conversion() {
1377 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1378 let paymaster =
1379 Some(Address::from_str("0xabcdefabcdefabcdefabcdefabcdefabcdefabcd").unwrap());
1380 let factory =
1381 Some(Address::from_str("0x12345678901234567890abcdefabcdefabcdefab").unwrap());
1382
1383 let user_op = UserOperation::new(
1384 sender,
1385 Uint256::from(100),
1386 b"execution_data",
1387 150000,
1388 250000,
1389 60000,
1390 30_000_000_000,
1391 2_000_000_000,
1392 factory,
1393 Some(b"factory_data"),
1394 paymaster,
1395 Some(400000),
1396 Some(200000),
1397 Some(b"paymaster_specific_data"),
1398 );
1399
1400 let packed = PackedUserOperation::from_user_operation(&user_op);
1401
1402 assert_eq!(packed.sender, user_op.sender);
1403 assert_eq!(packed.nonce, user_op.nonce);
1404 assert_eq!(packed.init_code.len(), 32);
1405 assert_eq!(packed.call_data, user_op.call_data);
1406 assert_eq!(packed.pre_verification_gas, user_op.pre_verification_gas);
1407
1408 assert_eq!(packed.account_gas_limits.len(), 32);
1410
1411 assert_eq!(packed.gas_fees.len(), 32);
1413
1414 assert_eq!(
1416 packed.paymaster_and_data.len(),
1417 20 + 16 + 16 + b"paymaster_specific_data".len()
1418 );
1419 }
1420
1421 #[test]
1422 fn test_user_operation_signature_request_serialization() {
1423 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1424 let paymaster =
1425 Some(Address::from_str("0xabcdefabcdefabcdefabcdefabcdefabcdefabcd").unwrap());
1426 let factory =
1427 Some(Address::from_str("0x12345678901234567890abcdefabcdefabcdefab").unwrap());
1428 let cohort_id = 1;
1429 let chain_id = 137;
1430
1431 let user_op = UserOperation::new(
1432 sender,
1433 Uint256::from(42),
1434 b"call_data",
1435 100000,
1436 200000,
1437 50000,
1438 20_000_000_000, 1_000_000_000, factory,
1441 Some(b"factory_data"),
1442 paymaster,
1443 Some(300000),
1444 Some(100000),
1445 Some(b"paymaster_data"),
1446 );
1447 let request = UserOperationSignatureRequest::new(
1448 user_op,
1449 cohort_id,
1450 chain_id,
1451 AAVersion::V08,
1452 Some(&Context::new("test_context")),
1453 );
1454
1455 let bytes = request.to_bytes();
1456 let deserialized = UserOperationSignatureRequest::from_bytes(&bytes).unwrap();
1457
1458 assert_eq!(request, deserialized);
1459 assert_eq!(deserialized.user_op.sender, sender);
1460 assert_eq!(deserialized.user_op.nonce, Uint256::from(42));
1461 assert_eq!(deserialized.aa_version, AAVersion::V08);
1462 assert_eq!(deserialized.cohort_id, cohort_id);
1463 assert_eq!(deserialized.chain_id, chain_id);
1464 assert_eq!(
1465 deserialized.context.as_ref().unwrap().as_ref(),
1466 "test_context"
1467 );
1468
1469 let direct_request = DirectSignatureRequest::from_bytes(&bytes).unwrap();
1471 assert_eq!(direct_request, DirectSignatureRequest::UserOp(request));
1472 assert_eq!(
1473 direct_request.signature_type(),
1474 SignatureRequestType::UserOp
1475 );
1476 assert_eq!(direct_request.cohort_id(), cohort_id);
1477 assert_eq!(direct_request.chain_id(), chain_id);
1478 assert_eq!(direct_request.context().unwrap().as_ref(), "test_context");
1479 }
1480
1481 #[test]
1482 fn test_packed_user_operation_signature_request_serialization() {
1483 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1484 let cohort_id = 1;
1485 let chain_id = 137;
1486
1487 let packed_user_op = PackedUserOperation::new(
1488 sender,
1489 Uint256::from(42),
1490 b"init_code",
1491 b"call_data",
1492 b"account_gas_limits",
1493 50000,
1494 b"gas_fees",
1495 b"paymaster_and_data",
1496 );
1497 let request = PackedUserOperationSignatureRequest::new(
1498 packed_user_op,
1499 cohort_id,
1500 chain_id,
1501 AAVersion::V08,
1502 Some(&Context::new("test_context")),
1503 );
1504
1505 let bytes = request.to_bytes();
1506 let deserialized = PackedUserOperationSignatureRequest::from_bytes(&bytes).unwrap();
1507
1508 assert_eq!(request, deserialized);
1509 assert_eq!(deserialized.packed_user_op.sender, sender);
1510 assert_eq!(deserialized.packed_user_op.nonce, Uint256::from(42));
1511 assert_eq!(deserialized.aa_version, AAVersion::V08);
1512 assert_eq!(deserialized.cohort_id, cohort_id);
1513 assert_eq!(deserialized.chain_id, chain_id);
1514 assert_eq!(
1515 deserialized.context.as_ref().unwrap().as_ref(),
1516 "test_context"
1517 );
1518
1519 let direct_request = DirectSignatureRequest::from_bytes(&bytes).unwrap();
1521 assert_eq!(
1522 direct_request,
1523 DirectSignatureRequest::PackedUserOp(request)
1524 );
1525 assert_eq!(
1526 direct_request.signature_type(),
1527 SignatureRequestType::PackedUserOp
1528 );
1529 assert_eq!(direct_request.cohort_id(), cohort_id);
1530 assert_eq!(direct_request.chain_id(), chain_id);
1531 assert_eq!(direct_request.context().unwrap().as_ref(), "test_context");
1532 }
1533
1534 #[test]
1535 fn test_deserialize_signature_request_invalid_brand() {
1536 let invalid_bytes = b"XXXXinvalid_data";
1537 let result = deserialize_signature_request(invalid_bytes);
1538 assert!(result
1539 .unwrap_err()
1540 .contains("Unknown signature request brand"));
1541 }
1542
1543 fn validate_eip712_domain(
1544 eip712_domain: &serde_json::Map<String, JsonValue>,
1545 packed_user_op: &PackedUserOperation,
1546 is_v08: bool,
1547 ) {
1548 assert_eq!(eip712_domain.get("version").unwrap(), "1");
1549 assert_eq!(eip712_domain.get("chainId").unwrap(), 137);
1550 if is_v08 {
1551 assert_eq!(eip712_domain.get("name").unwrap(), "ERC4337");
1552 assert_eq!(
1553 eip712_domain.get("verifyingContract").unwrap(),
1554 ENTRYPOINT_V08
1555 );
1556 } else {
1557 assert_eq!(eip712_domain.get("name").unwrap(), "MultiSigDeleGator");
1558 assert_eq!(
1559 eip712_domain.get("verifyingContract").unwrap(),
1560 &JsonValue::String(packed_user_op.sender.to_checksum_address().to_string())
1561 );
1562 }
1563 }
1564
1565 fn validate_eip712_message(
1566 eip712_message: &serde_json::Map<String, JsonValue>,
1567 packed_user_op: &PackedUserOperation,
1568 is_v08: bool,
1569 ) {
1570 assert_eq!(
1571 eip712_message.get("sender").unwrap(),
1572 &JsonValue::String(packed_user_op.sender.to_checksum_address().to_string())
1573 );
1574 assert_eq!(
1575 eip712_message.get("nonce").unwrap(),
1576 &JsonValue::String(packed_user_op.nonce.to_string())
1577 );
1578 assert_eq!(
1579 eip712_message.get("initCode").unwrap(),
1580 &JsonValue::String(format!("0x{}", hex::encode(&packed_user_op.init_code)))
1581 );
1582 assert_eq!(
1583 eip712_message.get("callData").unwrap(),
1584 &JsonValue::String(format!("0x{}", hex::encode(&packed_user_op.call_data)))
1585 );
1586 assert_eq!(
1587 eip712_message.get("accountGasLimits").unwrap(),
1588 &JsonValue::String(format!(
1589 "0x{}",
1590 hex::encode(&packed_user_op.account_gas_limits)
1591 ))
1592 );
1593 assert_eq!(
1594 eip712_message.get("preVerificationGas").unwrap(),
1595 &JsonValue::String(format!("{}", packed_user_op.pre_verification_gas))
1596 );
1597 assert_eq!(
1598 eip712_message.get("gasFees").unwrap(),
1599 &JsonValue::String(format!("0x{}", hex::encode(&packed_user_op.gas_fees)))
1600 );
1601 assert_eq!(
1602 eip712_message.get("paymasterAndData").unwrap(),
1603 &JsonValue::String(format!(
1604 "0x{}",
1605 hex::encode(&packed_user_op.paymaster_and_data)
1606 ))
1607 );
1608
1609 if is_v08 {
1610 assert!(eip712_message.get("entryPoint").is_none());
1612 } else {
1613 assert_eq!(
1615 eip712_message.get("entryPoint").unwrap(),
1616 &JsonValue::String(ENTRYPOINT_V07.into())
1617 );
1618 }
1619 }
1620
1621 fn validate_eip712_types(eip712_types: &serde_json::Map<String, JsonValue>, is_v08: bool) {
1622 let packed_user_op_type = eip712_types
1624 .get("PackedUserOperation")
1625 .unwrap()
1626 .as_array()
1627 .unwrap();
1628 let expected_packed_user_op_fields = vec![
1629 ("sender", "address"),
1630 ("nonce", "uint256"),
1631 ("initCode", "bytes"),
1632 ("callData", "bytes"),
1633 ("accountGasLimits", "bytes32"),
1634 ("preVerificationGas", "uint256"),
1635 ("gasFees", "bytes32"),
1636 ("paymasterAndData", "bytes"),
1637 ("entryPoint", "address"),
1638 ];
1639 for (i, (field, field_type)) in expected_packed_user_op_fields.iter().enumerate() {
1640 if is_v08 && *field == "entryPoint" {
1641 continue;
1643 }
1644 let field_obj = packed_user_op_type.get(i).unwrap().as_object().unwrap();
1645 assert_eq!(field_obj.get("name").unwrap(), field);
1646 assert_eq!(field_obj.get("type").unwrap(), field_type);
1647 }
1648 }
1649
1650 #[test]
1651 fn test_packed_user_operation_to_eip712_struct() {
1652 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1653 let packed_user_op = PackedUserOperation::new(
1654 sender,
1655 Uint256::from(42),
1656 b"init_code",
1657 b"call_data",
1658 b"account_gas_limits",
1659 50000,
1660 b"gas_fees",
1661 b"paymaster_and_data",
1662 );
1663
1664 let eip712_struct_v07 = packed_user_op.to_eip712_struct(&AAVersion::V07, 137);
1666 assert!(eip712_struct_v07.is_err());
1667 assert!(eip712_struct_v07
1668 .unwrap_err()
1669 .contains("Not supported for AA v0.7.0 since it does not use EIP-712 signatures"));
1670
1671 let eip712_struct_v08 = packed_user_op
1673 .to_eip712_struct(&AAVersion::V08, 137)
1674 .unwrap();
1675
1676 assert_eq!(
1677 eip712_struct_v08.get("primaryType").unwrap(),
1678 &JsonValue::String("PackedUserOperation".into())
1679 );
1680
1681 let v08_types = eip712_struct_v08.get("types").unwrap().as_object().unwrap();
1682 validate_eip712_types(&v08_types, true);
1683
1684 let v08_domain = eip712_struct_v08
1685 .get("domain")
1686 .unwrap()
1687 .as_object()
1688 .unwrap();
1689 validate_eip712_domain(&v08_domain, &packed_user_op, true);
1690 let v08_message = eip712_struct_v08.get("message").unwrap();
1691 validate_eip712_message(v08_message.as_object().unwrap(), &packed_user_op, true);
1692
1693 let eip712_struct_mdt = packed_user_op
1695 .to_eip712_struct(&AAVersion::MDT, 137)
1696 .unwrap();
1697 assert_eq!(
1698 eip712_struct_mdt.get("primaryType").unwrap(),
1699 &JsonValue::String("PackedUserOperation".into())
1700 );
1701
1702 let mdt_types = eip712_struct_mdt.get("types").unwrap().as_object().unwrap();
1703 validate_eip712_types(&mdt_types, false);
1704
1705 let mdt_domain = eip712_struct_mdt
1706 .get("domain")
1707 .unwrap()
1708 .as_object()
1709 .unwrap();
1710 validate_eip712_domain(&mdt_domain, &packed_user_op, false);
1711 let mdt_message = eip712_struct_mdt.get("message").unwrap();
1712 validate_eip712_message(mdt_message.as_object().unwrap(), &packed_user_op, false);
1713 }
1714
1715 #[test]
1716 fn test_packed_user_operation_to_v07_abi_encoded_fields() {
1717 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1718 let packed_user_op = PackedUserOperation::new(
1719 sender,
1720 Uint256::from(42),
1721 b"init_code",
1722 b"call_data",
1723 b"account_gas_limits",
1724 50000,
1725 b"gas_fees",
1726 b"paymaster_and_data",
1727 );
1728
1729 let encoded_user_op = packed_user_op.to_v07_abi_encoded_fields();
1730
1731 let decoded = ethers::abi::decode(
1733 &[
1734 ethers::abi::ParamType::Address,
1735 ethers::abi::ParamType::Uint(256),
1736 ethers::abi::ParamType::FixedBytes(32),
1737 ethers::abi::ParamType::FixedBytes(32),
1738 ethers::abi::ParamType::FixedBytes(32),
1739 ethers::abi::ParamType::Uint(256),
1740 ethers::abi::ParamType::FixedBytes(32),
1741 ethers::abi::ParamType::FixedBytes(32),
1742 ],
1743 &encoded_user_op,
1744 )
1745 .unwrap();
1746 assert_eq!(
1747 decoded[0].clone().into_address().unwrap(),
1748 ethers::types::H160::from_slice(packed_user_op.sender.as_ref())
1749 );
1750 assert_eq!(
1751 decoded[1].clone().into_uint().unwrap(),
1752 ethers::types::U256::from_big_endian(&packed_user_op.nonce.to_be_bytes(),)
1753 );
1754 assert_eq!(
1755 decoded[2].clone().into_fixed_bytes().unwrap(),
1756 Keccak256::digest(&packed_user_op.init_code).as_slice()
1757 );
1758 assert_eq!(
1759 decoded[3].clone().into_fixed_bytes().unwrap(),
1760 Keccak256::digest(&packed_user_op.call_data).as_slice()
1761 );
1762 let mut expected_account_gas_limits = packed_user_op.account_gas_limits.to_vec();
1763 expected_account_gas_limits.resize(32, 0); assert_eq!(
1765 decoded[4].clone().into_fixed_bytes().unwrap(),
1766 expected_account_gas_limits
1767 );
1768 assert_eq!(
1769 decoded[5].clone().into_uint().unwrap(),
1770 ethers::types::U256::from(50000)
1771 );
1772 let mut expected_gas_fees = packed_user_op.gas_fees.to_vec();
1773 expected_gas_fees.resize(32, 0); assert_eq!(
1775 decoded[6].clone().into_fixed_bytes().unwrap(),
1776 expected_gas_fees
1777 );
1778 assert_eq!(
1779 decoded[7].clone().into_fixed_bytes().unwrap(),
1780 Keccak256::digest(&packed_user_op.paymaster_and_data).as_slice()
1781 );
1782 }
1783
1784 #[test]
1785 fn test_packed_user_operation_to_v07_hash() {
1786 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1787 let packed_user_op = PackedUserOperation::new(
1788 sender,
1789 Uint256::from(42),
1790 b"init_code",
1791 b"call_data",
1792 b"account_gas_limits",
1793 50000,
1794 b"gas_fees",
1795 b"paymaster_and_data",
1796 );
1797
1798 let chain_id = 137;
1799
1800 let encoded_user_op = packed_user_op.to_v07_abi_encoded_fields();
1801 let v07_encoding = packed_user_op.to_v07_hash(chain_id);
1802
1803 let hashed_encoded_user_op = Keccak256::digest(&encoded_user_op);
1804
1805 let overall_tokens = vec![
1807 Token::FixedBytes(hashed_encoded_user_op.as_slice().to_vec()),
1808 Token::Address(ethers::types::H160::from_slice(
1809 Address::from_str(ENTRYPOINT_V07).unwrap().as_ref(),
1810 )),
1811 Token::Uint(ethers::types::U256::from(chain_id)),
1812 ];
1813 let expected_v07_encoding = Keccak256::digest(&encode(&overall_tokens));
1814 assert_eq!(expected_v07_encoding.as_slice(), v07_encoding.as_slice());
1815 }
1816
1817 #[test]
1818 fn test_encrypted_threshold_signing_request() {
1819 let sender = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1820 let cohort_id = 1;
1821 let chain_id = 137;
1822
1823 let user_op = UserOperation::new(
1824 sender,
1825 Uint256::from(100),
1826 b"execution_data",
1827 150000,
1828 250000,
1829 60000,
1830 30_000_000_000,
1831 2_000_000_000,
1832 None,
1833 None,
1834 None,
1835 None,
1836 None,
1837 None,
1838 );
1839 let user_op_request = UserOperationSignatureRequest::new(
1840 user_op.clone(),
1841 cohort_id,
1842 chain_id,
1843 AAVersion::V08,
1844 None,
1845 );
1846
1847 let packed_user_op = PackedUserOperation::from_user_operation(&user_op);
1848 let packed_user_op_request = PackedUserOperationSignatureRequest::new(
1849 packed_user_op,
1850 cohort_id,
1851 chain_id,
1852 AAVersion::MDT,
1853 None,
1854 );
1855
1856 let service_secret = SessionStaticSecret::random();
1858
1859 let requester_secret = SessionStaticSecret::random();
1860 let requester_public_key = requester_secret.public_key();
1861
1862 let service_public_key = service_secret.public_key();
1864 let requester_shared_secret = requester_secret.derive_shared_secret(&service_public_key);
1865
1866 for request in [
1868 DirectSignatureRequest::UserOp(user_op_request),
1869 DirectSignatureRequest::PackedUserOp(packed_user_op_request),
1870 ] {
1871 let encrypted_request =
1872 request.encrypt(&requester_shared_secret, &requester_public_key);
1873
1874 let encrypted_request_bytes = encrypted_request.to_bytes();
1876 let encrypted_request_from_bytes =
1877 EncryptedThresholdSignatureRequest::from_bytes(&encrypted_request_bytes).unwrap();
1878
1879 assert_eq!(encrypted_request_from_bytes.cohort_id, cohort_id);
1880 assert_eq!(
1881 encrypted_request_from_bytes.requester_public_key,
1882 requester_public_key
1883 );
1884
1885 let service_shared_secret = service_secret
1887 .derive_shared_secret(&encrypted_request_from_bytes.requester_public_key);
1888 let decrypted_request = encrypted_request_from_bytes
1889 .decrypt(&service_shared_secret)
1890 .unwrap();
1891 assert_eq!(decrypted_request, request);
1892
1893 let random_secret_key = SessionStaticSecret::random();
1895 let random_shared_secret =
1896 random_secret_key.derive_shared_secret(&requester_public_key);
1897 assert!(encrypted_request_from_bytes
1898 .decrypt(&random_shared_secret)
1899 .is_err());
1900 }
1901 }
1902
1903 #[test]
1904 fn test_encrypted_threshold_signing_response() {
1905 let service_secret = SessionStaticSecret::random();
1906 let requester_secret = SessionStaticSecret::random();
1907
1908 let signer = Address::from_str("0x1234567890123456789012345678901234567890").unwrap();
1909 let response = SignatureResponse::new(
1910 signer,
1911 b"response_hash",
1912 b"response_signature",
1913 SignatureRequestType::UserOp,
1914 );
1915
1916 let requester_public_key = requester_secret.public_key();
1918
1919 let service_shared_secret = service_secret.derive_shared_secret(&requester_public_key);
1920 let encrypted_response = response.encrypt(&service_shared_secret);
1921
1922 let encrypted_response_bytes = encrypted_response.to_bytes();
1924 let encrypted_response_from_bytes =
1925 EncryptedThresholdSignatureResponse::from_bytes(&encrypted_response_bytes).unwrap();
1926
1927 let service_public_key = service_secret.public_key();
1929 let requester_shared_secret = requester_secret.derive_shared_secret(&service_public_key);
1930 assert_eq!(
1931 requester_shared_secret.as_bytes(),
1932 service_shared_secret.as_bytes()
1933 );
1934 let decrypted_response = encrypted_response_from_bytes
1935 .decrypt(&requester_shared_secret)
1936 .unwrap();
1937 assert_eq!(response, decrypted_response);
1938 assert_eq!(decrypted_response.signature, response.signature);
1940 assert_eq!(decrypted_response.signer, response.signer);
1941 assert_eq!(decrypted_response.hash, response.hash);
1942 assert_eq!(decrypted_response.signature_type, response.signature_type);
1943
1944 let random_secret_key = SessionStaticSecret::random();
1946 let random_shared_secret = random_secret_key.derive_shared_secret(&requester_public_key);
1947 assert!(encrypted_response_from_bytes
1948 .decrypt(&random_shared_secret)
1949 .is_err());
1950 }
1951}