pragma solidity >=0.8.0; // SPDX-License-Identifier: AGPL-3.0-or-later contract AddressDeclarator { mapping( address => address[] ) declarationIndex; mapping( bytes32 => uint256 ) declarationContentIndex; // the _latest_ content pointer for the declarator to subject mapping mapping( address => address[] ) declarator; mapping( address => address[] ) declaratorReverse; bytes32[][] contents; // Implements Declarator event DeclarationAdded(address indexed _declarator, address indexed _subject, bytes32 indexed _topic, bytes32 _proof); constructor(bytes32 _initial) { addDeclaration(address(this), _initial); } // Create a digest reference for a declarator and subject pair function toReference(address _declarator, address _subject) private pure returns ( bytes32 ) { bytes32 k; bytes memory addrMaterial = new bytes(40); bytes memory addrBytes = abi.encodePacked(_declarator); for (uint256 i = 0; i < 20; i++) { addrMaterial[i] = addrBytes[i]; } addrBytes = abi.encodePacked(_subject); for (uint256 i = 0; i < 20; i++) { addrMaterial[i+20] = addrBytes[i]; } k = sha256(addrMaterial); return k; } // Create a digest reference for a declarator and subject pair on top of the given digest function toReference(address _declarator, address _subject, bytes32 _digest) private pure returns ( bytes32[2] memory ) { bytes32 k; bytes32[2] memory ks; bytes memory signMaterial = new bytes(64); k = toReference(_declarator, _subject); for (uint256 i = 0; i < 32; i++) { signMaterial[i] = k[i]; } for (uint256 i = 0; i < 32; i++) { signMaterial[i+32] = _digest[i]; } ks[0] = k; ks[1] = sha256(signMaterial); return ks; } // Implements Declarator function declaratorCount(address _subject) public view returns ( uint256 ) { return declarator[_subject].length; } // Implements Declarator function declaratorAddressAt(address _subject, uint256 _idx) public view returns ( address ) { return declarator[_subject][_idx]; } // Implements Declarator function addDeclaration(address _subject, bytes32 _proof, bytes32 _topic) public returns ( bool ) { bytes32[2] memory ks; bytes32[] memory declarationContents; uint256 idx; ks = toReference(tx.origin, _subject, _topic); idx = declarationContentIndex[ks[1]]; if (idx == 0) { // This also works for the constructor :) declarator[_subject].push(tx.origin); contents.push(declarationContents); declarationIndex[tx.origin].push(_subject); idx = contents.length-1; } declarationContentIndex[ks[1]] = idx; contents[idx].push(_proof); return true; } // Implements Declarator function addDeclaration(address _subject, bytes32 _proof) public returns ( bool ) { return addDeclaration(_subject, _proof, bytes32(0)); } // Implements Declarator function declaration(address _declarator, address _subject) public view returns ( bytes32[] memory ) { return declaration(_declarator, _subject, bytes32(0)); } // Implements Declarator function declaration(address _declarator, address _subject, bytes32 _topic) public view returns ( bytes32[] memory ) { bytes32[2] memory k; uint256 idx; k = toReference(_declarator, _subject, _topic); idx = declarationContentIndex[k[1]]; return contents[idx]; } // Implements Declarator function declarationCount(address _declarator) public view returns ( uint256 ) { return declarationIndex[_declarator].length; } // Implements Declarator function declarationAddressAt(address _declarator, uint256 _idx) public view returns ( address ) { return declarationIndex[_declarator][_idx]; } // Implements EIP165 function supportsInterface(bytes4 _sum) public pure returns (bool) { if (_sum == 0x21b7493b) { // Implements Declarator return true; } if (_sum == 0x01ffc9a7) { // EIP165 return true; } return false; } }