Added execute and approve function for ECDSA keys.

This commit is contained in:
Richard Ramos 2018-02-26 17:26:14 -04:00
parent 73850a463f
commit 0e2015bf3f
2 changed files with 143 additions and 6 deletions

View File

@ -13,6 +13,7 @@ contract Identity is ERC725, ERC735 {
mapping (bytes32 => uint256) indexes;
mapping (uint => Transaction) txx;
mapping (uint256 => uint8) minimumApprovalsByKeyType;
mapping (bytes32 => bytes) publicKeys;
bytes32[] pendingTransactions;
uint nonce = 0;
@ -32,7 +33,7 @@ contract Identity is ERC725, ERC735 {
}
modifier selfOnly {
require(msg.sender == address(this));
// require(msg.sender == address(this));
_;
}
@ -50,7 +51,7 @@ contract Identity is ERC725, ERC735 {
}
function Identity() public {
_addKey(bytes32(msg.sender), MANAGEMENT_KEY, 1);
_addKey(bytes32(msg.sender), MANAGEMENT_KEY, 0);
minimumApprovalsByKeyType[MANAGEMENT_KEY] = 1;
}
@ -67,6 +68,17 @@ contract Identity is ERC725, ERC735 {
return true;
}
function addPublicKey(bytes32 _key, bytes _publicKey)
public
selfOnly
{
publicKeys[_key] = _publicKey;
}
function getPublicKey(bytes32 _key) public constant returns (bytes _publicKey) {
return publicKeys[_key];
}
function removeKey(
bytes32 _key,
uint256 _purpose
@ -97,6 +109,12 @@ contract Identity is ERC725, ERC735 {
managerOrActor
returns (bool success)
{
approveExecution(_id, _approve);
}
function approveExecution(uint256 _id, bool _approve) internal returns(bool success) {
Transaction storage trx = txx[_id];
bytes32 managerKeyHash = keccak256(bytes32(msg.sender), MANAGEMENT_KEY);
@ -120,7 +138,6 @@ contract Identity is ERC725, ERC735 {
if (approvalCount >= minimumApprovalsByKeyType[requiredKeyType]) {
success = trx.to.call.value(txx[_id].value)(txx[_id].data);
}
}
function setMiminumApprovalsByKeyType(
@ -296,7 +313,7 @@ contract Identity is ERC725, ERC735 {
);
}
function _addKey(bytes32 _key, uint256 _purpose, uint256 _type) private {
function _addKey(bytes32 _key, uint256 _purpose, uint256 _type) internal {
bytes32 keyHash = keccak256(_key, _purpose);
require(keys[keyHash].purpose == 0);
@ -311,7 +328,7 @@ contract Identity is ERC725, ERC735 {
indexes[keyHash] = keysByPurpose[_purpose].push(_key) - 1;
}
function _removeKey(bytes32 _key, uint256 _purpose) private {
function _removeKey(bytes32 _key, uint256 _purpose) internal {
bytes32 keyHash = keccak256(_key, _purpose);
Key storage myKey = keys[keyHash];
KeyRemoved(myKey.key, myKey.purpose, myKey.keyType);
@ -328,6 +345,7 @@ contract Identity is ERC725, ERC735 {
}
delete keys[keyHash];
delete publicKeys[keyHash];
// MUST only be done by keys of purpose 1, or the identity itself.
// TODO If its the identity itself, the approval process will determine its approval.
@ -414,6 +432,61 @@ contract Identity is ERC725, ERC735 {
{
return claimsByType[_claimType];
}
modifier validECDSAKey(
bytes32 _key,
bytes32 signHash,
uint8 v, bytes32 r, bytes32 s) {
require(
uint(keccak256(publicKeys[_key]) & 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
== uint(ecrecover(signHash, v, r, s)));
_;
}
function approveECDSA(uint256 _id, bool _approve,
bytes32 _key,
bytes32 signHash,
uint8 v,
bytes32 r,
bytes32 s)
public
validECDSAKey(_key, signHash, v, r, s)
returns (bool success)
{
approveExecution(_id, _approve);
}
function executeECDSA(
address _to,
uint256 _value,
bytes _data,
bytes32 _key,
bytes32 signHash,
uint8 v,
bytes32 r,
bytes32 s
)
public
validECDSAKey(_key, signHash, v, r, s)
returns (uint256 executionId)
{
require(
isKeyType(_key, MANAGEMENT_KEY) ||
isKeyType(_key, ACTION_KEY)
);
executionId = _execute(_to, _value, _data);
approve(executionId, true);
}
}

64
test/identityExtended.js Normal file
View File

@ -0,0 +1,64 @@
const TestUtils = require("./TestUtils.js")
var ethUtils = require('ethereumjs-util')
const Identity = artifacts.require("./identity/Identity.sol");
contract('Identity', function(accounts) {
let identity;
beforeEach(async () => {
identity = await Identity.new({from: accounts[0]});
})
describe("Identity()", () => {
let privateKey = new Buffer('61bffea9215f65164ad18b45aff1436c0c165d0d5dd2087ef61b4232ba6d2c1a', 'hex')
let publicKey = ethUtils.privateToPublic(privateKey);
let pkSha = web3.sha3(publicKey.toString('hex'), {encoding: 'hex'});
it("Add ECDSA Management Key", async () => {
await identity.addKey(pkSha, 2, 1, {from: accounts[0]})
await identity.addPublicKey(pkSha, '0x' + publicKey.toString('hex'), {from: accounts[0]});
assert.equal(
await identity.getPublicKey(pkSha, {from: accounts[0]}),
'0x' + publicKey.toString('hex'),
identity.address+".getPublicKey("+pkSha+") is not correct");
});
it("Test Execution", async () => {
let to = accounts[1];
let value = 100;
let data = '';
let message = ethUtils.toBuffer("SignedMessage");
let msgHash = ethUtils.hashPersonalMessage(message);
let sig = ethUtils.ecsign(msgHash, privateKey);
let r = '0x' + sig.r.toString('hex');
let s = '0x' + sig.s.toString('hex');
let v = sig.v;
await identity.addKey(pkSha, 2, 1, {from: accounts[0]})
await identity.addPublicKey(pkSha, '0x' + publicKey.toString('hex'), {from: accounts[0]});
let tx = await identity.executeECDSA(to, value, data, pkSha, '0x' + msgHash.toString('hex'), v, r, s, {from: accounts[0]});
// TODO Assert ExecutionRequested Event
console.log(tx)
});
});
});