// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /** * @title Perspectives * @dev Contract for storing IPFS hashes of perspectives submitted by users */ contract Perspectives { struct PerspectiveRecord { string ipfsHash; // IPFS hash of the full perspective data string issueId; // Unique identifier for the issue address submitter; // Address of the submitter uint256 timestamp; // Timestamp of submission bool isVerified; // Whether the submitter is verified } // Array to store all perspective records PerspectiveRecord[] public perspectiveRecords; // Mapping from IPFS hash to record index mapping(string => uint256) public ipfsHashToIndex; // Mapping from issue ID to list of indexes mapping(string => uint256[]) public issueIdToIndexes; // Event to emit when a perspective is submitted event PerspectiveSubmitted( uint256 indexed id, string ipfsHash, string issueId, address indexed submitter, uint256 timestamp, bool isVerified ); /** * @dev Submit a perspective to the blockchain * @param ipfsHash IPFS hash of the full perspective data * @param issueId Unique identifier for the issue * @param isVerified Whether the submitter is verified */ function submitPerspective( string memory ipfsHash, string memory issueId, bool isVerified ) public returns (uint256) { require(bytes(ipfsHash).length > 0, "IPFS hash cannot be empty"); require(bytes(issueId).length > 0, "Issue ID cannot be empty"); // Create a new perspective record uint256 id = perspectiveRecords.length; perspectiveRecords.push(PerspectiveRecord({ ipfsHash: ipfsHash, issueId: issueId, submitter: msg.sender, timestamp: block.timestamp, isVerified: isVerified })); // Update mappings ipfsHashToIndex[ipfsHash] = id; issueIdToIndexes[issueId].push(id); // Emit event emit PerspectiveSubmitted( id, ipfsHash, issueId, msg.sender, block.timestamp, isVerified ); return id; } /** * @dev Get the total number of perspectives * @return Total number of perspective records */ function getPerspectiveCount() public view returns (uint256) { return perspectiveRecords.length; } /** * @dev Get a perspective by index * @param index Index of the perspective * @return The perspective record */ function getPerspective(uint256 index) public view returns ( string memory ipfsHash, string memory issueId, address submitter, uint256 timestamp, bool isVerified ) { require(index < perspectiveRecords.length, "Index out of bounds"); PerspectiveRecord storage record = perspectiveRecords[index]; return ( record.ipfsHash, record.issueId, record.submitter, record.timestamp, record.isVerified ); } /** * @dev Get a perspective by IPFS hash * @param ipfsHash IPFS hash of the perspective * @return The perspective record */ function getPerspectiveByHash(string memory ipfsHash) public view returns ( uint256 index, string memory issueId, address submitter, uint256 timestamp, bool isVerified ) { index = ipfsHashToIndex[ipfsHash]; require(index > 0 || (index == 0 && keccak256(bytes(perspectiveRecords[0].ipfsHash)) == keccak256(bytes(ipfsHash))), "Perspective not found"); PerspectiveRecord storage record = perspectiveRecords[index]; return ( index, record.issueId, record.submitter, record.timestamp, record.isVerified ); } /** * @dev Get all perspective indexes for an issue * @param issueId Issue ID to get perspectives for * @return Array of perspective indexes */ function getPerspectiveIndexesByIssue(string memory issueId) public view returns (uint256[] memory) { return issueIdToIndexes[issueId]; } }