import os sol_code = """// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract AuditReceiptLedger { struct AuditReceipt { bytes16 gatewayUuid; bytes32 merkleRoot; uint256 objectCount; uint256 timestamp; uint256 nonce; } bytes32 public immutable DOMAIN_SEPARATOR; bytes32 public constant AUDIT_RECEIPT_TYPEHASH = keccak256( "AuditReceipt(bytes16 gatewayUuid,bytes32 merkleRoot,uint256 objectCount,uint256 timestamp,uint256 nonce)" ); address public immutable authorizedSigner; mapping(uint256 => bool) public usedNonces; mapping(bytes32 => bool) public verifiedMerkleRoots; event ReceiptAnchored(bytes16 indexed gatewayUuid, bytes32 indexed merkleRoot, uint256 objectCount, uint256 timestamp); constructor(address _authorizedSigner) { authorizedSigner = _authorizedSigner; DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes("AuditReceiptLedger")), keccak256(bytes("1")), block.chainid, address(this) ) ); } function verifyAndAnchor(AuditReceipt calldata receipt, bytes calldata signature) external returns (bool) { require(!usedNonces[receipt.nonce], "Nonce used"); require(receipt.timestamp + 300 >= block.timestamp && receipt.timestamp <= block.timestamp + 300, "Timestamp drift"); bytes32 structHash = keccak256( abi.encode(AUDIT_RECEIPT_TYPEHASH, receipt.gatewayUuid, receipt.merkleRoot, receipt.objectCount, receipt.timestamp, receipt.nonce) ); bytes32 digest = keccak256(abi.encodePacked("\\x19\\x01", DOMAIN_SEPARATOR, structHash)); address signer = recoverSigner(digest, signature); require(signer == authorizedSigner, "Invalid signer"); usedNonces[receipt.nonce] = true; verifiedMerkleRoots[receipt.merkleRoot] = true; emit ReceiptAnchored(receipt.gatewayUuid, receipt.merkleRoot, receipt.objectCount, receipt.timestamp); return true; } function recoverSigner(bytes32 digest, bytes memory sig) internal pure returns (address) { require(sig.length == 65, "Sig length"); bytes32 r; bytes32 s; uint8 v; assembly { r := mload(add(sig, 32)) s := mload(add(sig, 64)) v := byte(0, mload(add(sig, 96))) } if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E735E5C9258C5716C851F818E00) revert("Invalid s"); if (v != 27 && v != 28) revert("Invalid v"); address signer = ecrecover(digest, v, r, s); require(signer != address(0), "Zero signer"); return signer; } }""" backend_code = """import uuid, time from eth_account import Account from eth_account.messages import encode_typed_data from web3 import Web3 class EIP712Signer: def __init__(self, private_key: str, contract_address: str, chain_id: int): self.account = Account.from_key(private_key) self.contract_address = Web3.to_checksum_address(contract_address) self.chain_id = chain_id def build_typed_data(self, gateway_uuid_bytes: bytes, merkle_root_bytes: bytes, object_count: int, nonce: int, timestamp: int) -> dict: return { "types": { "EIP712Domain": [ {"name": "name", "type": "string"}, {"name": "version", "type": "string"}, {"name": "chainId", "type": "uint256"}, {"name": "verifyingContract", "type": "address"} ], "AuditReceipt": [ {"name": "gatewayUuid", "type": "bytes16"}, {"name": "merkleRoot", "type": "bytes32"}, {"name": "objectCount", "type": "uint256"}, {"name": "timestamp", "type": "uint256"}, {"name": "nonce", "type": "uint256"} ] }, "primaryType": "AuditReceipt", "domain": {"name": "AuditReceiptLedger", "version": "1", "chainId": self.chain_id, "verifyingContract": self.contract_address}, "message": {"gatewayUuid": gateway_uuid_bytes, "merkleRoot": merkle_root_bytes, "objectCount": object_count, "timestamp": timestamp, "nonce": nonce} } def sign_audit_receipt(self, gateway_uuid_str: str, merkle_root_hex: str, object_count: int, nonce: int) -> dict: g_bytes = uuid.UUID(gateway_uuid_str).bytes m_bytes = bytes.fromhex(merkle_root_hex.replace("0x", "")) ts = int(time.time()) typed_data = self.build_typed_data(g_bytes, m_bytes, object_count, nonce, ts) sig = self.account.sign_message(encode_typed_data(full_message=typed_data)).signature.hex() return { "receipt": {"gatewayUuid": "0x" + g_bytes.hex(), "merkleRoot": "0x" + m_bytes.hex(), "objectCount": object_count, "timestamp": ts, "nonce": nonce}, "signature": sig, "signer": self.account.address }""" app_code = """import streamlit as st, hashlib, time from eip712_backend import EIP712Signer st.sidebar.header("EIP-712 On-Chain Anchor") CONTRACT_ADDRESS = st.sidebar.text_input("Ledger Address", "0x1234567890123456789012345678901234567890") CHAIN_ID = st.sidebar.number_input("Chain ID", value=1, step=1) SIGNER_KEY = st.sidebar.text_input("Signer Key", type="password") if st.sidebar.button("Sign EIP-712 Anchor"): if not SIGNER_KEY or not CONTRACT_ADDRESS: st.error("Missing configuration.") else: root = hashlib.sha256(b"hardened_audit_log_data").hexdigest() signer = EIP712Signer(private_key=SIGNER_KEY, contract_address=CONTRACT_ADDRESS, chain_id=CHAIN_ID) payload = signer.sign_audit_receipt("a1b2c3d4-e5f6-47a8-8901-23456789abcd", root, 1024, int(time.time())) st.success("Signed") st.json(payload)""" with open("AuditReceiptLedger.sol", "w") as f: f.write(sol_code) with open("eip712_backend.py", "w") as f: f.write(backend_code) with open("app.py", "w") as f: f.write(app_code) print("Files created: AuditReceiptLedger.sol, eip712_backend.py, app.py")