refactor execution and multisig process

This commit is contained in:
Ricardo Guilherme Schmidt 2018-05-09 01:18:35 -03:00
parent 8938d03911
commit a14485c0b0
1 changed files with 83 additions and 69 deletions

View File

@ -12,9 +12,10 @@ contract Identity is ERC725, ERC735, MessageSigned {
mapping (uint256 => bytes32[]) claimsByType; mapping (uint256 => bytes32[]) claimsByType;
mapping (bytes32 => uint256) indexes; mapping (bytes32 => uint256) indexes;
mapping (uint256 => Transaction) txx; mapping (uint256 => Transaction) multisigTx;
mapping (uint256 => uint256) purposeThreshold; mapping (uint256 => uint256) purposeThreshold;
uint256 txCount;
uint256 nonce; uint256 nonce;
address recoveryContract; address recoveryContract;
bytes32 recoveryManager; bytes32 recoveryManager;
@ -24,12 +25,11 @@ contract Identity is ERC725, ERC735, MessageSigned {
address to; address to;
uint256 value; uint256 value;
bytes data; bytes data;
uint256 nonce;
uint256 approverCount; uint256 approverCount;
mapping(bytes32 => bool) approvals; mapping(bytes32 => bool) approvals;
} }
modifier requiredKey(uint256 keyPurpose) { modifier msgSenderKey(uint256 keyPurpose) {
if(msg.sender == address(this)) { if(msg.sender == address(this)) {
_; _;
} else { } else {
@ -58,7 +58,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
_; _;
} }
modifier validECDSAKey ( modifier keyMessageSigned (
bytes32 _key, bytes32 _key,
bytes32 _messageHash, bytes32 _messageHash,
bytes _signature bytes _signature
@ -128,7 +128,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
uint256 _type uint256 _type
) )
public public
requiredKey(MANAGEMENT_KEY) msgSenderKey(MANAGEMENT_KEY)
returns (bool success) returns (bool success)
{ {
_addKey(_key, _purpose, _type); _addKey(_key, _purpose, _type);
@ -141,7 +141,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
uint256 _newType uint256 _newType
) )
public public
requiredKey(MANAGEMENT_KEY) msgSenderKey(MANAGEMENT_KEY)
returns (bool success) returns (bool success)
{ {
uint256 purpose = keys[_oldKey].purpose; uint256 purpose = keys[_oldKey].purpose;
@ -155,7 +155,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
uint256 _purpose uint256 _purpose
) )
public public
requiredKey(MANAGEMENT_KEY) msgSenderKey(MANAGEMENT_KEY)
returns (bool success) returns (bool success)
{ {
_removeKey(_key, _purpose); _removeKey(_key, _purpose);
@ -168,27 +168,16 @@ contract Identity is ERC725, ERC735, MessageSigned {
bytes _data bytes _data
) )
public public
returns (uint256 executionId) returns (uint256 txId)
{ {
uint256 requiredKey = _to == address(this) ? MANAGEMENT_KEY : ACTION_KEY; txId = _execute(keccak256(msg.sender), _to, _value, _data);
if (purposeThreshold[requiredKey] == 1) {
executionId = nonce; //(?) useless in this case
nonce++; //(?) should increment
require(isKeyPurpose(keccak256(msg.sender), requiredKey));
_to.call.value(_value)(_data); //(?) success not used
emit Executed(executionId, _to, _value, _data); //no information on success
} else {
executionId = _execute(_to, _value, _data);
approve(executionId, true);
}
} }
function approve(uint256 _id, bool _approval) function approve(uint256 _id, bool _approval)
public public
returns (bool success) returns (bool success)
{ {
return _approve(keccak256(msg.sender), _id, _approval); return _approveRequest(keccak256(msg.sender), _id, _approval);
} }
function setMinimumApprovalsByKeyType( function setMinimumApprovalsByKeyType(
@ -196,14 +185,13 @@ contract Identity is ERC725, ERC735, MessageSigned {
uint256 _minimumApprovals uint256 _minimumApprovals
) )
public public
requiredKey(MANAGEMENT_KEY) msgSenderKey(MANAGEMENT_KEY)
{ {
require(_minimumApprovals > 0); require(_minimumApprovals > 0);
require(_minimumApprovals <= keysByPurpose[_purpose].length); require(_minimumApprovals <= keysByPurpose[_purpose].length);
purposeThreshold[_purpose] = _minimumApprovals; purposeThreshold[_purpose] = _minimumApprovals;
} }
function addClaim( function addClaim(
uint256 _claimType, uint256 _claimType,
uint256 _scheme, uint256 _scheme,
@ -224,7 +212,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
} }
} else { } else {
require(isKeyPurpose(keccak256(msg.sender), CLAIM_SIGNER_KEY)); require(isKeyPurpose(keccak256(msg.sender), CLAIM_SIGNER_KEY));
_execute(address(this), 0, msg.data); _requestApproval(address(this), 0, msg.data);
emit ClaimRequested( emit ClaimRequested(
claimHash, claimHash,
_claimType, _claimType,
@ -352,14 +340,14 @@ contract Identity is ERC725, ERC735, MessageSigned {
return claimsByType[_claimType]; return claimsByType[_claimType];
} }
function approveECDSA( function approveMessageSigned(
uint256 _id, uint256 _id,
bool _approval, bool _approval,
bytes32 _key, bytes32 _key,
bytes _signature bytes _signature
) )
public public
validECDSAKey( keyMessageSigned(
_key, _key,
keccak256( keccak256(
address(this), address(this),
@ -371,10 +359,10 @@ contract Identity is ERC725, ERC735, MessageSigned {
) )
returns (bool success) returns (bool success)
{ {
return _approve(_key, _id, _approval); return _approveRequest(_key, _id, _approval);
} }
function executeECDSA( function executeMessageSigned(
address _to, address _to,
uint256 _value, uint256 _value,
bytes _data, bytes _data,
@ -383,7 +371,7 @@ contract Identity is ERC725, ERC735, MessageSigned {
bytes _signature bytes _signature
) )
public public
validECDSAKey( keyMessageSigned(
_key, _key,
keccak256( keccak256(
address(this), address(this),
@ -395,16 +383,14 @@ contract Identity is ERC725, ERC735, MessageSigned {
), ),
_signature _signature
) )
requiredKey(_to == address(this) ? MANAGEMENT_KEY : ACTION_KEY) returns (uint256 txId)
returns (uint256 executionId)
{ {
executionId = _execute(_to, _value, _data); txId = _execute(_key, _to, _value, _data);
_approve(_key, executionId, true);
} }
function setupRecovery(address _recoveryContract) function setupRecovery(address _recoveryContract)
public public
requiredKey(MANAGEMENT_KEY) msgSenderKey(MANAGEMENT_KEY)
{ {
require(recoveryContract == address(0)); require(recoveryContract == address(0));
recoveryContract = _recoveryContract; recoveryContract = _recoveryContract;
@ -423,27 +409,45 @@ contract Identity is ERC725, ERC735, MessageSigned {
} }
function _execute( function _execute(
bytes32 _key,
address _to, address _to,
uint256 _value, uint256 _value,
bytes _data bytes _data
) )
private internal
returns (uint256 executionId) returns (uint256 txId)
{ {
executionId = nonce; uint256 requiredPurpose = _to == address(this) ? MANAGEMENT_KEY : ACTION_KEY;
nonce++; require(isKeyPurpose(_key, requiredPurpose));
txx[executionId] = Transaction({ if (purposeThreshold[requiredPurpose] == 1) {
txId = txCount++;
_commitCall(txId, _to, _value, _data);
} else {
txId = _requestApproval(_to, _value, _data);
_approveRequest(_key, txId, true);
}
}
function _requestApproval(
address _to,
uint256 _value,
bytes _data
)
internal
returns (uint256 txId)
{
txId = txCount++;
multisigTx[txCount] = Transaction({
valid: true, valid: true,
to: _to, to: _to,
value: _value, value: _value,
data: _data, data: _data,
nonce: nonce,
approverCount: 0 approverCount: 0
}); });
emit ExecutionRequested(executionId, _to, _value, _data); emit ExecutionRequested(txId, _to, _value, _data);
} }
function _approve( function _approveRequest(
bytes32 _key, bytes32 _key,
uint256 _id, uint256 _id,
bool _approval bool _approval
@ -452,33 +456,43 @@ contract Identity is ERC725, ERC735, MessageSigned {
returns(bool success) //(?) should return approved instead of success? returns(bool success) //(?) should return approved instead of success?
{ {
Transaction memory trx = txx[_id]; Transaction memory approvedTx = multisigTx[_id];
require(trx.valid); require(approvedTx.valid);
uint256 requiredKeyPurpose = trx.to == address(this) ? MANAGEMENT_KEY : ACTION_KEY; uint256 requiredKeyPurpose = approvedTx.to == address(this) ? MANAGEMENT_KEY : ACTION_KEY;
require(isKeyPurpose(_key, requiredKeyPurpose)); require(isKeyPurpose(_key, requiredKeyPurpose));
bytes32 keyHash = keccak256(_key, requiredKeyPurpose); require(multisigTx[_id].approvals[_key] != _approval);
require(txx[_id].approvals[keyHash] != _approval);
if (_approval) {
trx.approverCount++;
} else {
trx.approverCount--;
}
emit Approved(_id, _approval); emit Approved(_id, _approval);
if (trx.approverCount < purposeThreshold[requiredKeyPurpose]) { if (_approval) {
txx[_id].approvals[keyHash] = _approval; if (approvedTx.approverCount + 1 == purposeThreshold[requiredKeyPurpose]) {
txx[_id] = trx; delete multisigTx[_id];
} else { return _commitCall(_id, approvedTx.to, approvedTx.value, approvedTx.data);
delete txx[_id];
//(?) success should be included in event?
success = address(trx.to).call.value(trx.value)(trx.data);
if(success){
emit Executed(_id, trx.to, trx.value, trx.data);
} else { } else {
emit ExecutionFailed(_id, trx.to, trx.value, trx.data)); multisigTx[_id].approverCount++;
} }
} else {
multisigTx[_id].approverCount--;
}
multisigTx[_id].approvals[_key] = _approval;
}
function _commitCall(
uint256 _txId,
address _to,
uint256 _value,
bytes _data
)
internal
returns(bool success)
{
nonce++;
success = _to.call.value(_value)(_data);
if (success) {
emit Executed(_txId, _to, _value, _data);
} else {
emit ExecutionFailed(_txId, _to, _value, _data);
} }
} }