update ERC725 spec

This commit is contained in:
Ricardo Guilherme Schmidt 2018-05-09 17:12:43 -03:00
parent 3a62fcf5db
commit 036c6285a6
2 changed files with 67 additions and 62 deletions

View File

@ -15,16 +15,17 @@ contract ERC725 {
event Approved(uint256 indexed executionId, bool approved); event Approved(uint256 indexed executionId, bool approved);
struct Key { struct Key {
uint256 purpose; //e.g., MANAGEMENT_KEY = 1, ACTION_KEY = 2, etc. uint256[] purposes; //e.g., MANAGEMENT_KEY = 1, ACTION_KEY = 2, etc.
uint256 keyType; // e.g. 1 = ECDSA, 2 = RSA, etc. uint256 keyType; // e.g. 1 = ECDSA, 2 = RSA, etc.
bytes32 key; bytes32 key;
} }
function getKey(bytes32 _key, uint256 _purpose) public view returns(uint256 purpose, uint256 keyType, bytes32 key);
function getKeyPurpose(bytes32 _key) public view returns(uint256[] purpose);
function getKeysByPurpose(uint256 _purpose) public view returns(bytes32[] keys);
function addKey(bytes32 _key, uint256 _purpose, uint256 _keyType) public returns (bool success);
function removeKey(bytes32 _key, uint256 _purpose) public returns (bool success);
function execute(address _to, uint256 _value, bytes _data) public returns (uint256 executionId); function execute(address _to, uint256 _value, bytes _data) public returns (uint256 executionId);
function approve(uint256 _id, bool _approve) public returns (bool success); function approve(uint256 _id, bool _approve) public returns (bool success);
function addKey(bytes32 _key, uint256 _purpose, uint256 _keyType) public returns (bool success);
function removeKey(bytes32 _key, uint256 _purpose) public returns (bool success);
function getKey(bytes32 _key, uint256 _purpose) public view returns(uint256[] purposes, uint256 keyType, bytes32 key);
function getKeyPurpose(bytes32 _key) public view returns(uint256[] purpose);
function getKeysByPurpose(uint256 _purpose) public view returns(bytes32[] keys);
function keyHasPurpose(bytes32 _key, uint256 purpose) public view returns(bool exists);
} }

View File

@ -11,6 +11,7 @@ import "../common/MessageSigned.sol";
contract Identity is ERC725, ERC735, MessageSigned { contract Identity is ERC725, ERC735, MessageSigned {
mapping (bytes32 => Key) keys; mapping (bytes32 => Key) keys;
mapping (bytes32 => bool) isKeyPurpose;
mapping (uint256 => bytes32[]) keysByPurpose; mapping (uint256 => bytes32[]) keysByPurpose;
mapping (bytes32 => Claim) claims; mapping (bytes32 => Claim) claims;
mapping (uint256 => bytes32[]) claimsByType; mapping (uint256 => bytes32[]) claimsByType;
@ -74,7 +75,6 @@ contract Identity is ERC725, ERC735, MessageSigned {
) )
) )
); );
require(keys[_key].purpose != 0);
_; _;
} }
@ -313,7 +313,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
_includeClaim(claimHash, _claimType, _scheme, _issuer, _signature, _data, _uri); _includeClaim(claimHash, _claimType, _scheme, _issuer, _signature, _data, _uri);
} }
} else { } else {
require(isKeyPurpose(keccak256(msg.sender), CLAIM_SIGNER_KEY)); require(hasKeyPurpose(keccak256(msg.sender), CLAIM_SIGNER_KEY));
_requestApproval(address(this), 0, msg.data); _requestApproval(address(this), 0, msg.data);
emit ClaimRequested( emit ClaimRequested(
claimHash, claimHash,
@ -408,18 +408,18 @@ contract Identity is ERC725, ERC735, MessageSigned {
) )
public public
view view
returns(uint256 purpose, uint256 keyType, bytes32 key) returns(uint256[] purposes, uint256 keyType, bytes32 key)
{ {
Key storage myKey = keys[keccak256(_key, _purpose)]; Key storage myKey = keys[_key];
return (myKey.purpose, myKey.keyType, myKey.key); return (myKey.purposes, myKey.keyType, myKey.key);
} }
function isKeyPurpose(bytes32 _key, uint256 _purpose) function hasKeyPurpose(bytes32 _key, uint256 _purpose)
public public
view view
returns (bool) returns (bool)
{ {
return keys[keccak256(_key, _purpose)].purpose == _purpose; return isKeyPurpose[keccak256(_key, _purpose)];
} }
function getKeyPurpose(bytes32 _key) function getKeyPurpose(bytes32 _key)
@ -427,36 +427,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
view view
returns(uint256[] purpose) returns(uint256[] purpose)
{ {
return keys[_key].purposes;
uint256[] memory purposeHolder = new uint256[](4);
uint8 counter = 0;
if (isKeyPurpose(_key, MANAGEMENT_KEY)) {
purposeHolder[counter] = MANAGEMENT_KEY;
counter++;
}
if (isKeyPurpose(_key, ACTION_KEY)) {
purposeHolder[counter] = ACTION_KEY;
counter++;
}
if (isKeyPurpose(_key, CLAIM_SIGNER_KEY)) {
purposeHolder[counter] = CLAIM_SIGNER_KEY;
counter++;
}
if (isKeyPurpose(_key, ENCRYPTION_KEY)) {
purposeHolder[counter] = ENCRYPTION_KEY;
counter++;
}
uint256[] memory result = new uint256[](counter);
for (uint8 i = 0; i < counter; i++) {
result[i] = purposeHolder[i];
}
return result;
} }
function getKeysByPurpose(uint256 _purpose) function getKeysByPurpose(uint256 _purpose)
@ -517,7 +488,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
returns (uint256 txId) returns (uint256 txId)
{ {
uint256 requiredPurpose = _to == address(this) ? MANAGEMENT_KEY : ACTION_KEY; uint256 requiredPurpose = _to == address(this) ? MANAGEMENT_KEY : ACTION_KEY;
require(isKeyPurpose(_key, requiredPurpose)); require(hasKeyPurpose(_key, requiredPurpose));
if (purposeThreshold[requiredPurpose] == 1) { if (purposeThreshold[requiredPurpose] == 1) {
txId = txCount++; txId = txCount++;
_commitCall(txId, _to, _value, _data); _commitCall(txId, _to, _value, _data);
@ -580,7 +551,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
Transaction memory approvedTx = multisigTx[_id]; Transaction memory approvedTx = multisigTx[_id];
require(approvedTx.valid); require(approvedTx.valid);
uint256 requiredKeyPurpose = approvedTx.to == address(this) ? MANAGEMENT_KEY : ACTION_KEY; uint256 requiredKeyPurpose = approvedTx.to == address(this) ? MANAGEMENT_KEY : ACTION_KEY;
require(isKeyPurpose(_key, requiredKeyPurpose)); require(hasKeyPurpose(_key, requiredKeyPurpose));
require(multisigTx[_id].approvals[_key] != _approval); require(multisigTx[_id].approvals[_key] != _approval);
emit Approved(_id, _approval); emit Approved(_id, _approval);
@ -607,10 +578,20 @@ contract Identity is ERC725, ERC735, MessageSigned {
private private
{ {
require(_purpose > 0); require(_purpose > 0);
bytes32 keyHash = keccak256(_key, _purpose); bytes32 keyPurposeHash = keccak256(_key, _purpose);
require(keys[keyHash].purpose == 0);
keys[keyHash] = Key(_purpose, _type, _key); require(!isKeyPurpose[keyPurposeHash]);
indexes[keyHash] = keysByPurpose[_purpose].push(_key) - 1; isKeyPurpose[keyPurposeHash] = true;
indexes[keyPurposeHash] = keysByPurpose[_purpose].push(_key) - 1;
if (keys[_key].key == 0) {
uint256[] memory purposes = new uint256[](_purpose);
keys[_key] = Key(purposes,_type,_key);
keys[_key].key == _key;
keys[_key].keyType == _type;
} else {
indexes[keccak256(keyPurposeHash)] = keys[_key].purposes.push(_purpose) - 1;
}
emit KeyAdded(_key, _purpose, _type); emit KeyAdded(_key, _purpose, _type);
} }
@ -620,23 +601,46 @@ contract Identity is ERC725, ERC735, MessageSigned {
) )
private private
{ {
//forbidden to remove last management key
if (_purpose == MANAGEMENT_KEY) { if (_purpose == MANAGEMENT_KEY) {
require(keysByPurpose[MANAGEMENT_KEY].length > purposeThreshold[MANAGEMENT_KEY]); require(keysByPurpose[MANAGEMENT_KEY].length > purposeThreshold[MANAGEMENT_KEY]);
} }
bytes32 keyHash = keccak256(_key, _purpose); //require isKeyPurpose mapping and remove it
Key memory myKey = keys[keyHash]; bytes32 keyPurposeHash = keccak256(_key, _purpose);
uint256 index = indexes[keyHash]; require(isKeyPurpose[keyPurposeHash]);
bytes32 indexReplacer = keysByPurpose[_purpose][keysByPurpose[_purpose].length - 1]; delete isKeyPurpose[keyPurposeHash];
//remove keys by purpose array element
uint256 removedIndex = indexes[keyPurposeHash];
delete indexes[keyPurposeHash];
uint256 replacerIndex = keysByPurpose[_purpose].length - 1; // replacer is last element
if(removedIndex != replacerIndex) {
bytes32 replacerKey = keysByPurpose[_purpose][replacerIndex];
keysByPurpose[_purpose][removedIndex] = replacerKey; //overwrite removed index by replacer
indexes[keccak256(replacerKey, _purpose)] = removedIndex; //update index of replacer
}
keysByPurpose[_purpose].length--; //remove last element
//remove key purposes array element
Key storage myKey = keys[_key];
uint256 _type = myKey.keyType;
replacerIndex = myKey.purposes.length - 1;
if (replacerIndex > 0) {
bytes32 keyPurposeHashHash = keccak256(keyPurposeHash);
removedIndex = indexes[keyPurposeHashHash];
delete indexes[keyPurposeHashHash];
if(removedIndex != replacerIndex) {
uint256 replacerPurpose = myKey.purposes[replacerIndex];
myKey.purposes[removedIndex] = replacerPurpose;
indexes[keccak256(keccak256(_key, replacerPurpose))] = removedIndex;
}
myKey.purposes.length--;
} else {
delete keys[_key];
}
keysByPurpose[_purpose][index] = indexReplacer; emit KeyRemoved(_key, _purpose, _type);
indexes[keccak256(indexReplacer, _purpose)] = index;
keysByPurpose[_purpose].length--;
delete indexes[keyHash];
delete keys[keyHash];
emit KeyRemoved(myKey.key, myKey.purpose, myKey.keyType);
} }
function _includeClaim( function _includeClaim(