miden_standards/account/auth/
eip712.rs1use alloc::vec::Vec;
19
20use miden_core_lib::dsa::ecdsa_k256_keccak::encode_signature;
21use miden_protocol::account::auth::PublicKeyCommitment;
22use miden_protocol::crypto::dsa::ecdsa_k256_keccak::{PublicKey, Signature};
23use miden_protocol::crypto::hash::keccak::Keccak256;
24use miden_protocol::transaction::TransactionSummary;
25use miden_protocol::{Felt, Hasher, Word};
26
27const EIP191_PREFIX: u8 = 0x19;
29
30const EIP712_VERSION: u8 = 0x01;
32
33const DOMAIN_SEPARATOR: [u8; 32] = [
35 0xd2, 0x99, 0x3b, 0x31, 0x72, 0x06, 0xdc, 0x17, 0xb9, 0x59, 0x70, 0x00, 0x08, 0x48, 0x82, 0x92,
36 0x43, 0x11, 0xd2, 0x36, 0xaa, 0xa8, 0xfc, 0xcd, 0x54, 0xd6, 0xce, 0x4f, 0xaa, 0xce, 0xc6, 0xb7,
37];
38
39const TRANSACTION_TYPE_HASH: [u8; 32] = [
41 0xd4, 0x6c, 0xfc, 0xb2, 0xf8, 0x1c, 0xad, 0x54, 0x42, 0x3e, 0x73, 0x1d, 0x56, 0x4b, 0xb1, 0xa2,
42 0x60, 0x60, 0xc1, 0xfe, 0xa0, 0x1f, 0xff, 0x7f, 0x86, 0xa0, 0xcd, 0x79, 0x6c, 0xaf, 0x2b, 0x63,
43];
44
45const SIGNATURE_KEY_DOMAIN: u64 = u64::from_le_bytes(*b"EIP712\0\0");
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
50pub struct Eip712Digest([u8; 32]);
51
52impl Eip712Digest {
53 pub const fn as_bytes(&self) -> &[u8; 32] {
55 &self.0
56 }
57
58 pub const fn into_bytes(self) -> [u8; 32] {
60 self.0
61 }
62}
63
64pub trait Eip712TransactionSummary {
66 fn eip712_hash(&self) -> Eip712Digest;
68
69 fn eip712_signature_key(&self, public_key: PublicKeyCommitment) -> Word;
71
72 fn eip712_signature_advice(
78 &self,
79 public_key: &PublicKey,
80 signature: &Signature,
81 ) -> (Word, Vec<Felt>) {
82 let key = self.eip712_signature_key(public_key.to_commitment().into());
83 (key, encode_signature(public_key, signature))
84 }
85}
86
87impl Eip712TransactionSummary for TransactionSummary {
88 fn eip712_hash(&self) -> Eip712Digest {
89 let mut struct_preimage = [0u8; 64];
90 struct_preimage[..32].copy_from_slice(&TRANSACTION_TYPE_HASH);
91 struct_preimage[32..].copy_from_slice(&self.to_commitment().as_bytes());
92 let struct_hash: [u8; 32] = Keccak256::hash(&struct_preimage).into();
93
94 let mut digest_preimage = [0u8; 66];
95 digest_preimage[..2].copy_from_slice(&[EIP191_PREFIX, EIP712_VERSION]);
96 digest_preimage[2..34].copy_from_slice(&DOMAIN_SEPARATOR);
97 digest_preimage[34..].copy_from_slice(&struct_hash);
98
99 Eip712Digest(Keccak256::hash(&digest_preimage).into())
100 }
101
102 fn eip712_signature_key(&self, public_key: PublicKeyCommitment) -> Word {
103 let raw_signature_key = Hasher::merge(&[public_key.into(), self.to_commitment()]);
104 let domain = Word::new([
105 Felt::new_unchecked(SIGNATURE_KEY_DOMAIN),
106 Felt::ZERO,
107 Felt::ZERO,
108 Felt::ZERO,
109 ]);
110 Hasher::merge(&[raw_signature_key, domain])
111 }
112}