Untitled

 avatar
unknown
plain_text
2 years ago
9.8 kB
2
Indexable
//SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import "hardhat/console.sol";

contract SharedStructs {
    struct Service {
        address actorID;
        string serviceName;
        string servicePurpose;
        string operation;
        string[] personalData;
    }
}

contract DataUsage is SharedStructs {
    mapping(address => Service[]) public services;
    address[] public actorAddresses;

    function addService(string memory _serviceName, string memory _servicePurpose, string memory _operation, string[] memory _personalData) public {
        Service memory newService = Service(msg.sender, _serviceName, _servicePurpose, _operation, _personalData);
        services[msg.sender].push(newService);

        bool actorExists = false;
        for (uint256 i = 0; i < actorAddresses.length; i++) {
            if (actorAddresses[i] == msg.sender) {
                actorExists = true;
                break;
            }
        }

        if (!actorExists) {
            actorAddresses.push(msg.sender);
        }
    }

    function getService(address _actorID, uint256 index) public view returns (Service memory) {
        require(index < services[_actorID].length, "Index out of bounds");
        return services[_actorID][index];
    }

    function getServicesCount(address _actorID) public view returns (uint256) {
        return services[_actorID].length;
    }

    function getActorAddressesCount() public view returns (uint256) {
        return actorAddresses.length;
    }
}


// 'Banking Transactions', 'Banking Services', 'Write', ['Account Number', 'Transaction History'] 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db
// 'Financial Transactions', 'Financial Services', 'Read', ['Phone Number', 'Account History'] 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db
// 'Medical Transactions', 'Financial Services', 'Transfer', ['Phone Number', 'Account History'] 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB


//0xc5075f64488d32a067f76bd1d177b5376e72e8a9e3f0fb2395c1014b928d0181, 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db, 'Write', ['Account Number', 'Transaction History'], true //0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
//0xc5075f64488d32a067f76bd1d177b5376e72e8a9e3f0fb2395c1014b928d0181, 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB, 'Read', ['Phone Number', 'Account History'], true

//0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db, 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 'Write', ['Account Number', 'Transaction History'], 'Banking Services'
//0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB, 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 'Transfer', ['Phone Number', 'Account History'], 'Medical Services'

contract Agreement is SharedStructs {
    struct Consent {
        bytes32 purposeHash;
        address actorID;
        string operation;
        string[] personalData;
        address userId;
        bool isPositive;
    }

    event LogServiceParams(
        address indexed actorID,
        string serviceName,
        string servicePurpose,
        string operation,
        string[] personalData
    );

    mapping(address => mapping(address => Consent[])) public consents;

    function giveConsent(bytes32 _purposeHash, address _actorID, string memory _operation, string[] memory _personalData, bool _isPositive) public {
        Consent memory newConsent = Consent(_purposeHash, _actorID, _operation, _personalData, msg.sender, _isPositive);
        consents[_actorID][msg.sender].push(newConsent);
    }

    function getConsents(address actorID, address userId) public view returns (Consent[] memory) {
        return consents[actorID][userId];
    }

    function callGetService(address dataUsageContractAddress) public {
        DataUsage dataUsage = DataUsage(dataUsageContractAddress);
        uint256 numActors = dataUsage.getActorAddressesCount();

        for (uint256 i = 0; i < numActors; i++) {
            address actorAddress = dataUsage.actorAddresses(i);
            uint256 numServices = dataUsage.getServicesCount(actorAddress);

            for (uint256 j = 0; j < numServices; j++) {
                Service memory service = dataUsage.getService(actorAddress, j);
                emit LogServiceParams(
                    service.actorID,
                    service.serviceName,
                    service.servicePurpose,
                    service.operation,
                    service.personalData
                );
            }
        }
    }
}

contract Log {
    struct LogEntry {
        address actorId;
        address userId;
        string operation;
        string[] processedData;
        string serviceName;
    }
    
    mapping(uint256 => LogEntry) public logEntries;
    uint256 public entryCount;

    function addLogEntry(address _actorId, address _userId, string memory _operation, string[] memory _processedData, string memory _serviceName) public {
        LogEntry memory newEntry = LogEntry(_actorId, _userId, _operation, _processedData, _serviceName);
        logEntries[entryCount] = newEntry;
        entryCount++;
    }

    function getLogEntry(uint256 index) public view returns (LogEntry memory) {
        return logEntries[index];
    }
}

contract Verification {
    DataUsage dataUsage;
    Agreement agreement;
    Log log;

    constructor(address _dataUsageAddress, address _agreementAddress, address _logAddress) {
        dataUsage = DataUsage(_dataUsageAddress);
        agreement = Agreement(_agreementAddress);
        log = Log(_logAddress);
    }

    function checkLog() public view returns (address[] memory){
        uint256 numActors = dataUsage.getActorAddressesCount();
        uint256 numLogEntries = log.entryCount();
        address[] memory violatingActors = new address[](numLogEntries);
        uint256 violatingCount = 0;
        //Iterating through log entries
        for (uint256 i = 0; i < numLogEntries; i++) {
            Log.LogEntry memory logEntry = log.getLogEntry(i);
            bool consentFound = false;
            //Iterating through actor count
            for (uint16 j = 0; j < numActors; j++) {
                address actorAddress = dataUsage.actorAddresses(j);
                Agreement.Consent[] memory userConsents = agreement.getConsents(actorAddress, logEntry.userId);
                //Iterating through user consent (actoraddress, index)
                for (uint16 k = 0; k < userConsents.length; k++) {
                    Agreement.Consent memory consent = userConsents[k];
                    //verification contract - 1
                    if (logEntry.actorId == consent.actorID) {                    
                        SharedStructs.Service memory service = dataUsage.getService(actorAddress, k);
                        //verification contract - 2, 3
                        if (keccak256(abi.encodePacked(logEntry.operation)) == keccak256(abi.encodePacked(service.operation)) &&
                            keccak256(abi.encodePacked(logEntry.operation)) == keccak256(abi.encodePacked(consent.operation)) &&
                            isSubset(logEntry.processedData, consent.personalData)) {
                            //break from the inner loop once a matching consent is found.
                            consentFound = true;
                            break;
                        }
                    }
                }
            }
            if (!consentFound) {
                violatingActors[violatingCount] = logEntry.actorId;
                violatingCount++;
            }
        }
        //creating a new array that will store the address of the violating actors
        address[] memory result;

        //If no violations, print to console "no violations found" and return an empty array
        if (violatingCount == 0) {
            console.log("No violations found!");
            return new address[](0);
        } else {
            console.log("Violations found!");

            // Creating a temporary array to store unique addresses
            address[] memory uniqueAddresses = new address[](violatingCount);

            // Counting the number of unique addresses
            uint uniqueCount = 0;

            // Iterating through the violatingActors array and counting unique addresses
            for (uint i = 0; i < violatingCount; i++) {
                bool isNewAddress = true;
                for (uint j = 0; j < uniqueCount; j++) {
                    if (uniqueAddresses[j] == violatingActors[i]) {
                        isNewAddress = false;
                        break;
                    }
                }
                if (isNewAddress) {
                    uniqueAddresses[uniqueCount] = violatingActors[i];
                    uniqueCount++;
                }
            }

            // Creating a new array with the size of unique addresses
            result = new address[](uniqueCount);

            // Appending the unique addresses to the result array
            for (uint i = 0; i < uniqueCount; i++) {
                result[i] = uniqueAddresses[i];
            }

            console.log("The violating actors are:");
            for (uint i = 0; i < result.length; i++) {
                console.log(result[i]);
            }

            return result;
        }
    }

    function isSubset(string[] memory subset, string[] memory superset) private pure returns (bool) {
        for (uint256 i = 0; i < subset.length; i++) {
            bool found = false;
            for (uint256 j = 0; j < superset.length; j++) {
                if (keccak256(abi.encodePacked(subset[i])) == keccak256(abi.encodePacked(superset[j]))) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                return false;
            }
        }
        return true;
    } 
}