use alloc::vec::Vec;
use miden_core_lib::dsa::ecdsa_k256_keccak::encode_signature;
use miden_protocol::account::auth::PublicKeyCommitment;
use miden_protocol::crypto::dsa::ecdsa_k256_keccak::{PublicKey, Signature};
use miden_protocol::crypto::hash::keccak::Keccak256;
use miden_protocol::transaction::TransactionSummary;
use miden_protocol::{Felt, Hasher, Word};
const EIP191_PREFIX: u8 = 0x19;
const EIP712_VERSION: u8 = 0x01;
const DOMAIN_SEPARATOR: [u8; 32] = [
0xd2, 0x99, 0x3b, 0x31, 0x72, 0x06, 0xdc, 0x17, 0xb9, 0x59, 0x70, 0x00, 0x08, 0x48, 0x82, 0x92,
0x43, 0x11, 0xd2, 0x36, 0xaa, 0xa8, 0xfc, 0xcd, 0x54, 0xd6, 0xce, 0x4f, 0xaa, 0xce, 0xc6, 0xb7,
];
const TRANSACTION_TYPE_HASH: [u8; 32] = [
0xd4, 0x6c, 0xfc, 0xb2, 0xf8, 0x1c, 0xad, 0x54, 0x42, 0x3e, 0x73, 0x1d, 0x56, 0x4b, 0xb1, 0xa2,
0x60, 0x60, 0xc1, 0xfe, 0xa0, 0x1f, 0xff, 0x7f, 0x86, 0xa0, 0xcd, 0x79, 0x6c, 0xaf, 0x2b, 0x63,
];
const SIGNATURE_KEY_DOMAIN: u64 = u64::from_le_bytes(*b"EIP712\0\0");
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Eip712Digest([u8; 32]);
impl Eip712Digest {
pub const fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
pub const fn into_bytes(self) -> [u8; 32] {
self.0
}
}
pub trait Eip712TransactionSummary {
fn eip712_hash(&self) -> Eip712Digest;
fn eip712_signature_key(&self, public_key: PublicKeyCommitment) -> Word;
fn eip712_signature_advice(
&self,
public_key: &PublicKey,
signature: &Signature,
) -> (Word, Vec<Felt>) {
let key = self.eip712_signature_key(public_key.to_commitment().into());
(key, encode_signature(public_key, signature))
}
}
impl Eip712TransactionSummary for TransactionSummary {
fn eip712_hash(&self) -> Eip712Digest {
let mut struct_preimage = [0u8; 64];
struct_preimage[..32].copy_from_slice(&TRANSACTION_TYPE_HASH);
struct_preimage[32..].copy_from_slice(&self.to_commitment().as_bytes());
let struct_hash: [u8; 32] = Keccak256::hash(&struct_preimage).into();
let mut digest_preimage = [0u8; 66];
digest_preimage[..2].copy_from_slice(&[EIP191_PREFIX, EIP712_VERSION]);
digest_preimage[2..34].copy_from_slice(&DOMAIN_SEPARATOR);
digest_preimage[34..].copy_from_slice(&struct_hash);
Eip712Digest(Keccak256::hash(&digest_preimage).into())
}
fn eip712_signature_key(&self, public_key: PublicKeyCommitment) -> Word {
let raw_signature_key = Hasher::merge(&[public_key.into(), self.to_commitment()]);
let domain = Word::new([
Felt::new_unchecked(SIGNATURE_KEY_DOMAIN),
Felt::ZERO,
Felt::ZERO,
Felt::ZERO,
]);
Hasher::merge(&[raw_signature_key, domain])
}
}