Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
9.0 kB
3
Indexable
Never
//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] = newService;
        actorAddresses.push(msg.sender);
    }

    function getService(address _actorID) public view returns (Service memory) {
        return services[_actorID];
    }

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

contract Agreement is SharedStructs {
// 'Banking Transactions', 'Banking Services', 'Write', ['Account Number', 'Transaction History'] 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2 
// 'Financial Transactions', 'Financial Services', 'Read', ['Phone Number', 'Account History'] 0x17F6AD8Ef982297579C203069C1DbfFE4348c372 
//0xc5075f64488d32a067f76bd1d177b5376e72e8a9e3f0fb2395c1014b928d0181, 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2, 'Write', ['Account Number', 'Transaction History'], false
//0xc5075f64488d32a067f76bd1d177b5376e72e8a9e3f0fb2395c1014b928d0181, 0x17F6AD8Ef982297579C203069C1DbfFE4348c372, 'Read', ['Account Number', 'Transaction History'], true
//0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2, 0x17F6AD8Ef982297579C203069C1DbfFE4348c372, 'Read', ['Account Number', 'Transaction History'], 'Financial Services'
//0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2, 0x17F6AD8Ef982297579C203069C1DbfFE4348c372, 'Write', ['Account Number', 'Transaction History'], 'Banking Services'
    struct Consent {
        bytes32 purposeHash;
        address actorID;
        string operation;
        string[] personalData;
        address userId;
        bool isPositive;
    }
//0xc5075f64488d32a067f76bd1d177b5376e72e8a9e3f0fb2395c1014b928d0181, 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, Write, ['Account Number', 'Transaction History'], 202, false
    event LogServiceParams(
        address indexed actorID,
        string serviceName,
        string servicePurpose,
        string operation,
        string[] personalData
    );
    //to store user consents for data processing purposes, where each consent is associated with a specific actor 
    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);
        //The function stores the newConsent struct in the consents nested mapping using the _actorID as the key for the outer mapping and the _userId as the key for the inner mapping.
        consents[_actorID][msg.sender] = newConsent;
    }

    function getConsent(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);
            Service memory service = dataUsage.getService(actorAddress);
            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();
        //To store the violating actors 
        address[] memory violatingActors = new address[](numLogEntries);
        //violator count
        uint256 violatingCount = 0;
        for (uint256 i = 0; i < numLogEntries; i++) {
            Log.LogEntry memory logEntry = log.getLogEntry(i);
            bool consentFound = false; //matching consented operation
            for (uint16 j = 0; j < numActors; j++) {
                address actorAddress = dataUsage.actorAddresses(j);
                Agreement.Consent memory consent = agreement.getConsent(actorAddress, logEntry.userId);
                if (logEntry.actorId == consent.actorID) {                    
                    SharedStructs.Service memory service = dataUsage.getService(actorAddress);
                    //Converting string to bytes, as string memory can't be directly compared
                    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)) {
                        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;

            // Iteratating 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;
    }
}