// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {CheckpointStorage} from "../storage/CheckpointStorage.sol";

/// @title CheckpointEIP712 — typed data for relayer + validator attestations
library CheckpointEIP712 {
    bytes32 public constant DOMAIN_TYPEHASH =
        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");

    bytes32 public constant BATCH_ATTESTATION_TYPEHASH = keccak256(
        "BatchAttestation(uint64 chainId,uint64 batchId,uint256 checkpointBlock,bytes32 blockHash,bytes32 stateRoot,bytes32 paymentsRoot,uint64 previousBatchId)"
    );

    function domainSeparator(address verifyingContract, uint256 chainId) internal pure returns (bytes32) {
        return keccak256(
            abi.encode(
                DOMAIN_TYPEHASH,
                keccak256("Chain138MainnetCheckpoint"),
                keccak256("2"),
                chainId,
                verifyingContract
            )
        );
    }

    function hashBatchAttestation(CheckpointStorage.CheckpointHeader memory header) internal pure returns (bytes32) {
        return keccak256(
            abi.encode(
                BATCH_ATTESTATION_TYPEHASH,
                header.chainId,
                header.batchId,
                header.checkpointBlock,
                header.blockHash,
                header.stateRoot,
                header.paymentsRoot,
                header.previousBatchId
            )
        );
    }

    function digest(
        address verifyingContract,
        uint256 chainId,
        CheckpointStorage.CheckpointHeader memory header
    ) internal pure returns (bytes32) {
        bytes32 structHash = hashBatchAttestation(header);
        bytes32 domain = domainSeparator(verifyingContract, chainId);
        return keccak256(abi.encodePacked("\x19\x01", domain, structHash));
    }
}
