// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import { ATTESTATION_VALID_SALT, ATTESTATION_INVALID_SALT, RECEIPT_VALID_SALT, RECEIPT_INVALID_SALT, SNAPSHOT_VALID_SALT, STATE_INVALID_SALT } from "../../contracts/libs/Constants.sol"; import {SnapshotLib, State, RawAttestation, RawExecReceipt, RawSnapshot, RawState} from "./libs/SynapseStructs.t.sol"; import {SynapseUtilities} from "./SynapseUtilities.t.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; // solhint-disable no-empty-blocks // solhint-disable ordering abstract contract SynapseAgents is SynapseUtilities { struct Domain { string name; address agent; address[] agents; } // domain => Domain's name uint32[] internal allDomains; mapping(uint32 => Domain) internal domains; mapping(address => uint256) internal agentPK; /// @notice Prevents this contract from being included in the coverage report function testSynapseAgents() external {} function setUp() public virtual { // Setup domains and create agents for them setupDomain(0, "Guards"); setupDomain(DOMAIN_LOCAL, "Local"); setupDomain(DOMAIN_REMOTE, "Remote"); setupDomain(DOMAIN_OTHER, "Other"); } // ═══════════════════════════════════════════════════ SETUP ═══════════════════════════════════════════════════════ function setupDomain(uint32 domain, string memory name) public virtual { allDomains.push(domain); domains[domain].name = name; string memory baseAgentName = domain == 0 ? "Guard" : string.concat("Notary(", name, ")"); domains[domain].agents = new address[](DOMAIN_AGENTS); for (uint256 i = 0; i < DOMAIN_AGENTS; ++i) { domains[domain].agents[i] = createAgent(string.concat(baseAgentName, " ", Strings.toString(i))); } domains[domain].agent = domains[domain].agents[0]; } // ══════════════════════════════════════════════════ AGENTS ═══════════════════════════════════════════════════════ function createAgent(string memory name) public returns (address agent) { uint256 privKey; (agent, privKey) = makeAddrAndKey(name); agentPK[agent] = privKey; } function getAgent(uint256 domainId, uint256 agentId) public view returns (uint32 domain, address agent) { domain = allDomains[domainId % allDomains.length]; agent = domains[domain].agents[agentId % DOMAIN_AGENTS]; } function getDomainAgent(uint32 domain, uint256 agentId) public view returns (address agent) { agent = domains[domain].agents[agentId % DOMAIN_AGENTS]; } function getGuard(uint256 agentId) public view returns (address guard) { guard = getDomainAgent(0, agentId); } function getNotary(uint256 domainId, uint256 agentId) public view returns (address notary) { uint32 domain = allDomains[1 + (domainId % (allDomains.length - 1))]; notary = getDomainAgent(domain, agentId); } /// @dev Private to enforce using salt-specific signing function signMessage(address agent, bytes32 hashedMsg) private view returns (bytes memory signature) { uint256 privKey = agentPK[agent]; require(privKey != 0, "Unknown agent"); return signMessage(privKey, hashedMsg); } /// @notice Signs a salted hash of a message function signMessage(address agent, bytes32 salt, bytes32 hashedMsg) public view returns (bytes memory signature) { return signMessage(agent, keccak256(bytes.concat(salt, hashedMsg))); } /// @notice Signs hashed message, by using a requested salt. function signMessage(address agent, bytes32 salt, bytes memory message) public view returns (bytes memory signature) { return signMessage(agent, salt, keccak256(message)); } // ════════════════════════════════════════════ SIGNING STATEMENTS ═════════════════════════════════════════════════ function signAttestation(address agent, bytes memory attestation) public view returns (bytes memory signature) { return signMessage(agent, ATTESTATION_VALID_SALT, attestation); } function signAttestation(address agent, RawAttestation memory ra) public view returns (bytes memory attestation, bytes memory signature) { attestation = ra.formatAttestation(); signature = signAttestation(agent, attestation); } function signAttestationReport(address agent, bytes memory attPayload) public view returns (bytes memory signature) { return signMessage(agent, ATTESTATION_INVALID_SALT, attPayload); } function signAttestationReport(address agent, RawAttestation memory ra) public view returns (bytes memory attPayload, bytes memory arSignature) { attPayload = ra.formatAttestation(); arSignature = signAttestationReport(agent, attPayload); } function signReceipt(address agent, bytes memory receipt) public view returns (bytes memory signature) { return signMessage(agent, RECEIPT_VALID_SALT, receipt); } function signReceipt(address agent, RawExecReceipt memory re) public view returns (bytes memory receipt, bytes memory signature) { receipt = re.formatReceipt(); signature = signReceipt(agent, receipt); } function signReceiptReport(address agent, bytes memory rcptPayload) public view returns (bytes memory signature) { return signMessage(agent, RECEIPT_INVALID_SALT, rcptPayload); } function signReceiptReport(address agent, RawExecReceipt memory re) public view returns (bytes memory rcptPayload, bytes memory rrSignature) { rcptPayload = re.formatReceipt(); rrSignature = signReceiptReport(agent, rcptPayload); } function signSnapshot(address agent, bytes memory snapshot) public view returns (bytes memory signature) { return signMessage(agent, SNAPSHOT_VALID_SALT, snapshot); } function signSnapshot(address agent, RawSnapshot memory rawSnap) public view returns (bytes memory snapshot, bytes memory signature) { snapshot = rawSnap.formatSnapshot(); signature = signSnapshot(agent, snapshot); } function signSnapshot(address agent, State[] memory states) public view returns (bytes memory snapshot, bytes memory signature) { snapshot = SnapshotLib.formatSnapshot(states); signature = signSnapshot(agent, snapshot); } function signStateReport(address agent, bytes memory statePayload) public view returns (bytes memory signature) { return signMessage(agent, STATE_INVALID_SALT, statePayload); } function signStateReport(address agent, RawState memory rs) public view returns (bytes memory statePayload, bytes memory srSignature) { statePayload = rs.formatState(); srSignature = signStateReport(agent, statePayload); } }