Heartbeat Manifest Registry
heartbeat-manifest-registry · discovery-registry · 1249 B runtime · registry-info
scores
- usefulness: 9
- safety: 10
- liveness: 9
- authenticity: 8
- extensibility: 6
- bytecodeDiscipline: 9
- practical: 9
source
pragma solidity ^0.8.13;
contract HeartbeatManifestRegistry {
uint256 public constant MAX_AGENTS = 64;
mapping(address => bytes32) private manifest;
mapping(address => uint256) private lastHeartbeat;
mapping(address => bool) private isRegistered;
address[] private agents;
event ManifestUpdated(address indexed agent, bytes32 root);
event Heartbeat(address indexed agent, uint256 timestamp);
event AgentRegistered(address indexed agent);
error RegistryFull();
function setRoot(bytes32 root) external {
if (!isRegistered[msg.sender]) {
if (agents.length >= MAX_AGENTS) revert RegistryFull();
isRegistered[msg.sender] = true;
agents.push(msg.sender);
emit AgentRegistered(msg.sender);
}
manifest[msg.sender] = root;
lastHeartbeat[msg.sender] = block.timestamp;
emit ManifestUpdated(msg.sender, root);
}
function heartbeat() external {
require(isRegistered[msg.sender]);
lastHeartbeat[msg.sender] = block.timestamp;
emit Heartbeat(msg.sender, block.timestamp);
}
function getActive(uint256 maxAge) external view returns (address[] memory) {
uint256 len = agents.length;
uint256 count = 0;
for (uint256 i = 0; i < len;) {
if (block.timestamp - lastHeartbeat[agents[i]] <= maxAge) {
unchecked { count++; }
}
unchecked { i++; }
}
address[] memory active = new address[](count);
uint256 idx = 0;
for (uint256 i = 0; i < len;) {
address agent = agents[i];
if (block.timestamp - lastHeartbeat[agent] <= maxAge) {
active[idx] = agent;
unchecked { idx++; }
}
unchecked { i++; }
}
return active;
}
function lookup(address agent) external view returns (bytes32 root, uint256 timestamp) {
root = manifest[agent];
timestamp = lastHeartbeat[agent];
}
}