Skip to content

Commit

Permalink
Merge branch 'release/v2.11.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
wulfraem committed Aug 5, 2020
2 parents f37b0f1 + d178125 commit 79b923d
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 17 deletions.
12 changes: 12 additions & 0 deletions VERSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@
### Deprecations


## Version 2.11.0
### Features
- update identity contracts' purpose handling
- to match updated purpose handling
- `VERSION_ID` can be used to decide which version to use
- identities with version `null` only need purpose 1 for everything
- newer identities will have version 1
- keys can be added and removed with multiple purposes at once (`addMultiPurposeKey`, `removeMultiPurposeKey`)
- accounts with purpose 3 can only be removed by themselves
- only one account with purpose 3 is allowed per identity


## Version 2.10.0
### Features
- Added deactivation feature for `DidRegistry`
Expand Down
4 changes: 2 additions & 2 deletions contracts/compiled.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contracts/compiled.json

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions contracts/verifications/KeyHolder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import "./KeyHolderLibrary.sol";


contract KeyHolder is ERC725 {
uint256 public VERSION_ID = 1;
KeyHolderLibrary.KeyHolderData keyHolderData;

constructor(address _keyHolderOwner) public {
Expand Down Expand Up @@ -70,6 +71,13 @@ contract KeyHolder is ERC725 {
return KeyHolderLibrary.addKey(keyHolderData, _key, _purpose, _type);
}

function addMultiPurposeKey(bytes32 _key, uint256[] _purposes, uint256 _type)
public
returns (bool success)
{
return KeyHolderLibrary.addMultiPurposeKey(keyHolderData, _key, _purposes, _type);
}

function approve(uint256 _id, bool _approve)
public
returns (bool success)
Expand Down Expand Up @@ -100,6 +108,13 @@ contract KeyHolder is ERC725 {
return KeyHolderLibrary.removeKey(keyHolderData, _key, _purpose);
}

function removeMultiPurposeKey(bytes32 _key, uint256[] _purposes)
public
returns (bool success)
{
return KeyHolderLibrary.removeMultiPurposeKey(keyHolderData, _key, _purposes);
}

function keyHasPurpose(bytes32 _key, uint256 _purpose)
public
view
Expand Down
85 changes: 75 additions & 10 deletions contracts/verifications/KeyHolderLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ library KeyHolderLibrary {
event ContractCreated(uint256 indexed executionId, address indexed contractId);

struct Key {
uint256[] purposes; //e.g., MANAGEMENT_KEY = 1, ACTION_KEY = 2, etc.
uint256[] purposes; //e.g., MANAGEMENT_KEY = 1, ACTION_KEY = 2, RECOVERY = 3, etc.
uint256 keyType; // e.g. 1 = ECDSA, 2 = RSA, etc.
bytes32 key;
}
Expand All @@ -53,9 +53,12 @@ library KeyHolderLibrary {
bytes32 _key = keccak256(abi.encodePacked(_keyHolderOwner));
_keyHolderData.keys[_key].key = _key;
_keyHolderData.keys[_key].purposes.push(1);
_keyHolderData.keys[_key].purposes.push(2);
_keyHolderData.keys[_key].keyType = 1;
_keyHolderData.keysByPurpose[1].push(_key);
_keyHolderData.keysByPurpose[2].push(_key);
emit KeyAdded(_key, 1, 1);
emit KeyAdded(_key, 2, 1);
}

function getKey(KeyHolderData storage _keyHolderData, bytes32 _key)
Expand Down Expand Up @@ -91,9 +94,8 @@ library KeyHolderLibrary {
returns (bool success)
{
require(_keyHolderData.keys[_key].key != _key, "Key already exists"); // Key should not already exist
if (msg.sender != address(this)) {
require(keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)), 1), "Sender does not have management key"); // Sender has MANAGEMENT_KEY
}
require(keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)), 1), "Sender does not have key management key");
require(_purpose != 3 || _keyHolderData.keysByPurpose[3][0] == bytes32(0), "recovery key already registered");

_keyHolderData.keys[_key].key = _key;
_keyHolderData.keys[_key].purposes.push(_purpose);
Expand All @@ -106,6 +108,26 @@ library KeyHolderLibrary {
return true;
}

function addMultiPurposeKey(KeyHolderData storage _keyHolderData, bytes32 _key, uint256[] _purposes, uint256 _type)
public
returns (bool success)
{
require(_keyHolderData.keys[_key].key != _key, "Key already exists"); // Key should not already exist
require(keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)), 1), "Sender does not have key management key");

_keyHolderData.keys[_key].key = _key;
_keyHolderData.keys[_key].keyType = _type;
for (uint256 i = 0; i < _purposes.length; i++) {
uint256 purpose = _purposes[i];
require(purpose != 3 || _keyHolderData.keysByPurpose[3][0] == bytes32(0), "recovery key already registered");
_keyHolderData.keys[_key].purposes.push(purpose);
_keyHolderData.keysByPurpose[purpose].push(_key[i]);
emit KeyAdded(_key, purpose, _type);
}

return true;
}

function approve(KeyHolderData storage _keyHolderData, uint256 _id, bool _approve)
public
returns (bool success)
Expand Down Expand Up @@ -185,7 +207,7 @@ library KeyHolderLibrary {

emit ExecutionRequested(_keyHolderData.executionNonce, _to, _value, _keyHolderData.executions[_keyHolderData.executionNonce].data);

if (keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)),1) || keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)),2)) {
if (keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)),2)) {
approve(_keyHolderData, _keyHolderData.executionNonce, true, _data);
}

Expand Down Expand Up @@ -217,7 +239,7 @@ library KeyHolderLibrary {
bytes32 prefixedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message));
address recovered = getRecoveredAddress(_signedTransactionInfo, prefixedHash);
// allow tx if signer === recovered
if (keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(recovered)),1) || keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(recovered)),2)) {
if (keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(recovered)),2)) {
handleApprove(_keyHolderData, _keyHolderData.executionNonce, true, _data);
}

Expand All @@ -229,9 +251,8 @@ library KeyHolderLibrary {
public
returns (bool success)
{
if (msg.sender != address(this)) {
require(keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)), 1), "Sender does not have management key"); // Sender has MANAGEMENT_KEY
}
require(keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)), 1), "Sender does not have key management key");
require(!keyHasPurpose(_keyHolderData, _key, 3) || keccak256(abi.encodePacked(msg.sender)) == _key, "keys with purpose 3 can only be removed by themselves");

require(_keyHolderData.keys[_key].key == _key, "No such key");
emit KeyRemoved(_key, _purpose, _keyHolderData.keys[_key].keyType);
Expand Down Expand Up @@ -266,6 +287,50 @@ library KeyHolderLibrary {
return true;
}

function removeMultiPurposeKey(KeyHolderData storage _keyHolderData, bytes32 _key, uint256[] _purposes)
public
returns (bool success)
{
require(keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)), 1), "Sender does not have key management key");
require(!keyHasPurpose(_keyHolderData, _key, 3) || keccak256(abi.encodePacked(msg.sender)) == _key, "keys with purpose 3 can only be removed by themselves");

require(_keyHolderData.keys[_key].key == _key, "No such key");

// Remove purpose from key
uint256[] storage purposes = _keyHolderData.keys[_key].purposes;
for (uint i = 0; i < purposes.length; i++) {
for (uint argi = 0; argi < _purposes.length; argi++) {
if (purposes[i] == _purposes[argi]) {
purposes[i] = purposes[purposes.length - 1];
delete purposes[purposes.length - 1];
purposes.length--;
emit KeyRemoved(_key, _purposes[argi], _keyHolderData.keys[_key].keyType);
break;
}
}
}

// If no more purposes, delete key
if (purposes.length == 0) {
delete _keyHolderData.keys[_key];
}

// Remove key from keysByPurpose
for (uint argj = 0; argj < purposes.length; argj++) {
bytes32[] storage keys = _keyHolderData.keysByPurpose[_purposes[argj]];
for (uint j = 0; j < keys.length; j++) {
if (keys[j] == _key) {
keys[j] = keys[keys.length - 1];
delete keys[keys.length - 1];
keys.length--;
break;
}
}
}

return true;
}

function keyHasPurpose(KeyHolderData storage _keyHolderData, bytes32 _key, uint256 _purpose)
public
view
Expand All @@ -278,7 +343,7 @@ library KeyHolderLibrary {

uint256[] storage purposes = _keyHolderData.keys[_key].purposes;
for (uint i = 0; i < purposes.length; i++) {
if (purposes[i] <= _purpose) {
if (purposes[i] == _purpose) {
isThere = true;
break;
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/verifications/VerificationHolderLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ library VerificationHolderLibrary {

// owner of identity and issuer can remove
if (msg.sender != address(this) && msg.sender != _verifications.byId[_verificationId].issuer) {
require(KeyHolderLibrary.keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)), 1), "Sender does not have management key");
require(KeyHolderLibrary.keyHasPurpose(_keyHolderData, keccak256(abi.encodePacked(msg.sender)), 2), "Sender does not have action key");
}

emit VerificationRemoved(
Expand Down
4 changes: 2 additions & 2 deletions lib/solc.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ const librariesAddresses = {
'AbstractENS.sol:AbstractENS':
'0x937bbC1d3874961CA38726E9cD07317ba81eD2e1',
'verifications/KeyHolderLibrary.sol:KeyHolderLibrary':
'0x498A9beDAf23401d888b4f52fD379bBA144D2370',
'0xfC1ebdbC58A6CEff55fd8fd2c7Cdf84a74991062',
'verifications/VerificationHolderLibrary.sol:VerificationHolderLibrary':
'0x30aD628d39F55E66aE42F7e48c741D6567AA8F55',
'0xe387c961DeF72C14631f5226405573c1Be7F938c',
'verifications/VerificationsRegistryLibrary.sol:VerificationsRegistryLibrary':
'0xDB93AaB864031340E3D98f6Cd937FC2a51Be1998',
'DSRolesPerContractLibrary.sol:DSRolesPerContractLibrary':
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@
"scripts": {
"build-contracts": "node ./scripts/build-contracts.js"
},
"version": "2.10.0"
"version": "2.11.0"
}

0 comments on commit 79b923d

Please sign in to comment.