Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERC: Key Manager #734

Open
frozeman opened this issue Oct 9, 2017 · 10 comments

Comments

@frozeman
Copy link
Member

commented Oct 9, 2017

eip: 734
title: Key Manager
author: Fabian Vogelsteller (@frozeman)
discussions-to: https://github.com/ethereum/EIPs/issues/734
status: WIP
type: Standards Track
category: ERC
created: 2017-10-02

NOTE: Due to the changes in ERC725, this spec is not fully compatible with the current ERC725v2. If you're interested in adopting this spec to work with 725v2, please comment below, or send a gist with changes.

Simple Summary

A contract for key management of a blockchain proxy account.

Abstract

The following describes standard functions for a key manager to be used in conjunction with ERC725.
This contract can hold keys to sign actions (transactions, documents, logins, access, etc), as well as execute instructions through an ERC 725 proxy account.

Motivation

This key manager standard allows for more complex management of an ERC725 proxy account.

Definitions

  • keys: Keys are public keys from either external accounts, or contracts' addresses.
  • claim issuer: is another smart contract or external account, which issues claims about this identity. The claim issuer can be an identity contract itself.
  • claim: For details about claims see #ERC735

Specification

Key Management

Keys are cryptographic public keys, or contract addresses associated with this identity.
The structure should be as follows:

  • key: A public key owned by this identity
    • purpose: uint256[] Array of the key types, like 1 = MANAGEMENT, 2 = EXECUTION
    • keyType: The type of key used, which would be a uint256 for different key types. e.g. 1 = ECDSA, 2 = RSA, etc.
    • key: bytes32 The public key. // for non-hex and long keys, its the Keccak256 hash of the key
struct Key {
    uint256[] purposes;
    uint256 keyType;
    bytes32 key;
}

getKey

Returns the full key data, if present in the identity.

function getKey(bytes32 _key) constant returns(uint256[] purposes, uint256 keyType, bytes32 key);

keyHasPurpose

Returns TRUE if a key is present and has the given purpose. If the key is not present it returns FALSE.

function keyHasPurpose(bytes32 _key, uint256 purpose) constant returns(bool exists);

getKeysByPurpose

Returns an array of public key bytes32 held by this identity.

function getKeysByPurpose(uint256 _purpose) constant returns(bytes32[] keys);

addKey

Adds a _key to the identity. The _purpose specifies the purpose of the key. Initially, we propose four purposes:

  • 1: MANAGEMENT keys, which can manage the identity
  • 2: EXECUTION keys, which perform executions in this identity's name (signing, logins, transactions, etc.)

MUST only be done by keys of purpose 1, or the identity itself. If it's the identity itself, the approval process will determine its approval.

Triggers Event: KeyAdded

function addKey(bytes32 _key, uint256 _purpose, uint256 _keyType) returns (bool success)

removeKey

Removes _key from the identity.

MUST only be done by keys of purpose 1, or the identity itself. If it's the identity itself, the approval process will determine its approval.

Triggers Event: KeyRemoved

function removeKey(bytes32 _key, uint256 _purpose) returns (bool success)

changeKeysRequired

Changes the keys required to perform an action for a specific purpose. (This is the n in an n of m multisig approval process.)

MUST only be done by keys of purpose 1, or the identity itself. If it's the identity itself, the approval process will determine its approval.

Triggers Event: KeysRequiredChanged

function changeKeysRequired(uint256 purpose, uint256 number) external

getKeysRequired

Returns number of keys required for purpose.

function getKeysRequired(uint256 purpose) external view returns(uint256)

Identity usage

execute

Passes an execution instruction to an ERC725 identity.
SHOULD require approve to be called with one or more keys of purpose 1 or 2 to approve this execution.

Execute COULD be used as the only accessor for addKey, removeKey and replaceKey and removeClaim.

Returns executionId: SHOULD be sent to the approve function, to approve or reject this execution.

Triggers Event: ExecutionRequested
Triggers on direct execution Event: Executed

function execute(address _to, uint256 _value, bytes _data) returns (uint256 executionId)

approve

Approves an execution or claim addition.
This SHOULD require n of m approvals of keys purpose 1, if the _to of the execution is the identity contract itself, to successfully approve an execution.
And COULD require n of m approvals of keys purpose 2, if the _to of the execution is another contract, to successfully approve an execution.

Triggers Event: Approved
Triggers on successfull execution Event: Executed
Triggers on successfull claim addition Event: ClaimAdded

function approve(uint256 _id, bool _approve) returns (bool success)

Events

KeyAdded

MUST be triggered when addKey was successfully called.

event KeyAdded(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType)

KeyRemoved

MUST be triggered when removeKey was successfully called.

event KeyRemoved(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType)

ExecutionRequested

MUST be triggered when execute was successfully called.

event ExecutionRequested(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data)

Executed

MUST be triggered when approve was called and the execution was successfully approved.

event Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data)

Approved

MUST be triggered when approve was successfully called.

event Approved(uint256 indexed executionId, bool approved)

KeysRequiredChanged

MUST be triggered when changeKeysRequired was successfully called.

event KeysRequiredChanged(uint256 purpose, uint256 number)

Rationale

This specification was chosen to allow most flexibility and experimentation around verifiable accounts. By having a separate contract as proxy on chain allows for cross greater compatibility, as well as extra and altered functionality for new use cases.

Solidity Interface

pragma solidity ^0.4.18;

contract ERC734 {

    uint256 constant MANAGEMENT_KEY = 1;
    uint256 constant EXECUTION_KEY = 2;

    event KeyAdded(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType);
    event KeyRemoved(bytes32 indexed key, uint256 indexed purpose, uint256 indexed keyType);
    event ExecutionRequested(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data);
    event Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data);
    event Approved(uint256 indexed executionId, bool approved);
    event KeysRequiredChanged(uint256 purpose, uint256 number);

    struct Key {
        uint256 purpose; //e.g., MANAGEMENT_KEY = 1, EXECUTION_KEY = 2, etc.
        uint256 keyType; // e.g. 1 = ECDSA, 2 = RSA, etc.
        bytes32 key;
    }

    function getKey(bytes32 _key) public constant returns(uint256[] purposes, uint256 keyType, bytes32 key);
    function keyHasPurpose(bytes32 _key, uint256 _purpose) public constant returns (bool exists);
    function getKeysByPurpose(uint256 _purpose) public constant 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 changeKeysRequired(uint256 purpose, uint256 number) external;
    function getKeysRequired(uint256 purpose) external view returns(uint256);
    function execute(address _to, uint256 _value, bytes _data) public returns (uint256 executionId);
    function approve(uint256 _id, bool _approve) public returns (bool success);
}

Copyright

Copyright and related rights waived via CC0.

@frozeman frozeman changed the title ERC: Claim Holder Empty issue Oct 9, 2017

@frozeman frozeman closed this Oct 9, 2017

@frozeman frozeman changed the title Empty issue Placholder issue Oct 9, 2017

@frozeman frozeman changed the title Placholder issue Placeholder issue Oct 9, 2017

@frozeman frozeman changed the title Placeholder issue ERC: Keymanager Feb 15, 2019

@frozeman frozeman changed the title ERC: Keymanager ERC: Key Manager Feb 15, 2019

@frozeman frozeman reopened this Feb 15, 2019

@frozeman

This comment has been minimized.

Copy link
Member Author

commented Feb 15, 2019

This issue was reopened, to serve as a container for a Key Manager contract, which was formerly ERC 725 v1.
The new ERC 725 v2 serves now as a proxy account standard, that can be owned by a ERC 734 key manager contract.

@jpitts jpitts added the type: ERC label Feb 16, 2019

@wighawag

This comment has been minimized.

Copy link
Contributor

commented Mar 2, 2019

Nice. I like the simple design.

I would add a bytes calldata _operationData parameter to execute though to not have to overload _data with extra purpose when extra data need to be passed in for specific operation type. I am thinking of #1077 for example.

@frozeman

This comment has been minimized.

Copy link
Member Author

commented Mar 2, 2019

Could you write the whole execution function how you envision it?

This standard needs to be improved a bit to fully fit 725v2.

@wighawag

This comment has been minimized.

Copy link
Contributor

commented Mar 2, 2019

I was actually referring to 725v2

the whole execute function would be

function execute(uint256 _operationType, bytes calldata _operationData, address _to, uint256 _value, bytes calldata _data) external;

@charyorde

This comment has been minimized.

Copy link

commented May 6, 2019

@frozeman Simply, is this a design for KYC? Like Identity verification?

@frozeman

This comment has been minimized.

Copy link
Member Author

commented May 6, 2019

This is a standard for key management, intended to be used in conjunction with #725

@cbruguera

This comment has been minimized.

Copy link

commented Jun 11, 2019

@frozeman I see there are multiple references to claim-related functionality in this spec. I thought all claim functionality was moved to be handled by ERC735... Is this proposal description outdated or is it indeed coupled with claim related functionality?

@cbruguera

This comment has been minimized.

Copy link

commented Jul 10, 2019

@frozeman You might have missed it, but could you provide clarity on my last question? I'm starting to work on an implementation for identity contracts based on these proposals (ERC734/725) soon. Thanks.

@frozeman

This comment has been minimized.

Copy link
Member Author

commented Jul 10, 2019

Hi @cbruguera those are outdated, in fact 734 and 735 needs a bit of re-work to adapt fully to 725v2, if you start working on it it would be great if you can improve the current spec. Send you transformed spec in a gist and ill will update it here.

the old 725 was moved to here (734), that's why there are those issues.

734 should only concern about key management. Also the execute function needs to then call the execute function on 725v2 (and the key manager, needs to be an owner of an 725v2 contract).

Alternatively, The gnosis safe should also work as a key manager.
But improving this spec would be appreciated.

@cbruguera

This comment has been minimized.

Copy link

commented Jul 11, 2019

Thanks for the reply. I understand now.

Maybe an indication at the top stating that the specs are outdated would be a good idea in the meantime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.